diff --git a/.gitignore b/.gitignore index 0e2a4677f..0fb3c32c0 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,4 @@ src/Handler/Course.SnapCustom.hs .directory tags test.log +*.dump-splices diff --git a/messages/uniworx/de.msg b/messages/uniworx/de.msg index 6ae69522d..b95fc67c4 100644 --- a/messages/uniworx/de.msg +++ b/messages/uniworx/de.msg @@ -41,18 +41,18 @@ GenericAvg: Avg GenericMax: Max GenericAll: Insgesamt -SummerTerm year@Integer: Sommersemester #{display year} -WinterTerm year@Integer: Wintersemester #{display year}/#{display $ succ year} -SummerTermShort year@Integer: SoSe #{display year} -WinterTermShort year@Integer: WiSe #{display year}/#{display $ mod (succ year) 100} +SummerTerm year@Integer: Sommersemester #{year} +WinterTerm year@Integer: Wintersemester #{year}/#{succ year} +SummerTermShort year@Integer: SoSe #{year} +WinterTermShort year@Integer: WiSe #{year}/#{mod (succ year) 100} PSLimitNonPositive: “pagesize” muss größer als null sein -Page num@Int64: #{display num} +Page num@Int64: #{num} TermsHeading: Semesterübersicht TermCurrent: Aktuelles Semester TermEditHeading: Semester editieren/anlegen -TermEditTid tid@TermId: Semester #{display tid} editieren -TermEdited tid@TermId: Semester #{display tid} erfolgreich editiert. +TermEditTid tid@TermId: Semester #{tid} editieren +TermEdited tid@TermId: Semester #{tid} erfolgreich editiert. TermNewTitle: Semester editieren/anlegen. InvalidInput: Eingaben bitte korrigieren. Term: Semester @@ -91,23 +91,23 @@ CourseTutorial: Tutorium CourseStudyFeatureTooltip: Korrekte Angabe kann Notenweiterleitungen beschleunigen CourseSecretWrong: Falsches Kennwort CourseSecret: Zugangspasswort -CourseEditOk tid@TermId ssh@SchoolId csh@CourseShorthand: Kurs #{display tid}-#{display ssh}-#{csh} wurde erfolgreich geändert. -CourseNewDupShort tid@TermId ssh@SchoolId csh@CourseShorthand: Kurs #{display tid}-#{display ssh}-#{csh} konnte nicht erstellt werden: Es gibt bereits einen anderen Kurs mit dem Kürzel #{csh} in diesem Semester. -CourseEditDupShort tid@TermId ssh@SchoolId csh@CourseShorthand: Kurs #{display tid}-#{display ssh}-#{csh} konnte nicht geändert werden: Es gibt bereits einen anderen Kurs mit dem Kürzel #{csh} in diesem Semester. +CourseEditOk tid@TermId ssh@SchoolId csh@CourseShorthand: Kurs #{tid}-#{ssh}-#{csh} wurde erfolgreich geändert. +CourseNewDupShort tid@TermId ssh@SchoolId csh@CourseShorthand: Kurs #{tid}-#{ssh}-#{csh} konnte nicht erstellt werden: Es gibt bereits einen anderen Kurs mit dem Kürzel #{csh} in diesem Semester. +CourseEditDupShort tid@TermId ssh@SchoolId csh@CourseShorthand: Kurs #{tid}-#{ssh}-#{csh} konnte nicht geändert werden: Es gibt bereits einen anderen Kurs mit dem Kürzel #{csh} in diesem Semester. FFSheetName: Name -TermCourseListHeading tid@TermId: Kursübersicht #{display tid} -TermSchoolCourseListHeading tid@TermId school@SchoolName: Kursübersicht #{display tid} für #{school} +TermCourseListHeading tid@TermId: Kursübersicht #{tid} +TermSchoolCourseListHeading tid@TermId school@SchoolName: Kursübersicht #{tid} für #{school} CourseListTitle: Alle Kurse -TermCourseListTitle tid@TermId: Kurse #{display tid} -TermSchoolCourseListTitle tid@TermId school@SchoolName: Kurse #{display tid} für #{school} +TermCourseListTitle tid@TermId: Kurse #{tid} +TermSchoolCourseListTitle tid@TermId school@SchoolName: Kurse #{tid} für #{school} CourseNewHeading: Neuen Kurs anlegen -CourseEditHeading tid@TermId ssh@SchoolId csh@CourseShorthand: Kurs #{display tid}-#{display ssh}-#{csh} editieren +CourseEditHeading tid@TermId ssh@SchoolId csh@CourseShorthand: Kurs #{tid}-#{ssh}-#{csh} editieren CourseEditTitle: Kurs editieren/anlegen CourseMembers: Teilnehmer CourseMemberOf: Teilnehmer -CourseMembersCount n@Int: #{display n} -CourseMembersCountLimited n@Int max@Int: #{display n}/#{display max} -CourseMembersCountOf n@Int mbNum@IntMaybe: #{display n} Anmeldungen #{maybeDisplay " von " mbNum " möglichen"} +CourseMembersCount n@Int: #{n} +CourseMembersCountLimited n@Int max@Int: #{n}/#{max} +CourseMembersCountOf n@Int mbNum@IntMaybe: #{n} Anmeldungen #{maybeToMessage " von " mbNum " möglichen"} CourseName: Name CourseDescription: Beschreibung CourseDescriptionTip: Beliebiges HTML-Markup ist gestattet @@ -147,23 +147,23 @@ CourseDeregistrationEndMustBeAfterStart: Ende des Abmeldezeitraums muss nach dem CourseUserMustBeLecturer: Aktueller Benutzer muss als Kursverwalter eingetragen sein CourseLecturerRightsIdentical: Alle Sorten von Kursverwalter haben identische Rechte. -NoSuchTerm tid@TermId: Semester #{display tid} gibt es nicht. -NoSuchSchool ssh@SchoolId: Institut #{display ssh} gibt es nicht. +NoSuchTerm tid@TermId: Semester #{tid} gibt es nicht. +NoSuchSchool ssh@SchoolId: Institut #{ssh} gibt es nicht. NoSuchCourseShorthand csh@CourseShorthand: Kein Kurs mit Kürzel #{csh} bekannt. NoSuchCourse: Keinen passenden Kurs gefunden. Sheet: Blatt -SheetList tid@TermId ssh@SchoolId csh@CourseShorthand: #{display tid}-#{display ssh}-#{csh} Übersicht Übungsblätter -SheetNewHeading tid@TermId ssh@SchoolId csh@CourseShorthand: #{display tid}-#{display ssh}-#{csh} Neues Übungsblatt anlegen -SheetNewOk tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{sheetName} wurde als neues Übungsblatt im Kurs #{display tid}-#{display ssh}-#{csh} erfolgreich erstellt. -SheetTitle tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{display tid}-#{display ssh}-#{csh} #{sheetName} -SheetTitleNew tid@TermId ssh@SchoolId csh@CourseShorthand : #{display tid}-#{display ssh}-#{csh}: Neues Übungsblatt -SheetEditHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{display tid}-#{display ssh}-#{csh} #{sheetName} editieren -SheetEditOk tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Übungsblatt #{sheetName} wurde gespeichert in Kurs #{display tid}-#{display ssh}-#{csh} -SheetNameDup tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Es gibt bereits ein Übungsblatt #{sheetName} in diesem Kurs #{display tid}-#{display ssh}-#{csh} -SheetDelHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{sheetName} wirklich aus Kurs #{display tid}-#{display ssh}-#{csh} herauslöschen? Alle assoziierten Abgaben und Korrekturen gehen ebenfalls verloren! -SheetDelOk tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{display tid}-#{display ssh}-#{csh}: #{sheetName} gelöscht. -SheetDelHasSubmissions objs@Int: Inkl. #{tshow objs} #{pluralDE objs "Abgabe" "Abgaben"}! +SheetList tid@TermId ssh@SchoolId csh@CourseShorthand: #{tid}-#{ssh}-#{csh} Übersicht Übungsblätter +SheetNewHeading tid@TermId ssh@SchoolId csh@CourseShorthand: #{tid}-#{ssh}-#{csh} Neues Übungsblatt anlegen +SheetNewOk tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{sheetName} wurde als neues Übungsblatt im Kurs #{tid}-#{ssh}-#{csh} erfolgreich erstellt. +SheetTitle tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{tid}-#{ssh}-#{csh} #{sheetName} +SheetTitleNew tid@TermId ssh@SchoolId csh@CourseShorthand : #{tid}-#{ssh}-#{csh}: Neues Übungsblatt +SheetEditHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{tid}-#{ssh}-#{csh} #{sheetName} editieren +SheetEditOk tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Übungsblatt #{sheetName} wurde gespeichert in Kurs #{tid}-#{ssh}-#{csh} +SheetNameDup tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Es gibt bereits ein Übungsblatt #{sheetName} in diesem Kurs #{tid}-#{ssh}-#{csh} +SheetDelHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{sheetName} wirklich aus Kurs #{tid}-#{ssh}-#{csh} herauslöschen? Alle assoziierten Abgaben und Korrekturen gehen ebenfalls verloren! +SheetDelOk tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{tid}-#{ssh}-#{csh}: #{sheetName} gelöscht. +SheetDelHasSubmissions objs@Int: Inkl. #{objs} #{pluralDE objs "Abgabe" "Abgaben"}! SheetDeleteQuestion: Wollen Sie das unten aufgeführte Übungsblatt und alle zugehörigen Abgaben wirklich löschen? SheetDeleted: Übungsblatt gelöscht @@ -209,12 +209,12 @@ Deadline: Abgabe Done: Eingereicht Submission: Abgabenummer -SubmissionsCourse tid@TermId ssh@SchoolId csh@CourseShorthand: Alle Abgaben Kurs #{display tid}-#{display ssh}-#{csh} +SubmissionsCourse tid@TermId ssh@SchoolId csh@CourseShorthand: Alle Abgaben Kurs #{tid}-#{ssh}-#{csh} SubmissionsSheet sheetName@SheetName: Abgaben für #{sheetName} SubmissionWrongSheet: Abgabenummer gehört nicht zum angegebenen Übungsblatt. SubmissionAlreadyExists: Sie haben bereits eine Abgabe zu diesem Übungsblatt. -SubmissionEditHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{display tid}-#{display ssh}-#{csh} #{sheetName}: Abgabe editieren/anlegen -CorrectionHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName cid@CryptoFileNameSubmission: #{display tid}-#{display ssh}-#{csh} #{sheetName}: Korrektur +SubmissionEditHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{tid}-#{ssh}-#{csh} #{sheetName}: Abgabe editieren/anlegen +CorrectionHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName cid@CryptoFileNameSubmission: #{tid}-#{ssh}-#{csh} #{sheetName}: Korrektur SubmissionMembers: Abgebende SubmissionMember: Abgebende(r) SubmissionArchive: Zip-Archiv der Abgabedatei(en) @@ -253,10 +253,10 @@ MaterialNewHeading: Neues Material veröffentlichen MaterialNewTitle: Neues Material MaterialEditHeading materialName@MaterialName: Material "#{materialName}" editieren MaterialEditTitle materialName@MaterialName: Material "#{materialName}" editieren -MaterialSaveOk tid@TermId ssh@SchoolId csh@CourseShorthand materialName@MaterialName: Material "#{materialName}" erfolgreich gespeichert in Kurs #{display tid}-#{display ssh}-#{csh} -MaterialNameDup tid@TermId ssh@SchoolId csh@CourseShorthand materialName@MaterialName: Es gibt bereits Material mit Namen "#{materialName}" in diesem Kurs #{display tid}-#{display ssh}-#{csh} +MaterialSaveOk tid@TermId ssh@SchoolId csh@CourseShorthand materialName@MaterialName: Material "#{materialName}" erfolgreich gespeichert in Kurs #{tid}-#{ssh}-#{csh} +MaterialNameDup tid@TermId ssh@SchoolId csh@CourseShorthand materialName@MaterialName: Es gibt bereits Material mit Namen "#{materialName}" in diesem Kurs #{tid}-#{ssh}-#{csh} MaterialDeleteCaption: Wollen Sie das unten aufgeführte Material wirklich löschen? -MaterialDelHasFiles count@Int64: inklusive #{tshow count} #{pluralDE count "Datei" "Dateien"} +MaterialDelHasFiles count@Int64: inklusive #{count} #{pluralDE count "Datei" "Dateien"} MaterialIsVisible: Achtung, dieses Material wurde bereits veröffentlicht. MaterialDeleted materialName@MaterialName: Material "#{materialName}" gelöscht @@ -310,12 +310,12 @@ UnauthorizedTutorialRegisterGroup: Sie sind bereits in einem Tutorium mit dersel EMail: E-Mail EMailUnknown email@UserEmail: E-Mail #{email} gehört zu keinem bekannten Benutzer. -NotAParticipant email@UserEmail tid@TermId csh@CourseShorthand: #{email} ist nicht im Kurs #{display tid}-#{csh} angemeldet. +NotAParticipant email@UserEmail tid@TermId csh@CourseShorthand: #{email} ist nicht im Kurs #{tid}-#{csh} angemeldet. TooManyParticipants: Es wurden zu viele Mitabgebende angegeben AddCorrector: Zusätzlicher Korrektor CorrectorExists: Nutzer ist bereits als Korrektor eingetragen -SheetCorrectorsTitle tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Korrektoren für #{display tid}-#{display ssh}-#{csh} #{sheetName} +SheetCorrectorsTitle tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Korrektoren für #{tid}-#{ssh}-#{csh} #{sheetName} CountTutProp: Tutorien zählen gegen Proportion CountTutPropTip: Wenn Abgaben nach Tutorium zugeteilt werden, zählen diese Zuteilungen in Bezug auf den jeweiligen Anteil? AutoAssignCorrs: Korrekturen nach Ablauf des Abgabezeitraums automatisch zuteilen @@ -325,11 +325,11 @@ CorState: Status CorByTut: Zuteilung nach Tutorium CorProportion: Anteil CorDeficitProportion: Defizit Anteile -CorByProportionOnly proportion@Rational: #{display proportion} Anteile -CorByProportionIncludingTutorial proportion@Rational: #{display proportion} Anteile - Tutorium -CorByProportionExcludingTutorial proportion@Rational: #{display proportion} Anteile + Tutorium +CorByProportionOnly proportion@Rational: #{rationalToFixed3 proportion} Anteile +CorByProportionIncludingTutorial proportion@Rational: #{rationalToFixed3 proportion} Anteile - Tutorium +CorByProportionExcludingTutorial proportion@Rational: #{rationalToFixed3 proportion} Anteile + Tutorium -RowCount count@Int64: #{display count} #{pluralDE count "passender Eintrag" "passende Einträge"} insgesamt +RowCount count@Int64: #{count} #{pluralDE count "passender Eintrag" "passende Einträge"} insgesamt DeleteRow: Entfernen ProportionNegative: Anteile dürfen nicht negativ sein CorrectorUpdated: Korrektor erfolgreich aktualisiert @@ -357,7 +357,7 @@ TokensResetSuccess: Authorisierungs-Tokens invalidiert HomeOpenCourses: Kurse mit offener Registrierung HomeUpcomingSheets: Anstehende Übungsblätter -NumCourses num@Int64: #{display num} Kurse +NumCourses num@Int64: #{num} Kurse CloseAlert: Schliessen Name: Name @@ -394,23 +394,23 @@ NatField name@Text: #{name} muss eine natürliche Zahl sein! JSONFieldDecodeFailure aesonFailure@String: Konnte JSON nicht parsen: #{aesonFailure} SecretJSONFieldDecryptFailure: Konnte versteckte vertrauliche Daten nicht entschlüsseln -SubmissionsAlreadyAssigned num@Int64: #{display num} Abgaben waren bereits einem Korrektor zugeteilt und wurden nicht verändert: -SubmissionsAssignUnauthorized num@Int64: #{display num} Abgaben können momentan nicht einem Korrektor zugeteilt werden (z.B. weil die Abgabe noch offen ist): -UpdatedAssignedCorrectorSingle num@Int64: #{display num} Abgaben wurden dem neuen Korrektor zugeteilt. +SubmissionsAlreadyAssigned num@Int64: #{num} Abgaben waren bereits einem Korrektor zugeteilt und wurden nicht verändert: +SubmissionsAssignUnauthorized num@Int64: #{num} Abgaben können momentan nicht einem Korrektor zugeteilt werden (z.B. weil die Abgabe noch offen ist): +UpdatedAssignedCorrectorSingle num@Int64: #{num} Abgaben wurden dem neuen Korrektor zugeteilt. NoCorrector: Kein Korrektor -RemovedCorrections num@Int64: Korrektur-Daten wurden von #{display num} Abgaben entfernt. -UpdatedAssignedCorrectorsAuto num@Int64: #{display num} Abgaben wurden unter den Korrektoren aufgeteilt. -UpdatedSheetCorrectorsAutoAssigned n@Int: #{display n} #{pluralDE n "Abgabe wurde einem Korrektor" "Abgaben wurden Korrektoren"} zugteilt. -UpdatedSheetCorrectorsAutoFailed n@Int: #{display n} #{pluralDE n "Abgabe konnte" "Abgaben konnten"} nicht automatisch zugewiesen werden. -CouldNotAssignCorrectorsAuto num@Int64: #{display num} Abgaben konnten nicht automatisch zugewiesen werden: -SelfCorrectors num@Int64: #{display num} Abgaben wurden Abgebenden als eigenem Korrektor zugeteilt! +RemovedCorrections num@Int64: Korrektur-Daten wurden von #{num} Abgaben entfernt. +UpdatedAssignedCorrectorsAuto num@Int64: #{num} Abgaben wurden unter den Korrektoren aufgeteilt. +UpdatedSheetCorrectorsAutoAssigned n@Int: #{n} #{pluralDE n "Abgabe wurde einem Korrektor" "Abgaben wurden Korrektoren"} zugteilt. +UpdatedSheetCorrectorsAutoFailed n@Int: #{n} #{pluralDE n "Abgabe konnte" "Abgaben konnten"} nicht automatisch zugewiesen werden. +CouldNotAssignCorrectorsAuto num@Int64: #{num} Abgaben konnten nicht automatisch zugewiesen werden: +SelfCorrectors num@Int64: #{num} Abgaben wurden Abgebenden als eigenem Korrektor zugeteilt! CorrectionSheets: Übersicht Korrekturen nach Blättern CorrectionCorrectors: Übersicht Korrekturen nach Korrektoren AssignSubmissionExceptionNoCorrectors: Es sind keine Korrektoren eingestellt AssignSubmissionExceptionNoCorrectorsByProportion: Es sind keine Korrektoren mit Anteil ungleich Null eingestellt -AssignSubmissionExceptionSubmissionsNotFound n@Int: #{tshow n} Abgaben konnten nicht gefunden werden +AssignSubmissionExceptionSubmissionsNotFound n@Int: #{n} Abgaben konnten nicht gefunden werden NrSubmittorsTotal: Abgebende NrSubmissionsTotal: Abgaben NrSubmissionsTotalShort: Abg. @@ -424,7 +424,7 @@ NrSubmissionsNotCorrectedShort: Unkg. CorrectionTime: Korrekturdauer AssignSubmissionsRandomWarning: Die Zuteilungsvorschau kann von der tatsächlichen Zuteilung abweichen, wenn mehrere Blätter auf einmal zugeteilt werden, da beim Ausgleich der Kontigente nur bereits zugeteilte Abgaben berücksichtigt werden. Da es ein randomisierte Prozess ist, kann es auch bei einzelnen Blättern gerinfgügige Abweichungen geben. -CorrectionsUploaded num@Int64: #{display num} Korrekturen wurden gespeichert: +CorrectionsUploaded num@Int64: #{num} Korrekturen wurden gespeichert: NoCorrectionsUploaded: In der hochgeladenen Datei wurden keine Korrekturen gefunden. RatingBy: Korrigiert von @@ -433,8 +433,8 @@ AssignedTime: Zuteilung AchievedBonusPoints: Erreichte Bonuspunkte AchievedNormalPoints: Erreichte Punkte AchievedPassPoints: Erreichte Punkte -AchievedOf achieved@Points possible@Points: #{display achieved} von #{display possible} -PassAchievedOf points@Points passingPoints@Points maxPoints@Points: #{display points} von #{display maxPoints} (Bestanden ab #{display passingPoints}) +AchievedOf achieved@Points possible@Points: #{achieved} von #{possible} +PassAchievedOf points@Points passingPoints@Points maxPoints@Points: #{points} von #{maxPoints} (Bestanden ab #{passingPoints}) PassedResult: Ergebnis Passed: Bestanden NotPassed: Nicht bestanden @@ -447,7 +447,7 @@ RatingDone: Bewertung sichtbar RatingPercent: Erreicht RatingFiles: Korrigierte Dateien PointsNotPositive: Punktzahl darf nicht negativ sein -PointsTooHigh maxPoints@Points: Punktzahl darf nicht höher als #{tshow maxPoints} sein +PointsTooHigh maxPoints@Points: Punktzahl darf nicht höher als #{maxPoints} sein RatingPointsDone: Abgabe zählt als korrigiert, gdw. Punktezahl gesetzt ist ColumnRatingPoints: Punktzahl Pseudonyms: Pseudonyme @@ -527,7 +527,7 @@ LastEdit: Letzte Änderung LastEditByUser: Ihre letzte Bearbeitung NoEditByUser: Nicht von Ihnen bearbeitet -SubmissionFilesIgnored n@Int: Es #{pluralDE n "wurde" "wurden"} #{tshow n} #{pluralDE n "Datei" "Dateien"} in der hochgeladenen Abgabe ignoriert +SubmissionFilesIgnored n@Int: Es #{pluralDE n "wurde" "wurden"} #{n} #{pluralDE n "Datei" "Dateien"} in der hochgeladenen Abgabe ignoriert SubmissionDoesNotExist smid@CryptoFileNameSubmission: Es existiert keine Abgabe mit Nummer #{toPathPiece smid}. LDAPLoginTitle: Campus-Login @@ -542,8 +542,8 @@ CorrectorExcused: Entschuldigt CorrectorStateTip: Abwesende Korrektoren bekommen bei späteren Übungsblättern mehr Korrekturen zum Ausgleich zugewiesen. Entschuldigte Korrektoren müssen nicht nacharbeiten. DayIsAHoliday tid@TermId name@Text date@Text: "#{name}" (#{date}) ist ein Feiertag -DayIsOutOfLecture tid@TermId name@Text date@Text: "#{name}" (#{date}) ist außerhalb der Vorlesungszeit des #{display tid} -DayIsOutOfTerm tid@TermId name@Text date@Text: "#{name}" (#{date}) liegt nicht im Semester #{display tid} +DayIsOutOfLecture tid@TermId name@Text date@Text: "#{name}" (#{date}) ist außerhalb der Vorlesungszeit des #{tid} +DayIsOutOfTerm tid@TermId name@Text date@Text: "#{name}" (#{date}) liegt nicht im Semester #{tid} UploadModeNone: Kein Upload UploadModeAny: Upload, beliebige Datei(en) @@ -623,15 +623,15 @@ MailSubjectSheetActive csh@CourseShorthand sheetName@SheetName: #{sheetName} in MailSheetActiveIntro courseName@Text termDesc@Text sheetName@SheetName: Sie können nun #{sheetName} im Kurs #{courseName} (#{termDesc}) herunterladen. MailSubjectSubmissionsUnassigned csh@CourseShorthand sheetName@SheetName: Abgaben zu #{sheetName} in #{csh} konnten nicht verteilt werden -MailSubmissionsUnassignedIntro n@Int courseName@Text termDesc@Text sheetName@SheetName: #{tshow n} Abgaben zu #{sheetName} im Kurs #{courseName} (#{termDesc}) konnten nicht automatisiert verteilt werden. +MailSubmissionsUnassignedIntro n@Int courseName@Text termDesc@Text sheetName@SheetName: #{n} Abgaben zu #{sheetName} im Kurs #{courseName} (#{termDesc}) konnten nicht automatisiert verteilt werden. MailSubjectSheetSoonInactive csh@CourseShorthand sheetName@SheetName: #{sheetName} in #{csh} kann nur noch kurze Zeit abgegeben werden MailSheetSoonInactiveIntro courseName@Text termDesc@Text sheetName@SheetName: Abgabefirst für #{sheetName} im Kurs #{courseName} (#{termDesc}) endet in Kürze. MailSubjectSheetInactive csh@CourseShorthand sheetName@SheetName: Abgabezeitraum für #{sheetName} in #{csh} abgelaufen -MailSheetInactiveIntro courseName@Text termDesc@Text sheetName@SheetName n@Int num@Int64: Die Abgabefirst für #{sheetName} im Kurs #{courseName} (#{termDesc}) beendet. Es gab #{noneOneMoreDE n "Keine Abgaben" "Nur eine Abgabe von " (display n <> " Abgaben von ")}#{noneOneMoreDE num "" "einem Teilnehmer" (display num <> " Teilnehmern")}. +MailSheetInactiveIntro courseName@Text termDesc@Text sheetName@SheetName n@Int num@Int64: Die Abgabefirst für #{sheetName} im Kurs #{courseName} (#{termDesc}) beendet. Es gab #{noneOneMoreDE n "Keine Abgaben" "Nur eine Abgabe von " (toMessage n <> " Abgaben von ")}#{noneOneMoreDE num "" "einem Teilnehmer" (toMessage num <> " Teilnehmern")}. MailSubjectCorrectionsAssigned csh@CourseShorthand sheetName@SheetName: Ihnen wurden Korrekturen zu #{sheetName} in #{csh} zugeteilt -MailCorrectionsAssignedIntro courseName@Text termDesc@Text sheetName@SheetName n@Int: #{display n} #{pluralDE n "Abgabe wurde" "Abgaben wurden"} Ihnen zur Korrektur für #{sheetName} im Kurs #{courseName} (#{termDesc}) zugeteilt. +MailCorrectionsAssignedIntro courseName@Text termDesc@Text sheetName@SheetName n@Int: #{n} #{pluralDE n "Abgabe wurde" "Abgaben wurden"} Ihnen zur Korrektur für #{sheetName} im Kurs #{courseName} (#{termDesc}) zugeteilt. MailSubjectUserRightsUpdate name@Text: Berechtigungen für #{name} aktualisiert MailUserRightsIntro name@Text email@UserEmail: #{name} <#{email}> hat folgende Uni2work Berechtigungen: @@ -644,22 +644,22 @@ MailSubjectSupport: Supportanfrage MailSubjectSupportCustom customSubject@Text: [Support] #{customSubject} CommCourseSubject: Kursmitteilung -MailSubjectLecturerInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{display tid}-#{display ssh}-#{csh}] Einladung zum Kursverwalter +MailSubjectLecturerInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Einladung zum Kursverwalter InvitationAcceptDecline: Einladung annehmen/ablehnen -MailSubjectParticipantInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{display tid}-#{display ssh}-#{csh}] Einladung zum Kursteilname +MailSubjectParticipantInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Einladung zum Kursteilname -MailSubjectCorrectorInvitation tid@TermId ssh@SchoolId csh@CourseShorthand shn@SheetName: [#{display tid}-#{display ssh}-#{csh}] Einladung zum Korrektor für #{shn} +MailSubjectCorrectorInvitation tid@TermId ssh@SchoolId csh@CourseShorthand shn@SheetName: [#{tid}-#{ssh}-#{csh}] Einladung zum Korrektor für #{shn} -MailSubjectTutorInvitation tid@TermId ssh@SchoolId csh@CourseShorthand tutn@TutorialName: [#{display tid}-#{display ssh}-#{csh}] Einladung zum Tutor für #{tutn} +MailSubjectTutorInvitation tid@TermId ssh@SchoolId csh@CourseShorthand tutn@TutorialName: [#{tid}-#{ssh}-#{csh}] Einladung zum Tutor für #{tutn} -MailSubjectExamCorrectorInvitation tid@TermId ssh@SchoolId csh@CourseShorthand examn@ExamName: [#{display tid}-#{display ssh}-#{csh}] Einladung zum Korrektor für Klausur #{examn} +MailSubjectExamCorrectorInvitation tid@TermId ssh@SchoolId csh@CourseShorthand examn@ExamName: [#{tid}-#{ssh}-#{csh}] Einladung zum Korrektor für Klausur #{examn} -MailSubjectSubmissionUserInvitation tid@TermId ssh@SchoolId csh@CourseShorthand shn@SheetName: [#{display tid}-#{display ssh}-#{csh}] Einladung zu einer Abgabe für #{shn} +MailSubjectSubmissionUserInvitation tid@TermId ssh@SchoolId csh@CourseShorthand shn@SheetName: [#{tid}-#{ssh}-#{csh}] Einladung zu einer Abgabe für #{shn} SheetGrading: Bewertung -SheetGradingPoints maxPoints@Points: #{tshow maxPoints} Punkte -SheetGradingPassPoints maxPoints@Points passingPoints@Points: Bestanden ab #{tshow passingPoints} von #{tshow maxPoints} Punkten +SheetGradingPoints maxPoints@Points: #{maxPoints} Punkte +SheetGradingPassPoints maxPoints@Points passingPoints@Points: Bestanden ab #{passingPoints} von #{maxPoints} Punkten SheetGradingPassBinary: Bestanden/Nicht Bestanden SheetGradingInfo: "Bestanden nach Punkten" zählt sowohl zur maximal erreichbaren Gesamtpunktzahl also auch zur Anzahl der zu bestehenden Blätter. @@ -677,8 +677,8 @@ SheetTypeInfoNotGraded: Blätter ohne Wertung werden nirgends angerechnet, die B SheetTypeInfoBonus: Bonus Blätter zählen normal, erhöhen aber nicht die maximal erreichbare Punktzahl bzw. Anzahl zu bestehender Blätter. SheetGradingBonusIncluded: Erzielte Bonuspunkte wurden hier bereits zu den erreichten normalen Punkten hinzugezählt. SummaryTitle: Zusammenfassung über -SheetGradingSummaryTitle intgr@Integer: #{display intgr} #{pluralDE intgr "Blatt" "Blätter"} -SubmissionGradingSummaryTitle intgr@Integer: #{display intgr} #{pluralDE intgr "Abgabe" "Abgaben"} +SheetGradingSummaryTitle intgr@Integer: #{intgr} #{pluralDE intgr "Blatt" "Blätter"} +SubmissionGradingSummaryTitle intgr@Integer: #{intgr} #{pluralDE intgr "Abgabe" "Abgaben"} SheetTypeBonus': Bonus SheetTypeNormal': Normal @@ -910,8 +910,8 @@ CommSubject: Betreff CommBody: Nachricht CommRecipients: Empfänger CommRecipientsTip: Sie selbst erhalten immer eine Kopie der Nachricht -CommDuplicateRecipients n@Int: #{tshow n} #{pluralDE n "doppelter" "doppelte"} Empfänger ignoriert -CommSuccess n@Int: Nachricht wurde an #{tshow n} Empfänger versandt +CommDuplicateRecipients n@Int: #{n} #{pluralDE n "doppelter" "doppelte"} Empfänger ignoriert +CommSuccess n@Int: Nachricht wurde an #{n} Empfänger versandt CommCourseHeading: Kursmitteilung CommTutorialHeading: Tutorium-Mitteilung @@ -1008,7 +1008,7 @@ TutorialDelete: Löschen CourseExams: Klausuren CourseTutorials: Übungen -ParticipantsN n@Int: #{tshow n} Teilnehmer +ParticipantsN n@Int: #{n} Teilnehmer TutorialDeleteQuestion: Wollen Sie das unten aufgeführte Tutorium wirklich löschen? TutorialDeleted: Tutorium gelöscht @@ -1045,11 +1045,11 @@ HealthLDAPAdmins: Anteil der Administratoren, die im LDAP-Verzeichnis gefunden w HealthSMTPConnect: SMTP-Server kann erreicht werden HealthWidgetMemcached: Memcached-Server liefert Widgets korrekt aus -CourseParticipants n@Int: Derzeit #{tshow n} angemeldete Kursteilnehmer -CourseParticipantsInvited n@Int: #{tshow n} #{pluralDE n "Einladung" "Einladungen"} per E-Mail verschickt -CourseParticipantsAlreadyRegistered n@Int: #{tshow n} Teilnehmer #{pluralDE n "ist" "sind"} bereits angemeldet -CourseParticipantsRegisteredWithoutField n@Int: #{tshow n} Teilnehmer #{pluralDE n "wurde ohne assoziiertes Hauptfach" "wurden assoziierte Hauptfächer"} angemeldet, da #{pluralDE n "kein eindeutiges Hauptfach bestimmt werden konnte" "keine eindeutigen Hauptfächer bestimmt werden konnten"} -CourseParticipantsRegistered n@Int: #{tshow n} Teilnehmer erfolgreich angemeldet +CourseParticipants n@Int: Derzeit #{n} angemeldete Kursteilnehmer +CourseParticipantsInvited n@Int: #{n} #{pluralDE n "Einladung" "Einladungen"} per E-Mail verschickt +CourseParticipantsAlreadyRegistered n@Int: #{n} Teilnehmer #{pluralDE n "ist" "sind"} bereits angemeldet +CourseParticipantsRegisteredWithoutField n@Int: #{n} Teilnehmer #{pluralDE n "wurde ohne assoziiertes Hauptfach" "wurden assoziierte Hauptfächer"} angemeldet, da #{pluralDE n "kein eindeutiges Hauptfach bestimmt werden konnte" "keine eindeutigen Hauptfächer bestimmt werden konnten"} +CourseParticipantsRegistered n@Int: #{n} Teilnehmer erfolgreich angemeldet CourseParticipantsRegisterHeading: Kursteilnehmer hinzufügen ExamName: Name @@ -1164,4 +1164,4 @@ ExamClosedMustBeAfterStart: "Noten stehen fest ab" muss nach Start liegen ExamClosedMustBeAfterEnd: "Noten stehen fest ab" muss nach Ende liegen VersionHistory: Versionsgeschichte -KnownBugs: Bekannte Bugs \ No newline at end of file +KnownBugs: Bekannte Bugs diff --git a/package-lock.json b/package-lock.json index 337c5e344..aa51ea98c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5919,7 +5919,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -5940,12 +5941,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5960,17 +5963,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6087,7 +6093,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6099,6 +6106,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6113,6 +6121,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6120,12 +6129,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6144,6 +6155,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6224,7 +6236,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6236,6 +6249,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6321,7 +6335,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6357,6 +6372,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6376,6 +6392,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6419,12 +6436,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -12465,47 +12484,6 @@ "mkdirp": "^0.5.1" } }, - "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "write-yaml-file": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/write-yaml-file/-/write-yaml-file-3.0.1.tgz", - "integrity": "sha512-OHzbrlgjw/K/BAH6LdEOcSQFz5nkk0I/25CjKLIVFvcg2Ej7+QE/GTnitgqWnhlsdghor7OV5gfttQPGogQ1XA==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "js-yaml": "^3.8.1", - "make-dir": "^3.0.0", - "pify": "^4.0.0", - "write-file-atomic": "^2.4.3" - }, - "dependencies": { - "make-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", - "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.2.tgz", - "integrity": "sha512-z4PqiCpomGtWj8633oeAdXm1Kn1W++3T8epkZYnwiVgIYIJ0QHszhInYSJTYxebByQH7KVCEAn8R9duzZW2PhQ==", - "dev": true - } - } - }, "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", diff --git a/src/Data/CryptoID/Instances.hs b/src/Data/CryptoID/Instances.hs new file mode 100644 index 000000000..60b6e9081 --- /dev/null +++ b/src/Data/CryptoID/Instances.hs @@ -0,0 +1,14 @@ +{-# OPTIONS_GHC -fno-warn-orphans #-} + +module Data.CryptoID.Instances + ( + ) where + +import qualified Data.CryptoID as CID + +import Text.Blaze (ToMarkup(..)) + +import ClassyPrelude + +instance ToMarkup s => ToMarkup (CID.CryptoID c s) where + toMarkup = toMarkup . CID.ciphertext \ No newline at end of file diff --git a/src/Data/Fixed/Instances.hs b/src/Data/Fixed/Instances.hs new file mode 100644 index 000000000..03afaeb0e --- /dev/null +++ b/src/Data/Fixed/Instances.hs @@ -0,0 +1,13 @@ +{-# OPTIONS_GHC -fno-warn-orphans #-} + +module Data.Fixed.Instances + ( + ) where + +import ClassyPrelude +import Data.Fixed + +import Text.Blaze (ToMarkup(..)) + +instance HasResolution a => ToMarkup (Fixed a) where + toMarkup = toMarkup . showFixed True \ No newline at end of file diff --git a/src/Data/Maybe/Instances.hs b/src/Data/Maybe/Instances.hs new file mode 100644 index 000000000..4b6eaf9e8 --- /dev/null +++ b/src/Data/Maybe/Instances.hs @@ -0,0 +1,13 @@ +{-# OPTIONS_GHC -fno-warn-orphans #-} + +module Data.Maybe.Instances + ( + ) where + +import ClassyPrelude + +import Text.Blaze (ToMarkup(..), string) + +instance ToMarkup a => ToMarkup (Maybe a) where + toMarkup Nothing = string "" + toMarkup (Just x) = toMarkup x \ No newline at end of file diff --git a/src/Data/Sum/Instances.hs b/src/Data/Sum/Instances.hs new file mode 100644 index 000000000..81c99f393 --- /dev/null +++ b/src/Data/Sum/Instances.hs @@ -0,0 +1,13 @@ +{-# OPTIONS_GHC -fno-warn-orphans #-} + +module Data.Sum.Instances + ( + ) where + +import ClassyPrelude +import Data.Monoid (Sum(..)) + +import Text.Blaze (ToMarkup(..)) + +instance ToMarkup a => ToMarkup (Sum a) where + toMarkup = toMarkup . getSum \ No newline at end of file diff --git a/src/Foundation.hs b/src/Foundation.hs index ba5336f14..dae8095fc 100644 --- a/src/Foundation.hs +++ b/src/Foundation.hs @@ -21,10 +21,7 @@ import qualified Network.Wai as W (pathInfo) import Yesod.Core.Types (Logger) import qualified Yesod.Core.Unsafe as Unsafe -import Data.CaseInsensitive (CI) -import qualified Data.CaseInsensitive as CI - -import qualified Data.CryptoID as E +import Data.CaseInsensitive (original, mk) import Data.ByteArray (convert) import Crypto.Hash (Digest, SHAKE256, SHAKE128) @@ -91,18 +88,6 @@ import qualified Data.Aeson as JSON import Data.FileEmbed (embedFile) -instance DisplayAble b => DisplayAble (E.CryptoID a b) where - display = display . ciphertext - -instance {-# OVERLAPS #-} namespace ~ CryptoIDNamespace (CI FilePath) SubmissionId => DisplayAble (E.CryptoID namespace (CI FilePath)) where - display = toPathPiece - -instance DisplayAble TermId where - display = termToText . unTermKey - -instance DisplayAble SchoolId where - display = CI.original . unSchoolKey - type SMTPPool = Pool SMTPConnection -- infixl 9 :$: @@ -225,9 +210,9 @@ type IntMaybe = Maybe Int type TextList = [Text] -- | Convenience function for i18n messages definitions -maybeDisplay :: DisplayAble m => Text -> Maybe m -> Text -> Text -maybeDisplay _ Nothing _ = mempty -maybeDisplay before (Just x) after = before <> (display x) <> after +maybeToMessage :: ToMessage m => Text -> Maybe m -> Text -> Text +maybeToMessage _ Nothing _ = mempty +maybeToMessage before (Just x) after = before <> (toMessage x) <> after -- Messages creates type UniWorXMessage and RenderMessage UniWorX instance mkMessage "UniWorX" "messages/uniworx" "de" @@ -259,6 +244,17 @@ instance RenderMessage UniWorX ShortTermIdentifier where instance RenderMessage UniWorX String where renderMessage f ls str = renderMessage f ls $ Text.pack str +-- TODO: raw number representation; instead, display e.g. 1000 as 1.000 or 1,000 or ... (language-dependent!) +instance RenderMessage UniWorX Int where + renderMessage f ls = renderMessage f ls . tshow +instance RenderMessage UniWorX Int64 where + renderMessage f ls = renderMessage f ls . tshow +instance RenderMessage UniWorX Integer where + renderMessage f ls = renderMessage f ls . tshow + +instance HasResolution a => RenderMessage UniWorX (Fixed a) where + renderMessage f ls = renderMessage f ls . showFixed True + instance RenderMessage UniWorX Load where renderMessage foundation ls = renderMessage foundation ls . \case (Load {byTutorial=Nothing , byProportion=p}) -> MsgCorByProportionOnly p @@ -336,6 +332,23 @@ instance RenderMessage UniWorX ExamGrade where renderMessage _ _ = pack . (showFixed False :: Deci -> String) . fromRational . review numberGrade +-- ToMessage instances for converting raw numbers to Text (no internationalization) + +instance ToMessage Int where + toMessage = tshow +instance ToMessage Int64 where + toMessage = tshow +instance ToMessage Integer where + toMessage = tshow + +instance HasResolution a => ToMessage (Fixed a) where + toMessage = toMessage . showFixed True + +-- Do not use toMessage on Rationals and round them automatically. Instead, use rationalToFixed3 (declared in src/Utils.hs) to convert a Rational to Fixed E3! +-- instance ToMessage Rational where +-- toMessage = toMessage . fromRational' +-- where fromRational' = fromRational :: Rational -> Fixed E3 + newtype ErrorResponseTitle = ErrorResponseTitle ErrorResponse embedRenderMessageVariant ''UniWorX ''ErrorResponseTitle ("ErrorResponseTitle" <>) @@ -1483,11 +1496,11 @@ instance YesodBreadcrumbs UniWorX where breadcrumb (TermEditExistR tid) = return ("Editieren" , Just $ TermCourseListR tid) breadcrumb (TermCourseListR (unTermKey -> tid)) = getMessageRender <&> \mr -> (mr $ ShortTermIdentifier tid, Just CourseListR) - breadcrumb (TermSchoolCourseListR tid ssh) = return (CI.original $ unSchoolKey ssh, Just $ TermCourseListR tid) + breadcrumb (TermSchoolCourseListR tid ssh) = return (original $ unSchoolKey ssh, Just $ TermCourseListR tid) breadcrumb CourseListR = return ("Kurse" , Nothing) breadcrumb CourseNewR = return ("Neu" , Just CourseListR) - breadcrumb (CourseR tid ssh csh CShowR) = return (CI.original csh, Just $ TermSchoolCourseListR tid ssh) + breadcrumb (CourseR tid ssh csh CShowR) = return (original csh, Just $ TermSchoolCourseListR tid ssh) -- (CourseR tid ssh csh CRegisterR) -- is POST only breadcrumb (CourseR tid ssh csh CEditR) = return ("Editieren" , Just $ CourseR tid ssh csh CShowR) breadcrumb (CourseR tid ssh csh CUsersR) = return ("Anmeldungen", Just $ CourseR tid ssh csh CShowR) @@ -1507,15 +1520,15 @@ instance YesodBreadcrumbs UniWorX where breadcrumb (CourseR tid ssh csh CExamListR) = return ("Klausuren", Just $ CourseR tid ssh csh CShowR) breadcrumb (CourseR tid ssh csh CExamNewR) = return ("Anlegen", Just $ CourseR tid ssh csh CExamListR) - breadcrumb (CExamR tid ssh csh examn EShowR) = return (CI.original examn, Just $ CourseR tid ssh csh CExamListR) + breadcrumb (CExamR tid ssh csh examn EShowR) = return (original examn, Just $ CourseR tid ssh csh CExamListR) breadcrumb (CExamR tid ssh csh examn EEditR) = return ("Bearbeiten", Just $ CExamR tid ssh csh examn EShowR) - breadcrumb (CTutorialR tid ssh csh tutn TUsersR) = return (CI.original tutn, Just $ CourseR tid ssh csh CTutorialListR) + breadcrumb (CTutorialR tid ssh csh tutn TUsersR) = return (original tutn, Just $ CourseR tid ssh csh CTutorialListR) breadcrumb (CTutorialR tid ssh csh tutn TEditR) = return ("Bearbeiten", Just $ CTutorialR tid ssh csh tutn TUsersR) breadcrumb (CTutorialR tid ssh csh tutn TDeleteR) = return ("Löschen", Just $ CTutorialR tid ssh csh tutn TUsersR) breadcrumb (CTutorialR tid ssh csh tutn TCommR) = return ("Mitteilung", Just $ CTutorialR tid ssh csh tutn TUsersR) - breadcrumb (CSheetR tid ssh csh shn SShowR) = return (CI.original shn, Just $ CourseR tid ssh csh SheetListR) + breadcrumb (CSheetR tid ssh csh shn SShowR) = return (original shn, Just $ CourseR tid ssh csh SheetListR) breadcrumb (CSheetR tid ssh csh shn SEditR) = return ("Bearbeiten" , Just $ CSheetR tid ssh csh shn SShowR) breadcrumb (CSheetR tid ssh csh shn SDelR ) = return ("Löschen" , Just $ CSheetR tid ssh csh shn SShowR) breadcrumb (CSheetR tid ssh csh shn SSubsR) = return ("Abgaben" , Just $ CSheetR tid ssh csh shn SShowR) @@ -1531,7 +1544,7 @@ instance YesodBreadcrumbs UniWorX where breadcrumb (CourseR tid ssh csh MaterialListR) = return ("Material" , Just $ CourseR tid ssh csh CShowR) breadcrumb (CourseR tid ssh csh MaterialNewR ) = return ("Neu" , Just $ CourseR tid ssh csh MaterialListR) - breadcrumb (CMaterialR tid ssh csh mnm MShowR) = return (CI.original mnm, Just $ CourseR tid ssh csh MaterialListR) + breadcrumb (CMaterialR tid ssh csh mnm MShowR) = return (original mnm, Just $ CourseR tid ssh csh MaterialListR) breadcrumb (CMaterialR tid ssh csh mnm MEditR) = return ("Bearbeiten" , Just $ CMaterialR tid ssh csh mnm MShowR) breadcrumb (CMaterialR tid ssh csh mnm MDelR) = return ("Löschen" , Just $ CMaterialR tid ssh csh mnm MShowR) -- (CMaterialR tid ssh csh mnm MFileR) -- just for Downloads @@ -2062,8 +2075,8 @@ pageActions (CourseR tid ssh csh SheetListR) = , menuItemLabel = MsgMenuCorrectionsOwn , menuItemIcon = Nothing , menuItemRoute = SomeRoute (CorrectionsR, [ ("corrections-term" , termToText $ unTermKey tid) - , ("corrections-school", CI.original $ unSchoolKey ssh) - , ("corrections-course", CI.original csh) + , ("corrections-school", original $ unSchoolKey ssh) + , ("corrections-course", original csh) ]) , menuItemModal = False , menuItemAccessCallback' = do @@ -2223,9 +2236,9 @@ pageActions (CSheetR tid ssh csh shn SShowR) = , menuItemLabel = MsgMenuCorrectionsOwn , menuItemIcon = Nothing , menuItemRoute = SomeRoute (CorrectionsR, [ ("corrections-term" , termToText $ unTermKey tid) - , ("corrections-school", CI.original $ unSchoolKey ssh) - , ("corrections-course", CI.original csh) - , ("corrections-sheet" , CI.original shn) + , ("corrections-school", original $ unSchoolKey ssh) + , ("corrections-course", original csh) + , ("corrections-sheet" , original shn) ]) , menuItemModal = False , menuItemAccessCallback' = (== Authorized) <$> evalAccessCorrector tid ssh csh @@ -2576,7 +2589,7 @@ routeNormalizers = tell $ Any True maybeOrig f route = maybeT (return route) $ f route hasChanged a b - | ((/=) `on` CI.original) a b = do + | ((/=) `on` original) a b = do $logDebugS "routeNormalizers" [st|#{tshow a} /= #{tshow b}|] tell $ Any True | otherwise = return () @@ -2642,7 +2655,7 @@ instance YesodAuth UniWorX where now <- liftIO getCurrentTime let - userIdent = CI.mk credsIdent + userIdent = mk credsIdent uAuth = UniqueAuthentication userIdent isDummy = credsPlugin == "dummy" @@ -2680,7 +2693,7 @@ instance YesodAuth UniWorX where flip catches excHandlers $ case (,) <$> appLdapConf <*> appLdapPool of Just (ldapConf, ldapPool) -> fmap (either id id) . runExceptT $ do - ldapData <- campusUser ldapConf ldapPool $ Creds credsPlugin (CI.original userIdent) credsExtra + ldapData <- campusUser ldapConf ldapPool $ Creds credsPlugin (original userIdent) credsExtra $logDebugS "LDAP" $ "Successful LDAP lookup: " <> tshow ldapData let @@ -2697,7 +2710,7 @@ instance YesodAuth UniWorX where userEmail <- if | Just [bs] <- userEmail' , Right userEmail <- Text.decodeUtf8' bs - -> return $ CI.mk userEmail + -> return $ mk userEmail | otherwise -> throwError $ ServerError "Could not retrieve user email" userDisplayName <- if @@ -2752,7 +2765,7 @@ instance YesodAuth UniWorX where Right str <- return $ Text.decodeUtf8' v' return str - termNames = nubBy ((==) `on` CI.mk) $ do + termNames = nubBy ((==) `on` mk) $ do (k, v) <- ldapData guard $ k == Attr "dfnEduPersonFieldOfStudyString" v' <- v diff --git a/src/Handler/Corrections.hs b/src/Handler/Corrections.hs index 43a8bbed7..811f0fcb5 100644 --- a/src/Handler/Corrections.hs +++ b/src/Handler/Corrections.hs @@ -126,7 +126,7 @@ colSheet = sortable (Just "sheet") (i18nCell MsgSheet) $ \row -> ssh = course ^. _4 csh = course ^. _2 shn = sheetName $ entityVal sheet - in anchorCell (CSheetR tid ssh csh shn SShowR) [whamlet|#{display shn}|] + in anchorCell (CSheetR tid ssh csh shn SShowR) [whamlet|_{shn}|] colSheetType :: IsDBTable m a => Colonnade Sortable CorrectionTableData (DBCell m a) colSheetType = sortable (toNothing "sheetType") (i18nCell MsgSheetType) $ @@ -149,7 +149,7 @@ colSubmissionLink = sortable Nothing (i18nCell MsgSubmission) mkRoute = do cid <- mkCid return $ CSubmissionR tid ssh csh shn cid SubShowR - in anchorCellM mkRoute (mkCid >>= \cid -> [whamlet|#{display cid}|]) + in anchorCellM mkRoute (mkCid >>= \cid -> [whamlet|#{cid}|]) colSelect :: forall act h. (Semigroup act, Monoid act, Headedness h) => Colonnade h CorrectionTableData (DBCell _ (FormResult (act, DBFormResult CryptoFileNameSubmission Bool CorrectionTableData), SheetTypeSummary)) colSelect = dbSelect (_1 . applying _2) id $ \DBRow{ dbrOutput=(Entity subId _, _, _, _, _, _) } -> encrypt subId diff --git a/src/Handler/Course.hs b/src/Handler/Course.hs index f55328ca5..3340c6894 100644 --- a/src/Handler/Course.hs +++ b/src/Handler/Course.hs @@ -53,7 +53,7 @@ colCourse :: IsDBTable m a => Colonnade Sortable CourseTableData (DBCell m a) colCourse = sortable (Just "course") (i18nCell MsgCourse) $ \DBRow{ dbrOutput=(Entity _ Course{..}, _, _, _) } -> anchorCell (CourseR courseTerm courseSchool courseShorthand CShowR) - [whamlet|#{display courseName}|] + [whamlet|_{courseName}|] -- colCourseDescr :: IsDBTable m a => Colonnade Sortable CourseTableData (DBCell m a) -- colCourseDescr = sortable (Just "course") (i18nCell MsgCourse) $ do @@ -70,7 +70,7 @@ colDescription = sortable Nothing mempty colCShort :: IsDBTable m a => Colonnade Sortable CourseTableData (DBCell m a) colCShort = sortable (Just "cshort") (i18nCell MsgCourseShort) $ \DBRow{ dbrOutput=(Entity _ Course{..}, _, _, _) } -> - anchorCell (CourseR courseTerm courseSchool courseShorthand CShowR) [whamlet|#{display courseShorthand}|] + anchorCell (CourseR courseTerm courseSchool courseShorthand CShowR) [whamlet|_{courseShorthand}|] -- colCShortDescr :: IsDBTable m a => Colonnade Sortable CourseTableData (DBCell m a) -- colCShortDescr = sortable (Just "cshort") (i18nCell MsgCourseShort) @@ -89,17 +89,17 @@ colCShort = sortable (Just "cshort") (i18nCell MsgCourseShort) colTerm :: IsDBTable m a => Colonnade Sortable CourseTableData (DBCell m a) colTerm = sortable (Just "term") (i18nCell MsgTerm) $ \DBRow{ dbrOutput=(Entity _ Course{..}, _, _, _) } -> - anchorCell (TermCourseListR courseTerm) [whamlet|#{display courseTerm}|] + anchorCell (TermCourseListR courseTerm) [whamlet|#{courseTerm}|] colSchool :: IsDBTable m a => Colonnade Sortable CourseTableData (DBCell m a) colSchool = sortable (Just "school") (i18nCell MsgCourseSchool) $ \DBRow{ dbrOutput=(Entity _ Course{..}, _, _, Entity _ School{..}) } -> - anchorCell (TermSchoolCourseListR courseTerm courseSchool) [whamlet|#{display schoolName}|] + anchorCell (TermSchoolCourseListR courseTerm courseSchool) [whamlet|_{schoolName}|] colSchoolShort :: IsDBTable m a => Colonnade Sortable CourseTableData (DBCell m a) colSchoolShort = sortable (Just "schoolshort") (i18nCell MsgCourseSchoolShort) $ \DBRow{ dbrOutput=(Entity _ Course{..}, _, _, Entity _ School{..}) } -> - anchorCell (TermSchoolCourseListR courseTerm courseSchool) [whamlet|#{display schoolShorthand}|] + anchorCell (TermSchoolCourseListR courseTerm courseSchool) [whamlet|_{schoolShorthand}|] colRegFrom :: IsDBTable m a => Colonnade Sortable CourseTableData (DBCell m a) colRegFrom = sortable (Just "register-from") (i18nCell MsgRegisterFrom) @@ -1220,7 +1220,7 @@ postCUsersR tid ssh csh = do ] addMessageI Success $ MsgCourseUsersDeregistered nrDel redirect $ CourseR tid ssh csh CUsersR - let headingLong = [whamlet|_{MsgMenuCourseMembers} #{courseName course} #{display tid}|] + let headingLong = [whamlet|_{MsgMenuCourseMembers} #{courseName course} #{tid}|] headingShort = prependCourseTitle tid ssh csh MsgCourseMembers siteLayout headingLong $ do setTitleI headingShort @@ -1407,7 +1407,7 @@ postCUserR tid ssh csh uCId = do mRegAt <- for (courseParticipantRegistration . entityVal <$> mRegistration) $ formatTime SelFormatDateTime -- generate output - let headingLong = [whamlet|^{nameWidget userDisplayName userSurname} - _{MsgCourseMemberOf} #{csh} #{display tid}|] + let headingLong = [whamlet|^{nameWidget userDisplayName userSurname} - _{MsgCourseMemberOf} #{csh} #{tid}|] headingShort = prependCourseTitle tid ssh csh $ SomeMessage userDisplayName siteLayout headingLong $ do setTitleI headingShort diff --git a/src/Handler/Home.hs b/src/Handler/Home.hs index b907ecf50..84420bb07 100644 --- a/src/Handler/Home.hs +++ b/src/Handler/Home.hs @@ -33,14 +33,14 @@ homeOpenCourses = do colonnade = mconcat [ -- dbRow sortable (Just "term") (i18nCell MsgTerm) $ \DBRow{ dbrOutput=Entity{entityVal = course} } -> - textCell $ display $ courseTerm course + textCell $ toMessage $ courseTerm course , sortable (Just "school") (i18nCell MsgCourseSchool) $ \DBRow{ dbrOutput=Entity{entityVal = course} } -> - textCell $ display $ courseSchool course + textCell $ toMessage $ courseSchool course , sortable (Just "course") (i18nCell MsgCourse) $ \DBRow{ dbrOutput=Entity{entityVal = course} } -> do let tid = courseTerm course ssh = courseSchool course csh = courseShorthand course - anchorCell (CourseR tid ssh csh CShowR) (toWidget $ display csh) + anchorCell (CourseR tid ssh csh CShowR) (toWidget csh) , sortable (Just "deadline") (i18nCell MsgRegisterTo) $ \DBRow{ dbrOutput=Entity{entityVal = course} } -> cell $ traverse (formatTime SelFormatDateTime) (courseRegisterTo course) >>= maybe mempty toWidget ] @@ -117,13 +117,13 @@ homeUpcomingSheets uid = do [ -- dbRow -- TOOD: sortable (Just "term") (textCell MsgTerm) $ \DBRow{ dbrOutput=(view _1 -> E.Value tid) } -> sortable (Just "term") (i18nCell MsgTerm) $ \DBRow{ dbrOutput=(E.Value tid,_,_,_,_,_) } -> - textCell $ display tid + textCell $ toMessage tid , sortable (Just "school") (i18nCell MsgCourseSchool) $ \DBRow{ dbrOutput=(_,E.Value ssh,_,_,_,_) } -> - textCell $ display ssh + textCell $ toMessage ssh , sortable (Just "course") (i18nCell MsgCourse) $ \DBRow{ dbrOutput=(E.Value tid, E.Value ssh, E.Value csh, _, _, _) } -> - anchorCell (CourseR tid ssh csh CShowR) (toWidget $ display csh) + anchorCell (CourseR tid ssh csh CShowR) (toWidget csh) , sortable (Just "sheet") (i18nCell MsgSheet) $ \DBRow{ dbrOutput=(E.Value tid, E.Value ssh, E.Value csh, E.Value shn, _, _) } -> - anchorCell (CSheetR tid ssh csh shn SShowR) (toWidget $ display shn) + anchorCell (CSheetR tid ssh csh shn SShowR) (toWidget shn) , sortable (Just "deadline") (i18nCell MsgDeadline) $ \DBRow{ dbrOutput=(_, _, _, _, E.Value deadline, _) } -> cell $ formatTime SelFormatDateTime deadline >>= toWidget , sortable (Just "done") (i18nCell MsgDone) $ \DBRow{ dbrOutput=(E.Value tid, E.Value ssh, E.Value csh, E.Value shn, _, E.Value mbsid) } -> diff --git a/src/Handler/Profile.hs b/src/Handler/Profile.hs index 282286f4f..783752808 100644 --- a/src/Handler/Profile.hs +++ b/src/Handler/Profile.hs @@ -45,7 +45,7 @@ makeSettingForm template html = do <*> notificationForm (stgNotificationSettings <$> template) return (result, widget) -- no validation required here where - themeList = [Option (display t) t (toPathPiece t) | t <- universeF] + themeList = [Option (toMessage t) t (toPathPiece t) | t <- universeF] -- -- Version with proper grouping: -- diff --git a/src/Handler/Sheet.hs b/src/Handler/Sheet.hs index 791bce180..946e0395f 100644 --- a/src/Handler/Sheet.hs +++ b/src/Handler/Sheet.hs @@ -236,7 +236,7 @@ getSheetListR tid ssh csh = do mkRoute = do cid' <- mkCid return $ CSubmissionR tid ssh csh sheetName cid' SubShowR - in anchorCellM mkRoute (mkCid >>= \cid2 -> [whamlet|#{display cid2}|]) + in anchorCellM mkRoute (mkCid >>= \cid2 -> [whamlet|#{cid2}|]) , sortable (Just "rating") (i18nCell MsgRating) $ \DBRow{dbrOutput=(Entity _ Sheet{..}, _, mbSub,_)} -> let stats = sheetTypeSum sheetType in -- for statistics over all shown rows diff --git a/src/Handler/Users.hs b/src/Handler/Users.hs index 8af2f6620..01b0055d9 100644 --- a/src/Handler/Users.hs +++ b/src/Handler/Users.hs @@ -41,7 +41,7 @@ getUsersR = do (nameWidget userDisplayName userSurname) , sortable (Just "matriculation") (i18nCell MsgMatrikelNr) $ \DBRow{ dbrOutput = Entity uid User{..} } -> anchorCellM (AdminUserR <$> encrypt uid) - (toWidget . display $ userMatrikelnummer) + (toWgt userMatrikelnummer) -- , sortable (Just "last-name") (i18nCell MsgName) $ \DBRow{ dbrOutput = Entity uid User{..} } -> anchorCellM -- (AdminUserR <$> encrypt uid) -- (toWidget . display $ last $ impureNonNull $ words $ userDisplayName) diff --git a/src/Handler/Utils/Table/Cells.hs b/src/Handler/Utils/Table/Cells.hs index b901fb8d3..2e8e53db8 100644 --- a/src/Handler/Utils/Table/Cells.hs +++ b/src/Handler/Utils/Table/Cells.hs @@ -175,8 +175,8 @@ cellHasEMail = emailCell . view _userEmail maybeDateTimeCell :: IsDBTable m a => Maybe UTCTime -> DBCell m a maybeDateTimeCell = maybe mempty dateTimeCell -numCell :: (IsDBTable m a, Num b, DisplayAble b) => b -> DBCell m a -numCell = textCell . display +numCell :: (IsDBTable m a, Num b, ToMessage b) => b -> DBCell m a +numCell = textCell . toMessage int64Cell :: (IsDBTable m a) => Int64-> DBCell m a int64Cell = numCell @@ -185,7 +185,7 @@ termCell :: IsDBTable m a => TermId -> DBCell m a termCell tid = anchorCell link name where link = TermCourseListR tid - name = text2widget $ display tid + name = toWgt tid termCellCL :: IsDBTable m a => CourseLink -> DBCell m a termCellCL (tid,_,_) = termCell tid @@ -194,11 +194,11 @@ schoolCell :: IsDBTable m a => Maybe TermId -> SchoolId -> DBCell m a schoolCell (Just tid) ssh = anchorCell link name where link = TermSchoolCourseListR tid ssh - name = text2widget $ display ssh + name = toWgt ssh schoolCell Nothing ssh = anchorCell link name where link = SchoolShowR ssh - name = text2widget $ display ssh + name = toWgt ssh schoolCellCL :: IsDBTable m a => CourseLink -> DBCell m a schoolCellCL (tid,ssh,_) = schoolCell (Just tid) ssh @@ -207,7 +207,7 @@ courseCellCL :: IsDBTable m a => CourseLink -> DBCell m a courseCellCL (tid,ssh,csh) = anchorCell link name where link = CourseR tid ssh csh CShowR - name = citext2widget csh + name = toWgt csh courseCell :: IsDBTable m a => Course -> DBCell m a courseCell Course{..} = anchorCell link name `mappend` desc @@ -228,7 +228,7 @@ sheetCell crse shn = ssh = crse ^. _2 csh = crse ^. _3 link= CSheetR tid ssh csh shn SShowR - in anchorCell link $ display2widget shn + in anchorCell link $ toWgt shn submissionCell :: IsDBTable m a => CourseLink -> SheetName -> SubmissionId -> DBCell m a submissionCell crse shn sid = @@ -237,7 +237,7 @@ submissionCell crse shn sid = csh = crse ^. _3 mkCid = encrypt sid mkRoute cid = CSubmissionR tid ssh csh shn cid SubShowR - mkText = display2widget + mkText = toWgt in anchorCellM' mkCid mkRoute mkText correctorStateCell :: IsDBTable m a => SheetCorrector -> DBCell m a diff --git a/src/Import/NoModel.hs b/src/Import/NoModel.hs index d2ba81705..9753d0e75 100644 --- a/src/Import/NoModel.hs +++ b/src/Import/NoModel.hs @@ -76,6 +76,10 @@ import Language.Haskell.TH.Instances as Import () import Data.List.NonEmpty.Instances as Import () import Data.NonNull.Instances as Import () import Data.Monoid.Instances as Import () +import Data.Maybe.Instances as Import () +import Data.CryptoID.Instances as Import () +import Data.Sum.Instances as Import () +import Data.Fixed.Instances as Import () import Data.Set.Instances as Import () import Data.HashMap.Strict.Instances as Import () import Data.HashSet.Instances as Import () diff --git a/src/Model.hs b/src/Model.hs index ee5a8bbd8..c97b1a68e 100644 --- a/src/Model.hs +++ b/src/Model.hs @@ -16,13 +16,16 @@ import Cron.Types import Data.Aeson (Value) -import Data.CaseInsensitive (CI) +import Data.CaseInsensitive (CI, original) import Data.CaseInsensitive.Instances () import Utils.Message (MessageStatus) import Settings.Cluster (ClusterSettingsKey) +import Text.Blaze (ToMarkup(..)) + + -- You can define all of your database entities in the entities file. -- You can find more information on persistent and how to declare entities -- at: @@ -48,3 +51,17 @@ instance Ord User where submissionRatingDone :: Submission -> Bool submissionRatingDone Submission{..} = isJust submissionRatingTime + +-- ToMarkup and ToMessage instances for displaying selected database primary keys + +instance ToMarkup (Key School) where + toMarkup = toMarkup . unSchoolKey + +instance ToMessage (Key School) where + toMessage = original . unSchoolKey + +instance ToMarkup (Key Term) where + toMarkup = toMarkup . termToText . unTermKey + +instance ToMessage (Key Term) where + toMessage = termToText . unTermKey \ No newline at end of file diff --git a/src/Model/Types/Common.hs b/src/Model/Types/Common.hs index 94966e1c1..c7d18cd54 100644 --- a/src/Model/Types/Common.hs +++ b/src/Model/Types/Common.hs @@ -16,7 +16,6 @@ import qualified Yesod.Auth.Util.PasswordStore as PWStore type Count = Sum Integer type Points = Centi - type Email = Text type SchoolName = CI Text @@ -34,4 +33,4 @@ type PWHashAlgorithm = ByteString -> PWStore.Salt -> Int -> ByteString type InstanceId = UUID type ClusterId = UUID type TokenId = UUID -type TermCandidateIncidence = UUID +type TermCandidateIncidence = UUID \ No newline at end of file diff --git a/src/Model/Types/DateTime.hs b/src/Model/Types/DateTime.hs index a1dad3e8d..0cbd6fd2b 100644 --- a/src/Model/Types/DateTime.hs +++ b/src/Model/Types/DateTime.hs @@ -45,8 +45,6 @@ seasonFromChar c where (~=) = (==) `on` CI.mk --- instance DisplayAble Season - data TermIdentifier = TermIdentifier { year :: Integer -- ^ Using 'Integer' to model years is consistent with 'Data.Time.Calendar' , season :: Season diff --git a/src/Model/Types/Misc.hs b/src/Model/Types/Misc.hs index efe0308a6..510b21251 100644 --- a/src/Model/Types/Misc.hs +++ b/src/Model/Types/Misc.hs @@ -39,6 +39,6 @@ instance Finite Theme nullaryPathPiece ''Theme $ camelToPathPiece' 1 -$(deriveSimpleWith ''DisplayAble 'display (over Text.packed $ Text.intercalate " " . unsafeTail . splitCamel) ''Theme) -- describe theme to user +$(deriveSimpleWith ''ToMessage 'toMessage (over Text.packed $ Text.intercalate " " . unsafeTail . splitCamel) ''Theme) -- describe theme to user derivePersistField "Theme" diff --git a/src/Model/Types/Sheet.hs b/src/Model/Types/Sheet.hs index 5e971fb1d..b4a6b0a90 100644 --- a/src/Model/Types/Sheet.hs +++ b/src/Model/Types/Sheet.hs @@ -164,13 +164,6 @@ sheetFile2markup SheetHint = iconHint sheetFile2markup SheetSolution = iconSolution sheetFile2markup SheetMarking = iconMarking --- $(deriveSimpleWith ''DisplayAble 'display (drop 17) ''SheetFileType) --- instance DisplayAble SheetFileType where -- deprecated, see RenderMessage instance in Foundation --- display SheetExercise = "Aufgabenstellung" --- display SheetHint = "Hinweise" --- display SheetSolution = "Musterlösung" --- display SheetMarking = "Korrekturhinweise" - -- partitionFileType' :: Ord a => [(SheetFileType,a)] -> Map SheetFileType (Set a) -- partitionFileType' = groupMap diff --git a/src/Utils.hs b/src/Utils.hs index e51b9dd38..6096851e2 100644 --- a/src/Utils.hs +++ b/src/Utils.hs @@ -31,7 +31,6 @@ import Text.Blaze (Markup, ToMarkup) import Data.Char (isDigit, isSpace, isAscii) import Data.Text (dropWhileEnd, takeWhileEnd, justifyRight) -import Numeric (showFFloat) import Data.Set (Set) import qualified Data.Set as Set @@ -48,9 +47,6 @@ import Control.Monad.Except (MonadError(..)) import Control.Monad.Trans.Maybe as Utils (MaybeT(..)) import Control.Monad.Catch hiding (throwM) - -import qualified Database.Esqueleto as E (Value, unValue) - import Language.Haskell.TH import Language.Haskell.TH.Instances () import Instances.TH.Lift () @@ -252,63 +248,14 @@ str2widget :: (MonadBaseControl IO m, MonadThrow m, MonadIO m) => String -> WidgetT site m () str2widget s = [whamlet|#{s}|] -display2widget :: (MonadBaseControl IO m, MonadThrow m, MonadIO m, DisplayAble a) - => a -> WidgetT site m () -display2widget = text2widget . display - withFragment :: Monad m => MForm m (a, WidgetT site IO ()) -> Markup -> MForm m (a, WidgetT site IO ()) withFragment form html = flip fmap form $ over _2 (toWidget html >>) +rationalToFixed :: forall a. HasResolution a => Rational -> Fixed a +rationalToFixed = MkFixed . round . (* (fromIntegral $ resolution (Proxy :: HasResolution a => Proxy a))) --- Types that can be converted to Text for direct displayed to User! (Show for debugging, Display for Production) -{- (not so sure we really want to get rid of display?!) DEPRECATED display "Create RenderMessage Instances instead!" -} -class DisplayAble a where - display :: a -> Text - -- Default definitions for types belonging to Show (allows empty instance declarations) - default display :: Show a => a -> Text - display = pack . show - -instance DisplayAble Text where - display = id - --- instance DisplayAble String where --- display = pack - -instance DisplayAble Int -instance DisplayAble Int64 -instance DisplayAble Integer - -instance DisplayAble Rational where - display r = showFFloat (Just 2) (rat2float r) "" - & pack - & dropWhileEnd ('0'==) - & dropWhileEnd ('.'==) - where - rat2float :: Rational -> Double - rat2float = fromRational - -instance DisplayAble a => DisplayAble (Maybe a) where - display Nothing = "" - display (Just x) = display x - -instance DisplayAble a => DisplayAble (E.Value a) where - display = display . E.unValue - -instance DisplayAble a => DisplayAble (CI a) where - display = display . CI.original - -instance HasResolution a => DisplayAble (Fixed a) where - display = pack . showFixed True - -instance DisplayAble a => DisplayAble (Sum a) where - display = display . getSum - -{- We do not want DisplayAble for every Show-Class: - We want to explicitly verify that the resulting text can be displayed to the User! - For example: UTCTime values were shown without proper format rendering! -instance {-# OVERLAPPABLE #-} Show a => DisplayAble a where -- The easy way out of UndecidableInstances (TypeFamilies would have been proper, but are much more complicated) - display = pack . show --} +rationalToFixed3 :: Rational -> Fixed E3 +rationalToFixed3 = rationalToFixed -- | Convert `part` and `whole` into percentage including symbol -- showing trailing zeroes and to decimal digits @@ -326,8 +273,8 @@ textPercent' trailZero precision part whole | precision == 4 = showPercent (frac :: Micro) | otherwise = showPercent (frac :: Pico) where - frac :: forall a . HasResolution a => Fixed a - frac = MkFixed $ round $ (* (fromInteger $ resolution (Proxy :: Proxy a))) $ (100*) $ toRational part / toRational whole + frac :: forall a. HasResolution a => Fixed a + frac = rationalToFixed $ (100*) $ toRational part / toRational whole showPercent :: HasResolution a => Fixed a -> Text showPercent f = pack $ showFixed trailZero f <> "%" diff --git a/src/Utils/TH.hs b/src/Utils/TH.hs index 5e7b1f36d..a1f9e9163 100644 --- a/src/Utils/TH.hs +++ b/src/Utils/TH.hs @@ -95,9 +95,6 @@ afterN n = do deriveShowWith :: (String -> String) -> Name -> Q [Dec] deriveShowWith = deriveSimpleWith ''Show 'show --- deriveDisplayWith :: (String -> String) -> Name -> Q [Dec] --- deriveDisplayWith = deriveSimpleWith ''DisplayAble 'display - deriveSimpleWith :: Name -> Name -> (String -> String) -> Name -> Q [Dec] deriveSimpleWith cls fun strOp ty = do (TyConI tyCon) <- reify ty diff --git a/src/index.md b/src/index.md index d90c78eb2..4dceca669 100644 --- a/src/index.md +++ b/src/index.md @@ -7,8 +7,7 @@ Utils, Utils.* : Hilfsfunktionionen _unabhängig von Foundation_ Utils - : Yesod Hilfsfunktionen und Instanzen, Text-HTML-Widget-Konvertierungen - (`DisplayAble`), Crud, `NTop`, Utility-Funktionen für `MonadPlus`, `Maybe`, + : Yesod Hilfsfunktionen und Instanzen, Crud, `NTop`, Utility-Funktionen für `MonadPlus`, `Maybe`, `MaybeT`, `Map`, und Attrs-Lists Utils.TH diff --git a/templates/correction-user.hamlet b/templates/correction-user.hamlet index 0a639bf81..78a4533b2 100644 --- a/templates/correction-user.hamlet +++ b/templates/correction-user.hamlet @@ -2,11 +2,11 @@