feat(allocations): display number of ratings and vetos to admins

This commit is contained in:
Gregor Kleen 2021-06-15 17:40:19 +02:00
parent 6a1a64a611
commit 6da8ad3481
6 changed files with 48 additions and 6 deletions

View File

@ -874,6 +874,9 @@ section
@extend .explanation @extend .explanation
grid-area: admin-info grid-area: admin-info
.notification
margin-top: 0
@media (max-width: 426px) @media (max-width: 426px)
.allocation-course .allocation-course
grid-template-columns: 1fr grid-template-columns: 1fr

View File

@ -98,6 +98,7 @@ AllocationNoApplication: Keine Bewerbung
CourseAllocationCourseParticipants: Teilnehmer:innen CourseAllocationCourseParticipants: Teilnehmer:innen
CourseMembersCount n@Int !ident-ok: #{n} CourseMembersCount n@Int !ident-ok: #{n}
CourseMembersCountLimited n@Int max@Int !ident-ok: #{n}/#{max} CourseMembersCountLimited n@Int max@Int !ident-ok: #{n}/#{max}
CourseAllocationCourseRatings ratings@Word64 vetos@Word64: #{ratings} #{pluralDE ratings "Bewertung" "Bewertungen"} (#{vetos} #{pluralDE vetos "Veto" "Vetos"})
#templates allocation/accept #templates allocation/accept
ComputedAllocation: Berechnete Vergabe ComputedAllocation: Berechnete Vergabe
@ -246,4 +247,5 @@ AllocationMatchingLogFileName tid@TermId ssh@SchoolId ash@AllocationShorthand cI
AllocationUserDeleteQuestion: Wollen Sie den/die unten aufgeführten Benutzer:in wirklich aus der Zentralanmeldung entfernen? AllocationUserDeleteQuestion: Wollen Sie den/die unten aufgeführten Benutzer:in wirklich aus der Zentralanmeldung entfernen?
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"})

View File

@ -98,6 +98,7 @@ AllocationNoApplication: No application
CourseAllocationCourseParticipants: Participants CourseAllocationCourseParticipants: Participants
CourseMembersCount n: #{n} CourseMembersCount n: #{n}
CourseMembersCountLimited n max: #{n}/#{max} CourseMembersCountLimited n max: #{n}/#{max}
CourseAllocationCourseRatings ratings vetos: #{ratings} #{pluralENs ratings "rating"} (#{vetos} #{pluralENs vetos "veto"})
#templates allocation/accept #templates allocation/accept
ComputedAllocation: Computed allocation ComputedAllocation: Computed allocation
@ -246,3 +247,4 @@ AllocationUserDeleteQuestion: Do you really want to remove the allocation partic
AllocationUserDeleted: Participant successfully removed 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"})

View File

@ -63,6 +63,10 @@ postAShowR tid ssh ash = do
resultAllocationCourse = _6 . _entityVal resultAllocationCourse = _6 . _entityVal
resultParticipantCount :: _ => Lens' a Int resultParticipantCount :: _ => Lens' a Int
resultParticipantCount = _7 . _Value resultParticipantCount = _7 . _Value
resultRatingsCount :: _ => Getter a (Maybe Word64)
resultRatingsCount = _8 . _1 . _Value . to (assertM' (> 0))
resultVetosCount :: _ => Lens' a Word64
resultVetosCount = _8 . _2 . _Value
(Entity aId Allocation{..}, School{..}, isAnyLecturer, isAdmin, courses, registration, wouldNotifyNewCourse) <- runDB $ do (Entity aId Allocation{..}, School{..}, isAnyLecturer, isAdmin, courses, registration, wouldNotifyNewCourse) <- runDB $ do
alloc@(Entity aId Allocation{allocationSchool}) <- getBy404 $ TermSchoolAllocationShort tid ssh ash alloc@(Entity aId Allocation{allocationSchool}) <- getBy404 $ TermSchoolAllocationShort tid ssh ash
@ -86,6 +90,17 @@ postAShowR tid ssh ash = do
participantCount = E.subSelectCount . E.from $ \courseParticipant -> participantCount = E.subSelectCount . E.from $ \courseParticipant ->
E.where_ $ courseParticipant E.^. CourseParticipantCourse E.==. course E.^. CourseId E.where_ $ courseParticipant E.^. CourseParticipantCourse E.==. course E.^. CourseId
E.&&. courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive E.&&. courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
ratingsCount = E.subSelectCount . E.from $ \courseApplication' -> do
E.where_ $ courseApplication' E.^. CourseApplicationCourse E.==. course E.^. CourseId
E.&&. courseApplication' E.^. CourseApplicationAllocation E.==. E.justVal aId
E.&&. ( E.isJust (courseApplication' E.^. CourseApplicationRatingPoints)
E.||. E.isJust (courseApplication' E.^. CourseApplicationRatingComment)
E.||. courseApplication' E.^. CourseApplicationRatingVeto
)
vetosCount = E.subSelectCount . E.from $ \courseApplication' -> do
E.where_ $ courseApplication' E.^. CourseApplicationCourse E.==. course E.^. CourseId
E.&&. courseApplication' E.^. CourseApplicationAllocation E.==. E.justVal aId
E.&&. courseApplication' E.^. CourseApplicationRatingVeto
return ( course return ( course
, courseApplication , courseApplication
, hasTemplate , hasTemplate
@ -93,6 +108,7 @@ postAShowR tid ssh ash = do
, courseIsVisible now course . Just $ E.val aId , courseIsVisible now course . Just $ E.val aId
, allocationCourse , allocationCourse
, participantCount , participantCount
, (ratingsCount, vetosCount)
) )
registration <- fmap join . for muid $ getBy . UniqueAllocationUser aId registration <- fmap join . for muid $ getBy . UniqueAllocationUser aId
@ -166,6 +182,8 @@ postAShowR tid ssh ash = do
courseVisible = cEntry ^. resultCourseVisible courseVisible = cEntry ^. resultCourseVisible
AllocationCourse{..} = cEntry ^. resultAllocationCourse AllocationCourse{..} = cEntry ^. resultAllocationCourse
partCount = cEntry ^. resultParticipantCount partCount = cEntry ^. resultParticipantCount
mRatings = cEntry ^. resultRatingsCount
vetos = cEntry ^. resultVetosCount
cID <- encrypt cid :: WidgetFor UniWorX CryptoUUIDCourse cID <- encrypt cid :: WidgetFor UniWorX CryptoUUIDCourse
mayApply <- hasWriteAccessTo . AllocationR tid ssh ash $ AApplyR cID mayApply <- hasWriteAccessTo . AllocationR tid ssh ash $ AApplyR cID
mayEdit <- hasWriteAccessTo $ CourseR tid ssh courseShorthand CEditR mayEdit <- hasWriteAccessTo $ CourseR tid ssh courseShorthand CEditR

View File

@ -9,6 +9,8 @@ import Handler.Allocation.Application
import Handler.Utils import Handler.Utils
import qualified Database.Esqueleto as E import qualified Database.Esqueleto as E
import qualified Database.Esqueleto.Utils as E
import qualified Database.Esqueleto.PostgreSQL as E
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Text.Blaze (toMarkup) import Text.Blaze (toMarkup)
@ -69,16 +71,17 @@ allocationUserForm aId mTemplate = wFormToAForm $ do
<*> applicationsRes <*> applicationsRes
allocationApplicationsForm :: forall m. allocationApplicationsForm :: forall m backend.
( MonadHandler m, HandlerSite m ~ UniWorX ( MonadHandler m, HandlerSite m ~ UniWorX
, E.SqlBackendCanRead backend
) )
=> AllocationId => AllocationId
-> Maybe UserId -> Maybe UserId
-> Map CourseId (Course, AllocationCourse, Bool) -> Map CourseId (Course, AllocationCourse, Bool)
-> FieldSettings UniWorX -> FieldSettings UniWorX
-> Bool -> Bool
-> AForm m (Map CourseId ApplicationForm) -> AForm (ReaderT backend m) (Map CourseId ApplicationForm)
allocationApplicationsForm aId muid courses FieldSettings{..} fvRequired = formToAForm . hoist liftHandler $ do allocationApplicationsForm aId muid courses FieldSettings{..} fvRequired = formToAForm $ do
now <- liftIO getCurrentTime now <- liftIO getCurrentTime
let afmApplicant = True let afmApplicant = True
@ -90,7 +93,16 @@ allocationApplicationsForm aId muid courses FieldSettings{..} fvRequired = form
guard hasApplicationTemplate guard hasApplicationTemplate
let Course{..} = course let Course{..} = course
toTextUrl $ CourseR courseTerm courseSchool courseShorthand CRegisterTemplateR toTextUrl $ CourseR courseTerm courseSchool courseShorthand CRegisterTemplateR
over _2 (course, allocCourse, mApplicationTemplate, ) <$> applicationForm (Just aId) cId muid ApplicationFormMode{..} Nothing counts <- lift . fmap (maybe (Nothing, 0) $ bimap (assertM' (> 0) . E.unValue) E.unValue) . E.selectMaybe . E.from $ \courseApplication -> do
E.where_ $ courseApplication E.^. CourseApplicationCourse E.==. E.val cId
E.&&. courseApplication E.^. CourseApplicationAllocation E.==. E.justVal aId
let hasRating = E.isJust (courseApplication E.^. CourseApplicationRatingPoints)
E.||. E.isJust (courseApplication E.^. CourseApplicationRatingComment)
E.||. courseApplication E.^. CourseApplicationRatingVeto
return ( E.count (courseApplication E.^. CourseApplicationId) `E.filterWhere` hasRating
, E.count (courseApplication E.^. CourseApplicationId) `E.filterWhere` (courseApplication E.^. CourseApplicationRatingVeto)
)
hoist liftHandler $ over _2 (course, allocCourse, mApplicationTemplate, counts, ) <$> applicationForm (Just aId) cId muid ApplicationFormMode{..} Nothing
let appsRes = sequenceA $ view _1 <$> appsRes' let appsRes = sequenceA $ view _1 <$> appsRes'
appsViews = view _2 <$> appsRes' appsViews = view _2 <$> appsRes'
@ -98,7 +110,7 @@ allocationApplicationsForm aId muid courses FieldSettings{..} fvRequired = form
[whamlet| [whamlet|
$newline never $newline never
<div .allocation__courses> <div .allocation__courses>
$forall (Course{courseTerm, courseSchool, courseShorthand, courseName, courseApplicationsInstructions}, AllocationCourse{allocationCourseAcceptSubstitutes}, mApplicationTemplate, ApplicationFormView{afvPriority, afvForm}) <- Map.elems appsViews $forall (Course{courseTerm, courseSchool, courseShorthand, courseName, courseApplicationsInstructions}, AllocationCourse{allocationCourseAcceptSubstitutes}, mApplicationTemplate, (mRatings, vetos), ApplicationFormView{afvPriority, afvForm}) <- Map.elems appsViews
<div .allocation-course> <div .allocation-course>
<div .allocation-course__priority-label .allocation__label> <div .allocation-course__priority-label .allocation__label>
_{MsgAllocationPriority} _{MsgAllocationPriority}
@ -116,6 +128,8 @@ allocationApplicationsForm aId muid courses FieldSettings{..} fvRequired = form
_{MsgCourseAllocationCourseAcceptsSubstitutesNever} _{MsgCourseAllocationCourseAcceptsSubstitutesNever}
$if allocationCourseAcceptSubstitutes >= Just now $if allocationCourseAcceptSubstitutes >= Just now
\ ^{iconOK} \ ^{iconOK}
$maybe ratings <- mRatings
^{notification NotificationBroad =<< messageI Warning (MsgAllocationCourseHasRatings ratings vetos)}
$if is _Just mApplicationTemplate || is _Just courseApplicationsInstructions $if is _Just mApplicationTemplate || is _Just courseApplicationsInstructions
<div .allocation-course__instructions-label .allocation__label> <div .allocation-course__instructions-label .allocation__label>
_{MsgCourseAllocationApplicationInstructionsApplication} _{MsgCourseAllocationApplicationInstructionsApplication}

View File

@ -33,6 +33,9 @@ $if isAdmin
$nothing $nothing
\ _{MsgCourseMembersCount partCount} \ _{MsgCourseMembersCount partCount}
\ ^{iconProblem} \ ^{iconProblem}
$maybe ratings <- mRatings
<p>
_{MsgCourseAllocationCourseRatings ratings vetos}
$if hasApplicationTemplate || is _Just courseApplicationsInstructions $if hasApplicationTemplate || is _Just courseApplicationsInstructions
<div .allocation-course__instructions-label .allocation__label> <div .allocation-course__instructions-label .allocation__label>
_{MsgCourseApplicationInstructionsApplication} _{MsgCourseApplicationInstructionsApplication}