chore(exam): add examiner to occurrence options
we intend to use the exam examiner for adding occurrences through tutorials
This commit is contained in:
parent
ae6d3b0fc3
commit
36a3b04ad8
@ -1,6 +0,0 @@
|
||||
if [[ ! -d .stack-work-test ]]; then
|
||||
mv -vT .stack-work .stack-work-test
|
||||
[[ -d .stack-work-build ]] && mv -vT .stack-work-build .stack-work
|
||||
else
|
||||
echo "Directory .stack-work-test exists already."
|
||||
fi
|
||||
@ -64,7 +64,7 @@ ExamAutomaticGradingTip: Sollen die Gesamtleistungen der Teilnehmer:innen automa
|
||||
ExamBonus: Bonuspunkte-System
|
||||
ExamGradingMode: Bewertungsmodus
|
||||
ExamGradingModeTip: In welcher Form werden Prüfungsleistungen für diese Prüfung eingetragen?
|
||||
ExamStaff: Prüfer:innen/Verantwortliche Hochschullehrer:innen
|
||||
ExamStaff: Prüfer:innen
|
||||
ExamStaffTip: Geben Sie bitte in jedem Fall einen Namen an, der Prüfer:in/Veranstalter:in/Hochschullehrer:in eindeutig identifiziert! Sollte der Name des Prüfers/der Prüferin allein womöglich nicht eindeutig sein, so geben Sie bitte eindeutig identifizierende Zusatzinfos, wie beispielsweise den Lehrstuhl bzw. die LFE o.Ä., an.
|
||||
ExamExamOfficeSchools: Zusätzliche Bereiche
|
||||
ExamExamOfficeSchoolsTip: Prüfungsbeauftragte von Bereichen, die Sie hier angeben, erhalten im System (zusätzlich zum primären Bereich der zugehörigen Kursart) volle Einsicht in sämtliche für diese Prüfung hinterlegten Leistungen, unabhängig von den Studiendaten der Teilnehmer:innen.
|
||||
@ -123,6 +123,8 @@ ExamOccurrenceStartMustBeAfterExamStart eoName@ExamOccurrenceName: Beginn des Te
|
||||
ExamOccurrenceEndMustBeBeforeExamEnd eoName@ExamOccurrenceName: Ende des Termins #{eoName} liegt nach dem Ende der Prüfung
|
||||
ExamOccurrenceDuplicate eoRoom@Text eoRange@Text: Raum #{eoRoom}, Termin #{eoRange} kommt mehrfach mit der selben Beschreibung vor
|
||||
ExamOccurrenceDuplicateName eoName@ExamOccurrenceName: Interne Terminbezeichnung #{eoName} kommt mehrfach vor
|
||||
ExamOccurrenceExaminerIsUnset !ident-ok: —
|
||||
ExamOccurrenceExaminerIsHidden: Prüfer wird nur Teilnehmer:innen angezeigt
|
||||
ExamOccurrenceRoomIsUnset !ident-ok: —
|
||||
ExamOccurrenceRoomIsHidden: Raum wird nur Teilnehmer:innen angezeigt
|
||||
ExamOccurrenceCannotBeDeletedDueToRegistrations eoName@ExamOccurrenceName: Termin #{eoName} kann nicht gelöscht werden, da noch Teilnehmer:innen diesem Termin zugewiesen sind. Über die Liste von Prüfungsteilnehmern können Sie zunächst die entsprechenden Terminzuweisungen entfernen.
|
||||
@ -264,6 +266,7 @@ ExamAutoOccurrenceExceptionRoomTooSmall: Automatische Verteilung gescheitert. Ei
|
||||
ExamBonusInfoPoints: Zur Berechnung von Bonuspunkten werden nur jene Blätter herangezogen, deren Aktivitätszeitraum vor Start des jeweiligen Termin/Prüfung begonnen hat
|
||||
ExamUserCsvSheetName tid@TermId ssh@SchoolId csh@CourseShorthand examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn} Teilnehmer
|
||||
|
||||
ExamRoomExaminerTip: Nur bereits eingetragene Korrektor:innen sind hier erlaubt
|
||||
ExamRoomCapacityTip: Maximale Anzahl an Prüfungsteilnehmern für diesen Termin/Raum; leer lassen für unbeschränkte Teilnehmeranzahl
|
||||
ExamRoomMappingRandom: Verteilung
|
||||
ExamFinishHeading: Prüfungsergebnisse sichtbar schalten
|
||||
|
||||
@ -64,7 +64,7 @@ ExamAutomaticGradingTip: Should the exam achievement be automatically computed f
|
||||
ExamBonus: Bonus point system
|
||||
ExamGradingMode: Grading mode
|
||||
ExamGradingModeTip: In which format should grades for this exam be entered?
|
||||
ExamStaff: Examiner/Responsible university teacher
|
||||
ExamStaff: Examiner
|
||||
ExamStaffTip: Please always specify a name that uniquely identifies the examiner/organiser/repsonsible university teacher! If there is a possibility that the name alone is ambiguous please also specify some additional information e.g. the professorial chair or the educational and research unit.
|
||||
ExamExamOfficeSchools: Additional departments
|
||||
ExamExamOfficeSchoolsTip: Exam offices of departments you specify here will also have full access to all results for this exam disregarding the individual participants' features of study.
|
||||
@ -123,8 +123,10 @@ ExamOccurrenceStartMustBeAfterExamStart eoName: Start of the occurrence #{eoName
|
||||
ExamOccurrenceEndMustBeBeforeExamEnd eoName: End of the occurrence #{eoName} must be before the exam end
|
||||
ExamOccurrenceDuplicate eoRoom eoRange: Combination of room #{eoRoom} and occurrence #{eoRange} occurs multiple times
|
||||
ExamOccurrenceDuplicateName eoName: Internal name #{eoName} occurs multiple times
|
||||
ExamOccurrenceExaminerIsUnset !ident-ok: —
|
||||
ExamOccurrenceExaminerIsHidden: Examiner only displayed to participants registered for this occurrence
|
||||
ExamOccurrenceRoomIsUnset: —
|
||||
ExamOccurrenceRoomIsHidden: Room is only displayed to participants registered for this occurrence/room
|
||||
ExamOccurrenceRoomIsHidden: Room only displayed to participants registered for this occurrence
|
||||
ExamOccurrenceCannotBeDeletedDueToRegistrations eoName: Occurrence #{eoName} cannot be deleted because participants are registered for it. You can remove the offending registrations via the list of exam participants.
|
||||
ExamRegistrationMustFollowSchoolSeparationFromStart dayCount: As per school rules there #{pluralEN dayCount "needs" "need"} to be at least #{dayCount} #{pluralEN dayCount "day" "days"} between "Register from" and "Start".
|
||||
ExamRegistrationMustFollowSchoolDuration dayCount: As per school rules there #{pluralEN dayCount "needs" "need"} to be at least #{dayCount} #{pluralEN dayCount "day" "days"} between "Register from" and "Register to".
|
||||
@ -262,6 +264,8 @@ ExamAutoOccurrenceExceptionNoUsers: No participants can be distributed with the
|
||||
ExamAutoOccurrenceExceptionRoomTooSmall: Automatic distribution failed. A different distribution procedure might succeed. Alternatively, minimizing rooms or removing small rooms might help.
|
||||
ExamBonusInfoPoints: When calculating an exam bonus only those sheets will be considered, for which the submission period started before the start of the relevant occurrence/room
|
||||
ExamUserCsvSheetName tid ssh csh examn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn} Participants
|
||||
|
||||
ExamRoomExaminerTip: Only correctors allowed here, add beforehand
|
||||
ExamRoomCapacityTip: Maximum number of participants for this occurrence/room; leave empty for unlimited capacity
|
||||
ExamRoomMappingRandom: Distribution
|
||||
ExamFinishHeading: Make results visible
|
||||
|
||||
@ -34,4 +34,5 @@ NullDeletes: Zum Löschen NULL eingeben.
|
||||
SortPriority: Sortierungspriorität
|
||||
NoProblem: Keine Probleme gefunden
|
||||
Unknown: ist unbekannt
|
||||
Ambiguous: ist uneindeutig
|
||||
UnknownOrNotAllowed: ist unbekannt oder hier nicht erlaubt
|
||||
Ambiguous: ist uneindeutig
|
||||
|
||||
@ -34,4 +34,5 @@ NullDeletes: Enter NULL to delete.
|
||||
SortPriority: Sort order priority
|
||||
NoProblem: No Probleme found
|
||||
Unknown: is unknown
|
||||
Ambiguous: is ambiguous
|
||||
UnknownOrNotAllowed: is unknown or not allowed here
|
||||
Ambiguous: is ambiguous
|
||||
|
||||
@ -37,14 +37,15 @@ ExamPart
|
||||
UniqueExamPartName exam name !force
|
||||
deriving Read Show Eq Ord Generic
|
||||
ExamOccurrence
|
||||
exam ExamId
|
||||
name ExamOccurrenceName
|
||||
room RoomReference Maybe
|
||||
roomHidden Bool default=false
|
||||
capacity Word64 Maybe
|
||||
start UTCTime
|
||||
end UTCTime Maybe
|
||||
description StoredMarkup Maybe
|
||||
exam ExamId
|
||||
name ExamOccurrenceName
|
||||
examiner UserId Maybe
|
||||
room RoomReference Maybe
|
||||
roomHidden Bool default=false
|
||||
capacity Word64 Maybe
|
||||
start UTCTime
|
||||
end UTCTime Maybe
|
||||
description StoredMarkup Maybe
|
||||
UniqueExamOccurrence exam name
|
||||
deriving Generic
|
||||
ExamRegistration
|
||||
|
||||
@ -80,6 +80,7 @@ postEEditR tid ssh csh examn = do
|
||||
ExamOccurrence
|
||||
{ examOccurrenceExam = eId
|
||||
, examOccurrenceName = eofName
|
||||
, examOccurrenceExaminer = eofExaminer
|
||||
, examOccurrenceRoom = eofRoom
|
||||
, examOccurrenceRoomHidden = eofRoomHidden
|
||||
, examOccurrenceCapacity = eofCapacity
|
||||
@ -95,6 +96,7 @@ postEEditR tid ssh csh examn = do
|
||||
lift $ replace eofId' ExamOccurrence
|
||||
{ examOccurrenceExam = eId
|
||||
, examOccurrenceName = eofName
|
||||
, examOccurrenceExaminer = eofExaminer
|
||||
, examOccurrenceRoom = eofRoom
|
||||
, examOccurrenceRoomHidden = eofRoomHidden
|
||||
, examOccurrenceCapacity = eofCapacity
|
||||
@ -118,7 +120,7 @@ postEEditR tid ssh csh examn = do
|
||||
|
||||
when brokenRefs $
|
||||
throwM ExamEditWouldBreakSheetTypeReference
|
||||
|
||||
|
||||
deleteWhere [ ExamPartExam ==. eId, ExamPartId /<-. pIds ]
|
||||
forM_ (Set.toList efExamParts) $ \case
|
||||
ExamPartForm{ epfId = Nothing, .. } -> insert_
|
||||
|
||||
@ -62,6 +62,7 @@ data ExamForm = ExamForm
|
||||
data ExamOccurrenceForm = ExamOccurrenceForm
|
||||
{ eofId :: Maybe CryptoUUIDExamOccurrence
|
||||
, eofName :: ExamOccurrenceName
|
||||
, eofExaminer :: Maybe UserId
|
||||
, eofRoom :: Maybe RoomReference
|
||||
, eofRoomHidden :: Bool
|
||||
, eofCapacity :: Maybe Word64
|
||||
@ -74,6 +75,7 @@ instance Ord ExamOccurrenceForm where
|
||||
compare = mconcat
|
||||
[ comparing eofName
|
||||
, comparing eofStart
|
||||
, comparing eofExaminer
|
||||
, comparing eofRoom
|
||||
, comparing eofEnd
|
||||
, comparing eofCapacity
|
||||
@ -164,7 +166,7 @@ examForm (Entity _ Course{..}) template csrf = hoist liftHandler $ do
|
||||
(fslI MsgExamAuthorshipStatementContent & setTooltip MsgExamAuthorshipStatementContentForcedTip)
|
||||
contentField ttipReq
|
||||
| not schoolSheetExamAuthorshipStatementAllowOther
|
||||
= fmap (fmap authorshipStatementDefinitionContent) . traverse forcedContentField $ entityVal <$> mSchoolAuthorshipStatement
|
||||
= fmap (fmap authorshipStatementDefinitionContent) (traverse (forcedContentField . entityVal) mSchoolAuthorshipStatement)
|
||||
| otherwise
|
||||
= Just <$> reqContentField ttipReq
|
||||
in case schoolSheetExamAuthorshipStatementMode of
|
||||
@ -257,9 +259,18 @@ examOccurrenceForm prev = wFormToAForm $ do
|
||||
|
||||
fmap (fmap Set.fromList) . massInputAccumEditW miAdd' miCell' miButtonAction' miLayout' miIdent' (fslI MsgExamOccurrences) False $ Set.toList <$> prev
|
||||
where
|
||||
examinerField = knownUserField True $ Just $ E.from $ \usr -> do
|
||||
E.where_ $
|
||||
(E.exists . E.from $ \exCorr -> E.where_ $ exCorr E.^. ExamCorrectorUser E.==. usr E.^. UserId
|
||||
) E.||.
|
||||
(E.exists . E.from $ \exOccr -> E.where_ $ exOccr E.^. ExamOccurrenceExaminer E.==. E.just (usr E.^. UserId)
|
||||
)
|
||||
pure usr
|
||||
|
||||
examOccurrenceForm' nudge mPrev csrf = do
|
||||
(eofIdRes, eofIdView) <- mopt hiddenField ("" & addName (nudge "id")) (Just $ eofId =<< mPrev)
|
||||
(eofNameRes, eofNameView) <- mpreq (textField & cfStrip & cfCI) (fslI MsgExamRoomName & addName (nudge "name")) (eofName <$> mPrev)
|
||||
(eofExaminerRes, eofExaminerView) <- mopt examinerField (fslI MsgExamStaff & addName (nudge "examiner")) (eofExaminer <$> mPrev) -- TODO: restrict suggestions!
|
||||
(eofRoomRes', eofRoomView) <- ($ mempty) . renderAForm FormVertical $ (,)
|
||||
<$> roomReferenceFormOpt (fslI MsgExamRoomRoom & addName (nudge "room")) (eofRoom <$> mPrev)
|
||||
<*> apopt checkBoxField (fslI MsgExamRoomRoomHidden & setTooltip MsgExamRoomRoomHiddenTip & addName (nudge "room-hidden")) (eofRoomHidden <$> mPrev)
|
||||
@ -273,6 +284,7 @@ examOccurrenceForm prev = wFormToAForm $ do
|
||||
return ( ExamOccurrenceForm
|
||||
<$> eofIdRes
|
||||
<*> eofNameRes
|
||||
<*> eofExaminerRes
|
||||
<*> eofRoomRes
|
||||
<*> eofRoomHiddenRes
|
||||
<*> eofCapacityRes
|
||||
@ -372,6 +384,7 @@ examFormTemplate (Entity eId Exam{..}) = do
|
||||
return ExamOccurrenceForm
|
||||
{ eofId
|
||||
, eofName = examOccurrenceName
|
||||
, eofExaminer = examOccurrenceExaminer
|
||||
, eofRoom = examOccurrenceRoom
|
||||
, eofRoomHidden = examOccurrenceRoomHidden
|
||||
, eofCapacity = examOccurrenceCapacity
|
||||
|
||||
@ -75,6 +75,7 @@ postCExamNewR tid ssh csh = do
|
||||
| ExamOccurrenceForm{..} <- Set.toList efOccurrences
|
||||
, let examOccurrenceExam = examid
|
||||
examOccurrenceName = eofName
|
||||
examOccurrenceExaminer = eofExaminer
|
||||
examOccurrenceRoom = eofRoom
|
||||
examOccurrenceRoomHidden = eofRoomHidden
|
||||
examOccurrenceCapacity = eofCapacity
|
||||
|
||||
@ -48,7 +48,7 @@ getEShowR tid ssh csh examn = do
|
||||
let occurrenceAssignmentsVisible = NTop (Just cTime) >= NTop examPublishOccurrenceAssignments || examOccurrenceRule == ExamRoomFifo
|
||||
occurrenceAssignmentsShown = occurrenceAssignmentsVisible || lecturerInfoShown
|
||||
|
||||
sheets <- selectList [ SheetCourse ==. examCourse ] []
|
||||
sheets <- selectList [ SheetCourse ==. examCourse ] []
|
||||
let examPartSheets epId = do
|
||||
let sheets' = flip filter sheets $ \(Entity _ Sheet{..}) -> has (_examPart . re _SqlKey . only epId) sheetType
|
||||
flip filterM sheets' $ \(Entity _ Sheet{..}) -> hasReadAccessTo $ CSheetR tid ssh csh sheetName SShowR
|
||||
@ -142,6 +142,11 @@ getEShowR tid ssh csh examn = do
|
||||
guard $ all (\(Entity _ occ, _, _, _) -> examOccurrenceRoom occ == examOccurrenceRoom primeOcc) occurrences
|
||||
guard $ andOf (folded . _4) occurrences
|
||||
examOccurrenceRoom primeOcc
|
||||
examExaminer = do
|
||||
(Entity _ primeOcc, _, _, _) <- occurrences ^? _head
|
||||
guard $ all (\(Entity _ occ, _, _, _) -> examOccurrenceExaminer occ == examOccurrenceExaminer primeOcc) occurrences
|
||||
guard $ andOf (folded . _4) occurrences
|
||||
examOccurrenceExaminer primeOcc
|
||||
registerWidget mOcc
|
||||
| isRegistered <- is _Just $ join registered
|
||||
, examOccurrenceRule /= ExamRoomFifo || (isRegistered && not (orOf (folded . _2) occurrences))
|
||||
@ -204,7 +209,7 @@ getEShowR tid ssh csh examn = do
|
||||
guard $ evalExamModeDNF schoolExamDiscouragedModes examExamMode
|
||||
guardM . lift . hasWriteAccessTo $ CExamR tid ssh csh examn EEditR
|
||||
return $ notification NotificationBroad =<< messageI Warning MsgExamModeSchoolDiscouraged
|
||||
|
||||
|
||||
siteLayoutMsg heading $ do
|
||||
setTitleI heading
|
||||
let
|
||||
|
||||
@ -185,7 +185,7 @@ commR CommunicationRoute{..} = do
|
||||
recipientAForm = postProcess <$> massInputA MassInput{..} (fslI MsgCommRecipients & setTooltip MsgCommRecipientsTip) True (Just chosenRecipients')
|
||||
where
|
||||
miAdd pos@(BoundedPosition RecipientCustom, 0) dim@1 liveliness nudge submitView = guardOn (miAllowAdd pos dim liveliness) $ \csrf -> do
|
||||
(addRes, addView) <- mpreq (multiUserField True Nothing) (fslpI MsgUtilEMail (mr MsgUtilEMail) & setTooltip MsgUtilMultiEmailFieldTip & addName (nudge "email")) Nothing
|
||||
(addRes, addView) <- mpreq (multiUserField False Nothing) (fslpI MsgUtilEMail (mr MsgUtilEMail) & setTooltip MsgUtilMultiEmailFieldTip & addName (nudge "email")) Nothing
|
||||
let
|
||||
addRes' = addRes <&> \nEmails ((Map.elems &&& maybe 0 (succ . snd . fst) . Map.lookupMax) . Map.filterWithKey (\(BoundedPosition c, _) _ -> c == RecipientCustom) -> (oEmails, kStart)) -> FormSuccess . Map.fromList . zip (map (BoundedPosition RecipientCustom, ) [kStart..]) . Set.toList $ nEmails `Set.difference` Set.fromList oEmails
|
||||
return (addRes', $(widgetFile "widgets/communication/recipientAdd"))
|
||||
|
||||
@ -2006,7 +2006,7 @@ knownUserField onlySuggested suggestions = Field{..}
|
||||
let errMsg m = SomeMessage $ SomeMessages [SomeMessage MsgAvsPersonNo, text2message "/", SomeMessage MsgCompanyPersonalNumber, text2message t, m]
|
||||
case dbRes of
|
||||
[uid] -> return $ Right $ Just $ E.unValue uid
|
||||
[] -> return $ Left $ errMsg $ SomeMessage MsgUnknown
|
||||
[] -> return $ Left $ errMsg $ SomeMessage $ bool MsgUnknown MsgUnknownOrNotAllowed onlySuggested
|
||||
_ -> return $ Left $ errMsg $ SomeMessage MsgAmbiguous
|
||||
|
||||
fieldParse _ _ = return $ Right Nothing
|
||||
|
||||
@ -84,6 +84,9 @@ $maybe desc <- examDescription
|
||||
#{c}
|
||||
|
||||
^{notificationPersonalIdentification}
|
||||
$maybe examinerId <- examExaminer
|
||||
<dt .deflist__dt>_{MsgExamStaff}
|
||||
<dd .deflist__dd>^{userIdWidget examinerId}
|
||||
$maybe room <- examRoom
|
||||
<dt .deflist__dt>_{MsgExamRoom}
|
||||
<dd .deflist__dd>^{roomReferenceShortWidget room}
|
||||
@ -194,6 +197,8 @@ $if not (null occurrences)
|
||||
<th .table__th>
|
||||
_{MsgExamRoomName}
|
||||
\ ^{isVisible False}
|
||||
$if is _Nothing examExaminer
|
||||
<th .table__th>_{MsgExamStaff}
|
||||
$if is _Nothing examRoom
|
||||
<th .table__th>_{MsgExamRoom}
|
||||
$if not examTimes
|
||||
@ -234,11 +239,21 @@ $if not (null occurrences)
|
||||
<th .table__th>_{MsgExamRoomDescription}
|
||||
<tbody>
|
||||
$forall (occurrence, registered, rCount, showRoom) <- occurrences
|
||||
$with Entity _occId ExamOccurrence{examOccurrenceName, examOccurrenceRoom, examOccurrenceStart, examOccurrenceEnd, examOccurrenceDescription} <- occurrence
|
||||
$with Entity _occId ExamOccurrence{examOccurrenceName, examOccurrenceExaminer, examOccurrenceRoom, examOccurrenceStart, examOccurrenceEnd, examOccurrenceDescription} <- occurrence
|
||||
$with registerWdgt <- registerWidget (Just occurrence)
|
||||
<tr .table__row :markUnregisteredOccurrences (Just occurrence) && not registered:.occurrence--not-registered>
|
||||
$if occurrenceNamesShown
|
||||
<td .table__td #exam-occurrence__#{examOccurrenceName}>#{examOccurrenceName}
|
||||
$if is _Nothing examExaminer
|
||||
$if showRoom
|
||||
<td .table__td>
|
||||
$maybe examinerId <- examOccurrenceExaminer
|
||||
^{userIdWidget examinerId}
|
||||
$nothing
|
||||
_{MsgExamOccurrenceExaminerIsUnset}
|
||||
$else
|
||||
<td .table__td .explanation>
|
||||
_{MsgExamOccurrenceExaminerIsHidden}
|
||||
$if is _Nothing examRoom
|
||||
$if showRoom
|
||||
<td .table__td>
|
||||
|
||||
@ -5,6 +5,7 @@ $#
|
||||
$# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
<td .form--vertical__cell>#{csrf}^{fvInput eofIdView}^{fvWidget eofNameView}
|
||||
<td .form--vertical__cell>^{fvWidget eofExaminerView}
|
||||
<td .form--vertical__cell>^{eofRoomView}
|
||||
<td .form--vertical__cell>^{fvWidget eofCapacityView}
|
||||
<td .form--vertical__cell>^{fvWidget eofStartView}
|
||||
|
||||
@ -10,6 +10,8 @@ $# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
<th>
|
||||
_{MsgExamRoomName} #
|
||||
<span .form-group__required-marker>
|
||||
<th>
|
||||
_{MsgExamStaff}
|
||||
<th>
|
||||
_{MsgExamRoom}
|
||||
<th>
|
||||
@ -22,6 +24,7 @@ $# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
<td>
|
||||
<tr>
|
||||
<td>
|
||||
<td .explanation>_{MsgExamRoomExaminerTip}
|
||||
<td>
|
||||
<td .explanation>_{MsgExamRoomCapacityTip}
|
||||
<td>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user