From 94bb3911cb7dc1d12544be5a644ff0b7ec25725a Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Mon, 2 Dec 2019 11:50:13 +0100 Subject: [PATCH] feat(external-exams): create new exams --- messages/uniworx/de-de-formal.msg | 45 +++++-- messages/uniworx/en-eu.msg | 25 ++++ src/Handler/ExternalExam/Edit.hs | 2 + src/Handler/ExternalExam/Form.hs | 115 ++++++++++++++++++ src/Handler/ExternalExam/New.hs | 54 +++++++- .../external-exam/schoolMassInput/add.hamlet | 6 + .../external-exam/schoolMassInput/cell.hamlet | 3 + .../schoolMassInput/layout.hamlet | 11 ++ .../external-exam/staffMassInput/add.hamlet | 6 + .../staffMassInput/cellInvitation.hamlet | 6 + .../staffMassInput/cellKnown.hamlet | 3 + .../staffMassInput/layout.hamlet | 11 ++ 12 files changed, 275 insertions(+), 12 deletions(-) create mode 100644 src/Handler/ExternalExam/Form.hs create mode 100644 templates/external-exam/schoolMassInput/add.hamlet create mode 100644 templates/external-exam/schoolMassInput/cell.hamlet create mode 100644 templates/external-exam/schoolMassInput/layout.hamlet create mode 100644 templates/external-exam/staffMassInput/add.hamlet create mode 100644 templates/external-exam/staffMassInput/cellInvitation.hamlet create mode 100644 templates/external-exam/staffMassInput/cellKnown.hamlet create mode 100644 templates/external-exam/staffMassInput/layout.hamlet diff --git a/messages/uniworx/de-de-formal.msg b/messages/uniworx/de-de-formal.msg index da7f03b5e..48ac52d8f 100644 --- a/messages/uniworx/de-de-formal.msg +++ b/messages/uniworx/de-de-formal.msg @@ -401,9 +401,9 @@ UnauthorizedToken404: Authorisierungs-Tokens können nicht auf Fehlerseiten ausg UnauthorizedSiteAdmin: Sie sind kein System-weiter Administrator. UnauthorizedSchoolAdmin: Sie sind nicht als Administrator für dieses Institut eingetragen. UnauthorizedAdminEscalation: Sie sind nicht Administrator für alle Institute, für die dieser Nutzer Administrator oder Veranstalter ist. -UnauthorizedExamOffice: Sie sind nicht Teil eines Prüfungsamts. -UnauthorizedExamExamOffice: Es existieren keine Prüfungsergebnisse für Nutzer, für die Sie Teil eines assoziierten Prüfungsamts sind. -UnauthorizedExternalExamExamOffice: Es existieren keine Prüfungsergebnisse für Nutzer, für die Sie Teil eines assoziierten Prüfungsamts sind. +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. +UnauthorizedExternalExamExamOffice: Es existieren keine Prüfungsergebnisse für Nutzer, für die Sie mit der Prüfungsverwaltung beauftragt sind. UnauthorizedSchoolLecturer: Sie sind nicht als Veranstalter für dieses Institut 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. @@ -1000,7 +1000,7 @@ NotificationTriggerKindCorrector: Für Korrektoren NotificationTriggerKindLecturer: Für Dozenten NotificationTriggerKindCourseLecturer: Für Kursverwalter NotificationTriggerKindAdmin: Für Administratoren -NotificationTriggerKindExamOffice: Für das Prüfungsamt +NotificationTriggerKindExamOffice: Für Prüfungsverwalter NotificationTriggerKindEvaluation: Für Vorlesungsumfragen NotificationTriggerKindAllocationStaff: Für Zentralanmeldungen (Dozenten) NotificationTriggerKindAllocationParticipant: Für Zentralanmeldungen @@ -1127,7 +1127,7 @@ MenuCourseMembers: Kursteilnehmer MenuCourseAddMembers: Kursteilnehmer hinzufügen MenuCourseCommunication: Kursmitteilung (E-Mail) MenuCourseApplications: Bewerbungen -MenuCourseExamOffice: Prüfungsämter +MenuCourseExamOffice: Prüfungsbeauftragte MenuTermShow: Semester MenuSubmissionDelete: Abgabe löschen MenuUsers: Benutzer @@ -1267,7 +1267,7 @@ AuthPredsActive: Aktive Authorisierungsprädikate AuthPredsActiveChanged: Authorisierungseinstellungen für aktuelle Sitzung gespeichert AuthTagFree: Seite ist universell zugänglich AuthTagAdmin: Nutzer ist Administrator -AuthTagExamOffice: Nutzer ist Teil eines Prüfungsamts +AuthTagExamOffice: Nutzer ist mit Prüfungsverwaltung beauftragt AuthTagToken: Nutzer präsentiert Authorisierungs-Token AuthTagNoEscalation: Nutzer-Rechte werden nicht auf fremde Institute ausgeweitet AuthTagDeprecated: Seite ist nicht überholt @@ -1522,9 +1522,9 @@ ExamFinishedOffice: Noten bekannt gegeben ExamFinishedParticipant: Bewertung vorrausichtlich abgeschlossen ExamFinishedTip: Zeitpunkt zu dem Prüfungergebnisse den Teilnehmern gemeldet werden ExamClosed: Noten gemeldet -ExamClosedTip: Prüfungsämter, die im System Noten einsehen, werden zu diesem Zeitpunkt benachrichtigt und danach bei Änderungen informiert +ExamClosedTip: Prüfungsbeauftraget, die im System Noten einsehen, werden zu diesem Zeitpunkt benachrichtigt und danach bei Änderungen informiert ExamShowGrades: Klausur ist benotet -ExamShowGradesTip: Sollen genaue Noten angezeigt werden, oder sollen Teilnehmer und Prüfungsämter nur informiert werden, ob die Klausur bestanden wurde? +ExamShowGradesTip: Sollen genaue Noten angezeigt werden, oder sollen Teilnehmer und Prüfungsbeauftragte nur informiert werden, ob die Klausur bestanden wurde? ExamPublicStatistics: Statistik veröffentlichen ExamPublicStatisticsTip: Soll die automatisch berechnete statistische Auswertung auch den Teilnehmern angezeigt werden, sobald diese ihre Noten einsehen können? ExamAutomaticGrading: Automatische Notenberechnung @@ -1938,7 +1938,7 @@ SchoolExists ssh@SchoolId: Institut „#{ssh}“ existiert bereits SchoolAdmin: Admin SchoolLecturer: Dozent SchoolEvaluation: Kursumfragenverwaltung -SchoolExamOffice: Prüfungsamt +SchoolExamOffice: Prüfungsverwaltung ApplicationEditTip: Während des Bewerbungszeitraums können eigene Bewerbungen beliebig angepasst und auch wieder zurückgezogen werden. @@ -2016,10 +2016,10 @@ MailSubjectChangeUserDisplayEmail: Diese E-Mail Adresse in Uni2work veröffentli MailIntroChangeUserDisplayEmail displayEmail@UserEmail: Der oben genannte Benutzer möchte „#{displayEmail}“ als öffentliche Adresse, assoziiert mit sich selbst, angeben. Wenn Sie diese Aktion nicht selbst ausgelöst haben, ignorieren Sie diese Mitteilung bitte! MailTitleChangeUserDisplayEmail displayName@Text: #{displayName} möchte diese E-Mail Adresse in Uni2work veröffentlichen -ExamOfficeOptOutsChanged: Zuständige Prüfungsämter erfolgreich angepasst +ExamOfficeOptOutsChanged: Zuständige Prüfungsbeauftragte erfolgreich angepasst BtnCloseExam: Klausur abschließen -ExamCloseTip: Wenn eine Klausur abgeschlossen wird, werden Prüfungsämter, die im System Noten einsehen, benachrichtigt und danach bei Änderungen informiert. +ExamCloseTip: Wenn eine Klausur abgeschlossen wird, werden Prüfungsbeauftragte, die im System Noten einsehen, benachrichtigt und danach bei Änderungen informiert. ExamCloseReminder: Bitte schließen Sie die Klausur frühstmöglich, sobald die Prüfungsleistungen sich voraussichtlich nicht mehr ändern werden. Z.B. direkt nach der Klausureinsicht. ExamDidClose: Klausur erfolgreich abgeschlossen @@ -2220,3 +2220,26 @@ Deficit: Defizit MetricNoSamples: Keine Messwerte MetricName: Name MetricValue: Wert + +ExternalExamSemester: Semester +ExternalExamSchool: Institut +ExternalExamCourseName: Veranstaltung +ExternalExamCourseNameTip: Muss nur innerhalb von Semester und Institut eindeutig sein. +ExternalExamCourseNamePlaceholder: Analysis I, Programmierung und Modellierung, ... +ExternalExamExamName: Prüfung +ExternalExamExamNameTip: Muss innerhalb der Veranstaltung eindeutig sein. +ExternalExamExamNamePlaceholder: Klausur, Nachklausur, Projektabnahme, ... +ExternalExamDefaultTime: Voreingestellter Zeitpunkt +ExternalExamDefaultTimePlaceholder: Zeitpunkt +ExternalExamDefaultTimeTip: Der Zeitpunkt zu dem die Prüfung abgelegt wurde, muss pro Teilnehmer festgelegt werden. Der hier angegebene Zeitpunkt wird als Standardwert für Teilnehmer verwendet, bei denen später nicht ein abweichender Zeitpunkt angegeben wird. +ExternalExamShowGrades: Klausur ist benotet +ExternalExamShowGradesTip: Sollen genaue Noten angezeigt werden, oder sollen Teilnehmer und Prüfungsbeauftragte nur informiert werden, ob die Klausur bestanden wurde? +ExternalExamExamOfficeSchools: Zusätzliche Institute +ExternalExamExamOfficeSchoolsTip: Prüfungsbeauftragte von Instituten, die Sie hier angeben, erhalten im System (zusätzlich zum angegebenen primären Institut) volle Einsicht in sämtliche für diese Prüfung hinterlegten Leistungen, unabhängig von den Studiendaten der Teilnehmer. +ExternalExamStaff: Assoziierte Personen +ExternalExamStaffTip: Assoziierte Personen werden den Prüfungsbeauftragten und Teilnehmern angezeigt und dürfen Leistungen für die Prüfung hinterlegen. +ExternalExamStaffAlreadyAdded: Person wurde bereits der Prüfung hinzugefügt +ExternalExamUserMustBeStaff: Sie selbst müssen stets assoziierte Person sein, für die externen Prüfungen, die Sie anlegen +ExternalExamCourseExists: Der angegebene Kurs existiert im System. Prüfungen sollten daher direkt beim Kurs (statt extern) hinterlegt werden. +ExternalExamExists coursen@CourseName examn@ExamName: Prüfung „#{examn}“ für Kurs „#{coursen}“ existiert bereits. +ExternalExamCreated coursen@CourseName examn@ExamName: Prüfung „#{examn}“ für Kurs „#{coursen}“ erfolgreich angelegt. \ No newline at end of file diff --git a/messages/uniworx/en-eu.msg b/messages/uniworx/en-eu.msg index bbc7d1fa4..7dc50cac4 100644 --- a/messages/uniworx/en-eu.msg +++ b/messages/uniworx/en-eu.msg @@ -401,6 +401,7 @@ UnauthorizedSchoolAdmin: You are no administrator for this department. 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. 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. UnauthorizedSchoolLecturer: You are no lecturer for this department. UnauthorizedLecturer: You are no administrator for this course. UnauthorizedAllocationLecturer: You are no administrator for any of the courses of this central allocation. @@ -449,6 +450,7 @@ UnauthorizedTutorialRegisterGroup: You are already registered for a tutorial wit UnauthorizedLDAP: Specified user does not log in with their campus account. UnauthorizedPWHash: Specified user does not log in with an Uni2work-account. UnauthorizedExternalExamListNotEmpty: List of external exams is not empty +UnauthorizedExternalExamLecturer: You are not an associated person for this external exam UnauthorizedPasswordResetToken: This authorisation-token may no longer be used to change passwords @@ -2217,3 +2219,26 @@ Deficit: Deficit MetricNoSamples: No samples MetricName: Name MetricValue: Value + +ExternalExamSemester: Semester +ExternalExamSchool: Department +ExternalExamCourseName: Course +ExternalExamCourseNameTip: Needs only be unique among within semester and department. +ExternalExamCourseNamePlaceholder: Analysis I, Programming and Modelling, ... +ExternalExamExamName: Exam title +ExternalExamExamNameTip: Needs only be unique within the course. +ExternalExamExamNamePlaceholder: Exam, Exam resit, Project discussion, ... +ExternalExamDefaultTime: Default time +ExternalExamDefaultTimePlaceholder: Time +ExternalExamDefaultTimeTip: The time of the exam needs to be specified for each participant. The time entered here is used as a default value for participants for whom no different time is later specified. +ExternalExamShowGrades: Exam is graded +ExternalExamShowGradesTip: Should participants and relevant exam offices be show exact grades or only whether the exam was passed or failed? +ExternalExamExamOfficeSchools: Additional departments +ExternalExamExamOfficeSchoolsTip: 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. +ExternalExamStaff: Associated persons +ExternalExamStaffTip: The list of ssociated persons is shown to exam offices and participants. Additionally associated persons may upload results for the exam. +ExternalExamStaffAlreadyAdded: Person is already associated with the exam. +ExternalExamUserMustBeStaff: You yourself must always be an associated person for exams you create. +ExternalExamCourseExists: This course already exists with uni2work. Exams for courses that exist within uni2work should be associated with the course directly instead of being created as an external exam. +ExternalExamExists coursen@CourseName examn@ExamName: Exam “#{examn}” already exists for course “#{coursen}”. +ExternalExamCreated coursen@CourseName examn@ExamName: Succesfully created exam “#{examn}” for course “#{coursen}”. diff --git a/src/Handler/ExternalExam/Edit.hs b/src/Handler/ExternalExam/Edit.hs index 66961d477..d89987ab9 100644 --- a/src/Handler/ExternalExam/Edit.hs +++ b/src/Handler/ExternalExam/Edit.hs @@ -4,6 +4,8 @@ module Handler.ExternalExam.Edit import Import +import Handler.ExternalExam.Form () + getEEEditR, postEEEditR :: TermId -> SchoolId -> CourseName -> ExamName -> Handler Html getEEEditR = postEEEditR diff --git a/src/Handler/ExternalExam/Form.hs b/src/Handler/ExternalExam/Form.hs new file mode 100644 index 000000000..a8c5d5c18 --- /dev/null +++ b/src/Handler/ExternalExam/Form.hs @@ -0,0 +1,115 @@ +module Handler.ExternalExam.Form + ( ExternalExamForm(..) + , externalExamForm + ) where + +import Import +import Handler.Utils + +import Handler.ExternalExam.StaffInvite () + +import qualified Data.Set as Set +import Data.Map ((!)) + +import qualified Control.Monad.State.Class as State + + +data ExternalExamForm = ExternalExamForm + { eefTerm :: TermId + , eefSchool :: SchoolId + , eefCourseName :: CI Text + , eefExamName :: CI Text + , eefDefaultTime :: Maybe UTCTime + , eefShowGrades :: Bool + , eefOfficeSchools :: Set SchoolId + , eefStaff :: Set (Either UserEmail UserId) + } + +makeLenses_ ''ExternalExamForm + +externalExamForm :: Maybe ExternalExamForm -> Form ExternalExamForm +externalExamForm template = validateForm validateExternalExam $ \html -> do + uid <- requireAuthId + cRoute <- fromMaybe (error "tutorialForm called from 404-Handler") <$> getCurrentRoute + MsgRenderer mr <- getMsgRenderer + + let termsField = case template of + Just template' -> termsSetField [eefTerm template'] + _other -> termsAllowedField + + (lecturerSchools, adminSchools, oldSchool) <- liftHandler . runDB $ do + lecturerSchools <- map (userFunctionSchool . entityVal) <$> selectList [UserFunctionUser ==. uid, UserFunctionFunction <-. [SchoolLecturer]] [] + protoAdminSchools <- map (userFunctionSchool . entityVal) <$> selectList [UserFunctionUser ==. uid, UserFunctionFunction <-. [SchoolAdmin]] [] + adminSchools <- filterM (hasWriteAccessTo . flip SchoolR SchoolEditR) protoAdminSchools + let oldSchool = eefSchool <$> template + return (lecturerSchools, adminSchools, oldSchool) + let userSchools = nub . maybe id (:) oldSchool $ lecturerSchools ++ adminSchools + + flip (renderAForm FormStandard) html $ ExternalExamForm + <$> areq termsField (fslI MsgExternalExamSemester) (eefTerm <$> template) + <*> areq (schoolFieldFor userSchools) (fslI MsgExternalExamSchool) (eefSchool <$> template) + <*> areq (textField & cfStrip & cfCI) (fslI MsgExternalExamCourseName & setTooltip MsgExternalExamCourseNameTip & addPlaceholder (mr MsgExternalExamCourseNamePlaceholder)) (eefCourseName <$> template) + <*> areq (textField & cfStrip & cfCI) (fslI MsgExternalExamExamName & setTooltip MsgExternalExamExamNameTip & addPlaceholder (mr MsgExternalExamExamNamePlaceholder)) (eefExamName <$> template) + <*> aopt utcTimeField (fslI MsgExternalExamDefaultTime & setTooltip MsgExternalExamDefaultTimeTip & addPlaceholder (mr MsgExternalExamDefaultTimePlaceholder)) (eefDefaultTime <$> template) + <*> apopt checkBoxField (fslI MsgExternalExamShowGrades & setTooltip MsgExternalExamShowGradesTip) (eefShowGrades <$> template) + <*> (Set.fromList <$> officeSchoolForm cRoute (Set.toList . eefOfficeSchools <$> template)) + <*> (Set.fromList <$> staffForm cRoute ((Set.toList . eefStaff <$> template) <|> pure (pure $ Right uid))) + where + officeSchoolForm cRoute = massInputAccumA miAdd miCell miButtonAction miLayout miIdent fSettings fRequired + where + miAdd mkUnique submitView csrf = do + (schoolRes, addView) <- mpopt schoolField ("" & addName (mkUnique "school")) Nothing + let schoolRes' = schoolRes <&> \newDat oldDat -> FormSuccess (guardOn (newDat `notElem` oldDat) newDat) + return (schoolRes', $(widgetFile "external-exam/schoolMassInput/add")) + miCell ssh = do + School{..} <- liftHandler . runDB $ getJust ssh + $(widgetFile "external-exam/schoolMassInput/cell") + miButtonAction :: forall p. PathPiece p => p -> Maybe (SomeRoute UniWorX) + miButtonAction = Just . SomeRoute . (cRoute :#:) + miLayout :: MassInputLayout ListLength SchoolId () + miLayout lLength _ cellWdgts delButtons addWdgts = $(widgetFile "external-exam/schoolMassInput/layout") + miIdent :: Text + miIdent = "external-exams-school" + fSettings = fslI MsgExternalExamExamOfficeSchools & setTooltip (UniWorXMessages [SomeMessage MsgExternalExamExamOfficeSchoolsTip, SomeMessage MsgMassInputTip]) + fRequired = False + staffForm cRoute = massInputAccumA miAdd miCell miButtonAction miLayout miIdent fSettings fRequired + where + miAdd mkUnique submitView csrf = do + MsgRenderer mr <- getMsgRenderer + (usersRes, addView) <- mpreq (multiUserField False Nothing) ("" & addName (mkUnique "email")) Nothing + let + usersRes' = usersRes <&> \newDat oldDat -> if + | existing <- newDat `Set.intersection` Set.fromList oldDat + , not $ Set.null existing + -> FormFailure [mr MsgExternalExamStaffAlreadyAdded] + | otherwise + -> FormSuccess $ Set.toList newDat + return (usersRes', $(widgetFile "external-exam/staffMassInput/add")) + miCell (Left email) = do + invWarnMsg <- messageI Warning MsgEmailInvitationWarning + $(widgetFile "external-exam/staffMassInput/cellInvitation") + miCell (Right userId) = do + User{..} <- liftHandler . runDB $ getJust userId + $(widgetFile "external-exam/staffMassInput/cellKnown") + miButtonAction :: forall p. PathPiece p => p -> Maybe (SomeRoute UniWorX) + miButtonAction = Just . SomeRoute . (cRoute :#:) + miLayout :: MassInputLayout ListLength (Either UserEmail UserId) () + miLayout lLength _ cellWdgts delButtons addWdgts = $(widgetFile "external-exam/staffMassInput/layout") + miIdent :: Text + miIdent = "external-exams-staff" + fSettings = fslI MsgExternalExamStaff & setTooltip (UniWorXMessages [SomeMessage MsgExternalExamStaffTip, SomeMessage MsgMassInputTip]) + fRequired = True + +validateExternalExam :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX) => FormValidator ExternalExamForm m () +validateExternalExam = do + State.modify $ \eeForm -> eeForm & over _eefOfficeSchools (Set.delete $ eeForm ^. _eefSchool) + + ExternalExamForm{..} <- State.get + + isAdmin <- hasWriteAccessTo $ SchoolR eefSchool SchoolEditR + unless isAdmin $ do + uid <- requireAuthId + guardValidation MsgExternalExamUserMustBeStaff $ Right uid `Set.member` eefStaff + + courseExists <- liftHandler . runDB . existsBy $ TermSchoolCourseName eefTerm eefSchool eefCourseName + guardValidation MsgExternalExamCourseExists $ not courseExists diff --git a/src/Handler/ExternalExam/New.hs b/src/Handler/ExternalExam/New.hs index 1ccd89731..b8403b674 100644 --- a/src/Handler/ExternalExam/New.hs +++ b/src/Handler/ExternalExam/New.hs @@ -4,7 +4,59 @@ module Handler.ExternalExam.New import Import +import Jobs.Queue + +import Handler.Utils +import Handler.Utils.Invitations + +import Handler.ExternalExam.StaffInvite +import Handler.ExternalExam.Form + +import qualified Data.Set as Set + getEExamNewR, postEExamNewR :: Handler Html getEExamNewR = postEExamNewR -postEExamNewR = error "Not implemented" +postEExamNewR = do + ((newExamResult, newExamWidget'), newExamEnctype) <- runFormPost $ externalExamForm Nothing + + formResult newExamResult $ \ExternalExamForm{..} -> do + insertRes <- runDBJobs $ do + insertRes <- insertUnique ExternalExam + { externalExamTerm = eefTerm + , externalExamSchool = eefSchool + , externalExamCourseName = eefCourseName + , externalExamExamName = eefExamName + , externalExamDefaultTime = eefDefaultTime + , externalExamShowGrades = eefShowGrades + } + whenIsJust insertRes $ \eeId -> do + insertMany_ + [ ExternalExamOfficeSchool{..} + | externalExamOfficeSchoolSchool <- Set.toList eefOfficeSchools + , externalExamOfficeSchoolSchool /= eefSchool + , let externalExamOfficeSchoolExam = eeId + ] + + let (invites, adds) = partitionEithers $ Set.toList eefStaff + insertMany_ [ ExternalExamStaff{..} + | externalExamStaffUser <- adds + , let externalExamStaffExam = eeId + ] + sinkInvitationsF externalExamStaffInvitationConfig $ map (, eeId, (InvDBDataExternalExamStaff, InvTokenDataExternalExamStaff)) invites + return insertRes + + case insertRes of + Nothing -> addMessageI Error $ MsgExternalExamExists eefCourseName eefExamName + Just _ -> do + addMessageI Success $ MsgExternalExamCreated eefCourseName eefExamName + redirect $ EExamR eefTerm eefSchool eefCourseName eefExamName EEShowR + + let heading = MsgMenuExternalExamNew + + siteLayoutMsg heading $ do + setTitleI heading + wrapForm newExamWidget' def + { formAction = Just $ SomeRoute EExamNewR + , formEncoding = newExamEnctype + } diff --git a/templates/external-exam/schoolMassInput/add.hamlet b/templates/external-exam/schoolMassInput/add.hamlet new file mode 100644 index 000000000..cf4cc6e72 --- /dev/null +++ b/templates/external-exam/schoolMassInput/add.hamlet @@ -0,0 +1,6 @@ +$newline never + + #{csrf} + ^{fvInput addView} + + ^{fvInput submitView} diff --git a/templates/external-exam/schoolMassInput/cell.hamlet b/templates/external-exam/schoolMassInput/cell.hamlet new file mode 100644 index 000000000..13905b209 --- /dev/null +++ b/templates/external-exam/schoolMassInput/cell.hamlet @@ -0,0 +1,3 @@ +$newline never + + #{schoolName} diff --git a/templates/external-exam/schoolMassInput/layout.hamlet b/templates/external-exam/schoolMassInput/layout.hamlet new file mode 100644 index 000000000..65352dd95 --- /dev/null +++ b/templates/external-exam/schoolMassInput/layout.hamlet @@ -0,0 +1,11 @@ +$newline never + + + $forall coord <- review liveCoords lLength + + ^{cellWdgts ! coord} + + + ^{addWdgts ! (0, 0)} diff --git a/templates/external-exam/staffMassInput/add.hamlet b/templates/external-exam/staffMassInput/add.hamlet new file mode 100644 index 000000000..bdf6da247 --- /dev/null +++ b/templates/external-exam/staffMassInput/add.hamlet @@ -0,0 +1,6 @@ +$newline never +
+ ^{fvInput (delButtons ! coord)} +
+ #{csrf} + ^{fvInput addView} + + ^{fvInput submitView} diff --git a/templates/external-exam/staffMassInput/cellInvitation.hamlet b/templates/external-exam/staffMassInput/cellInvitation.hamlet new file mode 100644 index 000000000..df7df418a --- /dev/null +++ b/templates/external-exam/staffMassInput/cellInvitation.hamlet @@ -0,0 +1,6 @@ +$newline never + + + #{email} + + ^{messageTooltip invWarnMsg} diff --git a/templates/external-exam/staffMassInput/cellKnown.hamlet b/templates/external-exam/staffMassInput/cellKnown.hamlet new file mode 100644 index 000000000..5ea4cca6f --- /dev/null +++ b/templates/external-exam/staffMassInput/cellKnown.hamlet @@ -0,0 +1,3 @@ +$newline never + + ^{nameEmailWidget userEmail userDisplayName userSurname} diff --git a/templates/external-exam/staffMassInput/layout.hamlet b/templates/external-exam/staffMassInput/layout.hamlet new file mode 100644 index 000000000..65352dd95 --- /dev/null +++ b/templates/external-exam/staffMassInput/layout.hamlet @@ -0,0 +1,11 @@ +$newline never + + + $forall coord <- review liveCoords lLength + + ^{cellWdgts ! coord} + + + ^{addWdgts ! (0, 0)}
+ ^{fvInput (delButtons ! coord)} +