Merge branch 'master' into feat/pagination

This commit is contained in:
Gregor Kleen 2018-06-30 18:54:19 +02:00
commit 60b250f5b3
22 changed files with 391 additions and 119 deletions

View File

@ -11,12 +11,16 @@ SummerTerm year@Integer: Sommersemester #{tshow year}
WinterTerm year@Integer: Wintersemester #{tshow year}/#{tshow $ succ year} WinterTerm year@Integer: Wintersemester #{tshow year}/#{tshow $ succ year}
PSLimitNonPositive: “pagesize” muss größer als null sein PSLimitNonPositive: “pagesize” muss größer als null sein
Page n@Int64: #{tshow n} Page n@Int64: #{tshow n}
TermEdited tid@TermIdentifier: Semester #{termToText tid} erfolgreich editiert.
TermNewTitle: Semester editiere/anlegen. TermsHeading: Semesterübersicht
TermCurrent: Aktuelles Semester
TermEditHeading: Semester editieren/anlegen
TermEditTid tk@TermId: Semester #{display tk} editieren
TermEdited tid@TermIdentifier: Semester #{display tid} erfolgreich editiert.
TermNewTitle: Semester editieren/anlegen.
InvalidInput: Eingaben bitte korrigieren. InvalidInput: Eingaben bitte korrigieren.
Term: Semester Term: Semester
TermPlaceholder: W/S + vierstellige Jahreszahl TermPlaceholder: W/S + vierstellige Jahreszahl
TermEditHeading: Semester editieren/anlegen
LectureStart: Beginn Vorlesungen LectureStart: Beginn Vorlesungen
@ -26,20 +30,25 @@ CourseNewOk tid@TermIdentifier courseShortHand@Text: Kurs #{termToText ti
CourseEditOk tid@TermIdentifier courseShortHand@Text: Kurs #{termToText tid}-#{courseShortHand} wurde erfolgreich geändert. CourseEditOk tid@TermIdentifier courseShortHand@Text: Kurs #{termToText tid}-#{courseShortHand} wurde erfolgreich geändert.
CourseNewDupShort tid@TermIdentifier courseShortHand@Text: Kurs #{termToText tid}-#{courseShortHand} konnte nicht erstellt werden: Es gibt bereits einen anderen Kurs mit dem Kürzel #{courseShortHand} in diesem Semester. CourseNewDupShort tid@TermIdentifier courseShortHand@Text: Kurs #{termToText tid}-#{courseShortHand} konnte nicht erstellt werden: Es gibt bereits einen anderen Kurs mit dem Kürzel #{courseShortHand} in diesem Semester.
CourseEditDupShort tid@TermIdentifier courseShortHand@Text: Kurs #{termToText tid}-#{courseShortHand} konnte nicht geändert werden: Es gibt bereits einen anderen Kurs mit dem Kürzel #{courseShortHand} in diesem Semester. CourseEditDupShort tid@TermIdentifier courseShortHand@Text: Kurs #{termToText tid}-#{courseShortHand} konnte nicht geändert werden: Es gibt bereits einen anderen Kurs mit dem Kürzel #{courseShortHand} in diesem Semester.
TermCourseListHeading tid@TermIdentifier: Kursübersicht #{termToText tid} FFSheetName: Name
TermCourseListTitle tid@TermIdentifier: Kurse #{termToText tid} TermCourseListHeading tk@TermId: Kursübersicht #{display tk}
CourseEditHeading: Kurs editieren/anlegen TermCourseListTitle tk@TermId: Kurse #{display tk}
CourseNewHeading: Neuen Kurs anlegen
CourseEditHeading tk@TermId courseShortHand@Text: Kurs #{display tk}-#{courseShortHand} editieren
CourseEditTitle: Kurs editieren/anlegen CourseEditTitle: Kurs editieren/anlegen
Sheet: Blatt Sheet: Blatt
SheetNewOk tid@TermIdentifier courseShortHand@Text sheetName@Text: Neues Übungsblatt #{sheetName} wurde im Kurs #{termToText tid}-#{courseShortHand} erfolgreich erstellt. SheetList tk@TermId courseShortHand@Text: #{display tk}-#{courseShortHand} Übersicht Übungsblätter
SheetTitle tid@TermIdentifier courseShortHand@Text sheetName@Text: #{termToText tid}-#{courseShortHand} #{sheetName} SheetNewHeading tk@TermId courseShortHand@Text: #{display tk}-#{courseShortHand} Neues Übungsblatt anlegen
SheetTitleNew tid@TermIdentifier courseShortHand@Text : #{termToText tid}-#{courseShortHand}: Neues Übungsblatt SheetNewOk tk@TermId courseShortHand@Text sheetName@Text: Neues Übungsblatt #{sheetName} wurde im Kurs #{display tk}-#{courseShortHand} erfolgreich erstellt.
SheetEditOk tid@TermIdentifier courseShortHand@Text sheetName@Text: Übungsblatt #{sheetName} aus Kurs #{termToText tid}-#{courseShortHand} wurde gespeichert. SheetTitle tk@TermId courseShortHand@Text sheetName@Text: #{display tk}-#{courseShortHand} #{sheetName}
SheetNameDup tid@TermIdentifier courseShortHand@Text sheetName@Text: Es gibt bereits ein Übungsblatt #{sheetName} in diesem Kurs #{termToText tid}-#{courseShortHand}. SheetTitleNew tk@TermId courseShortHand@Text : #{display tk}-#{courseShortHand}: Neues Übungsblatt
SheetDelTitle tid@TermIdentifier courseShortHand@Text sheetName@Text: Übungsblatt #{sheetName} wirklich aus Kurs #{termToText tid}-#{courseShortHand} herauslöschen? SheetEditHead tk@TermId courseShortHand@Text sheetName@Text: #{display tk}-#{courseShortHand} #{sheetName} editieren
SheetEditOk tk@TermId courseShortHand@Text sheetName@Text: Übungsblatt #{sheetName} aus Kurs #{display tk}-#{courseShortHand} wurde gespeichert.
SheetNameDup tk@TermId courseShortHand@Text sheetName@Text: Es gibt bereits ein Übungsblatt #{sheetName} in diesem Kurs #{display tk}-#{courseShortHand}.
SheetDelHead tk@TermId courseShortHand@Text sheetName@Text: Übungsblatt #{sheetName} wirklich aus Kurs #{display tk}-#{courseShortHand} herauslöschen?
SheetDelText submissionNo@Int: Dies kann nicht mehr rückgängig gemacht werden! Alle Einreichungen gehen ebenfalls verloren! Es gibt #{show submissionNo} Abgaben. SheetDelText submissionNo@Int: Dies kann nicht mehr rückgängig gemacht werden! Alle Einreichungen gehen ebenfalls verloren! Es gibt #{show submissionNo} Abgaben.
SheetDelOk tid@TermIdentifier courseShortHand@Text sheetName@Text: #{termToText tid}-#{courseShortHand}: Übungsblatt #{sheetName} gelöscht. SheetDelOk tk@TermId courseShortHand@Text sheetName@Text: #{display tk}-#{courseShortHand}: Übungsblatt #{sheetName} gelöscht.
Deadline: Abgabe Deadline: Abgabe
Done: Eingereicht Done: Eingereicht
@ -67,7 +76,7 @@ Submission: Abgabenummer
SubmissionWrongSheet: Abgabenummer gehört nicht zum angegebenen Übungsblatt. SubmissionWrongSheet: Abgabenummer gehört nicht zum angegebenen Übungsblatt.
SubmissionAlreadyExists: Sie haben bereits eine Abgabe zu diesem Übungsblatt. SubmissionAlreadyExists: Sie haben bereits eine Abgabe zu diesem Übungsblatt.
SubmissionTitle tid@TermIdentifier courseShortHand@Text sheetName@Text: #{termToText tid}-#{courseShortHand} #{sheetName}: Abgabe editieren/anlegen SubmissionEditHead tk@TermId courseShortHand@Text sheetName@Text: #{display tk}-#{courseShortHand} #{sheetName}: Abgabe editieren/anlegen
SubmissionMember g@Int: Mitabgebende(r) ##{tshow g} SubmissionMember g@Int: Mitabgebende(r) ##{tshow g}
SubmissionArchive: Zip-Archiv der Abgabedatei(en) SubmissionArchive: Zip-Archiv der Abgabedatei(en)
SubmissionFile: Datei zur Abgabe SubmissionFile: Datei zur Abgabe
@ -78,7 +87,7 @@ CourseCorrectionsTitle: Korrekturen für diesen Kurs
EMail: E-Mail EMail: E-Mail
EMailUnknown email@Text: E-Mail #{email} gehört zu keinem bekannten Benutzer. EMailUnknown email@Text: E-Mail #{email} gehört zu keinem bekannten Benutzer.
NotAParticipant user@Text tid@TermIdentifier csh@Text: #{user} ist nicht im Kurs #{termToText tid}-#{csh} angemeldet. NotAParticipant user@Text tk@TermId csh@Text: #{user} ist nicht im Kurs #{display tk}-#{csh} angemeldet.
AddCorrector: Zusätzlicher Korrektor AddCorrector: Zusätzlicher Korrektor
CorrectorExists user@Text: #{user} ist bereits als Korrektor eingetragen CorrectorExists user@Text: #{user} ist bereits als Korrektor eingetragen
@ -94,10 +103,10 @@ CorrectorsUpdated: Korrektoren erfolgreich aktualisiert
CorrectorsPlaceholder: Korrektoren... CorrectorsPlaceholder: Korrektoren...
CorrectorsDefaulted: Korrektoren-Liste wurde aus bisherigen Übungsblättern diesen Kurses generiert. Es sind keine Daten gespeichert. CorrectorsDefaulted: Korrektoren-Liste wurde aus bisherigen Übungsblättern diesen Kurses generiert. Es sind keine Daten gespeichert.
Users: Benutzer
HomeHeading: Aktuelle Termine HomeHeading: Aktuelle Termine
ProfileHeading: Benutzerprofil und Einstellungen ProfileHeading: Benutzerprofil und Einstellungen
ProfileDataHeading: Gespeicherte Benutzerdaten ProfileDataHeading: Gespeicherte Benutzerdaten
TermsHeading: Semesterübersicht
NumCourses n@Int64: #{tshow n} Kurse NumCourses n@Int64: #{tshow n} Kurse
CloseAlert: Schliessen CloseAlert: Schliessen

View File

@ -578,36 +578,42 @@ instance Yesod UniWorX where
-- Define breadcrumbs. -- Define breadcrumbs.
instance YesodBreadcrumbs UniWorX where instance YesodBreadcrumbs UniWorX where
breadcrumb TermShowR = return ("Semester", Just HomeR) breadcrumb (AuthR _) = return ("Login" , Just HomeR)
breadcrumb TermEditR = return ("Neu", Just TermShowR) breadcrumb HomeR = return ("Uni2work", Nothing)
breadcrumb (TermEditExistR _) = return ("Editieren", Just TermShowR) breadcrumb UsersR = return ("Benutzer", Just HomeR)
breadcrumb AdminTestR = return ("Test" , Just HomeR)
breadcrumb (AdminUserR _) = return ("Users" , Just UsersR)
breadcrumb CourseListR = return ("Kurs", Just HomeR) breadcrumb ProfileR = return ("Profile" , Just HomeR)
breadcrumb (TermCourseListR term) = return (toPathPiece term, Just TermShowR) breadcrumb ProfileDataR = return ("Data" , Just ProfileR)
breadcrumb (CourseR term course CShowR) = return (course, Just $ TermCourseListR term)
breadcrumb CourseNewR = return ("Neu", Just CourseListR)
breadcrumb (CourseR tid csh CEditR) = return ("Editieren", Just $ CourseR tid csh CShowR)
breadcrumb (CourseR tid csh CourseCorrectionsR) = return ("Abgaben", Just $ CourseR tid csh CShowR)
breadcrumb TermShowR = return ("Semester" , Just HomeR)
breadcrumb TermCurrentR = return ("Aktuell" , Just TermShowR)
breadcrumb TermEditR = return ("Neu" , Just TermCurrentR)
breadcrumb (TermEditExistR tid) = return ("Editieren" , Just $ TermCourseListR tid)
breadcrumb (TermCourseListR term) = return (display term, Just TermShowR)
breadcrumb CourseListR = return ("Kurs" , Just HomeR)
breadcrumb CourseNewR = return ("Neu" , Just CourseListR)
breadcrumb (CourseR tid csh CShowR) = return (csh , Just $ TermCourseListR tid)
-- (CourseR tid csh CRegisterR) -- is POST only
breadcrumb (CourseR tid csh CEditR) = return ("Editieren", Just $ CourseR tid csh CShowR)
breadcrumb (CourseR tid csh SheetListR) = return ("Übungen",Just $ CourseR tid csh CShowR) breadcrumb (CourseR tid csh SheetListR) = return ("Übungen",Just $ CourseR tid csh CShowR)
breadcrumb (CourseR tid csh SheetNewR ) = return ("Neu", Just $ CourseR tid csh SheetListR) breadcrumb (CourseR tid csh SheetNewR ) = return ("Neu", Just $ CourseR tid csh SheetListR)
breadcrumb (CSheetR tid csh shn SShowR) = return (shn, Just $ CourseR tid csh SheetListR) breadcrumb (CSheetR tid csh shn SShowR) = return (shn, Just $ CourseR tid csh SheetListR)
-- (CSheetR tid csh shn SFileR) -- just for Downloads
breadcrumb (CSheetR tid csh shn SEditR) = return ("Edit", Just $ CSheetR tid csh shn SShowR) breadcrumb (CSheetR tid csh shn SEditR) = return ("Edit", Just $ CSheetR tid csh shn SShowR)
breadcrumb (CSheetR tid csh shn SDelR ) = return ("DELETE", Just $ CSheetR tid csh shn SShowR) breadcrumb (CSheetR tid csh shn SDelR ) = return ("DELETE", Just $ CSheetR tid csh shn SShowR)
breadcrumb (CSheetR tid csh shn SCorrR) = return ("Korrektoren", Just $ CSheetR tid csh shn SShowR) breadcrumb (CSheetR tid csh shn SCorrR) = return ("Korrektoren", Just $ CSheetR tid csh shn SShowR)
breadcrumb (CSheetR tid csh shn SSubsR) = return ("Abgaben", Just $ CSheetR tid csh shn SShowR) breadcrumb (CSheetR tid csh shn SSubsR) = return ("Abgaben", Just $ CSheetR tid csh shn SShowR)
breadcrumb (CSheetR tid csh shn SubmissionNewR) = return ("Abgabe", Just $ CSheetR tid csh shn SShowR)
breadcrumb (CSheetR tid csh shn SubmissionOwnR) = return ("Abgabe", Just $ CSheetR tid csh shn SShowR)
breadcrumb (CSheetR tid csh shn (SubmissionR _)) = return ("Abgabe", Just $ CSheetR tid csh shn SShowR) breadcrumb (CSheetR tid csh shn (SubmissionR _)) = return ("Abgabe", Just $ CSheetR tid csh shn SShowR)
-- Deprecated below
breadcrumb SubmissionListR = return ("Abgaben", Just HomeR) breadcrumb SubmissionListR = return ("Abgaben", Just HomeR)
-- Others
breadcrumb CorrectionsR = return ("Korrekturen", Just HomeR) breadcrumb _ = return ("Uni2work", Nothing) -- Default is no breadcrumb at all
breadcrumb HomeR = return ("UniWorkY", Nothing)
breadcrumb (AuthR _) = return ("Login", Just HomeR)
breadcrumb ProfileR = return ("Profile", Just HomeR)
breadcrumb ProfileDataR = return ("Data", Just ProfileR)
breadcrumb _ = return ("home", Nothing)
pageActions :: Route UniWorX -> [MenuTypes] pageActions :: Route UniWorX -> [MenuTypes]
pageActions (CourseR tid csh CShowR) = pageActions (CourseR tid csh CShowR) =
@ -688,13 +694,19 @@ pageActions TermShowR =
, menuItemAccessCallback' = return True , menuItemAccessCallback' = return True
} }
] ]
pageActions (TermCourseListR _) = pageActions (TermCourseListR tid) =
[ PageActionPrime $ MenuItem [ PageActionPrime $ MenuItem
{ menuItemLabel = "Neuen Kurs anlegen" { menuItemLabel = "Neuen Kurs anlegen"
, menuItemIcon = Just "book" , menuItemIcon = Just "book"
, menuItemRoute = CourseNewR , menuItemRoute = CourseNewR
, menuItemAccessCallback' = return True , menuItemAccessCallback' = return True
} }
, PageActionPrime $ MenuItem
{ menuItemLabel = "Semster editieren"
, menuItemIcon = Nothing
, menuItemRoute = TermEditExistR tid
, menuItemAccessCallback' = return True
}
] ]
pageActions (ProfileR) = pageActions (ProfileR) =
[ PageActionPrime $ MenuItem [ PageActionPrime $ MenuItem
@ -729,26 +741,59 @@ i18nHeading msg = liftWidgetT $ toWidget =<< getMessageRender <*> pure msg
pageHeading :: Route UniWorX -> Maybe Widget pageHeading :: Route UniWorX -> Maybe Widget
pageHeading HomeR pageHeading HomeR
= Just $ i18nHeading MsgHomeHeading = Just $ i18nHeading MsgHomeHeading
pageHeading UsersR
= Just $ i18nHeading MsgUsers
pageHeading (AdminTestR) pageHeading (AdminTestR)
= Just $ [whamlet|Internal Code Demonstration Page|] = Just $ [whamlet|Internal Code Demonstration Page|]
pageHeading (AdminUserR _)
= Just $ [whamlet|User Display for Admin|]
pageHeading ProfileR pageHeading ProfileR
= Just $ i18nHeading MsgProfileHeading = Just $ i18nHeading MsgProfileHeading
pageHeading ProfileDataR pageHeading ProfileDataR
= Just $ i18nHeading MsgProfileDataHeading = Just $ i18nHeading MsgProfileDataHeading
pageHeading TermShowR pageHeading TermShowR
= Just $ i18nHeading MsgTermsHeading = Just $ i18nHeading MsgTermsHeading
pageHeading TermCurrentR
= Just $ i18nHeading MsgTermCurrent
pageHeading TermEditR pageHeading TermEditR
= Just $ i18nHeading MsgTermEditHeading = Just $ i18nHeading MsgTermEditHeading
pageHeading (TermEditExistR tid)
= Just $ i18nHeading $ MsgTermEditTid tid
pageHeading (TermCourseListR tid) pageHeading (TermCourseListR tid)
= Just . i18nHeading . MsgTermCourseListHeading $ unTermKey tid = Just . i18nHeading . MsgTermCourseListHeading $ tid
-- CourseListR -- just a redirect to TermCurrentR
pageHeading CourseNewR pageHeading CourseNewR
= Just $ i18nHeading MsgCourseEditHeading = Just $ i18nHeading MsgCourseNewHeading
pageHeading (CourseR tid csh CShowR) pageHeading (CourseR tid csh CShowR)
= Just $ do = Just $ do
Entity _ Course{..} <- handlerToWidget . runDB . getBy404 $ CourseTermShort tid csh Entity _ Course{..} <- handlerToWidget . runDB . getBy404 $ CourseTermShort tid csh
toWidget courseName toWidget courseName
pageHeading CorrectionsR pageHeading CorrectionsR
= Just $ i18nHeading MsgCorrectionsTitle = Just $ i18nHeading MsgCorrectionsTitle
-- (CourseR tid csh CRegisterR) -- just for POST
pageHeading (CourseR tid csh CEditR)
= Just $ i18nHeading $ MsgCourseEditHeading tid csh
pageHeading (CourseR tid csh SheetListR)
= Just $ i18nHeading $ MsgSheetList tid csh
pageHeading (CourseR tid csh SheetNewR)
= Just $ i18nHeading $ MsgSheetNewHeading tid csh
pageHeading (CSheetR tid csh shn SShowR)
= Just $ i18nHeading $ MsgSheetTitle tid csh shn
-- (CSheetR tid csh shn SFileR) -- just for Downloads
pageHeading (CSheetR tid csh shn SEditR)
= Just $ i18nHeading $ MsgSheetEditHead tid csh shn
pageHeading (CSheetR tid csh shn SDelR)
= Just $ i18nHeading $ MsgSheetDelHead tid csh shn
pageHeading (CSheetR tid csh shn SubmissionNewR)
= Just $ i18nHeading $ MsgSubmissionEditHead tid csh shn
pageHeading (CSheetR tid csh shn SubmissionOwnR)
= Just $ i18nHeading $ MsgSubmissionEditHead tid csh shn
pageHeading (CSheetR tid csh shn (SubmissionR _)) -- TODO: Rethink this one!
= Just $ i18nHeading $ MsgSubmissionEditHead tid csh shn
-- TODO: add headings for more single course- and single term-pages -- TODO: add headings for more single course- and single term-pages
pageHeading _ pageHeading _
= Nothing = Nothing

View File

@ -46,7 +46,7 @@ getAdminTestR :: Handler Html -- Demo Page. Referenzimplementierungen sollte hie
getAdminTestR = do getAdminTestR = do
(btnWdgt, btnEnctype) <- generateFormPost (buttonForm :: Form CreateButton) (btnWdgt, btnEnctype) <- generateFormPost (buttonForm :: Form CreateButton)
defaultLayout $ do defaultLayout $ do
-- setTitle "UniWorkY Admin Testpage" -- setTitle "Uni2work Admin Testpage"
$(widgetFile "adminTest") $(widgetFile "adminTest")
postAdminTestR :: Handler Html postAdminTestR :: Handler Html

View File

@ -25,7 +25,7 @@ import qualified Data.UUID.Cryptographic as UUID
getCourseListR :: Handler TypedContent getCourseListR :: Handler TypedContent
getCourseListR = redirect TermShowR getCourseListR = redirect TermCurrentR
getTermCurrentR :: Handler Html getTermCurrentR :: Handler Html
getTermCurrentR = do getTermCurrentR = do
@ -33,6 +33,9 @@ getTermCurrentR = do
case fromNullable termIds of case fromNullable termIds of
Nothing -> notFound Nothing -> notFound
(Just (maximum -> tid)) -> getTermCourseListR tid (Just (maximum -> tid)) -> getTermCourseListR tid
-- why not "redirect $ TermCourseListR tid"
-- Would save us breadcrumbs, headings, etc.?
getTermCourseListR :: TermId -> Handler Html getTermCourseListR :: TermId -> Handler Html
getTermCourseListR tidini = do getTermCourseListR tidini = do
@ -73,7 +76,7 @@ getTermCourseListR tidini = do
] ]
let coursesTable = encodeWidgetTable tableSortable colonnadeTerms courses let coursesTable = encodeWidgetTable tableSortable colonnadeTerms courses
defaultLayout $ do defaultLayout $ do
setTitleI . MsgTermCourseListTitle $ unTermKey tidini setTitleI . MsgTermCourseListTitle $ tidini
$(widgetFile "courses") $(widgetFile "courses")
getCShowR :: TermId -> Text -> Handler Html getCShowR :: TermId -> Text -> Handler Html

View File

@ -169,6 +169,6 @@ homeUser uid = do
} }
defaultLayout $ do defaultLayout $ do
-- setTitle "Willkommen zum Uniworky Test!" -- setTitle "Willkommen zum Uni2work Test!"
$(widgetFile "homeUser") $(widgetFile "homeUser")
$(widgetFile "dsgvDisclaimer") $(widgetFile "dsgvDisclaimer")

View File

@ -322,7 +322,6 @@ postSEditR = getSEditR
handleSheetEdit :: TermId -> Text -> Maybe SheetId -> Maybe SheetForm -> (Sheet -> YesodDB UniWorX (Maybe SheetId)) -> Handler Html handleSheetEdit :: TermId -> Text -> Maybe SheetId -> Maybe SheetForm -> (Sheet -> YesodDB UniWorX (Maybe SheetId)) -> Handler Html
handleSheetEdit tid csh msId template dbAction = do handleSheetEdit tid csh msId template dbAction = do
let tident = unTermKey tid
let mbshn = sfName <$> template let mbshn = sfName <$> template
aid <- requireAuthId aid <- requireAuthId
((res,formWidget), formEnctype) <- runFormPost $ makeSheetForm msId template ((res,formWidget), formEnctype) <- runFormPost $ makeSheetForm msId template
@ -346,20 +345,20 @@ handleSheetEdit tid csh msId template dbAction = do
} }
mbsid <- dbAction newSheet mbsid <- dbAction newSheet
case mbsid of case mbsid of
Nothing -> False <$ addMessageI "danger" (MsgSheetNameDup tident csh sfName) Nothing -> False <$ addMessageI "danger" (MsgSheetNameDup tid csh sfName)
(Just sid) -> do -- save files in DB: (Just sid) -> do -- save files in DB:
whenIsJust sfSheetF $ insertSheetFile' sid SheetExercise whenIsJust sfSheetF $ insertSheetFile' sid SheetExercise
whenIsJust sfHintF $ insertSheetFile sid SheetHint whenIsJust sfHintF $ insertSheetFile sid SheetHint
whenIsJust sfSolutionF $ insertSheetFile sid SheetSolution whenIsJust sfSolutionF $ insertSheetFile sid SheetSolution
insert_ $ SheetEdit aid actTime sid insert_ $ SheetEdit aid actTime sid
addMessageI "info" $ MsgSheetEditOk tident csh sfName addMessageI "info" $ MsgSheetEditOk tid csh sfName
return True return True
when saveOkay $ redirect $ CSheetR tid csh sfName SShowR -- redirect must happen outside of runDB when saveOkay $ redirect $ CSheetR tid csh sfName SShowR -- redirect must happen outside of runDB
(FormFailure msgs) -> forM_ msgs $ (addMessage "warning") . toHtml (FormFailure msgs) -> forM_ msgs $ (addMessage "warning") . toHtml
_ -> return () _ -> return ()
let pageTitle = maybe (MsgSheetTitleNew tident csh) let pageTitle = maybe (MsgSheetTitleNew tid csh)
(MsgSheetTitle tident csh) mbshn (MsgSheetTitle tid csh) mbshn
let formTitle = pageTitle -- let formTitle = pageTitle -- no longer used in template
let formText = Nothing :: Maybe UniWorXMessage let formText = Nothing :: Maybe UniWorXMessage
actionUrl <- fromMaybe (CourseR tid csh SheetNewR) <$> getCurrentRoute actionUrl <- fromMaybe (CourseR tid csh SheetNewR) <$> getCurrentRoute
defaultLayout $ do defaultLayout $ do
@ -370,24 +369,23 @@ handleSheetEdit tid csh msId template dbAction = do
getSDelR :: TermId -> Text -> Text -> Handler Html getSDelR :: TermId -> Text -> Text -> Handler Html
getSDelR tid csh shn = do getSDelR tid csh shn = do
let tident = unTermKey tid
((result,formWidget), formEnctype) <- runFormPost (buttonForm :: Form BtnDelete) ((result,formWidget), formEnctype) <- runFormPost (buttonForm :: Form BtnDelete)
case result of case result of
(FormSuccess BtnAbort) -> redirectUltDest $ CSheetR tid csh shn SShowR (FormSuccess BtnAbort) -> redirectUltDest $ CSheetR tid csh shn SShowR
(FormSuccess BtnDelete) -> do (FormSuccess BtnDelete) -> do
runDB $ fetchSheetId tid csh shn >>= deleteCascade runDB $ fetchSheetId tid csh shn >>= deleteCascade
-- TODO: deleteCascade löscht aber nicht die hochgeladenen Dateien!!! -- TODO: deleteCascade löscht aber nicht die hochgeladenen Dateien!!!
addMessageI "info" $ MsgSheetDelOk tident csh shn addMessageI "info" $ MsgSheetDelOk tid csh shn
redirect $ CourseR tid csh SheetListR redirect $ CourseR tid csh SheetListR
_other -> do _other -> do
submissionno <- runDB $ do submissionno <- runDB $ do
sid <- fetchSheetId tid csh shn sid <- fetchSheetId tid csh shn
count [SubmissionSheet ==. sid] count [SubmissionSheet ==. sid]
let formTitle = MsgSheetDelTitle tident csh shn let formTitle = MsgSheetDelHead tid csh shn
let formText = Just $ MsgSheetDelText submissionno let formText = Just $ MsgSheetDelText submissionno
let actionUrl = CSheetR tid csh shn SDelR let actionUrl = CSheetR tid csh shn SDelR
defaultLayout $ do defaultLayout $ do
setTitleI $ MsgSheetTitle tident csh shn setTitleI $ MsgSheetTitle tid csh shn
$(widgetFile "formPageI18n") $(widgetFile "formPageI18n")
postSDelR :: TermId -> Text -> Text -> Handler Html postSDelR :: TermId -> Text -> Text -> Handler Html

View File

@ -187,7 +187,7 @@ submissionHelper tid csh shn (SubmissionMode mcid) = do
let failmsgs = flip Map.foldMapWithKey participants $ \email -> \case let failmsgs = flip Map.foldMapWithKey participants $ \email -> \case
Nothing -> [mr $ MsgEMailUnknown $ CI.original email] Nothing -> [mr $ MsgEMailUnknown $ CI.original email]
(Just (_,False,_)) -> [mr $ MsgNotAParticipant (CI.original email) (unTermKey tid) csh] (Just (_,False,_)) -> [mr $ MsgNotAParticipant (CI.original email) tid csh]
(Just (_,_, True)) -> [mr $ MsgSubmissionAlreadyExistsFor (CI.original email)] (Just (_,_, True)) -> [mr $ MsgSubmissionAlreadyExistsFor (CI.original email)]
_other -> mempty _other -> mempty
return $ if null failmsgs return $ if null failmsgs
@ -232,7 +232,7 @@ submissionHelper tid csh shn (SubmissionMode mcid) = do
mArCid <- fmap ZIPArchiveName <$> traverse encrypt msmid mArCid <- fmap ZIPArchiveName <$> traverse encrypt msmid
let pageTitle = MsgSubmissionTitle (unTermKey tid) csh shn let pageTitle = MsgSubmissionEditHead tid csh shn
let formTitle = pageTitle let formTitle = pageTitle
let formText = Nothing :: Maybe UniWorXMessage let formText = Nothing :: Maybe UniWorXMessage
actionUrl <- Data.Maybe.fromJust <$> getCurrentRoute actionUrl <- Data.Maybe.fromJust <$> getCurrentRoute

View File

@ -487,7 +487,8 @@ setNameClass fs gName gClass = fs { fsName= Just gName, fsAttrs=("class",gClass)
setTooltip :: String -> FieldSettings site -> FieldSettings site setTooltip :: String -> FieldSettings site -> FieldSettings site
setTooltip tt fs setTooltip tt fs
| null tt = fs { fsTooltip = Nothing } | null tt = fs { fsTooltip = Nothing }
| otherwise = fs { fsTooltip = Just $ fromString tt, fsAttrs=("info",fromString tt):(fsAttrs fs) } | otherwise = fs { fsTooltip = Just $ fromString tt
, fsAttrs=("data-tooltip",fromString tt):(fsAttrs fs) }
optionsPersistCryptoId :: forall site backend a msg. optionsPersistCryptoId :: forall site backend a msg.
( YesodPersist site ( YesodPersist site

View File

@ -5,7 +5,7 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric, DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric, DeriveDataTypeable #-}
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
{-- # LANGUAGE ExistentialQuantification #-} -- for DA type
module Model.Types where module Model.Types where
@ -92,6 +92,14 @@ instance DisplayAble SheetFileType where -- deprecated, see RenderMessage instan
display SheetSolution = "Musterlösung" display SheetSolution = "Musterlösung"
display SheetMarking = "Korrekturhinweise" display SheetMarking = "Korrekturhinweise"
{-
data DA = forall a . (DisplayAble a) => DA a
instance DisplayAble DA where
display (DA x) = display x
-}
data ExamStatus = Attended | NoShow | Voided data ExamStatus = Attended | NoShow | Voided
deriving (Show, Read, Eq, Ord, Enum, Bounded) deriving (Show, Read, Eq, Ord, Enum, Bounded)
derivePersistField "ExamStatus" derivePersistField "ExamStatus"
@ -244,6 +252,11 @@ instance Read Theme where -- generic Read-Instance for Show/Bounded
| (Just t) <- (Map.lookup s readTheme) = [(t,"")] | (Just t) <- (Map.lookup s readTheme) = [(t,"")]
| otherwise = [(Default,"")] -- read shall always succeed | otherwise = [(Default,"")] -- read shall always succeed
{-
instance Default Theme where
def = Default
-}
derivePersistField "Theme" derivePersistField "Theme"

View File

@ -1,7 +1,23 @@
<div .container> <div .alerts>
<h1>Uniworky - Admin Demopage <div .alert>
<div .alert__content>
Uni2work ist noch nicht abgeschlossen.
<div .alert .alert-success>
<div .alert__content>
Die Korrektoren wurden aktualisiert! (.alert-success)
<p> <div .alert .alert-warning>
<div .alert__content>
... willst dus nochmal probieren? (.alert-warning)
<div .alert .alert-danger>
<div .alert__content>
Nicht so gut! Egal was das war. Es hat mir nicht gefallen! (.alert-error)
<div .container>
<h1>Uni2work - Admin Demopage
<p data-tooltip="Solch ein Tooltip kann mit dem <em>data-tooltip</em> Attribut erzeugt werden. Funktioniert aber nur in Block-Elementen die einen sinnvollen Wrapper haben.">
Diese interne Seite dient lediglich zum Testen diverser Funktionalitäten Diese interne Seite dient lediglich zum Testen diverser Funktionalitäten
und zur Demonstration der verschiedenen Hilfsfunktionen/Module. und zur Demonstration der verschiedenen Hilfsfunktionen/Module.

View File

@ -1,4 +1,4 @@
<div .container> 0<div .container>
<div .scrolltable> <div .scrolltable>
<table .table.table--striped.table--hover.table--vertical> <table .table.table--striped.table--hover.table--vertical>
$maybe school <- schoolMB $maybe school <- schoolMB

View File

@ -24,11 +24,12 @@
^{pageactionprime} ^{pageactionprime}
<!-- alerts --> <!-- alerts -->
$forall (status, msg) <- mmsgs <div .alerts>
$with status2 <- bool status "info" (status == "") $forall (status, msg) <- mmsgs
<div class="alert alert-#{status2}"> $with status2 <- bool status "info" (status == "")
<div .alert__content> <div class="alert alert-#{status2}">
#{msg} <div .alert__content>
#{msg}
<!-- actual content --> <!-- actual content -->

View File

@ -2,13 +2,13 @@
<h3> <h3>
Re-Implementierung von <a href="https://uniworx.ifi.lmu.de/">UniWorX</a> Re-Implementierung von <a href="https://uniworx.ifi.lmu.de/">UniWorX</a>
<div .alert .alert-danger> <div .alerts>
<div .alert__content> <div .alert .alert-danger>
Vorabversion! <div .alert__content>
Die Implementierung von Vorabversion!
UniWorkY ist noch nicht abgeschlossen. Die Implementierung von
Uni2work ist noch nicht abgeschlossen.
<h1>Kurse mit offener Registrierung <h1>Kurse mit offener Registrierung
<div .container> <div .container>
^{courseTable} ^{courseTable}

View File

@ -2,11 +2,12 @@
<h3> <h3>
Re-Implementierung von <a href="https://uniworx.ifi.lmu.de/">UniWorX</a> Re-Implementierung von <a href="https://uniworx.ifi.lmu.de/">UniWorX</a>
<div .alert .alert-danger> <div .alerts>
<div .alert__content> <div .alert .alert-danger>
Vorabversion! <div .alert__content>
Die Implementierung von Vorabversion!
UniWorkY ist noch nicht abgeschlossen. Die Implementierung von
Uni2work ist noch nicht abgeschlossen.
<h1>Anstehende Übungsblätter <h1>Anstehende Übungsblätter
<div .container> <div .container>
@ -20,4 +21,3 @@
<h1> <h1>
Anstehende Kursanmeldungen Anstehende Kursanmeldungen
TODO TODO

View File

@ -17,4 +17,4 @@ $# new files
<input type=checkbox id=#{fieldId}_zip name=#{fieldName} value=#{unpackZips}> <input type=checkbox id=#{fieldId}_zip name=#{fieldName} value=#{unpackZips}>
<div class="js-tooltip"> <div class="js-tooltip">
<div class="tooltip__handle">? <div class="tooltip__handle">?
<div class="tooltip__content hidden">Entpackt hochgeladene Zip-Dateien (*.zip) automatisch und fügt den Inhalt dem Stamm-Verzeichnis der Abgabe hinzu. <div class="tooltip__content">Entpackt hochgeladene Zip-Dateien (*.zip) automatisch und fügt den Inhalt dem Stamm-Verzeichnis der Abgabe hinzu.

View File

@ -1,9 +1,10 @@
<div .container> <div .container>
<div .alert .alert-danger> <div .alerts>
<div .alert__content> <div .alert .alert-danger>
TODO: Alle Benutzerbezogenen Daten sollen hier angezeigt <div .alert__content>
und verlinkt werden TODO: Alle Benutzerbezogenen Daten sollen hier angezeigt
(alle Abgaben, Klausurnoten, etc.) und verlinkt werden
(alle Abgaben, Klausurnoten, etc.)
<em> TODO: Hier mehr Daten in Tabellen anzeigen! <em> TODO: Hier mehr Daten in Tabellen anzeigen!

View File

@ -10,7 +10,7 @@
closeEl.addEventListener('click', function(event) { closeEl.addEventListener('click', function(event) {
alertEl.classList.add('alert--invisible'); alertEl.classList.add('alert--invisible');
}); });
alertEl.appendChild(closeEl); alertEl.insertBefore(closeEl, alertEl.children[0]);
} }
})(); })();

View File

@ -1,72 +1,211 @@
/* ALERTS */ /* ALERTS */
.alerts {
position: fixed;
bottom: 5%;
right: 0;
z-index: 20;
text-align: right;
display: flex;
flex-direction: column;
}
.alert { .alert {
position: relative; position: relative;
display: flex; display: inline-block;
justify-content: space-between; background-color: var(--color-dark);
background-color: #f5f5f5; border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
font-size: 1rem; font-size: 1rem;
border-color: #dbdbdb; color: #f3f3f3;
border-radius: 4px;
border-style: solid;
border-width: 0 0 0 4px;
color: #4a4a4a;
z-index: 0; z-index: 0;
max-height: 200px; max-height: 200px;
transition: all .2s ease-in-out; transition: all .3s ease-in-out;
transform-origin: top; padding-left: 30px;
margin-left: 20px;
margin-right: 60px;
box-shadow: 0 0 7px var(--color-dark);
+ .alert:not(.alert--invisible) {
margin-top: 20px;
}
&:hover {
.alert__content {
&::after {
opacity: 1;
}
}
}
}
@media (min-width: 425px) {
.alert {
margin-left: 80px;
}
}
@media (min-width: 768px) {
.alert {
margin-left: 40px;
min-width: 400px;
}
}
@media (min-width: 1024px) {
.alert {
min-width: 400px;
}
} }
.alert__content { .alert__content {
padding: 1.25em 1.5em; padding: 1.25em 1.5em;
position: relative;
display: inline-block;
font-weight: 600;
&::before {
content: '';
position: absolute;
top: 0;
right: -60px;
width: 60px;
height: calc(100% - 0px);
background-color: var(--color-dark);
opacity: 0.4;
}
&::after {
content: '\f05a';
position: absolute;
display: flex;
font-family: "Font Awesome 5 Free";
top: 0;
right: -60px;
width: 60px;
height: calc(100% - 0px);
justify-content: center;
align-items: center;
font-size: 40px;
color: var(--color-dark);
}
} }
.alert__close { .alert__close {
cursor: pointer; cursor: pointer;
text-align: right; text-align: right;
display: flex; position: absolute;
align-items: center; left: 0px;
justify-content: center; top: 0;
padding: 0 10px; width: 60px;
background-color: var(--color-light); height: 100%;
color: var(--color-lightwhite); /* TODO: remove next line as soon as messagerenderer-error in julius gets resolved */
transition: all .2s ease; color: var(--color-dark);
transition: all .3s ease;
z-index: 40;
&:hover { &:hover {
background-color: var(--color-primary);
transform: scale(1.05, 1.05); transform: scale(1.05, 1.05);
&::before {
box-shadow: 0 0 4px white;
background-color: rgba(255, 255, 255, 0.1);
color: white;
}
}
&::before {
content: '\f00d';
position: absolute;
font-family: "Font Awesome 5 Free";
top: 50%;
left: 50%;
display: flex;
color: rgba(255, 255, 255, 0.5);
align-items: center;
justify-content: center;
transform: translate(-50%, -50%);
border-radius: 50%;
width: 30px;
height: 30px;
transition: all .15s ease;
} }
} }
.alert-success { .alert-success {
background-color: #f6fef9;
border-color: var(--color-success);
.alert__close { .alert__content {
background-color: var(--color-success);
&::before {
background-color: var(--color-success);
}
&::after {
content: '\f05a';
color: var(--color-success);
}
} }
} }
.alert-warning { .alert-warning {
background-color: #fffdf5; background-color: var(--color-warning);
border-color: var(--color-warning); color: var(--color-dark);
box-shadow: 0 0 7px var(--color-warning);
.alert__close { .alert__close {
background-color: var(--color-warning); color: var(--color-warning);
color: var(--color-dark);
/* TODO: remove me as soon as messagerenderer-error in julius gets resolved */
&::before {
color: var(--color-dark);
}
}
.alert__content {
&::before {
background-color: var(--color-warning);
}
&::after {
content: '\f071';
color: var(--color-warning);
}
} }
} }
.alert-danger, .alert-danger,
.alert-error { .alert-error {
border-color: var(--color-error); background-color: var(--color-error);
background-color: #fff5f7; color: var(--color-lightwhite);
box-shadow: 0 0 7px var(--color-error);
.alert__close { .alert__close {
background-color: var(--color-error); color: var(--color-error);
/* TODO: remove me as soon as messagerenderer-error in julius gets resolved */
&::before {
color: var(--color-lightwhite);
}
}
.alert__content {
&::before {
background-color: var(--color-error);
}
&::after {
content: '\f071';
color: var(--color-error);
}
} }
} }
.alert--invisible { .alert--invisible {
max-height: 0; max-height: 0;
transform: scaleY(0); transform: translateX(120%);
} }

View File

@ -10,6 +10,9 @@
var left = false; var left = false;
// initially set content to hidden
content.classList.add('hidden');
handle.addEventListener('mouseenter', function() { handle.addEventListener('mouseenter', function() {
left = false; left = false;
content.classList.toggle('to-left', handle.getBoundingClientRect().left + 300 > window.innerWidth); content.classList.toggle('to-left', handle.getBoundingClientRect().left + 300 > window.innerWidth);
@ -24,12 +27,39 @@
} }
}, 250); }, 250);
}); });
} };
window.utils.tooltipFromAttribute = function(el) {
var tt = document.createElement('div');
var handle = document.createElement('div');
var content = document.createElement('div');
tt.classList.add('js-tooltip');
handle.classList.add('tooltip__handle');
content.classList.add('tooltip__content', 'hidden');
handle.innerText = '?';
content.innerHTML = el.getAttribute('data-tooltip');
tt.appendChild(handle);
tt.appendChild(content);
if (el.nextSiblingElement) {
el.parentElement.insertBefore(tt, el.nextSiblingElement);
} else {
el.parentElement.appendChild(tt);
}
};
})(); })();
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// initialize tooltips set via `data-tooltip`
Array.from(document.querySelectorAll('[data-tooltip]')).forEach(function(el) {
window.utils.tooltipFromAttribute(el)
});
// initialize tooltips // initialize tooltips
Array.from(document.querySelectorAll('.js-tooltip')).forEach(function(tt) { Array.from(document.querySelectorAll('.js-tooltip')).forEach(function(tt) {
window.utils.tooltip(tt); window.utils.tooltip(tt);

View File

@ -1,5 +1,6 @@
.js-tooltip { .js-tooltip {
position: relative; position: relative;
display: inline-block;
.tooltip__handle { .tooltip__handle {
background-color: var(--color-dark); background-color: var(--color-dark);
@ -26,7 +27,6 @@
border-radius: 4px; border-radius: 4px;
padding: 13px 17px; padding: 13px 17px;
box-shadow: 0 0 20px 4px rgba(0, 0, 0, 0.1); box-shadow: 0 0 20px 4px rgba(0, 0, 0, 0.1);
// display: none;
&.to-left { &.to-left {
left: auto; left: auto;
@ -46,8 +46,6 @@
transform: rotate(45deg); transform: rotate(45deg);
position: absolute; position: absolute;
left: 10px; left: 10px;
// box-shadow: 0 0 4px black;
// outline: 1px solid red;
bottom: -8px; bottom: -8px;
} }
} }
@ -56,3 +54,17 @@
display: none; display: none;
} }
} }
@media (max-width: 768px) {
.js-tooltip {
display: block;
margin-top: 10px;
.tooltip__content {
left: 3px;
right: 3px;
width: auto;
}
}
}

View File

@ -43,6 +43,10 @@
.asidenav__list-item { .asidenav__list-item {
position: relative; position: relative;
color: var(--color-lightwhite); color: var(--color-lightwhite);
min-height: 50px;
display: flex;
justify-content: flex-start;
align-items: center;
&:hover { &:hover {
color: var(--color-link); color: var(--color-link);

View File

@ -49,7 +49,7 @@
} }
&::before { &::before {
content: 'UniWorkY'; content: 'Uni2work';
font-family: var(--font-logo); font-family: var(--font-logo);
font-size: 42px; font-size: 42px;
font-weight: bold; font-weight: bold;