Merge branch 'master' of gitlab.cip.ifi.lmu.de:jost/UniWorX

This commit is contained in:
SJost 2018-04-03 16:50:18 +02:00
commit 74dc1d52de
5 changed files with 48 additions and 19 deletions

View File

@ -1,6 +1,7 @@
SummerTerm year@Integer: Sommersemester #{tshow year} SummerTerm year@Integer: Sommersemester #{tshow year}
WinterTerm year@Integer: Wintersemester #{tshow year}/#{tshow $ succ year} WinterTerm year@Integer: Wintersemester #{tshow year}/#{tshow $ succ year}
PSLimitNonPositive: “pagesize” muss größer als null sein PSLimitNonPositive: “pagesize” muss größer als null sein
Page n@Int64 num@Int64: Seite #{tshow n} von #{tshow num}
TermEdited tid@TermIdentifier: Semester #{termToText tid} erfolgreich editiert. TermEdited tid@TermIdentifier: Semester #{termToText tid} erfolgreich editiert.
TermNewTitle: Semester editiere/anlegen. TermNewTitle: Semester editiere/anlegen.
InvalidInput: Eingaben bitte korrigieren. InvalidInput: Eingaben bitte korrigieren.

View File

@ -30,7 +30,7 @@ getTermShowR = do
-- --
let let
termData = E.from $ \term -> do termData = E.from $ \term -> do
E.orderBy [E.desc $ term E.^. TermStart ] -- E.orderBy [E.desc $ term E.^. TermStart ]
let courseCount :: E.SqlExpr (E.Value Int) let courseCount :: E.SqlExpr (E.Value Int)
courseCount = E.sub_select . E.from $ \course -> do courseCount = E.sub_select . E.from $ \course -> do
E.where_ $ term E.^. TermId E.==. course E.^. CourseTermId E.where_ $ term E.^. TermId E.==. course E.^. CourseTermId

View File

@ -3,30 +3,51 @@
, RecordWildCards , RecordWildCards
, OverloadedStrings , OverloadedStrings
, TemplateHaskell , TemplateHaskell
, QuasiQuotes
, LambdaCase , LambdaCase
, ViewPatterns , ViewPatterns
#-} #-}
module Handler.Utils.Table.Pagination where module Handler.Utils.Table.Pagination
( SortColumn(..), SortDirection(..)
, DBTable(..)
, PaginationSettings(..)
, PSValidator(..)
, dbTable
) where
import Import import Import
import qualified Database.Esqueleto as E import qualified Database.Esqueleto as E
import qualified Database.Esqueleto.Internal.Sql as E (SqlSelect) import qualified Database.Esqueleto.Internal.Sql as E (SqlSelect)
import Text.Blaze (Attribute) import Text.Blaze (Attribute)
import qualified Text.Blaze.Html5.Attributes as Html5
import Data.CaseInsensitive (CI)
import qualified Data.CaseInsensitive as CI
import Control.Monad.RWS hiding ((<>), Foldable(..), mapM_) import Control.Monad.RWS hiding ((<>), Foldable(..), mapM_)
import Data.Map (Map) import Data.Map (Map, (!))
import Colonnade hiding (bool, fromMaybe) import Colonnade hiding (bool, fromMaybe)
import Yesod.Colonnade import Yesod.Colonnade
import Text.Hamlet (hamletFile) import Text.Hamlet (hamletFile)
import Data.Ratio ((%))
data SortColumn = forall a. PersistField a => SortColumn { getSortColumn :: E.SqlExpr (E.Value a) } data SortColumn = forall a. PersistField a => SortColumn { getSortColumn :: E.SqlExpr (E.Value a) }
data SortDirection = SortAsc | SortDesc data SortDirection = SortAsc | SortDesc
deriving (Eq, Ord, Enum, Show, Read) deriving (Eq, Ord, Enum, Show, Read)
instance PathPiece SortDirection where
toPathPiece SortAsc = "asc"
toPathPiece SortDesc = "desc"
fromPathPiece (CI.mk -> t)
| t == "asc" = Just SortAsc
| t == "desc" = Just SortDesc
| otherwise = Nothing
sqlSortDirection :: (SortColumn, SortDirection) -> E.SqlExpr E.OrderBy sqlSortDirection :: (SortColumn, SortDirection) -> E.SqlExpr E.OrderBy
sqlSortDirection (SortColumn e, SortAsc ) = E.asc e sqlSortDirection (SortColumn e, SortAsc ) = E.asc e
@ -45,7 +66,7 @@ data DBTable = forall a r h i.
} }
data PaginationSettings = PaginationSettings data PaginationSettings = PaginationSettings
{ psSorting :: [(SortColumn, SortDirection)] { psSorting :: [(Text, SortDirection)]
, psLimit :: Int64 , psLimit :: Int64
, psPage :: Int64 , psPage :: Int64
, psShortcircuit :: Bool , psShortcircuit :: Bool
@ -74,23 +95,21 @@ dbTable :: PSValidator -> DBTable -> Handler Widget
dbTable PSValidator{..} DBTable{ dbtIdent = (toPathPiece -> dbtIdent), .. } = do dbTable PSValidator{..} DBTable{ dbtIdent = (toPathPiece -> dbtIdent), .. } = do
let let
sortingOptions = mkOptionList sortingOptions = mkOptionList
[ Option t' (c, d) t' [ Option t' (t, d) t'
| (t, c) <- mapToList dbtSorting | (t, _) <- mapToList dbtSorting
, d <- [SortAsc, SortDesc] , d <- [SortAsc, SortDesc]
, let t' = t <> "-" <> tshow d , let t' = t <> "-" <> toPathPiece d
] ]
sortingField = Field parse (\_ _ _ _ _ -> return ()) UrlEncoded
where
parse optlist _ = case mapM (olReadExternal sortingOptions) optlist of
Nothing -> return $ Left "Error parsing values"
Just res -> return $ Right $ Just res
(_, defPS) = runPSValidator Nothing (_, defPS) = runPSValidator Nothing
wIdent n wIdent n
| not $ null dbtIdent = dbtIdent <> "-" <> n | not $ null dbtIdent = dbtIdent <> "-" <> n
| otherwise = n | otherwise = n
dbtAttrs'
| not $ null dbtIdent = Html5.id (fromString $ unpack dbtIdent) <> dbtAttrs
| otherwise = dbtAttrs
psResult <- runInputGetResult $ PaginationSettings psResult <- runInputGetResult $ PaginationSettings
<$> ireq sortingField (wIdent "sorting") <$> ireq (multiSelectField $ return sortingOptions) (wIdent "sorting")
<*> (fromMaybe (psLimit defPS) <$> iopt intField (wIdent "pagesize")) <*> (fromMaybe (psLimit defPS) <$> iopt intField (wIdent "pagesize"))
<*> (fromMaybe (psPage defPS) <$> iopt intField (wIdent "page")) <*> (fromMaybe (psPage defPS) <$> iopt intField (wIdent "page"))
<*> ireq checkBoxField (wIdent "table-only") <*> ireq checkBoxField (wIdent "table-only")
@ -105,17 +124,22 @@ dbTable PSValidator{..} DBTable{ dbtIdent = (toPathPiece -> dbtIdent), .. } = do
FormSuccess ps -> runPSValidator $ Just ps FormSuccess ps -> runPSValidator $ Just ps
FormFailure errs -> first (map SomeMessage errs <>) $ runPSValidator Nothing FormFailure errs -> first (map SomeMessage errs <>) $ runPSValidator Nothing
FormMissing -> runPSValidator Nothing FormMissing -> runPSValidator Nothing
psSorting' = map (first (dbtSorting !)) psSorting
sqlQuery' = dbtSQLQuery sqlQuery' = dbtSQLQuery
<* E.orderBy (map sqlSortDirection psSorting) <* E.orderBy (map sqlSortDirection psSorting')
<* E.limit psLimit <* E.limit psLimit
<* E.offset (psPage * psLimit) <* E.offset (psPage * psLimit)
mapM_ (addMessageI "warning") errs mapM_ (addMessageI "warning") errs
rows <- runDB $ E.select sqlQuery' (rows, [E.Value rowCount]) <- runDB $ (,) <$> E.select sqlQuery' <*> E.select (E.countRows <$ dbtSQLQuery :: E.SqlQuery (E.SqlExpr (E.Value Int64)))
bool return (sendResponse <=< tblLayout) psShortcircuit $ do bool return (sendResponse <=< tblLayout) psShortcircuit $ do
encodeCellTable dbtAttrs dbtColonnade rows let table = encodeCellTable dbtAttrs' dbtColonnade rows
pageCount = max 1 . ceiling $ rowCount % psLimit
$(widgetFile "table-layout")
where where
tblLayout :: Widget -> Handler Html tblLayout :: Widget -> Handler Html
tblLayout = widgetToPageContent >=> (\tbl -> withUrlRenderer $(hamletFile "templates/table-layout.hamlet")) tblLayout tbl' = do
tbl <- widgetToPageContent tbl'
withUrlRenderer $(hamletFile "templates/table-layout-wrapper.hamlet")

View File

@ -0,0 +1 @@
^{pageBody tbl}

View File

@ -1 +1,4 @@
^{pageBody tbl} <div .table>
^{table}
<p style="text-align:center">
_{MsgPage (succ psPage) pageCount}