feat: course-participant-lists
This commit is contained in:
parent
9e2a733286
commit
88dd5a90b9
@ -404,6 +404,7 @@ UnauthorizedAdminEscalation: Sie sind nicht Administrator für alle Institute, f
|
|||||||
UnauthorizedExamOffice: Sie sind nicht mit Prüfungsverwaltung beauftragt.
|
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.
|
||||||
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.
|
||||||
@ -1203,6 +1204,7 @@ MenuExternalExamUsers: Teilnehmer
|
|||||||
MenuExternalExamEdit: Bearbeiten
|
MenuExternalExamEdit: Bearbeiten
|
||||||
MenuExternalExamNew: Neue externe Prüfung
|
MenuExternalExamNew: Neue externe Prüfung
|
||||||
MenuExternalExamList: Externe Prüfungen
|
MenuExternalExamList: Externe Prüfungen
|
||||||
|
MenuParticipantsList: Kursteilnehmerlisten
|
||||||
|
|
||||||
BreadcrumbSubmissionFile: Datei
|
BreadcrumbSubmissionFile: Datei
|
||||||
BreadcrumbSubmissionUserInvite: Einladung zur Abgabe
|
BreadcrumbSubmissionUserInvite: Einladung zur Abgabe
|
||||||
@ -1263,6 +1265,8 @@ BreadcrumbExternalExamEdit: Editieren
|
|||||||
BreadcrumbExternalExamUsers: Teilnehmer
|
BreadcrumbExternalExamUsers: Teilnehmer
|
||||||
BreadcrumbExternalExamGrades: Prüfungsleistungen
|
BreadcrumbExternalExamGrades: Prüfungsleistungen
|
||||||
BreadcrumbExternalExamStaffInvite: Einladung zum Prüfer
|
BreadcrumbExternalExamStaffInvite: Einladung zum Prüfer
|
||||||
|
BreadcrumbParticipantsList: Kursteilnehmerlisten
|
||||||
|
BreadcrumbParticipants: Kursteilnehmerliste
|
||||||
|
|
||||||
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}
|
||||||
@ -1276,6 +1280,7 @@ AuthPredsActiveChanged: Authorisierungseinstellungen für aktuelle Sitzung gespe
|
|||||||
AuthTagFree: Seite ist universell zugänglich
|
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
|
||||||
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
|
||||||
@ -1720,6 +1725,7 @@ CourseUserCsvName tid@TermId ssh@SchoolId csh@CourseShorthand: #{foldCase (termT
|
|||||||
ExamUserCsvName tid@TermId ssh@SchoolId csh@CourseShorthand examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn}-teilnehmer
|
ExamUserCsvName tid@TermId ssh@SchoolId csh@CourseShorthand examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn}-teilnehmer
|
||||||
ExternalExamUserCsvName tid@TermId ssh@SchoolId coursen@CourseName examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase coursen}-#{foldedCase examn}-teilnehmer
|
ExternalExamUserCsvName tid@TermId ssh@SchoolId coursen@CourseName examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase coursen}-#{foldedCase examn}-teilnehmer
|
||||||
CourseApplicationsTableCsvName tid@TermId ssh@SchoolId csh@CourseShorthand: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-bewerbungen
|
CourseApplicationsTableCsvName tid@TermId ssh@SchoolId csh@CourseShorthand: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-bewerbungen
|
||||||
|
ParticipantsCsvName tid@TermId ssh@SchoolId: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-kursteilnehmer
|
||||||
|
|
||||||
CsvColumnsExplanationsLabel: Spalten- & Zellenformat
|
CsvColumnsExplanationsLabel: Spalten- & Zellenformat
|
||||||
CsvColumnsExplanationsTip: Bedeutung und Format der in der CSV-Datei enthaltenen Spalten
|
CsvColumnsExplanationsTip: Bedeutung und Format der in der CSV-Datei enthaltenen Spalten
|
||||||
|
|||||||
@ -400,6 +400,7 @@ UnauthorizedSiteAdmin: You are no system-wide administrator.
|
|||||||
UnauthorizedSchoolAdmin: You are no administrator for this department.
|
UnauthorizedSchoolAdmin: You are no administrator for this department.
|
||||||
UnauthorizedAdminEscalation: You aren't an administrator for all departments for which this user is an administrator.
|
UnauthorizedAdminEscalation: You aren't an administrator for all departments for which this user is an administrator.
|
||||||
UnauthorizedExamOffice: You are not part of an exam office.
|
UnauthorizedExamOffice: You are not part of an exam office.
|
||||||
|
UnauthorizedEvaluation: You are not charged with course evaluation.
|
||||||
UnauthorizedExamExamOffice: You are not part of the appropriate exam office for any of the participants of this exam.
|
UnauthorizedExamExamOffice: You are not part of the appropriate exam office for any of the participants of this exam.
|
||||||
UnauthorizedExternalExamExamOffice: You are not part of the appropriate exam office for any of the participants of this exam.
|
UnauthorizedExternalExamExamOffice: You are not part of the appropriate exam office for any of the participants of this exam.
|
||||||
UnauthorizedSchoolLecturer: You are no lecturer for this department.
|
UnauthorizedSchoolLecturer: You are no lecturer for this department.
|
||||||
@ -1202,6 +1203,7 @@ MenuExternalExamUsers: Participants
|
|||||||
MenuExternalExamEdit: Edit
|
MenuExternalExamEdit: Edit
|
||||||
MenuExternalExamNew: New external exam
|
MenuExternalExamNew: New external exam
|
||||||
MenuExternalExamList: External exams
|
MenuExternalExamList: External exams
|
||||||
|
MenuParticipantsList: Lists of course participants
|
||||||
|
|
||||||
BreadcrumbSubmissionFile: File
|
BreadcrumbSubmissionFile: File
|
||||||
BreadcrumbSubmissionUserInvite: Invitation to participate in a submission
|
BreadcrumbSubmissionUserInvite: Invitation to participate in a submission
|
||||||
@ -1262,6 +1264,8 @@ BreadcrumbExternalExamEdit: Edit
|
|||||||
BreadcrumbExternalExamUsers: Participants
|
BreadcrumbExternalExamUsers: Participants
|
||||||
BreadcrumbExternalExamGrades: Exam results
|
BreadcrumbExternalExamGrades: Exam results
|
||||||
BreadcrumbExternalExamStaffInvite: Invitation
|
BreadcrumbExternalExamStaffInvite: Invitation
|
||||||
|
BreadcrumbParticipantsList: Lists of course participants
|
||||||
|
BreadcrumbParticipants: Course participants
|
||||||
|
|
||||||
ExternalExamEdit coursen examn: Edit: #{coursen}, #{examn}
|
ExternalExamEdit coursen examn: Edit: #{coursen}, #{examn}
|
||||||
ExternalExamGrades coursen examn: Exam achievements: #{coursen}, #{examn}
|
ExternalExamGrades coursen examn: Exam achievements: #{coursen}, #{examn}
|
||||||
@ -1275,6 +1279,7 @@ AuthPredsActiveChanged: Authorisation settings saved for the current session
|
|||||||
AuthTagFree: Page is freely accessable
|
AuthTagFree: Page is freely accessable
|
||||||
AuthTagAdmin: User is administrator
|
AuthTagAdmin: User is administrator
|
||||||
AuthTagExamOffice: User is part of an exam office
|
AuthTagExamOffice: User is part of an exam office
|
||||||
|
AuthTagEvaluation: User is charged with course evaluation
|
||||||
AuthTagToken: User is presenting an authorisation-token
|
AuthTagToken: User is presenting an authorisation-token
|
||||||
AuthTagNoEscalation: User permissions are not being expanded to other departments
|
AuthTagNoEscalation: User permissions are not being expanded to other departments
|
||||||
AuthTagDeprecated: Page is not deprecated
|
AuthTagDeprecated: Page is not deprecated
|
||||||
@ -1718,6 +1723,7 @@ CourseUserCsvName tid ssh csh: #{foldCase (termToText (unTermKey tid))}-#{folded
|
|||||||
ExamUserCsvName tid ssh csh examn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn}-participants
|
ExamUserCsvName tid ssh csh examn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn}-participants
|
||||||
ExternalExamUserCsvName tid@TermId ssh@SchoolId coursen@CourseName examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase coursen}-#{foldedCase examn}-participants
|
ExternalExamUserCsvName tid@TermId ssh@SchoolId coursen@CourseName examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase coursen}-#{foldedCase examn}-participants
|
||||||
CourseApplicationsTableCsvName tid ssh csh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-applications
|
CourseApplicationsTableCsvName tid ssh csh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-applications
|
||||||
|
ParticipantsCsvName tid ssh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-participants
|
||||||
|
|
||||||
CsvColumnsExplanationsLabel: Column & cell format
|
CsvColumnsExplanationsLabel: Column & cell format
|
||||||
CsvColumnsExplanationsTip: Meaning and format of the columns contained in imported and exported CSV files
|
CsvColumnsExplanationsTip: Meaning and format of the columns contained in imported and exported CSV files
|
||||||
|
|||||||
3
routes
3
routes
@ -108,6 +108,9 @@
|
|||||||
/register ARegisterR POST !time
|
/register ARegisterR POST !time
|
||||||
/course/#CryptoUUIDCourse/apply AApplyR POST !timeANDallocation-registered
|
/course/#CryptoUUIDCourse/apply AApplyR POST !timeANDallocation-registered
|
||||||
|
|
||||||
|
/participants ParticipantsListR GET !evaluation
|
||||||
|
/participants/#TermId/#SchoolId ParticipantsR GET !evaluation
|
||||||
|
|
||||||
|
|
||||||
-- For Pattern Synonyms see Foundation
|
-- For Pattern Synonyms see Foundation
|
||||||
/course/ CourseListR GET !free
|
/course/ CourseListR GET !free
|
||||||
|
|||||||
@ -123,6 +123,7 @@ import Handler.Allocation
|
|||||||
import Handler.ExamOffice
|
import Handler.ExamOffice
|
||||||
import Handler.Metrics
|
import Handler.Metrics
|
||||||
import Handler.ExternalExam
|
import Handler.ExternalExam
|
||||||
|
import Handler.Participants
|
||||||
|
|
||||||
|
|
||||||
-- This line actually creates our YesodDispatch instance. It is the second half
|
-- This line actually creates our YesodDispatch instance. It is the second half
|
||||||
|
|||||||
@ -388,8 +388,19 @@ tagAccessPredicate AuthExamOffice = APDB $ \mAuthId route _ -> case route of
|
|||||||
return Authorized
|
return Authorized
|
||||||
_other -> $cachedHereBinary mAuthId . exceptT return return $ do
|
_other -> $cachedHereBinary mAuthId . exceptT return return $ do
|
||||||
authId <- maybeExceptT AuthenticationRequired $ return mAuthId
|
authId <- maybeExceptT AuthenticationRequired $ return mAuthId
|
||||||
adrights <- lift $ selectFirst [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolExamOffice] []
|
isExamOffice <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolExamOffice]
|
||||||
guardMExceptT (isJust adrights) (unauthorizedI MsgUnauthorizedExamOffice)
|
guardMExceptT isExamOffice (unauthorizedI MsgUnauthorizedExamOffice)
|
||||||
|
return Authorized
|
||||||
|
tagAccessPredicate AuthEvaluation = APDB $ \mAuthId route _ -> case route of
|
||||||
|
ParticipantsR tid ssh -> $cachedHereBinary (mAuthId, tid, ssh) . exceptT return return $ do
|
||||||
|
authId <- maybeExceptT AuthenticationRequired $ return mAuthId
|
||||||
|
isEvaluation <- lift . existsBy $ UniqueUserFunction authId ssh SchoolEvaluation
|
||||||
|
guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedEvaluation
|
||||||
|
return Authorized
|
||||||
|
_other -> $cachedHereBinary mAuthId . exceptT return return $ do
|
||||||
|
authId <- maybeExceptT AuthenticationRequired $ return mAuthId
|
||||||
|
isEvaluation <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolEvaluation]
|
||||||
|
guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedEvaluation
|
||||||
return Authorized
|
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
|
||||||
@ -1838,6 +1849,9 @@ instance YesodBreadcrumbs UniWorX where
|
|||||||
MaybeT $ get cid
|
MaybeT $ get cid
|
||||||
return (CI.original courseName, Just $ AllocationR tid ssh ash AShowR)
|
return (CI.original courseName, Just $ AllocationR tid ssh ash AShowR)
|
||||||
|
|
||||||
|
breadcrumb ParticipantsListR = i18nCrumb MsgBreadcrumbParticipantsList $ Just CourseListR
|
||||||
|
breadcrumb (ParticipantsR _ _) = i18nCrumb MsgBreadcrumbParticipants $ Just ParticipantsListR
|
||||||
|
|
||||||
breadcrumb CourseListR = i18nCrumb MsgMenuCourseList Nothing
|
breadcrumb CourseListR = i18nCrumb MsgMenuCourseList Nothing
|
||||||
breadcrumb CourseNewR = i18nCrumb MsgMenuCourseNew $ Just CourseListR
|
breadcrumb CourseNewR = i18nCrumb MsgMenuCourseNew $ Just CourseListR
|
||||||
breadcrumb (CourseR tid ssh csh CShowR) = maybeT (i18nCrumb MsgBreadcrumbCourse . Just $ TermSchoolCourseListR tid ssh) $ do
|
breadcrumb (CourseR tid ssh csh CShowR) = maybeT (i18nCrumb MsgBreadcrumbCourse . Just $ TermSchoolCourseListR tid ssh) $ do
|
||||||
@ -2411,6 +2425,14 @@ pageActions TermShowR =
|
|||||||
, menuItemModal = False
|
, menuItemModal = False
|
||||||
, menuItemAccessCallback' = return True
|
, menuItemAccessCallback' = return True
|
||||||
}
|
}
|
||||||
|
, MenuItem
|
||||||
|
{ menuItemType = PageActionPrime
|
||||||
|
, menuItemLabel = MsgMenuParticipantsList
|
||||||
|
, menuItemIcon = Nothing
|
||||||
|
, menuItemRoute = SomeRoute ParticipantsListR
|
||||||
|
, menuItemModal = False
|
||||||
|
, menuItemAccessCallback' = return True
|
||||||
|
}
|
||||||
]
|
]
|
||||||
pageActions (TermCourseListR tid) =
|
pageActions (TermCourseListR tid) =
|
||||||
[ MenuItem
|
[ MenuItem
|
||||||
@ -2467,6 +2489,14 @@ pageActions (CourseListR) =
|
|||||||
, menuItemModal = False
|
, menuItemModal = False
|
||||||
, menuItemAccessCallback' = return True
|
, menuItemAccessCallback' = return True
|
||||||
}
|
}
|
||||||
|
, MenuItem
|
||||||
|
{ menuItemType = PageActionPrime
|
||||||
|
, menuItemLabel = MsgMenuParticipantsList
|
||||||
|
, menuItemIcon = Nothing
|
||||||
|
, menuItemRoute = SomeRoute ParticipantsListR
|
||||||
|
, menuItemModal = False
|
||||||
|
, menuItemAccessCallback' = return True
|
||||||
|
}
|
||||||
]
|
]
|
||||||
pageActions (CourseNewR) = [
|
pageActions (CourseNewR) = [
|
||||||
MenuItem
|
MenuItem
|
||||||
@ -3184,6 +3214,16 @@ pageActions (EExamR tid ssh coursen examn EEUsersR) =
|
|||||||
, menuItemAccessCallback' = return True
|
, menuItemAccessCallback' = return True
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
pageActions ParticipantsListR =
|
||||||
|
[ MenuItem
|
||||||
|
{ menuItemType = PageActionPrime
|
||||||
|
, menuItemLabel = MsgCsvOptions
|
||||||
|
, menuItemIcon = Nothing
|
||||||
|
, menuItemRoute = SomeRoute CsvOptionsR
|
||||||
|
, menuItemModal = True
|
||||||
|
, menuItemAccessCallback' = return True
|
||||||
|
}
|
||||||
|
]
|
||||||
pageActions _ = []
|
pageActions _ = []
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
79
src/Handler/Participants.hs
Normal file
79
src/Handler/Participants.hs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
|
||||||
|
module Handler.Participants
|
||||||
|
( getParticipantsListR
|
||||||
|
, getParticipantsR
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Import
|
||||||
|
|
||||||
|
import qualified Database.Esqueleto as E
|
||||||
|
import qualified Database.Esqueleto.Utils as E
|
||||||
|
|
||||||
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
|
import Handler.Utils.Csv
|
||||||
|
import Handler.Utils.ContentDisposition
|
||||||
|
|
||||||
|
import qualified Data.Csv as Csv
|
||||||
|
|
||||||
|
import qualified Data.Conduit.List as C
|
||||||
|
|
||||||
|
|
||||||
|
data ParticipantEntry = ParticipantEntry
|
||||||
|
{ peCourse :: CourseName
|
||||||
|
, peEmail :: UserEmail
|
||||||
|
} deriving (Eq, Ord, Read, Show, Generic, Typeable)
|
||||||
|
|
||||||
|
instance ToNamedRecord ParticipantEntry where
|
||||||
|
toNamedRecord ParticipantEntry{..} = Csv.namedRecord
|
||||||
|
[ "course" Csv..= peCourse
|
||||||
|
, "email" Csv..= peEmail
|
||||||
|
]
|
||||||
|
|
||||||
|
instance DefaultOrdered ParticipantEntry where
|
||||||
|
headerOrder _ = Csv.header ["course", "email"]
|
||||||
|
|
||||||
|
|
||||||
|
getParticipantsListR :: Handler Html
|
||||||
|
getParticipantsListR = do
|
||||||
|
schoolTerms'' <- runDB . E.select . E.from $ \(school `E.InnerJoin` term) -> do
|
||||||
|
E.on E.true
|
||||||
|
|
||||||
|
E.where_ . E.exists . E.from $ \(course `E.InnerJoin` participant) -> do
|
||||||
|
E.on $ course E.^. CourseId E.==. participant E.^. CourseParticipantCourse
|
||||||
|
E.where_ $ course E.^. CourseTerm E.==. term E.^. TermId
|
||||||
|
E.&&. course E.^. CourseSchool E.==. school E.^. SchoolId
|
||||||
|
|
||||||
|
return (school E.^. SchoolId, term E.^. TermId)
|
||||||
|
|
||||||
|
schoolTerms' <- flip filterM schoolTerms'' $ \(E.Value ssh, E.Value tid) ->
|
||||||
|
hasReadAccessTo $ ParticipantsR tid ssh
|
||||||
|
|
||||||
|
let schoolTerms :: Set (SchoolId, TermId)
|
||||||
|
schoolTerms = setOf (folded . $(multifocusG 2) (_1 . _Value) (_2 . _Value)) schoolTerms'
|
||||||
|
|
||||||
|
siteLayoutMsg MsgMenuParticipantsList $ do
|
||||||
|
setTitleI MsgMenuParticipantsList
|
||||||
|
|
||||||
|
let schools :: Set SchoolId
|
||||||
|
schools = Set.map (view _1) schoolTerms
|
||||||
|
terms :: Set TermId
|
||||||
|
terms = Set.map (view _2) schoolTerms
|
||||||
|
$(widgetFile "participants-list")
|
||||||
|
|
||||||
|
getParticipantsR :: TermId -> SchoolId -> Handler TypedContent
|
||||||
|
getParticipantsR tid ssh = do
|
||||||
|
csvName <- timestampCsv <*> fmap (flip (addExtension `on` unpack) extensionCsv) (getMessageRender <*> pure (MsgParticipantsCsvName tid ssh))
|
||||||
|
setContentDisposition' $ Just csvName
|
||||||
|
respondDefaultOrderedCsvDB $ E.selectSource partQuery .| C.map toParticipantEntry
|
||||||
|
where
|
||||||
|
partQuery = E.from $ \(course `E.InnerJoin` participant `E.InnerJoin` user) -> do
|
||||||
|
E.on $ user E.^. UserId E.==. participant E.^. CourseParticipantUser
|
||||||
|
E.on $ course E.^. CourseId E.==. participant E.^. CourseParticipantCourse
|
||||||
|
|
||||||
|
E.where_ $ course E.^. CourseTerm E.==. E.val tid
|
||||||
|
E.&&. course E.^. CourseSchool E.==. E.val ssh
|
||||||
|
|
||||||
|
return (course E.^. CourseName, user E.^. UserEmail)
|
||||||
|
|
||||||
|
toParticipantEntry (E.Value peCourse, E.Value peEmail) = ParticipantEntry{..}
|
||||||
@ -50,6 +50,7 @@ data AuthTag -- sortiert nach gewünschter Reihenfolge auf /authpreds, d.h. Prä
|
|||||||
| AuthTutor
|
| AuthTutor
|
||||||
| AuthTutorControl
|
| AuthTutorControl
|
||||||
| AuthExamOffice
|
| AuthExamOffice
|
||||||
|
| AuthEvaluation
|
||||||
| AuthAllocationRegistered
|
| AuthAllocationRegistered
|
||||||
| AuthCourseRegistered
|
| AuthCourseRegistered
|
||||||
| AuthTutorialRegistered
|
| AuthTutorialRegistered
|
||||||
|
|||||||
@ -49,6 +49,9 @@ _nullable = prism' toNullable fromNullable
|
|||||||
_SchoolId :: Iso' SchoolId SchoolShorthand
|
_SchoolId :: Iso' SchoolId SchoolShorthand
|
||||||
_SchoolId = iso unSchoolKey SchoolKey
|
_SchoolId = iso unSchoolKey SchoolKey
|
||||||
|
|
||||||
|
_TermId :: Iso' TermId TermIdentifier
|
||||||
|
_TermId = iso unTermKey TermKey
|
||||||
|
|
||||||
_StudyTermsId :: Iso' StudyTermsId StudyTermsKey
|
_StudyTermsId :: Iso' StudyTermsId StudyTermsKey
|
||||||
_StudyTermsId = iso unStudyTermsKey StudyTermsKey'
|
_StudyTermsId = iso unStudyTermsKey StudyTermsKey'
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,16 @@
|
|||||||
$newline never
|
$newline never
|
||||||
<dl .deflist>
|
<dl .deflist>
|
||||||
|
<dt .deflist__dt>
|
||||||
|
^{formatGregorianW 2020 01 17}
|
||||||
|
<dd .deflist__dd>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Eintragung von Ergebnissen für extern (nicht in Uni2work #
|
||||||
|
verwaltete) Klausuren zur Übermittlung an Prüfungsbeauftragte
|
||||||
|
<li>
|
||||||
|
Export von Listen von Kursteilnehmern zur Durchführung von #
|
||||||
|
Kursumfragen
|
||||||
|
|
||||||
<dt .deflist__dt>
|
<dt .deflist__dt>
|
||||||
^{formatGregorianW 2019 12 05}
|
^{formatGregorianW 2019 12 05}
|
||||||
<dd .deflist__dd>
|
<dd .deflist__dd>
|
||||||
|
|||||||
@ -1,5 +1,15 @@
|
|||||||
$newline never
|
$newline never
|
||||||
<dl .deflist>
|
<dl .deflist>
|
||||||
|
<dt .deflist__dt>
|
||||||
|
^{formatGregorianW 2020 01 17}
|
||||||
|
<dd .deflist__dd>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Support for uploading results of external exams (not managed #
|
||||||
|
within Uni2work).
|
||||||
|
<li>
|
||||||
|
Export of lists of course participants
|
||||||
|
|
||||||
<dt .deflist__dt>
|
<dt .deflist__dt>
|
||||||
^{formatGregorianW 2019 12 05}
|
^{formatGregorianW 2019 12 05}
|
||||||
<dd .deflist__dd>
|
<dd .deflist__dd>
|
||||||
|
|||||||
17
templates/participants-list.hamlet
Normal file
17
templates/participants-list.hamlet
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
$newline never
|
||||||
|
<div .scrolltable .scrolltable--bordered>
|
||||||
|
<table .table .table--striped .table--hover>
|
||||||
|
<thead>
|
||||||
|
<tr .table__row .table__row--head>
|
||||||
|
<th .table__th>_{MsgTerm}
|
||||||
|
$forall school <- schools
|
||||||
|
<th .table__th>#{unSchoolKey school}
|
||||||
|
<tbody>
|
||||||
|
$forall term <- terms
|
||||||
|
<tr .table__row>
|
||||||
|
<th .table__th>_{ShortTermIdentifier (unTermKey term)}
|
||||||
|
$forall school <- schools
|
||||||
|
<td .table__td>
|
||||||
|
$if Set.member (school, term) schoolTerms
|
||||||
|
<a href=@{ParticipantsR term school}>
|
||||||
|
#{iconFileCSV}
|
||||||
Reference in New Issue
Block a user