feat(exams): exam finish button
This commit is contained in:
parent
a6390eccbd
commit
78d0f2522d
@ -588,13 +588,35 @@ section
|
||||
padding-bottom: 30px
|
||||
border-bottom: 1px solid #d3d3d3
|
||||
|
||||
+ section
|
||||
& + section, & + .two-column-sections
|
||||
margin-top: 20px
|
||||
|
||||
&:last-child
|
||||
border-bottom: none
|
||||
padding-bottom: 0px
|
||||
|
||||
.two-column-sections
|
||||
padding-bottom: 30px
|
||||
border-bottom: 1px solid #d3d3d3
|
||||
|
||||
& + section, & + .two-column-sections
|
||||
margin-top: 20px
|
||||
|
||||
&:last-child
|
||||
border-bottom: none
|
||||
padding-bottom: 0px
|
||||
|
||||
@media (min-width: 768px)
|
||||
display: flex
|
||||
justify-content: space-between
|
||||
|
||||
& > section
|
||||
padding: 0
|
||||
border: none
|
||||
|
||||
margin: 0 auto
|
||||
width: calc(50% - 7px)
|
||||
|
||||
.headline-one
|
||||
margin-bottom: 10px
|
||||
|
||||
|
||||
@ -2551,8 +2551,13 @@ ExamCloseTip: Wenn eine Prüfung abgeschlossen wird, werden Prüfungsbeauftragte
|
||||
ExamCloseReminder: Bitte schließen Sie die Prüfung frühstmöglich, sobald die Prüfungsleistungen sich voraussichtlich nicht mehr ändern werden. Z.B. direkt nach der Klausureinsicht.
|
||||
ExamDidClose: Prüfung erfolgreich abgeschlossen
|
||||
ExamCloseTipOnFinished: Die Prüfung wird automatisch abgeschlossen, also Prüfungsbeauftragte, die im System Note einsehen, benachrichtigt und danach bei Änderungen informiert, sobald die Noten für die Prüfungsteilnehmer veröffentlicht werden.
|
||||
ExamFinishHeading: Prüfungsergebnisse sichtbar schalten
|
||||
BtnFinishExam: Prüfungsergebnisse sichtbar schalten
|
||||
ExamFinishTip: Wenn die Prufungsergebnisse sichtbar geschaltet sind, können Teilnehmende ihre Ergebnisse im System einsehen und werden über diesen Umstand informiert. Es wird die Prüfungfrist „_{MsgExamFinished}“ auf den aktuellen Zeitpunkt gesetzt.
|
||||
ExamDidFinish: Prüfungsergbnisse sichtbar geschaltet
|
||||
|
||||
ExamClosedSince time@Text: Prüfung abgeschlossen seit #{time}
|
||||
ExamFinishedSince time@Text: Prüfungsergebnisse sichtbar seit #{time}
|
||||
|
||||
LecturerInfoTooltipNew: Neues Feature
|
||||
LecturerInfoTooltipProblem: Feature mit bekannten Problemen
|
||||
|
||||
@ -2551,8 +2551,13 @@ ExamCloseTip: When an exam is closed all relevant exam offices, which pull exam
|
||||
ExamCloseReminder: Please close the exam as soon as possible, when exam achievements are no longer expected to change e.g. after inspection of the exam has concluced.
|
||||
ExamDidClose: Successfully closed exam
|
||||
ExamCloseTipOnFinished: The exam will be closed automatically as soon as exam participants are informed of their exam achievements. That means exam offices will be able notified once and after that each time a grade changes.
|
||||
ExamFinishHeading: Make results visible
|
||||
BtnFinishExam: Make results visible
|
||||
ExamFinishTip: After results are made visible participants are notified and can view their result in Uni2work. The exam timestamp “_{MsgExamFinished}” will be set to the current time.
|
||||
ExamDidFinish: Successfully made results visible
|
||||
|
||||
ExamClosedSince time: Exam closed since #{time}
|
||||
ExamFinishedSince time: Exam results visible since #{time}
|
||||
|
||||
LecturerInfoTooltipNew: New feature
|
||||
LecturerInfoTooltipProblem: Feature with known issues
|
||||
|
||||
@ -7,7 +7,7 @@ import Handler.Exam.Register
|
||||
|
||||
import Handler.Exam.AutoOccurrence (examAutoOccurrenceCalculateWidget)
|
||||
|
||||
import Handler.ExamOffice.Exam (examCloseWidget)
|
||||
import Handler.ExamOffice.Exam (examCloseWidget, examFinishWidget)
|
||||
|
||||
import Data.Map ((!?))
|
||||
import qualified Data.Map as Map
|
||||
@ -106,6 +106,7 @@ getEShowR tid ssh csh examn = do
|
||||
partNumbersShown = lecturerInfoShown
|
||||
examClosedShown = lecturerInfoShown && isn't _ExamCloseOnFinished' schoolExamCloseMode
|
||||
showCloseWidget = lecturerInfoShown
|
||||
showFinishWidget = lecturerInfoShown && is _Nothing examFinished
|
||||
showAutoOccurrenceCalculateWidget = lecturerInfoShown
|
||||
showRegisteredCount = lecturerInfoShown
|
||||
examFinishedMsg = if lecturerInfoShown then MsgExamFinished else MsgExamFinishedParticipant
|
||||
@ -191,6 +192,7 @@ getEShowR tid ssh csh examn = do
|
||||
showOccurrenceMappingColumn = examOccurrenceRuleAutomatic examOccurrenceRule && occurrenceAssignmentsShown && is _Just examExamOccurrenceMapping
|
||||
|
||||
closeWgt <- examCloseWidget (SomeRoute $ CExamR tid ssh csh examn EUsersR) eId
|
||||
finishWgt <- examFinishWidget (SomeRoute $ CExamR tid ssh csh examn EUsersR) eId
|
||||
|
||||
let heading = prependCourseTitle tid ssh csh $ CI.original examName
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ import Handler.Utils.StudyFeatures
|
||||
|
||||
import Handler.Exam.AutoOccurrence (examAutoOccurrenceCalculateWidget)
|
||||
|
||||
import Handler.ExamOffice.Exam (examCloseWidget)
|
||||
import Handler.ExamOffice.Exam (examCloseWidget, examFinishWidget)
|
||||
|
||||
import qualified Database.Esqueleto as E
|
||||
import qualified Database.Esqueleto.Utils as E
|
||||
@ -1131,6 +1131,7 @@ postEUsersR tid ssh csh examn = do
|
||||
redirect $ CExamR tid ssh csh examn EUsersR
|
||||
|
||||
closeWgt <- examCloseWidget (SomeRoute $ CExamR tid ssh csh examn EUsersR) eId
|
||||
finishWgt <- examFinishWidget (SomeRoute $ CExamR tid ssh csh examn EUsersR) eId
|
||||
|
||||
siteLayoutMsg (prependCourseTitle tid ssh csh MsgExamUsersHeading) $ do
|
||||
setTitleI $ prependCourseTitle tid ssh csh MsgExamUsersHeading
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
module Handler.ExamOffice.Exam
|
||||
( getEGradesR, postEGradesR
|
||||
, examCloseWidget
|
||||
, examCloseWidget, examFinishWidget
|
||||
) where
|
||||
|
||||
import Import
|
||||
@ -79,6 +79,47 @@ examCloseWidget dest eId = do
|
||||
return $(widgetFile "widgets/exam-close")
|
||||
|
||||
|
||||
data ButtonFinishExam = BtnFinishExam
|
||||
deriving (Enum, Eq, Ord, Bounded, Read, Show, Generic, Typeable)
|
||||
instance Universe ButtonFinishExam
|
||||
instance Finite ButtonFinishExam
|
||||
|
||||
nullaryPathPiece ''ButtonFinishExam $ camelToPathPiece' 1
|
||||
|
||||
embedRenderMessage ''UniWorX ''ButtonFinishExam id
|
||||
instance Button UniWorX ButtonFinishExam where
|
||||
btnClasses BtnFinishExam = [BCIsButton]
|
||||
|
||||
|
||||
examFinishWidget :: SomeRoute UniWorX -> ExamId -> Handler Widget
|
||||
examFinishWidget dest eId = do
|
||||
Exam{examFinished} <- runDB $ get404 eId
|
||||
|
||||
examFinishedStr <- for examFinished $ formatTime SelFormatDateTime
|
||||
|
||||
((finishRes, finishView'), finishEnc) <- runFormPost $ identifyForm BtnFinishExam buttonForm
|
||||
|
||||
formResult finishRes $ \case
|
||||
BtnFinishExam -> do
|
||||
now <- liftIO getCurrentTime
|
||||
|
||||
unless (is _Nothing examFinished) $
|
||||
invalidArgs ["Exam is already finished"]
|
||||
|
||||
runDB $ update eId [ ExamFinished =. Just now ]
|
||||
addMessageI Success MsgExamDidFinish
|
||||
redirect dest
|
||||
|
||||
let finishView = wrapForm finishView' def
|
||||
{ formSubmit = FormNoSubmit
|
||||
, formAction = Just dest
|
||||
, formEncoding = finishEnc
|
||||
}
|
||||
|
||||
return $(widgetFile "widgets/exam-finish")
|
||||
|
||||
|
||||
|
||||
type ExamUserTableExpr = ( E.SqlExpr (Entity ExamResult)
|
||||
`E.InnerJoin` E.SqlExpr (Entity User)
|
||||
)
|
||||
@ -186,7 +227,7 @@ getEGradesR = postEGradesR
|
||||
postEGradesR tid ssh csh examn = do
|
||||
uid <- requireAuthId
|
||||
now <- liftIO getCurrentTime
|
||||
((usersResult, examUsersTable), Entity eId _) <- runDB $ do
|
||||
((usersResult, examUsersTable), Entity eId Exam{examFinished}) <- runDB $ do
|
||||
exam@(Entity eid Exam{..}) <- fetchExam tid ssh csh examn
|
||||
Course{..} <- getJust examCourse
|
||||
|
||||
@ -431,6 +472,7 @@ postEGradesR tid ssh csh examn = do
|
||||
whenIsJust usersResult join
|
||||
|
||||
closeWgt <- examCloseWidget (SomeRoute $ CExamR tid ssh csh examn EGradesR) eId
|
||||
finishWgt <- examFinishWidget (SomeRoute $ CExamR tid ssh csh examn EGradesR) eId
|
||||
hasUsers <- hasReadAccessTo $ CExamR tid ssh csh examn EUsersR
|
||||
|
||||
siteLayoutMsg (prependCourseTitle tid ssh csh MsgExamOfficeExamUsersHeading) $ do
|
||||
|
||||
@ -957,4 +957,4 @@ correctionInvisibleWidget tid ssh csh shn cID (Entity subId sub) = runMaybeT $ d
|
||||
unless (NTop (Just now) >= NTop examFinished) $
|
||||
tellPoint CorrectionInvisibleExamUnfinished
|
||||
|
||||
return $ notificationWidget NotificationBroad Warning $(widgetFile "submission-correction-invisible")
|
||||
return $ notification NotificationBroad =<< messageIconWidget Warning IconInvisible $(widgetFile "submission-correction-invisible")
|
||||
|
||||
@ -1,6 +1,13 @@
|
||||
$newline never
|
||||
<section>
|
||||
^{closeWgt}
|
||||
$if is _Nothing examFinished
|
||||
<div .two-column-sections>
|
||||
<section>
|
||||
^{closeWgt}
|
||||
<section>
|
||||
^{finishWgt}
|
||||
$else
|
||||
<section>
|
||||
^{closeWgt}
|
||||
<section>
|
||||
$if hasUsers
|
||||
^{examGradesExplanation}
|
||||
|
||||
@ -140,12 +140,31 @@ $maybe desc <- examDescription
|
||||
$if is _Nothing (examRequiredEquipment examExamMode)
|
||||
^{notificationPersonalIdentification}
|
||||
|
||||
$if showCloseWidget && is _Nothing examClosed
|
||||
<section>
|
||||
<h2>
|
||||
_{MsgExamCloseHeading}
|
||||
\ ^{isVisible False}
|
||||
^{closeWgt}
|
||||
$if (showCloseWidget && is _Nothing examClosed) && (showFinishWidget && is _Nothing examFinished)
|
||||
<div .two-column-sections>
|
||||
<section>
|
||||
<h2>
|
||||
_{MsgExamCloseHeading}
|
||||
\ ^{isVisible False}
|
||||
^{closeWgt}
|
||||
<section>
|
||||
<h2>
|
||||
_{MsgExamFinishHeading}
|
||||
\ ^{isVisible False}
|
||||
^{finishWgt}
|
||||
$else
|
||||
$if showCloseWidget && is _Nothing examClosed
|
||||
<section>
|
||||
<h2>
|
||||
_{MsgExamCloseHeading}
|
||||
\ ^{isVisible False}
|
||||
^{closeWgt}
|
||||
$if showFinishWidget && is _Nothing examFinished
|
||||
<section>
|
||||
<h2>
|
||||
_{MsgExamFinishHeading}
|
||||
\ ^{isVisible False}
|
||||
^{finishWgt}
|
||||
$if examOccurrenceRuleAutomatic examOccurrenceRule && showAutoOccurrenceCalculateWidget
|
||||
<section>
|
||||
<h2>
|
||||
@ -318,6 +337,8 @@ $if (gradingShown || partsShown) && not (null examParts)
|
||||
$if partNumbersShown
|
||||
<td>
|
||||
<td>
|
||||
$if showPartSheets
|
||||
<td>
|
||||
<td .table__td>
|
||||
#{showFixed True sumMaxPoints}
|
||||
<td>
|
||||
@ -327,6 +348,8 @@ $if (gradingShown || partsShown) && not (null examParts)
|
||||
<td .table__td>
|
||||
<a href=@{CourseR tid ssh csh SheetListR}>
|
||||
_{MsgExamBonusAchieved}
|
||||
$if showPartSheets
|
||||
<td>
|
||||
$if showMaxPoints
|
||||
<td .table__td>
|
||||
$if showAchievedPoints
|
||||
@ -336,6 +359,8 @@ $if (gradingShown || partsShown) && not (null examParts)
|
||||
$if partNumbersShown
|
||||
<td>
|
||||
<td>
|
||||
$if showPartSheets
|
||||
<td>
|
||||
$if showMaxPoints
|
||||
<td>
|
||||
$if showAchievedPoints
|
||||
@ -349,6 +374,8 @@ $if (gradingShown || partsShown) && not (null examParts)
|
||||
$if partNumbersShown
|
||||
<td>
|
||||
<td>
|
||||
$if showPartSheets
|
||||
<td>
|
||||
$if showMaxPoints
|
||||
<td .table__td>
|
||||
#{showFixed True sumMaxPoints}
|
||||
|
||||
@ -1,8 +1,17 @@
|
||||
$newline never
|
||||
<section>
|
||||
$if is _Nothing examClosed
|
||||
<h2>_{MsgExamCloseHeading}
|
||||
^{closeWgt}
|
||||
$if is _Nothing examFinished
|
||||
<div .two-column-sections>
|
||||
<section>
|
||||
<h2>_{MsgExamCloseHeading}
|
||||
^{closeWgt}
|
||||
<section>
|
||||
<h2>_{MsgExamFinishHeading}
|
||||
^{finishWgt}
|
||||
$else
|
||||
<section>
|
||||
$if is _Nothing examClosed
|
||||
<h2>_{MsgExamCloseHeading}
|
||||
^{closeWgt}
|
||||
$if examOccurrenceRuleAutomatic examOccurrenceRule
|
||||
<section>
|
||||
<h2>_{MsgExamAutoOccurrenceHeading}
|
||||
|
||||
8
templates/widgets/exam-finish.hamlet
Normal file
8
templates/widgets/exam-finish.hamlet
Normal file
@ -0,0 +1,8 @@
|
||||
$newline never
|
||||
$maybe finished <- examFinishedStr
|
||||
<p>
|
||||
_{MsgExamFinishedSince finished}
|
||||
$nothing
|
||||
<p .explanation>
|
||||
_{MsgExamFinishTip}
|
||||
^{finishView}
|
||||
Loading…
Reference in New Issue
Block a user