feat(allocations): table of allocation users

This commit is contained in:
Gregor Kleen 2020-02-27 11:09:16 +01:00
parent aef7fad5d8
commit 2735d465eb
10 changed files with 303 additions and 15 deletions

View File

@ -406,6 +406,7 @@ UnauthorizedExamOffice: Sie sind nicht mit Prüfungsverwaltung beauftragt.
UnauthorizedExamExamOffice: Es existieren keine Prüfungsergebnisse für Nutzer, für die Sie mit der Prüfungsverwaltung beauftragt sind. UnauthorizedExamExamOffice: Es existieren keine Prüfungsergebnisse für Nutzer, für die Sie mit der Prüfungsverwaltung beauftragt sind.
UnauthorizedExternalExamExamOffice: Es existieren keine Prüfungsergebnisse für Nutzer, für die Sie mit der Prüfungsverwaltung beauftragt sind. UnauthorizedExternalExamExamOffice: Es existieren keine Prüfungsergebnisse für Nutzer, für die Sie mit der Prüfungsverwaltung beauftragt sind.
UnauthorizedEvaluation: Sie sind nicht mit der Kursumfragenverwaltung beauftragt. UnauthorizedEvaluation: Sie sind nicht mit der Kursumfragenverwaltung beauftragt.
UnauthorizedAllocationAdmin: Sie sind nicht mit der Administration von Zentralanmeldungen beauftragt.
UnauthorizedSchoolLecturer: Sie sind nicht als Veranstalter für dieses Institut eingetragen. UnauthorizedSchoolLecturer: Sie sind nicht als Veranstalter für dieses Institut eingetragen.
UnauthorizedLecturer: Sie sind nicht als Veranstalter für diese Veranstaltung eingetragen. UnauthorizedLecturer: Sie sind nicht als Veranstalter für diese Veranstaltung eingetragen.
UnauthorizedAllocationLecturer: Sie sind nicht als Veranstalter für eine Veranstaltung dieser Zentralanmeldung eingetragen. UnauthorizedAllocationLecturer: Sie sind nicht als Veranstalter für eine Veranstaltung dieser Zentralanmeldung eingetragen.
@ -1013,6 +1014,7 @@ NotificationTriggerKindEvaluation: Für Vorlesungsumfragen
NotificationTriggerKindAllocationStaff: Für Zentralanmeldungen (Dozenten) NotificationTriggerKindAllocationStaff: Für Zentralanmeldungen (Dozenten)
NotificationTriggerKindAllocationParticipant: Für Zentralanmeldungen NotificationTriggerKindAllocationParticipant: Für Zentralanmeldungen
NotificationTriggerKindSubmissionUser: Für Mitabgebende einer Übungsblatt-Abgabe NotificationTriggerKindSubmissionUser: Für Mitabgebende einer Übungsblatt-Abgabe
NotificationTriggerKindAllocationAdmin: Für Administratoren von Zentralanmeldungen
CorrCreate: Abgaben registrieren CorrCreate: Abgaben registrieren
UnknownPseudonymWord pseudonymWord@Text: Unbekanntes Pseudonym-Wort "#{pseudonymWord}" UnknownPseudonymWord pseudonymWord@Text: Unbekanntes Pseudonym-Wort "#{pseudonymWord}"
@ -1210,6 +1212,7 @@ MenuExternalExamNew: Neue externe Prüfung
MenuExternalExamList: Externe Prüfungen MenuExternalExamList: Externe Prüfungen
MenuParticipantsList: Kursteilnehmerlisten MenuParticipantsList: Kursteilnehmerlisten
MenuParticipantsIntersect: Überschneidung von Kursteilnehmern MenuParticipantsIntersect: Überschneidung von Kursteilnehmern
MenuAllocationUsers: Bewerber
BreadcrumbSubmissionFile: Datei BreadcrumbSubmissionFile: Datei
BreadcrumbSubmissionUserInvite: Einladung zur Abgabe BreadcrumbSubmissionUserInvite: Einladung zur Abgabe
@ -1275,6 +1278,7 @@ BreadcrumbParticipantsList: Kursteilnehmerlisten
BreadcrumbParticipants: Kursteilnehmerliste BreadcrumbParticipants: Kursteilnehmerliste
BreadcrumbExamAutoOccurrence: Automatische Termin-/Raumverteilung BreadcrumbExamAutoOccurrence: Automatische Termin-/Raumverteilung
BreadcrumbStorageKey: Lokalen Schlüssel generieren BreadcrumbStorageKey: Lokalen Schlüssel generieren
BreadcrumbAllocationUsers: Bewerber
ExternalExamEdit coursen@CourseName examn@ExamName: Bearbeiten: #{coursen}, #{examn} ExternalExamEdit coursen@CourseName examn@ExamName: Bearbeiten: #{coursen}, #{examn}
ExternalExamGrades coursen@CourseName examn@ExamName: Prüfungsleistungen: #{coursen}, #{examn} ExternalExamGrades coursen@CourseName examn@ExamName: Prüfungsleistungen: #{coursen}, #{examn}
@ -1289,6 +1293,7 @@ AuthTagFree: Seite ist universell zugänglich
AuthTagAdmin: Nutzer ist Administrator AuthTagAdmin: Nutzer ist Administrator
AuthTagExamOffice: Nutzer ist mit Prüfungsverwaltung beauftragt AuthTagExamOffice: Nutzer ist mit Prüfungsverwaltung beauftragt
AuthTagEvaluation: Nutzer ist mit Kursumfragenverwaltung beauftragt AuthTagEvaluation: Nutzer ist mit Kursumfragenverwaltung beauftragt
AuthTagAllocationAdmin: Nutzer ist mit der Administration von Zentralanmeldungen beauftragt
AuthTagToken: Nutzer präsentiert Authorisierungs-Token AuthTagToken: Nutzer präsentiert Authorisierungs-Token
AuthTagNoEscalation: Nutzer-Rechte werden nicht auf fremde Institute ausgeweitet AuthTagNoEscalation: Nutzer-Rechte werden nicht auf fremde Institute ausgeweitet
AuthTagDeprecated: Seite ist nicht überholt AuthTagDeprecated: Seite ist nicht überholt
@ -2003,6 +2008,7 @@ SchoolAdmin: Admin
SchoolLecturer: Dozent SchoolLecturer: Dozent
SchoolEvaluation: Kursumfragenverwaltung SchoolEvaluation: Kursumfragenverwaltung
SchoolExamOffice: Prüfungsverwaltung SchoolExamOffice: Prüfungsverwaltung
SchoolAllocation: Zentralanmeldungs-Administration
ApplicationEditTip: Während des Bewerbungszeitraums können eigene Bewerbungen beliebig angepasst und auch wieder zurückgezogen werden. ApplicationEditTip: Während des Bewerbungszeitraums können eigene Bewerbungen beliebig angepasst und auch wieder zurückgezogen werden.
@ -2336,3 +2342,19 @@ InfoLecturerAllocations: Zentralanmeldungen
ParticipantsIntersectCourseOption tid@TermId ssh@SchoolId coursen@CourseName: #{tid} - #{ssh} - #{coursen} ParticipantsIntersectCourseOption tid@TermId ssh@SchoolId coursen@CourseName: #{tid} - #{ssh} - #{coursen}
ParticipantsIntersectCourses: Kurse ParticipantsIntersectCourses: Kurse
AllocationUsersTitle tid@TermId ssh@SchoolId ash@AllocationShorthand: #{tid}-#{ssh}-#{ash}: Bewerber
AllocationUsersApplied: Bewerbungen
AllocationUsersAssigned: Zuweisungen
AllocationUsersVetoed: Vetos
AllocationUsersRequested: Angefragte Plätze
CsvColumnAllocationUserSurname: Nachname(n) des Bewerbers
CsvColumnAllocationUserFirstName: Vorname(n) des Bewerbers
CsvColumnAllocationUserName: Voller Name des Bewerbers
CsvColumnAllocationUserMatriculation: Matrikelnummer des Bewerber
CsvColumnAllocationUserRequested: Maximale Anzahl von Plätzen, die der Bewerber bereit ist, zu akzeptieren
CsvColumnAllocationUserApplied: Anzahl von Bewerbungen, die der Bewerber eingereicht hat
CsvColumnAllocationUserVetos: Anzahl von Bewerbungen, die von Kursverwaltern ein Veto oder eine Note erhalten haben, die äquivalent ist zu "Nicht Bestanden" (5.0)
CsvColumnAllocationUserAssigned: Anzahl von Plätzen, die der Bewerber durch diese Zentralanmeldung bereits erhalten hat
AllocationUsersCsvName tid@TermId ssh@SchoolId ash@AllocationShorthand: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase ash}-bewerber

1
routes
View File

@ -108,6 +108,7 @@
/ AShowR GET !free / AShowR GET !free
/register ARegisterR POST !time /register ARegisterR POST !time
/course/#CryptoUUIDCourse/apply AApplyR POST !timeANDallocation-registered /course/#CryptoUUIDCourse/apply AApplyR POST !timeANDallocation-registered
/users AUsersR GET POST !allocation-admin
/participants ParticipantsListR GET !evaluation /participants ParticipantsListR GET !evaluation
/participants/#TermId/#SchoolId ParticipantsR GET !evaluation /participants/#TermId/#SchoolId ParticipantsR GET !evaluation

View File

@ -424,7 +424,7 @@ tagAccessPredicate AuthExamOffice = APDB $ \mAuthId route _ -> case route of
guardMExceptT isExamOffice (unauthorizedI MsgUnauthorizedExamOffice) guardMExceptT isExamOffice (unauthorizedI MsgUnauthorizedExamOffice)
return Authorized return Authorized
tagAccessPredicate AuthEvaluation = APDB $ \mAuthId route _ -> case route of tagAccessPredicate AuthEvaluation = APDB $ \mAuthId route _ -> case route of
ParticipantsR tid ssh -> $cachedHereBinary (mAuthId, tid, ssh) . exceptT return return $ do ParticipantsR _ ssh -> $cachedHereBinary (mAuthId, ssh) . exceptT return return $ do
authId <- maybeExceptT AuthenticationRequired $ return mAuthId authId <- maybeExceptT AuthenticationRequired $ return mAuthId
isEvaluation <- lift . existsBy $ UniqueUserFunction authId ssh SchoolEvaluation isEvaluation <- lift . existsBy $ UniqueUserFunction authId ssh SchoolEvaluation
guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedEvaluation guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedEvaluation
@ -434,6 +434,17 @@ tagAccessPredicate AuthEvaluation = APDB $ \mAuthId route _ -> case route of
isEvaluation <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolEvaluation] isEvaluation <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolEvaluation]
guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedEvaluation guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedEvaluation
return Authorized return Authorized
tagAccessPredicate AuthAllocationAdmin = APDB $ \mAuthId route _ -> case route of
AllocationR _ ssh _ _ -> $cachedHereBinary (mAuthId, ssh) . exceptT return return $ do
authId <- maybeExceptT AuthenticationRequired $ return mAuthId
isEvaluation <- lift . existsBy $ UniqueUserFunction authId ssh SchoolAllocation
guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedAllocationAdmin
return Authorized
_other -> $cachedHereBinary mAuthId . exceptT return return $ do
authId <- maybeExceptT AuthenticationRequired $ return mAuthId
isEvaluation <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolAllocation]
guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedAllocationAdmin
return Authorized
tagAccessPredicate AuthToken = APDB $ \mAuthId route isWrite -> exceptT return return $ tagAccessPredicate AuthToken = APDB $ \mAuthId route isWrite -> exceptT return return $
lift . validateToken mAuthId route isWrite =<< askTokenUnsafe lift . validateToken mAuthId route isWrite =<< askTokenUnsafe
tagAccessPredicate AuthNoEscalation = APDB $ \mAuthId route _ -> case route of tagAccessPredicate AuthNoEscalation = APDB $ \mAuthId route _ -> case route of
@ -2004,18 +2015,20 @@ instance YesodBreadcrumbs UniWorX where
return (CI.original $ unSchoolKey ssh, Just $ TermCourseListR tid) return (CI.original $ unSchoolKey ssh, Just $ TermCourseListR tid)
breadcrumb AllocationListR = i18nCrumb MsgAllocationListTitle $ Just NewsR breadcrumb AllocationListR = i18nCrumb MsgAllocationListTitle $ Just NewsR
breadcrumb (AllocationR tid ssh ash AShowR) = maybeT (i18nCrumb MsgBreadcrumbAllocation $ Just AllocationListR) $ do breadcrumb (AllocationR tid ssh ash sRoute) = case sRoute of
mr <- getMessageRender AShowR -> maybeT (i18nCrumb MsgBreadcrumbAllocation $ Just AllocationListR) $ do
Entity _ Allocation{allocationName} <- MaybeT . runDB . getBy $ TermSchoolAllocationShort tid ssh ash mr <- getMessageRender
return ([st|#{allocationName} (#{mr (ShortTermIdentifier (unTermKey tid))}, #{CI.original (unSchoolKey ssh)})|], Just $ AllocationListR) Entity _ Allocation{allocationName} <- MaybeT . runDB . getBy $ TermSchoolAllocationShort tid ssh ash
breadcrumb (AllocationR tid ssh ash ARegisterR) = i18nCrumb MsgBreadcrumbAllocationRegister . Just $ AllocationR tid ssh ash AShowR return ([st|#{allocationName} (#{mr (ShortTermIdentifier (unTermKey tid))}, #{CI.original (unSchoolKey ssh)})|], Just $ AllocationListR)
breadcrumb (AllocationR tid ssh ash (AApplyR cID)) = maybeT (i18nCrumb MsgBreadcrumbCourse . Just $ AllocationR tid ssh ash AShowR) $ do ARegisterR -> i18nCrumb MsgBreadcrumbAllocationRegister . Just $ AllocationR tid ssh ash AShowR
cid <- decrypt cID AApplyR cID -> maybeT (i18nCrumb MsgBreadcrumbCourse . Just $ AllocationR tid ssh ash AShowR) $ do
Course{..} <- hoist runDB $ do cid <- decrypt cID
aid <- MaybeT . getKeyBy $ TermSchoolAllocationShort tid ssh ash Course{..} <- hoist runDB $ do
guardM . lift $ exists [ AllocationCourseAllocation ==. aid, AllocationCourseCourse ==. cid ] aid <- MaybeT . getKeyBy $ TermSchoolAllocationShort tid ssh ash
MaybeT $ get cid guardM . lift $ exists [ AllocationCourseAllocation ==. aid, AllocationCourseCourse ==. cid ]
return (CI.original courseName, Just $ AllocationR tid ssh ash AShowR) MaybeT $ get cid
return (CI.original courseName, Just $ AllocationR tid ssh ash AShowR)
AUsersR -> i18nCrumb MsgBreadcrumbAllocationUsers . Just $ AllocationR tid ssh ash AShowR
breadcrumb ParticipantsListR = i18nCrumb MsgBreadcrumbParticipantsList $ Just CourseListR breadcrumb ParticipantsListR = i18nCrumb MsgBreadcrumbParticipantsList $ Just CourseListR
breadcrumb (ParticipantsR _ _) = i18nCrumb MsgBreadcrumbParticipants $ Just ParticipantsListR breadcrumb (ParticipantsR _ _) = i18nCrumb MsgBreadcrumbParticipants $ Just ParticipantsListR
@ -2984,7 +2997,7 @@ pageActions TermShowR = do
, navChildren = participantsSecondary , navChildren = participantsSecondary
} }
] ]
pageActions (AllocationR _tid _ssh _ash AShowR) = return pageActions (AllocationR tid ssh ash AShowR) = return
[ NavPageActionPrimary [ NavPageActionPrimary
{ navLink = NavLink { navLink = NavLink
{ navLabel = MsgMenuAllocationInfo { navLabel = MsgMenuAllocationInfo
@ -2996,6 +3009,17 @@ pageActions (AllocationR _tid _ssh _ash AShowR) = return
} }
, navChildren = [] , navChildren = []
} }
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuAllocationUsers
, navRoute = AllocationR tid ssh ash AUsersR
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
] ]
pageActions CourseListR = do pageActions CourseListR = do
participantsSecondary <- pageQuickActions NavQuickViewPageActionSecondary ParticipantsListR participantsSecondary <- pageQuickActions NavQuickViewPageActionSecondary ParticipantsListR

View File

@ -7,3 +7,4 @@ 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 import Handler.Allocation.List as Handler.Allocation
import Handler.Allocation.Users as Handler.Allocation

View File

@ -0,0 +1,196 @@
{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
module Handler.Allocation.Users
( getAUsersR, postAUsersR
) where
import Import
import Handler.Utils
import Handler.Utils.Allocation
import qualified Database.Esqueleto as E
import qualified Database.Esqueleto.Utils.TH as E
import qualified Data.Csv as Csv
type UserTableExpr = E.SqlExpr (Entity User)
`E.InnerJoin` E.SqlExpr (Entity AllocationUser)
queryUser :: Getter UserTableExpr (E.SqlExpr (Entity User))
queryUser = to $(E.sqlIJproj 2 1)
queryAllocationUser :: Getter UserTableExpr (E.SqlExpr (Entity AllocationUser))
queryAllocationUser = to $(E.sqlIJproj 2 2)
queryAppliedCourses :: Getter UserTableExpr (E.SqlExpr (E.Value Int))
queryAppliedCourses = queryAllocationUser . to queryAppliedCourses'
where queryAppliedCourses' allocationUser = E.subSelectCount . E.from $ \courseApplication ->
E.where_ $ courseApplication E.^. CourseApplicationUser E.==. allocationUser E.^. AllocationUserUser
E.&&. courseApplication E.^. CourseApplicationAllocation E.==. E.just (allocationUser E.^. AllocationUserAllocation)
queryAssignedCourses :: Getter UserTableExpr (E.SqlExpr (E.Value Int))
queryAssignedCourses = queryAllocationUser . to queryAssignedCourses'
where queryAssignedCourses' allocationUser = E.subSelectCount . E.from $ \courseParticipant ->
E.where_ $ courseParticipant E.^. CourseParticipantUser E.==. allocationUser E.^. AllocationUserUser
E.&&. courseParticipant E.^. CourseParticipantAllocated E.==. E.just (allocationUser E.^. AllocationUserAllocation)
queryVetoedCourses :: Getter UserTableExpr (E.SqlExpr (E.Value Int))
queryVetoedCourses = queryAllocationUser . to queryVetoedCourses'
where queryVetoedCourses' allocationUser = E.subSelectCount . E.from $ \courseApplication -> do
E.where_ $ courseApplication E.^. CourseApplicationUser E.==. allocationUser E.^. AllocationUserUser
E.&&. courseApplication E.^. CourseApplicationAllocation E.==. E.just (allocationUser E.^. AllocationUserAllocation)
E.where_ $ courseApplication E.^. CourseApplicationRatingVeto
E.||. courseApplication E.^. CourseApplicationRatingPoints `E.in_` E.valList (map Just $ filter (view $ passingGrade . _Wrapped . to not) universeF)
type UserTableData = DBRow ( Entity User
, Entity AllocationUser
, Int -- ^ Applied
, Int -- ^ Assigned
, Int -- ^ Vetoed
)
resultUser :: Lens' UserTableData (Entity User)
resultUser = _dbrOutput . _1
resultAllocationUser :: Lens' UserTableData (Entity AllocationUser)
resultAllocationUser = _dbrOutput . _2
resultAppliedCourses, resultAssignedCourses, resultVetoedCourses :: Lens' UserTableData Int
resultAppliedCourses = _dbrOutput . _3
resultAssignedCourses = _dbrOutput . _4
resultVetoedCourses = _dbrOutput . _5
data AllocationUserTableCsv = AllocationUserTableCsv
{ csvAUserSurname :: Text
, csvAUserFirstName :: Text
, csvAUserName :: Text
, csvAUserMatriculation :: Maybe Text
, csvAUserRequested
, csvAUserApplied
, csvAUserVetos
, csvAUserAssigned :: Natural
} deriving (Generic)
makeLenses_ ''AllocationUserTableCsv
allocationUserTableCsvOptions :: Csv.Options
allocationUserTableCsvOptions = Csv.defaultOptions { Csv.fieldLabelModifier = camelToPathPiece' 3}
instance Csv.ToNamedRecord AllocationUserTableCsv where
toNamedRecord = Csv.genericToNamedRecord allocationUserTableCsvOptions
instance Csv.DefaultOrdered AllocationUserTableCsv where
headerOrder = Csv.genericHeaderOrder allocationUserTableCsvOptions
instance CsvColumnsExplained AllocationUserTableCsv where
csvColumnsExplanations = genericCsvColumnsExplanations allocationUserTableCsvOptions $ mconcat
[ singletonMap 'csvAUserSurname MsgCsvColumnAllocationUserSurname
, singletonMap 'csvAUserFirstName MsgCsvColumnAllocationUserFirstName
, singletonMap 'csvAUserName MsgCsvColumnAllocationUserName
, singletonMap 'csvAUserMatriculation MsgCsvColumnAllocationUserMatriculation
, singletonMap 'csvAUserRequested MsgCsvColumnAllocationUserRequested
, singletonMap 'csvAUserApplied MsgCsvColumnAllocationUserApplied
, singletonMap 'csvAUserVetos MsgCsvColumnAllocationUserVetos
, singletonMap 'csvAUserAssigned MsgCsvColumnAllocationUserAssigned
]
getAUsersR, postAUsersR :: TermId -> SchoolId -> AllocationShorthand -> Handler Html
getAUsersR = postAUsersR
postAUsersR tid ssh ash = do
usersTable <- runDB $ do
Entity aId _ <- getBy404 $ TermSchoolAllocationShort tid ssh ash
now <- liftIO getCurrentTime
resultsDone <- (<= NTop (Just now)) . NTop <$> allocationDone aId
csvName <- getMessageRender <*> pure (MsgAllocationUsersCsvName tid ssh ash)
let
allocationUsersDBTable = DBTable{..}
where
dbtSQLQuery = runReaderT $ do
user <- view queryUser
allocationUser <- view queryAllocationUser
applied <- view queryAppliedCourses
assigned <- view queryAssignedCourses
vetoed <- view queryVetoedCourses
lift $ do
E.on $ user E.^. UserId E.==. allocationUser E.^. AllocationUserUser
E.&&. allocationUser E.^. AllocationUserAllocation E.==. E.val aId
E.where_ $ applied E.>. E.val 0
E.||. assigned E.>. E.val 0
return ( user
, allocationUser
, applied
, assigned
, vetoed)
dbtRowKey = views queryAllocationUser (E.^. AllocationUserId)
dbtProj = runReaderT $ (asks . set _dbrOutput) <=< magnify _dbrOutput $
(,,,,)
<$> view _1 <*> view _2 <*> view (_3 . _Value) <*> view (_4 . _Value) <*> view (_5 . _Value)
dbtColonnade :: Colonnade Sortable _ _
dbtColonnade = mconcat
[ colUserDisplayName $ resultUser . _entityVal . $(multifocusL 2) _userDisplayName _userSurname
, colUserMatriculation $ resultUser . _entityVal . _userMatrikelnummer
, colAllocationRequested $ resultAllocationUser . _entityVal . _allocationUserTotalCourses
, colAllocationApplied resultAppliedCourses
, colAllocationVetoed resultVetoedCourses
, assignedHeated $ colAllocationAssigned resultAssignedCourses
]
where
assignedHeated
| resultsDone = imapColonnade assignedHeated'
| otherwise = id
where
assignedHeated' res
= let maxAssign = min (res ^. resultAllocationUser . _entityVal . _allocationUserTotalCourses . to fromIntegral)
(res ^. resultAppliedCourses)
assigned = res ^. resultAssignedCourses
in cellAttrs <>~ [ ("class", "heated")
, ("style", [st|--hotness: #{tshow (heat maxAssign assigned)}|])
]
dbtSorting = mconcat
[ sortUserName' $ queryUser . $(multifocusG 2) (to (E.^. UserDisplayName)) (to (E.^. UserSurname))
, sortUserMatriculation $ queryUser . (to (E.^. UserMatrikelnummer))
, sortAllocationApplied queryAppliedCourses
, sortAllocationAssigned queryAssignedCourses
, sortAllocationRequested $ queryAllocationUser . (to (E.^. AllocationUserTotalCourses))
, sortAllocationVetoed queryVetoedCourses
]
dbtFilter = mconcat
[ fltrUserName' $ queryUser . (to (E.^. UserDisplayName))
, fltrUserMatriculation $ queryUser . (to (E.^. UserMatrikelnummer))
]
dbtFilterUI = mconcat
[ fltrUserNameUI'
, fltrUserMatriculationUI
]
dbtStyle = def { dbsFilterLayout = defaultDBSFilterLayout }
dbtParams = def
dbtIdent :: Text
dbtIdent = "allocation-users"
dbtCsvEncode = simpleCsvEncode csvName $ AllocationUserTableCsv
<$> view (resultUser . _entityVal . _userSurname)
<*> view (resultUser . _entityVal . _userFirstName)
<*> view (resultUser . _entityVal . _userDisplayName)
<*> view (resultUser . _entityVal . _userMatrikelnummer)
<*> view (resultAllocationUser . _entityVal . _allocationUserTotalCourses)
<*> view (resultAppliedCourses . to fromIntegral)
<*> view (resultVetoedCourses . to fromIntegral)
<*> view (resultAssignedCourses . to fromIntegral)
dbtCsvDecode = Nothing
allocationUsersDBTableValidator = def
& defaultSorting [SortAscBy "user-matriculation"]
& defaultPagesize PagesizeAll
dbTableWidget' allocationUsersDBTableValidator allocationUsersDBTable
siteLayoutMsg MsgMenuAllocationUsers $ do
setTitleI $ MsgAllocationUsersTitle tid ssh ash
usersTable

View File

@ -74,6 +74,7 @@ instance RenderMessage UniWorX NotificationTriggerKind where
NTKFunctionary SchoolLecturer -> mr MsgNotificationTriggerKindLecturer NTKFunctionary SchoolLecturer -> mr MsgNotificationTriggerKindLecturer
NTKFunctionary SchoolExamOffice -> mr MsgNotificationTriggerKindExamOffice NTKFunctionary SchoolExamOffice -> mr MsgNotificationTriggerKindExamOffice
NTKFunctionary SchoolEvaluation -> mr MsgNotificationTriggerKindEvaluation NTKFunctionary SchoolEvaluation -> mr MsgNotificationTriggerKindEvaluation
NTKFunctionary SchoolAllocation -> mr MsgNotificationTriggerKindAllocationAdmin
where where
mr = renderMessage f ls mr = renderMessage f ls

View File

@ -784,6 +784,46 @@ fltrDegreeUI :: Maybe (Map FilterKey [Text]) -> AForm (YesodDB UniWorX) (Map Fil
fltrDegreeUI mPrev = fltrDegreeUI mPrev =
prismAForm (singletonFilter "degree") mPrev $ aopt textField (fslI MsgDegreeName) prismAForm (singletonFilter "degree") mPrev $ aopt textField (fslI MsgDegreeName)
-----------------
-- Allocations --
-----------------
colAllocationApplied :: OpticColonnade Int
colAllocationApplied resultApplied = Colonnade.singleton (fromSortable header) body
where
header = Sortable (Just "applied") (i18nCell MsgAllocationUsersApplied)
body = views resultApplied $ cell . toWidget . toMarkup
sortAllocationApplied :: forall applied. PersistField applied => OpticSortColumn applied
sortAllocationApplied queryApplied = singletonMap "applied" . SortColumn $ view queryApplied
colAllocationAssigned :: OpticColonnade Int
colAllocationAssigned resultAssigned = Colonnade.singleton (fromSortable header) body
where
header = Sortable (Just "assigned") (i18nCell MsgAllocationUsersAssigned)
body = views resultAssigned $ cell . toWidget . toMarkup
sortAllocationAssigned :: forall assigned. PersistField assigned => OpticSortColumn assigned
sortAllocationAssigned queryAssigned = singletonMap "assigned" . SortColumn $ view queryAssigned
colAllocationVetoed :: OpticColonnade Int
colAllocationVetoed resultVetoed = Colonnade.singleton (fromSortable header) body
where
header = Sortable (Just "vetoed") (i18nCell MsgAllocationUsersVetoed)
body = views resultVetoed $ cell . toWidget . toMarkup
sortAllocationVetoed :: forall vetoed. PersistField vetoed => OpticSortColumn vetoed
sortAllocationVetoed queryVetoed = singletonMap "vetoed" . SortColumn $ view queryVetoed
colAllocationRequested :: OpticColonnade Natural
colAllocationRequested resultRequested = Colonnade.singleton (fromSortable header) body
where
header = Sortable (Just "requested") (i18nCell MsgAllocationUsersRequested)
body = views resultRequested $ cell . toWidget . toMarkup
sortAllocationRequested :: forall requested. PersistField requested => OpticSortColumn requested
sortAllocationRequested queryRequested = singletonMap "requested" . SortColumn $ view queryRequested
---------------------------- ----------------------------
-- Colonnade manipulation -- -- Colonnade manipulation --
---------------------------- ----------------------------

View File

@ -8,6 +8,7 @@ data SchoolFunction
| SchoolLecturer | SchoolLecturer
| SchoolEvaluation | SchoolEvaluation
| SchoolExamOffice | SchoolExamOffice
| SchoolAllocation
deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic, Typeable) deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic, Typeable)
instance Universe SchoolFunction instance Universe SchoolFunction
instance Finite SchoolFunction instance Finite SchoolFunction

View File

@ -50,6 +50,7 @@ data AuthTag -- sortiert nach gewünschter Reihenfolge auf /authpreds, d.h. Prä
| AuthTutorControl | AuthTutorControl
| AuthExamOffice | AuthExamOffice
| AuthEvaluation | AuthEvaluation
| AuthAllocationAdmin
| AuthAllocationRegistered | AuthAllocationRegistered
| AuthCourseRegistered | AuthCourseRegistered
| AuthTutorialRegistered | AuthTutorialRegistered

View File

@ -219,6 +219,7 @@ makeLenses_ ''CourseUserExamOfficeOptOut
makeLenses_ ''CourseNewsFile makeLenses_ ''CourseNewsFile
makeLenses_ ''AllocationCourse makeLenses_ ''AllocationCourse
makeLenses_ ''AllocationUser
makeLenses_ ''Tutorial makeLenses_ ''Tutorial