feat(allocations): show table of all allocations
Cleanup imports & pageactions
This commit is contained in:
parent
440f0a97d0
commit
d621e61b11
@ -226,6 +226,8 @@ CourseAllocationCapacityMayNotBeChanged: Kapazität eines Kurses, der an einer Z
|
|||||||
|
|
||||||
CourseLecturerRightsIdentical: Alle Sorten von Kursverwalter haben identische Rechte.
|
CourseLecturerRightsIdentical: Alle Sorten von Kursverwalter haben identische Rechte.
|
||||||
|
|
||||||
|
School: Institut
|
||||||
|
|
||||||
NoSuchTerm tid@TermId: Semester #{tid} gibt es nicht.
|
NoSuchTerm tid@TermId: Semester #{tid} gibt es nicht.
|
||||||
NoSuchSchool ssh@SchoolId: Institut #{ssh} gibt es nicht.
|
NoSuchSchool ssh@SchoolId: Institut #{ssh} gibt es nicht.
|
||||||
NoSuchCourseShorthand csh@CourseShorthand: Kein Kurs mit Kürzel #{csh} bekannt.
|
NoSuchCourseShorthand csh@CourseShorthand: Kein Kurs mit Kürzel #{csh} bekannt.
|
||||||
@ -962,6 +964,7 @@ MenuHelp: Hilfe
|
|||||||
MenuProfile: Anpassen
|
MenuProfile: Anpassen
|
||||||
MenuLogin: Login
|
MenuLogin: Login
|
||||||
MenuLogout: Logout
|
MenuLogout: Logout
|
||||||
|
MenuAllocationList: Zentralanmeldungen
|
||||||
MenuCourseList: Kurse
|
MenuCourseList: Kurse
|
||||||
MenuCourseMembers: Kursteilnehmer
|
MenuCourseMembers: Kursteilnehmer
|
||||||
MenuCourseAddMembers: Kursteilnehmer hinzufügen
|
MenuCourseAddMembers: Kursteilnehmer hinzufügen
|
||||||
@ -1466,6 +1469,7 @@ MailSchoolLecturerInviteHeading school@SchoolName: Einladung zum Dozent für „
|
|||||||
SchoolLecturerInviteExplanation: Sie wurden eingeladen, Dozent für ein Institut zu sein. Sie können, nachdem Sie die Einladung annehmen, eigenständig neue Kurse anlegen.
|
SchoolLecturerInviteExplanation: Sie wurden eingeladen, Dozent für ein Institut zu sein. Sie können, nachdem Sie die Einladung annehmen, eigenständig neue Kurse anlegen.
|
||||||
SchoolLecturerInvitationAccepted school@SchoolName: Einladung zum Dozent für „#{school}“ angenommen
|
SchoolLecturerInvitationAccepted school@SchoolName: Einladung zum Dozent für „#{school}“ angenommen
|
||||||
|
|
||||||
|
AllocationName: Name
|
||||||
AllocationTitle termText@Text ssh'@SchoolShorthand allocation@AllocationName: #{termText} - #{ssh'}: #{allocation}
|
AllocationTitle termText@Text ssh'@SchoolShorthand allocation@AllocationName: #{termText} - #{ssh'}: #{allocation}
|
||||||
AllocationShortTitle termText@Text ssh'@SchoolShorthand ash@AllocationShorthand: #{termText} - #{ssh'} - #{ash}
|
AllocationShortTitle termText@Text ssh'@SchoolShorthand ash@AllocationShorthand: #{termText} - #{ssh'} - #{ash}
|
||||||
AllocationDescription: Beschreibung
|
AllocationDescription: Beschreibung
|
||||||
@ -1507,4 +1511,6 @@ ApplicationRatingCommentInvisibleTip: Dient zunächst nur als Notiz für Kursver
|
|||||||
|
|
||||||
AllocationSchoolShort: Institut
|
AllocationSchoolShort: Institut
|
||||||
Allocation: Zentralanmeldung
|
Allocation: Zentralanmeldung
|
||||||
AllocationRegisterTo: Anmeldungen bis
|
AllocationRegisterTo: Anmeldungen bis
|
||||||
|
|
||||||
|
AllocationListTitle: Zentralanmeldungen
|
||||||
1
routes
1
routes
@ -80,6 +80,7 @@
|
|||||||
/school SchoolListR GET !development
|
/school SchoolListR GET !development
|
||||||
/school/#SchoolId SchoolShowR GET !development
|
/school/#SchoolId SchoolShowR GET !development
|
||||||
|
|
||||||
|
/allocation/ AllocationListR GET !free
|
||||||
/allocation/#TermId/#SchoolId/#AllocationShorthand AllocationR:
|
/allocation/#TermId/#SchoolId/#AllocationShorthand AllocationR:
|
||||||
/ AShowR GET !free
|
/ AShowR GET !free
|
||||||
/register ARegisterR POST !time
|
/register ARegisterR POST !time
|
||||||
|
|||||||
@ -64,8 +64,6 @@ import qualified Yesod.Core.Types as Yesod (Logger(..))
|
|||||||
|
|
||||||
import qualified Data.HashMap.Strict as HashMap
|
import qualified Data.HashMap.Strict as HashMap
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Data.Proxy
|
import Data.Proxy
|
||||||
|
|
||||||
import qualified Data.Aeson as Aeson
|
import qualified Data.Aeson as Aeson
|
||||||
|
|||||||
@ -10,7 +10,6 @@ module Auth.LDAP
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Import.NoFoundation hiding (userEmail, userDisplayName)
|
import Import.NoFoundation hiding (userEmail, userDisplayName)
|
||||||
import Control.Lens
|
|
||||||
import Network.Connection
|
import Network.Connection
|
||||||
|
|
||||||
import Data.CaseInsensitive (CI)
|
import Data.CaseInsensitive (CI)
|
||||||
|
|||||||
19
src/Colonnade/Instances.hs
Normal file
19
src/Colonnade/Instances.hs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||||
|
|
||||||
|
module Colonnade.Instances
|
||||||
|
(
|
||||||
|
) where
|
||||||
|
|
||||||
|
import ClassyPrelude
|
||||||
|
|
||||||
|
import Control.Lens.Indexed (FunctorWithIndex(imap))
|
||||||
|
|
||||||
|
import Colonnade.Encode (Colonnade(..), OneColonnade(..))
|
||||||
|
|
||||||
|
instance Functor h => FunctorWithIndex (Maybe a) (Colonnade h a) where
|
||||||
|
imap f (Colonnade ones) = Colonnade $ dimapColonnade' <$> ones
|
||||||
|
where
|
||||||
|
dimapColonnade' OneColonnade{..} = OneColonnade
|
||||||
|
{ oneColonnadeEncode = \x -> f (Just x) $ oneColonnadeEncode x
|
||||||
|
, oneColonnadeHead = f Nothing <$> oneColonnadeHead
|
||||||
|
}
|
||||||
@ -65,7 +65,6 @@ import Control.Monad.Memo.Class (MonadMemo(..), for4)
|
|||||||
import qualified Control.Monad.Catch as C
|
import qualified Control.Monad.Catch as C
|
||||||
|
|
||||||
import Handler.Utils.StudyFeatures
|
import Handler.Utils.StudyFeatures
|
||||||
import Utils.Lens
|
|
||||||
import Utils.Form
|
import Utils.Form
|
||||||
import Utils.Sheet
|
import Utils.Sheet
|
||||||
import Utils.SystemMessage
|
import Utils.SystemMessage
|
||||||
@ -1742,10 +1741,11 @@ instance YesodBreadcrumbs UniWorX where
|
|||||||
|
|
||||||
breadcrumb (TermSchoolCourseListR tid ssh) = return (original $ unSchoolKey ssh, Just $ TermCourseListR tid)
|
breadcrumb (TermSchoolCourseListR tid ssh) = return (original $ unSchoolKey ssh, Just $ TermCourseListR tid)
|
||||||
|
|
||||||
|
breadcrumb AllocationListR = return ("Zentralanmeldungen", Just HomeR)
|
||||||
breadcrumb (AllocationR tid ssh ash AShowR) = do
|
breadcrumb (AllocationR tid ssh ash AShowR) = do
|
||||||
mr <- getMessageRender
|
mr <- getMessageRender
|
||||||
Entity _ Allocation{allocationName} <- runDB . getBy404 $ TermSchoolAllocationShort tid ssh ash
|
Entity _ Allocation{allocationName} <- runDB . getBy404 $ TermSchoolAllocationShort tid ssh ash
|
||||||
return ([st|#{allocationName} (#{mr (ShortTermIdentifier (unTermKey tid))}, #{original (unSchoolKey ssh)})|], Just $ HomeR)
|
return ([st|#{allocationName} (#{mr (ShortTermIdentifier (unTermKey tid))}, #{original (unSchoolKey ssh)})|], Just $ AllocationListR)
|
||||||
breadcrumb (AllocationR tid ssh ash (AApplicationR _)) = return ("Bewerbung", Just $ AllocationR tid ssh ash AShowR)
|
breadcrumb (AllocationR tid ssh ash (AApplicationR _)) = return ("Bewerbung", Just $ AllocationR tid ssh ash AShowR)
|
||||||
|
|
||||||
breadcrumb CourseListR = return ("Kurse" , Nothing)
|
breadcrumb CourseListR = return ("Kurse" , Nothing)
|
||||||
@ -1964,35 +1964,11 @@ pageActions (HomeR) =
|
|||||||
, menuItemModal = False
|
, menuItemModal = False
|
||||||
, menuItemAccessCallback' = return True
|
, menuItemAccessCallback' = return True
|
||||||
}
|
}
|
||||||
, MenuItem
|
|
||||||
{ menuItemType = PageActionPrime
|
|
||||||
, menuItemLabel = MsgAdminHeading
|
|
||||||
, menuItemIcon = Just "screwdriver"
|
|
||||||
, menuItemRoute = SomeRoute AdminR
|
|
||||||
, menuItemModal = False
|
|
||||||
, menuItemAccessCallback' = return True
|
|
||||||
}
|
|
||||||
, MenuItem
|
|
||||||
{ menuItemType = PageActionPrime
|
|
||||||
, menuItemLabel = MsgAdminFeaturesHeading
|
|
||||||
, menuItemIcon = Nothing
|
|
||||||
, menuItemRoute = SomeRoute AdminFeaturesR
|
|
||||||
, menuItemModal = False
|
|
||||||
, menuItemAccessCallback' = return True
|
|
||||||
}
|
|
||||||
, MenuItem
|
, MenuItem
|
||||||
{ menuItemType = PageActionPrime
|
{ menuItemType = PageActionPrime
|
||||||
, menuItemLabel = MsgMenuMessageList
|
, menuItemLabel = MsgMenuAllocationList
|
||||||
, menuItemIcon = Nothing
|
, menuItemIcon = Nothing
|
||||||
, menuItemRoute = SomeRoute MessageListR
|
, menuItemRoute = SomeRoute AllocationListR
|
||||||
, menuItemModal = False
|
|
||||||
, menuItemAccessCallback' = return True
|
|
||||||
}
|
|
||||||
, MenuItem
|
|
||||||
{ menuItemType = PageActionPrime
|
|
||||||
, menuItemLabel = MsgMenuAdminErrMsg
|
|
||||||
, menuItemIcon = Nothing
|
|
||||||
, menuItemRoute = SomeRoute AdminErrMsgR
|
|
||||||
, menuItemModal = False
|
, menuItemModal = False
|
||||||
, menuItemAccessCallback' = return True
|
, menuItemAccessCallback' = return True
|
||||||
}
|
}
|
||||||
@ -2016,20 +1992,12 @@ pageActions (AdminR) =
|
|||||||
}
|
}
|
||||||
, MenuItem
|
, MenuItem
|
||||||
{ menuItemType = PageActionPrime
|
{ menuItemType = PageActionPrime
|
||||||
, menuItemLabel = MsgErrMsgHeading
|
, menuItemLabel = MsgMenuAdminErrMsg
|
||||||
, menuItemIcon = Nothing
|
, menuItemIcon = Nothing
|
||||||
, menuItemRoute = SomeRoute AdminErrMsgR
|
, menuItemRoute = SomeRoute AdminErrMsgR
|
||||||
, menuItemModal = False
|
, menuItemModal = False
|
||||||
, menuItemAccessCallback' = return True
|
, menuItemAccessCallback' = return True
|
||||||
}
|
}
|
||||||
, MenuItem
|
|
||||||
{ menuItemType = PageActionPrime
|
|
||||||
, menuItemLabel = MsgMenuUsers
|
|
||||||
, menuItemIcon = Nothing
|
|
||||||
, menuItemRoute = SomeRoute UsersR
|
|
||||||
, menuItemModal = False
|
|
||||||
, menuItemAccessCallback' = return True
|
|
||||||
}
|
|
||||||
, MenuItem
|
, MenuItem
|
||||||
{ menuItemType = PageActionSecondary
|
{ menuItemType = PageActionSecondary
|
||||||
, menuItemLabel = MsgMenuAdminTest
|
, menuItemLabel = MsgMenuAdminTest
|
||||||
@ -2185,6 +2153,14 @@ pageActions (CourseListR) =
|
|||||||
, menuItemModal = False
|
, menuItemModal = False
|
||||||
, menuItemAccessCallback' = return True
|
, menuItemAccessCallback' = return True
|
||||||
}
|
}
|
||||||
|
, MenuItem
|
||||||
|
{ menuItemType = PageActionPrime
|
||||||
|
, menuItemLabel = MsgMenuAllocationList
|
||||||
|
, menuItemIcon = Nothing
|
||||||
|
, menuItemRoute = SomeRoute AllocationListR
|
||||||
|
, menuItemModal = False
|
||||||
|
, menuItemAccessCallback' = return True
|
||||||
|
}
|
||||||
]
|
]
|
||||||
pageActions (CourseNewR) = [
|
pageActions (CourseNewR) = [
|
||||||
MenuItem
|
MenuItem
|
||||||
|
|||||||
@ -8,8 +8,6 @@ import Data.Aeson.Encode.Pretty (encodePrettyToTextBuilder)
|
|||||||
import Control.Monad.Trans.Except
|
import Control.Monad.Trans.Except
|
||||||
import Control.Monad.Trans.Writer (mapWriterT)
|
import Control.Monad.Trans.Writer (mapWriterT)
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
-- import Data.Time
|
-- import Data.Time
|
||||||
import Data.Char (isDigit)
|
import Data.Char (isDigit)
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
|
|||||||
@ -5,3 +5,4 @@ module Handler.Allocation
|
|||||||
import Handler.Allocation.Show as Handler.Allocation
|
import Handler.Allocation.Show as Handler.Allocation
|
||||||
import Handler.Allocation.Application as Handler.Allocation
|
import Handler.Allocation.Application as Handler.Allocation
|
||||||
import Handler.Allocation.Register as Handler.Allocation
|
import Handler.Allocation.Register as Handler.Allocation
|
||||||
|
import Handler.Allocation.List as Handler.Allocation
|
||||||
|
|||||||
@ -12,8 +12,6 @@ module Handler.Allocation.Application
|
|||||||
import Import hiding (hash)
|
import Import hiding (hash)
|
||||||
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
|
|||||||
85
src/Handler/Allocation/List.hs
Normal file
85
src/Handler/Allocation/List.hs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
module Handler.Allocation.List
|
||||||
|
( getAllocationListR
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Import
|
||||||
|
|
||||||
|
import qualified Database.Esqueleto as E
|
||||||
|
import Handler.Utils.Table.Columns
|
||||||
|
import Handler.Utils.Table.Pagination
|
||||||
|
|
||||||
|
|
||||||
|
type AllocationTableExpr = E.SqlExpr (Entity Allocation)
|
||||||
|
type AllocationTableData = DBRow (Entity Allocation)
|
||||||
|
|
||||||
|
allocationListIdent :: Text
|
||||||
|
allocationListIdent = "allocations"
|
||||||
|
|
||||||
|
queryAllocation :: Getter AllocationTableExpr (E.SqlExpr (Entity Allocation))
|
||||||
|
queryAllocation = id
|
||||||
|
|
||||||
|
resultAllocation :: Getter AllocationTableData (Entity Allocation)
|
||||||
|
resultAllocation = _dbrOutput
|
||||||
|
|
||||||
|
allocationTermLink :: TermId -> SomeRoute UniWorX
|
||||||
|
allocationTermLink tid = SomeRoute (AllocationListR, [(dbFilterKey allocationListIdent "term", toPathPiece tid)])
|
||||||
|
|
||||||
|
allocationSchoolLink :: SchoolId -> SomeRoute UniWorX
|
||||||
|
allocationSchoolLink ssh = SomeRoute (AllocationListR, [(dbFilterKey allocationListIdent "school", toPathPiece ssh)])
|
||||||
|
|
||||||
|
allocationLink :: Allocation -> SomeRoute UniWorX
|
||||||
|
allocationLink Allocation{..} = SomeRoute $ AllocationR allocationTerm allocationSchool allocationShorthand AShowR
|
||||||
|
|
||||||
|
getAllocationListR :: Handler Html
|
||||||
|
getAllocationListR = do
|
||||||
|
let
|
||||||
|
dbtSQLQuery :: AllocationTableExpr -> E.SqlQuery _
|
||||||
|
dbtSQLQuery = return
|
||||||
|
|
||||||
|
dbtProj :: DBRow _ -> MaybeT (YesodDB UniWorX) AllocationTableData
|
||||||
|
dbtProj = return
|
||||||
|
|
||||||
|
dbtRowKey = view $ queryAllocation . to (E.^. AllocationId)
|
||||||
|
|
||||||
|
dbtColonnade :: Colonnade Sortable _ _
|
||||||
|
dbtColonnade = mconcat
|
||||||
|
[ anchorColonnade (views (resultAllocation . _entityVal . _allocationTerm) allocationTermLink) . colTermShort $ resultAllocation . _entityVal . _allocationTerm
|
||||||
|
, anchorColonnade (views (resultAllocation . _entityVal . _allocationSchool) allocationSchoolLink) . colSchoolShort $ resultAllocation . _entityVal . _allocationSchool
|
||||||
|
, anchorColonnade (views (resultAllocation . _entityVal) allocationLink) . colAllocationName $ resultAllocation . _entityVal . _allocationName
|
||||||
|
]
|
||||||
|
|
||||||
|
dbtSorting = mconcat
|
||||||
|
[ sortTerm $ queryAllocation . to (E.^. AllocationTerm)
|
||||||
|
, sortSchool $ queryAllocation . to (E.^. AllocationSchool)
|
||||||
|
, sortAllocationName $ queryAllocation . to (E.^. AllocationName)
|
||||||
|
]
|
||||||
|
|
||||||
|
dbtFilter = mconcat
|
||||||
|
[ fltrTerm $ queryAllocation . to (E.^. AllocationTerm)
|
||||||
|
, fltrSchool $ queryAllocation . to (E.^. AllocationSchool)
|
||||||
|
, fltrAllocationName $ queryAllocation . to (E.^. AllocationName)
|
||||||
|
]
|
||||||
|
dbtFilterUI = mconcat
|
||||||
|
[ fltrTermUI
|
||||||
|
, fltrSchoolUI
|
||||||
|
, fltrAllocationNameUI
|
||||||
|
]
|
||||||
|
|
||||||
|
dbtStyle = def
|
||||||
|
{ dbsFilterLayout = defaultDBSFilterLayout
|
||||||
|
}
|
||||||
|
dbtParams = def
|
||||||
|
|
||||||
|
dbtCsvEncode = noCsvEncode
|
||||||
|
dbtCsvDecode = Nothing
|
||||||
|
|
||||||
|
dbtIdent = allocationListIdent
|
||||||
|
|
||||||
|
psValidator :: PSValidator _ _
|
||||||
|
psValidator = def
|
||||||
|
|
||||||
|
table <- runDB $ dbTableWidget' psValidator DBTable{..}
|
||||||
|
|
||||||
|
siteLayoutMsg MsgAllocationListTitle $ do
|
||||||
|
setTitleI MsgAllocationListTitle
|
||||||
|
table
|
||||||
@ -8,8 +8,6 @@ module Handler.Allocation.Register
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Handler.Utils.Form
|
import Handler.Utils.Form
|
||||||
|
|
||||||
{-# ANN module ("HLint: ignore Use newtype instead of data"::String) #-}
|
{-# ANN module ("HLint: ignore Use newtype instead of data"::String) #-}
|
||||||
|
|||||||
@ -4,8 +4,7 @@ module Handler.Allocation.Show
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Handler.Allocation.Register
|
import Handler.Allocation.Register
|
||||||
import Handler.Allocation.Application
|
import Handler.Allocation.Application
|
||||||
|
|
||||||
|
|||||||
@ -12,8 +12,6 @@ import Handler.Utils.SheetType
|
|||||||
import Handler.Utils.Delete
|
import Handler.Utils.Delete
|
||||||
-- import Handler.Utils.Zip
|
-- import Handler.Utils.Zip
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Data.List as List (nub, foldl, foldr)
|
import Data.List as List (nub, foldl, foldr)
|
||||||
import Data.Set (Set)
|
import Data.Set (Set)
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
|||||||
@ -5,7 +5,6 @@ module Handler.Course.Edit
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Utils.Form
|
import Utils.Form
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Handler.Utils.Invitations
|
import Handler.Utils.Invitations
|
||||||
|
|||||||
@ -8,7 +8,6 @@ module Handler.Course.LecturerInvite
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Utils.Form
|
import Utils.Form
|
||||||
import Handler.Utils.Invitations
|
import Handler.Utils.Invitations
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import Import
|
|||||||
|
|
||||||
import Data.Maybe (fromJust)
|
import Data.Maybe (fromJust)
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Utils.Form
|
import Utils.Form
|
||||||
-- import Utils.DB
|
-- import Utils.DB
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
|
|||||||
@ -8,7 +8,6 @@ module Handler.Course.ParticipantInvite
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Utils.Form
|
import Utils.Form
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Handler.Utils.Invitations
|
import Handler.Utils.Invitations
|
||||||
|
|||||||
@ -7,7 +7,6 @@ module Handler.Course.Register
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
|
|
||||||
import Data.Function ((&))
|
import Data.Function ((&))
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import qualified Database.Esqueleto.Utils as E
|
|||||||
import Database.Esqueleto.Utils.TH
|
import Database.Esqueleto.Utils.TH
|
||||||
|
|
||||||
import qualified Data.CaseInsensitive as CI
|
import qualified Data.CaseInsensitive as CI
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,6 @@ module Handler.Course.User
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Utils.Form
|
import Utils.Form
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Database.Esqueleto.Utils.TH
|
import Database.Esqueleto.Utils.TH
|
||||||
|
|||||||
@ -9,7 +9,6 @@ module Handler.Course.Users
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Utils.Form
|
import Utils.Form
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Handler.Utils.Database
|
import Handler.Utils.Database
|
||||||
|
|||||||
@ -8,8 +8,6 @@ import Handler.Exam.RegistrationInvite
|
|||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Handler.Utils.Exam
|
import Handler.Utils.Exam
|
||||||
import Handler.Utils.Invitations
|
import Handler.Utils.Invitations
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
|
|||||||
@ -12,8 +12,6 @@ import Import
|
|||||||
import Handler.Utils.Invitations
|
import Handler.Utils.Invitations
|
||||||
import Handler.Utils.Exam
|
import Handler.Utils.Exam
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Text.Hamlet (ihamlet)
|
import Text.Hamlet (ihamlet)
|
||||||
|
|
||||||
import Data.Aeson hiding (Result(..))
|
import Data.Aeson hiding (Result(..))
|
||||||
|
|||||||
@ -6,8 +6,6 @@ import Import
|
|||||||
import Handler.Exam.Form
|
import Handler.Exam.Form
|
||||||
import Handler.Exam.CorrectorInvite
|
import Handler.Exam.CorrectorInvite
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
|
|||||||
@ -8,8 +8,6 @@ module Handler.Exam.Form
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Import
|
import Import
|
||||||
import Utils.Lens hiding (parts)
|
|
||||||
|
|
||||||
import Handler.Exam.CorrectorInvite
|
import Handler.Exam.CorrectorInvite
|
||||||
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
@ -230,12 +228,12 @@ examPartsForm prev = wFormToAForm $ do
|
|||||||
|
|
||||||
examFormTemplate :: Entity Exam -> DB ExamForm
|
examFormTemplate :: Entity Exam -> DB ExamForm
|
||||||
examFormTemplate (Entity eId Exam{..}) = do
|
examFormTemplate (Entity eId Exam{..}) = do
|
||||||
parts <- selectList [ ExamPartExam ==. eId ] []
|
examParts <- selectList [ ExamPartExam ==. eId ] []
|
||||||
occurrences <- selectList [ ExamOccurrenceExam ==. eId ] []
|
occurrences <- selectList [ ExamOccurrenceExam ==. eId ] []
|
||||||
correctors <- selectList [ ExamCorrectorExam ==. eId ] []
|
correctors <- selectList [ ExamCorrectorExam ==. eId ] []
|
||||||
invitations <- map (\(email, InvDBDataExamCorrector) -> email) <$> sourceInvitationsList eId
|
invitations <- map (\(email, InvDBDataExamCorrector) -> email) <$> sourceInvitationsList eId
|
||||||
|
|
||||||
parts' <- forM parts $ \(Entity pid part) -> (,) <$> encrypt pid <*> pure part
|
examParts' <- forM examParts $ \(Entity pid part) -> (,) <$> encrypt pid <*> pure part
|
||||||
occurrences' <- forM occurrences $ \(Entity oid occ) -> (,) <$> encrypt oid <*> pure occ
|
occurrences' <- forM occurrences $ \(Entity oid occ) -> (,) <$> encrypt oid <*> pure occ
|
||||||
|
|
||||||
return ExamForm
|
return ExamForm
|
||||||
@ -267,7 +265,7 @@ examFormTemplate (Entity eId Exam{..}) = do
|
|||||||
, eofDescription = examOccurrenceDescription
|
, eofDescription = examOccurrenceDescription
|
||||||
}
|
}
|
||||||
, efExamParts = Set.fromList $ do
|
, efExamParts = Set.fromList $ do
|
||||||
(Just -> epfId, ExamPart{..}) <- parts'
|
(Just -> epfId, ExamPart{..}) <- examParts'
|
||||||
return ExamPartForm
|
return ExamPartForm
|
||||||
{ epfId
|
{ epfId
|
||||||
, epfName = examPartName
|
, epfName = examPartName
|
||||||
|
|||||||
@ -16,8 +16,6 @@ import Handler.Utils.Invitations
|
|||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
import Text.Hamlet (ihamlet)
|
import Text.Hamlet (ihamlet)
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Data.Aeson hiding (Result(..))
|
import Data.Aeson hiding (Result(..))
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,6 @@ module Handler.Exam.Show
|
|||||||
import Import
|
import Import
|
||||||
import Handler.Exam.Register
|
import Handler.Exam.Register
|
||||||
|
|
||||||
import Utils.Lens hiding (parts)
|
|
||||||
|
|
||||||
import Data.Map ((!?))
|
import Data.Map ((!?))
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
@ -24,7 +22,7 @@ getEShowR tid ssh csh examn = do
|
|||||||
cTime <- liftIO getCurrentTime
|
cTime <- liftIO getCurrentTime
|
||||||
mUid <- maybeAuthId
|
mUid <- maybeAuthId
|
||||||
|
|
||||||
(Entity _ Exam{..}, parts, examVisible, (gradingVisible, gradingShown), (occurrenceAssignmentsVisible, occurrenceAssignmentsShown), results, result, occurrences, (registered, mayRegister), occurrenceNamesShown) <- runDB $ do
|
(Entity _ Exam{..}, examParts, examVisible, (gradingVisible, gradingShown), (occurrenceAssignmentsVisible, occurrenceAssignmentsShown), results, result, occurrences, (registered, mayRegister), occurrenceNamesShown) <- runDB $ do
|
||||||
exam@(Entity eId Exam{..}) <- fetchExam tid ssh csh examn
|
exam@(Entity eId Exam{..}) <- fetchExam tid ssh csh examn
|
||||||
|
|
||||||
let examVisible = NTop (Just cTime) >= NTop examVisibleFrom
|
let examVisible = NTop (Just cTime) >= NTop examVisibleFrom
|
||||||
@ -35,12 +33,12 @@ getEShowR tid ssh csh examn = do
|
|||||||
let occurrenceAssignmentsVisible = NTop (Just cTime) >= NTop examPublishOccurrenceAssignments
|
let occurrenceAssignmentsVisible = NTop (Just cTime) >= NTop examPublishOccurrenceAssignments
|
||||||
occurrenceAssignmentsShown <- or2M (return occurrenceAssignmentsVisible) . hasReadAccessTo $ CExamR tid ssh csh examn EEditR
|
occurrenceAssignmentsShown <- or2M (return occurrenceAssignmentsVisible) . hasReadAccessTo $ CExamR tid ssh csh examn EEditR
|
||||||
|
|
||||||
parts <- selectList [ ExamPartExam ==. eId ] [ Asc ExamPartName ]
|
examParts <- selectList [ ExamPartExam ==. eId ] [ Asc ExamPartName ]
|
||||||
|
|
||||||
resultsRaw <- for mUid $ \uid ->
|
resultsRaw <- for mUid $ \uid ->
|
||||||
E.select . E.from $ \examPartResult -> do
|
E.select . E.from $ \examPartResult -> do
|
||||||
E.where_ $ examPartResult E.^. ExamPartResultUser E.==. E.val uid
|
E.where_ $ examPartResult E.^. ExamPartResultUser E.==. E.val uid
|
||||||
E.&&. examPartResult E.^. ExamPartResultExamPart `E.in_` E.valList (map entityKey parts)
|
E.&&. examPartResult E.^. ExamPartResultExamPart `E.in_` E.valList (map entityKey examParts)
|
||||||
return examPartResult
|
return examPartResult
|
||||||
let results = maybe Map.empty (\rs -> Map.fromList [ (examPartResultExamPart, res) | res@(Entity _ ExamPartResult{..}) <- rs ]) resultsRaw
|
let results = maybe Map.empty (\rs -> Map.fromList [ (examPartResultExamPart, res) | res@(Entity _ ExamPartResult{..}) <- rs ]) resultsRaw
|
||||||
|
|
||||||
@ -66,7 +64,7 @@ getEShowR tid ssh csh examn = do
|
|||||||
|
|
||||||
occurrenceNamesShown <- hasReadAccessTo $ CExamR tid ssh csh examn EEditR
|
occurrenceNamesShown <- hasReadAccessTo $ CExamR tid ssh csh examn EEditR
|
||||||
|
|
||||||
return (exam, parts, examVisible, (gradingVisible, gradingShown), (occurrenceAssignmentsVisible, occurrenceAssignmentsShown), results, result, occurrences, (registered, mayRegister), occurrenceNamesShown)
|
return (exam, examParts, examVisible, (gradingVisible, gradingShown), (occurrenceAssignmentsVisible, occurrenceAssignmentsShown), results, result, occurrences, (registered, mayRegister), occurrenceNamesShown)
|
||||||
|
|
||||||
let examTimes = all (\(Entity _ ExamOccurrence{..}, _) -> Just examOccurrenceStart == examStart && examOccurrenceEnd == examEnd) occurrences
|
let examTimes = all (\(Entity _ ExamOccurrence{..}, _) -> Just examOccurrenceStart == examStart && examOccurrenceEnd == examEnd) occurrences
|
||||||
registerWidget
|
registerWidget
|
||||||
|
|||||||
@ -6,7 +6,6 @@ module Handler.Exam.Users
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Handler.Utils.Exam
|
import Handler.Utils.Exam
|
||||||
import Handler.Utils.Table.Columns
|
import Handler.Utils.Table.Columns
|
||||||
|
|||||||
@ -5,8 +5,6 @@ import Import
|
|||||||
import qualified Data.Aeson.Encode.Pretty as Aeson
|
import qualified Data.Aeson.Encode.Pretty as Aeson
|
||||||
import qualified Data.Text.Lazy.Builder as Builder
|
import qualified Data.Text.Lazy.Builder as Builder
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import qualified Data.UUID as UUID
|
import qualified Data.UUID as UUID
|
||||||
|
|
||||||
import Data.Semigroup (Min(..), Max(..))
|
import Data.Semigroup (Min(..), Max(..))
|
||||||
|
|||||||
@ -2,7 +2,6 @@ module Handler.Home where
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Handler.Utils.Table.Cells
|
import Handler.Utils.Table.Cells
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@ import qualified Data.Conduit.List as C
|
|||||||
import qualified Database.Esqueleto as E
|
import qualified Database.Esqueleto as E
|
||||||
import Database.Esqueleto.Utils.TH
|
import Database.Esqueleto.Utils.TH
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Utils.Form
|
import Utils.Form
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Handler.Utils.Delete
|
import Handler.Utils.Delete
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import Import
|
|||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Handler.Utils.Table.Cells
|
import Handler.Utils.Table.Cells
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
-- import Colonnade hiding (fromMaybe, singleton)
|
-- import Colonnade hiding (fromMaybe, singleton)
|
||||||
-- import Yesod.Colonnade
|
-- import Yesod.Colonnade
|
||||||
import Data.Monoid (Any(..))
|
import Data.Monoid (Any(..))
|
||||||
|
|||||||
@ -49,11 +49,6 @@ import Data.Map (Map, (!))
|
|||||||
|
|
||||||
import Data.Monoid (Any(..))
|
import Data.Monoid (Any(..))
|
||||||
|
|
||||||
-- import Control.Lens
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
--import qualified Data.Aeson as Aeson
|
|
||||||
|
|
||||||
import Control.Monad.Random.Class (MonadRandom(..))
|
import Control.Monad.Random.Class (MonadRandom(..))
|
||||||
import Utils.Sql
|
import Utils.Sql
|
||||||
|
|
||||||
|
|||||||
@ -6,8 +6,6 @@ import Import
|
|||||||
|
|
||||||
import Jobs
|
import Jobs
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
-- import Yesod.Form.Bootstrap3
|
-- import Yesod.Form.Bootstrap3
|
||||||
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
|
|||||||
@ -11,8 +11,6 @@ import qualified Data.List.NonEmpty as NonEmpty
|
|||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Handler.Utils.Table.Cells
|
import Handler.Utils.Table.Cells
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import qualified Database.Esqueleto as E
|
import qualified Database.Esqueleto as E
|
||||||
|
|
||||||
-- htmlField' moved to Handler.Utils.Form/Fields
|
-- htmlField' moved to Handler.Utils.Form/Fields
|
||||||
|
|||||||
@ -5,8 +5,6 @@ import Handler.Utils
|
|||||||
import Handler.Utils.Table.Cells
|
import Handler.Utils.Table.Cells
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import qualified Database.Esqueleto as E
|
import qualified Database.Esqueleto as E
|
||||||
|
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
|||||||
@ -25,8 +25,6 @@ import qualified Data.CaseInsensitive as CI
|
|||||||
|
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Data.Aeson hiding (Result(..))
|
import Data.Aeson hiding (Result(..))
|
||||||
import Text.Hamlet (ihamlet)
|
import Text.Hamlet (ihamlet)
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,6 @@ module Handler.Tutorial.Users
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Utils.Form
|
import Utils.Form
|
||||||
-- import Utils.DB
|
-- import Utils.DB
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
|
|||||||
@ -13,8 +13,6 @@ import Handler.Utils.Invitations
|
|||||||
|
|
||||||
import qualified Auth.LDAP as Auth
|
import qualified Auth.LDAP as Auth
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import qualified Data.CaseInsensitive as CI
|
import qualified Data.CaseInsensitive as CI
|
||||||
|
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
|||||||
@ -4,8 +4,6 @@ module Handler.Utils
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding as T
|
import qualified Data.Text.Encoding as T
|
||||||
import Data.Map ((!))
|
import Data.Map ((!))
|
||||||
|
|||||||
@ -9,7 +9,6 @@ module Handler.Utils.Communication
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Jobs.Queue
|
import Jobs.Queue
|
||||||
import Control.Monad.Trans.Reader (mapReaderT)
|
import Control.Monad.Trans.Reader (mapReaderT)
|
||||||
|
|||||||
@ -5,8 +5,6 @@ module Handler.Utils.ContentDisposition
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
-- | Check whether the user's preference for files is inline-viewing or downloading
|
-- | Check whether the user's preference for files is inline-viewing or downloading
|
||||||
downloadFiles :: (MonadHandler m, HandlerSite m ~ UniWorX) => m Bool
|
downloadFiles :: (MonadHandler m, HandlerSite m ~ UniWorX) => m Bool
|
||||||
downloadFiles = do
|
downloadFiles = do
|
||||||
|
|||||||
@ -16,8 +16,6 @@ module Handler.Utils.DateTime
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Data.Time.Zones
|
import Data.Time.Zones
|
||||||
import qualified Data.Time.Zones as TZ
|
import qualified Data.Time.Zones as TZ
|
||||||
|
|
||||||
|
|||||||
@ -17,8 +17,6 @@ module Handler.Utils.Delete
|
|||||||
import Import
|
import Import
|
||||||
import Handler.Utils.Form
|
import Handler.Utils.Form
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
|
|||||||
@ -12,8 +12,6 @@ import qualified Database.Esqueleto.Utils as E
|
|||||||
import qualified Database.Esqueleto.Internal.Sql as E
|
import qualified Database.Esqueleto.Internal.Sql as E
|
||||||
import Database.Esqueleto.Utils.TH
|
import Database.Esqueleto.Utils.TH
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import qualified Data.Conduit.List as C
|
import qualified Data.Conduit.List as C
|
||||||
|
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
|||||||
@ -40,8 +40,6 @@ import Control.Monad.Error.Class (MonadError(..))
|
|||||||
|
|
||||||
import Data.Either (partitionEithers)
|
import Data.Either (partitionEithers)
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Data.Aeson (eitherDecodeStrict')
|
import Data.Aeson (eitherDecodeStrict')
|
||||||
import Data.Aeson.Text (encodeToLazyText)
|
import Data.Aeson.Text (encodeToLazyText)
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,6 @@ module Handler.Utils.Form.MassInput
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
import Utils.Form
|
import Utils.Form
|
||||||
import Utils.Lens
|
|
||||||
import Handler.Utils.Form.MassInput.Liveliness
|
import Handler.Utils.Form.MassInput.Liveliness
|
||||||
import Handler.Utils.Form.MassInput.TH
|
import Handler.Utils.Form.MassInput.TH
|
||||||
|
|
||||||
|
|||||||
@ -10,8 +10,6 @@ import qualified Data.Set as Set
|
|||||||
import Data.Map ((!))
|
import Data.Map ((!))
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
|
|
||||||
data OccurrenceScheduleKind = ScheduleKindWeekly
|
data OccurrenceScheduleKind = ScheduleKindWeekly
|
||||||
deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic, Typeable)
|
deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic, Typeable)
|
||||||
|
|||||||
@ -16,7 +16,6 @@ module Handler.Utils.Invitations
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Import
|
import Import
|
||||||
import Utils.Lens
|
|
||||||
import Utils.Form
|
import Utils.Form
|
||||||
import Jobs.Queue
|
import Jobs.Queue
|
||||||
|
|
||||||
|
|||||||
@ -7,8 +7,6 @@ module Handler.Utils.Mail
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import qualified Data.CaseInsensitive as CI
|
import qualified Data.CaseInsensitive as CI
|
||||||
|
|
||||||
import qualified Data.ByteString.Lazy as LBS
|
import qualified Data.ByteString.Lazy as LBS
|
||||||
|
|||||||
@ -39,8 +39,6 @@ import qualified Database.Esqueleto as E
|
|||||||
|
|
||||||
import qualified Data.Conduit.List as Conduit
|
import qualified Data.Conduit.List as Conduit
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
|
|
||||||
instance HasResolution prec => Pretty (Fixed prec) where
|
instance HasResolution prec => Pretty (Fixed prec) where
|
||||||
pretty = pretty . show
|
pretty = pretty . show
|
||||||
|
|||||||
@ -5,7 +5,6 @@ module Handler.Utils.SheetType
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
import Data.Monoid (Sum(..))
|
import Data.Monoid (Sum(..))
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
addBonusToPoints :: SheetTypeSummary -> SheetTypeSummary
|
addBonusToPoints :: SheetTypeSummary -> SheetTypeSummary
|
||||||
addBonusToPoints sts =
|
addBonusToPoints sts =
|
||||||
|
|||||||
@ -15,8 +15,6 @@ import Import hiding (joinPath)
|
|||||||
import Jobs.Queue
|
import Jobs.Queue
|
||||||
import Yesod.Core.Types (HandlerContents(..), ErrorResponse(..))
|
import Yesod.Core.Types (HandlerContents(..), ErrorResponse(..))
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Control.Monad.State as State (StateT)
|
import Control.Monad.State as State (StateT)
|
||||||
import Control.Monad.State.Class as State
|
import Control.Monad.State.Class as State
|
||||||
import Control.Monad.Writer (MonadWriter(..), execWriterT, execWriter)
|
import Control.Monad.Writer (MonadWriter(..), execWriterT, execWriter)
|
||||||
|
|||||||
@ -2,7 +2,6 @@ module Handler.Utils.Table where
|
|||||||
-- General Utilities for Tables
|
-- General Utilities for Tables
|
||||||
|
|
||||||
import Import
|
import Import
|
||||||
import Data.Profunctor
|
|
||||||
|
|
||||||
import Control.Monad.Except
|
import Control.Monad.Except
|
||||||
|
|
||||||
@ -51,10 +50,12 @@ headedRowSelector toExternal fromExternal attrs colonnade tdata = do
|
|||||||
externalIds <- mapM (lift . toExternal) tdata
|
externalIds <- mapM (lift . toExternal) tdata
|
||||||
|
|
||||||
let
|
let
|
||||||
checkbox extId = Field parse view UrlEncoded
|
checkbox extId = Field{..}
|
||||||
where
|
where
|
||||||
parse [] _ = return $ Right Nothing
|
fieldEnctype = UrlEncoded
|
||||||
parse optlist _ = runExceptT $ do
|
|
||||||
|
fieldParse [] _ = return $ Right Nothing
|
||||||
|
fieldParse optlist _ = runExceptT $ do
|
||||||
extIds <- maybe (throwError "Error parsing values") return $ mapM fromPathPiece optlist
|
extIds <- maybe (throwError "Error parsing values") return $ mapM fromPathPiece optlist
|
||||||
case () of
|
case () of
|
||||||
_ | extId `elem` extIds
|
_ | extId `elem` extIds
|
||||||
@ -62,11 +63,11 @@ headedRowSelector toExternal fromExternal attrs colonnade tdata = do
|
|||||||
| otherwise
|
| otherwise
|
||||||
-> return Nothing
|
-> return Nothing
|
||||||
|
|
||||||
view _ name attributes val _ =
|
fieldView theId name attributes val _ =
|
||||||
-- TODO: move this to a *.hamlet file
|
-- TODO: move this to a *.hamlet file
|
||||||
[whamlet|
|
[whamlet|
|
||||||
<label style="display: block">
|
<label style="display: block">
|
||||||
<input type=checkbox name=#{name} value=#{toPathPiece extId} *{attributes} :isRight val:checked>
|
<input ##{theId} type=checkbox name=#{name} value=#{toPathPiece extId} *{attributes} :isRight val:checked>
|
||||||
|]
|
|]
|
||||||
|
|
||||||
selectionIdent <- newFormIdent
|
selectionIdent <- newFormIdent
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import Control.Monad.Trans.Writer (WriterT)
|
|||||||
|
|
||||||
import Text.Blaze (ToMarkup(..))
|
import Text.Blaze (ToMarkup(..))
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
|
|
||||||
import Utils.Occurrences
|
import Utils.Occurrences
|
||||||
|
|||||||
@ -14,12 +14,14 @@ import Import
|
|||||||
import qualified Database.Esqueleto as E
|
import qualified Database.Esqueleto as E
|
||||||
import Database.Esqueleto.Utils (mkExactFilter, mkExactFilterWith, mkContainsFilter, mkContainsFilterWith, anyFilter)
|
import Database.Esqueleto.Utils (mkExactFilter, mkExactFilterWith, mkContainsFilter, mkContainsFilterWith, anyFilter)
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Handler.Utils.Table.Cells
|
import Handler.Utils.Table.Cells
|
||||||
|
|
||||||
import qualified Data.CaseInsensitive as CI
|
import qualified Data.CaseInsensitive as CI
|
||||||
|
|
||||||
|
import qualified Colonnade
|
||||||
|
import Colonnade.Encode (Colonnade(..), OneColonnade(..))
|
||||||
|
|
||||||
|
|
||||||
--------------------------------
|
--------------------------------
|
||||||
-- Generic Columns
|
-- Generic Columns
|
||||||
@ -35,6 +37,31 @@ import qualified Data.CaseInsensitive as CI
|
|||||||
-- * fltrXYZ : filter definitions for these columns
|
-- * fltrXYZ : filter definitions for these columns
|
||||||
-- * additional helper, such as default sorting
|
-- * additional helper, such as default sorting
|
||||||
|
|
||||||
|
type OpticColonnade focus
|
||||||
|
= forall m x r' h.
|
||||||
|
( IsDBTable m x
|
||||||
|
, FromSortable h
|
||||||
|
)
|
||||||
|
=> Getting focus r' focus
|
||||||
|
-> Colonnade h r' (DBCell m x)
|
||||||
|
|
||||||
|
type OpticSortColumn focus
|
||||||
|
= forall t sortingMap.
|
||||||
|
( IsMap sortingMap
|
||||||
|
, ContainerKey sortingMap ~ SortingKey
|
||||||
|
, MapValue sortingMap ~ SortColumn t
|
||||||
|
)
|
||||||
|
=> Getting (E.SqlExpr focus) t (E.SqlExpr focus)
|
||||||
|
-> sortingMap
|
||||||
|
|
||||||
|
type OpticFilterColumn t focus
|
||||||
|
= forall filterMap.
|
||||||
|
( IsMap filterMap
|
||||||
|
, ContainerKey filterMap ~ FilterKey
|
||||||
|
, MapValue filterMap ~ FilterColumn t
|
||||||
|
)
|
||||||
|
=> Getting (E.SqlExpr focus) t (E.SqlExpr focus)
|
||||||
|
-> filterMap
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
-- Numbers and Indices
|
-- Numbers and Indices
|
||||||
@ -44,6 +71,65 @@ import qualified Data.CaseInsensitive as CI
|
|||||||
dbRowIndicator :: IsDBTable m Any => Colonnade Sortable (DBRow r) (DBCell m Any)
|
dbRowIndicator :: IsDBTable m Any => Colonnade Sortable (DBRow r) (DBCell m Any)
|
||||||
dbRowIndicator = sortable Nothing (i18nCell MsgNrColumn) $ \DBRow{ dbrIndex } -> tellCell (Any True) $ textCell $ tshow dbrIndex
|
dbRowIndicator = sortable Nothing (i18nCell MsgNrColumn) $ \DBRow{ dbrIndex } -> tellCell (Any True) $ textCell $ tshow dbrIndex
|
||||||
|
|
||||||
|
-----------
|
||||||
|
-- Terms --
|
||||||
|
-----------
|
||||||
|
|
||||||
|
colTermShort :: OpticColonnade TermId
|
||||||
|
colTermShort resultTid = Colonnade.singleton (fromSortable header) body
|
||||||
|
where
|
||||||
|
header = Sortable (Just "term") (i18nCell MsgTerm)
|
||||||
|
body = i18nCell . ShortTermIdentifier . unTermKey . view resultTid
|
||||||
|
|
||||||
|
sortTerm :: OpticSortColumn (E.Value TermId)
|
||||||
|
sortTerm queryTid = singletonMap "term" . SortColumn $ view queryTid
|
||||||
|
|
||||||
|
fltrTerm :: IsFilterColumn t (t -> Set TermId -> E.SqlExpr (E.Value Bool))
|
||||||
|
=> OpticFilterColumn t (E.Value TermId)
|
||||||
|
fltrTerm queryTid = singletonMap "term" . FilterColumn $ mkExactFilter (view queryTid)
|
||||||
|
|
||||||
|
fltrTermUI :: DBFilterUI
|
||||||
|
fltrTermUI mPrev = prismAForm (singletonFilter "term" . maybePrism _PathPiece) mPrev $ aopt (hoistField lift termField) (fslI MsgTerm)
|
||||||
|
|
||||||
|
-------------
|
||||||
|
-- Schools --
|
||||||
|
-------------
|
||||||
|
|
||||||
|
colSchoolShort :: OpticColonnade SchoolId
|
||||||
|
colSchoolShort resultSsh = Colonnade.singleton (fromSortable header) body
|
||||||
|
where
|
||||||
|
header = Sortable (Just "school") (i18nCell MsgSchool)
|
||||||
|
body = i18nCell . unSchoolKey . view resultSsh
|
||||||
|
|
||||||
|
sortSchool :: OpticSortColumn (E.Value SchoolId)
|
||||||
|
sortSchool querySsh = singletonMap "school" . SortColumn $ view querySsh
|
||||||
|
|
||||||
|
fltrSchool :: IsFilterColumn t (t -> Set SchoolId -> E.SqlExpr (E.Value Bool))
|
||||||
|
=> OpticFilterColumn t (E.Value SchoolId)
|
||||||
|
fltrSchool querySsh = singletonMap "school" . FilterColumn $ mkExactFilter (view querySsh)
|
||||||
|
|
||||||
|
fltrSchoolUI :: DBFilterUI
|
||||||
|
fltrSchoolUI mPrev = prismAForm (singletonFilter "school" . maybePrism _PathPiece) mPrev $ aopt (hoistField lift schoolField) (fslI MsgSchool)
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
-- Allocations --
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
colAllocationName :: OpticColonnade AllocationName
|
||||||
|
colAllocationName resultName = Colonnade.singleton (fromSortable header) body
|
||||||
|
where
|
||||||
|
header = Sortable (Just "allocation") (i18nCell MsgAllocationName)
|
||||||
|
body = i18nCell . view resultName
|
||||||
|
|
||||||
|
sortAllocationName :: OpticSortColumn (E.Value AllocationName)
|
||||||
|
sortAllocationName queryName = singletonMap "allocation" . SortColumn $ view queryName
|
||||||
|
|
||||||
|
fltrAllocationName :: IsFilterColumn t (t -> Set AllocationName -> E.SqlExpr (E.Value Bool))
|
||||||
|
=> OpticFilterColumn t (E.Value AllocationName)
|
||||||
|
fltrAllocationName queryName = singletonMap "allocation" . FilterColumn $ mkContainsFilter (view queryName)
|
||||||
|
|
||||||
|
fltrAllocationNameUI :: DBFilterUI
|
||||||
|
fltrAllocationNameUI mPrev = prismAForm (singletonFilter "allocation" . maybePrism _PathPiece) mPrev $ aopt (ciField :: Field _ AllocationName) (fslI MsgAllocation)
|
||||||
|
|
||||||
---------------
|
---------------
|
||||||
-- Files
|
-- Files
|
||||||
@ -282,3 +368,43 @@ fltrDegree queryFeatures = ( "degree"
|
|||||||
fltrDegreeUI :: Maybe (Map FilterKey [Text]) -> AForm (YesodDB UniWorX) (Map FilterKey [Text])
|
fltrDegreeUI :: Maybe (Map FilterKey [Text]) -> AForm (YesodDB UniWorX) (Map FilterKey [Text])
|
||||||
fltrDegreeUI mPrev =
|
fltrDegreeUI mPrev =
|
||||||
prismAForm (singletonFilter "degree") mPrev $ aopt textField (fslI MsgDegreeName)
|
prismAForm (singletonFilter "degree") mPrev $ aopt textField (fslI MsgDegreeName)
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
-- Colonnade manipulation --
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
imapColonnade :: (a -> c -> c)
|
||||||
|
-> Colonnade h a c
|
||||||
|
-> Colonnade h a c
|
||||||
|
-- ^ Not quite `imap`
|
||||||
|
imapColonnade f (Colonnade ones) = Colonnade $ dimapColonnade' <$> ones
|
||||||
|
where
|
||||||
|
dimapColonnade' OneColonnade{..} = OneColonnade
|
||||||
|
{ oneColonnadeEncode = \x -> f x $ oneColonnadeEncode x
|
||||||
|
, oneColonnadeHead
|
||||||
|
}
|
||||||
|
|
||||||
|
anchorColonnade :: forall h r' m a url.
|
||||||
|
( HasRoute UniWorX url
|
||||||
|
, IsDBTable m a
|
||||||
|
, HandlerSite m ~ UniWorX
|
||||||
|
)
|
||||||
|
=> (r' -> url)
|
||||||
|
-> Colonnade h r' (DBCell m a)
|
||||||
|
-> Colonnade h r' (DBCell m a)
|
||||||
|
anchorColonnade = anchorColonnadeM . (return .)
|
||||||
|
|
||||||
|
|
||||||
|
anchorColonnadeM :: forall h r' m a url.
|
||||||
|
( HasRoute UniWorX url
|
||||||
|
, IsDBTable m a
|
||||||
|
, HandlerSite m ~ UniWorX
|
||||||
|
)
|
||||||
|
=> (r' -> WidgetT UniWorX IO url)
|
||||||
|
-> Colonnade h r' (DBCell m a)
|
||||||
|
-> Colonnade h r' (DBCell m a)
|
||||||
|
anchorColonnadeM mkUrl = imapColonnade anchorColonnade'
|
||||||
|
where
|
||||||
|
anchorColonnade' :: r' -> DBCell m a -> DBCell m a
|
||||||
|
anchorColonnade' inp (view dbCell -> (attrs, act)) = review dbCell . (attrs,) $
|
||||||
|
view (dbCell . _2) . anchorCellM (mkUrl inp) =<< act
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
module Handler.Utils.Table.Pagination
|
module Handler.Utils.Table.Pagination
|
||||||
( module Handler.Utils.Table.Pagination.Types
|
( module Handler.Utils.Table.Pagination.Types
|
||||||
|
, dbFilterKey
|
||||||
, SortColumn(..), SortDirection(..)
|
, SortColumn(..), SortDirection(..)
|
||||||
, SortingSetting(..)
|
, SortingSetting(..)
|
||||||
, pattern SortAscBy, pattern SortDescBy
|
, pattern SortAscBy, pattern SortDescBy
|
||||||
@ -10,7 +11,7 @@ module Handler.Utils.Table.Pagination
|
|||||||
, DBCsvActionMode(..)
|
, DBCsvActionMode(..)
|
||||||
, DBCsvDiff(..), _DBCsvDiffNew, _DBCsvDiffExisting, _DBCsvDiffMissing, _dbCsvOldKey, _dbCsvOld, _dbCsvNewKey, _dbCsvNew
|
, DBCsvDiff(..), _DBCsvDiffNew, _DBCsvDiffExisting, _DBCsvDiffMissing, _dbCsvOldKey, _dbCsvOld, _dbCsvNewKey, _dbCsvNew
|
||||||
, DBTCsvEncode, DBTCsvDecode(..)
|
, DBTCsvEncode, DBTCsvDecode(..)
|
||||||
, DBTable(..), noCsvEncode, IsDBTable(..), DBCell(..)
|
, DBTable(..), DBFilterUI, noCsvEncode, IsDBTable(..), DBCell(..)
|
||||||
, singletonFilter
|
, singletonFilter
|
||||||
, DBParams(..)
|
, DBParams(..)
|
||||||
, cellAttrs, cellContents
|
, cellAttrs, cellContents
|
||||||
@ -80,8 +81,6 @@ import Text.Hamlet (hamletFile)
|
|||||||
|
|
||||||
import Data.Ratio ((%))
|
import Data.Ratio ((%))
|
||||||
|
|
||||||
import Control.Lens.Extras (is)
|
|
||||||
|
|
||||||
import Data.List (elemIndex)
|
import Data.List (elemIndex)
|
||||||
|
|
||||||
import Data.Aeson (Options(..), SumEncoding(..), defaultOptions)
|
import Data.Aeson (Options(..), SumEncoding(..), defaultOptions)
|
||||||
@ -115,6 +114,22 @@ type Monoid' x = (Sem.Semigroup x, Monoid x)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
data WithIdent x = forall ident. PathPiece ident => WithIdent { _ident :: ident, _withoutIdent :: x }
|
||||||
|
|
||||||
|
instance PathPiece x => PathPiece (WithIdent x) where
|
||||||
|
toPathPiece (WithIdent ident x)
|
||||||
|
| not . null $ toPathPiece ident = toPathPiece ident <> "-" <> toPathPiece x
|
||||||
|
| otherwise = toPathPiece x
|
||||||
|
fromPathPiece txt = do
|
||||||
|
let sep = "-"
|
||||||
|
(ident, (Text.stripSuffix sep -> Just rest)) <- return $ Text.breakOn sep txt
|
||||||
|
WithIdent <$> pure ident <*> fromPathPiece rest
|
||||||
|
|
||||||
|
|
||||||
|
dbFilterKey :: PathPiece dbtIdent => dbtIdent -> FilterKey -> Text
|
||||||
|
dbFilterKey ident = toPathPiece . WithIdent ident
|
||||||
|
|
||||||
|
|
||||||
data SortColumn t = forall a. PersistField a => SortColumn { getSortColumn :: t -> E.SqlExpr (E.Value a) }
|
data SortColumn t = forall a. PersistField a => SortColumn { getSortColumn :: t -> E.SqlExpr (E.Value a) }
|
||||||
|
|
||||||
data SortDirection = SortAsc | SortDesc
|
data SortDirection = SortAsc | SortDesc
|
||||||
@ -485,17 +500,6 @@ singletonFilter key = prism' fromInner (fmap Just . fromOuter)
|
|||||||
fromOuter = Map.lookup key >=> listToMaybe
|
fromOuter = Map.lookup key >=> listToMaybe
|
||||||
|
|
||||||
|
|
||||||
data WithIdent x = forall ident. PathPiece ident => WithIdent { _ident :: ident, _withoutIdent :: x }
|
|
||||||
|
|
||||||
instance PathPiece x => PathPiece (WithIdent x) where
|
|
||||||
toPathPiece (WithIdent ident x)
|
|
||||||
| not . null $ toPathPiece ident = toPathPiece ident <> "-" <> toPathPiece x
|
|
||||||
| otherwise = toPathPiece x
|
|
||||||
fromPathPiece txt = do
|
|
||||||
let sep = "-"
|
|
||||||
(ident, (Text.stripSuffix sep -> Just rest)) <- return $ Text.breakOn sep txt
|
|
||||||
WithIdent <$> pure ident <*> fromPathPiece rest
|
|
||||||
|
|
||||||
type DBTCsvEncode r' csv = DictMaybe (ToNamedRecord csv, DefaultOrdered csv, CsvColumnsExplained csv) (Conduit r' (YesodDB UniWorX) csv)
|
type DBTCsvEncode r' csv = DictMaybe (ToNamedRecord csv, DefaultOrdered csv, CsvColumnsExplained csv) (Conduit r' (YesodDB UniWorX) csv)
|
||||||
data DBTCsvDecode r' k' csv = forall route csvAction csvActionClass csvException.
|
data DBTCsvDecode r' k' csv = forall route csvAction csvActionClass csvException.
|
||||||
( FromNamedRecord csv, ToNamedRecord csv, DefaultOrdered csv
|
( FromNamedRecord csv, ToNamedRecord csv, DefaultOrdered csv
|
||||||
@ -528,7 +532,7 @@ data DBTable m x = forall a r r' h i t k k' csv.
|
|||||||
, dbtColonnade :: Colonnade h r' (DBCell m x)
|
, dbtColonnade :: Colonnade h r' (DBCell m x)
|
||||||
, dbtSorting :: Map SortingKey (SortColumn t)
|
, dbtSorting :: Map SortingKey (SortColumn t)
|
||||||
, dbtFilter :: Map FilterKey (FilterColumn t)
|
, dbtFilter :: Map FilterKey (FilterColumn t)
|
||||||
, dbtFilterUI :: Maybe (Map FilterKey [Text]) -> AForm (YesodDB UniWorX) (Map FilterKey [Text])
|
, dbtFilterUI :: DBFilterUI
|
||||||
, dbtStyle :: DBStyle r'
|
, dbtStyle :: DBStyle r'
|
||||||
, dbtParams :: DBParams m x
|
, dbtParams :: DBParams m x
|
||||||
, dbtCsvEncode :: DBTCsvEncode r' csv
|
, dbtCsvEncode :: DBTCsvEncode r' csv
|
||||||
@ -536,6 +540,8 @@ data DBTable m x = forall a r r' h i t k k' csv.
|
|||||||
, dbtIdent :: i
|
, dbtIdent :: i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DBFilterUI = Maybe (Map FilterKey [Text]) -> AForm (YesodDB UniWorX) (Map FilterKey [Text])
|
||||||
|
|
||||||
noCsvEncode :: DictMaybe (ToNamedRecord Void, DefaultOrdered Void, CsvColumnsExplained Void) (Conduit r' (YesodDB UniWorX) Void)
|
noCsvEncode :: DictMaybe (ToNamedRecord Void, DefaultOrdered Void, CsvColumnsExplained Void) (Conduit r' (YesodDB UniWorX) Void)
|
||||||
noCsvEncode = Nothing
|
noCsvEncode = Nothing
|
||||||
|
|
||||||
@ -770,7 +776,7 @@ dbTable PSValidator{..} dbtable@DBTable{ dbtIdent = dbtIdent'@(toPathPiece -> db
|
|||||||
|
|
||||||
piInput <- lift . runInputGetResult $ PaginationInput
|
piInput <- lift . runInputGetResult $ PaginationInput
|
||||||
<$> iopt (multiSelectField $ return sortingOptions) (wIdent "sorting")
|
<$> iopt (multiSelectField $ return sortingOptions) (wIdent "sorting")
|
||||||
<*> (assertM' (not . Map.null) . Map.mapMaybe (assertM $ not . null) <$> Map.traverseWithKey (\k _ -> iopt multiTextField . wIdent $ toPathPiece k) dbtFilter)
|
<*> (assertM' (not . Map.null) . Map.mapMaybe (assertM $ not . null) <$> Map.traverseWithKey (\k _ -> iopt multiTextField $ dbFilterKey dbtIdent' k) dbtFilter)
|
||||||
<*> iopt pathPieceField (wIdent "pagesize")
|
<*> iopt pathPieceField (wIdent "pagesize")
|
||||||
<*> iopt intField (wIdent "page")
|
<*> iopt intField (wIdent "page")
|
||||||
|
|
||||||
@ -817,7 +823,7 @@ dbTable PSValidator{..} dbtable@DBTable{ dbtIdent = dbtIdent'@(toPathPiece -> db
|
|||||||
tblLink f = SomeRoute . (currentRoute, ) . over (mapped . _2) (fromMaybe Text.empty) $ (f . substPi . setParam "_hasdata" Nothing) getParams
|
tblLink f = SomeRoute . (currentRoute, ) . over (mapped . _2) (fromMaybe Text.empty) $ (f . substPi . setParam "_hasdata" Nothing) getParams
|
||||||
substPi = foldr (.) id
|
substPi = foldr (.) id
|
||||||
[ setParams (wIdent "sorting") . map toPathPiece $ fromMaybe [] piSorting
|
[ setParams (wIdent "sorting") . map toPathPiece $ fromMaybe [] piSorting
|
||||||
, foldr (.) id . map (\k -> setParams (wIdent $ toPathPiece k) . fromMaybe [] . join $ traverse (Map.lookup k) piFilter) $ Map.keys dbtFilter
|
, foldr (.) id . map (\k -> setParams (dbFilterKey dbtIdent' k) . fromMaybe [] . join $ traverse (Map.lookup k) piFilter) $ Map.keys dbtFilter
|
||||||
, setParam (wIdent "pagesize") $ fmap toPathPiece piLimit
|
, setParam (wIdent "pagesize") $ fmap toPathPiece piLimit
|
||||||
, setParam (wIdent "page") $ fmap toPathPiece piPage
|
, setParam (wIdent "page") $ fmap toPathPiece piPage
|
||||||
, setParam (wIdent "pagination") Nothing
|
, setParam (wIdent "pagination") Nothing
|
||||||
|
|||||||
@ -4,7 +4,7 @@ module Handler.Utils.Table.Pagination.Types
|
|||||||
( FilterKey, SortingKey
|
( FilterKey, SortingKey
|
||||||
, Sortable(..)
|
, Sortable(..)
|
||||||
, sortable
|
, sortable
|
||||||
, ToSortable(..)
|
, ToSortable(..), FromSortable(..)
|
||||||
, SortableP(..)
|
, SortableP(..)
|
||||||
, DBTableInvalid(..)
|
, DBTableInvalid(..)
|
||||||
) where
|
) where
|
||||||
@ -58,6 +58,19 @@ instance ToSortable Headless where
|
|||||||
pSortable = Nothing
|
pSortable = Nothing
|
||||||
|
|
||||||
|
|
||||||
|
class FromSortable s where
|
||||||
|
fromSortable :: forall a. Sortable a -> s a
|
||||||
|
|
||||||
|
instance FromSortable Sortable where
|
||||||
|
fromSortable = id
|
||||||
|
|
||||||
|
instance FromSortable Headed where
|
||||||
|
fromSortable Sortable{..} = Headed sortableContent
|
||||||
|
|
||||||
|
instance FromSortable Headless where
|
||||||
|
fromSortable _ = Headless
|
||||||
|
|
||||||
|
|
||||||
data DBTableInvalid = DBTIRowsMissing Int
|
data DBTableInvalid = DBTIRowsMissing Int
|
||||||
deriving (Eq, Ord, Read, Show, Generic, Typeable)
|
deriving (Eq, Ord, Read, Show, Generic, Typeable)
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,6 @@ module Handler.Utils.Tokens
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Control.Monad.Trans.Maybe (runMaybeT)
|
import Control.Monad.Trans.Maybe (runMaybeT)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -10,8 +10,6 @@ import qualified Database.Esqueleto as E
|
|||||||
import qualified Database.Esqueleto.Internal.Sql as E
|
import qualified Database.Esqueleto.Internal.Sql as E
|
||||||
import Database.Esqueleto.Utils.TH
|
import Database.Esqueleto.Utils.TH
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
|
|
||||||
fetchTutorialAux :: ( SqlBackendCanRead backend
|
fetchTutorialAux :: ( SqlBackendCanRead backend
|
||||||
, E.SqlSelect b a
|
, E.SqlSelect b a
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import Model.Submission as Import
|
|||||||
import Model.Tokens as Import
|
import Model.Tokens as Import
|
||||||
import Utils.Tokens as Import
|
import Utils.Tokens as Import
|
||||||
import Utils.Frontend.Modal as Import
|
import Utils.Frontend.Modal as Import
|
||||||
|
import Utils.Lens as Import
|
||||||
|
|
||||||
import Settings as Import
|
import Settings as Import
|
||||||
import Settings.StaticFiles as Import
|
import Settings.StaticFiles as Import
|
||||||
|
|||||||
@ -3,7 +3,18 @@ module Import.NoModel
|
|||||||
, MForm
|
, MForm
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import ClassyPrelude.Yesod as Import hiding (formatTime, derivePersistFieldJSON, getMessages, addMessage, addMessageI, (.=), MForm, Proxy, foldlM, static, boolField, identifyForm, cons, HasHttpManager(..))
|
import ClassyPrelude.Yesod as Import
|
||||||
|
hiding ( formatTime
|
||||||
|
, derivePersistFieldJSON
|
||||||
|
, getMessages, addMessage, addMessageI
|
||||||
|
, (.=)
|
||||||
|
, MForm
|
||||||
|
, Proxy
|
||||||
|
, foldlM
|
||||||
|
, static
|
||||||
|
, boolField, identifyForm
|
||||||
|
, HasHttpManager(..)
|
||||||
|
)
|
||||||
|
|
||||||
import Model.Types.TH.JSON as Import
|
import Model.Types.TH.JSON as Import
|
||||||
import Model.Types.TH.Wordlist as Import
|
import Model.Types.TH.Wordlist as Import
|
||||||
@ -114,6 +125,16 @@ import System.FilePath.Instances as Import ()
|
|||||||
import Net.IP.Instances as Import ()
|
import Net.IP.Instances as Import ()
|
||||||
import Data.Void.Instances as Import ()
|
import Data.Void.Instances as Import ()
|
||||||
import Crypto.Hash.Instances as Import ()
|
import Crypto.Hash.Instances as Import ()
|
||||||
|
import Colonnade.Instances as Import ()
|
||||||
|
|
||||||
|
import Control.Lens as Import
|
||||||
|
hiding ( (<.>)
|
||||||
|
, universe
|
||||||
|
, cons, uncons, snoc, unsnoc, (<|)
|
||||||
|
, Index, index, (<.)
|
||||||
|
)
|
||||||
|
import Control.Lens.Extras as Import (is)
|
||||||
|
import Data.Set.Lens as Import
|
||||||
|
|
||||||
|
|
||||||
import Control.Monad.Trans.RWS (RWST)
|
import Control.Monad.Trans.RWS (RWST)
|
||||||
|
|||||||
@ -6,8 +6,6 @@ module Jobs
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Import
|
import Import
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Jobs.Types as Types hiding (JobCtl(JobCtlQueue))
|
import Jobs.Types as Types hiding (JobCtl(JobCtlQueue))
|
||||||
import Jobs.Types (JobCtl(JobCtlQueue))
|
import Jobs.Types (JobCtl(JobCtlQueue))
|
||||||
import Jobs.Queue
|
import Jobs.Queue
|
||||||
|
|||||||
@ -4,8 +4,6 @@ module Jobs.Crontab
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import qualified Data.HashMap.Strict as HashMap
|
import qualified Data.HashMap.Strict as HashMap
|
||||||
import Jobs.Types
|
import Jobs.Types
|
||||||
|
|
||||||
|
|||||||
@ -9,8 +9,6 @@ import qualified Data.CaseInsensitive as CI
|
|||||||
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Data.Bitraversable
|
import Data.Bitraversable
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,6 @@ module Jobs.Handler.Invitation
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Import
|
import Import
|
||||||
import Utils.Lens
|
|
||||||
import Handler.Utils.Mail
|
import Handler.Utils.Mail
|
||||||
|
|
||||||
import qualified Data.CaseInsensitive as CI
|
import qualified Data.CaseInsensitive as CI
|
||||||
|
|||||||
@ -4,7 +4,6 @@ module Jobs.Handler.SendCourseCommunication
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
|
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
|||||||
@ -6,7 +6,6 @@ module Jobs.Handler.SendNotification.SubmissionRated
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Jobs.Handler.SendNotification.Utils
|
import Jobs.Handler.SendNotification.Utils
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,6 @@ module Jobs.Handler.SendNotification.UserAuthModeUpdate
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Import
|
import Import
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Handler.Utils.Mail
|
import Handler.Utils.Mail
|
||||||
import Jobs.Handler.SendNotification.Utils
|
import Jobs.Handler.SendNotification.Utils
|
||||||
|
|||||||
@ -4,7 +4,6 @@ module Jobs.Handler.SendPasswordReset
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Handler.Utils.Users
|
import Handler.Utils.Users
|
||||||
|
|
||||||
|
|||||||
@ -8,8 +8,6 @@ import Handler.Utils.DateTime
|
|||||||
|
|
||||||
import Text.Shakespeare.Text
|
import Text.Shakespeare.Text
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
dispatchJobSendTestEmail :: Email -> MailContext -> Handler ()
|
dispatchJobSendTestEmail :: Email -> MailContext -> Handler ()
|
||||||
dispatchJobSendTestEmail jEmail jMailContext = mailT jMailContext $ do
|
dispatchJobSendTestEmail jEmail jMailContext = mailT jMailContext $ do
|
||||||
_mailTo .= [Address Nothing jEmail]
|
_mailTo .= [Address Nothing jEmail]
|
||||||
|
|||||||
@ -4,7 +4,6 @@ module Jobs.Handler.TransactionLog
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Import hiding (currentYear)
|
import Import hiding (currentYear)
|
||||||
import Utils.Lens hiding ((<.))
|
|
||||||
import Handler.Utils.DateTime
|
import Handler.Utils.DateTime
|
||||||
|
|
||||||
import Database.Persist.Sql (updateWhereCount, deleteWhereCount)
|
import Database.Persist.Sql (updateWhereCount, deleteWhereCount)
|
||||||
|
|||||||
@ -14,8 +14,6 @@ import Data.Proxy (Proxy(..))
|
|||||||
|
|
||||||
import qualified Data.ByteArray as ByteArray
|
import qualified Data.ByteArray as ByteArray
|
||||||
|
|
||||||
import Utils.Lens
|
|
||||||
|
|
||||||
import Network.HTTP.Simple (httpJSON, httpLBS)
|
import Network.HTTP.Simple (httpJSON, httpLBS)
|
||||||
import qualified Network.HTTP.Simple as HTTP
|
import qualified Network.HTTP.Simple as HTTP
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,6 @@ module Jobs.Queue
|
|||||||
import Import hiding ((<>))
|
import Import hiding ((<>))
|
||||||
|
|
||||||
import Utils.Sql
|
import Utils.Sql
|
||||||
import Utils.Lens
|
|
||||||
import Jobs.Types
|
import Jobs.Types
|
||||||
|
|
||||||
import Control.Monad.Trans.Writer (WriterT, runWriterT)
|
import Control.Monad.Trans.Writer (WriterT, runWriterT)
|
||||||
|
|||||||
@ -9,7 +9,6 @@ module Model.Types.DateTime
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Import.NoModel
|
import Import.NoModel
|
||||||
import Control.Lens
|
|
||||||
|
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
import qualified Data.CaseInsensitive as CI
|
import qualified Data.CaseInsensitive as CI
|
||||||
|
|||||||
@ -14,7 +14,6 @@ import Model.Types.Common
|
|||||||
|
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
|
|
||||||
import Control.Lens hiding (universe)
|
|
||||||
import Utils.Lens.TH
|
import Utils.Lens.TH
|
||||||
|
|
||||||
import qualified Data.Csv as Csv
|
import qualified Data.Csv as Csv
|
||||||
|
|||||||
@ -8,7 +8,6 @@ module Model.Types.Misc
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Import.NoModel
|
import Import.NoModel
|
||||||
import Control.Lens
|
|
||||||
|
|
||||||
import Data.Maybe (fromJust)
|
import Data.Maybe (fromJust)
|
||||||
|
|
||||||
|
|||||||
@ -11,8 +11,6 @@ import Import.NoModel
|
|||||||
import Model.Types.Common
|
import Model.Types.Common
|
||||||
import Utils.Lens.TH
|
import Utils.Lens.TH
|
||||||
|
|
||||||
import Control.Lens
|
|
||||||
import Control.Lens.Extras (is)
|
|
||||||
import Generics.Deriving.Monoid (memptydefault, mappenddefault)
|
import Generics.Deriving.Monoid (memptydefault, mappenddefault)
|
||||||
|
|
||||||
import Data.Set (Set)
|
import Data.Set (Set)
|
||||||
|
|||||||
@ -20,8 +20,6 @@ import Data.Word.Word24
|
|||||||
|
|
||||||
import qualified Data.CaseInsensitive as CI
|
import qualified Data.CaseInsensitive as CI
|
||||||
|
|
||||||
import Control.Lens
|
|
||||||
|
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
|
|||||||
@ -44,8 +44,6 @@ import qualified Data.Text.Encoding as Text
|
|||||||
|
|
||||||
import qualified Ldap.Client as Ldap
|
import qualified Ldap.Client as Ldap
|
||||||
|
|
||||||
import Control.Lens
|
|
||||||
|
|
||||||
import qualified Network.HaskellNet.Auth as HaskellNet (UserName, Password, AuthType(..))
|
import qualified Network.HaskellNet.Auth as HaskellNet (UserName, Password, AuthType(..))
|
||||||
import qualified Network.Socket as HaskellNet (PortNumber(..), HostName)
|
import qualified Network.Socket as HaskellNet (PortNumber(..), HostName)
|
||||||
import qualified Network
|
import qualified Network
|
||||||
|
|||||||
@ -3,11 +3,16 @@
|
|||||||
|
|
||||||
module Utils.Lens ( module Utils.Lens ) where
|
module Utils.Lens ( module Utils.Lens ) where
|
||||||
|
|
||||||
import ClassyPrelude.Yesod hiding (HasHttpManager(..))
|
import Import.NoModel
|
||||||
import qualified ClassyPrelude.Yesod as Yesod (HasHttpManager(..))
|
|
||||||
import Model
|
import Model
|
||||||
|
import qualified ClassyPrelude.Yesod as Yesod (HasHttpManager(..))
|
||||||
|
|
||||||
import Control.Lens as Utils.Lens hiding ((<.>), universe, snoc)
|
import Control.Lens as Utils.Lens
|
||||||
|
hiding ( (<.>)
|
||||||
|
, universe
|
||||||
|
, cons, uncons, snoc, unsnoc, (<|)
|
||||||
|
, Index, index, (<.)
|
||||||
|
)
|
||||||
import Control.Lens.Extras as Utils.Lens (is)
|
import Control.Lens.Extras as Utils.Lens (is)
|
||||||
import Utils.Lens.TH as Utils.Lens (makeLenses_, makeClassyFor_)
|
import Utils.Lens.TH as Utils.Lens (makeLenses_, makeClassyFor_)
|
||||||
import Data.Set.Lens as Utils.Lens
|
import Data.Set.Lens as Utils.Lens
|
||||||
@ -42,6 +47,8 @@ _SchoolId = iso unSchoolKey SchoolKey
|
|||||||
-----------------------------------
|
-----------------------------------
|
||||||
-- Lens Definitions for our Types
|
-- Lens Definitions for our Types
|
||||||
|
|
||||||
|
makeClassyFor_ ''Term
|
||||||
|
|
||||||
|
|
||||||
-- makeLenses_ ''Course
|
-- makeLenses_ ''Course
|
||||||
makeClassyFor_ ''Course
|
makeClassyFor_ ''Course
|
||||||
|
|||||||
@ -126,7 +126,7 @@ $if not (null occurrences)
|
|||||||
$maybe desc <- examOccurrenceDescription
|
$maybe desc <- examOccurrenceDescription
|
||||||
#{desc}
|
#{desc}
|
||||||
|
|
||||||
$if gradingShown && not (null parts)
|
$if gradingShown && not (null examParts)
|
||||||
<section>
|
<section>
|
||||||
<h2>
|
<h2>
|
||||||
_{MsgExamParts}
|
_{MsgExamParts}
|
||||||
@ -139,7 +139,7 @@ $if gradingShown && not (null parts)
|
|||||||
<th .table__th>_{MsgExamPartMaxPoints}
|
<th .table__th>_{MsgExamPartMaxPoints}
|
||||||
<th .table__th>_{MsgExamPartResultPoints}
|
<th .table__th>_{MsgExamPartResultPoints}
|
||||||
<tbody>
|
<tbody>
|
||||||
$forall Entity partId ExamPart{examPartName, examPartWeight, examPartMaxPoints} <- parts
|
$forall Entity partId ExamPart{examPartName, examPartWeight, examPartMaxPoints} <- examParts
|
||||||
<tr .table__row>
|
<tr .table__row>
|
||||||
<td .table__td>#{examPartName}
|
<td .table__td>#{examPartName}
|
||||||
<td .table__td>
|
<td .table__td>
|
||||||
|
|||||||
@ -3,14 +3,16 @@ $if null rows && (dbsEmptyStyle == DBESNoHeading)
|
|||||||
_{dbsEmptyMessage}
|
_{dbsEmptyMessage}
|
||||||
$else
|
$else
|
||||||
<div .table-header>
|
<div .table-header>
|
||||||
<div .table__row-count>
|
$if rowCount > 5
|
||||||
_{MsgRowCount rowCount}
|
<div .table__row-count>
|
||||||
|
_{MsgRowCount rowCount}
|
||||||
|
|
||||||
^{table}
|
^{table}
|
||||||
|
|
||||||
<div .table-footer>
|
<div .table-footer>
|
||||||
<div .table__row-count>
|
$if rowCount > 5
|
||||||
_{MsgRowCount rowCount}
|
<div .table__row-count>
|
||||||
|
_{MsgRowCount rowCount}
|
||||||
$# Since the current pagesize is always a member of pagesizeOptions we don't need to check `pageCount > 1`
|
$# Since the current pagesize is always a member of pagesizeOptions we don't need to check `pageCount > 1`
|
||||||
$if toEnum (fromIntegral rowCount) > minimum (pagesizeOptions referencePagesize)
|
$if toEnum (fromIntegral rowCount) > minimum (pagesizeOptions referencePagesize)
|
||||||
^{pagesizeWdgt'}
|
^{pagesizeWdgt'}
|
||||||
|
|||||||
Reference in New Issue
Block a user