module View where import Misc import Data.List import Happstack.Server.HTTP.Types (Request) import qualified Data.ByteString.Char8 as B import Data.Char import Control.Monad.Reader import Text.StringTemplate.Helpers import Data.Maybe import StateVersions.AppState1 import Happstack.Helpers -- Notice, there are no Happstack.* imports -- Idea is, view is meant to be used from controller. -- :browse View in ghci should reveal there's no IO for any of these function sigs. {- RenderGlobals is essentially just a cute wrapper around a triple meant to pass along the set of templates, the SessionData which is stored in a cookie when the user has logged in, and the actual Request made. -} data RenderGlobals = RenderGlobals { origrq :: Request , templates :: STDirGroups String , mbSession :: Maybe SessionData } deriving Show mbUser :: RenderGlobals -> Maybe UserName mbUser = fmap sesUser . mbSession tutlayout :: RenderGlobals -> [(String, String)] -> String -> String tutlayout (RenderGlobals rq ts' mbSess) attrs tmpl0 = let ts = getTemplateGroup "." ts' tmpl = cleanTemplateName tmpl0 mbU = fmap sesUser mbSess rendertut :: [(String,String)] -> String -> String rendertut = renderTemplateGroup ts -- should use readM, or whatever it's called, from Data.Safe --readtut :: (Monad m, Read a) => String -> m a readtut file = (Misc.safeRead . rendertut [] . concatMap escapequote $ file) where escapequote char = if char=='"' then "\\\"" else [char] readTutTuples :: String -> [(String,String)] readTutTuples f = either (const [("readTutTuples error","")]) id (readtut f :: Either String [(String,String)] ) attrsL = maybe attrs ( \user -> ("loggedInUser",B.unpack . unusername $ user) : attrs ) mbU content = rendertut attrsL tmpl header = rendertut [("menubarMenu",menubarMenu),("userMenu",userMenu),("mainUserMenu",mainUserMenu)] "header" where userMenu = maybe ( rendertut attrsL "login" ) ( \user -> hMenuBars rq [("/tutorial/logout","logout " ++ (B.unpack . unusername $ user)) , ("/tutorial/changepassword","change password")] ) mbU mainUserMenu = if isJust mbU then hMenuBars rq $ readTutTuples "mainusermenu" else "" menubarMenu = hMenuBars rq $ readTutTuples "menubarmenu" tocArea = vMenuOL rq $ readTutTuples "toc" in rendertut [("tocarea",tocArea) ,("contentarea",content) ,("headerarea",header)] "base" cleanTemplateName :: String -> String cleanTemplateName = filter isAlpha paintblurb :: String -> String paintblurb = newlinesToHtmlLines paintProfile :: RenderGlobals -> String -> UserProfile -> String -> String paintProfile rglobs user cp userimagepath = let ts = getTemplateGroup "." . templates $ rglobs attrs = [("username",user) , ("userimage", userimagepath ) , ("blurb",newlinesToHtmlLines . B.unpack . blurb $ cp) , ("contact", newlinesToHtmlLines . B.unpack . contact $ cp)] in renderTemplateGroup ts attrs "consultantprofile" paintUserJobsTable :: B.ByteString -> [(JobName, Job)] -> String paintUserJobsTable postedBy rsUserJobs = let jobCells = map ( \( JobName j', Job _ _) -> let j = B.unpack j' in [ joblink postedBy j , simpleLink ("/tutorial/editjob?user="++ B.unpack postedBy ++"&job=" ++ j,"edit") , simpleLink ("/tutorial/deletejob?user="++ B.unpack postedBy ++"&job=" ++ j,"delete") ] ) rsUserJobs in paintTable Nothing jobCells Nothing -- no pagination for now joblink :: B.ByteString -> String -> String joblink postedBy j = simpleLink ("/tutorial/viewjob?user="++B.unpack postedBy++"&job=" ++ j,j) userlink :: B.ByteString -> String userlink pBy = simpleLink ("/tutorial/viewprofile?user=" ++ B.unpack pBy, B.unpack pBy) paintjob :: RenderGlobals -> UserName -> (JobName, Job) -> String paintjob rglobs (UserName pBy) (JobName jN, Job jBud jBlu) = let ts = getTemplateGroup "." . templates $ rglobs attrs = [ ("username",B.unpack pBy) , ("jobname",B.unpack jN) , ("budget",B.unpack jBud) , ("jobblurb",B.unpack jBlu) , ("postedBy",userlink pBy)] in renderTemplateGroup ts attrs "job"