parent
6da8ad3481
commit
5e38f03a85
@ -593,7 +593,7 @@ section
|
|||||||
& + section, & + .two-column-sections
|
& + section, & + .two-column-sections
|
||||||
margin-top: 20px
|
margin-top: 20px
|
||||||
|
|
||||||
&:last-child
|
&:last-of-type
|
||||||
border-bottom: none
|
border-bottom: none
|
||||||
padding-bottom: 0px
|
padding-bottom: 0px
|
||||||
|
|
||||||
@ -604,7 +604,7 @@ section
|
|||||||
& + section, & + .two-column-sections
|
& + section, & + .two-column-sections
|
||||||
margin-top: 20px
|
margin-top: 20px
|
||||||
|
|
||||||
&:last-child
|
&:last-of-type
|
||||||
border-bottom: none
|
border-bottom: none
|
||||||
padding-bottom: 0px
|
padding-bottom: 0px
|
||||||
|
|
||||||
|
|||||||
@ -248,4 +248,12 @@ AllocationUserDeleteQuestion: Wollen Sie den/die unten aufgeführten Benutzer:in
|
|||||||
AllocationUserDeleted: Benutzer:in erfolgreich entfernt
|
AllocationUserDeleted: Benutzer:in erfolgreich entfernt
|
||||||
AllocationApplicationsCount n@Word64: #{n} #{pluralDE n "Bewerbung" "Bewerbungen"}
|
AllocationApplicationsCount n@Word64: #{n} #{pluralDE n "Bewerbung" "Bewerbungen"}
|
||||||
AllocationAllocationsCount n@Word64: #{n} #{pluralDE n "Zuweisung" "Zuweisungen"}
|
AllocationAllocationsCount n@Word64: #{n} #{pluralDE n "Zuweisung" "Zuweisungen"}
|
||||||
AllocationCourseHasRatings ratings@Word64 vetos@Word64: Dieser Kurs hat bereits #{ratings} #{pluralDE ratings "Bewertung" "Bewertungen"} (#{vetos} #{pluralDE vetos "Veto" "Vetos"})
|
AllocationCourseHasRatings ratings@Word64 vetos@Word64: Dieser Kurs hat bereits #{ratings} #{pluralDE ratings "Bewertung" "Bewertungen"} (#{vetos} #{pluralDE vetos "Veto" "Vetos"})
|
||||||
|
|
||||||
|
AllocationCourseParticipantFormCourse: Kurs
|
||||||
|
AllocationCourseParticipantFormIsRegistered: Registriert?
|
||||||
|
AllocationCourseParticipantFormIsSelfInflicted: Selbstverschuldet abgemeldet (Grund)?
|
||||||
|
AllocationCourseParticipantFormDefaultReason: Kein Grund
|
||||||
|
|
||||||
|
AllocationUserCourseParticipantFormTitle: Anmeldungen
|
||||||
|
AllocationUserAllocationUserFormTitle: Teilnahme an der Zentralanmeldung
|
||||||
@ -248,3 +248,11 @@ AllocationUserDeleted: Participant successfully removed
|
|||||||
AllocationApplicationsCount n: #{n} #{pluralENs n "application"}
|
AllocationApplicationsCount n: #{n} #{pluralENs n "application"}
|
||||||
AllocationAllocationsCount n: #{n} #{pluralENs n "allocation"}
|
AllocationAllocationsCount n: #{n} #{pluralENs n "allocation"}
|
||||||
AllocationCourseHasRatings ratings vetos: This course already has #{ratings} #{pluralENs ratings "rating"} (#{vetos} #{pluralENs vetos "veto"})
|
AllocationCourseHasRatings ratings vetos: This course already has #{ratings} #{pluralENs ratings "rating"} (#{vetos} #{pluralENs vetos "veto"})
|
||||||
|
|
||||||
|
AllocationCourseParticipantFormCourse: Course
|
||||||
|
AllocationCourseParticipantFormIsRegistered: Registered?
|
||||||
|
AllocationCourseParticipantFormIsSelfInflicted: Deregistration “self inflicted” (reason)?
|
||||||
|
AllocationCourseParticipantFormDefaultReason: No Reason
|
||||||
|
|
||||||
|
AllocationUserCourseParticipantFormTitle: Course registrations
|
||||||
|
AllocationUserAllocationUserFormTitle: Participation in allocation
|
||||||
|
|||||||
@ -513,7 +513,7 @@ unRenderMessage' cmp foundation inp = nub $ do
|
|||||||
unRenderMessage :: (Eq a, Finite a, RenderMessage master a) => master -> Text -> [a]
|
unRenderMessage :: (Eq a, Finite a, RenderMessage master a) => master -> Text -> [a]
|
||||||
unRenderMessage = unRenderMessage' (==)
|
unRenderMessage = unRenderMessage' (==)
|
||||||
|
|
||||||
unRenderMessageLenient :: (Eq a, Finite a, RenderMessage master a) => master -> Text -> [a]
|
unRenderMessageLenient :: forall a master. (Eq a, Finite a, RenderMessage master a) => master -> Text -> [a]
|
||||||
unRenderMessageLenient = unRenderMessage' cmp
|
unRenderMessageLenient = unRenderMessage' cmp
|
||||||
where cmp = (==) `on` mk . under packed (filter Char.isAlphaNum . concatMap unidecode)
|
where cmp = (==) `on` mk . under packed (filter Char.isAlphaNum . concatMap unidecode)
|
||||||
|
|
||||||
|
|||||||
@ -110,8 +110,9 @@ applicationForm maId@(is _Just -> isAlloc) cid muid ApplicationFormMode{..} mcsr
|
|||||||
prioField = selectField' (Just $ SomeMessage MsgAllocationCourseNoApplication) $ return prioOptions
|
prioField = selectField' (Just $ SomeMessage MsgAllocationCourseNoApplication) $ return prioOptions
|
||||||
|
|
||||||
(prioRes, prioView) <- case (isAlloc, afmApplicant, afmApplicantEdit, mApp) of
|
(prioRes, prioView) <- case (isAlloc, afmApplicant, afmApplicantEdit, mApp) of
|
||||||
(True , True , True , Nothing)
|
(True , True , True , _)
|
||||||
-> over _2 Just <$> mopt prioField (fslI MsgApplicationPriority) (Just oldPrio)
|
| is _Nothing mApp || is _Nothing mcsrf
|
||||||
|
-> over _2 Just <$> mopt prioField (fslI MsgApplicationPriority) (Just oldPrio)
|
||||||
(True , True , True , Just _ )
|
(True , True , True , Just _ )
|
||||||
-> over (_1 . _FormSuccess) Just . over _2 Just <$> mreq prioField (fslI MsgApplicationPriority) oldPrio
|
-> over (_1 . _FormSuccess) Just . over _2 Just <$> mreq prioField (fslI MsgApplicationPriority) oldPrio
|
||||||
(True , True , False, _ )
|
(True , True , False, _ )
|
||||||
@ -263,6 +264,7 @@ editApplicationR maId uid cid mAppId afMode allowAction postAction = do
|
|||||||
if
|
if
|
||||||
| BtnAllocationApply <- afAction
|
| BtnAllocationApply <- afAction
|
||||||
, allowAction afAction
|
, allowAction afAction
|
||||||
|
, is _Nothing maId || is _Just afPriority
|
||||||
-> runDB . setSerializable $ do
|
-> runDB . setSerializable $ do
|
||||||
haveOld <- exists [ CourseApplicationCourse ==. cid
|
haveOld <- exists [ CourseApplicationCourse ==. cid
|
||||||
, CourseApplicationUser ==. uid
|
, CourseApplicationUser ==. uid
|
||||||
@ -293,6 +295,7 @@ editApplicationR maId uid cid mAppId afMode allowAction postAction = do
|
|||||||
| is _BtnAllocationApplicationEdit afAction || is _BtnAllocationApplicationRate afAction
|
| is _BtnAllocationApplicationEdit afAction || is _BtnAllocationApplicationRate afAction
|
||||||
, allowAction afAction
|
, allowAction afAction
|
||||||
, Just appId <- mAppId
|
, Just appId <- mAppId
|
||||||
|
, is _Nothing maId || is _Just afPriority
|
||||||
-> runDB . setSerializable $ do
|
-> runDB . setSerializable $ do
|
||||||
now <- liftIO getCurrentTime
|
now <- liftIO getCurrentTime
|
||||||
|
|
||||||
|
|||||||
@ -17,36 +17,128 @@ import qualified Data.Conduit.Combinators as C
|
|||||||
import Handler.Utils.Delete
|
import Handler.Utils.Delete
|
||||||
|
|
||||||
import qualified Database.Esqueleto as E
|
import qualified Database.Esqueleto as E
|
||||||
|
import qualified Database.Esqueleto.Utils as E
|
||||||
|
|
||||||
|
import Handler.Course.Register (deregisterParticipant)
|
||||||
|
|
||||||
|
import Jobs.Queue
|
||||||
|
|
||||||
|
|
||||||
|
data AllocationCourseParticipantFormDefaultReason = AllocationCourseParticipantFormDefaultReason
|
||||||
|
deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic, Typeable)
|
||||||
|
deriving anyclass (Universe, Finite)
|
||||||
|
|
||||||
|
embedRenderMessage ''UniWorX ''AllocationCourseParticipantFormDefaultReason id
|
||||||
|
|
||||||
|
|
||||||
getAEditUserR, postAEditUserR :: TermId -> SchoolId -> AllocationShorthand -> CryptoUUIDUser -> Handler Html
|
getAEditUserR, postAEditUserR :: TermId -> SchoolId -> AllocationShorthand -> CryptoUUIDUser -> Handler Html
|
||||||
getAEditUserR = postAEditUserR
|
getAEditUserR = postAEditUserR
|
||||||
postAEditUserR tid ssh ash cID = do
|
postAEditUserR tid ssh ash cID = do
|
||||||
(Entity _ Allocation{..}, User{..}, (editUserAct, editUserForm, editUserEnctype)) <- runDB $ do
|
(Entity _ Allocation{..}, User{..}, editUserAct, editUserForm, regFormForm, formEnctype) <- runDBJobs $ do
|
||||||
uid <- decrypt cID
|
uid <- decrypt cID
|
||||||
user <- get404 uid
|
user <- get404 uid
|
||||||
alloc@(Entity aId _) <- getBy404 $ TermSchoolAllocationShort tid ssh ash
|
alloc@(Entity aId _) <- getBy404 $ TermSchoolAllocationShort tid ssh ash
|
||||||
Entity auId AllocationUser{..} <- getBy404 $ UniqueAllocationUser aId uid
|
Entity auId oldAllocationUser@AllocationUser{..} <- getBy404 $ UniqueAllocationUser aId uid
|
||||||
|
|
||||||
((editUserRes, editUserForm), editUserEnctype) <- runFormPost . renderAForm FormStandard $
|
regState <- do
|
||||||
allocationUserForm aId $ Just AllocationUserForm
|
courses <- E.select . E.from $ \((course `E.InnerJoin` allocationCourse) `E.LeftOuterJoin` courseParticipant `E.LeftOuterJoin` allocationDeregister) -> do
|
||||||
{ aauUser = uid
|
E.on $ allocationDeregister E.?. AllocationDeregisterUser E.==. E.justVal uid
|
||||||
, aauTotalCourses = allocationUserTotalCourses
|
E.&&. E.joinV (allocationDeregister E.?. AllocationDeregisterCourse) E.==. E.just (allocationCourse E.^. AllocationCourseCourse)
|
||||||
, aauPriority = allocationUserPriority
|
E.on $ courseParticipant E.?. CourseParticipantUser E.==. E.justVal uid
|
||||||
, aauApplications = Map.empty -- form collects existing applications itself
|
E.&&. courseParticipant E.?. CourseParticipantCourse E.==. E.just (allocationCourse E.^. AllocationCourseCourse)
|
||||||
}
|
E.on $ course E.^. CourseId E.==. allocationCourse E.^. AllocationCourseCourse
|
||||||
|
E.&&. allocationCourse E.^. AllocationCourseAllocation E.==. E.val aId
|
||||||
|
return ( course E.^. CourseId
|
||||||
|
, ( ( course E.^. CourseTerm
|
||||||
|
, course E.^. CourseSchool
|
||||||
|
, course E.^. CourseShorthand
|
||||||
|
)
|
||||||
|
, course E.^. CourseName
|
||||||
|
, ( ( E.joinV (courseParticipant E.?. CourseParticipantAllocated) E.==. E.justVal aId
|
||||||
|
E.||. E.isNothing (courseParticipant E.?. CourseParticipantId)
|
||||||
|
, courseParticipant E.?. CourseParticipantState
|
||||||
|
)
|
||||||
|
, ( E.isJust $ allocationDeregister E.?. AllocationDeregisterId
|
||||||
|
, E.joinV $ allocationDeregister E.?. AllocationDeregisterReason
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
MsgRenderer mr <- getMsgRenderer
|
||||||
|
return $
|
||||||
|
let toRegState (E.Value cId, (ident, E.Value cname, regState'))
|
||||||
|
= (cId, ((tid', ssh', csh), cname, courseRegState))
|
||||||
|
where (E.Value tid', E.Value ssh', E.Value csh) = ident
|
||||||
|
((E.Value isAlloc, E.Value mParState), (E.Value isDeregister, E.Value regReason)) = regState'
|
||||||
|
courseRegState
|
||||||
|
| not isAlloc = CourseParticipantFormNotAllocated
|
||||||
|
| isDeregister = CourseParticipantFormDeregistered
|
||||||
|
{ cpfDeregisterReason = Just $ fromMaybe defReason regReason
|
||||||
|
, cpfEverRegistered = True
|
||||||
|
}
|
||||||
|
| mParState == Just CourseParticipantActive = CourseParticipantFormRegistered
|
||||||
|
| otherwise = CourseParticipantFormDeregistered
|
||||||
|
{ cpfDeregisterReason = Nothing
|
||||||
|
, cpfEverRegistered = is _Just mParState
|
||||||
|
}
|
||||||
|
defReason = [st|<#{mr AllocationCourseParticipantFormDefaultReason}>|]
|
||||||
|
in Map.fromList $ map toRegState courses
|
||||||
|
|
||||||
editUserAct <- formResultMaybe editUserRes $ \AllocationUserForm{..} -> Just <$> do
|
((formRes, (regFormForm, editUserForm)), formEnctype) <- runFormPost $ \csrf
|
||||||
|
-> let allocForm = renderAForm FormStandard $
|
||||||
|
allocationUserForm aId $ Just AllocationUserForm
|
||||||
|
{ aauUser = uid
|
||||||
|
, aauTotalCourses = allocationUserTotalCourses
|
||||||
|
, aauPriority = allocationUserPriority
|
||||||
|
, aauApplications = Map.empty -- form collects existing applications itself
|
||||||
|
}
|
||||||
|
in (\(regRes, regForm) (editUserRes, editUserForm) -> ((,) <$> regRes <*> editUserRes, (regForm, editUserForm))) <$> courseParticipantForm regState csrf <*> allocForm mempty
|
||||||
|
|
||||||
|
editUserAct <- formResultMaybe formRes $ \(regState', AllocationUserForm{..}) -> Just <$> do
|
||||||
now <- liftIO getCurrentTime
|
now <- liftIO getCurrentTime
|
||||||
|
|
||||||
replace auId AllocationUser
|
|
||||||
{ allocationUserAllocation = aId
|
|
||||||
, allocationUserUser = aauUser
|
|
||||||
, allocationUserTotalCourses = aauTotalCourses
|
|
||||||
, allocationUserPriority = aauPriority
|
|
||||||
}
|
|
||||||
audit $ TransactionAllocationUserEdited aauUser aId
|
|
||||||
|
|
||||||
|
iforM_ (Map.intersectionWith (,) regState' regState) $ \cId (cpf, (_, _, oldCPF)) -> when (cpf /= oldCPF) $ case cpf of
|
||||||
|
CourseParticipantFormNotAllocated -> return ()
|
||||||
|
CourseParticipantFormDeregistered mReason _ -> do
|
||||||
|
hoist liftHandler $ deregisterParticipant uid =<< getJustEntity cId
|
||||||
|
|
||||||
|
app <- getYesod
|
||||||
|
let mReason' = mReason <&> \str -> maybe (Just str) (const Nothing) (listToMaybe $ unRenderMessageLenient @AllocationCourseParticipantFormDefaultReason app str)
|
||||||
|
deleteWhere [AllocationDeregisterUser ==. uid, AllocationDeregisterCourse ==. Just cId]
|
||||||
|
for_ mReason' $ \allocationDeregisterReason ->
|
||||||
|
insert AllocationDeregister
|
||||||
|
{ allocationDeregisterCourse = Just cId
|
||||||
|
, allocationDeregisterTime = now
|
||||||
|
, allocationDeregisterUser = uid
|
||||||
|
, allocationDeregisterReason
|
||||||
|
}
|
||||||
|
CourseParticipantFormRegistered -> do
|
||||||
|
void $ upsert CourseParticipant
|
||||||
|
{ courseParticipantCourse = cId
|
||||||
|
, courseParticipantUser = uid
|
||||||
|
, courseParticipantAllocated = Just aId
|
||||||
|
, courseParticipantState = CourseParticipantActive
|
||||||
|
, courseParticipantRegistration = now
|
||||||
|
}
|
||||||
|
[ CourseParticipantRegistration =. now
|
||||||
|
, CourseParticipantAllocated =. Just aId
|
||||||
|
, CourseParticipantState =. CourseParticipantActive
|
||||||
|
]
|
||||||
|
audit $ TransactionCourseParticipantEdit cId uid
|
||||||
|
queueDBJob . JobQueueNotification $ NotificationCourseRegistered uid cId
|
||||||
|
|
||||||
|
let newAllocationUser = AllocationUser
|
||||||
|
{ allocationUserAllocation = aId
|
||||||
|
, allocationUserUser = aauUser
|
||||||
|
, allocationUserTotalCourses = aauTotalCourses
|
||||||
|
, allocationUserPriority = aauPriority
|
||||||
|
}
|
||||||
|
when (newAllocationUser /= oldAllocationUser) $ do
|
||||||
|
replace auId newAllocationUser
|
||||||
|
audit $ TransactionAllocationUserEdited aauUser aId
|
||||||
|
|
||||||
|
-- Applications are complicated and it isn't easy to detect if something changed
|
||||||
|
-- Therefore we just always replace...
|
||||||
oldApps <- selectList [CourseApplicationUser ==. aauUser, CourseApplicationAllocation ==. Just aId] []
|
oldApps <- selectList [CourseApplicationUser ==. aauUser, CourseApplicationAllocation ==. Just aId] []
|
||||||
forM_ oldApps $ \(Entity appId CourseApplication{..}) -> do
|
forM_ oldApps $ \(Entity appId CourseApplication{..}) -> do
|
||||||
deleteWhere [ CourseApplicationFileApplication ==. appId ]
|
deleteWhere [ CourseApplicationFileApplication ==. appId ]
|
||||||
@ -74,9 +166,9 @@ postAEditUserR tid ssh ash cID = do
|
|||||||
|
|
||||||
return $ do
|
return $ do
|
||||||
addMessageI Success MsgAllocationEditUserUserEdited
|
addMessageI Success MsgAllocationEditUserUserEdited
|
||||||
redirect $ AllocationR tid ssh ash AUsersR
|
redirect . AllocationR tid ssh ash $ AEditUserR cID
|
||||||
|
|
||||||
return (alloc, user, (editUserAct, editUserForm, editUserEnctype))
|
return (alloc, user, editUserAct, editUserForm, regFormForm, formEnctype)
|
||||||
|
|
||||||
sequence_ editUserAct
|
sequence_ editUserAct
|
||||||
|
|
||||||
@ -86,10 +178,10 @@ postAEditUserR tid ssh ash cID = do
|
|||||||
|
|
||||||
siteLayoutMsg title $ do
|
siteLayoutMsg title $ do
|
||||||
setTitleI shortTitle
|
setTitleI shortTitle
|
||||||
wrapForm editUserForm FormSettings
|
wrapForm $(widgetFile "allocation/edit-user") FormSettings
|
||||||
{ formMethod = POST
|
{ formMethod = POST
|
||||||
, formAction = Just . SomeRoute . AllocationR tid ssh ash $ AEditUserR cID
|
, formAction = Just . SomeRoute . AllocationR tid ssh ash $ AEditUserR cID
|
||||||
, formEncoding = editUserEnctype
|
, formEncoding = formEnctype
|
||||||
, formAttrs = []
|
, formAttrs = []
|
||||||
, formSubmit = FormSubmit
|
, formSubmit = FormSubmit
|
||||||
, formAnchor = Nothing :: Maybe Text
|
, formAnchor = Nothing :: Maybe Text
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
module Handler.Allocation.UserForm
|
module Handler.Allocation.UserForm
|
||||||
( AllocationUserForm(..)
|
( AllocationUserForm(..)
|
||||||
, allocationUserForm
|
, allocationUserForm
|
||||||
|
, CourseParticipantForm(..)
|
||||||
|
, _CourseParticipantFormNotAllocated, _CourseParticipantFormDeregistered, _CourseParticipantFormRegistered, _cpfDeregisterReason, _cpfEverRegistered
|
||||||
|
, CourseParticipantForm'
|
||||||
|
, courseParticipantForm
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Import
|
import Import
|
||||||
@ -161,3 +165,63 @@ allocationApplicationsForm aId muid courses FieldSettings{..} fvRequired = form
|
|||||||
fvId <- maybe newIdent return fsId
|
fvId <- maybe newIdent return fsId
|
||||||
|
|
||||||
return (appsRes, pure FieldView{..})
|
return (appsRes, pure FieldView{..})
|
||||||
|
|
||||||
|
|
||||||
|
data CourseParticipantForm
|
||||||
|
= CourseParticipantFormNotAllocated -- ^ User is registered but not through allocation; no control
|
||||||
|
| CourseParticipantFormDeregistered -- ^ User is not currently registered
|
||||||
|
{ cpfDeregisterReason :: Maybe Text -- ^ `Just` if user was deregistered "self-inflicted", reason is required
|
||||||
|
, cpfEverRegistered :: Bool
|
||||||
|
}
|
||||||
|
| CourseParticipantFormRegistered -- ^ User is currently registered
|
||||||
|
deriving (Eq, Ord, Read, Show, Generic, Typeable)
|
||||||
|
|
||||||
|
type CourseParticipantForm' = Map CourseId CourseParticipantForm
|
||||||
|
|
||||||
|
makePrisms ''CourseParticipantForm
|
||||||
|
makeLenses_ ''CourseParticipantForm
|
||||||
|
|
||||||
|
courseParticipantForm :: forall m.
|
||||||
|
( MonadHandler m, HandlerSite m ~ UniWorX )
|
||||||
|
=> Map CourseId ((TermId, SchoolId, CourseShorthand), CourseName, CourseParticipantForm)
|
||||||
|
-> (Html -> MForm m (FormResult CourseParticipantForm', Widget))
|
||||||
|
courseParticipantForm courses csrf = do
|
||||||
|
lines' <- iforM courses $ \_cId ((tid, ssh, csh), cname, prevSt)
|
||||||
|
-> let toLine fCell = $(widgetFile "allocation/user-course-participant-form/line")
|
||||||
|
in over _2 toLine <$> case prevSt of
|
||||||
|
CourseParticipantFormNotAllocated -> do
|
||||||
|
(_, isRegView) <- mforced checkBoxField def True
|
||||||
|
return ( FormSuccess CourseParticipantFormNotAllocated
|
||||||
|
, $(widgetFile "allocation/user-course-participant-form/not-allocated")
|
||||||
|
)
|
||||||
|
_other -> do
|
||||||
|
let deregReason = prevSt ^? _cpfDeregisterReason . _Just
|
||||||
|
isRegPrev = is _CourseParticipantFormRegistered prevSt
|
||||||
|
everRegistered = fromMaybe True $ prevSt ^? _cpfEverRegistered
|
||||||
|
(isRegRes, isRegView) <- mpopt checkBoxField def $ Just isRegPrev
|
||||||
|
let selfInflictedFS = def
|
||||||
|
& addAttr "uw-interactive-fieldset" ""
|
||||||
|
& addAttr "data-conditional-input" (fvId isRegView)
|
||||||
|
& addAttr "data-conditional-negated" ""
|
||||||
|
(isSelfInflictedRes, isSelfInflictedView) <- if
|
||||||
|
| everRegistered -> over _2 Just <$> mopt (textField & cfStrip) selfInflictedFS (Just deregReason)
|
||||||
|
| otherwise -> return (FormSuccess Nothing, Nothing)
|
||||||
|
return ( case isRegRes of
|
||||||
|
FormMissing -> FormMissing
|
||||||
|
FormFailure es1 -> FormFailure $ es1 <> view _FormFailure isSelfInflictedRes
|
||||||
|
FormSuccess True
|
||||||
|
| FormFailure es2 <- isSelfInflictedRes
|
||||||
|
-> FormFailure es2
|
||||||
|
| otherwise
|
||||||
|
-> FormSuccess CourseParticipantFormRegistered
|
||||||
|
FormSuccess False
|
||||||
|
-> CourseParticipantFormDeregistered <$> isSelfInflictedRes <*> pure everRegistered
|
||||||
|
, $(widgetFile "allocation/user-course-participant-form/cell")
|
||||||
|
)
|
||||||
|
let linesWidget = Map.intersectionWith (,) courses lines'
|
||||||
|
& Map.elems
|
||||||
|
& sortBy (comparing . view $ _1 . _1)
|
||||||
|
& view (folded . _2 . _2)
|
||||||
|
return ( forM lines' $ view _1
|
||||||
|
, $(widgetFile "allocation/user-course-participant-form/layout")
|
||||||
|
)
|
||||||
|
|||||||
@ -22,9 +22,9 @@ postCAEditR tid ssh csh cID = do
|
|||||||
|
|
||||||
isAdmin <- case mAlloc of
|
isAdmin <- case mAlloc of
|
||||||
Just (Entity _ Allocation{..})
|
Just (Entity _ Allocation{..})
|
||||||
-> hasWriteAccessTo $ SchoolR allocationSchool SchoolEditR
|
-> hasWriteAccessTo $ AllocationR allocationTerm allocationSchool allocationShorthand AEditR
|
||||||
Nothing
|
Nothing
|
||||||
-> hasWriteAccessTo $ SchoolR courseSchool SchoolEditR
|
-> hasWriteAccessTo $ SchoolR courseSchool SchoolEditR
|
||||||
let afmApplicant = uid == courseApplicationUser || isAdmin
|
let afmApplicant = uid == courseApplicationUser || isAdmin
|
||||||
afmLecturer <- hasWriteAccessTo $ CourseR courseTerm courseSchool courseShorthand CEditR
|
afmLecturer <- hasWriteAccessTo $ CourseR courseTerm courseSchool courseShorthand CEditR
|
||||||
mayEdit <- hasWriteAccessTo $ CApplicationR tid ssh csh cID CAEditR
|
mayEdit <- hasWriteAccessTo $ CApplicationR tid ssh csh cID CAEditR
|
||||||
|
|||||||
@ -188,6 +188,7 @@ import Data.Bool.Instances as Import ()
|
|||||||
import Data.Encoding.Instances as Import ()
|
import Data.Encoding.Instances as Import ()
|
||||||
import Prometheus.Instances as Import ()
|
import Prometheus.Instances as Import ()
|
||||||
import Yesod.Form.Fields.Instances as Import ()
|
import Yesod.Form.Fields.Instances as Import ()
|
||||||
|
import Yesod.Form.Types.Instances as Import ()
|
||||||
import Data.MonoTraversable.Instances as Import ()
|
import Data.MonoTraversable.Instances as Import ()
|
||||||
import Web.Cookie.Instances as Import ()
|
import Web.Cookie.Instances as Import ()
|
||||||
import Network.HTTP.Types.Method.Instances as Import ()
|
import Network.HTTP.Types.Method.Instances as Import ()
|
||||||
|
|||||||
12
src/Yesod/Form/Types/Instances.hs
Normal file
12
src/Yesod/Form/Types/Instances.hs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||||
|
|
||||||
|
module Yesod.Form.Types.Instances
|
||||||
|
() where
|
||||||
|
|
||||||
|
import Yesod.Form.Types
|
||||||
|
|
||||||
|
import Data.Default
|
||||||
|
|
||||||
|
|
||||||
|
instance Default (FieldSettings site) where
|
||||||
|
def = ""
|
||||||
9
templates/allocation/edit-user.hamlet
Normal file
9
templates/allocation/edit-user.hamlet
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
$newline never
|
||||||
|
<section>
|
||||||
|
<h2>
|
||||||
|
_{MsgAllocationUserCourseParticipantFormTitle}
|
||||||
|
^{regFormForm}
|
||||||
|
<section>
|
||||||
|
<h2>
|
||||||
|
_{MsgAllocationUserAllocationUserFormTitle}
|
||||||
|
^{editUserForm}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
$newline never
|
||||||
|
<td .table__td .text--center>
|
||||||
|
^{fvWidget isRegView}
|
||||||
|
$maybe siView <- isSelfInflictedView
|
||||||
|
<td .table__td .text--center>
|
||||||
|
^{fvWidget siView}
|
||||||
|
$nothing
|
||||||
|
<td .table__td>
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
$newline never
|
||||||
|
#{csrf}
|
||||||
|
<div .scrolltable .scrolltable--bordered>
|
||||||
|
<table .table .table--hover .table--striped .table--condensed>
|
||||||
|
<thead>
|
||||||
|
<tr .table__row--head>
|
||||||
|
<th .table__th colspan=2>
|
||||||
|
_{MsgAllocationCourseParticipantFormCourse}
|
||||||
|
<th .table__th .text--center>
|
||||||
|
_{MsgAllocationCourseParticipantFormIsRegistered}
|
||||||
|
<th .table__th .text--center>
|
||||||
|
_{MsgAllocationCourseParticipantFormIsSelfInflicted}
|
||||||
|
<tbody>
|
||||||
|
^{linesWidget}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
$newline never
|
||||||
|
<tr .table__row>
|
||||||
|
<td .table__td>
|
||||||
|
<a href=@{CourseR tid ssh csh CShowR}>
|
||||||
|
#{toPathPiece tid}-#{ssh}-#{csh}
|
||||||
|
<td .table__td>
|
||||||
|
<a href=@{CourseR tid ssh csh CShowR}>
|
||||||
|
#{cname}
|
||||||
|
^{fCell}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
$newline never
|
||||||
|
<td .table__td .text--center>
|
||||||
|
^{fvWidget isRegView}
|
||||||
|
<td .table__td>
|
||||||
Loading…
Reference in New Issue
Block a user