Merge branch 'feat/timezones' into 'staging'
Timezones, date formatting & minor cleanup See merge request !45
This commit is contained in:
commit
0e6a8cc964
@ -40,7 +40,12 @@ ldap:
|
|||||||
password: "_env:LDAPPW:"
|
password: "_env:LDAPPW:"
|
||||||
basename: "_env:LDAPBN:"
|
basename: "_env:LDAPBN:"
|
||||||
|
|
||||||
userDefaultFavourites: 12
|
default-favourites: 12
|
||||||
|
default-theme: Default
|
||||||
|
default-date-time-format:
|
||||||
|
dateTimeFormat: "%a %d %b %Y %R"
|
||||||
|
dateFormat: "%d.%m.%Y"
|
||||||
|
timeFormat: "%R"
|
||||||
|
|
||||||
cryptoid-keyfile: "_env:CRYPTOID_KEYFILE:cryptoid_key.bf"
|
cryptoid-keyfile: "_env:CRYPTOID_KEYFILE:cryptoid_key.bf"
|
||||||
|
|
||||||
|
|||||||
8
db.hs
8
db.hs
@ -47,7 +47,7 @@ main = do
|
|||||||
|
|
||||||
fillDb :: DB ()
|
fillDb :: DB ()
|
||||||
fillDb = do
|
fillDb = do
|
||||||
defaultFavourites <- getsYesod $ appDefaultFavourites . appSettings
|
defaultFavourites <- getsYesod $ appDefaultMaxFavourites . appSettings
|
||||||
now <- liftIO getCurrentTime
|
now <- liftIO getCurrentTime
|
||||||
let
|
let
|
||||||
summer2017 = TermIdentifier 2017 Summer
|
summer2017 = TermIdentifier 2017 Summer
|
||||||
@ -60,7 +60,8 @@ fillDb = do
|
|||||||
, userEmail = "G.Kleen@campus.lmu.de"
|
, userEmail = "G.Kleen@campus.lmu.de"
|
||||||
, userDisplayName = "Gregor Kleen"
|
, userDisplayName = "Gregor Kleen"
|
||||||
, userMaxFavourites = 6
|
, userMaxFavourites = 6
|
||||||
, userTheme = AberdeenReds
|
, userTheme = Default
|
||||||
|
, userDateTimeFormat = def
|
||||||
}
|
}
|
||||||
fhamann <- insert User
|
fhamann <- insert User
|
||||||
{ userPlugin = "LDAP"
|
{ userPlugin = "LDAP"
|
||||||
@ -70,6 +71,7 @@ fillDb = do
|
|||||||
, userDisplayName = "Felix Hamann"
|
, userDisplayName = "Felix Hamann"
|
||||||
, userMaxFavourites = defaultFavourites
|
, userMaxFavourites = defaultFavourites
|
||||||
, userTheme = Default
|
, userTheme = Default
|
||||||
|
, userDateTimeFormat = def
|
||||||
}
|
}
|
||||||
jost <- insert User
|
jost <- insert User
|
||||||
{ userPlugin = "LDAP"
|
{ userPlugin = "LDAP"
|
||||||
@ -79,6 +81,7 @@ fillDb = do
|
|||||||
, userDisplayName = "Steffen Jost"
|
, userDisplayName = "Steffen Jost"
|
||||||
, userMaxFavourites = 14
|
, userMaxFavourites = 14
|
||||||
, userTheme = MossGreen
|
, userTheme = MossGreen
|
||||||
|
, userDateTimeFormat = def
|
||||||
}
|
}
|
||||||
void . insert $ User
|
void . insert $ User
|
||||||
{ userPlugin = "LDAP"
|
{ userPlugin = "LDAP"
|
||||||
@ -88,6 +91,7 @@ fillDb = do
|
|||||||
, userDisplayName = "Max Musterstudent"
|
, userDisplayName = "Max Musterstudent"
|
||||||
, userMaxFavourites = 7
|
, userMaxFavourites = 7
|
||||||
, userTheme = AberdeenReds
|
, userTheme = AberdeenReds
|
||||||
|
, userDateTimeFormat = def
|
||||||
}
|
}
|
||||||
void . insert $ Term
|
void . insert $ Term
|
||||||
{ termName = summer2017
|
{ termName = summer2017
|
||||||
|
|||||||
@ -76,6 +76,7 @@ CorrectionHead tid@TermId courseShortHand@Text sheetName@Text cid@CryptoFileName
|
|||||||
SubmissionMember g@Int: Mitabgebende(r) ##{display g}
|
SubmissionMember g@Int: Mitabgebende(r) ##{display g}
|
||||||
SubmissionArchive: Zip-Archiv der Abgabedatei(en)
|
SubmissionArchive: Zip-Archiv der Abgabedatei(en)
|
||||||
SubmissionFile: Datei zur Abgabe
|
SubmissionFile: Datei zur Abgabe
|
||||||
|
SubmissionFiles: Abgegebene Dateien
|
||||||
SubmissionAlreadyExistsFor user@Text: #{user} hat bereits eine Abgabe zu diesem bÜbungsblatt.
|
SubmissionAlreadyExistsFor user@Text: #{user} hat bereits eine Abgabe zu diesem bÜbungsblatt.
|
||||||
|
|
||||||
CorrectionsTitle: Zugewiesene Korrekturen
|
CorrectionsTitle: Zugewiesene Korrekturen
|
||||||
@ -195,4 +196,12 @@ NoUpcomingSheetDeadlines: Keine anstehenden Übungsblätter
|
|||||||
|
|
||||||
AdminFor: Administrator
|
AdminFor: Administrator
|
||||||
LecturerFor: Dozent
|
LecturerFor: Dozent
|
||||||
UserListTitle: Komprehensive Benutzerliste
|
UserListTitle: Komprehensive Benutzerliste
|
||||||
|
|
||||||
|
DateTimeFormatOption dateTimeExp@String dateExp@String timeExp@String: #{dateTimeExp} / #{dateExp} / #{timeExp}
|
||||||
|
|
||||||
|
InvalidDateTimeFormat: Ungültiges Datums- und Zeitformat, JJJJ-MM-TTTHH:MM[:SS] Format erwartet
|
||||||
|
AmbiguousUTCTime: Der angegebene Zeitpunkt lässt sich nicht eindeutig zu UTC konvertieren
|
||||||
|
|
||||||
|
LastEdits: Letzte Änderungen
|
||||||
|
EditedBy name@Text time@Text: Durch #{name} um #{time}
|
||||||
7
models
7
models
@ -4,8 +4,9 @@ User json
|
|||||||
matrikelnummer Text Maybe
|
matrikelnummer Text Maybe
|
||||||
email Text
|
email Text
|
||||||
displayName Text
|
displayName Text
|
||||||
maxFavourites Int default=12
|
maxFavourites Int
|
||||||
theme Theme default='default'
|
theme Theme
|
||||||
|
dateTimeFormat DateTimeFormat
|
||||||
UniqueAuthentication plugin ident
|
UniqueAuthentication plugin ident
|
||||||
UniqueEmail email
|
UniqueEmail email
|
||||||
deriving Show
|
deriving Show
|
||||||
@ -67,7 +68,7 @@ Course
|
|||||||
registerTo UTCTime Maybe
|
registerTo UTCTime Maybe
|
||||||
deregisterUntil UTCTime Maybe
|
deregisterUntil UTCTime Maybe
|
||||||
registerSecret Text Maybe -- Falls ein Passwort erforderlich ist
|
registerSecret Text Maybe -- Falls ein Passwort erforderlich ist
|
||||||
materialFree Bool default=true
|
materialFree Bool
|
||||||
CourseTermShort term shorthand
|
CourseTermShort term shorthand
|
||||||
CourseEdit
|
CourseEdit
|
||||||
user UserId
|
user UserId
|
||||||
|
|||||||
@ -83,6 +83,9 @@ dependencies:
|
|||||||
- MonadRandom
|
- MonadRandom
|
||||||
- email-validate
|
- email-validate
|
||||||
- scientific
|
- scientific
|
||||||
|
- tz
|
||||||
|
- system-locale
|
||||||
|
- th-lift-instances
|
||||||
|
|
||||||
# The library contains all of our application code. The executable
|
# The library contains all of our application code. The executable
|
||||||
# defined below is just a thin wrapper.
|
# defined below is just a thin wrapper.
|
||||||
|
|||||||
@ -72,8 +72,8 @@ import System.FilePath
|
|||||||
|
|
||||||
import Handler.Utils.Templates
|
import Handler.Utils.Templates
|
||||||
import Handler.Utils.StudyFeatures
|
import Handler.Utils.StudyFeatures
|
||||||
import Handler.Utils.DateTime
|
|
||||||
import Control.Lens
|
import Control.Lens
|
||||||
|
import Utils
|
||||||
import Utils.Lens
|
import Utils.Lens
|
||||||
|
|
||||||
import Data.Aeson
|
import Data.Aeson
|
||||||
@ -88,9 +88,6 @@ import Text.Shakespeare.Text (st)
|
|||||||
instance DisplayAble TermId where
|
instance DisplayAble TermId where
|
||||||
display = termToText . unTermKey
|
display = termToText . unTermKey
|
||||||
|
|
||||||
instance DisplayAble UTCTime where
|
|
||||||
display = pack . formatTimeGerDT2 -- default Time Format to be used: 00.00.00 00:00
|
|
||||||
|
|
||||||
instance (PathPiece b) => DisplayAble (Data.CryptoID.CryptoID a b) where
|
instance (PathPiece b) => DisplayAble (Data.CryptoID.CryptoID a b) where
|
||||||
display = toPathPiece -- requires import of Data.CryptoID here
|
display = toPathPiece -- requires import of Data.CryptoID here
|
||||||
-- -- MOVE ABOVE
|
-- -- MOVE ABOVE
|
||||||
@ -184,6 +181,13 @@ instance RenderMessage UniWorX SheetFileType where
|
|||||||
SheetMarking -> renderMessage' MsgSheetMarking
|
SheetMarking -> renderMessage' MsgSheetMarking
|
||||||
where renderMessage' = renderMessage foundation ls
|
where renderMessage' = renderMessage foundation ls
|
||||||
|
|
||||||
|
getTimeLocale' :: [Lang] -> TimeLocale
|
||||||
|
getTimeLocale' = $(timeLocaleMap [("de", "de_DE.utf8")])
|
||||||
|
|
||||||
|
appTZ :: TZ
|
||||||
|
appTZ = $(includeSystemTZ "Europe/Berlin")
|
||||||
|
|
||||||
|
|
||||||
-- Access Control
|
-- Access Control
|
||||||
data AccessPredicate
|
data AccessPredicate
|
||||||
= APPure (Route UniWorX -> Bool -> Reader MsgRenderer AuthResult)
|
= APPure (Route UniWorX -> Bool -> Reader MsgRenderer AuthResult)
|
||||||
@ -999,9 +1003,12 @@ instance YesodAuth UniWorX where
|
|||||||
userEmail <- maybe (throwError $ ServerError "Could not retrieve user email") return userEmail'
|
userEmail <- maybe (throwError $ ServerError "Could not retrieve user email") return userEmail'
|
||||||
userDisplayName <- maybe (throwError $ ServerError "Could not retrieve user name") return userDisplayName'
|
userDisplayName <- maybe (throwError $ ServerError "Could not retrieve user name") return userDisplayName'
|
||||||
|
|
||||||
|
AppSettings{..} <- getsYesod appSettings
|
||||||
|
|
||||||
let
|
let
|
||||||
userMaxFavourites = 12 -- TODO: appDefaultFavourites appSettings
|
userMaxFavourites = appDefaultMaxFavourites
|
||||||
userTheme = Default -- TODO: appDefaultFavourites appSettings
|
userTheme = appDefaultTheme
|
||||||
|
userDateTimeFormat = appDefaultDateTimeFormat
|
||||||
newUser = User{..}
|
newUser = User{..}
|
||||||
userUpdate = [ UserMatrikelnummer =. userMatrikelnummer
|
userUpdate = [ UserMatrikelnummer =. userMatrikelnummer
|
||||||
, UserDisplayName =. userDisplayName
|
, UserDisplayName =. userDisplayName
|
||||||
|
|||||||
@ -62,8 +62,8 @@ getTermCourseListR tid = do
|
|||||||
[ sortable (Just "shorthand") (textCell MsgCourse) $ anchorCell'
|
[ sortable (Just "shorthand") (textCell MsgCourse) $ anchorCell'
|
||||||
(\(Entity _ Course{..}, _) -> CourseR courseTerm courseShorthand CShowR)
|
(\(Entity _ Course{..}, _) -> CourseR courseTerm courseShorthand CShowR)
|
||||||
(\(Entity _ Course{..}, _) -> toWidget courseShorthand)
|
(\(Entity _ Course{..}, _) -> toWidget courseShorthand)
|
||||||
, sortable (Just "register-from") (textCell MsgRegisterFrom) $ \(Entity _ Course{..}, _) -> textCell $ display courseRegisterFrom
|
, sortable (Just "register-from") (textCell MsgRegisterFrom) $ \(Entity _ Course{..}, _) -> cell $ traverse (formatTime dateTimeFormat) courseRegisterFrom >>= maybe mempty toWidget
|
||||||
, sortable (Just "register-to") (textCell MsgRegisterTo) $ \(Entity _ Course{..}, _) -> textCell $ display courseRegisterTo
|
, sortable (Just "register-to") (textCell MsgRegisterTo) $ \(Entity _ Course{..}, _) -> cell $ traverse (formatTime dateTimeFormat) courseRegisterTo >>= maybe mempty toWidget
|
||||||
, sortable (Just "members") (textCell MsgCourseMembers) $ \(Entity _ Course{..}, E.Value num) -> textCell $ case courseCapacity of
|
, sortable (Just "members") (textCell MsgCourseMembers) $ \(Entity _ Course{..}, E.Value num) -> textCell $ case courseCapacity of
|
||||||
Nothing -> MsgCourseMembersCount num
|
Nothing -> MsgCourseMembersCount num
|
||||||
Just max -> MsgCourseMembersCountLimited num max
|
Just max -> MsgCourseMembersCountLimited num max
|
||||||
@ -110,6 +110,8 @@ getCShowR tid csh = do
|
|||||||
let course = entityVal courseEnt
|
let course = entityVal courseEnt
|
||||||
(regWidget, regEnctype) <- generateFormPost $ identifyForm "registerBtn" $ registerForm registered $ courseRegisterSecret course
|
(regWidget, regEnctype) <- generateFormPost $ identifyForm "registerBtn" $ registerForm registered $ courseRegisterSecret course
|
||||||
registrationOpen <- (==Authorized) <$> isAuthorized (CourseR tid csh CRegisterR) True
|
registrationOpen <- (==Authorized) <$> isAuthorized (CourseR tid csh CRegisterR) True
|
||||||
|
mRegFrom <- traverse (formatTime dateTimeFormat) $ courseRegisterFrom course
|
||||||
|
mRegTo <- traverse (formatTime dateTimeFormat) $ courseRegisterTo course
|
||||||
defaultLayout $ do
|
defaultLayout $ do
|
||||||
setTitle $ [shamlet| #{toPathPiece tid} - #{csh}|]
|
setTitle $ [shamlet| #{toPathPiece tid} - #{csh}|]
|
||||||
$(widgetFile "course")
|
$(widgetFile "course")
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import Handler.Utils
|
|||||||
|
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
import Data.Time
|
import Data.Time hiding (formatTime)
|
||||||
-- import qualified Data.Text as T
|
-- import qualified Data.Text as T
|
||||||
-- import Yesod.Form.Bootstrap3
|
-- import Yesod.Form.Bootstrap3
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ homeAnonymous = do
|
|||||||
, sortable (Just "term") (textCell MsgTerm) $ \DBRow{ dbrOutput=(Entity {entityVal = course}) } ->
|
, sortable (Just "term") (textCell MsgTerm) $ \DBRow{ dbrOutput=(Entity {entityVal = course}) } ->
|
||||||
textCell $ display $ courseTerm course
|
textCell $ display $ courseTerm course
|
||||||
, sortable (Just "deadline") (textCell MsgRegisterTo) $ \DBRow{ dbrOutput=(Entity {entityVal = course}) } ->
|
, sortable (Just "deadline") (textCell MsgRegisterTo) $ \DBRow{ dbrOutput=(Entity {entityVal = course}) } ->
|
||||||
textCell $ display $ courseRegisterTo course
|
cell $ traverse (formatTime dateTimeFormat) (courseRegisterTo course) >>= maybe mempty toWidget
|
||||||
]
|
]
|
||||||
courseTable <- dbTable def $ DBTable
|
courseTable <- dbTable def $ DBTable
|
||||||
{ dbtSQLQuery = tableData
|
{ dbtSQLQuery = tableData
|
||||||
@ -154,7 +154,7 @@ homeUser uid = do
|
|||||||
, sortable (Just "sheet") (textCell MsgSheet) $ \DBRow{ dbrOutput=(E.Value tid, E.Value csh, E.Value shn, _, _) } ->
|
, sortable (Just "sheet") (textCell MsgSheet) $ \DBRow{ dbrOutput=(E.Value tid, E.Value csh, E.Value shn, _, _) } ->
|
||||||
cell [whamlet|<a href=@{CSheetR tid csh shn SShowR}>#{display shn}|]
|
cell [whamlet|<a href=@{CSheetR tid csh shn SShowR}>#{display shn}|]
|
||||||
, sortable (Just "deadline") (textCell MsgDeadline) $ \DBRow{ dbrOutput=(_, _, _, E.Value deadline, _) } ->
|
, sortable (Just "deadline") (textCell MsgDeadline) $ \DBRow{ dbrOutput=(_, _, _, E.Value deadline, _) } ->
|
||||||
textCell $ display deadline
|
cell $ formatTime dateTimeFormat deadline >>= toWidget
|
||||||
, sortable (Just "done") (textCell MsgDone) $ \(DBRow{ dbrOutput=(E.Value tid, E.Value csh, E.Value shn, _, E.Value mbsid) }) ->
|
, sortable (Just "done") (textCell MsgDone) $ \(DBRow{ dbrOutput=(E.Value tid, E.Value csh, E.Value shn, _, E.Value mbsid) }) ->
|
||||||
case mbsid of
|
case mbsid of
|
||||||
Nothing -> mempty
|
Nothing -> mempty
|
||||||
|
|||||||
@ -160,8 +160,8 @@ getSheetListR tid csh = do
|
|||||||
let tid = courseTerm course
|
let tid = courseTerm course
|
||||||
let colBase = mconcat
|
let colBase = mconcat
|
||||||
[ headed "Blatt" $ \(sid,sheet,_) -> simpleLink (toWgt $ sheetName sheet) $ CSheetR tid csh (sheetName sheet) SShowR
|
[ headed "Blatt" $ \(sid,sheet,_) -> simpleLink (toWgt $ sheetName sheet) $ CSheetR tid csh (sheetName sheet) SShowR
|
||||||
, headed "Abgabe ab" $ toWgt . formatTimeGerWD . sheetActiveFrom . snd3
|
, headed "Abgabe ab" $ \(_,Sheet{..},_) -> formatTime dateTimeFormat sheetActiveFrom >>= toWidget
|
||||||
, headed "Abgabe bis" $ toWgt . formatTimeGerWD . sheetActiveTo . snd3
|
, headed "Abgabe bis" $ \(_,Sheet{..},_) -> formatTime dateTimeFormat sheetActiveTo >>= toWidget
|
||||||
, headed "Bewertung" $ toWgt . display . sheetType . snd3
|
, headed "Bewertung" $ toWgt . display . sheetType . snd3
|
||||||
]
|
]
|
||||||
let colAdmin = mconcat -- only show edit button for allowed course assistants
|
let colAdmin = mconcat -- only show edit button for allowed course assistants
|
||||||
@ -222,7 +222,7 @@ getSShowR tid csh shn = do
|
|||||||
SheetExercise -> textCell $ display $ sheetActiveFrom sheet
|
SheetExercise -> textCell $ display $ sheetActiveFrom sheet
|
||||||
SheetHint -> textCell $ display $ sheetHintFrom sheet
|
SheetHint -> textCell $ display $ sheetHintFrom sheet
|
||||||
SheetSolution -> textCell $ display $ sheetSolutionFrom sheet
|
SheetSolution -> textCell $ display $ sheetSolutionFrom sheet
|
||||||
, sortable (Just "time") "Modifikation" $ \(_,E.Value modified,_) -> stringCell $ formatTimeGerWDT (modified :: UTCTime)
|
, sortable (Just "time") "Modifikation" $ \(_,E.Value modified,_) -> cell $ formatTime dateTimeFormat (modified :: UTCTime) >>= toWidget
|
||||||
]
|
]
|
||||||
fileTable <- dbTable def $ DBTable
|
fileTable <- dbTable def $ DBTable
|
||||||
{ dbtSQLQuery = fileData
|
{ dbtSQLQuery = fileData
|
||||||
@ -244,8 +244,9 @@ getSShowR tid csh shn = do
|
|||||||
}
|
}
|
||||||
defaultLayout $ do
|
defaultLayout $ do
|
||||||
setTitle $ toHtml $ T.append "Übung " $ sheetName sheet
|
setTitle $ toHtml $ T.append "Übung " $ sheetName sheet
|
||||||
|
sheetFrom <- formatTime dateTimeFormat $ sheetActiveFrom sheet
|
||||||
|
sheetTo <- formatTime dateTimeFormat $ sheetActiveTo sheet
|
||||||
$(widgetFile "sheetShow")
|
$(widgetFile "sheetShow")
|
||||||
[whamlet| Under Construction !!! |] -- TODO
|
|
||||||
|
|
||||||
getSFileR :: TermId -> Text -> Text -> SheetFileType -> FilePath -> Handler TypedContent
|
getSFileR :: TermId -> Text -> Text -> SheetFileType -> FilePath -> Handler TypedContent
|
||||||
getSFileR tid csh shn typ title = do
|
getSFileR tid csh shn typ title = do
|
||||||
|
|||||||
@ -160,7 +160,7 @@ submissionHelper tid csh shn (SubmissionMode mcid) = do
|
|||||||
E.orderBy [E.desc $ submissionEdit E.^. SubmissionEditTime]
|
E.orderBy [E.desc $ submissionEdit E.^. SubmissionEditTime]
|
||||||
E.limit numberOfSubmissionEditDates
|
E.limit numberOfSubmissionEditDates
|
||||||
return $ (user E.^. UserDisplayName, submissionEdit E.^. SubmissionEditTime)
|
return $ (user E.^. UserDisplayName, submissionEdit E.^. SubmissionEditTime)
|
||||||
let lastEdits = map (bimap E.unValue E.unValue) lastEditValues
|
lastEdits <- forM lastEditValues $ \(E.Value name, E.Value time) -> (name, ) <$> formatTime dateTimeFormat time
|
||||||
return (sheet,buddies,lastEdits)
|
return (sheet,buddies,lastEdits)
|
||||||
let unpackZips = True -- undefined -- TODO
|
let unpackZips = True -- undefined -- TODO
|
||||||
((res,formWidget), formEnctype) <- runFormPost $ makeSubmissionForm msmid unpackZips sheetGrouping $ map E.unValue buddies
|
((res,formWidget), formEnctype) <- runFormPost $ makeSubmissionForm msmid unpackZips sheetGrouping $ map E.unValue buddies
|
||||||
|
|||||||
@ -46,19 +46,25 @@ getTermShowR = do
|
|||||||
anchorCell' (\(Entity tid _, _) -> TermCourseListR tid)
|
anchorCell' (\(Entity tid _, _) -> TermCourseListR tid)
|
||||||
(\(Entity tid _, _) -> [whamlet|#{display tid}|])
|
(\(Entity tid _, _) -> [whamlet|#{display tid}|])
|
||||||
, sortable (Just "lecture-start") (i18nCell MsgLectureStart) $ \(Entity _ Term{..},_) ->
|
, sortable (Just "lecture-start") (i18nCell MsgLectureStart) $ \(Entity _ Term{..},_) ->
|
||||||
stringCell $ formatTimeGerWD termLectureStart
|
cell $ formatTime dateFormat termLectureStart >>= toWidget
|
||||||
, sortable (Just "lecture-end") "Ende Vorlesungen" $ \(Entity _ Term{..},_) ->
|
, sortable (Just "lecture-end") "Ende Vorlesungen" $ \(Entity _ Term{..},_) ->
|
||||||
stringCell $ formatTimeGerWD termLectureEnd
|
cell $ formatTime dateFormat termLectureEnd >>= toWidget
|
||||||
, sortable Nothing "Aktiv" $ \(Entity _ Term{..},_) ->
|
, sortable Nothing "Aktiv" $ \(Entity _ Term{..},_) ->
|
||||||
textCell $ (bool "" tickmark termActive :: Text)
|
textCell $ (bool "" tickmark termActive :: Text)
|
||||||
, sortable Nothing "Kurse" $ \(_, E.Value numCourses) ->
|
, sortable Nothing "Kurse" $ \(_, E.Value numCourses) ->
|
||||||
cell [whamlet|_{MsgNumCourses numCourses}|]
|
cell [whamlet|_{MsgNumCourses numCourses}|]
|
||||||
, sortable (Just "start") "Semesteranfang" $ \(Entity _ Term{..},_) ->
|
, sortable (Just "start") "Semesteranfang" $ \(Entity _ Term{..},_) ->
|
||||||
stringCell $ formatTimeGerWD termStart
|
cell $ formatTime dateFormat termStart >>= toWidget
|
||||||
, sortable (Just "end") "Semesterende" $ \(Entity _ Term{..},_) ->
|
, sortable (Just "end") "Semesterende" $ \(Entity _ Term{..},_) ->
|
||||||
stringCell $ formatTimeGerWD termEnd
|
cell $ formatTime dateFormat termEnd >>= toWidget
|
||||||
, sortable Nothing "Feiertage im Semester" $ \(Entity _ Term{..},_) ->
|
, sortable Nothing "Feiertage im Semester" $ \(Entity _ Term{..},_) ->
|
||||||
stringCell $ (intercalate ", ") $ map formatTimeGerWD termHolidays
|
cell $ do
|
||||||
|
termHolidays' <- mapM (formatTime dateFormat) termHolidays
|
||||||
|
[whamlet|
|
||||||
|
<ul .list--inline .list--comma-separated>
|
||||||
|
$forall holiday <- termHolidays'
|
||||||
|
<li>#{holiday}
|
||||||
|
|]
|
||||||
]
|
]
|
||||||
-- let adminColonnade =
|
-- let adminColonnade =
|
||||||
-- [ sortable Nothing "Edit" $ \(Entity tid Term{..},_) -> cell $ do
|
-- [ sortable Nothing "Edit" $ \(Entity tid Term{..},_) -> cell $ do
|
||||||
|
|||||||
@ -1,60 +1,87 @@
|
|||||||
module Handler.Utils.DateTime where
|
{-# LANGUAGE NoImplicitPrelude
|
||||||
|
, TemplateHaskell
|
||||||
|
, OverloadedStrings
|
||||||
|
, RecordWildCards
|
||||||
|
, TypeFamilies
|
||||||
|
#-}
|
||||||
|
|
||||||
import Data.Time
|
module Handler.Utils.DateTime
|
||||||
|
( utcToLocalTime
|
||||||
|
, localTimeToUTC, TZ.LocalToUTCResult(..)
|
||||||
|
, formatTime'
|
||||||
|
, formatTime
|
||||||
|
, getTimeLocale, getDateTimeFormat
|
||||||
|
, validDateTimeFormats, dateTimeFormatOptions
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Import
|
||||||
|
|
||||||
germanTimeLocale :: TimeLocale
|
import Data.Time.Zones hiding (localTimeToUTCFull)
|
||||||
germanTimeLocale = TimeLocale
|
import qualified Data.Time.Zones as TZ
|
||||||
{ wDays = [("Sonntag" ,"So")
|
|
||||||
,("Montag" ,"Mo")
|
|
||||||
,("Dienstag" ,"Di")
|
|
||||||
,("Mittwoch" ,"Mi")
|
|
||||||
,("Donnerstag" ,"Do")
|
|
||||||
,("Freitag" ,"Fr")
|
|
||||||
,("Samstag" ,"Sa")
|
|
||||||
]
|
|
||||||
, months = [("Januar" ,"Jan")
|
|
||||||
,("Februar" ,"Feb")
|
|
||||||
,("März" ,"Mär")
|
|
||||||
,("April" ,"Apr")
|
|
||||||
,("Mai" ,"Mai")
|
|
||||||
,("Juni" ,"Jun")
|
|
||||||
,("Juli" ,"Jul")
|
|
||||||
,("August" ,"Aug")
|
|
||||||
,("September" ,"Sep")
|
|
||||||
,("Oktober" ,"Okt")
|
|
||||||
,("November" ,"Nov")
|
|
||||||
,("Dezember" ,"Dez")
|
|
||||||
]
|
|
||||||
, amPm = ("am","pm")
|
|
||||||
, dateTimeFmt = "%a %e.%m.%y %k:%M"
|
|
||||||
, dateFmt = "%e.%m.%y"
|
|
||||||
, timeFmt = "%k:%M"
|
|
||||||
, time12Fmt = "%H:%M"
|
|
||||||
, knownTimeZones = [] -- TODO?
|
|
||||||
}
|
|
||||||
|
|
||||||
formatTimeGer :: FormatTime t => String -> t -> String
|
import Data.Time hiding (formatTime, localTimeToUTC, utcToLocalTime)
|
||||||
formatTimeGer = formatTime germanTimeLocale
|
import qualified Data.Time.Format as Time
|
||||||
|
|
||||||
formatTimeGerDTlong :: FormatTime t => t -> String
|
import Data.Set (Set)
|
||||||
formatTimeGerDTlong = formatTimeGer "%A, %e. %B %Y, %k:%M:%S"
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
formatTimeGerWDT :: FormatTime t => t -> String
|
utcToLocalTime :: UTCTime -> LocalTime
|
||||||
formatTimeGerWDT = formatTimeGer $ dateTimeFmt germanTimeLocale
|
utcToLocalTime = TZ.utcToLocalTimeTZ appTZ
|
||||||
|
|
||||||
formatTimeGerDT :: FormatTime t => t -> String -- 0.00.00 0:00
|
localTimeToUTC :: LocalTime -> LocalToUTCResult
|
||||||
formatTimeGerDT = formatTimeGer "%e.%m.%y %k:%M" -- leading spaces at start, otherwise 0 padding
|
localTimeToUTC = TZ.localTimeToUTCFull appTZ
|
||||||
|
|
||||||
-- the following is used by DisplayAble's display:
|
formatTime' :: (FormatTime t, MonadHandler m, HandlerSite m ~ UniWorX, IsString str) => String -> t -> m str
|
||||||
formatTimeGerDT2 :: FormatTime t => t -> String -- Day 00.00.00 00:00
|
formatTime' fmtStr t = fmap fromString $ Time.formatTime <$> getTimeLocale <*> pure fmtStr <*> pure t
|
||||||
formatTimeGerDT2 = formatTimeGer "%a %d.%m.%y %H:%M" -- always padding with 0
|
|
||||||
|
|
||||||
formatTimeGerWD :: FormatTime t => t -> String
|
class FormatTime t => HasLocalTime t where
|
||||||
formatTimeGerWD = formatTimeGer "%a %e.%m.%y"
|
toLocalTime :: t -> LocalTime
|
||||||
|
|
||||||
formatTimeGerD :: FormatTime t => t -> String
|
instance HasLocalTime LocalTime where
|
||||||
formatTimeGerD = formatTimeGer $ dateFmt germanTimeLocale
|
toLocalTime = id
|
||||||
|
|
||||||
formatTimeGerT :: FormatTime t => t -> String
|
instance HasLocalTime Day where
|
||||||
formatTimeGerT = formatTimeGer $ timeFmt germanTimeLocale
|
toLocalTime d = toLocalTime $ UTCTime d 0
|
||||||
|
|
||||||
|
instance HasLocalTime UTCTime where
|
||||||
|
toLocalTime t = utcToLocalTime t
|
||||||
|
|
||||||
|
-- formatTime :: (FormatTime t, MonadHandler m, HandlerSite m ~ UniWorX, IsString str) => (DateTimeFormat -> String) -> t -> m str
|
||||||
|
-- Restricted type for safety
|
||||||
|
formatTime :: (HasLocalTime t, MonadHandler m, HandlerSite m ~ UniWorX) => (DateTimeFormat -> String) -> t -> m Text
|
||||||
|
formatTime proj t = flip formatTime' (toLocalTime t) =<< (proj <$> getDateTimeFormat)
|
||||||
|
|
||||||
|
getTimeLocale :: (MonadHandler m, HandlerSite m ~ UniWorX) => m TimeLocale
|
||||||
|
getTimeLocale = getTimeLocale' <$> languages
|
||||||
|
|
||||||
|
getDateTimeFormat :: (MonadHandler m, HandlerSite m ~ UniWorX) => m DateTimeFormat
|
||||||
|
getDateTimeFormat = do
|
||||||
|
mauth <- liftHandlerT maybeAuth
|
||||||
|
let
|
||||||
|
fmt
|
||||||
|
| Just (Entity _ User{..}) <- mauth
|
||||||
|
= userDateTimeFormat
|
||||||
|
| otherwise
|
||||||
|
= def
|
||||||
|
return fmt
|
||||||
|
|
||||||
|
validDateTimeFormats :: Set DateTimeFormat
|
||||||
|
validDateTimeFormats = Set.fromList $
|
||||||
|
[ DateTimeFormat "%a %d %b %Y %R" "%d.%m.%Y" "%R"
|
||||||
|
, DateTimeFormat "%a %d %b %Y %T" "%d.%m.%Y" "%T"
|
||||||
|
, DateTimeFormat "%a %d %b %Y %R" "%Y-%m-%d" "%R"
|
||||||
|
, DateTimeFormat "%a %d %b %Y %T" "%Y-%m-%d" "%T"
|
||||||
|
]
|
||||||
|
|
||||||
|
dateTimeFormatOptions :: (MonadHandler m, HandlerSite m ~ UniWorX) => m (OptionList DateTimeFormat)
|
||||||
|
dateTimeFormatOptions = do
|
||||||
|
now <- liftIO getCurrentTime
|
||||||
|
|
||||||
|
let
|
||||||
|
toOption fmt@DateTimeFormat{..} = do
|
||||||
|
dateTime <- formatTime' dateTimeFormat now
|
||||||
|
date <- formatTime' dateFormat now
|
||||||
|
time <- formatTime' timeFormat now
|
||||||
|
return $ (MsgDateTimeFormatOption dateTime date time, fmt)
|
||||||
|
|
||||||
|
optionsPairs <=< mapM toOption $ Set.toList validDateTimeFormats
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import Handler.Utils.Form.Types
|
|||||||
import Handler.Utils.Templates
|
import Handler.Utils.Templates
|
||||||
|
|
||||||
import Handler.Utils.DateTime
|
import Handler.Utils.DateTime
|
||||||
|
import qualified Data.Time as Time
|
||||||
|
|
||||||
import Import
|
import Import
|
||||||
import qualified Data.Char as Char
|
import qualified Data.Char as Char
|
||||||
@ -404,11 +405,11 @@ dayTimeField fs mutc = do
|
|||||||
-}
|
-}
|
||||||
|
|
||||||
|
|
||||||
utcTimeField :: (Monad m, RenderMessage (HandlerSite m) FormMessage) => Field m UTCTime
|
utcTimeField :: (Monad m, RenderMessage (HandlerSite m) FormMessage, RenderMessage (HandlerSite m) UniWorXMessage) => Field m UTCTime
|
||||||
-- StackOverflow: dayToUTC <$> (areq (jqueryDayField def {...}) settings Nothing)
|
-- StackOverflow: dayToUTC <$> (areq (jqueryDayField def {...}) settings Nothing)
|
||||||
-- TODO: Verify whether this is UTC or local time from Browser
|
-- Browser returns LocalTime
|
||||||
utcTimeField = Field
|
utcTimeField = Field
|
||||||
{ fieldParse = parseHelper $ readTime
|
{ fieldParse = parseHelperGen $ readTime
|
||||||
, fieldView = \theId name attrs val isReq ->
|
, fieldView = \theId name attrs val isReq ->
|
||||||
[whamlet|
|
[whamlet|
|
||||||
$newline never
|
$newline never
|
||||||
@ -420,15 +421,18 @@ utcTimeField = Field
|
|||||||
fieldTimeFormat :: String
|
fieldTimeFormat :: String
|
||||||
--fieldTimeFormat = "%e.%m.%y %k:%M"
|
--fieldTimeFormat = "%e.%m.%y %k:%M"
|
||||||
fieldTimeFormat = "%Y-%m-%dT%H:%M"
|
fieldTimeFormat = "%Y-%m-%dT%H:%M"
|
||||||
|
|
||||||
readTime :: Text -> Either FormMessage UTCTime
|
-- `defaultTimeLocale` is okay here, since `fieldTimeFormat` does not contain any
|
||||||
|
readTime :: Text -> Either UniWorXMessage UTCTime
|
||||||
readTime t =
|
readTime t =
|
||||||
case parseTimeM True germanTimeLocale fieldTimeFormat (T.unpack t) of
|
case localTimeToUTC <$> parseTimeM True defaultTimeLocale fieldTimeFormat (T.unpack t) of
|
||||||
(Just time) -> Right time
|
(Just (LTUUnique time _)) -> Right time
|
||||||
Nothing -> Left $ MsgInvalidEntry $ "Datum/Zeit Format: tt.mm.yy hh:mm " ++ t
|
(Just (LTUNone time _)) -> Right time -- FIXME: Should this be an error, too?
|
||||||
|
(Just (LTUAmbiguous _ _ _ _)) -> Left MsgAmbiguousUTCTime
|
||||||
|
Nothing -> Left MsgInvalidDateTimeFormat
|
||||||
|
|
||||||
showTime :: UTCTime -> Text
|
showTime :: UTCTime -> Text
|
||||||
showTime = fromString . (formatTime germanTimeLocale fieldTimeFormat)
|
showTime = fromString . (Time.formatTime defaultTimeLocale fieldTimeFormat)
|
||||||
|
|
||||||
|
|
||||||
fsm :: RenderMessage UniWorX msg => msg -> FieldSettings UniWorX -- DEPRECATED
|
fsm :: RenderMessage UniWorX msg => msg -> FieldSettings UniWorX -- DEPRECATED
|
||||||
|
|||||||
@ -3,20 +3,19 @@ module Import.NoFoundation
|
|||||||
( module Import
|
( module Import
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import ClassyPrelude.Yesod as Import
|
import ClassyPrelude.Yesod as Import hiding (formatTime)
|
||||||
import Model as Import
|
import Model as Import
|
||||||
import Settings as Import
|
import Settings as Import
|
||||||
import Settings.StaticFiles as Import
|
import Settings.StaticFiles as Import
|
||||||
import Yesod.Auth as Import
|
import Yesod.Auth as Import
|
||||||
import Yesod.Core.Types as Import (loggerSet)
|
import Yesod.Core.Types as Import (loggerSet)
|
||||||
import Yesod.Default.Config2 as Import
|
import Yesod.Default.Config2 as Import
|
||||||
import Utils as Import
|
import Utils as Import
|
||||||
|
|
||||||
|
|
||||||
import Data.Fixed as Import
|
import Data.Fixed as Import
|
||||||
|
|
||||||
import CryptoID as Import
|
import CryptoID as Import
|
||||||
import Data.UUID as Import (UUID)
|
import Data.UUID as Import (UUID)
|
||||||
|
|
||||||
|
import Text.Lucius as Import
|
||||||
import Text.Lucius as Import
|
|
||||||
|
|||||||
@ -38,6 +38,8 @@ import Data.Aeson.TH (deriveJSON, defaultOptions)
|
|||||||
import GHC.Generics (Generic)
|
import GHC.Generics (Generic)
|
||||||
import Data.Typeable (Typeable)
|
import Data.Typeable (Typeable)
|
||||||
|
|
||||||
|
import Data.Default
|
||||||
|
|
||||||
|
|
||||||
type Points = Centi
|
type Points = Centi
|
||||||
|
|
||||||
@ -294,3 +296,12 @@ instance PathPiece obj => PathPiece (ZIPArchiveName obj) where
|
|||||||
| otherwise = Nothing
|
| otherwise = Nothing
|
||||||
|
|
||||||
toPathPiece (ZIPArchiveName obj) = toPathPiece obj <> ".zip"
|
toPathPiece (ZIPArchiveName obj) = toPathPiece obj <> ".zip"
|
||||||
|
|
||||||
|
data DateTimeFormat = DateTimeFormat
|
||||||
|
{ dateTimeFormat, dateFormat, timeFormat :: String }
|
||||||
|
deriving (Eq, Ord, Read, Show)
|
||||||
|
$(deriveJSON defaultOptions ''DateTimeFormat)
|
||||||
|
derivePersistFieldJSON "DateTimeFormat"
|
||||||
|
|
||||||
|
instance Default DateTimeFormat where
|
||||||
|
def = DateTimeFormat "%a %d %b %Y %R" "%d.%m.%Y" "%R"
|
||||||
|
|||||||
@ -24,6 +24,8 @@ import Yesod.Default.Util (WidgetFileSettings,
|
|||||||
widgetFileNoReload,
|
widgetFileNoReload,
|
||||||
widgetFileReload)
|
widgetFileReload)
|
||||||
|
|
||||||
|
import Model
|
||||||
|
|
||||||
-- | Runtime settings to configure this application. These settings can be
|
-- | Runtime settings to configure this application. These settings can be
|
||||||
-- loaded from various sources: defaults, environment variables, config files,
|
-- loaded from various sources: defaults, environment variables, config files,
|
||||||
-- theoretically even a database.
|
-- theoretically even a database.
|
||||||
@ -59,8 +61,9 @@ data AppSettings = AppSettings
|
|||||||
, appSkipCombining :: Bool
|
, appSkipCombining :: Bool
|
||||||
-- ^ Perform no stylesheet/script combining
|
-- ^ Perform no stylesheet/script combining
|
||||||
|
|
||||||
, appDefaultFavourites :: Int
|
, appDefaultTheme :: Theme
|
||||||
-- ^ Initial Value for remembered Favourites
|
, appDefaultMaxFavourites :: Int
|
||||||
|
, appDefaultDateTimeFormat :: DateTimeFormat
|
||||||
|
|
||||||
-- Example app-specific configuration values.
|
-- Example app-specific configuration values.
|
||||||
, appCopyright :: Text
|
, appCopyright :: Text
|
||||||
@ -75,6 +78,7 @@ data AppSettings = AppSettings
|
|||||||
-- ^ If set authenticate against a local password file
|
-- ^ If set authenticate against a local password file
|
||||||
, appAllowDeprecated :: Bool
|
, appAllowDeprecated :: Bool
|
||||||
-- ^ Indicate if deprecated routes are accessible for everyone
|
-- ^ Indicate if deprecated routes are accessible for everyone
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
instance FromJSON AppSettings where
|
instance FromJSON AppSettings where
|
||||||
@ -101,7 +105,9 @@ instance FromJSON AppSettings where
|
|||||||
appMutableStatic <- o .:? "mutable-static" .!= defaultDev
|
appMutableStatic <- o .:? "mutable-static" .!= defaultDev
|
||||||
appSkipCombining <- o .:? "skip-combining" .!= defaultDev
|
appSkipCombining <- o .:? "skip-combining" .!= defaultDev
|
||||||
|
|
||||||
appDefaultFavourites <- o .: "userDefaultFavourites"
|
appDefaultMaxFavourites <- o .: "default-favourites"
|
||||||
|
appDefaultTheme <- o .: "default-theme"
|
||||||
|
appDefaultDateTimeFormat <- o .: "default-date-time-format"
|
||||||
|
|
||||||
appCopyright <- o .: "copyright"
|
appCopyright <- o .: "copyright"
|
||||||
appAnalytics <- o .:? "analytics"
|
appAnalytics <- o .:? "analytics"
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import qualified Data.Char as Char
|
|||||||
|
|
||||||
import Utils.DB as Utils
|
import Utils.DB as Utils
|
||||||
import Utils.Common as Utils
|
import Utils.Common as Utils
|
||||||
|
import Utils.DateTime as Utils
|
||||||
|
|
||||||
import Text.Blaze (Markup, ToMarkup)
|
import Text.Blaze (Markup, ToMarkup)
|
||||||
|
|
||||||
|
|||||||
57
src/Utils/DateTime.hs
Normal file
57
src/Utils/DateTime.hs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{-# LANGUAGE NoImplicitPrelude
|
||||||
|
, TemplateHaskell
|
||||||
|
, QuasiQuotes
|
||||||
|
, StandaloneDeriving
|
||||||
|
, DeriveLift
|
||||||
|
#-}
|
||||||
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||||
|
|
||||||
|
module Utils.DateTime
|
||||||
|
( timeLocaleMap
|
||||||
|
, TimeLocale(..)
|
||||||
|
, module Data.Time.Zones
|
||||||
|
, module Data.Time.Zones.TH
|
||||||
|
) where
|
||||||
|
|
||||||
|
import ClassyPrelude.Yesod hiding (lift)
|
||||||
|
import System.Locale.Read
|
||||||
|
|
||||||
|
import Data.Time (TimeZone(..), TimeLocale(..))
|
||||||
|
import Data.Time.Zones (TZ)
|
||||||
|
import Data.Time.Zones.TH (includeSystemTZ)
|
||||||
|
|
||||||
|
import Language.Haskell.TH
|
||||||
|
import Language.Haskell.TH.Syntax (Lift(..))
|
||||||
|
import Instances.TH.Lift ()
|
||||||
|
|
||||||
|
deriving instance Lift TimeZone
|
||||||
|
deriving instance Lift TimeLocale
|
||||||
|
|
||||||
|
-- $(timeLocaleMap _) :: [Lang] -> TimeLocale
|
||||||
|
timeLocaleMap :: [(Lang, String)] -- ^ Languages and matching locales, first is taken as default
|
||||||
|
-> ExpQ
|
||||||
|
timeLocaleMap [] = fail "Need at least one (language, locale)-pair"
|
||||||
|
timeLocaleMap extra@((_, defLocale):_) = do
|
||||||
|
localeMap <- newName "localeMap"
|
||||||
|
|
||||||
|
let
|
||||||
|
localeMap' = funD localeMap $ map matchLang extra ++ [reduceLangList, defaultLang]
|
||||||
|
|
||||||
|
defaultLang :: ClauseQ
|
||||||
|
defaultLang =
|
||||||
|
clause [listP []] (normalB $ localeExp defLocale) []
|
||||||
|
|
||||||
|
reduceLangList :: ClauseQ
|
||||||
|
reduceLangList = do
|
||||||
|
ls <- newName "ls"
|
||||||
|
clause [[p|(_ : $(varP ls))|]] (normalB [e|$(varE localeMap) $(varE ls)|]) []
|
||||||
|
|
||||||
|
matchLang :: (Lang, String) -> ClauseQ
|
||||||
|
matchLang (lang, localeStr) = do
|
||||||
|
lang' <- newName "lang"
|
||||||
|
clause [[p|($(varP lang') : _)|]] (guardedB [(,) <$> normalG [e|$(varE lang') == lang|] <*> localeExp localeStr]) []
|
||||||
|
|
||||||
|
localeExp :: String -> ExpQ
|
||||||
|
localeExp = lift <=< runIO . getLocale . Just
|
||||||
|
|
||||||
|
letE [localeMap'] (varE localeMap)
|
||||||
@ -3,10 +3,10 @@
|
|||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
{-# LANGUAGE FunctionalDependencies #-}
|
{-# LANGUAGE FunctionalDependencies #-}
|
||||||
module Utils.Lens where
|
module Utils.Lens ( module Utils.Lens ) where
|
||||||
|
|
||||||
import Import.NoFoundation
|
import Import.NoFoundation
|
||||||
import Control.Lens
|
import Control.Lens as Utils.Lens
|
||||||
|
|
||||||
makeClassy_ ''Entity
|
makeClassy_ ''Entity
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,10 @@ packages:
|
|||||||
git: https://github.com/pngwjpgh/encoding.git
|
git: https://github.com/pngwjpgh/encoding.git
|
||||||
commit: 67bb87ceff53f0178c988dd4e15eeb2daee92b84
|
commit: 67bb87ceff53f0178c988dd4e15eeb2daee92b84
|
||||||
extra-dep: true
|
extra-dep: true
|
||||||
|
- location:
|
||||||
|
git: https://github.com/pngwjpgh/system-locale.git
|
||||||
|
commit: d803ce3607ac6813ac1a065acb423220f57dab3c
|
||||||
|
extra-dep: true
|
||||||
|
|
||||||
extra-deps:
|
extra-deps:
|
||||||
- colonnade-1.2.0
|
- colonnade-1.2.0
|
||||||
|
|||||||
@ -22,13 +22,13 @@
|
|||||||
#{participants}
|
#{participants}
|
||||||
$maybe capacity <- courseCapacity course
|
$maybe capacity <- courseCapacity course
|
||||||
\ von #{capacity}
|
\ von #{capacity}
|
||||||
$maybe regFrom <- courseRegisterFrom course
|
$maybe regFrom <- mRegFrom
|
||||||
<dt .deflist__dt>Anmeldezeitraum
|
<dt .deflist__dt>Anmeldezeitraum
|
||||||
<dd .deflist__dd>
|
<dd .deflist__dd>
|
||||||
<div>
|
<div>
|
||||||
Ab #{formatTimeGerWD regFrom}
|
Ab #{regFrom}
|
||||||
$maybe regTo <- courseRegisterTo course
|
$maybe regTo <- mRegTo
|
||||||
\ bis #{formatTimeGerWD regTo}
|
\ bis #{regTo}
|
||||||
$if registrationOpen
|
$if registrationOpen
|
||||||
<dt .deflist__dt>
|
<dt .deflist__dt>
|
||||||
<dd .deflist__dd>
|
<dd .deflist__dd>
|
||||||
|
|||||||
@ -1,30 +1,23 @@
|
|||||||
<div .masthead>
|
|
||||||
<div .container>
|
|
||||||
<div .row>
|
|
||||||
<h1 .header>
|
|
||||||
#{sheetName sheet}
|
|
||||||
<div .container>
|
<div .container>
|
||||||
<div .bs-docs-section>
|
$maybe descr <- sheetDescription sheet
|
||||||
<div .row>
|
<h2 #description>Hinweise
|
||||||
<div .col-lg-12>
|
<p> #{descr}
|
||||||
<div .page-header>
|
|
||||||
|
|
||||||
$maybe descr <- sheetDescription sheet
|
<h3>Bewertung
|
||||||
<h2 #description>Hinweise
|
<p>
|
||||||
<p> #{descr}
|
#{display $ sheetType sheet}
|
||||||
<h3>Bewertung
|
|
||||||
<p> #{display $ sheetType sheet}
|
|
||||||
$maybe marking <- sheetMarkingText sheet
|
|
||||||
<p> #{marking}
|
|
||||||
<br>
|
|
||||||
Freigeschaltet ab:
|
|
||||||
\ #{formatTimeGerWD $ sheetActiveFrom sheet}
|
|
||||||
\ Abgabe bis:
|
|
||||||
\ #{formatTimeGerWD $ sheetActiveTo sheet}
|
|
||||||
|
|
||||||
<div .row>
|
$maybe marking <- sheetMarkingText sheet
|
||||||
<div .col-lg-12>
|
<p>
|
||||||
<h2>Dateien
|
#{marking}
|
||||||
^{fileTable}
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Freigeschaltet ab
|
||||||
|
#{sheetFrom}
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Abgabe bis
|
||||||
|
#{sheetTo}
|
||||||
|
|
||||||
|
<h2>Dateien
|
||||||
|
^{fileTable}
|
||||||
|
|||||||
@ -2,10 +2,13 @@ $maybe cID <- mcid
|
|||||||
<section style="padding-bottom:1em; margin-bottom:1em; border-bottom:1px solid black;">
|
<section style="padding-bottom:1em; margin-bottom:1em; border-bottom:1px solid black;">
|
||||||
<h2>
|
<h2>
|
||||||
<a href=@{CSubmissionR tid csh shn cID (SubArchiveR (ZIPArchiveName SubmissionCorrected))}>Archiv
|
<a href=@{CSubmissionR tid csh shn cID (SubArchiveR (ZIPArchiveName SubmissionCorrected))}>Archiv
|
||||||
$forall (name,time) <- lastEdits
|
$if not (null lastEdits)
|
||||||
<div>last edited by #{name} at #{formatTimeGerDTlong time}
|
<h3>_{MsgLastEdits}
|
||||||
|
<ul>
|
||||||
|
$forall (name,time) <- lastEdits
|
||||||
|
<li>_{MsgEditedBy name time}
|
||||||
$maybe fileTable <- mFileTable
|
$maybe fileTable <- mFileTable
|
||||||
<h3>Enthaltene Dateien:
|
<h3>_{MsgSubmissionFiles}
|
||||||
^{fileTable}
|
^{fileTable}
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user