feat(sheets): require exam registration
This commit is contained in:
parent
c87c9c13d1
commit
d770afd2c6
@ -332,6 +332,12 @@ SheetPseudonym: Persönliches Abgabe-Pseudonym
|
|||||||
SheetGeneratePseudonym: Generieren
|
SheetGeneratePseudonym: Generieren
|
||||||
SheetAnonymousCorrection: Anonymisierte Korrektur
|
SheetAnonymousCorrection: Anonymisierte Korrektur
|
||||||
SheetAnonymousCorrectionTip: Wenn die Korrektur anonymisiert erfolgt, können Korrektoren die ihnen zugeteilten Abgaben nicht bestimmten Studierenden zuordnen (Name, Matrikelnummer und feste Abgabegruppe der Abgebenden werden versteckt)
|
SheetAnonymousCorrectionTip: Wenn die Korrektur anonymisiert erfolgt, können Korrektoren die ihnen zugeteilten Abgaben nicht bestimmten Studierenden zuordnen (Name, Matrikelnummer und feste Abgabegruppe der Abgebenden werden versteckt)
|
||||||
|
SheetRequireExam: Anmeldung zu einer Prüfung voraussetzen?
|
||||||
|
SheetRequireExamTip: Wenn die Anmeldung zu einer Prüfung vorausgesetzt wird, können nur Kursteilnehmer abgeben, die zum Zeitpunkt der Abgabe auch zur gewählten Prüfung angemeldet sind. Auch der Download von Übungsblatt-Dateien wird nur zur Prüfung angemeldeten Kursteilnehmern erlaubt.
|
||||||
|
SheetRequiredExam: Prüfung
|
||||||
|
SheetShowRequiredExam: Vorausgesetze Prüfungsanmeldung
|
||||||
|
SheetSubmissionExamRegistrationRequired: Um die Angabe für dieses Übungsblatt herunterzuladen oder Abzugeben ist eine Anmeldung zur genannten Prüfung erforderlich.
|
||||||
|
SheetFilesExamRegistrationRequired: Um die Angabe für dieses Übungsblatt herunterzuladen oder Abzugeben ist eine Anmeldung zu der oben genannten Prüfung erforderlich.
|
||||||
|
|
||||||
SheetArchiveFileTypeDirectoryExercise: aufgabenstellung
|
SheetArchiveFileTypeDirectoryExercise: aufgabenstellung
|
||||||
SheetArchiveFileTypeDirectoryHint: hinweis
|
SheetArchiveFileTypeDirectoryHint: hinweis
|
||||||
@ -452,6 +458,8 @@ UnauthorizedExamCorrector: Sie sind nicht als Korrektor für diese Prüfung eing
|
|||||||
UnauthorizedExamCorrectorGrade: Sie haben nicht die Berechtigung für diese Prüfung Gesamtergebnisse einzutragen.
|
UnauthorizedExamCorrectorGrade: Sie haben nicht die Berechtigung für diese Prüfung Gesamtergebnisse einzutragen.
|
||||||
UnauthorizedCorrectorAny: Sie sind nicht als Korrektor für eine Veranstaltung eingetragen.
|
UnauthorizedCorrectorAny: Sie sind nicht als Korrektor für eine Veranstaltung eingetragen.
|
||||||
UnauthorizedRegistered: Sie sind nicht als Teilnehmer für diese Veranstaltung registriert.
|
UnauthorizedRegistered: Sie sind nicht als Teilnehmer für diese Veranstaltung registriert.
|
||||||
|
UnauthorizedRegisteredExam: Sie sind nicht als Teilnehmer für diese Prüfung registriert.
|
||||||
|
UnauthorizedRegisteredAnyExam: Sie sind nicht als Teilnehmer für eine Prüfung registriert.
|
||||||
UnauthorizedAllocationRegistered: Sie sind nicht als Teilnehmer für diese Zentralanmeldung registriert.
|
UnauthorizedAllocationRegistered: Sie sind nicht als Teilnehmer für diese Zentralanmeldung registriert.
|
||||||
UnauthorizedExamResult: Sie haben keine Ergebnisse in dieser Prüfung.
|
UnauthorizedExamResult: Sie haben keine Ergebnisse in dieser Prüfung.
|
||||||
UnauthorizedExamOccurrenceRegistration: Anmeldung zur Prüfung erfolgt nicht inkl. Raum/Termin.
|
UnauthorizedExamOccurrenceRegistration: Anmeldung zur Prüfung erfolgt nicht inkl. Raum/Termin.
|
||||||
|
|||||||
@ -331,6 +331,12 @@ SheetPseudonym: Personal pseudonym
|
|||||||
SheetGeneratePseudonym: Generate
|
SheetGeneratePseudonym: Generate
|
||||||
SheetAnonymousCorrection: Anonymized correction
|
SheetAnonymousCorrection: Anonymized correction
|
||||||
SheetAnonymousCorrectionTip: If correction is anonymized, correctors cannot see which students are involved in submissions that are assigned to them (names, matriculation numbers, and registered submission groups are hidden)
|
SheetAnonymousCorrectionTip: If correction is anonymized, correctors cannot see which students are involved in submissions that are assigned to them (names, matriculation numbers, and registered submission groups are hidden)
|
||||||
|
SheetRequireExam: Require registration for an exam?
|
||||||
|
SheetRequireExamTip: If registration for an exam is required, only course participants that are registered for that exam at the time of submission will be allowed to create submission. Download of sheet files will also be restricted to course participants registered for the exam.
|
||||||
|
SheetRequiredExam: Exam
|
||||||
|
SheetShowRequiredExam: Required exam registration
|
||||||
|
SheetSubmissionExamRegistrationRequired: Registration for the specified exam is required to download files associated with this exercise sheet and to submit.
|
||||||
|
SheetFilesExamRegistrationRequired: To download files for this exercise sheet or to submit you must first register for the exam mentioned above.
|
||||||
|
|
||||||
SheetArchiveFileTypeDirectoryExercise: exercise
|
SheetArchiveFileTypeDirectoryExercise: exercise
|
||||||
SheetArchiveFileTypeDirectoryHint: hint
|
SheetArchiveFileTypeDirectoryHint: hint
|
||||||
@ -450,6 +456,8 @@ UnauthorizedExamCorrector: You are no corrector for this exam.
|
|||||||
UnauthorizedExamCorrectorGrade: You may not enter overall exam achievements for this exam.
|
UnauthorizedExamCorrectorGrade: You may not enter overall exam achievements for this exam.
|
||||||
UnauthorizedCorrectorAny: You are no corrector for any course.
|
UnauthorizedCorrectorAny: You are no corrector for any course.
|
||||||
UnauthorizedRegistered: You are no participant in this course.
|
UnauthorizedRegistered: You are no participant in this course.
|
||||||
|
UnauthorizedRegisteredExam: You are not registered for this exam.
|
||||||
|
UnauthorizedRegisteredAnyExam: You are not registered for an exam.
|
||||||
UnauthorizedAllocationRegistered: You are no participant in this central allocation.
|
UnauthorizedAllocationRegistered: You are no participant in this central allocation.
|
||||||
UnauthorizedExamResult: You have no results in this exam.
|
UnauthorizedExamResult: You have no results in this exam.
|
||||||
UnauthorizedExamOccurrenceRegistration: Registration for exam is not done including occurrence/room.
|
UnauthorizedExamOccurrenceRegistration: Registration for exam is not done including occurrence/room.
|
||||||
|
|||||||
@ -13,6 +13,7 @@ Sheet -- exercise sheet for a given course
|
|||||||
submissionMode SubmissionMode -- Submission upload by students and/or through tutors?
|
submissionMode SubmissionMode -- Submission upload by students and/or through tutors?
|
||||||
autoDistribute Bool default=false -- Should correctors be assigned submissions automagically?
|
autoDistribute Bool default=false -- Should correctors be assigned submissions automagically?
|
||||||
anonymousCorrection Bool default=true
|
anonymousCorrection Bool default=true
|
||||||
|
requireExamRegistration ExamId Maybe -- Students may only submit if they are registered for the given exam
|
||||||
CourseSheet course name
|
CourseSheet course name
|
||||||
deriving Generic
|
deriving Generic
|
||||||
SheetEdit -- who edited when a row in table "Course", kept indefinitely
|
SheetEdit -- who edited when a row in table "Course", kept indefinitely
|
||||||
|
|||||||
16
routes
16
routes
@ -147,26 +147,26 @@
|
|||||||
/sheet/unassigned SheetOldUnassignedR GET
|
/sheet/unassigned SheetOldUnassignedR GET
|
||||||
/sheet/#SheetName SheetR:
|
/sheet/#SheetName SheetR:
|
||||||
/show SShowR GET !timeANDcourse-registered !timeANDmaterials !corrector !timeANDtutor
|
/show SShowR GET !timeANDcourse-registered !timeANDmaterials !corrector !timeANDtutor
|
||||||
/show/download SArchiveR GET !timeANDcourse-registered !timeANDmaterials !corrector !timeANDtutor
|
/show/download SArchiveR GET !timeANDcourse-registeredANDexam-registered !timeANDmaterialsANDexam-registered !corrector !timeANDtutor
|
||||||
/edit SEditR GET POST
|
/edit SEditR GET POST
|
||||||
/delete SDelR GET POST
|
/delete SDelR GET POST
|
||||||
/subs SSubsR GET POST -- for lecturer only
|
/subs SSubsR GET POST -- for lecturer only
|
||||||
!/subs/new SubmissionNewR GET POST !timeANDcourse-registeredANDuser-submissionsANDsubmission-group
|
!/subs/new SubmissionNewR GET POST !timeANDcourse-registeredANDuser-submissionsANDsubmission-groupANDexam-registered
|
||||||
!/subs/own SubmissionOwnR GET !free -- just redirect
|
!/subs/own SubmissionOwnR GET !free -- just redirect
|
||||||
!/subs/assign SAssignR GET POST !lecturerANDtime
|
!/subs/assign SAssignR GET POST !lecturerANDtime
|
||||||
/subs/#CryptoFileNameSubmission SubmissionR:
|
/subs/#CryptoFileNameSubmission SubmissionR:
|
||||||
/ SubShowR GET POST !ownerANDtimeANDuser-submissionsANDsubmission-group !ownerANDread !correctorANDread
|
/ SubShowR GET POST !ownerANDtimeANDuser-submissionsANDsubmission-groupANDexam-registered !ownerANDread !correctorANDread
|
||||||
/delete SubDelR GET POST !ownerANDtimeANDuser-submissions
|
/delete SubDelR GET POST !ownerANDtimeANDuser-submissionsANDexam-registered
|
||||||
/assign SubAssignR GET POST !lecturerANDtime
|
/assign SubAssignR GET POST !lecturerANDtime
|
||||||
/correction CorrectionR GET POST !corrector !ownerANDreadANDrated
|
/correction CorrectionR GET POST !corrector !ownerANDreadANDrated
|
||||||
/invite SInviteR GET POST !ownerANDtimeANDuser-submissionsANDsubmission-group
|
/invite SInviteR GET POST !ownerANDtimeANDuser-submissionsANDsubmission-groupANDexam-registered
|
||||||
!/#SubmissionFileType SubArchiveR GET !owner !corrector
|
!/#SubmissionFileType SubArchiveR GET !owner !corrector
|
||||||
!/#SubmissionFileType/*FilePath SubDownloadR GET !owner !corrector
|
!/#SubmissionFileType/*FilePath SubDownloadR GET !owner !corrector
|
||||||
/iscorrector SIsCorrR GET !corrector -- Route is used to check for corrector access to this sheet
|
/iscorrector SIsCorrR GET !corrector -- Route is used to check for corrector access to this sheet
|
||||||
/pseudonym SPseudonymR GET POST !course-registeredANDcorrector-submissions
|
/pseudonym SPseudonymR GET POST !course-registeredANDcorrector-submissionsANDexam-registered
|
||||||
/corrector-invite/ SCorrInviteR GET POST
|
/corrector-invite/ SCorrInviteR GET POST
|
||||||
!/#SheetFileType SZipR GET !timeANDcourse-registered !timeANDmaterials !corrector !timeANDtutor
|
!/#SheetFileType SZipR GET !timeANDcourse-registeredANDexam-registered !timeANDmaterialsANDexam-registered !corrector !timeANDtutor
|
||||||
!/#SheetFileType/*FilePath SFileR GET !timeANDcourse-registered !timeANDmaterials !corrector !timeANDtutor
|
!/#SheetFileType/*FilePath SFileR GET !timeANDcourse-registeredANDexam-registered !timeANDmaterialsANDexam-registered !corrector !timeANDtutor
|
||||||
/file MaterialListR GET !course-registered !materials !corrector !tutor
|
/file MaterialListR GET !course-registered !materials !corrector !tutor
|
||||||
/file/new MaterialNewR GET POST
|
/file/new MaterialNewR GET POST
|
||||||
/file/#MaterialName MaterialR:
|
/file/#MaterialName MaterialR:
|
||||||
|
|||||||
@ -1087,7 +1087,23 @@ tagAccessPredicate AuthExamRegistered = APDB $ \mAuthId route _ -> case route of
|
|||||||
E.&&. course E.^. CourseSchool E.==. E.val ssh
|
E.&&. course E.^. CourseSchool E.==. E.val ssh
|
||||||
E.&&. course E.^. CourseShorthand E.==. E.val csh
|
E.&&. course E.^. CourseShorthand E.==. E.val csh
|
||||||
E.&&. exam E.^. ExamName E.==. E.val examn
|
E.&&. exam E.^. ExamName E.==. E.val examn
|
||||||
guardMExceptT hasRegistration (unauthorizedI MsgUnauthorizedRegistered)
|
guardMExceptT hasRegistration $ unauthorizedI MsgUnauthorizedRegisteredExam
|
||||||
|
return Authorized
|
||||||
|
CSheetR tid ssh csh shn _ -> exceptT return return $ do
|
||||||
|
requiredExam' <- $cachedHereBinary (tid, ssh, csh, shn) . lift . E.selectMaybe . E.from $ \(course `E.InnerJoin` sheet) -> do
|
||||||
|
E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId
|
||||||
|
E.where_ $ course E.^. CourseTerm E.==. E.val tid
|
||||||
|
E.&&. course E.^. CourseSchool E.==. E.val ssh
|
||||||
|
E.&&. course E.^. CourseShorthand E.==. E.val csh
|
||||||
|
E.&&. sheet E.^. SheetName E.==. E.val shn
|
||||||
|
return $ sheet E.^. SheetRequireExamRegistration
|
||||||
|
requiredExam <- maybeMExceptT (unauthorizedI MsgUnauthorizedRegisteredExam) . return $ E.unValue <$> requiredExam'
|
||||||
|
whenIsJust requiredExam $ \eId -> do
|
||||||
|
authId <- maybeExceptT AuthenticationRequired $ return mAuthId
|
||||||
|
isRegistered <- $cachedHereBinary (authId, eId) . lift . E.selectExists . E.from $ \examRegistration ->
|
||||||
|
E.where_ $ examRegistration E.^. ExamRegistrationExam E.==. E.val eId
|
||||||
|
E.&&. examRegistration E.^. ExamRegistrationUser E.==. E.val authId
|
||||||
|
guardMExceptT isRegistered $ unauthorizedI MsgUnauthorizedRegisteredExam
|
||||||
return Authorized
|
return Authorized
|
||||||
CourseR tid ssh csh _ -> exceptT return return $ do
|
CourseR tid ssh csh _ -> exceptT return return $ do
|
||||||
authId <- maybeExceptT AuthenticationRequired $ return mAuthId
|
authId <- maybeExceptT AuthenticationRequired $ return mAuthId
|
||||||
@ -1098,7 +1114,7 @@ tagAccessPredicate AuthExamRegistered = APDB $ \mAuthId route _ -> case route of
|
|||||||
E.&&. course E.^. CourseTerm E.==. E.val tid
|
E.&&. course E.^. CourseTerm E.==. E.val tid
|
||||||
E.&&. course E.^. CourseSchool E.==. E.val ssh
|
E.&&. course E.^. CourseSchool E.==. E.val ssh
|
||||||
E.&&. course E.^. CourseShorthand E.==. E.val csh
|
E.&&. course E.^. CourseShorthand E.==. E.val csh
|
||||||
guardMExceptT hasRegistration (unauthorizedI MsgUnauthorizedRegistered)
|
guardMExceptT hasRegistration $ unauthorizedI MsgUnauthorizedRegisteredAnyExam
|
||||||
return Authorized
|
return Authorized
|
||||||
r -> $unsupportedAuthPredicate AuthExamRegistered r
|
r -> $unsupportedAuthPredicate AuthExamRegistered r
|
||||||
tagAccessPredicate AuthExamResult = APDB $ \mAuthId route _ -> case route of
|
tagAccessPredicate AuthExamResult = APDB $ \mAuthId route _ -> case route of
|
||||||
|
|||||||
@ -52,6 +52,7 @@ postSEditR tid ssh csh shn = do
|
|||||||
, sfAutoDistribute = sheetAutoDistribute
|
, sfAutoDistribute = sheetAutoDistribute
|
||||||
, sfAnonymousCorrection = sheetAnonymousCorrection
|
, sfAnonymousCorrection = sheetAnonymousCorrection
|
||||||
, sfCorrectors = currentLoads
|
, sfCorrectors = currentLoads
|
||||||
|
, sfRequireExamRegistration = sheetRequireExamRegistration
|
||||||
}
|
}
|
||||||
|
|
||||||
let action = uniqueReplace sid -- More specific error message for edit old sheet could go here by using myReplaceUnique instead
|
let action = uniqueReplace sid -- More specific error message for edit old sheet could go here by using myReplaceUnique instead
|
||||||
@ -62,7 +63,7 @@ handleSheetEdit tid ssh csh msId template dbAction = do
|
|||||||
let mbshn = sfName <$> template
|
let mbshn = sfName <$> template
|
||||||
aid <- requireAuthId
|
aid <- requireAuthId
|
||||||
cid <- runDB $ getKeyBy404 $ TermSchoolCourseShort tid ssh csh
|
cid <- runDB $ getKeyBy404 $ TermSchoolCourseShort tid ssh csh
|
||||||
((res,formWidget), formEnctype) <- runFormPost $ makeSheetForm msId template
|
((res,formWidget), formEnctype) <- runFormPost $ makeSheetForm cid msId template
|
||||||
case res of
|
case res of
|
||||||
(FormSuccess SheetForm{..}) -> do
|
(FormSuccess SheetForm{..}) -> do
|
||||||
saveOkay <- runDBJobs $ do
|
saveOkay <- runDBJobs $ do
|
||||||
@ -82,6 +83,7 @@ handleSheetEdit tid ssh csh msId template dbAction = do
|
|||||||
, sheetSubmissionMode = sfSubmissionMode
|
, sheetSubmissionMode = sfSubmissionMode
|
||||||
, sheetAutoDistribute = sfAutoDistribute
|
, sheetAutoDistribute = sfAutoDistribute
|
||||||
, sheetAnonymousCorrection = sfAnonymousCorrection
|
, sheetAnonymousCorrection = sfAnonymousCorrection
|
||||||
|
, sheetRequireExamRegistration = sfRequireExamRegistration
|
||||||
}
|
}
|
||||||
mbsid <- dbAction newSheet
|
mbsid <- dbAction newSheet
|
||||||
case mbsid of
|
case mbsid of
|
||||||
|
|||||||
@ -27,6 +27,7 @@ type Loads = Map (Either UserEmail UserId) (InvitationData SheetCorrector)
|
|||||||
data SheetForm = SheetForm
|
data SheetForm = SheetForm
|
||||||
{ sfName :: SheetName
|
{ sfName :: SheetName
|
||||||
, sfDescription :: Maybe Html
|
, sfDescription :: Maybe Html
|
||||||
|
, sfRequireExamRegistration :: Maybe ExamId
|
||||||
, sfSheetF, sfHintF, sfSolutionF, sfMarkingF :: Maybe FileUploads
|
, sfSheetF, sfHintF, sfSolutionF, sfMarkingF :: Maybe FileUploads
|
||||||
, sfVisibleFrom :: Maybe UTCTime
|
, sfVisibleFrom :: Maybe UTCTime
|
||||||
, sfActiveFrom :: Maybe UTCTime
|
, sfActiveFrom :: Maybe UTCTime
|
||||||
@ -51,8 +52,8 @@ getFtIdMap sId = do
|
|||||||
return sheetFile
|
return sheetFile
|
||||||
return $ partitionFileType [ (sheetFileType, sf ^. _FileReference . _1) | Entity _ sf@SheetFile{..} <- allSheetFiles ]
|
return $ partitionFileType [ (sheetFileType, sf ^. _FileReference . _1) | Entity _ sf@SheetFile{..} <- allSheetFiles ]
|
||||||
|
|
||||||
makeSheetForm :: Maybe SheetId -> Maybe SheetForm -> Form SheetForm
|
makeSheetForm :: CourseId -> Maybe SheetId -> Maybe SheetForm -> Form SheetForm
|
||||||
makeSheetForm msId template = identifyForm FIDsheet . validateForm validateSheet $ \html -> do
|
makeSheetForm cId msId template = identifyForm FIDsheet . validateForm validateSheet $ \html -> do
|
||||||
oldFileIds <- (return.) <$> case msId of
|
oldFileIds <- (return.) <$> case msId of
|
||||||
Nothing -> return $ partitionFileType mempty
|
Nothing -> return $ partitionFileType mempty
|
||||||
(Just sId) -> liftHandler $ runDB $ getFtIdMap sId
|
(Just sId) -> liftHandler $ runDB $ getFtIdMap sId
|
||||||
@ -61,6 +62,7 @@ makeSheetForm msId template = identifyForm FIDsheet . validateForm validateSheet
|
|||||||
flip (renderAForm FormStandard) html $ SheetForm
|
flip (renderAForm FormStandard) html $ SheetForm
|
||||||
<$> areq (textField & cfStrip & cfCI) (fslI MsgSheetName) (sfName <$> template)
|
<$> areq (textField & cfStrip & cfCI) (fslI MsgSheetName) (sfName <$> template)
|
||||||
<*> aopt htmlField (fslI MsgSheetDescription) (sfDescription <$> template)
|
<*> aopt htmlField (fslI MsgSheetDescription) (sfDescription <$> template)
|
||||||
|
<*> optionalActionA (apreq (examField Nothing cId) (fslI MsgSheetRequiredExam) (sfRequireExamRegistration =<< template)) (fslI MsgSheetRequireExam & setTooltip MsgSheetRequireExamTip) (is _Just . sfRequireExamRegistration <$> template)
|
||||||
<* aformSection MsgSheetFormFiles
|
<* aformSection MsgSheetFormFiles
|
||||||
<*> aopt (multiFileField $ oldFileIds SheetExercise) (fslI MsgSheetExercise) (sfSheetF <$> template)
|
<*> aopt (multiFileField $ oldFileIds SheetExercise) (fslI MsgSheetExercise) (sfSheetF <$> template)
|
||||||
<*> aopt (multiFileField $ oldFileIds SheetHint) (fslI MsgSheetHint) (sfHintF <$> template)
|
<*> aopt (multiFileField $ oldFileIds SheetHint) (fslI MsgSheetHint) (sfHintF <$> template)
|
||||||
|
|||||||
@ -64,6 +64,7 @@ postSheetNewR tid ssh csh = do
|
|||||||
, sfAutoDistribute = sheetAutoDistribute
|
, sfAutoDistribute = sheetAutoDistribute
|
||||||
, sfCorrectors = loads
|
, sfCorrectors = loads
|
||||||
, sfAnonymousCorrection = sheetAnonymousCorrection
|
, sfAnonymousCorrection = sheetAnonymousCorrection
|
||||||
|
, sfRequireExamRegistration = Nothing
|
||||||
}
|
}
|
||||||
_other -> Nothing
|
_other -> Nothing
|
||||||
let action newSheet = -- More specific error message for new sheet could go here, if insertUnique returns Nothing
|
let action newSheet = -- More specific error message for new sheet could go here, if insertUnique returns Nothing
|
||||||
|
|||||||
@ -103,6 +103,18 @@ getSShowR tid ssh csh shn = do
|
|||||||
, formEncoding = generateEnctype
|
, formEncoding = generateEnctype
|
||||||
, formSubmit = FormNoSubmit
|
, formSubmit = FormNoSubmit
|
||||||
}
|
}
|
||||||
|
mRequiredExam <- fmap join . for (sheetRequireExamRegistration sheet) $ \eId -> fmap (fmap $(E.unValueN 4)) . runDB . E.selectMaybe . E.from $ \(exam `E.InnerJoin` course) -> do
|
||||||
|
E.on $ exam E.^. ExamCourse E.==. course E.^. CourseId
|
||||||
|
E.where_ $ exam E.^. ExamId E.==. E.val eId
|
||||||
|
return (course E.^. CourseTerm, course E.^. CourseSchool, course E.^. CourseShorthand, exam E.^. ExamName)
|
||||||
|
mRequiredExamLink <- runMaybeT $ do
|
||||||
|
(etid, essh, ecsh, examn) <- hoistMaybe mRequiredExam
|
||||||
|
let eUrl = CExamR etid essh ecsh examn EShowR
|
||||||
|
guardM $ hasReadAccessTo eUrl
|
||||||
|
return eUrl
|
||||||
|
mMissingExamRegistration <- for (sheetRequireExamRegistration sheet) $ \eId -> maybeT (return True) $ do
|
||||||
|
uid <- MaybeT maybeAuthId
|
||||||
|
lift . fmap not . runDB $ exists [ ExamRegistrationExam ==. eId, ExamRegistrationUser ==. uid ]
|
||||||
|
|
||||||
defaultLayout $ do
|
defaultLayout $ do
|
||||||
setTitleI $ prependCourseTitle tid ssh csh $ SomeMessage shn
|
setTitleI $ prependCourseTitle tid ssh csh $ SomeMessage shn
|
||||||
|
|||||||
@ -1765,6 +1765,15 @@ examPassedGradeField :: forall m.
|
|||||||
examPassedGradeField = hoistField liftHandler . selectField $ (<>) <$> (fmap Right <$> optionsFinite) <*> (fmap Left <$> optionsFinite)
|
examPassedGradeField = hoistField liftHandler . selectField $ (<>) <$> (fmap Right <$> optionsFinite) <*> (fmap Left <$> optionsFinite)
|
||||||
|
|
||||||
|
|
||||||
|
examField :: forall m.
|
||||||
|
( MonadHandler m
|
||||||
|
, HandlerSite m ~ UniWorX
|
||||||
|
)
|
||||||
|
=> Maybe (SomeMessage UniWorX) -> CourseId -> Field m ExamId
|
||||||
|
examField optMsg cId = hoistField liftHandler . selectField' optMsg . (fmap $ fmap entityKey) $
|
||||||
|
optionsPersistCryptoId [ExamCourse ==. cId] [Asc ExamName] examName
|
||||||
|
|
||||||
|
|
||||||
data CsvFormatOptions' = CsvFormatOptionsPreset' CsvPreset
|
data CsvFormatOptions' = CsvFormatOptionsPreset' CsvPreset
|
||||||
| CsvFormatOptionsCustom'
|
| CsvFormatOptionsCustom'
|
||||||
deriving (Eq, Ord, Read, Show, Generic, Typeable)
|
deriving (Eq, Ord, Read, Show, Generic, Typeable)
|
||||||
|
|||||||
@ -1,5 +1,12 @@
|
|||||||
$newline never
|
$newline never
|
||||||
<dl .deflist>
|
<dl .deflist>
|
||||||
|
<dt .deflist__dt>
|
||||||
|
^{formatGregorianW 2020 07 20}
|
||||||
|
<dd .deflist__dd>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Abgabe und Download von einzelnen Übungsblättern kann auf Prüfungsteilnehmer beschränkt werden.
|
||||||
|
|
||||||
<dt .deflist__dt>
|
<dt .deflist__dt>
|
||||||
^{formatGregorianW 2020 06 17}
|
^{formatGregorianW 2020 06 17}
|
||||||
<dd .deflist__dd>
|
<dd .deflist__dd>
|
||||||
|
|||||||
@ -1,5 +1,12 @@
|
|||||||
$newline never
|
$newline never
|
||||||
<dl .deflist>
|
<dl .deflist>
|
||||||
|
<dt .deflist__dt>
|
||||||
|
^{formatGregorianW 2020 07 20}
|
||||||
|
<dd .deflist__dd>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Submission for and download of exercise sheets may be restricted to participants who are registered for an exam.
|
||||||
|
|
||||||
<dt .deflist__dt>
|
<dt .deflist__dt>
|
||||||
^{formatGregorianW 2020 06 17}
|
^{formatGregorianW 2020 06 17}
|
||||||
<dd .deflist__dd>
|
<dd .deflist__dd>
|
||||||
|
|||||||
@ -35,8 +35,20 @@ $maybe descr <- sheetDescription sheet
|
|||||||
$maybe solution <- solutionFrom <* guard hasSolution
|
$maybe solution <- solutionFrom <* guard hasSolution
|
||||||
<dt .deflist__dt>_{MsgSheetSolutionFrom}
|
<dt .deflist__dt>_{MsgSheetSolutionFrom}
|
||||||
<dd .deflist__dd>#{solution}
|
<dd .deflist__dd>#{solution}
|
||||||
|
$maybe (_, _, _, examn) <- mRequiredExam
|
||||||
|
<dt .deflist__dt>
|
||||||
|
_{MsgSheetShowRequiredExam}
|
||||||
|
<p .deflist__explanation>
|
||||||
|
_{MsgSheetSubmissionExamRegistrationRequired}
|
||||||
|
<dd .deflist__dd>
|
||||||
|
$maybe url <- mRequiredExamLink
|
||||||
|
<a href=@{url}>
|
||||||
|
#{examn}
|
||||||
|
$nothing
|
||||||
|
#{examn}
|
||||||
<dt .deflist__dt>_{MsgSheetSubmissionMode}
|
<dt .deflist__dt>_{MsgSheetSubmissionMode}
|
||||||
<dd .deflist__dd>_{classifySubmissionMode (sheetSubmissionMode sheet)}
|
<dd .deflist__dd>
|
||||||
|
_{classifySubmissionMode (sheetSubmissionMode sheet)}
|
||||||
$case sheetSubmissionMode sheet
|
$case sheetSubmissionMode sheet
|
||||||
$of SubmissionMode True _
|
$of SubmissionMode True _
|
||||||
^{messageTooltip submissionTip}
|
^{messageTooltip submissionTip}
|
||||||
@ -63,3 +75,6 @@ $if hasFiles
|
|||||||
<section>
|
<section>
|
||||||
<h2>^{simpleLinkI (SomeMessage MsgSheetFiles) zipLink}
|
<h2>^{simpleLinkI (SomeMessage MsgSheetFiles) zipLink}
|
||||||
^{fileTable}
|
^{fileTable}
|
||||||
|
$elseif fromMaybe False mMissingExamRegistration
|
||||||
|
<section>
|
||||||
|
^{notificationWidget NotificationBroad Warning (i18n MsgSheetFilesExamRegistrationRequired)}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user