packages feed

MFlow 0.3.1.1 → 0.3.2.0

raw patch · 36 files changed

+1766/−1374 lines, 36 files

Files

Demos/Actions.hs view
@@ -2,15 +2,16 @@ module Actions (actions) where
 
 import MFlow.Wai.Blaze.Html.All
+import Menu 
-actions n= do
-  r<- ask $   p << b <<  "Two  boxes with one action each one"
+actions = do
+  r<- askm  $   p << b <<  "Two  boxes with one action each one"
           ++> getString (Just "widget1") `waction` action
           <+> getString (Just "widget2") `waction` action
           <** submitButton "submit"
-  ask $ p << ( show r ++ " returned")  ++> wlink ()  << p <<  " menu"
+  askm  $ p << ( show r ++ " returned")  ++> wlink ()  << p <<  " menu"
   where
-  action n=  ask $ getString (Just $ n ++ " action")<** submitButton "submit action"
+  action n=  askm  $ getString (Just $ n ++ " action")<** submitButton "submit action"
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav actions
Demos/AjaxSample.hs view
@@ -1,18 +1,20 @@ 
 
 module AjaxSample ( ajaxsample) where
-import MFlow.Wai.Blaze.Html.All
+import MFlow.Wai.Blaze.Html.All+import Menu
 import Data.Monoid
-import Data.ByteString.Lazy.Char8 as B
+import Data.ByteString.Lazy.Char8 as B+
 ajaxsample= do
-   r <- ask $   p << b <<  "Ajax example that increment the value in a box"
+   r <- askm  $   p << b <<  "Ajax example that increment the value in a box"
             ++> do
                  let elemval= "document.getElementById('text1').value"
                  ajaxc <- ajax $ \n -> return . B.pack $ elemval <> "='" <> show(read  n +1) <>  "'"
                  b <<  "click the box "
                    ++> getInt (Just 0) <! [("id","text1"),("onclick", ajaxc  elemval)] <** submitButton "submit"
-   ask $ p << ( show r ++ " returned")  ++> wlink ()  << p <<  " menu"
+   askm  $ p << ( show r ++ " returned")  ++> wlink ()  << p <<  " menu"
 
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav ajaxsample
Demos/AutoCompList.hs view
@@ -1,18 +1,19 @@ 
 module AutoCompList ( autocompList) where
 import MFlow.Wai.Blaze.Html.All
+import Menu
 import Data.List
 
 autocompList= do
-   r <- ask $   p <<  "Autocomplete with a list of selected entries"
+   r <- askm  $   p <<  "Autocomplete with a list of selected entries"
             ++> p <<  "enter  and press enter"
-            ++> p <<  "when su press submit, the entries are returned"
+            ++> p <<  "when submit is pressed, the entries are returned"
             ++> wautocompleteList "red,green,blue" filter1 ["red"]
             <** submitButton "submit"
-   ask $ p << ( show r ++ " selected")  ++> wlink () (p <<  " menu")
+   askm  $ p << ( show r ++ " selected")  ++> wlink () (p <<  " menu")
 
    where
-   filter1 s = return $ filter (isPrefixOf s) ["red","reed rose","green","green grass","blue","blues"]
+   filter1 s = return $ filter (isPrefixOf s) ["red","red rose","green","green grass","blue","blues"]
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav autocompList
Demos/AutoComplete.hs view
@@ -1,19 +1,20 @@ 
 module AutoComplete ( autocomplete1) where
 import MFlow.Wai.Blaze.Html.All
+import Menu
 import Data.List
 
 autocomplete1= do
-   r <- ask $   p <<  "Autocomplete "
-            ++> p <<  "when su press submit, the box value  is returned"
+   r <- askm  $   p <<  "Autocomplete "
+            ++> p <<  "when submit is pressed, the box value  is returned"
             ++> wautocomplete Nothing filter1 <! hint "red,green or blue"
             <** submitButton "submit"
-   ask $ p << ( show r ++ " selected")  ++> wlink () (p <<  " menu")
+   askm  $ p << ( show r ++ " selected")  ++> wlink () (p <<  " menu")
 
    where
-   filter1 s = return $ filter (isPrefixOf s) ["red","reed rose","green","green grass","blue","blues"]
+   filter1 s = return $ filter (isPrefixOf s) ["red","red rose","green","green grass","blue","blues"]
 
 hint s= [("placeholder",s)]
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav autocomplete1
Demos/CheckBoxes.hs view
@@ -1,17 +1,18 @@ 
 module CheckBoxes ( checkBoxes) where
-import MFlow.Wai.Blaze.Html.All
+import MFlow.Wai.Blaze.Html.All+import Menu
 import Data.Monoid
 
 checkBoxes= do
-   r <- ask $ getCheckBoxes(  (setCheckBox False "Red"   <++ b <<  "red")
+   r <- askm  $ getCheckBoxes(  (setCheckBox False "Red"   <++ b <<  "red")
                            <> (setCheckBox False "Green" <++ b <<  "green")
                            <> (setCheckBox False "blue"  <++ b <<  "blue"))
               <** submitButton "submit"
 
 
-   ask $ p << ( show r ++ " selected")  ++> wlink () (p <<  " menu")
+   askm  $ p << ( show r ++ " selected")  ++> wlink () (p <<  " menu")
 
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav checkBoxes
Demos/Combination.hs view
@@ -1,16 +1,17 @@ 
-module Combination ( combination, wlogin) where
+module Combination ( combination, wlogin1) where
 import MFlow.Wai.Blaze.Html.All
+import Menu
 import Counter(counterWidget)
 import Data.String
 
 text= fromString
 
-combination =  ask $ do
+combination =  askm  $ do
      p << "Three active widgets in the same page with autoRefresh. Each widget refresh itself \
           \with Ajax. If Ajax is not active, they will refresh by sending a new page."
      ++> hr
-     ++> p << "Login widget (use admin/admin)" ++> autoRefresh (pageFlow "r" wlogin)  <++ hr
+     ++> p << "Login widget (use admin/admin)" ++> autoRefresh (pageFlow "r" wlogin1)  <++ hr
      **> p << "Counter widget" ++> autoRefresh (pageFlow "c" (counterWidget 0))  <++ hr
      **> p << "Dynamic form widget" ++> autoRefresh (pageFlow "f" formWidget) <++ hr
      **> wlink () << b << "exit"
@@ -54,34 +55,35 @@ 
 
 
--- | If not logged, it present a page flow which ask for the user name, then the password if not logged
+-- | If not logged, it present a page flow which askm  for the user name, then the password if not logged
 --
 -- If logged, it present the user name and a link to logout
 --
 -- normally to be used with autoRefresh and pageFlow when used with other widgets.
-wlogin :: View Html IO ()
-wlogin=  (do
-    username <- getCurrentUser
-    if username /= anonymous
-     then return username
-     else do
-      name <- getString Nothing <! hint "username" <++ br
-      pass <- getPassword <! focus <** submitButton "login" <++ br
-      val  <- userValidate (name,pass)
-      case val of
-        Just msg -> notValid msg
-        Nothing  -> login name >> return name)
-
+wlogin1 :: View Html IO ()
+wlogin1 =  do
+   username <- getCurrentUser
+   if username /= anonymous
+         then return username
+         else do
+          name <- getString Nothing <! hint "username" <++ br
+          clear
+          pass <- getPassword <! hint "password" <** submitButton "login" <++ br
+          val  <- userValidate (name,pass)
+          case val of
+            Just msg -> notValid msg
+            Nothing  -> login name >> return name
+       
    `wcallback` (\name -> b << ("logged as " ++ name)
-                     ++> p << ("navigate away of this page before logging out")
+                     ++> p << "navigate away of this page before logging out"
                      ++>  wlink "logout"  << b << " logout")
-   `wcallback`  const (logout >>  wlogin)
+   `wcallback`  const (logout >> wlogin1)
 
 focus = [("onload","this.focus()")]
 
 
 
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav  combination
 
Demos/ContentManagement.hs view
@@ -1,46 +1,54 @@ 
 module ContentManagement ( textEdit) where
 import MFlow.Wai.Blaze.Html.All
+
 import Text.Blaze.Html5 as El
 import Text.Blaze.Html5.Attributes as At hiding (step)
 import Data.Monoid
+import Data.TCache.Memoization
 
+
+import Menu
+
+-- to run it alone, change askm by ask and uncomment this:
+--askm = ask
+--main= runNavigation "" $ transientNav textEdit
+
+
+
+editUser= "edituser"
+
 textEdit= do
+    userRegister editUser editUser
     let first=  p << i <<
                    (El.span <<  "this is a page with"
                    <> b <<  " two " <> El.span <<  "paragraphs. this is the first")
 
         second= p << i <<  "This is the original  of the second paragraph"
 
-
-
-    ask $   p << b <<  "An example of content management"
+    askm  $   p << b <<  "An example of content management"
         ++> first
         ++> second
         ++> wlink ()  << p <<  "click here to edit it"
-
-
-    ask $   p <<  "Please login with admin/admin to edit it"
-        ++> userWidget (Just "admin") userLogin
-
-    ask $   p <<  "Now you can click the fields and edit them"
-        ++> p << b <<  "to save an edited field, double click on it"
-        ++> tFieldEd "first"  first
-        **> tFieldEd "second" second
+    
+    askm  $   p <<  "Please login with edituser/edituser to edit it"
+        ++> userWidget (Just editUser) userLogin
+     
+    askm  $   p <<  "Now you can click the fields and edit them"
+        ++> p << b <<  "to save an edited field, press the save icon in the left"
+        ++> tFieldEd editUser "first"  first
+        **> tFieldEd editUser "second" second
         **> wlink ()  << p <<  "click here to see it as a normal user"
 
     logout
-
-    ask $   p <<  "the user sees the edited content. He can not edit"
-        ++> tFieldEd "first"  first
-        **> tFieldEd "second" second
-        **> wlink ()  << p <<  "click to continue"
+   
+    askm  $   p <<  "the user sees the edited content. He can not edit"
+        ++> tFieldEd editUser "first"  first
+        **> tFieldEd editUser "second" second
+        **> wlink "a"  << p <<  "click to continue"
 
-    ask $   p <<  "When texts are fixed,the edit facility and the original texts can be removed. The content is indexed by the field key"
+    askm  $   p <<  "When texts are fixed,the edit facility and the original texts can be removed. The content is indexed by the field key"
         ++> tField "first"
         **> tField "second"
         **> p << "End of edit field demo" ++> wlink ()  << p <<  "click here to go to menu"
 
-
--- to run it alone:
---main= runNavigation "" $ transientNav textEdit
Demos/Counter.hs view
@@ -1,6 +1,7 @@ 
 module Counter ( counter, counterWidget) where
 import MFlow.Wai.Blaze.Html.All
+import Menu
 import Data.Monoid
 import Data.String
 
@@ -8,17 +9,20 @@ text= fromString
 
 counter= do
-   let explain=
-        p << "This example emulates the"
-        <> a ! href (attr "http://www.seaside.st/about/examples/counter") << "seaside counter example"
-        <> p << "This widget uses a callback to permit an independent"
-        <> p << "execution flow for each widget." <> a ! href (attr "/noscript/multicounter") << "Multicounter" <> (text " instantiate various counter widgets")
-        <> p << "But while the seaside case the callback update the widget object, in this case"
-        <> p << "the callback call generates a new copy of the counter with the value modified."
-
-   ask $   explain
+   
+   askm  $   explain
        ++> pageFlow "c" (counterWidget 0) <++ br
        <|> wlink () << p << "exit"
+   where
+   explain= do   -- using the blaze-html monad
+        p << "This example emulates the"
+        a ! href (attr "http://www.seaside.st/about/examples/counter") << "seaside counter example"
+        p << "This widget uses a callback to permit an independent"
+        p << "execution flow for each widget."
+        a ! href (attr "/noscript/multicounter") << "Multicounter"
+        text " instantiate various counter widgets"
+        p << "But while the seaside case the callback update the widget object, in this case"
+        p << "the callback recursvely generates a new copy of the counter with the value modified."
 
 counterWidget n= 
       (h2 << show n     
@@ -30,5 +34,5 @@           "d" -> counterWidget (n - 1)
 
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav counter
Demos/Dialog.hs view
@@ -1,11 +1,12 @@ 
 module Dialog (wdialog1) where
 
-import MFlow.Wai.Blaze.Html.All
+import MFlow.Wai.Blaze.Html.All+import Menu
 
 wdialog1= do
-   ask  wdialogw
-   ask (wlink () << "out of the page flow, press here to go to the menu")
+   askm   wdialogw
+   askm  (wlink () << "out of the page flow, press here to go to the menu")
 
 wdialogw= pageFlow "diag" $ do
    r <- wform $ p << "please enter your name" ++> getString (Just "your name") <** submitButton "ok"
@@ -16,5 +17,5 @@                       else  wlink () << b << "thanks, press here to exit from the page Flow"
 
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav wdialog1
Demos/Grid.hs view
@@ -2,17 +2,18 @@ module Grid ( grid) where
 
 import MFlow.Wai.Blaze.Html.All
+import Menu
 import Data.String
 import Text.Blaze.Html5.Attributes as At hiding (step)
 
 attr= fromString
 
 grid = do
-  r <- ask $   addLink
+  r <- askm  $   addLink
            ++> wEditList table  row ["",""] "wEditListAdd"
            <** submitButton "submit"
            
-  ask $   p << (show r ++ " returned")
+  askm  $   p << (show r ++ " returned")
       ++> wlink () (p <<  " back to menu")
       
   where
@@ -30,5 +31,5 @@              
   tdborder= td ! At.style  (attr "border: solid 1px")
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav grid
Demos/IncreaseInt.hs view
@@ -2,18 +2,20 @@ module IncreaseInt ( clickn) where
 
 import MFlow.Wai.Blaze.Html.All
+import Menu 
 -- |+| add a widget before and after another and return both results.
 -- in this case, a link wraps a form field
-
++clickn :: Int -> FlowM Html IO ()
 clickn n= do
-   r <- ask $   p << b <<  "increase an Int"
+   r <- askm  $ p << b <<  "increase an Int"
             ++> wlink "menu"  << p <<  "menu"      
             |+| getInt (Just n)  <* submitButton "submit"
 
    case r of
-    (Just _,_) -> return ()  --  ask $ wlink () << p << "thanks"
+    (Just _,_) -> return ()  --  askm  $ wlink () << p << "thanks"
     (_, Just n') -> clickn $ n'+1
 
--- to run it alone:
+-- to run it alone, change askm by askm  and uncomment this:
 --main= runNavigation "" $ transientNav sumWidget
Demos/IncreaseString.hs view
@@ -2,9 +2,10 @@ module IncreaseString ( clicks) where
 
 import MFlow.Wai.Blaze.Html.All
+import Menu 
 clicks s= do
-   s' <- ask $  p << b <<  "increase a String"
+   s' <- askm  $  p << b <<  "increase a String"
              ++> p << b <<  "press the back button to go back to the menu"
              ++>(getString (Just s)
              <* submitButton "submit")
@@ -12,5 +13,5 @@    clicks $ s'++ "1"
 
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav clicks "1"
Demos/ListEdit.hs view
@@ -1,33 +1,34 @@-
+{-# LANGUAGE OverloadedStrings #-}
 module ListEdit ( wlistEd) where
 
 import MFlow.Wai.Blaze.Html.All
+import Menu
 import Text.Blaze.Html5 as El
 import Text.Blaze.Html5.Attributes as At hiding (step)
 import Data.String
 
-attr= fromString
 
+
 wlistEd= do
-   r <-  ask  $   addLink
+   r <-  askm   $   addLink
               ++> br
               ++> (wEditList El.div getString1   ["hi", "how are you"] "wEditListAdd")
               <++ br
               <** submitButton "send"
 
-   ask $   p << (show r ++ " returned")
-       ++> wlink () (p <<  " back to menu")
+   askm  $   p << (show r ++ " returned")
+       ++> wlink () (p " back to menu")
 
 
    where
-   addLink = a ! At.id  (attr "wEditListAdd")
-               ! href (attr "#")
-               $ b << "add"
-   delBox  =  input ! type_   (attr "checkbox")
-                    ! checked (attr "")
-                    ! onclick (attr "this.parentNode.parentNode.removeChild(this.parentNode)")
+   addLink = a ! At.id  "wEditListAdd"
+               ! href  "#"
+               $ b "add"
+   delBox  =  input ! type_    "checkbox"
+                    ! checked  ""
+                    ! onclick  "this.parentNode.parentNode.removeChild(this.parentNode)"
    getString1 mx= El.div  <<< delBox ++> getString  mx <++ br
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav wListEd
 
Demos/LoginSample.hs view
@@ -3,25 +3,29 @@ 
 import MFlow.Wai.Blaze.Html.All
 import Data.Monoid
+import Menu
+-- to run it alone, comment import Menu and uncomment this:
+--main= runNavigation "" $ transientNav loginSample
+--askm= ask
 
 loginSample= do
-    r <- ask $   p <<  "Please login with admin/admin"
-             ++> userWidget (Just "admin") userLogin
-             <|> wlink "exit" << p << "or exit"
+    userRegister "user" "user"
+    r <- askm  $   p <<  "Please login with user/user"
+               ++> userWidget Nothing userLogin
+               <|> wlink "exit" << p << "or exit"
         
     if r == "exit" then return () else do
         user <- getCurrentUser
     
-        r <- ask $   b <<  ("user logged as " <>  user)
-                ++> wlink True  << p <<  "logout"
-                <|> wlink False << p <<  "or exit"
+        r <- askm  $   b <<  ("user logged as " <>  user)
+                   ++> wlink True  << p <<  "logout"
+                   <|> wlink False << p <<  "or exit"
 
         if r
           then do
              logout
-             ask $ p << "logged out" ++> wlink () << "press here to exit"
+             askm  $ p << "logged out" ++> wlink () << "press here to exit"
           else return ()
   
 
--- to run it alone:
--- main= runNavigation "" $ transientNav loginSample
+
+ Demos/MCounter.hs view
@@ -0,0 +1,29 @@+module MCounter (
+mcounter
+) where
+import MFlow.Wai.Blaze.Html.All
+import Menu
+import Data.Monoid
+import Data.String
+
+
+
+mcounter  = do 
+ (op,n) <- step . askm $ do
+              n <- getSessionData  `onNothing` return (0 :: Int) -- get Int data from the session
+              op <- h2 << show n    
+                     ++> wlink "i" << b << " ++ "
+                     <|> wlink "d" << b << " -- "
+
+              return(op,n)  -- unlike in the case of the shopping example where the shopcart is not logged
+                            -- here the state is smaller (the Int counter) anc can be logged      
+ case op  of
+          "i" -> setSessionData  (n + 1)                     
+          "d" -> setSessionData  (n - 1)
+
+ mcounter
+
+-- to run it alone, change askm by ask and uncomment this:
+--main= runNavigation ""  mcounter
+
+
Demos/Multicounter.hs view
@@ -2,7 +2,8 @@ module Multicounter ( multicounter) where
 
 import MFlow.Wai.Blaze.Html.All
-import Data.Monoid
+import Menu
+import Data.Monoid 
 import Data.String
 import Counter(counterWidget)
 
@@ -10,7 +11,7 @@ attr= fromString
 
 multicounter=
- ask $   explain
+ askm  $ explain
      ++> add (counterWidget 0) [1..4]
      <|> wlink () << p << "exit"
 
@@ -26,5 +27,5 @@  add widget list= firstOf [autoRefresh $ pageFlow (show i) widget <++ hr | i <- list]
 
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav multicounter
Demos/Options.hs view
@@ -2,18 +2,19 @@ module Options (options) where
 
 import MFlow.Wai.Blaze.Html.All
+import Menu 
 options= do
-   r <- ask $ getSelect (setSelectedOption ""  (p <<  "select a option") <|>
+   r <- askm  $ getSelect (setSelectedOption ""  (p <<  "select a option") <|>
                          setOption "red"  (b <<  "red")                  <|>
                          setOption "blue" (b <<  "blue")                 <|>
                          setOption "Green"  (b <<  "Green")  )
                          <! dosummit
-   ask $ p << (r ++ " selected") ++> wlink () (p <<  " menu")
+   askm  $ p << (r ++ " selected") ++> wlink () (p <<  " menu")
 
 
    where
    dosummit= [("onchange","this.form.submit()")]
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav options
Demos/PreventGoingBack.hs view
@@ -1,6 +1,7 @@ 
 module PreventGoingBack ( preventBack) where
-import MFlow.Wai.Blaze.Html.All
+import MFlow.Wai.Blaze.Html.All+import Menu
 import System.IO.Unsafe
 import Control.Concurrent.MVar
 
@@ -8,14 +9,14 @@ 
 
 preventBack= do
-    ask $ wlink () << b << "press here to pay 100000 $ "
+    askm  $ wlink "don't care" << b << "press here to pay 100000 $ "
     payIt
     paid  <- liftIO $ readMVar rpaid
-    preventGoingBack . ask $   p << "You already paid 100000 before"
-                           ++> p << "you can no go back until the end of the buy process"
+    preventGoingBack . askm  $ p << "You already paid 100000 before"
+                           ++> p << "you can not go back until the end of the buy process"
                            ++> wlink () << p << "Please press here to continue"
                            
-    ask $   p << ("you paid "++ show paid)
+    askm  $   p << ("you paid "++ show paid)
         ++> wlink () << p << "Press here to go to the menu or press the back button to verify that you can not pay again"
     where
     payIt= liftIO $ do
@@ -23,5 +24,5 @@       paid <- takeMVar  rpaid
       putMVar rpaid $ paid + 100000
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav preventBack
Demos/PushDecrease.hs view
@@ -2,17 +2,22 @@ module PushDecrease ( pushDecrease) where
 
 import MFlow.Wai.Blaze.Html.All
+
 import Control.Concurrent.STM
 import Text.Hamlet
 import Control.Concurrent
 
+import Menu
+-- to run it alone, comment "import menu" and uncomment:
+--main= runNavigation "" $ transientNav pushDecrease
 
+
 atomic= liftIO . atomically
 
 pushDecrease= do
  tv <- liftIO $ newTVarIO 10
 
- page $
+ pagem $
       [shamlet|
        <div>
            <h2> Maxwell Smart push counter
@@ -25,7 +30,7 @@ 
  where
  counter tv = push Html 0 $ do
-      setTimeouts 2 0     -- kill  the thread when count finish
+      setTimeouts 2 0     -- kill  the thread after 2 s of incactivity, when count finish
       n <- atomic $ readTVar tv
       if (n== -1)
         then  do
@@ -35,6 +40,4 @@           liftIO $ threadDelay 1000000
           h1 << (show n) ++> noWidget
 
--- to run it alone:
---main= runNavigation "" $ transientNav pushDecrease
 
Demos/PushSample.hs view
@@ -1,13 +1,14 @@ 
 module PushSample (pushSample) where
 
-import MFlow.Wai.Blaze.Html.All
-import Control.Concurrent.STM
+import MFlow.Wai.Blaze.Html.All hiding (retry)+import Menu 
+import Control.Concurrent.STM 
 
 
 pushSample=  do
   tv <- liftIO $ newTVarIO $ Just "The content will be appended here"
-  page $   h2 << "Push example"
+  pagem $   h2 << "Push example"
        ++> p << "The content of the text box will be appended to the push widget above."
        ++> p << "A push widget can have links and form fields."
        ++> p << "Since they are asynchronous, the communucation must be trough mutable variables"
@@ -43,5 +44,5 @@ 
 atomic= liftIO . atomically
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav pushSample
Demos/Radio.hs view
@@ -2,12 +2,13 @@ module Radio ( radio) where
 
 import MFlow.Wai.Blaze.Html.All
+import Menu 
 radio = do
-   r <- ask $   p << b <<  "Radio buttons"
+   r <- askm $   p << b <<  "Radio buttons"
             ++> getRadio [\n -> fromStr v ++> setRadioActive v n | v <- ["red","green","blue"]]
 
-   ask $ p << ( show r ++ " selected")  ++> wlink ()  << p <<  " menu"
+   askm $ p << ( show r ++ " selected")  ++> wlink ()  << p <<  " menu"
 
--- to run it alone:
+-- to run it alone, change askm by ask and uncomment this:
 --main= runNavigation "" $ transientNav radio
Demos/ShopCart.hs view
@@ -2,7 +2,8 @@ {-# OPTIONS  -XDeriveDataTypeable #-}
 module ShopCart ( shopCart) where
 
-import MFlow.Wai.Blaze.Html.All
+import MFlow.Wai.Blaze.Html.All+
 import Data.Typeable
 import qualified Data.Vector as V
 import Text.Blaze.Html5 as El
@@ -10,50 +11,61 @@ import Data.Monoid
 import Data.String
 import Data.Typeable
++import Menu 
+-- to run it alone, comment import Menu and uncomment the code below
+--main= runNavigation ""   shopCart+
--askm= ask+
 data ShopOptions= IPhone | IPod | IPad deriving (Bounded, Enum, Show,Read , Typeable)
 
+newtype Cart= Cart (V.Vector Int) deriving Typeable 
-newtype Cart= Cart (V.Vector Int) deriving Typeable
 emptyCart= Cart $ V.fromList [0,0,0]
-
-shopCart  = do
-
-   addHeader $ \html -> p << ( El.span <<
-     "A persistent flow  (uses step). The process is killed after 100 seconds of inactivity \
-     \but it is restarted automatically. Event If you restart the whole server, it remember the shopping cart\n\n \
-     \Defines a table with links that return ints and a link to the menu, that abandon this flow.\n\
-     \The cart state is not stored, Only the history of events is saved. The cart is recreated by running the history of events."
++shopCart= shopCart1 
-     <> html)
-   setTimeouts 100 (60 * 60)
-   shopCart1
-   where
-   shopCart1 =  do
-     o <-  step . ask $ do
-             let moreexplain= p << "The second parameter of \"setTimeout\" is the time during which the cart is recorded"
+shopCart1  =  do+     setHeader  stdheader 
+--     setTimeouts 200 $ 60*60   
+     prod <-+        step . askm $ do
              Cart cart <- getSessionData `onNothing` return  emptyCart
 
              moreexplain
-              ++>
+              ++> 
               (table ! At.style (attr "border:1;width:20%;margin-left:auto;margin-right:auto")
               <<< caption <<  "choose an item"
               ++> thead << tr << ( th << b <<   "item" <> th << b <<  "times chosen")
               ++> (tbody
                   <<< tr ! rowspan (attr "2") << td << linkHome
-                  ++> (tr <<< td <<< wlink  IPhone (b <<  "iphone") <++  td << ( b <<  show ( cart V.! 0))
-                  <|>  tr <<< td <<< wlink  IPod   (b <<  "ipod")   <++  td << ( b <<  show ( cart V.! 1))
-                  <|>  tr <<< td <<< wlink  IPad   (b <<  "ipad")   <++  td << ( b <<  show ( cart V.! 2)))
+                  ++> (tr <<< td <<< wlink  IPhone (b <<  "iphone")+                          <++  tdc << ( b <<  show ( cart V.! 0))
+                  <|>  tr <<< td <<< wlink  IPod   (b <<  "ipod")+                          <++  tdc << ( b <<  show ( cart V.! 1))
+                  <|>  tr <<< td <<< wlink  IPad   (b <<  "ipad")+                          <++  tdc << ( b <<  show ( cart V.! 2)))
                   <++  tr << td <<  linkHome
-                  ))
-     let i =fromEnum o
-     Cart cart <- getSessionData `onNothing` return emptyCart
+                  ))++                  
+     let i = fromEnum prod+     Cart cart <- getSessionData `onNothing` return  emptyCart
      setSessionData . Cart $ cart V.// [(i, cart V.!  i + 1 )]
      shopCart1
 
-    where
+    where+    tdc= td ! At.style (attr "text-align:center")
     linkHome= a ! href  (attr $ "/" ++ noScript) << b <<  "home"
-    attr= fromString
-
--- to run it alone:
---main= runNavigation ""   shopCart
+    attr= fromString+    moreexplain= do+     p $ El.span <<
+         "A persistent flow  (uses step). The process is killed after the timeout set by setTimeouts \
+         \but it is restarted automatically. Event If you restart the whole server, it remember the shopping cart\n\n \+         \The shopping cart is not logged, just the products bought returned by step are logged. The shopping cart\+         \is rebuild from the events (that is an example of event sourcing.\n\n\
+         \.Defines a table with links that return ints and a link to the menu, that abandon this flow.\n\
+         \.The cart state is not stored, Only the history of events is saved. The cart is recreated by running the history of events."
++     p << "The second parameter of \"setTimeout\" is the time during which the cart is recorded"
Demos/SumView.hs view
@@ -2,8 +2,9 @@ module SumView (sumInView) where
 
 import MFlow.Wai.Blaze.Html.All
+import Menu 
-sumInView= ask $ p << "ask for three numbers in the same page and display the result.\
+sumInView= askm $ p << "ask for three numbers in the same page and display the result.\
                       \It is possible to modify the inputs and the sum will reflect it"
                ++> sumWidget
                
@@ -20,5 +21,5 @@       p <<  ("The result is: "++show n)  ++>  wlink () << b << " menu"
       <++ p << "you can change the numbers in the boxes to see how the result changes"
 
--- to run it alone:
+-- to run it alone, replace askm by ask and uncomment the following line
 --main= runNavigation "" $ transientNav sumWidget
Demos/TestREST.hs view
@@ -1,45 +1,45 @@ 
 module TestREST where
 import MFlow.Wai.Blaze.Html.All
+import Menu
 import Data.Monoid
 import Data.String
 
--- 9 pages , each page has a restful link (page = ask)
+-- A menu with two branches, each one is a sucession of pages
 
--- to run it alone:
---main= runNavigation "" $ transientNav testREST
+-- 9 pages , each page has a restful link (pagem = ask)
 
+-- to run it alone,  delete "import Menu" and uncomment the next lines
 
-testREST= do
-  setTimeouts 120 0
+-- main= runNavigation "" $ transientNav testREST
 
-  addHeader header1
+-- pagem= page
 
-  option <- page $   wlink "a" << p << "letters " <++ p << "or"
-                 <|> wlink "1" << p << "numbers"
 
+testREST= do
+--  setTimeouts 120 0
+
+  option <- pagem $  h2 << "Choose between:"
+                 ++> wlink "a" << b << "letters " <++ i << " or "
+                 <|> wlink "1" << b << "numbers"
+
   case option of
     "1" -> do
-          page $ wlink "2" << contentFor "1"
-          page $ wlink "3" << contentFor "2"
-          page $ wlink "4" << contentFor "3"
-          page $ wlink ()  << "menu"
+          pagem $ wlink "2" << contentFor "1" 
+          pagem $ wlink "3" << contentFor "2"
+          pagem $ wlink "4" << contentFor "3"
+          pagem $ wlink ()  << "menu"
 
     "a" -> do
-          page $ wlink "b" << contentFor "a"
-          page $ wlink "c" << contentFor "b"
-          page $ wlink "d" << contentFor "c"
-          page $ wlink ()  << "menu"
+          pagem $ wlink "b" << contentFor "a"
+          pagem $ wlink "c" << contentFor "b"
+          pagem $ wlink "d" << contentFor "c"
+          pagem $ wlink ()  << "menu"
 
 
-contentFor x=
+contentFor x= do
         p << "page for"
-        <> b << x
-        <> p << "goto next page"
-
-header1 h= html << body (text h)
-  where
-  text h= a ! href (fromString "http://haskell-web.blogspot.com.es/2013/07/the-web-navigation-monad.html")
-            << "see this" <> hr <> h <> hr
-          <> a ! href (fromString "/") << "main menu"
+        b << x
+        p << "goto next page"
+        p << "or press the back button for the previous page"
 
Demos/TraceSample.hs view
@@ -2,10 +2,11 @@ module TraceSample ( traceSample) where
 
 import MFlow.Wai.Blaze.Html.All
+import Menu
 import Control.Monad.Loc
 
 traceSample= do
-  page $   h2 << "Error trace example"
+  pagem $  h2 << "Error trace example"
        ++> p << "MFlow now produces execution traces in case of error by making use of the backtracking mechanism"
        ++> p << "It is more detailed than a call stack"
        ++> p << "this example has a deliberate error"
@@ -13,14 +14,14 @@        ++> p << "You must be logged as admin to see the trace"
        ++> wlink () << p << "pres here"
 
-  page $   p <<  "Please login with admin/admin"
-       ++> userWidget (Just "admin") userLogin
+  pagem $   p <<  "Please login with admin/admin"
+        ++> userWidget (Just "admin") userLogin
 
   u <- getCurrentUser
-  page $   p << "The trace will appear after you press the link. press one of the options available at the bottom of the page"
-       ++> p << ("user="++ u) ++> br
-       ++> wlink () << "press here"
-  page $   error $ "this is the error"
+  pagem $   p << "The trace will appear after you press the link. press one of the options available at the bottom of the pagem"
+        ++> p << ("user="++ u) ++> br
+        ++> wlink () << "press here"
+  pagem $   error $ "this is the error"
 
--- to run it alone:
+-- to run it alone, replace askm by ask and uncomment the following line
 --main= runNavigation "" $ transientNav traceSample
Demos/demos-blaze.hs view
@@ -1,10 +1,11 @@-{-# OPTIONS  -XDeriveDataTypeable -XQuasiQuotes  -F -pgmF MonadLoc #-}
+{-# OPTIONS  -XDeriveDataTypeable -XQuasiQuotes -XOverloadedStrings -F -pgmF MonadLoc #-}
 module Main where
-import MFlow.Wai.Blaze.Html.All hiding (article)
-import Text.Blaze.Html5 as El hiding (article)
-import Text.Blaze.Html5.Attributes as At hiding (step)
-
+import MFlow.Wai.Blaze.Html.All hiding (name)
+import Text.Blaze.Html5 as El
+import Text.Blaze.Html5.Attributes as At hiding (step,name)
+import Data.TCache.IndexQuery
 import Data.Typeable
+ 
 import Data.Monoid
 import Data.String
@@ -12,7 +13,8 @@ 
 -- For error traces
 import Control.Monad.Loc
-
++import Menu
 import TestREST
 import Actions
 import IncreaseInt
@@ -35,253 +37,104 @@ import PushSample
 import Grid
 import Radio
-import SumView
+import SumView+import MCounter+import Database+import MFlowPersistent+import RuntimeTemplates
 
 import Debug.Trace-(!>)= flip trace
-
-main= do
-   setAdminUser "admin" "admin"
-   syncWrite SyncManual
-   setFilesPath "Demos/"
-   addMessageFlows  [("shop"      , runFlow $ shopCart  `showSource` "ShopCart.hs")
-                    ,("navigation", runFlow $ transientNav testREST `showSource` "TestREST.hs")]
-
-   runNavigation "" $  transientNav mainmenu
-
-
-attr= fromString
-text= fromString
-
-data Options= CountI | CountS | Radio
-            | Login | TextEdit |Grid | Autocomp | AutocompList
-            | ListEdit |Shop | Action | Ajax | Select
-            | CheckBoxes | PreventBack | Multicounter
-            | Combination
-            | FViewMonad | Counter | WDialog |Push |PushDec |Trace
-            deriving (Bounded, Enum,Read, Show,Typeable)
-
-newtype Server= Server String deriving Typeable
-mainmenu =  do
-       host <- getRawParam "Host" `onNothing` return "mflowdemo.herokuapp.com/"-       setSessionData $ Server host-       setHeader $ stdheader 
-       setTimeouts 100 0-       
-       r <- ask $  wcached "menu" 0 $
-               b <<  "PUSH"-               ++> (li <<< wlink Push << b << "Push example"-                                 <++ b << " A push widget in append mode receives input from\-                                         \a text box with autorefresh"-                                 <>  article pushl)
-               <|> (li <<< wlink PushDec << b << "A push counter"-                                 <++ b << " Show a countdown. Then goes to the main menu"-                                 <>  article pushdec)
-               <|> br ++> br
-               ++> b <<  "ERROR TRACES"
-               ++> (li <<< wlink Trace << b << " Execution traces for errors"-                             <++ b << " produces an error and show the complete execution trace"-                             <>  article errorTrace)
-               <|> br ++> br ++>
-               b <<  "DIFFERENT KINDS OF FLOWS"-               
-               ++> (li $ do a ! href (attr "/navigation") <<  " REST navigation"-                            b << " Navigates trough  menus and a sucession of GET pages"-                            article navigation)-                            
-               ++> (li $ do a ! href (attr "/shop") <<  " Stateful flow: shopping"-                            b << " Add articles to a persistent shopping cart"-                            article stateful)
-                       
-               ++>  br ++> br ++> b <<  "BASIC"-               
-               ++>  (li <<< wlink CountI       << b <<  "Increase an Int"-                                   <++ b << " A loop that increases the Int value of a text box")-                                   
-               <|>  (li <<< wlink CountS       << b <<  "Increase a String"-                                   <++ b << " A loop that concatenate text in a text box")-                                   
-               <|>  (li <<< wlink Select       << b <<  "Select options"-                                   <++ b << " A combo box")-                                   
-               <|>  (li <<< wlink CheckBoxes   << b <<  "Checkboxes")-           
-               <|>  (li <<< wlink Radio        << b <<  "Radio buttons")
-
-               <++  br <>  br                 <> b <<  "WIDGET ACTIONS & CALLBACKS"-               
-               <|>  (li <<< wlink Action       << b <<  "Example of action, executed when a widget is validated")
 -               <|>  (li <<< wlink FViewMonad   << b <<  "in page flow: sum of three numbers"-                             <++ b << " Page flows are monadic widgets that modifies themselves in the page"-                             <>  article pageflow)
--               <|>  (li <<< wlink Counter      << b <<  "Counter"-                             <++ b << " A page flow which increases a counter by using a callback"-                             <>  article callbacks)
--               <|>  (li <<< wlink Multicounter << b <<  "Multicounter"-                             <++ b << " Page flow with many independent counters with autoRefresh, so they modify themselves in-place"-                             <>  article callbacks)
--               <|>  (li <<< wlink Combination  << b <<  "Combination of three dynamic widgets"-                             <++ b << " Combination of autoRefreshe'd widgets in the same page, with\-                                      \ different behaviours"-                             <>  article combinationl)
--               <|>  (li <<< wlink WDialog      << b <<  "Modal dialog"-                             <++ b << " A modal Dialog box with a form within a page flow")          
+--(!>)= flip trace
 
-               <|>  br ++>  br               ++> b <<  "DYNAMIC WIDGETS"
+--attr= fromString -               ++>  (li <<< wlink Ajax         << b <<  "AJAX example"-                             <++ b << " A onclick event in a text box invokes a server procedure that \-                                      \increment the integer value"-                             <>  article ajaxl)
 -               <|>  (li <<< wlink Autocomp     << b <<  "autocomplete"-                             <++ b << " Example of autocomplete, a widget which takes the suggested values from a server procedure")                 
 -               <|>  (li <<< wlink AutocompList << b <<  "autocomplete List"-                             <++ b << " Example of a widget that generates a set of return values, suggested by a autocomplete input box"-                             <>  article editList)
--               <|>  (li <<< wlink ListEdit     << b <<  "list edition"-                             <++ b << " Example of a widget that edit, update and delete a list of user-defined widgets")
--               <|>  (li <<< wlink Grid         << b <<  "grid"-                             <++ b << " Example of the same widget In this case, containing a row of two fields, aranged in a table"-                             <>  article gridl)
--               <|>  (li <<< wlink TextEdit     << b <<  "Content Management"-                             <++ b << " Example of the (basic) content management primitives defined in MFlow.Forms.Widgets")
+main= do+   index idnumber                      -- for the Database example+   index tfieldKey
+   setAdminUser adminname adminname+   userRegister edadmin edadmin+   userRegister "edituser" "edituser"
+   syncWrite  $ Asyncronous 120 defaultCheck  1000+--   addMessageFlows[("wiki", transient $ runFlow $ ask  wiki)] 
+   setFilesPath "Demos/"+   runNavigation "" $ do+       setHeader $ stdheader 
+       setTimeouts 400 $ 60 * 60 
-               <|>  br ++>  br ++> b <<  "OTHERS"
+       r <- step . ask $   tFieldEd edadmin "head" "set Header" <++ hr+                       **> topLogin+                       **> (divmenu  <<< br ++>  mainMenu) 
+                       <** (El.div ! At.style "float:right;width:65%;overflow:auto;"+                            <<< tFieldEd edadmin "intro" "enter intro text")
+
+       case r of+             Wiki      ->    delSessionData (Filename "") >> step  wiki                 
+             CountI    ->     step  (clickn 0)           `showSource`  "IncreaseInt.hs"
+             CountS    ->     step  (clicks "1")         `showSource`  "IncreaseString.hs"
+             Action    ->     step  actions              `showSource`  "Actions.hs"
+             Ajax      ->     step  ajaxsample           `showSource`  "AjaxSample.hs"
+             Select    ->     step  options              `showSource`  "Options.hs"
+             CheckBoxes ->    step  checkBoxes           `showSource`  "CheckBoxes.hs"
+             TextEdit  ->     step  textEdit             `showSource`  "ContentManagement.hs"
+             Grid      ->     step  grid                 `showSource`  "Grid.hs"
+             Autocomp  ->     step  autocomplete1        `showSource`  "AutoComplete.hs"
+             AutocompList ->  step  autocompList         `showSource`  "AutoCompList.hs"
+             ListEdit  ->     step  wlistEd              `showSource`  "ListEdit.hs"
+             Radio     ->     step  radio                `showSource`  "Radio.hs"
+             Login     ->     step  loginSample          `showSource`  "LoginSample.hs"
+             PreventBack ->   step  preventBack          `showSource`  "PreventGoingBack.hs"
+             Multicounter->   step  multicounter         `showSource`  "Multicounter.hs"
+             FViewMonad  ->   step  sumInView            `showSource`  "SumView.hs"
+             Counter     ->   step  counter              `showSource`  "Counter.hs"
+             Combination ->   step  combination          `showSource`  "Combination.hs"
+             WDialog     ->   step  wdialog1             `showSource`  "Dialog.hs"
+             Push        ->   step  pushSample           `showSource`  "PushSample.hs"
+             PushDec     ->   step  pushDecrease         `showSource`  "PushDecrease.hs"
+             Trace       ->   step  traceSample          `showSource`  "TraceSample.hs"+             RESTNav     ->   step  testREST             `showSource`  "TestREST.hs"+             Database    ->   step  database             `showSource`  "Database.hs"
+             ShopCart    ->   shopCart                   `showSource` "ShopCart.hs"+             MCounter    ->   mcounter                   `showSource` "MCounter.hs"+             MFlowPersist ->  step mFlowPersistent       `showSource` "MFlowPersistent.hs"+             RuntimeTemplates -> step runtimeTemplates   `showSource` "RuntimeTemplates.hs" -               ++>  (li <<< wlink Login        << b <<  "login/logout"-                             <++ b << " Example of using the login and/or logout")
 -               <|>  (li <<< wlink PreventBack  << b <<  "Prevent going back after a transaction"-                             <++ b << " Control backtracking to avoid navigating back to undo something that can not be undone\-                                      \. For example, a payment"-                             <>  article preventbackl)
-
-
-
-       case r of
-             CountI    ->  clickn 0              `showSource`  "IncreaseInt.hs"
-             CountS    ->  clicks "1"            `showSource`  "IncreaseString.hs"
-             Action    ->  actions 1             `showSource`  "actions.hs"
-             Ajax      ->  ajaxsample            `showSource`  "AjaxSample.hs"
-             Select    ->  options               `showSource`  "Options.hs"
-             CheckBoxes -> checkBoxes            `showSource`  "CheckBoxes.hs"
-             TextEdit  ->  textEdit              `showSource`  "TextEdit.hs"
-             Grid      ->  grid                  `showSource`  "Grid.hs"
-             Autocomp  ->  autocomplete1         `showSource`  "Autocomplete.hs"
-             AutocompList -> autocompList        `showSource`  "AutoCompList.hs"
-             ListEdit  ->  wlistEd               `showSource`  "ListEdit.hs"
-             Radio     ->  radio                 `showSource`  "Radio.hs"
-             Login     ->  loginSample           `showSource`  "LoginSample.hs"
-             PreventBack -> preventBack          `showSource`  "PreventGoingBack.hs"
-             Multicounter-> multicounter         `showSource`  "Multicounter.hs"
-             FViewMonad  -> sumInView            `showSource`  "SumView.hs"
-             Counter    -> counter               `showSource`  "Counter.hs"
-             Combination -> combination          `showSource`  "Combination.hs"
-             WDialog     -> wdialog1             `showSource`  "Dialog.hs"
-             Push        -> pushSample           `showSource`  "PushSample.hs"
-             PushDec     -> pushDecrease         `showSource`  "PushDecrease.hs"
-             Trace       -> traceSample          `showSource`  "TraceSample.hs"
 -space= preEscapedToMarkup "&nbsp;"-article link=  space <> a ! href (attr link) <<  i << "(article)"+wiki =  do+  pag <- getRestParam `onNothing` return "Index"+  askm $+   (docTypeHtml $ do
+       El.head $ do+        El.title $ fromString pag)+        ++> (El.div ! At.style "float:right" <<< autoRefresh wlogin )+        **> ( h1 ! At.style "text-align:center" <<<  tFieldEd "editor" (wikip ++pag ++ "title.html") (fromString pag))+        **> tFieldEd "editor" (wikip ++ pag ++ "body.html") "Enter the body"+        **> noWidget -pushdec= "http://haskell-web.blogspot.com.es/2013/07/maxwell-smart-push-counter.html"-pushl= "http://haskell-web.blogspot.com.es/2013/07/new-push-widgets-for-presentation-of.html"-errorTrace= "http://haskell-web.blogspot.com.es/2013/07/automatic-error-trace-generation-in.html"-navigation= "http://haskell-web.blogspot.com.es/2013/07/the-web-navigation-monad.html"-combinationl= "http://haskell-web.blogspot.com.es/2013/06/and-finally-widget-auto-refreshing.html"-pageflow= "http://haskell-web.blogspot.com.es/2013/06/the-promising-land-of-monadic-formlets.html"-callbacks= "http://haskell-web.blogspot.com.es/2013/06/callbacks-in-mflow.html"-gridl= "http://haskell-web.blogspot.com.es/2013/01/now-example-of-use-of-active-widget.html"-editList= "http://haskell-web.blogspot.com.es/2012/12/on-spirit-of-mflow-anatomy-of-widget.html"-stateful= "http://haskell-web.blogspot.com.es/2013/04/more-on-session-management-in-mflow.html"-preventbackl= "http://haskell-web.blogspot.com.es/2013/04/controlling-backtracking-in-mflow.html"-ajaxl= "http://hackage.haskell.org/packages/archive/MFlow/0.3.1.0/doc/html/MFlow-Forms.html#g:17"+wikip="wiki/" -
-showSource w filename = do
-      Server host <- getSessionData `onNothing` error "host must have been set"
-      let path=  attr $ "http://" <> host <> filename !> host
-      addHeader $ \html -> source path html <> download path
-      w
-      where-      download path= p $ text "download " <> a ! href  path << filename
-      source path html =
-        El.div $ do
-             html
-             br
-             br
-             hr
-             h3 $ text "SOURCE CODE:"
-             iframe ! At.style sty
-                    ! At.height (attr "400")
-                    ! At.src path
-                    $ b $ text "no iframes"
-      sty= attr "float:left\
-                \;width:100%\
-                \;margin-left:5px;margin-right:10px;overflow:auto;"
-
++-- | to run it on heroku, traceSample is included since heroku does not run the monadloc preprocessor
 traceSample= do
-  page $   h2 << "Error trace example"
-       ++> p << "MFlow now produces execution traces in case of error by making use of the backtracking mechanism"
-       ++> p << "It is more detailed than a call stack"
-       ++> p << "this example has a deliberate error"
+  pagem $ h2  "Error trace example"
+       ++> p  "MFlow now produces execution traces in case of error by making use of the backtracking mechanism"
+       ++> p  "It is more detailed than a call stack"
+       ++> p  "this example has a deliberate error"
        ++> br
-       ++> p << "You must be logged as admin to see the trace"
-       ++> wlink () << p << "pres here"
+       ++> p "You must be logged as admin to see the trace"
+       ++> wlink () << p "pres here"
 
-  page $   p <<  "Please login with admin/admin"
-       ++> userWidget (Just "admin") userLogin
+  pagem $   p "Please login with admin/admin"
+        ++> userWidget (Just "admin") userLogin
 
   u <- getCurrentUser
-  page $   p << "The trace will appear after you press the link. press one of the options available at the bottom of the page"
+  pagem $  p "The trace will appear after you press the link. press one of the options available at the bottom of the page"
        ++> p << ("user="++ u) ++> br
-       ++> wlink () << "press here"
-  page $   error $ "this is the error"
+       ++> wlink () "press here"
+  pagem $  error $ "this is the error"
 
 
-stdheader  c= docTypeHtml
-   $ El.head << (El.title << "MFlow examples"
-     <> link ! rel   ( attr "stylesheet")
-             ! type_ ( attr "text/css")
-             ! href (attr "http://jqueryui.com/resources/demos/style.css"))
-   <> (body $ 
-      a ! At.style (attr "align:center;")
-        ! href ( attr  "http://hackage.haskell.org/packages/archive/MFlow/0.3.0.1/doc/html/MFlow-Forms.html")
-        << h1 <<  "MFlow examples"
-   <> br
-   <> hr
-   <> (El.div ! At.style (attr "float:left\
-                         \;width:50%\
-                         \;margin-left:10px;margin-right:10px;overflow:auto;") $
-          br <> c)
-   <> (El.div ! At.style (attr "float:right;width:45%;overflow:auto;") $
 
-       br
-       <> p  << a ! href (attr "/html/MFlow/index.html") <<  "MFlow package description and documentation"
-       <> p  << a ! href (attr "https://github.com/agocorona/MFlow/blob/master/Demos") <<  "see demos source code"
-       <> p  << a ! href (attr "https://github.com/agocorona/MFlow/issues") <<  "bug tracker"
-       <> p  << a ! href (attr "https://github.com/agocorona/MFlow") <<  "source repository"
-       <> p  << a ! href (attr "http://hackage.haskell.org/package/MFlow") <<  "Hackage repository"
---       <> (h3 $ do---             text "SOURCE CODE:"
---             iframe ! At.style sty
---                    ! At.height (attr "400")
---                    ! At.src (attr $   "http://" <> host <> ('/':"demos-blaze.hs"))
---                    $ b $ text "no iframes")-                ))
-   where-   sty= attr "float:left\
-                \;width:100%\
-                \;margin-left:5px;margin-right:10px;overflow:auto;"
-            
MFlow.cabal view
@@ -1,157 +1,133 @@ name: MFlow
-version: 0.3.1.1
+version: 0.3.2.0
 cabal-version: >=1.8
 build-type: Simple
 license: BSD3
 license-file: LICENSE
 maintainer: agocorona@gmail.com
 stability: experimental
-Bug-reports: https://github.com/agocorona/MFlow/issues
+bug-reports: https://github.com/agocorona/MFlow/issues
 synopsis: stateful, RESTful web framework
-description: MFlow is a Web Framework that turns Web programing back into just ordinary programming by automating all the extra-             complexities.-            .-            The goals of MFlow are:-            .-            -To invert back the inversion of control of web applications and turn web programming into ordinary, intuitive, imperative-like, programming as seen by the programmer.-            .-            -At the same time, to maintain, for the user, all the freedom that it has in web applications.--            -For scalability-sensitive applications, to avoid the fat state snapshots that continuation based frameworks need to cope with these two previous requirements. State replication and Horizontal scalability must be possible.-            .-            -For REST advocates, to maintain the elegant notation of REST urls and the statelessness of GET requests.-            .-            -For expert haskell programmers, to reuse the already existent web libraries and techniques.-            .-            -For beginner programmers and for Software Enginners, to provide with a high level DSL of reusable, self contained widgets for the user interface, and multipage procedures that can work together provided that they statically typecheck, with zero configuration.-            .-            -For highly interactive applications, to give dynamic widgets that have their own dynamic behaviors in the page, and communicate themselves without the need of explicit  JavaScript programming.-            .-            -No deployment, in order to speed up the development process. see <http://haskell-web.blogspot.com.es/2013/05/a-web-application-in-tweet.html>-            .-            MFlow try to solve the first requirements using a different approach. The routes are expressed as normal, monadic haskell code in the FlowM monad. Local links point to alternative routes within this monadic computation just like a textual menu in a console application. Any GET page is directly reachable by means of a RESTful URL.-            .-            At any moment the flow can respond to the back button or to any RESTful path that the user may paste in the navigation bar. If the procedure is waiting for another different page, the FlowM monad backtrack until the path partially match. From this position on, the execution goes forward until the rest of the path match.  Thus, no matter the previous state of the server process, it recover the state of execution appropriate for the request. This way the server process is virtually stateless for any GET request. However, it is possible to store a session state, which may backtrack or not when the navigation goes back and forth. It is up to the programmer. Synchronization between server state and web browser state is supported out-of-the-box.-            .-            When the state matters, and user interactions can last for long, such are shopping carts etc. It uses a log for thread state persistence. The server process shut itself down after a programmer defined timeout. Once a new request of the same user arrive, the log is used to recover the process state. There is no need to store a snapshot of every continuation, just the result of each step.-            .-            State consistence and transactions are given by the TCache package. It is data cache within the STM monad (Software Transactional Memory).  Serialization and deserialization of data is programmer defined, so it can adapt it to any database, although any other database interface can be used. Default persistence in files comes out of the box for rapid development purposes.-            .-            The processes interact trough widgets, that are an extension of formlets with additional applicative combinators , formatting, link management, callbacks, modifiers, caching and AJAX. All is coded in pure haskell. Each widget return statically typed data. They can dynamically modify themselves using AJAX internally (ust prefix it with autorefresh). They are auto-contained: they may include their own JavaScript code, server code and client code in a single pure Haskell procedure that can be combined with other widgets with no other configuration.-            .-            To combine widgets, applicative combinators are used. Widgets with dynamic behaviours can use the monadic syntax and callbacks.-            .-            The interfaces and communications are abstract, but there are bindings for blaze-html, HSP, Text.XHtml and byteString, Hack and WAI but it can be extended to non Web based architectures.-            .-            Bindings for hack, and hsp >= 0.8,  are not compiled by Hackage, and do not appear, but are included in the package files. To use them, add then to the exported modules and execute cabal install-            .-            The version 0.3.1 includes:-            .-            - Push widgets: http://haskell-web.blogspot.com.es/2013/07/maxwell-smart-push-counter.html-            .-            - Complete execution traces for errors: http://haskell-web.blogspot.com.es/2013/07/automatic-error-trace-generation-in.html-            .-            The version 0.3 added:-            - RESTful URLs: http://haskell-web.blogspot.com.es/2013/07/the-web-navigation-monad.html-            .-            - Automatic independent refreshing of widgets via Ajax. (see http://haskell-web.blogspot.com.es/2013/06/and-finally-widget-auto-refreshing.html)-            .-            - Page flows: Monadic widgets that can express his own behaviour and can run its own independent page flow. (see http://haskell-web.blogspot.com.es/2013/06/the-promising-land-of-monadic-formlets.html)-            .-            - Widget callbacks, used in page flows, that change the rendering of the widget (see http://haskell-web.blogspot.com.es/2013/06/callbacks-in-mflow.html)-            .-            - Widgets in modal and non modal dialogs (using jQuery dialog)-            .-            - Other jQuery widgets as MFlow widgets-            .-            The version 0.2 added better WAI integration, higher level dynamic Widgets, content management, multilanguage, blaze-html support, stateful ajax for server-side control, user-defined data in sessions and widget requirements for automatic installation of scripts, CSS and server flows.-            .-            The version 0.1 had transparent back button management, cached widgets, callbacks, modifiers, heterogeneous formatting, AJAX, and WAI integration.-            .-            .-            See "MFlow.Forms" for details-            .-            To do:-            .-            -Clustering 
-            .-            In this release, this issue has been fixed: <https://github.com/agocorona/MFlow/issues/8>-            
+description: MFlow is a Web Framework that turns Web programing back into just ordinary programming by automating all the extra
+             complexities.
+             .
+             The goals of MFlow are:
+             .
+             -To invert back the inversion of control of web applications and turn web programming into ordinary, intuitive, imperative-like, programming as seen by the programmer.
+             .
+             -At the same time, to maintain, for the user, all the freedom that it has in web applications.
+             -For scalability-sensitive applications, to avoid the fat state snapshots that continuation based frameworks need to cope with these two previous requirements. State replication and Horizontal scalability must be possible.
+             .
+             -For REST advocates, to maintain the elegant notation of REST urls and the statelessness of GET requests.
+             .
+             -For expert haskell programmers, to reuse the already existent web libraries and techniques.
+             .
+             -For beginner programmers and for Software Enginners, to provide with a high level DSL of reusable, self contained widgets for the user interface, and multipage procedures that can work together provided that they statically typecheck, with zero configuration.
+             .
+             -For highly interactive applications, to give dynamic widgets that have their own dynamic behaviors in the page, and communicate themselves without the need of explicit  JavaScript programming.
+             .
+             -No deployment, in order to speed up the development process. see <http://haskell-web.blogspot.com.es/2013/05/a-web-application-in-tweet.html>
+             .
+             MFlow try to solve the first requirements using a different approach. The routes are expressed as normal, monadic haskell code in the FlowM monad. Local links point to alternative routes within this monadic computation just like a textual menu in a console application. Any GET page is directly reachable by means of a RESTful URL.
+             .
+             At any moment the flow can respond to the back button or to any RESTful path that the user may paste in the navigation bar. If the procedure is waiting for another different page, the FlowM monad backtrack until the path partially match. From this position on, the execution goes forward until the rest of the path match.  Thus, no matter the previous state of the server process, it recover the state of execution appropriate for the request. This way the server process is virtually stateless for any GET request. However, it is possible to store a session state, which may backtrack or not when the navigation goes back and forth. It is up to the programmer. Synchronization between server state and web browser state is supported out-of-the-box.
+             .
+             When the state matters, and user interactions can last for long, such are shopping carts etc. It uses a log for thread state persistence. The server process shut itself down after a programmer defined timeout. Once a new request of the same user arrive, the log is used to recover the process state. There is no need to store a snapshot of every continuation, just the result of each step.
+             .
+             State consistence and transactions are given by the TCache package. It is data cache within the STM monad (Software Transactional Memory).  Serialization and deserialization of data is programmer defined, so it can adapt it to any database, although any other database interface can be used. Default persistence in files comes out of the box for rapid development purposes.
+             .
+             The processes interact trough widgets, that are an extension of formlets with additional applicative combinators , formatting, link management, callbacks, modifiers, caching and AJAX. All is coded in pure haskell. Each widget return statically typed data. They can dynamically modify themselves using AJAX internally (ust prefix it with autorefresh). They are auto-contained: they may include their own JavaScript code, server code and client code in a single pure Haskell procedure that can be combined with other widgets with no other configuration.
+             .
+             To combine widgets, applicative combinators are used. Widgets with dynamic behaviours can use the monadic syntax and callbacks.
+             .
+             The interfaces and communications are abstract, but there are bindings for blaze-html, HSP, Text.XHtml and byteString, Hack and WAI but it can be extended to non Web based architectures.
+             .
+             Bindings for hack, and hsp >= 0.8,  are not compiled by Hackage, and do not appear, but are included in the package files. To use them, add then to the exported modules and execute cabal install
+             .+             .+             This version 0.3.2 add runtime templates http://haskell-web.blogspot.com.es/2013/11/more-composable-elements-for-single.html+             .
+             The version 0.3.1 included:
+             .
+             - Push widgets: http://haskell-web.blogspot.com.es/2013/07/maxwell-smart-push-counter.html
+             .
+             - Complete execution traces for errors: http://haskell-web.blogspot.com.es/2013/07/automatic-error-trace-generation-in.html
+             .
+             The version 0.3 added:
+             - RESTful URLs: http://haskell-web.blogspot.com.es/2013/07/the-web-navigation-monad.html
+             .
+             - Automatic independent refreshing of widgets via Ajax. (see http://haskell-web.blogspot.com.es/2013/06/and-finally-widget-auto-refreshing.html)
+             .
+             - Page flows: Monadic widgets that can express his own behaviour and can run its own independent page flow. (see http://haskell-web.blogspot.com.es/2013/06/the-promising-land-of-monadic-formlets.html)
+             .
+             - Widget callbacks, used in page flows, that change the rendering of the widget (see http://haskell-web.blogspot.com.es/2013/06/callbacks-in-mflow.html)
+             .
+             - Widgets in modal and non modal dialogs (using jQuery dialog)
+             .
+             - Other jQuery widgets as MFlow widgets
+             .
+             The version 0.2 added better WAI integration, higher level dynamic Widgets, content management, multilanguage, blaze-html support, stateful ajax for server-side control, user-defined data in sessions and widget requirements for automatic installation of scripts, CSS and server flows.
+             .
+             The version 0.1 had transparent back button management, cached widgets, callbacks, modifiers, heterogeneous formatting, AJAX, and WAI integration.
+             .
+             .
+             See "MFlow.Forms" for details
+             .
+             To do:
+             .
+             -Clustering
+             .
+             In this release, runtime templates is e
 category: Web, Application Server
 author: Alberto Gómez Corona
 data-dir: ""
-extra-source-files: Demos/demos-blaze.hs-                  , Demos/TestREST.hs-                    , Demos/Actions.hs-                    , Demos/IncreaseInt.hs-                    , Demos/ShopCart.hs-                    , Demos/AjaxSample.hs-                    , Demos/TraceSample.hs-                    , Demos/IncreaseString.hs-                    , Demos/AutoCompList.hs-                    , Demos/ListEdit.hs-                    , Demos/AutoComplete.hs-                    , Demos/LoginSample.hs-                    , Demos/CheckBoxes.hs-                    , Demos/Multicounter.hs-                    , Demos/Combination.hs-                    , Demos/Options.hs-                    , Demos/ContentManagement.hs-                    , Demos/PreventGoingBack.hs-                    , Demos/Counter.hs-                    , Demos/PushDecrease.hs-                    , Demos/Dialog.hs-                    , Demos/PushSample.hs-                    , Demos/Grid.hs-                    , Demos/Radio.hs-                    , Demos/SumView.hs
-                  , src/MFlow/Hack.hs
-                  , src/MFlow/Hack/Response.hs
-                  , src/MFlow/Hack/XHtml.hs
-                  , src/MFlow/Hack/XHtml/All.hs
-                  , src/MFlow/Forms/HSP.hs-                  
-
+extra-source-files: Demos/demos-blaze.hs Demos/TestREST.hs
+                    Demos/Actions.hs Demos/IncreaseInt.hs Demos/ShopCart.hs
+                    Demos/AjaxSample.hs Demos/TraceSample.hs Demos/IncreaseString.hs
+                    Demos/AutoCompList.hs Demos/ListEdit.hs Demos/AutoComplete.hs
+                    Demos/LoginSample.hs Demos/CheckBoxes.hs Demos/Multicounter.hs
+                    Demos/Combination.hs Demos/Options.hs Demos/ContentManagement.hs
+                    Demos/PreventGoingBack.hs Demos/Counter.hs Demos/PushDecrease.hs
+                    Demos/Dialog.hs Demos/PushSample.hs Demos/Grid.hs Demos/Radio.hs
+                    Demos/SumView.hs src/MFlow/Hack.hs src/MFlow/Hack/Response.hs
+                    Demos/MCounter.hs src/MFlow/Hack/XHtml.hs
+                    src/MFlow/Hack/XHtml/All.hs src/MFlow/Forms/HSP.hs
 
 source-repository head
     type: git
     location: http://github.com/agocorona/MFlow
 
 library
-    build-depends: Workflow -any, transformers -any, mtl -any, 
+    build-depends: Workflow -any, transformers -any, mtl -any,
                    extensible-exceptions -any, xhtml -any, base >4.0 && <5,
-                   bytestring -any, containers -any, RefSerialize -any, TCache -any,
-                   stm >2, old-time -any, vector -any, directory -any,
-                   utf8-string -any, wai -any, case-insensitive -any, http-types -any,
-                   conduit -any, text -any, parsec -any, warp -any,
-                   random -any,  blaze-html -any, blaze-markup -any,-                   monadloc -any, hamlet -any-                  
-
-    exposed-modules: MFlow MFlow.Wai.Blaze.Html.All
-                     MFlow.Forms MFlow.Forms.Admin
-                     MFlow.Cookies  MFlow.Wai
-                     MFlow.Wai.XHtml.All MFlow.Forms.XHtml
-                     MFlow.Forms.Blaze.Html MFlow.Forms.Test
-                     MFlow.Forms.Widgets-                     MFlow.Forms.Internals-                     
-    other-modules:  MFlow.Wai.Response
+                   bytestring -any, containers -any, RefSerialize -any,
+                   TCache -any, stm >2, old-time -any, vector -any,
+                   directory -any, utf8-string -any, wai -any, case-insensitive -any,
+                   http-types -any, conduit -any, text -any, parsec -any, warp -any,
+                   random -any, blaze-html -any, blaze-markup -any, monadloc -any,
+                   hamlet -any
+    exposed-modules: MFlow MFlow.Wai.Blaze.Html.All MFlow.Forms
+                     MFlow.Forms.Admin MFlow.Cookies MFlow.Wai MFlow.Wai.XHtml.All
+                     MFlow.Forms.XHtml MFlow.Forms.Blaze.Html MFlow.Forms.Test
+                     MFlow.Forms.Widgets MFlow.Forms.Internals
     exposed: True
     buildable: True
     hs-source-dirs: src .
+    other-modules:  MFlow.Wai.Response
 
---executable demos-blaze---    build-depends: MFlow -any, RefSerialize -any, TCache -any, directory -any,---                   Workflow -any, base -any, blaze-html -any, bytestring -any,---                   containers -any, mtl -any, old-time -any, stm -any,---                   text -any, transformers -any, vector -any,  hamlet -any,---                   monadloc -any------    main-is: "demos-blaze.hs"---    ghc-options:---        -iDemos---        -threaded---        -rtsopts---    buildable: True---    hs-source-dirs: Demos+--executable demos-blaze
+--    build-depends: MFlow -any, RefSerialize -any, TCache -any,
+--                   directory -any ,  Workflow -any, base -any, blaze-html -any,
+--                   bytestring, containers -any, mtl -any, old-time -any,
+--                   stm -any, text -any, transformers -any, vector -any, hamlet -any,
+--                   monadloc -any, monadloc-pp -any, aws -any, network -any, hscolour -any,
+--                   persistent-template, persistent-sqlite, persistent,
+--                   conduit, http-conduit, monad-logger
+--
+--
+--    main-is: demos-blaze.Loc.hs
+--    buildable: True
+--    hs-source-dirs: Demos
+--    other-modules: MFlowPersistent MCounter
+--    ghc-options: -iDemos -threaded -rtsopts
+
src/MFlow.hs view
@@ -63,13 +63,13 @@ ,flushRec, receive, receiveReq, receiveReqTimeout, send, sendFlush, sendFragment
 , sendEndFragment, sendToMF
 -- * Flow configuration
-,addMessageFlows,getMessageFlows, transient, stateless,anonymous
+,addMessageFlows,getMessageFlows,delMessageFlow, transient, stateless,anonymous
 ,noScript,hlog, setNotFoundResponse,getNotFoundResponse,
 -- * ByteString tags
--- | very basic but efficient tag formatting
+-- | very basic but efficient bytestring tag formatting
 btag, bhtml, bbody,Attribs, addAttrs
 -- * user
-, userRegister, setAdminUser, getAdminName
+, userRegister, setAdminUser, getAdminName, Auth(..),getAuthMethod, setAuthMethod
 -- * static files
 ,setFilesPath
 -- * internal use
@@ -83,9 +83,9 @@ import GHC.Conc(unsafeIOToSTM)
 import Data.Typeable
 import Data.Maybe(isJust, isNothing, fromMaybe, fromJust)
-import Data.Char(isSeparator)
+import Data.Char(isSeparator) 
 import Data.List(isPrefixOf,isSuffixOf,isInfixOf, elem , span, (\\),intersperse)
-import Control.Monad(when)
+import Control.Monad(when) 
 
 import Data.Monoid
 import Control.Concurrent(forkIO,threadDelay,killThread, myThreadId, ThreadId)
@@ -96,8 +96,9 @@ import Data.TCache
 import Data.TCache.DefaultPersistence  hiding(Indexable(..))
 import Data.TCache.Memoization
-import  Data.ByteString.Lazy.Char8 as B  (head, readFile,ByteString, concat,pack, unpack,empty,append,cons,fromChunks)
+import qualified Data.ByteString.Lazy.Char8 as B  (head, readFile,ByteString, concat,pack, unpack,empty,append,cons,fromChunks)
 import Data.ByteString.Lazy.Internal (ByteString(Chunk))
+import qualified Data.ByteString.Char8 as SB
 import qualified Data.Map as M
 import System.IO
 import System.Time
@@ -106,11 +107,11 @@ import Control.Monad.Trans
 import qualified Control.Exception as CE
 import Data.RefSerialize hiding (empty)
-
+import qualified Data.Text as T
 import System.Posix.Internals
 
---import Debug.Trace
---(!>)  =   flip trace
+import Debug.Trace
+(!>)  =   flip trace
 
 
 -- | a Token identifies a flow that handle messages. The scheduler compose a Token with every `Processable`
@@ -118,9 +119,9 @@ data Token = Token{twfname,tuser, tind :: String , tpath :: [String], tenv:: Params, tsendq :: MVar Req, trecq :: MVar Resp}  deriving  Typeable
 
 instance Indexable  Token  where
-     key (Token w u i _ _ _ _  )=
-          if u== anonymous then  u ++ i   -- ++ "@" ++ w
-                          else  u       -- ++ "@" ++ w
+     key (Token w u i _ _ _ _  )=  i
+--          if u== anonymous then  u ++ i   -- ++ "@" ++ w
+--                          else  u       -- ++ "@" ++ w
 
 instance Show Token where
      show t = "Token " ++ key t
@@ -141,8 +142,9 @@      readsPrec _ str= error $ "parse error in Token read from: "++ str
 
 instance Serializable Token  where
-  serialize  = pack . show
-  deserialize= read . unpack
+  serialize  = B.pack . show
+  deserialize= read . B.unpack
+  setPersist =   \_ -> Just filePersist
 
 iorefqmap= unsafePerformIO  . newMVar $ M.empty
 
@@ -171,7 +173,7 @@ 
 type Flow= (Token -> Workflow IO ())
 
-data HttpData = HttpData Params [Cookie] ByteString | Error  ByteString deriving (Typeable, Show)
+data HttpData = HttpData [(SB.ByteString,SB.ByteString)]  [Cookie] ByteString | Error  ByteString deriving (Typeable, Show)
 
 
 --instance ToHttpData HttpData where
@@ -181,7 +183,7 @@ -- toHttpData bs= HttpData [] [] bs
 
 instance Monoid HttpData where
- mempty= HttpData [] [] empty
+ mempty= HttpData [] [] B.empty
  mappend (HttpData h c s) (HttpData h' c' s')= HttpData (h++h') (c++ c') $ mappend s s'
 
 -- | List of (wfname, workflow) pairs, to be scheduled depending on the message's pwfname
@@ -214,8 +216,7 @@     pind (Req x)= pind x   
     getParams (Req x)= getParams  x
 --    getServer (Req x)= getServer  x
---    getPath (Req x)= getPath  x
---    getPort (Req x)= getPort  x
+--    getPort (Req x)= getPort  x 
 
 data Resp  = Fragm HttpData
            | EndFragm HttpData
@@ -285,7 +286,7 @@       
 
 
--- | executes a simple monadic computation that receive the params and return a response
+-- | executes a simple request-response computation that receive the params and return a response
 --
 -- It is used with `addMessageFlows`
 --
@@ -324,6 +325,8 @@ -- | return the list of the scheduler
 getMessageFlows = readMVar _messageFlows
 
+delMessageFlow wfname= modifyMVar_ _messageFlows (\ms -> return $ M.delete wfname ms)
+
 --class ToHttpData a  where
 --    toHttpData :: a -> HttpData  
 
@@ -369,9 +372,9 @@ msgScheduler x  = do
   token <- getToken x
   let wfname = takeWhile (/='/') $ pwfname x
-  sendToMF token x
-  th <- startMessageFlow wfname token
-  r  <- recFromMF token                          -- !> let HttpData _ _ r1=r in unpack r1 
+  sendToMF token x                                 
+  th <- startMessageFlow wfname token     
+  r  <- recFromMF token                            --  !> let HttpData _ _ r1=r in unpack r1 
   return (r,th)
   where
   --start the flow if not started yet
@@ -394,23 +397,23 @@              
           Left (WFException e)-> do
               showError wfname token e
+              moveState wfname token token{tind= "error/"++tuser token}
               deleteTokenInList token                       -- !> "DELETETOKEN"
               
+              
           Right _ ->  delMsgHistory token >> return ()      -- !> ("finished " ++ wfname)
 
 
 
 showError wfname token@Token{..} e= do
-               let user= key token
                t <- return . calendarTimeToString =<< toCalendarTime =<< getClockTime
                let msg= errorMessage t e tuser (Prelude.concat $ intersperse "/" tpath) tenv
 
                logError  msg
---               moveState wfname token token{tuser= "error/"++tuser token}
                fresp <- getNotFoundResponse
                admin <- getAdminName
-               sendFlush token . Error $ fresp (user== admin)  $  Prelude.concat[ "<br/>"++ s | s <- lines msg]
-
+--               sendFlush token . Error $ fresp (tuser== admin)  $  Prelude.concat[ "<br/>"++ s | s <- lines msg]
+               sendFlush token . Error $ fresp True  $  Prelude.concat[ "<br/>"++ s | s <- lines msg]
 
 errorMessage t e u path env=
      "\n---------------------ERROR-------------------------\
@@ -418,7 +421,7 @@      e++
      "\n\nUSER= " ++ u ++
      "\n\nPATH= " ++ path ++
-     "\n\nREQUEST:\n\n"++
+     "\n\nREQUEST:\n\n" ++
      show env
 
 line= unsafePerformIO $ newMVar ()
@@ -440,10 +443,18 @@ 
 ------ USER MANAGEMENT -------
 
---instance Serialize a => Serializable a where
---  serialize=  runW . showp
---  deserialize=   runR readp
+data Auth = Auth{
+   uregister ::  UserStr -> PasswdStr -> (IO (Maybe String)),
+   uvalidate ::  UserStr -> PasswdStr -> (IO (Maybe String))}
 
+_authMethod= unsafePerformIO $ newIORef $ Auth tCacheRegister tCacheValidate
+
+-- | set an authentication method
+setAuthMethod auth= writeIORef _authMethod auth
+
+getAuthMethod = readIORef _authMethod
+
+
 data User= User
             { userName :: String
             , upassword :: String
@@ -460,39 +471,75 @@ -- | Return  the key name of an user
 keyUserName n= userPrefix++n
 
-instance Serialize a => Serializable a where
-  serialize= runW . showp
-  deserialize= runR  readp
-
+instance  Serializable User where
+  serialize=  B.pack . show
+  deserialize=   read . B.unpack
+  setPersist =   \_ -> Just filePersist
+  
 -- | Register an user/password 
-userRegister :: MonadIO m => String -> String  -> m (DBRef User)
-userRegister user password  = liftIO . atomically $ newDBRef $ User user password
+tCacheRegister ::  String -> String  -> IO (Maybe String)
+tCacheRegister user password  =  atomically $ do
+     withSTMResources [newuser]  doit
+     where
+     newuser= User user password
+     doit [Just (User _ _)] = resources{toReturn= Just "user already exist"}
+     doit [Nothing] = resources{toAdd= [newuser],toReturn= Nothing}
 
+tCacheValidate ::  UserStr -> PasswdStr -> IO (Maybe String)
+tCacheValidate  u p =
+    let user= eUser{userName=u}
+    in  atomically
+     $ withSTMResources [user]
+     $ \ mu -> case mu of
+         [Nothing] -> resources{toReturn= err }
+         [Just (User _ pass )] -> resources{toReturn= 
+               case pass==p  of
+                 True -> Nothing
+                 False -> err
+               }
 
+     where
+     err= Just  "Username or password invalid"
+
+userRegister u p= liftIO $ do
+   Auth reg _ <- getAuthMethod :: IO Auth
+   reg u p
+
+
+
+
 data Config = Config UserStr deriving (Read, Show, Typeable)
 
 keyConfig= "mflow.config"
 instance Indexable Config where key _= keyConfig
 rconf= getDBRef keyConfig
 
+instance  Serializable Config where
+  serialize=  B.pack . show
+  deserialize=   read . B.unpack
+  setPersist =   \_ -> Just filePersist
 
 type UserStr= String
 type PasswdStr= String
 
 setAdminUser :: MonadIO m => UserStr -> PasswdStr -> m ()
-setAdminUser user password= liftIO $  atomically $ do
-  newDBRef $ User user password
-  writeDBRef rconf $ Config user
+setAdminUser user password= liftIO $  do
+  userRegister user password
+  atomically $ writeDBRef rconf $ Config user
 
 getAdminName :: MonadIO m => m UserStr
-getAdminName= liftIO $ atomically ( readDBRef rconf `onNothing` error "admin user not set" ) >>= \(Config u) -> return u
+getAdminName=  liftIO  $ do
+     cu <- atomically $ readDBRef rconf
+     case cu of
+      Nothing -> setAdminUser "admin" "admin" >> getAdminName
+      Just (Config u) -> return u
 
 
 --------------- ERROR RESPONSES --------
 
 defNotFoundResponse isAdmin msg= fresp $
      case isAdmin of
-           True -> pack msg
+           True -> B.pack msg
            _    -> "The administrator has been notified"
   where
   fresp msg=
@@ -529,11 +576,11 @@ -- | Writes a XML tag in a ByteString. It is the most basic form of formatting. For
 -- more sophisticated formatting , use "MFlow.Forms.XHtml" or "MFlow.Forms.HSP".
 btag :: String -> Attribs  -> ByteString -> ByteString
-btag t rs v= "<" `append` pt `append` attrs rs `append` ">" `append` v `append`"</"`append` pt `append` ">"
+btag t rs v= "<" <> pt <> attrs rs <> ">" <> v <> "</" <> pt <> ">"
  where
- pt= pack t
+ pt= B.pack t
  attrs []= B.empty
- attrs rs=  pack $ concatMap(\(n,v) -> (' ' :   n) ++ "=\"" ++ v++ "\"" ) rs
+ attrs rs=  B.pack $ concatMap(\(n,v) -> (' ' :   n) ++ "=\"" ++ v++ "\"" ) rs
 
 -- |
 -- > bhtml ats v= btag "html" ats v
@@ -548,7 +595,7 @@ 
 addAttrs :: ByteString -> Attribs -> ByteString
 addAttrs (Chunk "<" (Chunk tag rest)) rs=
-   Chunk "<"(Chunk tag  (pack $ concatMap(\(n,v) -> (' ' :   n) ++ "=" ++  v ) rs))  <> rest
+   Chunk "<"(Chunk tag  (B.pack $ concatMap(\(n,v) -> (' ' :   n) ++ "=" ++  v ) rs))  <> rest
 
 addAttrs other _ = error  $ "addAttrs: byteString is not a tag: " ++ show other
 
@@ -594,6 +641,10 @@ instance Indexable NFlow where
   key _= "Flow"
 
+instance  Serializable NFlow where
+  serialize=  B.pack . show
+  deserialize=   read . B.unpack
+  setPersist =   \_ -> Just filePersist
 
 rflow= getDBRef . key $ NFlow undefined
 
@@ -602,7 +653,7 @@         atomically $ do 
                     NFlow n <- readDBRef rflow `onNothing` return (NFlow 0)
                     writeDBRef rflow . NFlow $ n+1
-                    return . show $ t + n
+                    return . SB.pack . show $ t + n
 
 
 mimeTable=[
src/MFlow/Cookies.hs view
@@ -1,7 +1,7 @@ {-# OPTIONS -XScopedTypeVariables  -XOverloadedStrings #-}  module MFlow.Cookies-(Cookie,contentHtml,urlDecode,cookieuser,cookieHeaders,getCookies)+(Cookie,contentHtml,cookieuser,cookieHeaders,getCookies) where import Control.Monad(MonadPlus(..), guard, replicateM_, when) import Data.Char@@ -14,29 +14,31 @@ import Data.Monoid import Text.Parsec import Control.Monad.Identity+import Data.ByteString.Char8 as B  --import Debug.Trace --(!>)= flip trace +contentHtml :: (ByteString, ByteString) contentHtml= ("Content-Type", "text/html") -type Cookie=  (String,String,String,Maybe String)+type Cookie=  (B.ByteString,B.ByteString,B.ByteString,Maybe B.ByteString)  cookieuser :: String cookieuser= "cookieuser" ---getCookies :: Params -> Params+ getCookies httpreq=      case  lookup "Cookie" $ httpreq of-             Just str  -> splitCookies str+             Just str  -> splitCookies str :: [(B.ByteString, B.ByteString)]              Nothing   -> []  cookieHeaders cs =  Prelude.map (\c-> ( "Set-Cookie", showCookie c)) cs -showCookie ::  Cookie -> String-showCookie (n,v,p,me) = n <> "="  <> v  <>-                       ";path="  <> p  <>-                        showMaxAge me+showCookie ::  Cookie -> B.ByteString+showCookie (n,v,p,me) =  n <> "="  <>  v  <>+                       ";path="  <>  p  <>+                        showMaxAge  me      where     showMaxAge Nothing =  ""
@@ -60,17 +62,17 @@  splitCookies cookies  = f cookies []  
     where
-    f s r | null s  = r
+    f s r | B.null s  = r
     f xs0 r =
       let-          xs   = dropWhile (==' ') xs0
-          name = takeWhile (/='=') xs
-          xs1  = dropWhile (/='=') xs
-          xs2  = dropWhile (=='=') xs1
-          val  = takeWhile (/=';') xs2
-          xs3  = dropWhile (/=';') xs2
-          xs4  = dropWhile (==';') xs3
-          xs5  = dropWhile (==' ') xs4
+          xs   = B.dropWhile (==' ') xs0
+          name = B.takeWhile (/='=') xs
+          xs1  = B.dropWhile (/='=') xs
+          xs2  = B.dropWhile (=='=') xs1
+          val  = B.takeWhile (/=';') xs2
+          xs3  = B.dropWhile (/=';') xs2
+          xs4  = B.dropWhile (==';') xs3
+          xs5  = B.dropWhile (==' ') xs4
       in  f xs5 ((name,val):r)  -----------------------------@@ -207,7 +209,7 @@ --         toInt d                = error ("hex2int: illegal hex digit " ++ [d])

  --urlDecode :: String -> [([(String, String)],String)]-urlDecode str= case parse readEnv "" str of  -- let Parser p= readEnv in  p str-                     Left err  -> error $ "urlDecode: decode  error: " ++ show err-                     Right r  ->   r+--urlDecode str= case parse readEnv "" str of  -- let Parser p= readEnv in  p str+--                     Left err  -> error $ "urlDecode: decode  error: " ++ show err+--                     Right r  ->   r --               !> ("decode="++str)
src/MFlow/Forms.hs view
@@ -111,15 +111,19 @@ be combined as such.  * NEW IN THIS RELEASE+[@Runtime templates@]  'template', 'edTemplate', 'witerate' and 'dField' permit the edition of+the widget content at runtime, and the management of placeholders with input fields and data fields+within the template with no navigation in the client, little bandwidth usage and little server load. Enven less+than using 'autoRefresh'. +* IN PREVIOUS RELEASES -{@Auto-Refresh@] Using `autoRefresh`, Dynamic widgets can refresh themselves with new information without forcing a refresh of the whole page+{@AutoRefresh@] Using `autoRefresh`, Dynamic widgets can refresh themselves with new information without forcing a refresh of the whole page  [@Push@]  With `push` a widget can push new content to the browser when something in the server happens  [@Error traces@] using the monadloc package, now each runtime error (in a monadic statement) has a complete execution trace. -* IN PREVIOUS RELEASES  [@RESTful URLs@] Now each page is directly reachable by means of a intuitive, RESTful url, whose path is composed by the sucession of links clicked to reach such page and such point in the procedure. Just what you would expect.@@ -200,11 +204,11 @@ FlowM, View(..), FormElm(..), FormInput(..) 
 -- * Users 
-,userRegister, userValidate, isLogged, setAdminUser, getAdminName
-,getCurrentUser,getUserSimple, getUser, userFormLine, userLogin,logout, userWidget,getLang, login,+, Auth(..), userRegister, setAuthMethod, userValidate, isLogged, setAdminUser, getAdminName
+,getCurrentUser,getUserSimple, getUser, userFormLine, userLogin,logout, userWidget, login, userName,
 -- * User interaction 
-ask, page, askt, clearEnv, wstateless, transfer, pageFlow, 
+ask, page, askt, clearEnv, wstateless, pageFlow,  
 -- * formLets 
 -- | They usually produce the HTML form elements (depending on the FormInput instance used) -- It is possible to modify their attributes with the `<!` operator.@@ -214,9 +218,9 @@ getString,getInt,getInteger, getTextBox 
 ,getMultilineText,getBool,getSelect, setOption,setSelectedOption, getPassword, getRadio, setRadio, setRadioActive, wlabel, getCheckBoxes, genCheckBoxes, setCheckBox,-submitButton,resetButton, whidden, wlink, returning, wform, firstOf, manyOf, wraw, wrender, notValid+submitButton,resetButton, whidden, wlink, getRestParam, returning, wform, firstOf, manyOf, wraw, wrender, notValid -- * FormLet modifiers-,validate, noWidget, waction, wcallback, wmodify,+,validate, noWidget, waction, wcallback, clear, wmodify,  -- * Caching widgets cachedWidget, wcached, wfreeze,@@ -245,10 +249,10 @@ ,flatten, normalize 
 -- * Running the flow monad
-,runFlow, transientNav,runFlowOnce,runFlowIn+,runFlow, transientNav, runFlowOnce, runFlowIn ,runFlowConf,MFlow.Forms.Internals.step -- * controlling backtracking-,goingBack,returnIfForward, breturn, preventGoingBack+,goingBack,returnIfForward, breturn, preventGoingBack, retry 
 -- * Setting parameters
 ,setHeader@@ -270,7 +274,9 @@ ,WebRequirement(..) ,requires -- * Utility+,getLang ,genNewId+,getNextId ,changeMonad ,FailBack ,fromFailBack@@ -284,9 +290,11 @@ import Data.TCache import Data.TCache.Memoization
 import MFlow-import MFlow.Forms.Internals
+import MFlow.Forms.Internals 
 import MFlow.Cookies-import Data.ByteString.Lazy.Char8 as B(ByteString,cons,pack,unpack,append,empty,fromChunks) 
+import Data.ByteString.Lazy.Char8 as B(ByteString,cons,pack,unpack,append,empty,fromChunks)+import qualified Data.Text as T+import Data.Text.Encoding
 import Data.List --import qualified Data.CaseInsensitive as CI
 import Data.Typeable
@@ -316,7 +324,7 @@      -> (a -> WState view m (Maybe view))      -> View view m a
 validate  formt val= View $ do
-   FormElm form mx <- (runView  formt)  
+   FormElm form mx <- runView  formt
    case mx of
     Just x -> do
       me <- val x@@ -414,15 +422,6 @@           ( isValidated mn  && v== fromValidated mn) (Just  "this.form.submit()")]           (fmap Radio $ valToMaybe mn) -valToMaybe (Validated x)= Just x-valToMaybe _= Nothing--isValidated (Validated x)= True-isValidated _= False--fromValidated (Validated x)= x-fromValidated NoParam= error $ "fromValidated : NoParam"-fromValidated (NotValidated s err)= error $ "fromValidated: NotValidated "++ s 
 -- | Implement a radio button -- the parameter is the name of the radio group@@ -567,25 +566,26 @@        
  -getCurrentName :: MonadState (MFlowState view) m =>  m String-getCurrentName= do-     st <- get-     let parm = mfSequence st-     return $ "p"++show parm+--getCurrentName :: MonadState (MFlowState view) m =>  m String+--getCurrentName= do+--     st <- get+--     let parm = mfSequence st+--     return $ "p"++show parm   -- | Display a multiline text box and return its content-getMultilineText :: (FormInput view,
-      Monad m) =>
-      String ->  View view m String
+getMultilineText :: (FormInput view
+                 ,  Monad m)
+                   => T.Text+                 ->  View view m T.Text
 getMultilineText nvalue = View $ do
     tolook <- genNewId     env <- gets mfEnv     r <- getParam1 tolook env     case r of-       Validated x        -> return $ FormElm [ftextarea tolook  (show x) ] $ Just x-       NotValidated s err -> return $ FormElm [ftextarea tolook  s ] $ Nothing-       NoParam            -> return $ FormElm [ftextarea tolook  nvalue ] $ Nothing
+       Validated x        -> return $ FormElm [ftextarea tolook  x] $ Just x+       NotValidated s err -> return $ FormElm [ftextarea tolook  (T.pack s)]  Nothing+       NoParam            -> return $ FormElm [ftextarea tolook  nvalue]  Nothing
 
       
 --instance  (MonadIO m, Functor m, FormInput view) => FormLet Bool m view where
@@ -820,6 +820,12 @@      back <- goingBack      if back then noWidget else return x +-- | forces backtracking if the widget validates, because a previous page handle this widget response+-- . This is useful for recurrent cached widgets that are present in multiple pages. For example+-- in the case of menus or common options. The active elements of this widget must be cached with no timeout.+retry :: Monad m => View v m a -> View v m ()+retry w=  w >> modify (\st -> st{inSync=False})+ -- | It creates a widget for user login\/registering. If a user name is specified -- in the first parameter, it is forced to login\/password as this specific user. -- If this user was already logged, the widget return the user without asking.@@ -868,31 +874,32 @@   login uname= do--- st <- get--- let t = mfToken st---     u = tuser t--- if u == uname then return () else do---     let t'= t{tuser= uname}---     moveState (twfname t) t t'---     put st{mfToken= t'}---     liftIO $ deleteTokenInList t---     liftIO $ addTokenToList t'-     setCookie cookieuser   uname "/"  (Just $ 365*24*60*60) 
---+    back <- goingBack+    if back then return () else do+     st <- get+     let t = mfToken st+         u = tuser t+     if u == uname then return () else do+         let t'= t{tuser= uname}+    --     moveState (twfname t) t t'+         put st{mfToken= t'}+--         liftIO $ deleteTokenInList t+         liftIO $ addTokenToList t'+         setCookie cookieuser   uname "/"  (Just $ 365*24*60*60)  -- | logout. The user is reset to the `anonymous` user logout :: (MonadIO m, MonadState (MFlowState view) m) => m ()
 logout= do---     st <- get---     let t = mfToken st---         t'= t{tuser= anonymous}---     if tuser t == anonymous then return () else do+    back <- goingBack+    if back then return () else do+     st <- get+     let t = mfToken st+         t'= t{tuser= anonymous}+     if tuser t == anonymous then return () else do --         moveState (twfname t) t t'---         put st{mfToken= t'}+         put st{mfToken= t'} --         liftIO $ deleteTokenInList t---         liftIO $ addTokenToList t'+         liftIO $ addTokenToList t'          setCookie cookieuser   anonymous "/" (Just $ -1000) 
 -- | If not logged, perform login. otherwise return the user@@ -918,20 +925,9 @@ -- | Authentication against `userRegister`ed users.
 -- to be used with `validate`
 userValidate :: (FormInput view,MonadIO m) => (UserStr,PasswdStr) -> m (Maybe view)
-userValidate (u,p) =
-    let user= eUser{userName=u}
-    in liftIO $ atomically
-     $ withSTMResources [user]
-     $ \ mu -> case mu of
-         [Nothing] -> resources{toReturn= err }
-         [Just (User _ pass )] -> resources{toReturn= 
-               case pass==p  of
-                 True -> Nothing
-                 False -> err
-               }
-
-     where
-     err= Just . fromStr $ "Username or password invalid"
+userValidate (u,p) = liftIO $  do+   Auth _ val <- getAuthMethod+   val u p >>= return .  fmap  fromStr
 
 -- | Join two widgets in the same page
 -- the resulting widget, when `ask`ed with it, return a 2 tuple of their validation results
@@ -1017,16 +1013,16 @@ -- -- 'ask' also synchronizes the execution of the flow with the user page navigation by --- * Backtracking (invoking previous 'ask' staement in the flow) when detecting mismatches between get and post parameters and what is expected by the widgets
+-- * Backtracking (invoking previous 'ask' staement in the flow) when detecting mismatches between+-- get and post parameters and what is expected by the widgets
 -- until a total or partial match is found. ----- * Advancing in the flow by mathing a single requests with one or more sucessive ask statements+-- * Advancing in the flow by matching a single requests with one or more sucessive ask statements -- -- Backtracking and advancing can occur in a single request, so the flow in any state can reach any--- other state in the flow if the request satisfy the parameters required.-ask-  :: (FormInput view) =>-      View view IO a -> FlowM view IO a
+-- other state in the flow if the request has the required parameters.+ask :: (FormInput view) =>+       View view IO a -> FlowM view IO a
 ask w =  do  st1 <- get  if not . null $ mfTrace st1 then fail "" else do@@ -1043,7 +1039,7 @@   -- END AJAX     _ ->   do-     let st= st1{needForm= False, inSync= False, mfRequirements= [],linkMatched=False} 
+     let st= st1{needForm= False, inSync= False, mfRequirements= [], linkMatched= False} 
      put st       FormElm forms mx <- FlowM . lift  $ runView  w@@ -1051,18 +1047,16 @@      st' <- get      if notSyncInAction st' then put st'{notSyncInAction=False}>> ask w -       else       case mx  of
        Just x -> do-         put st'{newAsk= True  , mfEnv=[]+         put st'{newAsk= True, mfEnv=[]                 ,mfPageIndex=Nothing                 ,mfPIndex= case isJust $ mfPageIndex st' of                             True -> length (mfPath st') -1                             False -> mfPIndex st'          }--         breturn x                                       -- !> "RETURN"+         breturn x                                        -- !> "RETURN" 
        Nothing ->          if  not (inSync st')  && not (newAsk st')@@ -1078,20 +1072,19 @@           else if mfAutorefresh st' then do                      resetState st st'                      FlowM (lift  nextMessage)-                     ask w                              --  !> "EN AUTOREFRESH"+                     ask w                                -- !> "EN AUTOREFRESH"           else do              reqs <-  FlowM $ lift installAllRequirements     -- !> "REPEAT"              let header= mfHeader st'                  t= mfToken st'              cont <- case (needForm st') of                       True ->  do-                               frm <- formPrefix (mfPIndex st') (twfname t ) st' forms False-                               return . header $  reqs <> frm+                              frm <- formPrefix (mfPIndex st') (twfname t ) st' forms False+                              return . header $  reqs <> frm                       _    ->  return . header $  reqs <> mconcat  forms               let HttpData ctype c s= toHttpData cont 
-             liftIO . sendFlush t $ HttpData (ctype++mfHttpHeaders st') (mfCookies st' ++ c) s-+             liftIO . sendFlush t $ HttpData (ctype ++ mfHttpHeaders st') (mfCookies st' ++ c) s               resetState st st'              
 @@ -1105,7 +1098,8 @@                    ,mfToken= mfToken st'                    ,mfPageIndex= mfPageIndex st'                    ,mfAjax= mfAjax st'-                   ,mfSeqCache= mfSeqCache st' }+                   ,mfSeqCache= mfSeqCache st'+                   ,mfData= mfData st' }   -- | A synonym of ask.@@ -1115,16 +1109,7 @@ page   :: (FormInput view) =>       View view IO a -> FlowM view IO a-page= ask-----
-comparePaths _ n [] xs=  n-comparePaths  o n _ [] = o-comparePaths  o n (v:path) (v': npath) | v== v' = comparePaths o (n+1)path npath-                                        | otherwise= n+page= ask
 
 nextMessage :: MonadIO m => WState view m ()
 nextMessage= do
@@ -1137,20 +1122,30 @@          env=   updateParams inPageFlow (mfEnv st) req          npath= pwfPath msg          path=  mfPath st-         inPageFlow= isJust $ mfPageIndex st  
+         inPageFlow= case (comparep,mfPageIndex st) of+                    (n, Just n') -> if n < n' then Nothing   else Just n'+                    _ -> Nothing+         comparep= comparePaths (mfPIndex st) 1 (tail path) (tail npath)
      put st{ mfPath= npath-           , mfPIndex= case mfPageIndex st of+           , mfPIndex= case inPageFlow of                          Just n -> n-                         Nothing ->-                             comparePaths (mfPIndex st) 1 (tail path) (tail npath)---           , mfPageIndex= Nothing+                         Nothing -> comparep++           , mfPageIndex= inPageFlow+           , mfLinks= if isNothing inPageFlow then M.empty else mfLinks st            , mfEnv= env }                        -- !> show req        where-     updateParams :: Bool -> Params -> Params -> Params-     updateParams False _ req= req-     updateParams True env req=++     comparePaths _ n [] xs=  n+     comparePaths  o n _ [] = o+     comparePaths  o n (v:path) (v': npath) | v== v' = comparePaths o (n+1)path npath+                                        | otherwise= n++     updateParams :: Maybe Int -> Params -> Params -> Params+     updateParams Nothing _ req= req+     updateParams (Just _) env req=         let params= takeWhile isparam env             fs= fst $ head req             parms= (case findIndex (\p -> fst p == fs)  params of@@ -1172,14 +1167,14 @@ -- higuer level form of the latter 
 wstateless   :: (Typeable view,  FormInput view) =>-     View view IO a -> Flow-wstateless w = transient $ runFlow loop-  where-  loop= do-      ask w-      env <- get-      put $ env{ mfSequence= 0} 
-      loop+     View view IO () -> Flow+wstateless w = transient . runFlow . ask $ w **> noWidget -- loop+--  where+--  loop= do+--      ask w+--      env <- get+--      put $ env{ mfSequence= 0} 
+--      loop   ---- This version writes a log with all the values returned by ask@@ -1196,22 +1191,14 @@ --         return r
 --      loop 
--- | transfer control to another flow.-transfer :: MonadIO m => String -> FlowM v m ()-transfer flowname =do-         t <- gets mfToken-         let t'= t{twfname= flowname}-         liftIO  $ do-             (r,_) <- msgScheduler t'-             sendFlush t r + 
 -- | Wrap a widget with form element within a form-action element. -- Usually this is not necessary since this wrapping is done automatically by the @Wiew@ monad, unless -- there are more than one form in the page.
 wform ::  (Monad m, FormInput view)
           => View view m b -> View view m b 
-
 wform x = View $ do
      FormElm form mr <- (runView $   x )      st <- get@@ -1243,7 +1230,7 @@ -- >          ++> getInt (Just 0) <! [("id","text1"),("onclick", ajaxc elemval)] ajax :: (MonadIO m)      => (String ->  View v m ByteString)  -- ^ user defined procedure, executed in the server.Receives the value of the javascript expression and must return another javascript expression that will be executed in the web browser-     ->  View v m (String -> String)      -- ^ returns a function that accept a javascript expression and return a javascript event handler expression that invoques the ajax server procedure+     ->  View v m (String -> String)      -- ^ returns a function that accept a javascript expression and return a javascript event handler expression that invokes the ajax server procedure ajax  f =  do      requires[JScript ajaxScript]      t <- gets mfToken@@ -1299,7 +1286,24 @@ --                       True  -> s{mfSeqCache= mfSeqCache s -1} --                       False -> s{mfSequence= mfSequence s -1}    ftag "label" str `attrs` [("for",id)] ++> w <! [("id",id)]-    
++getRestParam :: (Read a, Typeable a,Monad m,Functor m, FormInput v) => FlowM v m (Maybe a)+getRestParam= do+   st <- get+   let lpath = mfPath st+   let index' = mfPIndex st+                 + if linkMatched st then -1 else 0+                 + if Just (mfPIndex st)== mfPageIndex st then 1 else 0+       index = if index'== 0 then 1 else index'++   case  index < length lpath  of+             True -> do+                  modify $ \s -> s{inSync= True+                                 ,linkMatched= True, mfPIndex= index+1 }  -- !> (name ++ "<-" ++show index++ " MATCHED")+                  fmap valToMaybe $ readParam $ lpath !! index+             False ->  return Nothing++   
 -- | Creates a link wiget. A link can be composed with other widget elements,
 wlink :: (Typeable a, Show a, MonadIO m,  FormInput view) 
          => a -> view -> View  view m a
@@ -1325,7 +1329,7 @@           toSend = flink path v  -      r <- if linkMatched st then return Nothing+      r <- if linkMatched st then return Nothing -- only a link match per page or monadic sentence in page            else            if isJust $ mfPageIndex st -- !> (show $ mfPageIndex st)              then@@ -1338,7 +1342,7 @@                      modify $ \st -> st{ inSync= True,linkMatched= True                                       , mfPIndex= index + 1                                       , mfLinks= M.insert name (n-1) $ mfLinks st}-                                            -- !> (name ++" "++ show n ++ " Match")+                                           -- !> (name ++" "++ show n ++ " Match")                      return $ Just x                  Nothing -> return Nothing  -- !> (name ++ " 0 Fail")              else@@ -1347,21 +1351,22 @@                   modify $ \s -> s{inSync= True                                  ,linkMatched= True, mfPIndex= index+1 }  -- !> (name ++ "<-" ++show index++ " MATCHED")                   return $ Just x-             False ->  return Nothing                                        -- !> (name++"<-" ++show index++ " "++(if index < length lpath then lpath !! index else ""))+             False ->  return Nothing                                      -- !> ( "NOT MATCHED "++name++"<-" ++show index++ " "++(if index < length lpath then lpath !! index else ""))        return $ FormElm [toSend] r
    --- | When some user interface int return some response to the server, but it is not produced by--- a form or a link, but for example by an script, @returning@ notify the type checker.+-- | When some user interface return some response to the server, but it is not produced by+-- a form or a link, but for example by an script, @returning@  convert this code into a+-- widget. -- -- At runtime the parameter is read from the environment and validated. -- -- . The parameter is the visualization code, that accept a serialization function that generate -- the server invocation string, used by the visualization to return the value by means--- of a link or a @window.location@ statement in javasCript
+-- of an script, usually.
 returning :: (Typeable a, Read a, Show a,Monad m, FormInput view) 
          => ((a->String) ->view) -> View view m a returning expr=View $ do@@ -1402,31 +1407,27 @@ manyOf :: (FormInput view, MonadIO m, Functor m)=> [View view m a]  -> View view m [a]
 manyOf xs= whidden () *> (View $ do 
       forms <- mapM runView  xs
-      let vs  = concatMap (\(FormElm v _) ->  [mconcat v]) forms-          
-          res1= catMaybes $ map (\(FormElm _ r) -> r) forms--       
-      return $ FormElm  vs $  Just res1)-+      let vs  = concatMap (\(FormElm v _) ->  [mconcat v]) forms
+          res1= catMaybes $ map (\(FormElm _ r) -> r) forms
+      return . FormElm vs $  Just res1) -(>:>) :: (Monad m)=> View v m a -> View v m [a]  -> View v m [a]-(>:>) w ws= View $ do+(>:>) :: Monad m => View v m a -> View v m [a]  -> View v m [a]+(>:>) w ws = View $ do     FormElm fs mxs <- runView $  ws     FormElm f1 mx  <- runView w     return $ FormElm (f1++ fs)          $ case( mx,mxs) of              (Just x, Just xs) -> Just $ x:xs-             (Nothing, mxs) -> mxs-             (Just x, _) -> Just [x]+             (Nothing, mxs)    -> mxs+             (Just x, _)       -> Just [x]  -- | Intersperse a widget in a list of widgets. the results is a 2-tuple of both types. -- -- it has a infix priority @infixr 5@ (|*>) :: (MonadIO m, Functor m,Monoid view)             => View view m r-            -> [View view m r']-            -> View view m (Maybe r,Maybe r')+           -> [View view m r']+           -> View view m (Maybe r,Maybe r') (|*>) x xs= View $ do   FormElm fxs rxs <-  runView $ firstOf  xs   FormElm fx rx   <- runView $  x@@ -1558,7 +1559,7 @@     inred = btag "b" [("style", "color:red")]     finput n t v f c= btag "input"  ([("type", t) ,("name", n),("value",  v)] ++ if f then [("checked","true")]  else []                               ++ case c of Just s ->[( "onclick", s)]; _ -> [] ) ""-    ftextarea name text= btag "textarea"  [("name", name)]   $ pack text+    ftextarea name text= btag "textarea"  [("name", name)]   $ fromChunks [encodeUtf8 text]      fselect name   options=  btag "select" [("name", name)]   options @@ -1577,11 +1578,10 @@  ------ page Flows ---- --- | prepares the state for a page flow. A page flow is a dynamic page which changes his rendering by executing--- a monadic computation with widgets that are validated depending on the user responses.--- It initiates the creation of a well known sequence of identifiers for the formlets and also--- keep the state of the previous form submissions within the page.--- If the computation has branches   @if@ @case@ etc, each branch must have its pageFlow with a distinct identifier+-- | prepares the state for a page flow.+-- It add a prefix to every form element or link identifier for the formlets and also+-- keep the state of the links clicked and form imput entered within the widget.+-- If the computation within the widget has branches  @if@ @case@ etc, each branch must have its pageFlow with a distinct identifier -- -- See "http://haskell-web.blogspot.com.es/2013/06/the-promising-land-of-monadic-formlets.html" pageFlow
src/MFlow/Forms/Internals.hs view
@@ -20,7 +20,7 @@              -XGeneralizedNewtypeDeriving
              -XFlexibleContexts
              -XOverlappingInstances
-             -XRecordWildCards+             -XRecordWildCards
              -XTemplateHaskell
 #-}
 
@@ -31,7 +31,8 @@ import Data.Monoid
 import Control.Monad.Trans
 import Control.Monad.State
-import Data.ByteString.Lazy.Char8 as B(ByteString,cons,pack,unpack,append,empty,fromChunks)
+import qualified Data.ByteString.Lazy.Char8 as B
+import qualified Data.ByteString.Char8 as SB
 import Data.Typeable
 import Data.RefSerialize hiding((<|>))
 import Data.TCache
@@ -45,45 +46,46 @@ import Control.Monad.Identity
 import Data.List
 import System.IO.Unsafe
-import Control.Concurrent.MVar-import Control.Workflow(WFErrors(Timeout))
+import Control.Concurrent.MVar
+import qualified Data.Text as T
+
 --
 ---- for traces
-----import Control.Exception as CE(catch,SomeException,AsyncException,throw,fromException)-import Control.Concurrent-import Control.Monad.Loc
 --
---import Debug.Trace
---(!>) =    flip trace
 
+import Control.Exception as CE
+import Control.Concurrent
+import Control.Monad.Loc
 
+import Debug.Trace
+(!>) = flip trace
+
+
 data FailBack a = BackPoint a | NoBack a | GoBack   deriving (Show,Typeable)
 
 
 instance (Serialize a) => Serialize (FailBack a ) where
-   showp (BackPoint x)= insertString (pack iCanFailBack) >> showp x
-   showp (NoBack x)= insertString (pack noFailBack) >> showp x
-   showp GoBack = insertString (pack repeatPlease)
+   showp (BackPoint x)= insertString (B.pack iCanFailBack) >> showp x
+   showp (NoBack x)   = insertString (B.pack noFailBack) >> showp x
+   showp GoBack       = insertString (B.pack repeatPlease)
 
    readp = choice [icanFailBackp,repeatPleasep,noFailBackp]
     where
-    noFailBackp   = {-# SCC "deserialNoBack" #-} symbol noFailBack >> readp >>= return . NoBack
-    icanFailBackp = {-# SCC "deserialBackPoint" #-} symbol iCanFailBack >> readp >>= return . BackPoint
-    repeatPleasep = {-# SCC "deserialbackPlease" #-}  symbol repeatPlease  >> return  GoBack
+    noFailBackp   = symbol noFailBack >> readp >>= return . NoBack      
+    icanFailBackp = symbol iCanFailBack >> readp >>= return . BackPoint 
+    repeatPleasep = symbol repeatPlease  >> return  GoBack          
 
 iCanFailBack= "B"
 repeatPlease= "G"
 noFailBack= "N"
 
 newtype Sup m a = Sup { runSup :: m (FailBack a ) }
-+
 class MonadState s m => Supervise s m where
-   supBack     :: s -> m ()-   supBack = const $ return ()+   supBack     :: s -> m ()
+   supBack = const $ return ()
    
-   supervise ::    m (FailBack a) -> m (FailBack a)+   supervise ::    m (FailBack a) -> m (FailBack a)
    supervise= id
 
 --instance Monad m => Supervise () m where
@@ -109,9 +111,18 @@ 
 fromFailBack (NoBack  x)   = x
 fromFailBack (BackPoint  x)= x
-
 toFailBack x= NoBack x
 
+
+-- | the FlowM monad executes the page navigation. It perform Backtracking when necessary to syncronize
+-- when the user press the back button or when the user enter an arbitrary URL. The instruction pointer
+-- is moved to the right position within the procedure to handle the request.
+--
+-- However this is transparent to the programmer, who codify in the style of a console application.
+newtype FlowM v m a= FlowM {runFlowM :: FlowMM v m a} deriving (Monad,MonadIO,Functor,MonadState(MFlowState v))
+flowM= FlowM
+--runFlowM= runView
+
 {-# NOINLINE breturn  #-}
 
 -- | Use this instead of return to return from a computation with ask statements
@@ -153,143 +164,134 @@    readp= readp >>= \x -> return $ FormElm  [] x
 
 -- | @View v m a@ is a widget (formlet)  with formatting `v`  running the monad `m` (usually `IO`) and which return a value of type `a`
------ It has 'Applicative', 'Alternative' and 'Monad' instances.------ Things to know about these instances:------   If the View expression does not validate, ask will present the page again.------ /Alternative instance/: Both alternatives are executed. The rest is as usual------ /Monad Instance/:------  The rendering of each statement is added to the previous. If you want to avoid this, use 'wcallback'------  The execution is stopped when the statement has a formlet-widget that does not validate.------  The monadic code is executed from the beginning each time the page is presented or refreshed------  use 'pageFlow' if your page has more than one monadic computation with dynamic behaviour------ use 'pageFlow' to identify each subflow branch of a conditional------  For example:------  > pageFlow "myid" $ do---  >      r <- formlet1---  >      liftIO $ ioaction1 r---  >      s <- formlet2---  >      liftIO $ ioaction2 s---  >      case s of---  >       True  -> pageFlow "idtrue" $ do ....---  >       False -> paeFlow "idfalse" $ do ...---  >      ...------  Here if  @formlet2@ do not validate, @ioaction2@ is not executed. But if @formLet1@ validates and the---  page is refreshed two times (because @formlet2@ has failed, see above),then @ioaction1@ is executed two times.-+--
+-- It has 'Applicative', 'Alternative' and 'Monad' instances.
+--
+-- Things to know about these instances:
+--
+--   If the View expression does not validate, ask will present the page again.
+--
+-- /Alternative instance/: Both alternatives are executed. The rest is as usual
+--
+-- /Monad Instance/:
+--
+--  The rendering of each statement is added to the previous. If you want to avoid this, use 'wcallback'
+--
+--  The execution is stopped when the statement has a formlet-widget that does not validate and
+-- return an invalid response (So it will present the page again if no other widget in the expression validates).
+--
+--  The monadic code is executed from the beginning each time the page is presented or refreshed
+--
+--  use 'pageFlow' if your page has more than one monadic computation with dynamic behaviour
+--
+-- use 'pageFlow' to identify each subflow branch of a conditional
+--
+--  For example:
+--
+--  > pageFlow "myid" $ do
+--  >      r <- formlet1
+--  >      liftIO $ ioaction1 r
+--  >      s <- formlet2
+--  >      liftIO $ ioaction2 s
+--  >      case s of
+--  >       True  -> pageFlow "idtrue" $ do ....
+--  >       False -> paeFlow "idfalse" $ do ...
+--  >      ...
+--
+--  Here if  @formlet2@ do not validate, @ioaction2@ is not executed. But if @formLet1@ validates and the
+--  page is refreshed two times (because @formlet2@ has failed, see above),then @ioaction1@ is executed two times.
+--  use 'cachedByKey' if you want to avoid repeated IO executions.
 newtype View v m a = View { runView :: WState v m (FormElm v a)}
- 
+
 instance  Monad m => Supervise (MFlowState v) (WState v m) where
    supBack st= do
       MFlowState{..} <- get
-      put  st{ mfEnv= mfEnv,mfToken=mfToken-                    , mfPath=mfPath,mfPIndex= mfPIndex-                    , mfData=mfData-                    , mfTrace= mfTrace-                    , inSync=False,newAsk=False}+      put st{ mfEnv= mfEnv,mfToken=mfToken
+            , mfPath=mfPath,mfPIndex= mfPIndex
+            , mfData=mfData
+            , mfTrace= mfTrace
+            , inSync=False,newAsk=False}
 
 
----instance  CMT.MonadCatchIO (FlowM v IO) where---    catch f hand = FlowM . Sup $ do---            s <- get+
+--instance  CMT.MonadCatchIO (FlowM v IO) where
+--    catch f hand = FlowM . Sup $ do
+--            s <- get
 --            (r,s') <- lift $ execMF f s  `CE.catch` \e -> execMF (hand e) s
------            put s'---            return r---            where---            execMF f s= runStateT (runSup (runFlowM f) ) s--+--
+--            put s'
+--            return r
+--            where
+--            execMF f s= runStateT (runSup (runFlowM f) ) s
 
----instance  MonadLoc (FlowM v IO) where-    withLoc loc f = FlowM . Sup $ do-       withLoc loc $ do-            s <- get-            (r,s') <- lift $ do-                       rs@(r,s') <- runStateT (runSup (runFlowM f) ) s+
+
+instance  MonadLoc (FlowM v IO) where
+    withLoc loc f = FlowM . Sup $ do
+       withLoc loc $ do
+            s <- get
+            (r,s') <- lift $ do
+                       rs@(r,s') <- runStateT (runSup (runFlowM f) ) s
                                           `CE.catch` (handler1  loc s)
-                       case mfTrace s' of-                            []    ->  return rs-                            trace ->  return(r, s'{mfTrace= loc:trace})-            put s'-            return r-+                       case mfTrace s' of
+                            []    ->  return rs
+                            trace ->  return(r, s'{mfTrace= loc:trace})
+            put s'
+            return r
+
        where
-       handler1 loc s (e :: SomeException)= do-        case CE.fromException e :: Maybe WFErrors of-           Just e  -> CE.throw e     -- !> ("TROWNF=" ++ show e)-           Nothing ->-             case CE.fromException e :: Maybe AsyncException of-                Just e -> CE.throw e -- !> ("TROWN ASYNCF=" ++ show e)-                Nothing ->-                 return (GoBack, s{mfTrace= [show e]})-----instance (Serialize a,Typeable a, FormInput v) => MonadLoc (FlowM v (Workflow IO)) a where---    withLoc loc f =  FlowM . Sup $---       withLoc loc $  do---            s <- get---            (r,s') <-  lift . WF.step $ exec1d "jkkjk" ( runStateT (runSup $ runFlowM f) s) `CMT.catch` (handler1  loc s)---            put s'---            return r---+       handler1 loc s (e :: SomeException)= do
+        case CE.fromException e :: Maybe WFErrors of
+           Just e  -> CE.throw e     -- !> ("TROWNF=" ++ show e)
+           Nothing ->
+             case CE.fromException e :: Maybe AsyncException of
+                Just e -> CE.throw e -- !> ("TROWN ASYNCF=" ++ show e)
+                Nothing ->
+                 return (GoBack, s{mfTrace= [show e]})
+
+
+--instance (Serialize a,Typeable a, FormInput v) => MonadLoc (FlowM v (Workflow IO)) a where
+--    withLoc loc f =  FlowM . Sup $
+--       withLoc loc $  do
+--            s <- get
+--            (r,s') <-  lift . WF.step $ exec1d "jkkjk" ( runStateT (runSup $ runFlowM f) s) `CMT.catch` (handler1  loc s)
+--            put s'
+--            return r
+--
 --       where
---       handler1 loc s (e :: SomeException)=+--       handler1 loc s (e :: SomeException)=
 --        return (GoBack, s{mfTrace= Just ["exception: " ++show e]}) 
--instance  MonadLoc (View v IO)  where-    withLoc loc f = View $ do-       withLoc loc $ do-            s <- get-            (r,s') <- lift $ do-                       rs@(r,s') <- runStateT (runView f) s+
+instance  MonadLoc (View v IO)  where
+    withLoc loc f = View $ do
+       withLoc loc $ do
+            s <- get
+            (r,s') <- lift $ do
+                       rs@(r,s') <- runStateT (runView f) s
                                              `CE.catch` (handler1  loc s)
-                       case mfTrace s' of-                            []     ->  return rs-                            trace  ->  return(r, s'{mfTrace=  loc:trace})-            put s'-            return r-+                       case mfTrace s' of
+                            []     ->  return rs
+                            trace  ->  return(r, s'{mfTrace=  loc:trace})
+            put s'
+            return r
+
        where
-       handler1 loc s (e :: SomeException)= do-        case CE.fromException e :: Maybe WFErrors of-           Just e  -> CE.throw e                -- !> ("TROWN=" ++ show e)-           Nothing ->-             case CE.fromException e :: Maybe AsyncException of-                Just e -> CE.throw e            -- !> ("TROWN ASYNC=" ++ show e)-                Nothing ->+       handler1 loc s (e :: SomeException)= do
+        case CE.fromException e :: Maybe WFErrors of
+           Just e  -> CE.throw e                -- !> ("TROWN=" ++ show e)
+           Nothing ->
+             case CE.fromException e :: Maybe AsyncException of
+                Just e -> CE.throw e            -- !> ("TROWN ASYNC=" ++ show e)
+                Nothing ->
                   return (FormElm [] Nothing, s{mfTrace= [show e]}) -- !> loc
- 
 
--- | the FlowM monad executes the page navigation. It perform Supracking when necessary to syncronize--- when the user press the back button or when the user enter an arbitrary URL. The instruction pointer--- is moved to the right position within the procedure to handle the request.------ However this is transparent to the programmer, who codify in the style of a console application.
-newtype FlowM v m a= FlowM {runFlowM :: FlowMM v m a} deriving (Monad,MonadIO,MonadState(MFlowState v))
-flowM= FlowM
---runFlowM= runView
 
 
 
+
+
 instance (FormInput v,Serialize a)
    => Serialize (a,MFlowState v) where
    showp (x,s)= case mfDebug s of
@@ -330,23 +332,15 @@                    FormElm form1 mk <- x
                    case mk of
                      Just k  -> do
-                        modify $ \st -> st{linkMatched= False} 
+                        st <- get
+                        put st{linkMatched = False} 
                         FormElm form2 mk <- runView $ f k
                         return $ FormElm (form1 ++ form2) mk
 
                      Nothing -> 
-                        return $ FormElm form1 Nothing+                        return $ FormElm form1 Nothing
                         
-    View x >> f = View $ do
-                   FormElm form1 mk <- x
-                   case mk of
-                     Just k  -> do
-                        modify $ \st -> st{linkMatched= False} 
-                        FormElm form2 mk <- runView  f 
-                        return $ FormElm (form1 ++ form2) mk
 
-                     Nothing -> 
-                        return $ FormElm form1 Nothing
 
     return = View .  return . FormElm  [] . Just
 --    fail msg= View . return $ FormElm [fromStr msg] Nothing
@@ -374,11 +368,18 @@    FormElm form1 mk <- x
    case mk of
      Just k  -> do
-       modify $ \st -> st{linkMatched= False} 
+       modify $ \st -> st{linkMatched= False, needForm=False} 
        runView (f k)
      Nothing -> return $ FormElm form1 Nothing
--   
+
+--clear :: Monad m => View v m ()
+--clear=  View $ do
+--   modify $ \s -> s{mfClear= True}
+--   return . FormElm [] $ Just ()
+
+clear :: Monad m => View v m ()
+clear = wcallback (return()) (const $ return()) 
+
 --incLink :: MonadState (MFlowState view) m => m()
 --incLink= modify $ \st -> st{mfPIndex= if linkMatched st then mfPIndex  st + 1 else mfPIndex st
 --                ,linkMatched= False}  -- !> "<-inc"
@@ -488,11 +489,12 @@   :: ( Functor m, MonadIO m,  FormInput v) => FlowM v m () -> FlowM v m ()
 preventGoingBack msg= do
    back <- goingBack
-   if not back  then breturn() else do
-         breturn()  -- will not go back beyond this
-         clearEnv
-         modify $ \s -> s{newAsk= True}
-         msg
+   if not back  then breturn()  else do
+             breturn()  -- will not go back beyond this
+             clearEnv
+             modify $ \s -> s{newAsk= True}
+             msg
+             
 
 
 
@@ -510,7 +512,7 @@    mfkillTime       :: Int,
    mfSessionTime    :: Integer,
    mfCookies        :: [Cookie],
-   mfHttpHeaders    :: Params,
+   mfHttpHeaders    :: [(SB.ByteString,SB.ByteString)],
    mfHeader         :: view -> view,
    mfDebug          :: Bool,
    mfRequirements   :: [Requirement],
@@ -521,7 +523,6 @@ 
    -- Link management
    mfPath           :: [String],
-
    mfPrefix         :: String,
    mfPIndex         :: Int,
    mfPageIndex      :: Maybe Int,
@@ -529,7 +530,8 @@    mfLinks          :: M.Map String Int,
 
    mfAutorefresh   :: Bool,
-   mfTrace          :: [String]
+   mfTrace          :: [String],
+   mfClear          :: Bool
    }
    deriving Typeable
 
@@ -538,7 +540,7 @@ mFlowState0 :: (FormInput view) => MFlowState view
 mFlowState0 = MFlowState 0 False  True  True  "en"
                 [] False  (error "token of mFlowState0 used")
-                0 0 [] [] stdHeader False [] M.empty  Nothing 0 False    []   ""   1 Nothing False M.empty False []
+                0 0 [] [] stdHeader False [] M.empty  Nothing 0 False    []   ""   1 Nothing False M.empty False [] False
 
 
 -- | Set user-defined data in the context of the session.
@@ -558,9 +560,9 @@ setSessionData ::  (Typeable a,MonadState (MFlowState view) m) => a -> m ()  
 setSessionData  x=
   modify $ \st -> st{mfData= M.insert  (typeOf x ) (unsafeCoerce x) (mfData st)}
--delSessionData x=-  modify $ \st -> st{mfData= M.delete  (typeOf x ) (mfData st)}+
+delSessionData x=
+  modify $ \st -> st{mfData= M.delete  (typeOf x ) (mfData st)}
   
 -- | Get the session data of the desired type if there is any.
 getSessionData ::  (Typeable a, MonadState (MFlowState view) m) =>  m (Maybe a)
@@ -632,53 +634,44 @@   fs <- get
   put fs{mfHeader= header}
 
-----addHeader added= do
-----     h <- gets mfHeader
-----     let h' added html = h $ added <> html
-----     setHeader $ h' added
-----
-----addFooter added= do
-----     h <- gets mfHeader
-----     let h' added html = h $ html <> added
-----     setHeader $ h' added
 
 
 -- | Return the current header
 getHeader :: ( Monad m) => FlowM view m (view -> view)
 getHeader= gets mfHeader
---- | Add another header embedded in the previous one-addHeader new= do-  fhtml <- getHeader-  setHeader $ fhtml . new+
+-- | Add another header embedded in the previous one
+addHeader new= do
+  fhtml <- getHeader
+  setHeader $  fhtml . new
   
 -- | Set an HTTP cookie
 setCookie :: MonadState (MFlowState view) m
-          => String  -- ^ name
+          =>  String  -- ^ name
           -> String  -- ^ value
           -> String  -- ^ path
           -> Maybe Integer  -- ^ Max-Age in seconds. Nothing for a session cookie
           -> m ()
 setCookie n v p me= do
-    modify $ \st -> st{mfCookies= (n,v,p,fmap  show me):mfCookies st }
+    modify $ \st -> st{mfCookies= (SB.pack n,SB.pack v,SB.pack p, fmap  (SB.pack . show) me):mfCookies st }
 
 -- | Set an HTTP Response header
 setHttpHeader :: MonadState (MFlowState view) m
-          => String  -- ^ name
-          -> String  -- ^ value
+           => SB.ByteString  -- ^ name
+          -> SB.ByteString  -- ^ value
           -> m ()
 setHttpHeader n v = do
     modify $ \st -> st{mfHttpHeaders=  (n,v):mfHttpHeaders st }
 
 
--- | Set+-- | Set
 --  1) the timeout of the flow execution since the last user interaction.
--- Once passed, the flow executes from the begining.---+-- Once passed, the flow executes from the begining.
+--
 -- 2) In persistent flows
 -- it set the session state timeout for the flow, that is persistent. If the
--- flow is not persistent, it has no effect.---+-- flow is not persistent, it has no effect.
+--
 -- As the other state primitives, it can be run in the Flow and in the View monad
 --
 -- `transient` flows restart anew.
@@ -706,23 +699,13 @@ type Checked= Bool
 type OnClick= Maybe String
 
-normalize :: (Monad m, FormInput v) => View v m a -> View ByteString m a
+normalize :: (Monad m, FormInput v) => View v m a -> View B.ByteString m a
 normalize f=  View .  StateT $ \s ->do
        (FormElm fs mx, s') <-  runStateT  ( runView f) $ unsafeCoerce s
        return  (FormElm (map toByteString fs ) mx,unsafeCoerce s')
 
---class ToByteString a where
---  toByteString :: a -> ByteString
---
---instance ToByteString a => ToHttpData a where
---  toHttpData = toHttpData . toByteString
---
---instance ToByteString ByteString where
---  toByteString= id
---
---instance ToByteString String where
---  toByteString  =  pack
 
+
 -- | Minimal interface for defining the basic form and link elements. The core of MFlow is agnostic
 -- about the rendering package used. Every formatting (either HTML or not) used with MFlow must have an
 -- instance of this class
@@ -730,7 +713,7 @@ -- See "MFlow.Forms.Blaze.Html for the instance for blaze-html. "MFlow.Forms.XHtml" for the instance
 -- for @Text.XHtml@ and MFlow.Forms.HSP for the instance for Haskell Server Pages.
 class (Monoid view,Typeable view)   => FormInput view where
-    toByteString :: view -> ByteString
+    toByteString :: view -> B.ByteString
     toHttpData :: view -> HttpData
     fromStr :: String -> view
     fromStrNoEncode :: String -> view
@@ -740,7 +723,7 @@     flink1:: String -> view
     flink1 verb = flink verb (fromStr  verb) 
     finput :: Name -> Type -> Value -> Checked -> OnClick -> view 
-    ftextarea :: String -> String -> view
+    ftextarea :: String -> T.Text -> view
     fselect :: String -> view -> view
     foption :: String -> view -> Bool -> view
     foption1 :: String -> Bool -> view
@@ -770,19 +753,19 @@ --, permanently or for a certain time. this is very useful for complex widgets that present information. Specially it they must access to databases.
 --
 -- @
--- import MFlow.Wai.XHtm.All
+-- import MFlow.Wai.Blaze.Html.All
 -- import Some.Time.Library
 -- addMessageFlows [(noscript, time)]
 -- main= run 80 waiMessageFlow
 -- time=do  ask $ cachedWidget \"time\" 5
---            $ wlink () bold << \"the time is \" ++ show (execute giveTheTime) ++ \" click here\"
---          time
+--              $ wlink () b << \"the time is \" ++ show (execute giveTheTime) ++ \" click here\"
+--              time
 -- @
 --
 -- this pseudocode would update the time every 5 seconds. The execution of the IO computation
 -- giveTheTime must be executed inside the cached widget to avoid unnecesary IO executions.
 --
--- NOTE: cached widgets are shared by all users
+-- NOTE: the rendering of cached widgets are shared by all users
 cachedWidget :: (MonadIO m,Typeable view
          , FormInput view, Typeable a,  Executable m )
         => String  -- ^ The key of the cached object for the retrieval
@@ -793,9 +776,10 @@         let((FormElm  form _), sec)= execute $ cachedByKey key t $ proc mf s{mfCached=True}
         let((FormElm  _ mx2), s2)  = execute $ runStateT  ( runView mf)    s{mfSeqCache= sec,mfCached=True}
         let s''=  s{inSync = inSync s2
-                   ,mfRequirements=mfRequirements s2-                   ,mfPath= mfPath s2-                   ,mfPIndex= mfPIndex s2+                   ,mfRequirements=mfRequirements s2
+                   ,mfPath= mfPath s2
+                   ,needForm= needForm s2
+                   ,mfPIndex= mfPIndex s2
                    ,mfPageIndex= mfPageIndex s2
                    ,mfSeqCache= mfSeqCache s + mfSeqCache s2 - sec}
         return $ (mfSeqCache s'') `seq`  ((FormElm form mx2), s'')
@@ -818,53 +802,23 @@ -- It is faster than `cachedWidget`.
 -- It is not restricted to the Identity monad.
 --
--- NOTE: cached widgets are shared by all users
+-- NOTE: the content of freezed widgets are shared by all users
 wfreeze :: (MonadIO m,Typeable view
          , FormInput view, Typeable a,  Executable m )
-        => String  -- ^ The key of the cached object for the retrieval
-        -> Int     -- ^ Timeout of the caching. Zero means sessionwide
+        => String          -- ^ The key of the cached object for the retrieval
+        -> Int             -- ^ Timeout of the caching. Zero means sessionwide
         -> View view m a   -- ^ The cached widget
-        -> View view m a          -- ^ The cached result
+        -> View view m a   -- ^ The cached result
 wfreeze key t mf = View .  StateT $ \s -> do
-        ((FormElm  f mx), req,seq,ajax) <- cachedByKey key t $ proc mf s{mfCached=True}
-        return ((FormElm  f mx), s{mfRequirements=req,mfSeqCache= seq,mfAjax=ajax})
+        (FormElm  f mx, req,seq,ajax) <- cachedByKey key t $ proc mf s{mfCached=True}
+        return ((FormElm f mx), s{mfRequirements=req ,mfSeqCache= seq,mfAjax=ajax})
         where
         proc mf s= do
           (r,s) <- runStateT (runView mf) s
-          return (r,mfRequirements s, mfSeqCache s,mfAjax s)
+          return (r,mfRequirements s, mfSeqCache s, mfAjax s)
 
---
----- | FormLet class
---class (Functor m, MonadIO m) => FormLet  a  m view where
---   digest :: Maybe a
---          -> View view m a
 
---wrender
---  :: Widget a1 a m v => a1 -> StateT (MFlowState v) m ([v], Maybe a)
---
---wrender x =do
---         (FormElm frm x) <-  runView (widget x)
---         return (frm, x)
 
--- Minimal definition: either (wrender and wget) or widget
---class (Functor m, MonadIO m) => Widget  a b m view |  a -> b view where
---   wrender :: a -> WState view m [view]
---   wrender x =do
---         (FormElm frm (_ :: Maybe b)) <-  runView (widget x)
---         return frm
---   wget :: a -> WState view m (Maybe b)
---   wget x=  runView (widget x) >>= \(FormElm _ mx) -> return mx
-
---   widget :: a  -> View view m b
---   widget x = View $  do
---       form <- wrender x  
---       got  <- wget x  
---       return $ FormElm form got
-
-
---instance FormLet  a m view => Widget (Maybe a) a m view  where
---   widget = digest
-
 {- | Execute the Flow, in the @FlowM view m@ monad. It is used as parameter of `hackMessageFlow`
 `waiMessageFlow` or `addMessageFlows`
 
@@ -885,7 +839,7 @@     t' <- f t
     let t''= t'{tpath=[twfname t']}
     liftIO $ do
-       flushRec t''
+       flushRec t'' 
        sendToMF t'' t''  -- !> "SEND"
     loop  f t''          -- !> "LOOPAGAIN"
 
@@ -905,42 +859,112 @@                    ,mfEnv= tenv t} >>= return . fromFailBack
 
   where
-  backInit= do-     s <- get                       -- !> "BackInit"-     case mfTrace s of+  backInit= do
+     s <- get                       -- !> "BackInit"
+     case mfTrace s of
        [] -> do
          modify $ \s -> s{mfEnv=[], newAsk= True}
-         breturn ()-       tr -> do--         error $ disp tr-     where+         breturn ()
+       tr -> do
+
+         error $ disp tr
+     where
      disp tr= "TRACE (error in the last line):\n\n" ++(concat $ intersperse "\n" tr)
   -- to restart the flow in case of going back before the first page of the flow
 
 
 -- | Run a persistent flow inside the current flow. It is identified by the procedure and
 -- the string identifier.
--- unlike the normal flows, that are infinite loops, runFlowIn executes a finite flow
--- once executed, in subsequent executions the flow will return the stored result
--- without asking again. This is useful for asking/storing/retrieving user defined configurations.
+-- unlike the normal flows, that run within infinite loops, runFlowIn executes once.
+-- In subsequent executions, the flow will get the intermediate responses from te log
+-- and will return the result
+-- without asking again. This is useful for asking/storing/retrieving user defined configurations by
+-- means of web formularies.
 runFlowIn
   :: (MonadIO m,
       FormInput view)
   => String
   -> FlowM  view  (Workflow IO)  b
   -> FlowM view m b
-runFlowIn wf f= do
-  t <- gets mfToken
-  FlowM .  Sup $ liftIO $ WF.exec1nc wf $ runFlow1 f t
+runFlowIn wf f= FlowM . Sup $ do
+      st <- get     
+      let t = mfToken st
+      (r,st') <- liftIO $ exec1nc wf $ runFlow1 st f t
+      put st{mfPath= mfPath st'}
+      case r of
+        GoBack ->  delWF  wf ()
+      return r
 
   where
-  runFlow1 f t=   evalStateT (runSup . runFlowM $ f)  mFlowState0{mfToken=t,mfEnv= tenv t}  -- >>= return . fromFailBack  -- >> return ()
+  runFlow1 st f t= runStateT (runSup . runFlowM $ f) st
 
+--exec1bnc :: String ->  Workflow IO a ->   IO  a
+--exec1bnc wf f= liftIO $ do
+-- ei <- getState  wf f ()
+-- case ei of
+--  Left err -> CE.throw err
+--  Right (name, _, stat) -> do
+--     let vers = reverse $ dropWhile isback $ reverse $ S.versions stat !> (unpack $ runW $ showp (S.versions stat))
+--         stat'= stat{S.versions= vers, S.state= length vers} !> (unpack $ runW $ showp vers)
+--     atomically $ writeDBRef (S.self stat) stat'
+--     writeResource stat'
+--     runWF1 name f  stat' False
+--    `CE.catch`
+--      (\(e :: CE.SomeException) -> liftIO $ do
+----             let name=  keyWF wf ()
+--             clearRunningFlag name  --`debug` ("exception"++ show e)
+--             CE.throw e )
+--    `finally`
+--      (liftIO . atomically .
+--           when(S.recover stat) $ do
+--              let ref= S.self stat
+--              s <- readDBRef ref `onNothing` error ("step: not found: "++ S.wfName stat)
+--              writeDBRef ref s{S.recover= False,S.versions= reverse $ S.versions s})
+--
+-- where
+--
+--
+--isback x= serializedEqual x (pack "G ")
+--
+--
+--dropBacks  _ []= []
+--dropBacks nbacks (x:xs)=
+--  case isback x of
+--    True  -> dropBacks (nbacks+1) xs
+--    False -> if nbacks== 0 then x:dropBacks 0 xs
+--                           else dropBacks 0 xs
+--switchWF
+--  :: (MonadIO m,
+--      FormInput view)
+--  => String
+--  -> FlowM  view  (Workflow IO)  b
+--  -> FlowM view m b
+--switchWF wf f= FlowM . Sup $ do
+--      st <- get     
+--      let t = mfToken st
+--      (r,st') <- liftIO $ WF.exec1 wf $ runFlow1 st f t
+--      put st{mfPath= mfPath st'}
+--      return r
+
+--switchWF wf f= do
+--  liftIO $ addMessageFlows [(wf,runFlow f)]
+--  transfer wf
+--
+--  where
+--  runFlow1 st f t= runStateT (runSup . runFlowM $ f) st
+
+-- | transfer control to another flow. (experimental)
+--transfer :: MonadIO m => String -> FlowM v m ()
+--transfer flowname = do
+--         t <- gets mfToken
+--         let t'= t{twfname= flowname}
+--         liftIO  $ do
+--             (r,_) <- msgScheduler t'
+--             sendFlush t r
+
 -- | to unlift a FlowM computation. useful for executing the configuration generated by runFLowIn
--- outside of a web application
-runFlowConf :: (FormInput view, MonadIO m) 
-        => FlowM view m a ->  m a  
+-- outside of the web flow (FlowM) monad
+runFlowConf :: (FormInput view, MonadIO m) => FlowM view m a ->  m a  
 runFlowConf  f = do
   q  <- liftIO newEmptyMVar  -- `debug` (i++w++u)
   qr <- liftIO newEmptyMVar
@@ -955,6 +979,10 @@   st <- get
   put st{ mfEnv= []}
 
+
+-- | stores the result of the flow in a  persistent log. When restarted, it get the result
+-- from the log and it does not execute it again. When no results are in the log, the computation
+-- is executed. It is equivalent to 'Control.Workflow.step' but in the FlowM monad.
 step
   :: (Serialize a,
       Typeable view,
@@ -966,14 +994,17 @@ step f= do
    s <- get
    flowM $ Sup $ do
-        (r,s') <-  lift . WF.step $ runStateT (runSup $ runFlowM f) s
+        (r,s') <- lift . WF.step $ runStateT (runSup $ runFlowM f) s
+                  
         -- when recovery of a workflow, the MFlow state is not considered
         when( mfSequence s' /= -1) $ put s'  -- !> (show $ mfSequence s') -- else put  s{newAsk=True}
-        return r
---- | to execute transient flows as if they were persistent------ > transient $ runFlow f === runFlow $ transientNav f+        return r  
+
+-- | to execute transient flows as if they were persistent
+-- it can be used instead of step, but it does not log the response. it ever executes the computation
+--
+-- > transient $ runFlow f === runFlow $ transientNav f
+
 transientNav
   :: (Serialize a,
       Typeable view,
@@ -981,13 +1012,15 @@       Typeable a) =>
       FlowM view IO a
       -> FlowM view (Workflow IO) a
-transientNav f= do
-   s <- get
-   flowM $ Sup $ do
-        (r,s') <-  lift . unsafeIOtoWF $ runStateT (runSup $ runFlowM f) s-        put s'
-        return r
+transientNav= MFlow.Forms.Internals.step
 
+--transientNav f= do
+--   s <- get
+--   flowM $ Sup $ do
+--        (r,s') <-  lift . unsafeIOtoWF $ runStateT (runSup $ runFlowM f) s
+--        put s'
+--        return r
+
 --stepWFRef
 --  :: (Serialize a,
 --      Typeable view,
@@ -1046,22 +1079,39 @@ 
 data ParamResult v a= NoParam | NotValidated String v | Validated a deriving (Read, Show)
 
+valToMaybe (Validated x)= Just x
+valToMaybe _= Nothing
+
+isValidated (Validated x)= True
+isValidated _= False
+
+fromValidated (Validated x)= x
+fromValidated NoParam= error $ "fromValidated : NoParam"
+fromValidated (NotValidated s err)= error $ "fromValidated: NotValidated "++ s
+
+
 getParam1 :: (Monad m, MonadState (MFlowState v) m, Typeable a, Read a, FormInput v)
           => String -> Params ->  m (ParamResult v a)
-getParam1 par req =  r
+getParam1 par req =   case lookup  par req of
+    Just x1 -> readParam x1
+    Nothing  -> return  NoParam
+
+readParam :: (Monad m, MonadState (MFlowState v) m, Typeable a, Read a, FormInput v)
+           => String -> m (ParamResult v a)
+readParam x1 = r
  where
- r= case lookup  par req of
-    Just x -> do
-        modify $ \s -> s{inSync= True}
-        maybeRead x 
-    Nothing  -> return  NoParam 
+ r= do
+     modify $ \s -> s{inSync= True}
+     maybeRead x1
+      
  getType ::  m (ParamResult v a) -> a
  getType= undefined
  x= getType r
  maybeRead str= do
-   if typeOf x == (typeOf  ( undefined :: String))
-         then return . Validated $ unsafeCoerce str
-         else case readsPrec 0 $ str of
+   let typeofx = typeOf x
+   if typeofx == typeOf  ( undefined :: String)   then return . Validated $ unsafeCoerce  str
+    else if typeofx == typeOf (undefined :: T.Text) then return . Validated . unsafeCoerce  $ T.pack str
+    else case readsPrec 0 $ str of
               [(x,"")] ->  return $ Validated x
               _ -> do
 
@@ -1077,24 +1127,25 @@ -- procedure to be called with the list of requirements.
 -- Varios widgets in the page can require the same element, MFlow will install it once.
 requires rs =do
-    st <- get
+    st <- get 
     let l = mfRequirements st
 --    let rs'= map Requirement rs \\ l
     put st {mfRequirements= l ++ map Requirement rs}
 
 
 
-data Requirement= forall a.(Typeable a,Requirements a) => Requirement a deriving Typeable
+data Requirement= forall a.(Show a,Typeable a,Requirements a) => Requirement a deriving Typeable
 
 class Requirements  a where
    installRequirements :: (Monad m,FormInput view) => [a] ->  m view
 
-
+instance Show Requirement where
+   show (Requirement a)= show a ++ "\n"
 
 installAllRequirements :: ( Monad m, FormInput view) =>  WState view m view
 installAllRequirements= do
  rs <- gets mfRequirements
- installAllRequirements1 mempty rs
+ installAllRequirements1 mempty rs 
  where
 
  installAllRequirements1 v []= return v
@@ -1147,10 +1198,6 @@   \document.getElementsByTagName('head')[0].appendChild(fileref);"
 
 
-
-
-
-
 data WebRequirement= JScriptFile
                             String
                             [String]   -- ^ Script URL and the list of scripts to be executed when loaded
@@ -1158,7 +1205,7 @@                    | CSS String        -- ^ a String with a CSS description
                    | JScript String                -- ^ a string with a valid JavaScript
                    | ServerProc (String, Flow)     -- ^ a server procedure
-                   deriving(Typeable,Eq,Ord,Show)
+                     deriving(Typeable,Eq,Ord,Show)
 
 instance Eq (String, Flow) where
    (x,_) == (y,_)= x == y
@@ -1175,30 +1222,31 @@ 
 installWebRequirements ::  (Monad m,FormInput view) =>[WebRequirement] -> m view
 installWebRequirements rs= do
-  let s =  aggregate  $ sort rs
+  let s =  jsRequirements $ sort rs
 
   return $ ftag "script" (fromStrNoEncode  s)
-  where
-  aggregate  []= ""
 
 
-  aggregate (r@(JScriptFile f c) : r'@(JScriptFile f' c'):rs)
-         | f==f'= aggregate $ JScriptFile f (nub  c++c'):rs
-         | otherwise= strRequirement r++aggregate (r':rs)
+jsRequirements  []= ""
 
-  aggregate (r:r':rs)
-         | r== r' = aggregate $ r:rs
-         | otherwise= strRequirement r ++ aggregate (r':rs)
 
-  aggregate (r:rs)= strRequirement r++aggregate rs
+jsRequirements (r@(JScriptFile f c) : r'@(JScriptFile f' c'):rs)
+         | f==f' = jsRequirements $ JScriptFile f (nub $ c++c'):rs
+         | otherwise= strRequirement r ++ jsRequirements (r':rs)
 
-  strRequirement  (CSSFile s')         = loadcssfile s'
-  strRequirement (CSS s')              = loadcss s'
-  strRequirement (JScriptFile s' call) = loadjsfile s' call
-  strRequirement (JScript s')          = loadjs s'
-  strRequirement (ServerProc  f)= (unsafePerformIO $! addMessageFlows [f]) `seq` ""
+jsRequirements (r:r':rs)
+         | r== r' = jsRequirements $ r:rs
+         | otherwise= strRequirement r ++ jsRequirements (r':rs)
 
+jsRequirements (r:rs)= strRequirement r++jsRequirements rs
+  
+strRequirement (CSSFile s')          = loadcssfile s'
+strRequirement (CSS s')              = loadcss s'
+strRequirement (JScriptFile s' call) = loadjsfile s' call
+strRequirement (JScript s')          = loadjs s'
+strRequirement (ServerProc  f)= (unsafePerformIO $! addMessageFlows [f]) `seq` ""
 
+
 --- AJAX ----
 ajaxScript=
         "function loadXMLObj()" ++
@@ -1247,7 +1295,9 @@         True   -> concat $ take index  ['/':v | v <- lpath]  -- !> ("index= " ++ show index)
         False  -> concat ['/':v| v <- lpath])
 
--- | Generate a new string. Useful for creating tag identifiers and other attributes
+-- | Generate a new string. Useful for creating tag identifiers and other attributes.
+--
+-- if the page is refreshed, the identifiers generated are the same.
 genNewId :: MonadState (MFlowState view) m =>  m String
 genNewId=  do
   st <- get
@@ -1262,3 +1312,17 @@       let n = mfSeqCache st
       put $ st{mfSeqCache=n+1}
       return $  'c' : (show n)
+
+-- | get the next ideitifier that will be created by genNewId
+getNextId :: MonadState (MFlowState view) m =>  m String
+getNextId=  do
+  st <- get
+  case mfCached st of
+    False -> do
+      let n= mfSequence st
+          prefseq=  mfPrefix st
+      return $ 'p':show n++prefseq
+    True  -> do
+      let n = mfSeqCache st
+      return $  'c' : (show n)
+
src/MFlow/Forms/Widgets.hs view
@@ -15,28 +15,31 @@  module MFlow.Forms.Widgets ( -- * Ajax refreshing of widgets-autoRefresh, appendUpdate, prependUpdate, push, UpdateMethod(..)+autoRefresh, noAutoRefresh, appendUpdate, prependUpdate, push, UpdateMethod(..)  -- * JQueryUi widgets ,datePicker, getSpinner, wautocomplete, wdialog,  -- * User Management-userFormOrName,maybeLogout,+userFormOrName,maybeLogout, wlogin,  -- * Active widgets wEditList,wautocompleteList , wautocompleteEdit,  -- * Editing widgets-delEdited, getEdited-,prependWidget,appendWidget,setWidget+delEdited, getEdited,prependWidget,appendWidget,setWidget  -- * Content Management-,tField, tFieldEd, tFieldGen+,tField, tFieldEd, htmlEdit, edTemplate, dField, template, witerate,tfieldKey  -- * Multilanguage ,mFieldEd, mField +-- * utility+,insertForm++ ) where import MFlow import MFlow.Forms@@ -60,7 +63,7 @@ import Data.Char import Control.Monad.Identity import Control.Workflow(killWF)-+import Unsafe.Coerce   readyJQuery="ready=function(){if(!window.jQuery){return setTimeout(ready,100)}};"@@ -113,6 +116,34 @@       ta :: Medit v m a -> a       ta= undefined +-- | If not logged, it present a page flow which askm  for the user name, then the password if not logged
+--
+-- If logged, it present the user name and a link to logout
+--
+-- normally to be used with autoRefresh and pageFlow when used with other widgets.
+wlogin :: (MonadIO m,Functor m,FormInput v) => View v m ()
+wlogin=  do
+   username <- getCurrentUser
+   if username /= anonymous
+         then return username
+         else do
+          name <- getString Nothing <! hint "login name" <! size 9 <++ ftag "br" mempty
+          pass <- getPassword <! hint "password" <! size 9+                     <++ ftag "br" mempty+                     <** submitButton "login" 
+          val  <- userValidate (name,pass)
+          case val of
+            Just msg -> notValid msg
+            Nothing  -> login name >> return name
+       
+   `wcallback` (\name -> ftag "b" (fromStr $ "logged as " ++ name)
+                     ++>  wlink ("logout" :: String) (ftag "b" $ fromStr " logout"))
+   `wcallback`  const (logout >> wlogin)
+   
+focus = [("onload","this.focus()")]+hint s= [("placeholder",s)]+size n= [("size",show n)]+ getEdited1 id= do     Medit stored <- getSessionData `onNothing` return (Medit M.empty)     return $ fromMaybe [] $ M.lookup id stored@@ -170,6 +201,7 @@      where      typ :: View v Identity a -> a      typ = undefined+ -- | Return the javascript to be executed on the browser to prepend a widget to the location -- identified by the selector (the bytestring parameter), The selector must have the form of a jquery expression -- . It stores the added widgets in the edited list, that is accessed with 'getEdited'@@ -221,7 +253,6 @@ -- This example add or delete editable text boxes, with two initial boxes   with -- /hi/, /how are you/ as values. Tt uses blaze-html: --- -- >  r <-  ask  $   addLink -- >              ++> br -- >              ++> (El.div `wEditList`  getString1 $  ["hi", "how are you"]) "addid"@@ -298,9 +329,10 @@   -> (String -> IO a)   -- ^ Autocompletion procedure: will receive a prefix and return a list of strings   -> View v m String wautocomplete mv autocomplete  = do+    text1 <- genNewId     ajaxc <- ajax $ \u -> do                           r <- liftIO $ autocomplete u-                          return $ jaddtoautocomp r+                          return $ jaddtoautocomp text1 r       requires [JScriptFile jqueryScript [] -- [events]@@ -309,18 +341,18 @@       getString mv <!  [("type", "text")-                     ,("id", "text1")-                     ,("oninput",ajaxc "$('#text1').attr('value')" )+                     ,("id", text1)+                     ,("oninput",ajaxc $ "$('#"++text1++"').attr('value')" )                      ,("autocomplete", "off")]       where-    jaddtoautocomp us= "$('#text1').autocomplete({ source: " <> B.pack( show us) <> "  });"+    jaddtoautocomp text1 us= "$('#"<>B.pack text1<>"').autocomplete({ source: " <> B.pack( show us) <> "  });"   -- | Produces a text box. It gives a autocompletion list to the textbox. When return -- is pressed in the textbox, the box content is used to create a widget of a kind defined--- by the user, which will be situated above of the textbox. When submitted, the result of this widget is the content+-- by the user, which will be situated above of the textbox. When submitted, the result is the content -- of the created widgets (the validated ones). -- -- 'wautocompleteList' is an specialization of this widget, where@@ -341,18 +373,19 @@     -> (Maybe String  -> View v Identity a)   -- ^ the widget to add, initialized with the string entered in the box     -> [String]                               -- ^ initial set of values     -> View v m [a]                           -- ^ resulting widget-wautocompleteEdit phold   autocomplete  elem values= do+wautocompleteEdit phold autocomplete  elem values= do     id1 <- genNewId+    let textx= id1++"text"     let sel= "$('#" <> B.pack id1 <> "')"     ajaxc <- ajax $ \(c:u) ->-              case c of+              case c  of                 'f' -> prependWidget sel (elem $ Just u)                 _   -> do                           r <- liftIO $ autocomplete u-                          return $ jaddtoautocomp r+                          return $ jaddtoautocomp textx r  -    requires [JScriptFile jqueryScript [events ajaxc] -- [events]+    requires [JScriptFile jqueryScript  [events textx ajaxc]              ,CSSFile jqueryCSS              ,JScriptFile jqueryUI []] @@ -362,29 +395,29 @@       ++> manyOf (ws' ++ (map (changeMonad . elem . Just) values)))       <++ ftag "input" mempty              `attrs` [("type", "text")-                     ,("id", "text1")+                     ,("id", textx)                      ,("placeholder", phold)-                     ,("oninput",ajaxc "'n'+$('#text1').attr('value')" )+                     ,("oninput", ajaxc $ "'n'+$('#"++textx++"').val()" )                      ,("autocomplete", "off")]     delEdited sel ws'     return r     where-    events ajaxc=+    events textx ajaxc=          "$(document).ready(function(){   \-         \  $('#text1').keydown(function(){ \+         \  $('#"++textx++"').keydown(function(){ \          \   if(event.keyCode == 13){  \-             \   var v= $('#text1').attr('value'); \+             \   var v= $('#"++textx++"').val(); \              \   if(event.preventDefault) event.preventDefault();\              \   else if(event.returnValue) event.returnValue = false;" ++                  ajaxc "'f'+v"++";"++-             "   $('#text1').val('');\+             "   $('#"++textx++"').val('');\          \  }\          \ });\          \});" -    jaddtoautocomp us= "$('#text1').autocomplete({ source: " <> B.pack( show us) <> "  });"+    jaddtoautocomp textx us= "$('#"<>B.pack textx<>"').autocomplete({ source: " <> B.pack( show us) <> "  });" --- | A specialization of 'selectAutocompleteEdit' which make appear each option choosen with+-- | A specialization of 'wutocompleteEdit' which make appear each chosen option with -- a checkbox that deletes the element when uncheched. The result, when submitted, is the list of selected elements. wautocompleteList   :: (Functor m, MonadIO m, Executable m, FormInput v) =>@@ -392,44 +425,67 @@ wautocompleteList phold serverproc values=  wautocompleteEdit phold serverproc  wrender1 values  where- wrender1 x= ftag "div"    <<< ftag "input" mempty+ wrender1 x= ftag "div" <<< ftag "input" mempty                                 `attrs` [("type","checkbox")                                         ,("checked","")                                         ,("onclick","this.parentNode.parentNode.removeChild(this.parentNode)")]-                           ++> ftag "span" (fromStr $ fromJust x )-                           ++> whidden( fromJust x)+                        ++> ftag "span" (fromStr $ fromJust x )+                        ++> whidden( fromJust x)  ------- Templating and localization --------- -writetField    k s=  atomically $ writetFieldSTM k s+data TField  = TField {tfieldKey :: Key, tfieldContent :: B.ByteString}  deriving (Read, Show,Typeable) -writetFieldSTM k s=  do-             phold <- readDBRef tFields `onNothing` return (M.fromList [])-             let r= M.insert k  (toByteString s) phold-             writeDBRef tFields   r+instance Indexable TField where+    key (TField k _)= k+    defPath _= "texts/" ++instance Serializable TField where+    serialize (TField k content)  = B.pack $ "TField "++show k ++ " " ++ show (B.unpack content)-- B.pack . show+    deserialize bs=+                let ('T':'F':'i':'e':'l':'d':' ':s)= B.unpack bs -- read . B.unpack+                    [(k,rest)] =  readsPrec 0 s+                    [(content,_)] = readsPrec 0 $ tail rest+                in TField k (B.pack content)+    setPersist =   \_ -> Just filePersist+++writetField k s= atomically $ writeDBRef (getDBRef k) $ TField k $ toByteString s++ readtField text k= atomically $ do-       hs<- readDBRef tFields `onNothing` return (M.fromList [])-       let mp=  M.lookup k hs-       case mp of-         Just c  -> return   $ fromStrNoEncode $ B.unpack c-         Nothing -> writetFieldSTM k  text >> return  text+   let ref = getDBRef k+   mr <- readDBRef ref+   case mr of+    Just (TField k v) -> return $ fromStrNoEncode $ B.unpack v+    Nothing -> return text -type TFields  = M.Map String B.ByteString-instance Indexable TFields where-    key _= "texts"-    defPath _= "texts/" -tFields :: DBRef TFields-tFields =  getDBRef "texts"+htmlEdit :: (Monad m, FormInput v) =>  [String] -> UserStr -> View v m a -> View v m a+htmlEdit buttons jsuser w = do+  id <- genNewId -type Key= String+  let installHtmlField=+          "\nfunction installHtmlField(muser,cookieuser,name,buttons){\n\+            \if(muser== '' || document.cookie.search(cookieuser+'='+muser) != -1)\n\+                 \ bkLib.onDomLoaded(function() {\n\+                 \   var myNicEditor = new nicEditor({buttonList : buttons});\n\+                 \   myNicEditor.panelInstance(name);\n\+                 \})};\n"+      install= "installHtmlField('"++jsuser++"','"++cookieuser++"','"++id++"',"++show buttons++");\n" --- | A widget that display the content of an  html, But if logged as administrator,+  requires [JScriptFile nicEditUrl [installHtmlField,install]]+  w <! [("id",id)]++nicEditUrl= "http://js.nicedit.com/nicEdit-latest.js"+++-- | A widget that display the content of an  html, But if the user has edition privileges, -- it permits to edit it in place. So the editor could see the final appearance--- of what he write in the page.+-- of what he writes. ----- When the administrator double click in the paragraph, the content is saved and+-- When the user  click the save, the content is saved and -- identified by the key. Then, from now on, all the users will see the saved -- content instead of the code content. --@@ -437,102 +493,387 @@ -- a configurable version (`tFieldGen`). The content of the element and the formatting -- is cached in memory, so the display is, theoretically, very fast. ----- THis is an example of how to use the content management primitives (in demos.blaze.hs):------ > textEdit= do--- >   setHeader $ \t -> html << body << t--- >--- >   let first=  p << i <<--- >                  (El.span << text "this is a page with"--- >                  <> b << text " two " <> El.span << text "paragraphs")--- >--- >       second= p << i << text "This is the original text of the second paragraph"--- >--- >       pageEditable =  (tFieldEd "first"  first)--- >                   **> (tFieldEd "second" second)--- >--- >   ask $   first--- >       ++> second--- >       ++> wlink () (p << text "click here to edit it")--- >--- >   ask $ p << text "Please login with admin/admin to edit it"--- >           ++> userWidget (Just "admin") userLogin--- >--- >   ask $   p << text "now you can click the field and edit them"--- >       ++> p << b << text "to save the edited field, double click on it"--- >       ++> pageEditable--- >       **> wlink () (p << text "click here to see it as a normal user")--- >--- >   logout--- >--- >   ask $   p << text "the user sees the edited content. He can not edit"--- >       ++> pageEditable--- >       **> wlink () (p << text "click to continue")--- >--- >   ask $   p << text "When text are fixed,the edit facility and the original texts can be removed. The content is indexed by the field key"--- >       ++> tField "first"--- >       **> tField "second"--- >       **> p << text "End of edit field demo" ++> wlink () (p << text "click here to go to menu")+ tFieldEd   :: (Functor m,  MonadIO m, Executable m,       FormInput v) =>-      Key -> v -> View v m ()-tFieldEd  k text=-   tFieldGen k  (readtField text) writetField+      UserStr -> Key -> v -> View v m ()+tFieldEd  muser k  text= wfreeze k 0 $  do+   content <- liftIO $ readtField text k+   nam     <- genNewId+   let ipanel= nam++"panel"+       name= nam++"-"++k+       install= "\ninstallEditField('"++muser++"','"++cookieuser++"','"++name++"','"++ipanel++"');\n"+       getTexts :: (Token -> IO ())+       getTexts token = do+         let (k,s):_ = tenv token+         liftIO $ do+           writetField k  $ (fromStrNoEncode s `asTypeOf` text)+           flushCached k+           sendFlush token $ HttpData [] [] ""+           return() +   requires [JScriptFile nicEditUrl [install]+            ,JScript     ajaxSendText+            ,JScript     installEditField+--            ,JScriptFile jqueryScript []+            ,ServerProc  ("_texts",  transient getTexts)] --- | Like 'tFieldEd' with user-configurable storage.-tFieldGen :: (MonadIO m,Functor m, Executable m-        ,FormInput v)-        => Key-        -> (Key -> IO  v)  -- ^ the read procedure, user defined-        -> (Key ->v  -> IO())   -- ^ the write procedure, user defiend-        -> View v m ()-tFieldGen  k  getcontent create =   wfreeze k 0 $ do-    content <- liftIO $ getcontent  k-    admin   <- getAdminName-    ajaxjs  <- ajax  $ \str -> do-              let (k,s)= break (==',')    str  -- !> str-              liftIO  . create  k  $ fromStrNoEncode (tail s)-              liftIO $ flushCached k-              return "alert('saved')"-    attribs <- do-            name <- genNewId-            -- Need to check the user in the browser because the widget is wfreeze'd-            let ifUserAdmin= "if(document.cookie.search('"++cookieuser++"="++admin++"') != -1)"-                nikeditor= "var myNicEditor = new nicEditor();"-                callback=ifUserAdmin ++-                  "bkLib.onDomLoaded(function() {\-                     \    myNicEditor.addInstance('"++name++"');\-                     \});"-                param= ("'"++k  ++ "'+','+ document.getElementById('"++name++"').innerHTML")+   (ftag "div" mempty `attrs` [("id",ipanel)]) ++>+    wraw (ftag "span" content `attrs` [("id", name)]) -            requires  [JScriptFile "http://js.nicedit.com/nicEdit-latest.js" [nikeditor, callback]] -            return [("id", name),("ondblclick",  ifUserAdmin ++ ajaxjs param)] -    wraw $  (ftag "span" content `attrs` attribs)+installEditField=+          "\nfunction installEditField(muser,cookieuser,name,ipanel){\n\+            \if(muser== '' || document.cookie.search(cookieuser+'='+muser) != -1)\n\+                 \ bkLib.onDomLoaded(function() {\n\+                 \   var myNicEditor = new nicEditor({fullPanel : true, onSave : function(content, id, instance) {\+                 \        ajaxSendText(id,content);\n\+                 \        myNicEditor.removeInstance(name);\n\+                 \        myNicEditor.removePanel(ipanel);\n\+                 \      }});\n\+                 \   myNicEditor.addInstance(name);\n\+                 \   myNicEditor.setPanel(ipanel);\n\+                 \})};\n" --- | Read the field value and present it without edition.-tField :: (MonadIO m,Functor m, Executable m-       ,  FormInput v)+ajaxSendText = "\nfunction ajaxSendText(id,content){\n\+        \var arr= id.split('-');\n\+        \var k= arr[1];\n\+        \$.ajax({\n\+        \       type: 'POST',\n\+        \       url: '/_texts',\n\+        \       data: k + '='+ encodeURIComponent(content),\n\+        \       success: function (resp) {},\n\+        \       error: function (xhr, status, error) {\n\+        \                var msg = $('<div>' + xhr + '</div>');\n\+        \                id1.html(msg);\n\+        \       }\n\+        \   });\n\+        \return false;\n\+        \};\n"++-- | a text field. Read the cached  field value and present it without edition.+tField :: (MonadIO m,Functor m, Executable m, FormInput v)        => Key        -> View v m ()-tField  k    =  wfreeze k 0 $ do-    content <-  liftIO $ readtField (fromStrNoEncode "not found")  k+tField k = wfreeze k 0 $ do+    content <- liftIO $ readtField (fromStrNoEncode "not found")  k     wraw content  -- | A multilanguage version of tFieldEd. For a field with @key@ it add a suffix with the -- two characters of the language used.-mFieldEd k content= do+mFieldEd  muser k content= do   lang <- getLang-  tFieldEd (k ++ ('-':lang)) content+  tFieldEd  muser (k ++ ('-':lang)) content ++ -- | A multilanguage version of tField mField k= do   lang <- getLang   tField $ k ++ ('-':lang) +newtype IteratedId= IteratedId  String deriving Typeable++-- | Permits to iterate the presentation of data and//or input fields and widgets within+-- a web page that does not change. The placeholders are created with dField.  Both are widget+-- modifiers: The latter gets a widget and create a placeholder in the page that is updated+-- via ajax. The content of the update is the rendering of the widget at each iteration.+-- The former gets a wider widget which contains dField elements and permit the iteration.+-- Whenever a link or a form within the witerate widget is activated, the result is the+-- placeholders filled with the new  html content.  This content can be data, a input field,+-- a link or a widget. No navigation happens.+--+-- This permits even faster updates than autoRefresh.  since the latter refresh the whole+-- widget and it does not permits modifications of the layout at runtime.+--+-- When edTemplate or template is used on top of witerate, the result is editable at runtime,+-- and the span placeholders generated, that are updated via ajax can be relocated within+-- the layout of the template.+--+-- Additionally, contrary to some javascript frameworks, the pages generated with this+-- mechanism are searchable by web crawlers.++witerate+  :: (MonadIO m, Functor m, FormInput v) =>+      View v m a -> View v m a+witerate  w= do+   name  <- genNewId+   setSessionData $ IteratedId name+   st <- get+   let index= mfPIndex st+   let t= mfkillTime st+   let installAutoEval=+        "$(document).ready(function(){\n\+           \autoEvalLink('"++name++"','"++ show index ++"');\+           \autoEvalForm('"++name++"');\+           \})\n"+   let r = lookup ("auto"++name) $ mfEnv st+   ret <- case r of+    Nothing -> do+     requires [JScript     autoEvalLink+              ,JScript     autoEvalForm+              ,JScript     setId+              ,JScript     $ timeoutscript t+              ,JScriptFile jqueryScript [installAutoEval]]++     (ftag "div" <<< insertForm w) <! [("id",name)]+++    Just sind -> View $ do+         let t= mfToken st+         let index= read sind+         put st{mfPIndex= index}+         modify $ \s -> s{mfRequirements=[]}++         FormElm _ mr <- runView  w++         reqs <- return . map ( \(Requirement r) -> unsafeCoerce r) =<< gets mfRequirements+         let js = jsRequirements reqs+         liftIO . sendFlush t $ HttpData+                                (("Cache-Control", "no-cache, no-store"):mfHttpHeaders st)+                                (mfCookies st) (B.pack js)+         modify $ \st -> st{mfAutorefresh=True,inSync=True}+         return $ FormElm [] mr++   delSessionData $ IteratedId name+   return ret++autoEvalLink = "\nfunction autoEvalLink(id,ind){\n\+    \var id1= $('#'+id);\n\+    \var ida= $('#'+id+' a[class!=\"_noAutoRefresh\"]');\n\+    \ida.click(function () {\n\+    \ if (hadtimeout == true) return true;\n\+    \ var pdata = $(this).attr('data-value');\n\+    \ var actionurl = $(this).attr('href');\n\+    \ var dialogOpts = {\n\+    \       type: 'GET',\n\+    \       url: actionurl+'?bustcache='+ new Date().getTime()+'&auto'+id+'='+ind,\n\+    \       data: pdata,\n\+    \       success: function (resp) {\n\+    \           eval(resp);\n\+    \       },\n\+    \       error: function (xhr, status, error) {\n\+    \           var msg = $('<div>' + xhr + '</div>');\n\+    \           id1.html(msg);\n\+    \       }\n\+    \   };\n\+    \ $.ajax(dialogOpts);\n\+    \ return false;\n\+    \});\n\+  \}\n"++autoEvalForm = "\nfunction autoEvalForm(id) {\n\+    \var id1= $('#'+id);\n\+    \var idform= $('#'+id+' form[class!=\"_noAutoRefresh\"]');\n\+    \idform.submit(function (event) {\n\+        \if (hadtimeout == true) return true;\n\+        \event.preventDefault();\n\+        \var $form = $(this);\n\+        \var url = $form.attr('action');\n\+        \var pdata = $form.serialize();\n\+        \$.ajax({\n\+            \type: 'POST',\n\+            \url: url,\n\+            \data: 'auto'+id+'=true&'+pdata,\n\+            \success: function (resp) {\n\+                \eval(resp);\n\+            \},\n\+            \error: function (xhr, status, error) {\n\+                \var msg = $('<div>' + xhr + '</div>');\n\+                \id1.html(msg);\n\+            \}\n\+        \});\n\+       \});\n\+      \return false;\n\+     \}\n"++setId= "function setId(id,v){document.getElementById(id).innerHTML= v;};\n"++-- Present a widget via AJAX if it is within a 'witerate' context. In the first iteration it present the+-- widget surrounded by a placeholder. subsequent iterations will send just the javascript code+-- necessary for the refreshing of the placeholder.+dField+  :: (Monad m, FormInput view) =>+     View view m  b -> View view m b+dField w= View $ do+    id <- genNewId+    FormElm vs mx <- runView w+    let render = mconcat vs+    st <- get+    let env =  mfEnv st++    IteratedId name <- getSessionData `onNothing` return (IteratedId noid)+    let r =  lookup ("auto"++name) env+    if r == Nothing || (name == noid && newAsk st== True)  then do+       requires [JScriptFile jqueryScript ["$(document).ready(function() {setId('"++id++"','" ++ B.unpack (toByteString $ render)++"')});\n"]]+       return $ FormElm[(ftag "span" render) `attrs` [("id",id)]] mx+     else do+       requires [JScript $  "setId('"++id++"','" ++ B.unpack (toByteString $ render)++"');\n"]+       return $ FormElm mempty mx++noid= "noid"++--edTemplateList+--  :: (MonadIO m, Functor m, Typeable b, FormInput view) =>+--     UserStr -> String -> (a ->View view m  b) -> [a] -> View view m b+--edTemplateList user  name w xs= View $ do+--    id <- genNewId+--    let ws= Prelude.map w xs+--    FormElm vx mx <- runView $+--          edTemplate user name ( Prelude.head ws) <|>+--          firstOf [template name w | w <- Prelude.tail ws]+--+--    let render = mconcat vx+--    st <- get+--    let t= mfkillTime st+--    let env =  mfEnv st+--    let insertResults= "insert('" ++ id ++ "',"++ show (B.unpack $ toByteString render) ++");"+--    IteratedId name <- getSessionData `onNothing` return (IteratedId noid)+--    let r =  lookup ("auto"++name) env           -- !> ("TIMEOUT="++ show t)+--    if r == Nothing || (name == noid && newAsk st== True)+--     then do+--         requires[JScript autoEvalLink+--                 ,JScript $ timeoutscript t+--                 ,JScript jsInsertList+--                 ,JScriptFile jqueryScript [insertResults]]+--         return $ FormElm[(ftag "span" render) `attrs` [("id",id)]] mx  !> "NOPARAM edTemplateList"+--     else do+--       modify $ \st -> st{mfRequirements= [],mfAutorefresh=True,inSync=True}+--       requires[JScript insertResults]+--             !> "VALIDATED edTemplateList"+--       return $ FormElm mempty mx+--++-- | load a template with the name equal to the second parameter in the texts folder. If no template+-- exist, it uses the widget rendering. If the first parameter match the name of the logged user,+-- the template will be editable at runtime. edTemplate will present an edition bar on the top of+-- the template. The changes in the template will be effective inmediately for all the users.+--+-- The return value is the one returned by the internal widget each time it is executed.+--+-- edTemplate can be used to enrich the content and layout of a widget, for example, by adding+-- extra links, text and formatting. Widgets with form fields work well with an 'edTemplate' mask+-- as long as the tags created by the widget are not deleted, but the validation messages will not appear+--+-- To add dynamic elements to the template for data presentation and//or input field validation+-- messages, combine it with 'witerate' and 'dField'+edTemplate+  :: (MonadIO m, FormInput v, Typeable a) =>+      UserStr -> Key -> View v m a -> View v m a+edTemplate muser k w=  View $ do+   nam     <- genNewId++   let ipanel= nam++"panel"+       name= nam++"-"++k+       install= "\ninstallEditField('"++muser++"','"++cookieuser++"','"++name++"','"++ipanel++"');\n"+++   requires [JScriptFile nicEditUrl [install]+            ,JScript     ajaxSendText+            ,JScript     installEditField+            ,JScriptFile jqueryScript []+            ,ServerProc  ("_texts",  transient getTexts)]++   FormElm text mx <- runView w+   content <- liftIO $ readtField (mconcat text) k++   return $ FormElm [ftag "div" mempty `attrs` [("id",ipanel)]+                    ,ftag "span" content `attrs` [("id", name)]]+                     mx+   where+   getTexts :: (Token -> IO ())+   getTexts token= do+     let (k,s):_ = tenv token+     liftIO $ do+       writetField k  $ (fromStrNoEncode s `asTypeOf` viewFormat w)+       flushCached k+       sendFlush token $ HttpData [] [] ""+       return()++   viewFormat :: View v m a -> v+   viewFormat= undefined -- is a type function++-- | Does the same than template but without the edition facility+template k w= View $ do+    FormElm text mx <- runView  w+    let content= unsafePerformIO $ readtField  (mconcat text) k+    return $ FormElm [content] mx++--edTemplateList+--  :: (Typeable a,FormInput view) =>+--     UserStr -> String  -> [View view Identity a] -> View view IO a+--edTemplateList user templ  ws=  do+--  let  id = templ+--  let wrapid=  "wrapper-" ++ id+--  text <- liftIO $ readtField  (ftag "div" mempty `attrs` [("id",wrapid)])  wrapid+--  let   vwrtext= B.unpack $ toByteString (text `asTypeOf` witness ws)+--+----  wrapperEd wrapid vwrtext **>+--  (ftag "div" <<< elems id wrapid vwrtext) <! [("id",wrapid)]+--  where+--  witness :: [View view Identity a] -> view+--  witness = undefined+--+--  elems id wrapid vwrtext= View $ do+--    let holder=  ftag "span" (fromStr "holder") `attrs` [("_holder",id)]+--+--    FormElm fedit _ <- runView $ tFieldEd user templ holder+--    frest  <- liftIO $ readtField holder  templ+--+--    forms <-  mapM (runView . changeMonad) ws+--    let vs   = map (\(FormElm v _) ->  mconcat v) forms+--    requires [JScriptFile jqueryScript+--              [+----               replacewrap+----              ,"replacewrap('"++ wrapid ++ "','" ++ vwrtext ++ "')",+--              jsInsertList+--              ,"$(document).ready(function() {\+--               \insert('" ++ id ++ "',"++ show (map ( B.unpack . toByteString) vs) ++");\n\+--               \});"]]+--+--    let res = filter isJust $ map (\(FormElm _ r) -> r) forms
+--        res1= if null res then Nothing else head res+--+--    return $ FormElm  (mconcat fedit: take (length vs -1) (repeat frest)) res1+--+jsInsertList =+      "\nfunction insert(id,vs){\n\+      \$('[_holder=\"'+id+'\"]').each(function(n,it) {\n\+      \  $(it).html(vs[n]);\n\+      \})};\n"++--  wrapperEd :: (FormInput view) => String -> view -> View view IO ()+--  wrapperEd  wrapid  wrtext = do -- autoRefresh . pageFlow "wrap" $ do+--        vwrtext <- liftIO $ readtField  (ftag "div" mempty `attrs` [("id",wrapid)])  wrapid+--        let wrtext= B.unpack $ toByteString (vwrtext `asTypeOf` witness)+--        nwrtext<- getString  (Just wrtext)+--                          <! [("id", wrapid++"-ed")]+--                   <** submitButton "OK"+--+--        liftIO $ writetField wrapid (fromStr nwrtext `asTypeOf` witness ws) !> nwrtext+++--  replacewrap = "\nfunction replacewrap(id,wrapcode){\n\+--          \   var selector= '#'+id;\n\+--          \   var children = $(selector).children();\n\+--          \   var nchildren;\n\+--          \   $(selector).replaceWith(wrapcode);\n\+--          \   $(selector).html(children);\n\+--          \   if(wrapcode.search('table') != -1)\n\+--          \        $(children[1].children).wrap('<tr><td></td></tr>')\n\+--          \};\n"++--          \   if(wrapcode.search('xx') != -1){\n\+--          \        children.each(function(n,it){\n\+--          \                      $(it).wrap('<li></li>')});\n\++--          \        })\n\++++------------------- JQuery widgets ------------------- -- | present the JQuery datepicker calendar to choose a date. -- The second parameter is the configuration. Use \"()\" by default. -- See http://jqueryui.com/datepicker/@@ -576,8 +917,7 @@      (ftag "div" <<< insertForm w) <! [("id",id),("title", title)] --+-- | insert a form tag if the widget has form input fields. If not, it does nothing insertForm w=View $ do     FormElm forms mx <- runView w     st <- get@@ -608,6 +948,33 @@   -> View v m a autoRefresh w=  update "html" w +-- | In some cases, it is neccessary that a link or form inside a 'autoRefresh' or 'update' block+-- should not be autorefreshed, since it produces side effects in the rest of the page that+-- affect to the rendering of the whole. If you like to refresh the whole page, simply add+-- noAutoRefresh attribute to the widget to force the refresh of the whole page when it is activated.+--+-- That behaviour is common at the last sentence of the 'autoRefresh' block.+--+-- This is a cascade menu example.+--+-- > r <- page $ autoRefresh $ ul <<< do+-- >        li <<< wlink OptionA << "option A"+-- >        ul <<< li <<< (wlink OptionA1 << "Option A1" <! noAutoRefresh)+-- >           <|> li <<< (wlink OptionA2 << "Option A2" <! noAutoRefresh)+-- >        <|>...+-- >           maybe other content+-- >+-- > case r of+-- >    OptionA1 -> pageA1+-- >    OptionA2 -> pageA2+--+-- when @option A@ is clicked, the two sub-options appear with autorefresh. Only the two+-- lines are returned by the server using AJAX. but when Option A1-2 is pressed we want to+-- present other pages, so we add the noAutorefresh attribute.+--+-- NOTE: the noAutoRefresh attribute should be added to the <a/> or <form/> tags.+noAutoRefresh= [("class","_noAutoRefresh")]+ -- | does the same than autoRefresh but append the result of each request to the bottom of the widget appendUpdate  :: (MonadIO m,      FormInput v)@@ -622,6 +989,11 @@   -> View v m a prependUpdate= update "prepend" +update :: (MonadIO m,+     FormInput v)+  => B.ByteString+  -> View v m a+  -> View v m a update method w= do     id <- genNewId     st <- get@@ -633,34 +1005,35 @@                ++ "ajaxPostForm('"++id++"');"                ++ "})\n" -    r <- getParam1 ("auto"++id) $ mfEnv st           -- !> ("TIMEOUT="++ show t)+    let r= lookup ("auto"++id) $ mfEnv st           -- !> ("TIMEOUT="++ show t)     case r of-      NoParam -> do+      Nothing -> do          requires [JScript $ timeoutscript t                   ,JScript ajaxGetLink                   ,JScript ajaxPostForm                   ,JScriptFile jqueryScript [installscript]]          (ftag "div" <<< insertForm w) <! [("id",id)] 
 -      Validated (x :: String) -> View $ do+      Just sind -> View $ do          let t= mfToken st          FormElm form mr <- runView $ insertForm w          st <- get-         let HttpData ctype c s= toHttpData $ mconcat form+         let HttpData ctype c s= toHttpData $ method <> " " <> toByteString (mconcat form)+--                                            "$('#"<> B.pack id <>"')." <> method+--                                            <> "('" <> toByteString (mconcat form) <> "');"+--                                            <> "ajaxGetLink('" <> B.pack id  <> "');"+--                                            <> "ajaxPostForm('" <> B.pack id  <> "');"          liftIO . sendFlush t $ HttpData (ctype ++ ("Cache-Control", "no-cache, no-store"):mfHttpHeaders st) (mfCookies st ++ c) s-         put st{mfAutorefresh=True}+         put st{mfAutorefresh=True,inSync=True}          return $ FormElm [] mr    where -  timeoutscript t=-     "\nvar hadtimeout=false;\n\-     \setTimeout(function() {hadtimeout=true; }, "++show (t*1000)++");\n"    -- | adapted from http://www.codeproject.com/Articles/341151/Simple-AJAX-POST-Form-and-AJAX-Fetch-Link-to-Modal-  ajaxGetLink = "function ajaxGetLink(id){\n\+  ajaxGetLink = "\nfunction ajaxGetLink(id){\n\     \var id1= $('#'+id);\n\-    \var ida= $('#'+id+' a');\n\+    \var ida= $('#'+id+' a[class!=\"_noAutoRefresh\"]');\n\     \ida.click(function () {\n\     \if (hadtimeout == true) return true;\n\     \var pdata = $(this).attr('data-value');\n\@@ -670,8 +1043,13 @@     \       url: actionurl+'?bustcache='+ new Date().getTime()+'&auto'+id+'=true',\n\     \       data: pdata,\n\     \       success: function (resp) {\n\-    \         id1."++method++"(resp);\n\-    \         ajaxGetLink(id)\n\+    \            var ind= resp.indexOf(' ');\n\+    \            var dat = resp.substr(ind);\n\+    \            var method= resp.substr(0,ind);\n\+    \            if(method== 'html')id1.html(dat);\n\+    \            else if (method == 'append') id1.append(dat);\n\+    \            else id1.prepend(dat);\n\+    \            ajaxGetLink(id);\n\     \       },\n\     \       error: function (xhr, status, error) {\n\     \           var msg = $('<div>' + xhr + '</div>');\n\@@ -681,11 +1059,11 @@     \$.ajax(dialogOpts);\n\     \return false;\n\     \});\n\-  \}"+  \}\n" -  ajaxPostForm = "function ajaxPostForm(id) {\n\+  ajaxPostForm = "\nfunction ajaxPostForm(id) {\n\     \var id1= $('#'+id);\n\-    \var idform= $('#'+id+' form');\n\+    \var idform= $('#'+id+' form[class!=\"_noAutoRefresh\"]');\n\     \idform.submit(function (event) {\n\         \if (hadtimeout == true) return true;\n\         \event.preventDefault();\n\@@ -693,12 +1071,17 @@         \var url = $form.attr('action');\n\         \var pdata = $form.serialize();\n\         \$.ajax({\n\-            \type: 'GET',\n\+            \type: 'POST',\n\             \url: url,\n\             \data: 'auto'+id+'=true&'+pdata,\n\             \success: function (resp) {\n\-                \id1."++method++"(resp);\n\-                \ajaxPostForm(id)\n\+    \            var ind= resp.indexOf(' ');\n\+    \            var dat = resp.substr(ind);\n\+    \            var method= resp.substr(0,ind);\n\+    \            if(method== 'html')id1.html(dat);\n\+    \            else if (method == 'append') id1.append(dat);\n\+    \            else id1.prepend(dat);\n\+    \            ajaxPostForm(id);\n\             \},\n\             \error: function (xhr, status, error) {\n\                 \var msg = $('<div>' + xhr + '</div>');\n\@@ -707,8 +1090,13 @@         \});\n\        \});\n\       \return false;\n\-     \}"+     \}\n" +timeoutscript t=+     "\nvar hadtimeout=false;\n\+     \if("++show t++" > 0)setTimeout(function() {hadtimeout=true; }, "++show (t*1000)++");\n"++ data UpdateMethod= Append | Prepend | Html deriving Show  -- | continously execute a widget and update the content.@@ -795,8 +1183,6 @@         requires [ServerProc (procname, proc),                   JScript $ ajaxPush procname,                   JScriptFile jqueryScript [installscript]]--      (ftag "div" <<< noWidget) <! [("id",id)]       <++ ftag "div" mempty `attrs` [("id",id++"status")]
src/MFlow/Forms/XHtml.hs view
@@ -1,66 +1,66 @@------------------------------------------------------------------------------------ Module      :  Control.MessageFlow.Forms.XHtml--- Copyright   :  Alberto Gónez Corona--- License     :  BSD3------ Maintainer  :  agocorona@gmail.com--- Stability   :  experimental----------------------------------------------------------------------------------{- | Instances of `FormInput`  for  the 'Text.XHtml' module of the xhtml package--}--{-# OPTIONS -XMultiParamTypeClasses-            -XFlexibleInstances-            -XUndecidableInstances-            -XTypeSynonymInstances-            -XFlexibleContexts-            -XTypeOperators-            #-}---module MFlow.Forms.XHtml where--import MFlow (HttpData(..))-import MFlow.Forms-import MFlow.Cookies(contentHtml)-import Data.ByteString.Lazy.Char8(pack,unpack)--import Text.XHtml.Strict as X-import Control.Monad.Trans-import Data.Typeable--instance Monad m => ADDATTRS (View Html m a) where-  widget ! atrs= widget `wmodify`  \fs mx -> return ((head fs ! atrs:tail fs), mx)----instance FormInput  Html  where-    toByteString  =  pack. showHtmlFragment-    toHttpData = HttpData [contentHtml] []  . toByteString-    ftag t= tag t-    inred = X.bold ![X.thestyle "color:red"]-    finput n t v f c= X.input ! ([thetype t ,name  n, value  v] ++ if f then [checked]  else []-                              ++ case c of Just s ->[strAttr "onclick"  s]; _ -> [] )-    ftextarea name text= X.textarea ! [X.name  name] <<  text--    fselect name list = select ![ X.name  name] << list-    foption  name v msel=  X.option ! ([value  name] ++ selected msel) <<  v-            where-            selected msel = if  msel then [X.selected] else []--    attrs tag attrs = tag ! (map (\(n,v) -> strAttr  n  v)  attrs)----    formAction action form = X.form ! [X.action  action, method "post"] << form-    fromStr = stringToHtml-    fromStrNoEncode= primHtml--    flink  v str = toHtml $ hotlink  (  v) << str--instance Typeable Html where-     typeOf =  \_ -> mkTyConApp (mkTyCon3 "xhtml" "Text.XHtml.Strict" "Html") []--+-----------------------------------------------------------------------------
+--
+-- Module      :  Control.MessageFlow.Forms.XHtml
+-- Copyright   :  Alberto Gónez Corona
+-- License     :  BSD3
+--
+-- Maintainer  :  agocorona@gmail.com
+-- Stability   :  experimental
+--
+-----------------------------------------------------------------------------
+{- | Instances of `FormInput`  for  the 'Text.XHtml' module of the xhtml package
+-}
+
+{-# OPTIONS -XMultiParamTypeClasses
+            -XFlexibleInstances
+            -XUndecidableInstances
+            -XTypeSynonymInstances
+            -XFlexibleContexts
+            -XTypeOperators
+            #-}
+
+
+module MFlow.Forms.XHtml where
+
+import MFlow (HttpData(..))
+import MFlow.Forms
+import MFlow.Cookies(contentHtml)
+import Data.ByteString.Lazy.Char8(pack,unpack)
+import qualified Data.Text as T
+import Text.XHtml.Strict as X
+import Control.Monad.Trans
+import Data.Typeable
+
+instance Monad m => ADDATTRS (View Html m a) where
+  widget ! atrs= widget `wmodify`  \fs mx -> return ((head fs ! atrs:tail fs), mx)
+
+
+
+instance FormInput  Html  where
+    toByteString  =  pack. showHtmlFragment
+    toHttpData = HttpData [contentHtml] []  . toByteString
+    ftag t= tag t
+    inred = X.bold ![X.thestyle "color:red"]
+    finput n t v f c= X.input ! ([thetype t ,name  n, value  v] ++ if f then [checked]  else []
+                              ++ case c of Just s ->[strAttr "onclick"  s]; _ -> [] )
+    ftextarea name text= X.textarea ! [X.name  name] <<  T.unpack text
+
+    fselect name list = select ![ X.name  name] << list
+    foption  name v msel=  X.option ! ([value  name] ++ selected msel) <<  v
+            where
+            selected msel = if  msel then [X.selected] else []
+
+    attrs tag attrs = tag ! (map (\(n,v) -> strAttr  n  v)  attrs)
+
+
+
+    formAction action form = X.form ! [X.action  action, method "post"] << form
+    fromStr = stringToHtml
+    fromStrNoEncode= primHtml
+
+    flink  v str = toHtml $ hotlink  (  v) << str
+
+instance Typeable Html where
+     typeOf =  \_ -> mkTyConApp (mkTyCon3 "xhtml" "Text.XHtml.Strict" "Html") []
+
+
src/MFlow/Wai.hs view
@@ -38,18 +38,22 @@ import Data.Monoid
 import MFlow.Wai.Response
 import Network.Wai
-import Network.HTTP.Types hiding (urlDecode)
+import Network.HTTP.Types -- hiding (urlDecode)
 import Data.Conduit
 import Data.Conduit.Lazy
 import qualified Data.Conduit.List as CList
 import Data.CaseInsensitive
 import System.Time
-import qualified Data.Text as T
+import qualified Data.Text as T 
 
 
-flow=  "flow"
 
 
+--import Debug.Trace
+--(!>) = flip trace
+
+flow=  "flow"
+
 instance Processable Request  where
    pwfPath  env=  if Prelude.null sc then [noScript] else Prelude.map T.unpack sc
       where
@@ -62,7 +66,7 @@    
    puser env = fromMaybe anonymous $ fmap SB.unpack $ lookup ( mk $SB.pack cookieuser) $ requestHeaders env
                     
-   pind env= fromMaybe (error ": No FlowID") $ fmap SB.unpack $ lookup  (mk $ SB.pack flow) $ requestHeaders env
+   pind env= fromMaybe (error ": No FlowID") $ fmap SB.unpack $ lookup  (mk flow) $ requestHeaders env
    getParams=    mkParams1 . requestHeaders
      where
      mkParams1 = Prelude.map mkParam1
@@ -87,7 +91,7 @@ 
 waiMessageFlow  ::  Request ->  ResourceT IO Response
 waiMessageFlow req1=   do
-     let httpreq1= getParams  req1 
+     let httpreq1= requestHeaders  req1 
 
      let cookies = getCookies  httpreq1
 
@@ -97,7 +101,7 @@                      fl <- liftIO $ newFlow
                      return (fl,  [(flow,  fl, "/",Nothing):: Cookie])
                      
-{-  for state persistence in cookies 
+{-   for state persistence in cookies 
      putStateCookie req1 cookies
      let retcookies= case getStateCookie req1 of
                                 Nothing -> retcookies1
@@ -105,20 +109,24 @@ -}
 
      input <- case parseMethod $ requestMethod req1  of
-              Right POST -> if  lookup  ("Content-Type") httpreq1 == Just "application/x-www-form-urlencoded"
-                  then do
+              Right POST -> do
                    inp <- liftIO $ runResourceT (requestBody req1 $$ CList.consume)
-                   return .  urlDecode $ concatMap SB.unpack  inp
-                  else return []
+                   return . parseSimpleQuery $ SB.concat inp
+
                   
-              Right GET -> let tail1 s | s==SB.empty =s
-                               tail1 xs= SB.tail xs
-                           in return . urlDecode $  SB.unpack   . tail1 $ rawQueryString req1  --  !> (SB.unpack $ rawQueryString req1)
-              x ->  return []
-              
+                  
+              Right GET ->
+                   let tail1 s | s==SB.empty =s
+                       tail1 xs= SB.tail xs 
+                   in
+                   return . Prelude.map (\(x,y) -> (x,fromMaybe "" y)) $ queryString req1
+
+
+                                        
+               
      let req = case retcookies of
-          [] -> req1{requestHeaders=  mkParams (input ++ cookies) ++ requestHeaders req1}  -- !> "REQ"
-          _  -> req1{requestHeaders=  mkParams ((flow, flowval): input ++ cookies) ++ requestHeaders req1}  --  !> "REQ"
+          [] -> req1{requestHeaders= mkParams (input ++ cookies) ++ requestHeaders req1}  -- !> "REQ"
+          _  -> req1{requestHeaders= mkParams ((flow, flowval): input ++ cookies) ++ requestHeaders req1}  --  !> "REQ"
 
 
      (resp',th) <- liftIO $ msgScheduler req      -- !> (show $ requestHeaders req)
src/MFlow/Wai/Blaze/Html/All.hs view
@@ -15,18 +15,14 @@ module MFlow.Wai.Blaze.Html.All (
  module Data.TCache
 ,module MFlow
-,module MFlow.Wai
 ,module MFlow.Forms
 ,module MFlow.Forms.Widgets
 ,module MFlow.Forms.Blaze.Html
 ,module MFlow.Forms.Admin
-,module Network.Wai
-,module Network.Wai.Handler.Warp
 ,module Control.Applicative
---,module Text.Blaze.Internal
 ,module Text.Blaze.Html5
 ,module Text.Blaze.Html5.Attributes
-,module Control.Monad.IO.Class+,module Control.Monad.IO.Class
 ,runNavigation
 ) where
 
@@ -42,8 +38,8 @@ import Network.Wai
 import Network.Wai.Handler.Warp
 import Data.TCache
-import Text.Blaze.Internal(text)-+import Text.Blaze.Internal(text)
+
 import Control.Workflow (Workflow, unsafeIOtoWF)
 
 
@@ -52,54 +48,29 @@ import System.Environment
 import Data.Maybe(fromMaybe)
 import Data.Char(isNumber)
------ | run a transient flow (see 'transient'). The port is read from the first exectution parameter----- if no parameter, it is read from the PORT environment variable.----- if this does not exist, the port 80 is used.
---runServerTransient :: FormInput view => FlowM view IO () -> IO Bool---runServerTransient f= do
---    addMessageFlows[("", transient $ runFlow f)]---    porti <- getPort---    wait $ run porti waiMessageFlow-------- | a more grandiloquent name for runServerTransient---------- > runNavigation= runServerTransient---runNavigation :: FormInput view => FlowM view IO () -> IO Bool---runNavigation= runServerTransient----- The port is read from the first exectution parameter--- if no parameter, it is read from the PORT environment variable.--- if this does not exist, the port 80 is used.-getPort= do-    args <- getArgs-    port <- case args of-           port:xs -> return port-           _  -> do-               env <- getEnvironment-               return $ fromMaybe "80" $ lookup "PORT" env-    let porti= if and $ map isNumber port then fromIntegral $ read port-                                          else 80-    putStr "using port "-    print porti-    return porti---- | run a persistent flow. The port is read from the first exectution parameter--- if no parameter, it is read from the PORT environment variable.--- if this does not exist, the port 80 is used.-runNavigation :: String -> FlowM Html (Workflow IO) () -> IO Bool-runNavigation n f= do-    addMessageFlows[(n, runFlow f)]
-    porti <- getPort-    wait $ run porti waiMessageFlow-    
------- | a more grandiloquent synonym of runServerTransient---------- > runPersNavigation= runServer---runPersistentNavigation :: FormInput view => FlowM view (Workflow IO) () -> IO Bool
---runPersistentNavigation= runServer
 
+-- | The port is read from the first exectution parameter
+-- if no parameter, it is read from the PORT environment variable.
+-- if this does not exist, the port 80 is used.
+getPort= do
+    args <- getArgs
+    port <- case args of
+           port:xs -> return port
+           _  -> do
+               env <- getEnvironment
+               return $ fromMaybe "80" $ lookup "PORT" env
+    let porti= if and $ map isNumber port then fromIntegral $ read port
+                                          else 80
+    putStr "using port "
+    print porti
+    return porti
 
+-- | run a persistent flow. The port is read from the first exectution parameter
+-- if no parameter, it is read from the PORT environment variable.
+-- if this does not exist, the port 80 is used.
+runNavigation :: String -> FlowM Html (Workflow IO) () -> IO Bool
+runNavigation n f= do
+    addMessageFlows[(n, runFlow f)]
+    porti <- getPort
+    wait $ run porti waiMessageFlow
+    
src/MFlow/Wai/Response.hs view
@@ -11,7 +11,7 @@ import Data.Monoid
 import System.IO.Unsafe
 import Data.Map as M
---import Data.CaseInsensitive
+import Data.CaseInsensitive
 import Network.HTTP.Types
 import Control.Workflow(WFErrors(..))
 import Data.String
@@ -36,9 +36,9 @@               Nothing -> error $ "fragment of type " ++ show ( typeOf  y)  ++ " after fragment of type " ++ show ( typeOf x)
 
 
-contentHtml1= [mkparam contentHtml] -- [(mk $ SB.pack "Content-Type", SB.pack  "text/html")]
 mkParams = Prelude.map mkparam
-mkparam (x,y)= (fromString  x, fromString y)
+mkparam (x,y)= (mk  x, y)
+
 instance ToResponse TResp where
   toResponse (TResp x)= toResponse x
   toResponse (TRespR r)= toResponse r
@@ -47,13 +47,13 @@       toResponse = id
 
 instance ToResponse B.ByteString  where
-      toResponse x= responseLBS status200 contentHtml1 {-,("Content-Length",show $ B.length x) -} x
+      toResponse x= responseLBS status200 [mkparam contentHtml]  x
 
 instance ToResponse String  where
-      toResponse x= responseLBS status200 contentHtml1 {-,("Content-Length",show $ B.length x) -} $ B.pack x
+      toResponse x= responseLBS status200 [mkparam contentHtml]  $ B.pack x
 
 instance  ToResponse HttpData  where
-  toResponse (HttpData hs cookies x)= responseLBS status200 (mkParams ( hs ++ cookieHeaders cookies)) x
+  toResponse (HttpData hs cookies x)= responseLBS status200 (mkParams ( hs <> cookieHeaders cookies)) x
   toResponse (Error str)=  responseLBS status404 [("Content-Type", "text/html")] str
 
 --  toResponse $ error "FATAL ERROR: HttpData errors should not reach here: MFlow.Forms.Response.hs "