packages feed

RESTng-0.1: Example/Search.hs

module Search where

import Prelude hiding (div,span)
import Data.List (intersperse)
import Control.Monad (liftM, liftM2)
import Text.ParserCombinators.Parsec (parse)
import Database.HDBC (SqlValue, toSql)

import Text.CxML hiding (title)
import Text.YuiGrid

import RESTng.RqHandlers
import RESTng.System

import Resource
import InLineCSS
import Common (authorsShow, withTitleBox)
import Tags (booksShow)


searchForm :: CxML RequestContext
searchForm
           = form!("method","post")!("action","/search.html")
                /- [
                    textfield "search", 
                    button!("name","action")!("value","submit") /- [t "Search"]
                   ]

searchHandler :: RqHandlerT RESTng RESTngResp
searchHandler = --withDocName "search" $ withQueryField "search" $ \q ->
                withDocName "search" $ withPostField "search" $ \q ->
               okBoxesM [
                         return $ bigText $ smallMarginBottomCSS $ nearTop $ boxInMain $ t ("Found it in: "),

                         liftM (nearLeft . setColumnsVote 2 . commonLayoutHints) $ tagsMatchingBox q,
                         liftM (nearRight . setColumnsVote 2 . commonLayoutHints) $ booksMatchingBox q,
                         liftM (nearBottom . commonLayoutHints) $ authorsMatchingBox q
                        ]
             where
               commonLayoutHints = smallMarginBottomCSS . giveBorderCSS . inMain

-------------------------------
---------- Tags matching  -----
-------------------------------
tagsMatchingBox :: String -> RESTng (GridElement RequestContext)
tagsMatchingBox s = do tagListCxML <- listingResource exampleAppTagProxy [("tag",s)] []
                       return $ withTitleBox "Tags matching:" tagListCxML


-------------------------------
------ Books matching  -----
-------------------------------
booksMatchingBox :: String -> RESTng (GridElement RequestContext)
booksMatchingBox s = 
                         do books <- booksMatchingData s
                            return $ withTitleBox "Books matching:" $ toBox (booksShow books)


booksMatchingData :: String -> RESTng [Book]
booksMatchingData s = liftHDBC_0 $ runQueryN sqlRecordParser (booksMatchingQuery s)

booksMatchingQuery :: String -> SqlCommand
booksMatchingQuery s =    addCriterium (inBookExpr `or_` inAuthorExpr) $
                              sqlSelect [] [] bookProxy
                          where
                             inBookExpr = caseInsensitiveSearchExpr ["title"] s
                             inAuthorExpr = (tableName authorProxy ++ "_id") `in_` 
                                               (projectJustAttrs ["DISTINCT id"] $ authorsMatchingQuery s)

-------------------------------
------ Authors matching  -----
-------------------------------
authorsMatchingBox :: String -> RESTng (GridElement RequestContext)
authorsMatchingBox s =  do authors <- authorsMatchingData s
                           return $ withTitleBox "Authors:" $ toBox (authorsShow authors)

authorsMatchingData :: String -> RESTng [Author]
authorsMatchingData s = liftHDBC_0 $ runQueryN sqlRecordParser (authorsMatchingQuery s)
-- FIXME: in order to be more DRY, do some runQueryN' such that
-- authorsMatchingData s = runQueryN' (authorsMatchingQuery s)
-- so the function has type
-- runQueryN' :: SqlRecord a => SqlCommand -> RESTng [a]


authorsMatchingQuery :: String -> SqlCommand
authorsMatchingQuery s = addCriterium (caseInsensitiveSearchExpr ["name"] s) $
                            sqlSelect [] [] authorProxy

--FIXME: can search authors related to authorships containing s here also.