Course Form works; display not yet.
This commit is contained in:
parent
d10a629fa2
commit
b980bab1b1
18
models
18
models
@ -29,17 +29,19 @@ DegreeCourse json
|
|||||||
UniqueDegreeCourse degreeId courseId
|
UniqueDegreeCourse degreeId courseId
|
||||||
Course
|
Course
|
||||||
name Text
|
name Text
|
||||||
shorthand Text
|
|
||||||
description Html Maybe
|
description Html Maybe
|
||||||
linkexternal Text Maybe
|
linkExternal Text Maybe
|
||||||
schoolId SchoolId
|
shorthand Text
|
||||||
termId TermId -- TermId ist jetzt Text als Typ
|
termId TermIdentifier
|
||||||
|
schoolId SchoolId
|
||||||
capacity Int Maybe
|
capacity Int Maybe
|
||||||
created UTCTime
|
created UTCTime
|
||||||
changed UTCTime
|
changed UTCTime
|
||||||
registerFrom UTCTime
|
createdBy UserId
|
||||||
registerTo UTCTime
|
changedBy UserId
|
||||||
UniqueTermShorthand shorthand termId
|
registerFrom UTCTime Maybe
|
||||||
|
registerTo UTCTime Maybe
|
||||||
|
CourseTermShort termId shorthand
|
||||||
Lecturer
|
Lecturer
|
||||||
userId UserId
|
userId UserId
|
||||||
courseId CourseId
|
courseId CourseId
|
||||||
@ -113,7 +115,7 @@ TutorialUser
|
|||||||
tutorialId TutorialId
|
tutorialId TutorialId
|
||||||
UniqueTutorialUser userId tutorialId
|
UniqueTutorialUser userId tutorialId
|
||||||
Booking
|
Booking
|
||||||
termId TermId
|
termId TermIdentifier
|
||||||
begin UTCTime
|
begin UTCTime
|
||||||
end UTCTime
|
end UTCTime
|
||||||
weekly Bool
|
weekly Bool
|
||||||
|
|||||||
11
routes
11
routes
@ -8,8 +8,11 @@
|
|||||||
|
|
||||||
/profile ProfileR GET
|
/profile ProfileR GET
|
||||||
|
|
||||||
/term ShowTermsR GET
|
/term TermShowR GET
|
||||||
/term/edit EditTermR GET POST
|
/term/edit TermEditR GET POST
|
||||||
/term/#TermIdentifier/edit EditTermExistR GET
|
/term/#TermIdentifier/edit TermEditExistR GET
|
||||||
|
|
||||||
|
/course CourseShowR GET
|
||||||
|
/course/edit CourseEditR GET POST
|
||||||
|
/course/#TermIdentifier/#Text/edit CourseEditExistR GET
|
||||||
|
|
||||||
/assist/newcourse NewCourseR GET POST
|
|
||||||
|
|||||||
@ -43,7 +43,7 @@ import Handler.Common
|
|||||||
import Handler.Home
|
import Handler.Home
|
||||||
import Handler.Profile
|
import Handler.Profile
|
||||||
import Handler.Term
|
import Handler.Term
|
||||||
import Handler.Assist
|
import Handler.Course
|
||||||
|
|
||||||
-- This line actually creates our YesodDispatch instance. It is the second half
|
-- This line actually creates our YesodDispatch instance. It is the second half
|
||||||
-- of the call to mkYesodData which occurs in Foundation.hs. Please see the
|
-- of the call to mkYesodData which occurs in Foundation.hs. Please see the
|
||||||
|
|||||||
@ -35,7 +35,18 @@ permuteFun perm = lamE pat rhs
|
|||||||
where pat = map varP $ fn:xs
|
where pat = map varP $ fn:xs
|
||||||
rhs = foldl appE (varE fn) $ map varE ps
|
rhs = foldl appE (varE fn) $ map varE ps
|
||||||
-- rhs = appE (varE fn) (varE $ xs!!1)
|
-- rhs = appE (varE fn) (varE $ xs!!1)
|
||||||
ln = length perm
|
ln = length perm
|
||||||
xs = [ mkName $ "x" ++ show j | j <- [1..ln] ]
|
xs = [ mkName $ "x" ++ show j | j <- [1..ln] ]
|
||||||
ps = [ xs !! (j-1) | j <- perm ]
|
ps = [ xs !! (j-1) | j <- perm ]
|
||||||
fn = mkName "fn"
|
fn = mkName "fn"
|
||||||
|
|
||||||
|
altFun :: [Int] -> ExpQ -- generic permutation/repetition of function arguments, i.e. $(permuteFun [2,1]) == flip
|
||||||
|
altFun perm = lamE pat rhs
|
||||||
|
where pat = map varP $ fn:xs
|
||||||
|
rhs = foldl appE (varE fn) $ map varE ps
|
||||||
|
-- rhs = appE (varE fn) (varE $ xs!!1)
|
||||||
|
mx = maximum perm
|
||||||
|
xs = [ mkName $ "x" ++ show j | j <- [1..mx] ]
|
||||||
|
ps = [ xs !! (j-1) | j <- perm ]
|
||||||
|
fn = mkName "fn"
|
||||||
|
|
||||||
|
|||||||
@ -166,11 +166,16 @@ instance Yesod UniWorX where
|
|||||||
isAuthorized (StaticR _) _ = return Authorized
|
isAuthorized (StaticR _) _ = return Authorized
|
||||||
|
|
||||||
isAuthorized ProfileR _ = isAuthenticated
|
isAuthorized ProfileR _ = isAuthenticated
|
||||||
-- TODO: change to Assistants
|
|
||||||
isAuthorized NewCourseR _ = return Authorized
|
-- TODO: all?
|
||||||
isAuthorized EditTermR _ = return Authorized
|
isAuthorized TermShowR _ = return Authorized
|
||||||
isAuthorized (EditTermExistR _) _ = return Authorized
|
isAuthorized CourseShowR _ = return Authorized
|
||||||
isAuthorized ShowTermsR _ = return Authorized
|
-- TODO: change to Assistants
|
||||||
|
isAuthorized TermEditR _ = return Authorized
|
||||||
|
isAuthorized (TermEditExistR _) _ = return Authorized
|
||||||
|
isAuthorized CourseEditR _ = return Authorized
|
||||||
|
isAuthorized (CourseEditExistR _ _) _ = return Authorized
|
||||||
|
|
||||||
|
|
||||||
-- This function creates static content files in the static folder
|
-- This function creates static content files in the static folder
|
||||||
-- and names them based on a hash of their content. This allows
|
-- and names them based on a hash of their content. This allows
|
||||||
|
|||||||
@ -1,99 +0,0 @@
|
|||||||
{-# LANGUAGE NoImplicitPrelude #-}
|
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
|
||||||
{-# LANGUAGE TemplateHaskell #-}
|
|
||||||
{-# LANGUAGE QuasiQuotes #-}
|
|
||||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
|
||||||
module Handler.Assist where
|
|
||||||
|
|
||||||
import Import
|
|
||||||
import Handler.Utils
|
|
||||||
import qualified Data.Text as T
|
|
||||||
-- import Data.Maybe
|
|
||||||
import Yesod.Form.Bootstrap3 (BootstrapFormLayout (..), renderBootstrap3)
|
|
||||||
-- import Text.Julius (RawJS (..))
|
|
||||||
|
|
||||||
-- TODO: Move elsewhere
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- Handler for Assistants
|
|
||||||
|
|
||||||
data NewCourseForm = NewCourseForm
|
|
||||||
{ ncf_user :: UserId
|
|
||||||
, ncf_term :: TermIdentifier
|
|
||||||
, ncf_name :: Text
|
|
||||||
, ncf_short :: Text
|
|
||||||
, ncf_description :: Textarea
|
|
||||||
, ncf_homepage :: Maybe Text
|
|
||||||
, ncf_html :: Html
|
|
||||||
, ncf_capacity :: Maybe Int
|
|
||||||
}
|
|
||||||
|
|
||||||
newCourseForm :: UserId -> Form NewCourseForm
|
|
||||||
newCourseForm uid = renderBootstrap3 BootstrapBasicForm $ NewCourseForm
|
|
||||||
<$> pure uid
|
|
||||||
<*> areq termExistsField (set "Semester") Nothing
|
|
||||||
-- <*> areq textField (set "Semester") Nothing
|
|
||||||
<*> areq textField (set "Name des Kurses") Nothing
|
|
||||||
<*> areq textField (set "Kurs Kürzel (3-4 Zeichen)") Nothing
|
|
||||||
<*> areq textareaField (set "Beschreibung des Kurses") Nothing
|
|
||||||
<*> aopt urlField (set "Externe Kurshomepage") Nothing
|
|
||||||
<*> areq htmlField (set "Beschreibung in HTML") Nothing
|
|
||||||
<*> aopt intField (set "Maximale Teilnehmer") Nothing
|
|
||||||
-- Add attributes like the placeholder and CSS classes.
|
|
||||||
where set txt = FieldSettings
|
|
||||||
{ fsLabel = txt
|
|
||||||
, fsTooltip = Nothing
|
|
||||||
, fsId = Nothing
|
|
||||||
, fsName = Nothing
|
|
||||||
, fsAttrs =
|
|
||||||
[ ("class", "form-control")
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
getShowCourseR :: CourseId -> Handler Html
|
|
||||||
getShowCourseR courseId = do
|
|
||||||
defaultLayout $ do
|
|
||||||
[whamlet|
|
|
||||||
TODO unfinished
|
|
||||||
|]
|
|
||||||
|
|
||||||
getNewCourseR :: Handler Html
|
|
||||||
getNewCourseR = do
|
|
||||||
aid <- requireAuthId
|
|
||||||
(formWidget, formEnctype) <- generateFormPost $ newCourseForm aid
|
|
||||||
defaultLayout $ do
|
|
||||||
setTitle "Neuen Kurs anlegen"
|
|
||||||
[whamlet|
|
|
||||||
User: #{show aid}
|
|
||||||
|]
|
|
||||||
$(widgetFile "newCourse")
|
|
||||||
|
|
||||||
postNewCourseR :: Handler Html
|
|
||||||
postNewCourseR = do
|
|
||||||
aid <- requireAuthId
|
|
||||||
((result, formWidget), formEnctype) <- runFormPost $ newCourseForm aid
|
|
||||||
case result of
|
|
||||||
FormSuccess res -> defaultLayout $ do
|
|
||||||
setMessage "Got something!"
|
|
||||||
$(widgetFile "newCourse")
|
|
||||||
FormMissing -> defaultLayout $ do
|
|
||||||
setMessage "Keine Formulardaten erhalten."
|
|
||||||
$(widgetFile "newCourse")
|
|
||||||
FormFailure errorMsgs -> defaultLayout $ do
|
|
||||||
setMessage [shamlet| <span .error>Fehler:
|
|
||||||
<ul>
|
|
||||||
$forall errmsg <- errorMsgs
|
|
||||||
<li> #{errmsg}
|
|
||||||
|]
|
|
||||||
$(widgetFile "newCourse")
|
|
||||||
|
|
||||||
{-
|
|
||||||
defaultLayout $ do
|
|
||||||
let (commentFormId, commentTextareaId, commentListId) = commentIds
|
|
||||||
aDomId <- newIdent
|
|
||||||
setTitle "Welcome To Yesod!"
|
|
||||||
$(widgetFile "homepage")
|
|
||||||
-}
|
|
||||||
220
src/Handler/Course.hs
Normal file
220
src/Handler/Course.hs
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
{-# LANGUAGE NoImplicitPrelude #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
|
||||||
|
module Handler.Course where
|
||||||
|
|
||||||
|
import Import
|
||||||
|
import Handler.Utils
|
||||||
|
|
||||||
|
import Data.Time
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import Yesod.Form.Bootstrap3
|
||||||
|
|
||||||
|
import Colonnade
|
||||||
|
import Yesod.Colonnade
|
||||||
|
|
||||||
|
|
||||||
|
getCourseShowR :: Handler TypedContent
|
||||||
|
getCourseShowR = do
|
||||||
|
terms <- runDB $ selectList [] [Desc TermStart]
|
||||||
|
selectRep $ do
|
||||||
|
provideRep $ return $ toJSON terms
|
||||||
|
provideRep $ do
|
||||||
|
let colonnadeTerms = mconcat
|
||||||
|
[ headed "Kürzel" $ (\t -> let tn = termName t in do
|
||||||
|
adminLink <- handlerToWidget $ isAuthorized (TermEditExistR tn) False
|
||||||
|
[whamlet|
|
||||||
|
$if adminLink == Authorized
|
||||||
|
<a href=@{TermEditExistR tn}>
|
||||||
|
#{termToText tn}
|
||||||
|
$else
|
||||||
|
#{termToText tn}
|
||||||
|
|] )
|
||||||
|
, headed "Beginn Vorlesungen" $ fromString.formatTimeGerWD.termLectureStart
|
||||||
|
, headed "Ende Vorlesungen" $ fromString.formatTimeGerWD.termLectureEnd
|
||||||
|
, headed "Aktiv" (\t -> if termActive t then tickmark else "")
|
||||||
|
-- , Colonnade.bool (Headed "Aktiv") termActive (const tickmark) (const "")
|
||||||
|
, headed "Semesteranfang" $ fromString.formatTimeGerWD.termStart
|
||||||
|
, headed "Semesterende" $ fromString.formatTimeGerWD.termEnd
|
||||||
|
, headed "Feiertage im Semester" $
|
||||||
|
fromString.(intercalate ", ").(map formatTimeGerWD).termHolidays
|
||||||
|
]
|
||||||
|
defaultLayout $ do
|
||||||
|
setTitle "Freigeschaltete Semester"
|
||||||
|
encodeHeadedWidgetTable tableDefault colonnadeTerms (map entityVal terms)
|
||||||
|
|
||||||
|
|
||||||
|
getCourseEditR :: Handler Html
|
||||||
|
getCourseEditR = do
|
||||||
|
-- TODO: Defaults für Semester hier ermitteln und übergeben
|
||||||
|
courseEditHandler Nothing
|
||||||
|
|
||||||
|
postCourseEditR :: Handler Html
|
||||||
|
postCourseEditR = courseEditHandler Nothing
|
||||||
|
|
||||||
|
getCourseEditExistR :: TermIdentifier -> Text -> Handler Html
|
||||||
|
getCourseEditExistR tid csh = do
|
||||||
|
course <- runDB $ getBy $ CourseTermShort tid csh
|
||||||
|
courseEditHandler course
|
||||||
|
|
||||||
|
|
||||||
|
courseEditHandler :: Maybe (Entity Course) -> Handler Html
|
||||||
|
courseEditHandler course = do
|
||||||
|
aid <- requireAuthId
|
||||||
|
((result, formWidget), formEnctype) <- runFormPost $ newCourseForm $ courseToForm <$> course
|
||||||
|
action <- lookupPostParam "formaction"
|
||||||
|
case (result,action) of
|
||||||
|
(FormSuccess res, fAct)
|
||||||
|
| fAct == formActionDelete
|
||||||
|
, Just cid <- cfCourseId res -> do
|
||||||
|
runDB $ delete cid -- TODO Sicherheitsabfrage einbauen!
|
||||||
|
let cti = termToText $ cfTerm res
|
||||||
|
setMessage $ [shamlet| Kurs #{cti}/#{cfShort res} wurde gelöscht! |]
|
||||||
|
redirect CourseShowR
|
||||||
|
| fAct == formActionSave
|
||||||
|
, Just cid <- cfCourseId res -> do
|
||||||
|
actTime <- liftIO getCurrentTime
|
||||||
|
runDB $ do
|
||||||
|
update cid
|
||||||
|
[ CourseName =. cfName res
|
||||||
|
, CourseDescription =. cfDesc res
|
||||||
|
, CourseLinkExternal =. cfLink res
|
||||||
|
, CourseSchoolId =. cfSchool res
|
||||||
|
, CourseCapacity =. cfCapacity res
|
||||||
|
, CourseRegisterFrom =. cfRegFrom res
|
||||||
|
, CourseRegisterTo =. cfRegTo res
|
||||||
|
, CourseChangedBy =. aid
|
||||||
|
, CourseChanged =. actTime
|
||||||
|
]
|
||||||
|
let cti = termToText $ cfTerm res
|
||||||
|
setMessage $ [shamlet| Kurs #{cti}/#{cfShort res} wurde geändert. |]
|
||||||
|
| fAct == formActionSave
|
||||||
|
, Nothing <- cfCourseId res -> do
|
||||||
|
actTime <- liftIO getCurrentTime
|
||||||
|
insertOkay <- runDB $ insertUnique $ Course
|
||||||
|
{ courseName = cfName res
|
||||||
|
, courseDescription = cfDesc res
|
||||||
|
, courseLinkExternal = cfLink res
|
||||||
|
, courseShorthand = cfShort res
|
||||||
|
, courseTermId = cfTerm res
|
||||||
|
, courseSchoolId = cfSchool res
|
||||||
|
, courseCapacity = cfCapacity res
|
||||||
|
, courseRegisterFrom = cfRegFrom res
|
||||||
|
, courseRegisterTo = cfRegTo res
|
||||||
|
, courseCreated = actTime
|
||||||
|
, courseChanged = actTime
|
||||||
|
, courseCreatedBy = aid
|
||||||
|
, courseChangedBy = aid
|
||||||
|
}
|
||||||
|
case insertOkay of
|
||||||
|
(Just cid) -> do
|
||||||
|
runDB $ insert_ $ Lecturer aid cid
|
||||||
|
let cti = termToText $ cfTerm res
|
||||||
|
setMessage $ [shamlet| Kurs #{cti}/#{cfShort res} wurde angelegt. |]
|
||||||
|
redirect CourseShowR
|
||||||
|
Nothing -> do
|
||||||
|
let cti = termToText $ cfTerm res
|
||||||
|
setMessage $ [shamlet|
|
||||||
|
<div .alert .alert-danger>
|
||||||
|
Es gibt bereits einen Kurs #{cfShort res} in Semester #{cti}.
|
||||||
|
|]
|
||||||
|
(FormFailure _,_) -> setMessage "Bitte Eingabe korrigieren."
|
||||||
|
_other -> return ()
|
||||||
|
let formTitle = "Kurs editieren/anlegen" :: Text
|
||||||
|
let actionUrl = TermEditR
|
||||||
|
let formActions = defaultFormActions
|
||||||
|
defaultLayout $ do
|
||||||
|
setTitle [shamlet| #{formTitle} |]
|
||||||
|
$(widgetFile "generic_form")
|
||||||
|
|
||||||
|
|
||||||
|
data CourseForm = CourseForm
|
||||||
|
{ cfCourseId :: Maybe CourseId
|
||||||
|
, cfName :: Text
|
||||||
|
, cfDesc :: Maybe Html
|
||||||
|
, cfLink :: Maybe Text
|
||||||
|
, cfShort :: Text
|
||||||
|
, cfTerm :: TermIdentifier
|
||||||
|
, cfSchool :: SchoolId
|
||||||
|
, cfCapacity :: Maybe Int
|
||||||
|
, cfRegFrom :: Maybe UTCTime
|
||||||
|
, cfRegTo :: Maybe UTCTime
|
||||||
|
}
|
||||||
|
|
||||||
|
courseToForm :: Entity Course -> CourseForm
|
||||||
|
courseToForm cEntity = CourseForm
|
||||||
|
{ cfCourseId = Just $ entityKey cEntity
|
||||||
|
, cfName = courseName course
|
||||||
|
, cfDesc = courseDescription course
|
||||||
|
, cfLink = courseLinkExternal course
|
||||||
|
, cfShort = courseShorthand course
|
||||||
|
, cfTerm = courseTermId course
|
||||||
|
, cfSchool = courseSchoolId course
|
||||||
|
, cfCapacity = courseCapacity course
|
||||||
|
, cfRegFrom = courseRegisterFrom course
|
||||||
|
, cfRegTo = courseRegisterTo course
|
||||||
|
}
|
||||||
|
where
|
||||||
|
course = entityVal cEntity
|
||||||
|
|
||||||
|
newCourseForm :: Maybe CourseForm -> Form CourseForm
|
||||||
|
newCourseForm template html = do
|
||||||
|
(result, widget) <- flip (renderBootstrap3 bsHorizontalDefault) html $ CourseForm
|
||||||
|
<$> pure Nothing -- $ join (cfCourseId <$> template)
|
||||||
|
<*> areq textField (set "Name") (cfName <$> template)
|
||||||
|
<*> aopt htmlField (set "Beschreibung") (cfDesc <$> template)
|
||||||
|
<*> aopt urlField (set "Homepage") (cfLink <$> template)
|
||||||
|
<*> areq textField (setToolt "Kürzel" "Muss innerhalb des Semesters eindeutig sein") (cfShort <$> template)
|
||||||
|
<*> areq termExistsField (set "Semester") (cfTerm <$> template)
|
||||||
|
<*> areq (selectField schools) (set "Institut") (cfSchool <$> template)
|
||||||
|
<*> aopt (natField "Kapazität") (set "Kapazität") (cfCapacity <$> template)
|
||||||
|
<*> aopt utcTimeField (set "Anmeldung von:") (cfRegFrom <$> template)
|
||||||
|
<*> aopt utcTimeField (set "Anmeldung bis:") (cfRegTo <$> template)
|
||||||
|
return $ case result of
|
||||||
|
FormSuccess courseResult
|
||||||
|
| errorMsgs <- validateCourse courseResult
|
||||||
|
, not $ null errorMsgs ->
|
||||||
|
(FormFailure errorMsgs,
|
||||||
|
[whamlet|
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<h4> Fehler:
|
||||||
|
<ul>
|
||||||
|
$forall errmsg <- errorMsgs
|
||||||
|
<li> #{errmsg}
|
||||||
|
^{widget}
|
||||||
|
|]
|
||||||
|
)
|
||||||
|
_ -> (result, widget)
|
||||||
|
where
|
||||||
|
set :: Text -> FieldSettings site
|
||||||
|
set = bfs
|
||||||
|
|
||||||
|
setAttrs :: Text -> [(Text,Text)] -> FieldSettings site
|
||||||
|
setAttrs t attrs =
|
||||||
|
let ifs = bfs t in ifs { fsAttrs= attrs++(fsAttrs ifs) }
|
||||||
|
|
||||||
|
setToolt :: Text -> String -> FieldSettings site
|
||||||
|
setToolt t tt =
|
||||||
|
let ifs = bfs t in ifs { fsTooltip= Just $ fromString tt }
|
||||||
|
|
||||||
|
-- schools :: GHandler UniWorX UniWorX (OptionList SchoolId)
|
||||||
|
schools = do
|
||||||
|
entities <- runDB $ selectList [] [Asc SchoolShorthand]
|
||||||
|
optionsPairs $ map (\school -> (schoolShorthand $ entityVal school, entityKey school)) entities
|
||||||
|
|
||||||
|
validateCourse :: CourseForm -> [Text]
|
||||||
|
validateCourse (CourseForm{..}) =
|
||||||
|
[ msg | (False, msg) <-
|
||||||
|
[
|
||||||
|
( cfRegFrom <= cfRegTo
|
||||||
|
, "Ende der Anmeldungszeit muss nach dem Anfang liegen"
|
||||||
|
)
|
||||||
|
] ]
|
||||||
|
|
||||||
|
|
||||||
@ -18,18 +18,18 @@ import Colonnade
|
|||||||
import Yesod.Colonnade
|
import Yesod.Colonnade
|
||||||
|
|
||||||
|
|
||||||
getShowTermsR :: Handler TypedContent
|
getTermShowR :: Handler TypedContent
|
||||||
getShowTermsR = do
|
getTermShowR = do
|
||||||
terms <- runDB $ selectList [] [Desc TermStart]
|
terms <- runDB $ selectList [] [Desc TermStart]
|
||||||
selectRep $ do
|
selectRep $ do
|
||||||
provideRep $ return $ toJSON terms
|
provideRep $ return $ toJSON terms
|
||||||
provideRep $ do
|
provideRep $ do
|
||||||
let colonnadeTerms = mconcat
|
let colonnadeTerms = mconcat
|
||||||
[ headed "Kürzel" $ (\t -> let tn = termName t in do
|
[ headed "Kürzel" $ (\t -> let tn = termName t in do
|
||||||
adminLink <- handlerToWidget $ isAuthorized (EditTermExistR tn) False
|
adminLink <- handlerToWidget $ isAuthorized (TermEditExistR tn) False
|
||||||
[whamlet|
|
[whamlet|
|
||||||
$if adminLink == Authorized
|
$if adminLink == Authorized
|
||||||
<a href=@{EditTermExistR tn}>
|
<a href=@{TermEditExistR tn}>
|
||||||
#{termToText tn}
|
#{termToText tn}
|
||||||
$else
|
$else
|
||||||
#{termToText tn}
|
#{termToText tn}
|
||||||
@ -48,16 +48,16 @@ getShowTermsR = do
|
|||||||
encodeHeadedWidgetTable tableDefault colonnadeTerms (map entityVal terms)
|
encodeHeadedWidgetTable tableDefault colonnadeTerms (map entityVal terms)
|
||||||
|
|
||||||
|
|
||||||
getEditTermR :: Handler Html
|
getTermEditR :: Handler Html
|
||||||
getEditTermR = do
|
getTermEditR = do
|
||||||
-- TODO: Defaults für Semester hier ermitteln und übergeben
|
-- TODO: Defaults für Semester hier ermitteln und übergeben
|
||||||
termEditHandler Nothing
|
termEditHandler Nothing
|
||||||
|
|
||||||
postEditTermR :: Handler Html
|
postTermEditR :: Handler Html
|
||||||
postEditTermR = termEditHandler Nothing
|
postTermEditR = termEditHandler Nothing
|
||||||
|
|
||||||
getEditTermExistR :: TermIdentifier -> Handler Html
|
getTermEditExistR :: TermIdentifier -> Handler Html
|
||||||
getEditTermExistR tid = do
|
getTermEditExistR tid = do
|
||||||
term <- runDB $ get $ TermKey tid
|
term <- runDB $ get $ TermKey tid
|
||||||
termEditHandler term
|
termEditHandler term
|
||||||
|
|
||||||
@ -73,19 +73,19 @@ termEditHandler term = do
|
|||||||
let tid = termToText $ termName res
|
let tid = termToText $ termName res
|
||||||
let msg = "Semester " `T.append` tid `T.append` " erfolgreich gelöscht."
|
let msg = "Semester " `T.append` tid `T.append` " erfolgreich gelöscht."
|
||||||
setMessage $ [shamlet| #{msg} |]
|
setMessage $ [shamlet| #{msg} |]
|
||||||
redirect ShowTermsR
|
redirect TermShowR
|
||||||
| fAct == formActionSave -> do
|
| fAct == formActionSave -> do
|
||||||
-- term <- runDB $ get $ TermKey termName
|
-- term <- runDB $ get $ TermKey termName
|
||||||
runDB $ repsert (TermKey $ termName res) res
|
runDB $ repsert (TermKey $ termName res) res
|
||||||
let tid = termToText $ termName res
|
let tid = termToText $ termName res
|
||||||
let msg = "Semester " `T.append` tid `T.append` " erfolgreich editiert."
|
let msg = "Semester " `T.append` tid `T.append` " erfolgreich editiert."
|
||||||
setMessage [shamlet| #{msg} |]
|
setMessage [shamlet| #{msg} |]
|
||||||
redirect ShowTermsR
|
redirect TermShowR
|
||||||
| otherwise -> redirect ShowTermsR
|
| otherwise -> redirect TermShowR
|
||||||
(FormMissing,_) -> return ()
|
(FormMissing,_) -> return ()
|
||||||
(FormFailure _,_) -> setMessage "Bitte Eingabe korrigieren."
|
(FormFailure _,_) -> setMessage "Bitte Eingabe korrigieren."
|
||||||
let formTitle = "Semester editieren/anlegen" :: Text
|
let formTitle = "Semester editieren/anlegen" :: Text
|
||||||
let actionUrl = EditTermR
|
let actionUrl = TermEditR
|
||||||
let formActions = defaultFormActions
|
let formActions = defaultFormActions
|
||||||
defaultLayout $ do
|
defaultLayout $ do
|
||||||
setTitle [shamlet| #{formTitle} |]
|
setTitle [shamlet| #{formTitle} |]
|
||||||
@ -95,7 +95,7 @@ termEditHandler term = do
|
|||||||
wdgtTermForm :: (ToWidget UniWorX a) => a -> Enctype -> Handler Html
|
wdgtTermForm :: (ToWidget UniWorX a) => a -> Enctype -> Handler Html
|
||||||
wdgtTermForm formWidget formEnctype = do
|
wdgtTermForm formWidget formEnctype = do
|
||||||
let formTitle = "Semester editieren/anlegen" :: Text
|
let formTitle = "Semester editieren/anlegen" :: Text
|
||||||
let actionUrl = EditTermR
|
let actionUrl = TermEditR
|
||||||
let formActions = defaultFormActions
|
let formActions = defaultFormActions
|
||||||
defaultLayout $ do
|
defaultLayout $ do
|
||||||
setTitle [shamlet| #{formTitle} |]
|
setTitle [shamlet| #{formTitle} |]
|
||||||
@ -107,11 +107,11 @@ newTermForm template html = do
|
|||||||
(result, widget) <- flip (renderBootstrap3 bsHorizontalDefault) html $ Term
|
(result, widget) <- flip (renderBootstrap3 bsHorizontalDefault) html $ Term
|
||||||
<$> areq termNewField (bfs ("Semester" :: Text)) (termName <$> template)
|
<$> areq termNewField (bfs ("Semester" :: Text)) (termName <$> template)
|
||||||
<*> areq dayField (bfs ("Erster Tag" :: Text)) (termStart <$> template)
|
<*> areq dayField (bfs ("Erster Tag" :: Text)) (termStart <$> template)
|
||||||
<*> areq dayField (set "Letzer Tag") (termEnd <$> template)
|
<*> areq dayField (bfs ("Letzer Tag" :: Text)) (termEnd <$> template)
|
||||||
<*> pure [] -- TODO: List of Day field required, must probably be done as its own form and then combined
|
<*> pure [] -- TODO: List of Day field required, must probably be done as its own form and then combined
|
||||||
<*> areq dayField (bfs ("Beginn Vorlesungen" :: Text)) (termLectureStart <$> template)
|
<*> areq dayField (bfs ("Beginn Vorlesungen" :: Text)) (termLectureStart <$> template)
|
||||||
<*> areq dayField (set "Ende Vorlesungen") (termLectureEnd <$> template)
|
<*> areq dayField (bfs ("Ende Vorlesungen" :: Text)) (termLectureEnd <$> template)
|
||||||
<*> areq checkBoxField (set "Aktiv") (termActive <$> template)
|
<*> areq checkBoxField (bfs ("Aktiv" :: Text)) (termActive <$> template)
|
||||||
-- <* bootstrapSubmit (bsSubmit "Semester bearbeiten")
|
-- <* bootstrapSubmit (bsSubmit "Semester bearbeiten")
|
||||||
return $ case result of
|
return $ case result of
|
||||||
FormSuccess termResult
|
FormSuccess termResult
|
||||||
@ -128,12 +128,8 @@ newTermForm template html = do
|
|||||||
|]
|
|]
|
||||||
)
|
)
|
||||||
_ -> (result, widget)
|
_ -> (result, widget)
|
||||||
where set txt = FieldSettings
|
{-
|
||||||
{ fsLabel = txt
|
where
|
||||||
, fsTooltip = Nothing
|
set :: Text -> FieldSettings site
|
||||||
, fsId = Nothing
|
set = bfs
|
||||||
, fsName = Nothing
|
-}
|
||||||
, fsAttrs =
|
|
||||||
[ ("class", "form-control")
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ module Handler.Utils.DateTime where
|
|||||||
|
|
||||||
import Data.Time
|
import Data.Time
|
||||||
|
|
||||||
|
|
||||||
germanTimeLocale :: TimeLocale
|
germanTimeLocale :: TimeLocale
|
||||||
germanTimeLocale = TimeLocale
|
germanTimeLocale = TimeLocale
|
||||||
{ wDays = [("Montag" ,"Mo")
|
{ wDays = [("Montag" ,"Mo")
|
||||||
|
|||||||
@ -1,16 +1,24 @@
|
|||||||
{-# LANGUAGE NoImplicitPrelude #-}
|
{-# LANGUAGE NoImplicitPrelude #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
|
||||||
module Handler.Utils.Form where
|
module Handler.Utils.Form where
|
||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
-- import Data.Time
|
||||||
|
import Handler.Utils.DateTime
|
||||||
import Data.String (IsString(..))
|
import Data.String (IsString(..))
|
||||||
|
|
||||||
-- import Yesod.Core
|
-- import Yesod.Core
|
||||||
-- import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
-- import Yesod.Form.Types
|
-- import Yesod.Form.Types
|
||||||
-- import Yesod.Form.Functions
|
import Yesod.Form.Functions (parseHelper)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
formBtnSave :: (Text,Text,Text)
|
formBtnSave :: (Text,Text,Text)
|
||||||
formBtnSave = ("save" ,"Speichern" ,"btn-primary")
|
formBtnSave = ("save" ,"Speichern" ,"btn-primary")
|
||||||
@ -35,3 +43,44 @@ defaultFormActions = [ formBtnDelete
|
|||||||
, formBtnAbort
|
, formBtnAbort
|
||||||
, formBtnSave
|
, formBtnSave
|
||||||
]
|
]
|
||||||
|
|
||||||
|
------------
|
||||||
|
-- Fields --
|
||||||
|
------------
|
||||||
|
|
||||||
|
natField :: (Monad m, Integral i, RenderMessage (HandlerSite m) FormMessage) => Text -> Field m i
|
||||||
|
natField d = checkBool (>= 0) (T.append d " muss eine natürliche Zahl sein.") $ intField
|
||||||
|
|
||||||
|
posIntField :: (Monad m, Integral i, RenderMessage (HandlerSite m) FormMessage) => Text -> Field m i
|
||||||
|
posIntField d = checkBool (>= 1) (T.append d " muss eine positive Zahl sein.") $ intField
|
||||||
|
|
||||||
|
minIntField :: (Monad m, Integral i, Show i, RenderMessage (HandlerSite m) FormMessage) => i -> Text -> Field m i
|
||||||
|
minIntField m d = checkBool (>= m) (T.concat [d," muss größer als ", T.pack $ show m, " sein."]) $ intField
|
||||||
|
|
||||||
|
|
||||||
|
schoolField :: (Monad m, RenderMessage (HandlerSite m) FormMessage) => Field m SchoolId
|
||||||
|
schoolField = undefined -- TODO
|
||||||
|
|
||||||
|
utcTimeField :: (Monad m, RenderMessage (HandlerSite m) FormMessage) => Field m UTCTime
|
||||||
|
-- StackOverflow: dayToUTC <$> (areq (jqueryDayField def {...}) settings Nothing)
|
||||||
|
utcTimeField = Field
|
||||||
|
{ fieldParse = parseHelper $ readTime
|
||||||
|
, fieldView = \theId name attrs val isReq ->
|
||||||
|
[whamlet|
|
||||||
|
$newline never
|
||||||
|
<input id="#{theId}" name="#{name}" *{attrs} type="text" :isReq:required value="#{either id showTime val}">
|
||||||
|
|]
|
||||||
|
, fieldEnctype = UrlEncoded
|
||||||
|
}
|
||||||
|
where
|
||||||
|
fieldTimeFormat :: String
|
||||||
|
fieldTimeFormat = "%e.%m.%y %k:%M"
|
||||||
|
|
||||||
|
readTime :: Text -> Either FormMessage UTCTime
|
||||||
|
readTime t =
|
||||||
|
case parseTimeM True germanTimeLocale fieldTimeFormat (T.unpack t) of
|
||||||
|
(Just time) -> Right time
|
||||||
|
Nothing -> Left $ MsgInvalidEntry "Datum/Zeit Format: tt.mm.yy hh:mm"
|
||||||
|
|
||||||
|
showTime :: UTCTime -> Text
|
||||||
|
showTime = fromString . (formatTime germanTimeLocale fieldTimeFormat)
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import Model.Types
|
|||||||
|
|
||||||
termExistsField :: Field (HandlerT UniWorX IO) TermIdentifier
|
termExistsField :: Field (HandlerT UniWorX IO) TermIdentifier
|
||||||
termExistsField = termField True
|
termExistsField = termField True
|
||||||
|
-- TODO: Change this to an option list of active terms
|
||||||
|
|
||||||
termNewField :: Field (HandlerT UniWorX IO) TermIdentifier
|
termNewField :: Field (HandlerT UniWorX IO) TermIdentifier
|
||||||
termNewField = termField False
|
termNewField = termField False
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
#{formTitle}
|
#{formTitle}
|
||||||
|
|
||||||
<div .row>
|
<div .row>
|
||||||
<div .col-lg-6>
|
<div .col-md-10 .col-lg-9>
|
||||||
<div .bs-callout bs-callout-info well>
|
<div .bs-callout bs-callout-info well>
|
||||||
<form .form-horizontal method=post action=@{actionUrl}#forms enctype=#{formEnctype}>
|
<form .form-horizontal method=post action=@{actionUrl}#forms enctype=#{formEnctype}>
|
||||||
^{formWidget}
|
^{formWidget}
|
||||||
|
|||||||
Reference in New Issue
Block a user