module Yesod.TableView
(
TableView(..),
defTableView,
tableView,
module Yesod.TableView.Widget
)
where
import Control.Monad
import Text.Cassius
import Text.Hamlet
import Yesod
import Yesod.TableView.NumEntriesForm
import Yesod.TableView.Widget
data TableView s val =
TableView {
tableFilter :: [Filter val],
tableId :: String,
tableOrder :: [Order val],
tableRoute :: Int -> Int -> Route s,
tableShowHead :: Bool,
tableStyled :: Bool,
tableCurrentLimit :: Int,
tableCurrentOffset :: Int,
tableLimitPrompt :: String,
tableLimits :: [Int],
tableMinLimit :: Maybe Int,
tableMaxLimit :: Maybe Int
}
defTableView :: TableView s val
defTableView =
TableView { tableFilter = [],
tableId = undefined,
tableOrder = [],
tableRoute = undefined,
tableShowHead = True,
tableStyled = True,
tableCurrentLimit = undefined,
tableCurrentOffset = undefined,
tableLimitPrompt = "Number of entries per page:",
tableLimits = [10, 20, 50, 100],
tableMinLimit = Just 10,
tableMaxLimit = Just 100 }
clamp :: Ord a => Maybe a -> Maybe a -> a -> a
clamp mMin mMax = maybe id max mMin . maybe id min mMax
tableView :: forall s sub val.
( PersistBackend (YesodDB s (GGHandler sub s IO)),
PersistEntity val,
TableViewWidget val,
YesodPersist s) =>
TableView s val -> GHandler sub s (GWidget sub s ())
tableView cfg'@(TableView {
tableFilter = filters,
tableOrder = orders,
tableLimitPrompt = limitPrompt,
tableLimits = limitOpts,
tableRoute = thisRoute,
tableShowHead = showHead,
tableStyled = styled,
tableCurrentLimit = limit',
tableCurrentOffset = offset',
tableMinLimit = minLimit,
tableMaxLimit = maxLimit
}) = do
let minOffset = Just 0
maxOffset = Nothing
let limit = clamp minLimit maxLimit limit'
offset = clamp minOffset maxOffset offset'
prevOffset = clamp minOffset maxOffset (offset limit)
nextOffset = clamp minOffset maxOffset (offset + limit)
(entries, numEntries) <-
runDB $ liftM2 (,) (selectList filters orders limit offset) (count filters)
numEntriesWidget <- runNumEntriesForm
styled limitPrompt limitOpts limit (`thisRoute` offset)
let lastOffset = (numEntries 1) `div` limit * limit
return $ do
let entryRows = mapM_ row (zip [0..] entries)
firstRoute = guard (offset > 0) >> Just (thisRoute limit 0)
lastRoute = guard (offset < lastOffset) >>
Just (thisRoute limit lastOffset)
forwardRoute = guard (nextOffset < numEntries) >>
Just (thisRoute limit nextOffset)
backRoute = guard (offset > 0) >>
Just (thisRoute limit prevOffset)
mHeader = guard showHead >> Just (tableHeader (undefined :: val))
when styled $ addCassius $(cassiusFile "templates/tableview.cassius")
addWidget $(hamletFile "templates/tableview.hamlet")
where
row :: (Int, (Key val, val)) -> GWidget sub s ()
row (ix, (entryId, entry)) =
let rowClass = if even ix then "even-row" else "odd-row"
entryWidget = tableRecord ix entryId entry
in addWidget $(hamletFile "templates/tableview-row.hamlet")