module Happstack.Server.Dialogs.Scaffold where
import Happstack.Server
import Happstack.Server.Dialogs
import Language.Haskell.TH
import Data.Char (ord)
import Data.Maybe (fromMaybe)
escapeHtml :: String -> String
escapeHtml "" = ""
escapeHtml ('\"':cs) = """ ++ escapeHtml cs
escapeHtml ('\'':cs) = "'" ++ escapeHtml cs
escapeHtml ('&' :cs) = "&" ++ escapeHtml cs
escapeHtml ('<' :cs) = "<" ++ escapeHtml cs
escapeHtml ('>' :cs) = ">" ++ escapeHtml cs
escapeHtml (c :cs) | ord c >= 160 = "&#" ++ show (ord c) ++ ";" ++ escapeHtml cs
| otherwise = c : escapeHtml cs
scaffold :: (Scaffolded a, Monad m) => String -> a -> Dlg m a
scaffold s v = showPage out inp
where out n = return $ setHeader "Content-type" "text/html" $ toResponse $
"<html><body>"
++ escapeHtml s ++ "<br><hr>"
++ "<form>"
++ render "dlg-vals" v
++ "<input type=\"hidden\""
++ " name=\"dlg-dlgid\""
++ " value=\"" ++ show n ++ "\">"
++ "<input type=\"submit\" value=\"Submit\">"
++ "<script type=\"text/javascript\">"
++ " document.forms[0].elements[0].focus();"
++ "</script>"
++ "</form>"
++ "</html></body>"
inp = parse "dlg-vals"
class Scaffolded a where
render :: String -> a -> String
parse :: Monad m => String -> ServerPartT m a
instance Scaffolded () where
render _ () = ""
parse _ = return ()
instance Scaffolded String where
render pfx s = "<input type=\"text\" name=\"" ++ pfx ++ "\" value=\"" ++ s ++ "\">"
parse pfx = fmap (fromMaybe "") $ getDataFn (look pfx)
instance Scaffolded Bool where
render pfx v = "<input type=\"checkbox\" name=\"" ++ pfx ++ "\" value=\"True\" "
++ if v then "checked" else "" ++ ">"
parse pfx = fmap (maybe False (const True)) $ getDataFn (look pfx)
instance Scaffolded Int where
render pfx s = render pfx (show s)
parse pfx = fmap read $ parse pfx
instance (Scaffolded a, Scaffolded b) => Scaffolded (a, b) where
render pfx (x,y) = render (pfx ++ "_1") x
++ "<br>"
++ render (pfx ++ "_2") y
parse pfx = do x <- parse (pfx ++ "_1")
y <- parse (pfx ++ "_2")
return (x,y)
instance (Scaffolded a, Scaffolded b, Scaffolded c)
=> Scaffolded (a, b, c) where
render pfx (x,y,z) = render (pfx ++ "_1") x
++ "<br>"
++ render (pfx ++ "_2") y
++ "<br>"
++ render (pfx ++ "_3") z
parse pfx = do x <- parse (pfx ++ "_1")
y <- parse (pfx ++ "_2")
z <- parse (pfx ++ "_3")
return (x,y,z)