Merge branch 'master' into 205-klausuren

Fix tests
This commit is contained in:
Gregor Kleen 2019-06-27 09:45:57 +02:00
commit b63d77ec7b
26 changed files with 141 additions and 139 deletions

View File

@ -1,5 +1,5 @@
[Dolphin] [Dolphin]
Timestamp=2018,3,14,10,57,55 Timestamp=2019,6,26,19,32,25
Version=4 Version=4
[Settings] [Settings]

View File

@ -203,6 +203,7 @@ SheetErrHintEarly: Hinweise dürfen erst nach Beginn des Abgabezeitraums herausg
SheetErrSolutionEarly: Lösungen dürfen erst nach Ende der Abgabezeitraums herausgegeben werden SheetErrSolutionEarly: Lösungen dürfen erst nach Ende der Abgabezeitraums herausgegeben werden
SheetNoCurrent: Es gibt momentan kein aktives Übungsblatt. SheetNoCurrent: Es gibt momentan kein aktives Übungsblatt.
SheetNoOldUnassigned: Alle Abgaben inaktiver Blätter sind bereits einen Korrektor zugeteilt. SheetNoOldUnassigned: Alle Abgaben inaktiver Blätter sind bereits einen Korrektor zugeteilt.
SheetsUnassignable name@Text: Momentan keine Abgaben zuteilbar für #{name}
Deadline: Abgabe Deadline: Abgabe
Done: Eingereicht Done: Eingereicht
@ -323,7 +324,7 @@ Correctors: Korrektoren
CorState: Status CorState: Status
CorByTut: Zuteilung nach Tutorium CorByTut: Zuteilung nach Tutorium
CorProportion: Anteil CorProportion: Anteil
CorDeficit: Defizit CorDeficitProportion: Defizit Anteile
CorByProportionOnly proportion@Rational: #{display proportion} Anteile CorByProportionOnly proportion@Rational: #{display proportion} Anteile
CorByProportionIncludingTutorial proportion@Rational: #{display proportion} Anteile - Tutorium CorByProportionIncludingTutorial proportion@Rational: #{display proportion} Anteile - Tutorium
CorByProportionExcludingTutorial proportion@Rational: #{display proportion} Anteile + Tutorium CorByProportionExcludingTutorial proportion@Rational: #{display proportion} Anteile + Tutorium
@ -404,6 +405,7 @@ UpdatedSheetCorrectorsAutoFailed n@Int: #{display n} #{pluralDE n "Abgabe konnte
CouldNotAssignCorrectorsAuto num@Int64: #{display num} Abgaben konnten nicht automatisch zugewiesen werden: CouldNotAssignCorrectorsAuto num@Int64: #{display num} Abgaben konnten nicht automatisch zugewiesen werden:
SelfCorrectors num@Int64: #{display num} Abgaben wurden Abgebenden als eigenem Korrektor zugeteilt! SelfCorrectors num@Int64: #{display num} Abgaben wurden Abgebenden als eigenem Korrektor zugeteilt!
CorrectionSheets: Übersicht Korrekturen nach Blättern CorrectionSheets: Übersicht Korrekturen nach Blättern
CorrectionCorrectors: Übersicht Korrekturen nach Korrektoren CorrectionCorrectors: Übersicht Korrekturen nach Korrektoren
AssignSubmissionExceptionNoCorrectors: Es sind keine Korrektoren eingestellt AssignSubmissionExceptionNoCorrectors: Es sind keine Korrektoren eingestellt

View File

@ -160,6 +160,7 @@ deriving instance Generic SheetR
deriving instance Generic SubmissionR deriving instance Generic SubmissionR
deriving instance Generic MaterialR deriving instance Generic MaterialR
deriving instance Generic TutorialR deriving instance Generic TutorialR
deriving instance Generic ExamR
deriving instance Generic (Route UniWorX) deriving instance Generic (Route UniWorX)
-- | Convenient Type Synonyms: -- | Convenient Type Synonyms:
@ -1494,7 +1495,7 @@ instance YesodBreadcrumbs UniWorX where
breadcrumb (CourseR tid ssh csh CInviteR) = return ("Einladung", Just $ CourseR tid ssh csh CShowR) breadcrumb (CourseR tid ssh csh CInviteR) = return ("Einladung", Just $ CourseR tid ssh csh CShowR)
breadcrumb (CourseR tid ssh csh (CUserR _)) = return ("Teilnehmer" , Just $ CourseR tid ssh csh CUsersR) breadcrumb (CourseR tid ssh csh (CUserR _)) = return ("Teilnehmer" , Just $ CourseR tid ssh csh CUsersR)
breadcrumb (CourseR tid ssh csh CCorrectionsR) = return ("Abgaben" , Just $ CourseR tid ssh csh CShowR) breadcrumb (CourseR tid ssh csh CCorrectionsR) = return ("Abgaben" , Just $ CourseR tid ssh csh CShowR)
breadcrumb (CourseR tid ssh csh CAssignR) = return ("Zuteilung" , Just $ CourseR tid ssh csh CCorrectionsR) breadcrumb (CourseR tid ssh csh CAssignR) = return ("Zuteilung Korrekturen" , Just $ CourseR tid ssh csh CCorrectionsR)
breadcrumb (CourseR tid ssh csh SheetListR) = return ("Übungen" , Just $ CourseR tid ssh csh CShowR) breadcrumb (CourseR tid ssh csh SheetListR) = return ("Übungen" , Just $ CourseR tid ssh csh CShowR)
breadcrumb (CourseR tid ssh csh SheetNewR ) = return ("Neu", Just $ CourseR tid ssh csh SheetListR) breadcrumb (CourseR tid ssh csh SheetNewR ) = return ("Neu", Just $ CourseR tid ssh csh SheetListR)
breadcrumb (CourseR tid ssh csh SheetCurrentR) = return ("Aktuelles Blatt", Just $ CourseR tid ssh csh SheetListR) breadcrumb (CourseR tid ssh csh SheetCurrentR) = return ("Aktuelles Blatt", Just $ CourseR tid ssh csh SheetListR)
@ -1518,7 +1519,7 @@ instance YesodBreadcrumbs UniWorX where
breadcrumb (CSheetR tid ssh csh shn SEditR) = return ("Bearbeiten" , Just $ CSheetR tid ssh csh shn SShowR) breadcrumb (CSheetR tid ssh csh shn SEditR) = return ("Bearbeiten" , Just $ CSheetR tid ssh csh shn SShowR)
breadcrumb (CSheetR tid ssh csh shn SDelR ) = return ("Löschen" , Just $ CSheetR tid ssh csh shn SShowR) breadcrumb (CSheetR tid ssh csh shn SDelR ) = return ("Löschen" , Just $ CSheetR tid ssh csh shn SShowR)
breadcrumb (CSheetR tid ssh csh shn SSubsR) = return ("Abgaben" , Just $ CSheetR tid ssh csh shn SShowR) breadcrumb (CSheetR tid ssh csh shn SSubsR) = return ("Abgaben" , Just $ CSheetR tid ssh csh shn SShowR)
breadcrumb (CSheetR tid ssh csh shn SAssignR) = return ("Zuteilen" , Just $ CSheetR tid ssh csh shn SSubsR) breadcrumb (CSheetR tid ssh csh shn SAssignR) = return ("Zuteilung Korrekturen" , Just $ CSheetR tid ssh csh shn SSubsR)
breadcrumb (CSheetR tid ssh csh shn SubmissionNewR) = return ("Abgabe", Just $ CSheetR tid ssh csh shn SShowR) breadcrumb (CSheetR tid ssh csh shn SubmissionNewR) = return ("Abgabe", Just $ CSheetR tid ssh csh shn SShowR)
breadcrumb (CSheetR tid ssh csh shn SubmissionOwnR) = return ("Abgabe", Just $ CSheetR tid ssh csh shn SShowR) breadcrumb (CSheetR tid ssh csh shn SubmissionOwnR) = return ("Abgabe", Just $ CSheetR tid ssh csh shn SShowR)
breadcrumb (CSubmissionR tid ssh csh shn _ SubShowR) = return ("Abgabe", Just $ CSheetR tid ssh csh shn SShowR) breadcrumb (CSubmissionR tid ssh csh shn _ SubShowR) = return ("Abgabe", Just $ CSheetR tid ssh csh shn SShowR)

View File

@ -165,7 +165,7 @@ postAdminTestR = do
-- | Make a form for adding a point/line/plane/hyperplane/... (in this case: cell) -- | Make a form for adding a point/line/plane/hyperplane/... (in this case: cell)
-- --
-- This /needs/ to replace all occurences of @mreq@ with @mpreq@ (no fields should be /actually/ required) -- This /needs/ to replace all occurrences of @mreq@ with @mpreq@ (no fields should be /actually/ required)
mkAddForm :: ListPosition -- ^ Approximate position of the add-widget mkAddForm :: ListPosition -- ^ Approximate position of the add-widget
-> Natural -- ^ Dimension Index, outermost dimension ist 0 i.e. if dimension is 3 hyperplane-adders get passed 0, planes get passed 1, lines get 2, and points get 3 -> Natural -- ^ Dimension Index, outermost dimension ist 0 i.e. if dimension is 3 hyperplane-adders get passed 0, planes get passed 1, lines get 2, and points get 3
-> (Text -> Text) -- ^ Nudge deterministic field ids so they're unique -> (Text -> Text) -- ^ Nudge deterministic field ids so they're unique

View File

@ -1052,11 +1052,8 @@ data SubAssignInfo = SubAssignInfo { saiName :: SheetName, saiSubmissionNr, saiC
getCAssignR, postCAssignR :: TermId -> SchoolId -> CourseShorthand -> Handler Html getCAssignR, postCAssignR :: TermId -> SchoolId -> CourseShorthand -> Handler Html
getCAssignR = postCAssignR getCAssignR = postCAssignR
postCAssignR tid ssh csh = do postCAssignR tid ssh csh = do
(shids,cid) <- runDB $ do cid <- runDB $ getKeyBy404 $ TermSchoolCourseShort tid ssh csh
cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh assignHandler tid ssh csh cid []
shids <- selectKeysList [SheetCourse ==. cid] [Asc SheetActiveTo]
return (shids,cid)
assignHandler tid ssh csh cid shids
getSAssignR, postSAssignR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> Handler Html getSAssignR, postSAssignR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> Handler Html
getSAssignR = postSAssignR getSAssignR = postSAssignR
@ -1064,51 +1061,13 @@ postSAssignR tid ssh csh shn = do
(shid,cid) <- runDB $ fetchSheetIdCourseId tid ssh csh shn (shid,cid) <- runDB $ fetchSheetIdCourseId tid ssh csh shn
assignHandler tid ssh csh cid [shid] assignHandler tid ssh csh cid [shid]
-- DEPRECATED assignHandler', delete me soonish {- TODO: Feature:
assignHandler' :: TermId -> SchoolId -> CourseShorthand -> CourseId -> [SheetId] -> Handler Html make distivt buttons for each sheet, so that users see which sheet will be assigned.
assignHandler' tid ssh csh _cid rawSids = do Currently this information is available within the page heading!
-- gather data
openSubs <- runDB $ (\f -> foldM f Map.empty rawSids) $
\acc sid -> maybeT (return acc) $ do
Just Sheet{sheetName=saiName} <- lift $ get sid
guardM $ lift $ hasWriteAccessTo $ CSheetR tid ssh csh saiName SAssignR -- we must check, whether the submission is already closed and thus assignable
saiUnassignedNr <- lift $ count [SubmissionSheet ==. sid, SubmissionRatingBy ==. Nothing]
guard $ 0 < saiUnassignedNr -- only consider sheets with unassigned submissions
saiSubmissionNr <- lift $ count [SubmissionSheet ==. sid]
saiCorrectorNr <- lift $ count [SheetCorrectorSheet ==. sid, SheetCorrectorState ==. CorrectorNormal]
-- guard $ saiCorrectorNr > 0 -- COMMENTED OUT BECAUSE we should show sheets without possible correctors to inform the user about these problematic sheets
return $ Map.insert sid SubAssignInfo{..} acc
let sids = Map.keys openSubs
linkBack <- simpleLinkI (SomeMessage MsgGenericBack) <$> case sids of
[sid] -> do Sheet{sheetName} <- runDB $ getJust sid
return $ CSheetR tid ssh csh sheetName SSubsR
_ -> return $ CourseR tid ssh csh CCorrectionsR
-- process form
currentRoute <- getCurrentRoute
((btnResult, btnWdgt), btnEnctype) <- runFormPost $ identifyForm FIDAssignSubmissions buttonForm
assignmentStatus <- fmap (fromMaybe Map.empty) . formResultMaybe btnResult $ \BtnSubmissionsAssign ->
-- Assign submissions
fmap Just . runDB $ (\f -> foldM f Map.empty sids) $
\acc sid -> flip (Map.insert sid) acc <$> assignSubmissions sid Nothing
-- Too much important information for an alert message. Display proper info page instead
let btnForm = wrapForm btnWdgt def
{ formAction = SomeRoute <$> currentRoute
, formEncoding = btnEnctype
, formSubmit = FormNoSubmit
}
headingShort = MsgMenuCorrectionsAssign
headingLong = prependCourseTitle tid ssh csh MsgMenuCorrectionsAssign
siteLayoutMsg headingShort $ do
setTitleI headingLong
$(widgetFile "corrections-assign")
if null sids || not (null assignmentStatus)
then linkBack -- TODO: convenience link might be unnecessary: either via breadcrumb or closing model. Remove, if modal works fine. Otherwise change to PrimaryAction?
else btnForm
Stub:
{- TODO: make buttons for each sheet, so that users see which sheet is assigned
data ButtonCorrectionsAssign = BtnCorrectionsAssignAll | BtnCorrectionsAssignSheet SheetName data ButtonCorrectionsAssign = BtnCorrectionsAssignAll | BtnCorrectionsAssignSheet SheetName
deriving (Enum, Eq, Ord, Bounded, Read, Show, Generic, Typeable) deriving (Enum, Eq, Ord, Bounded, Read, Show, Generic, Typeable)
instance Button UniWorX ButtonCorrectionsAssign instance Button UniWorX ButtonCorrectionsAssign
-- Are those needed any more? -- Are those needed any more?
instance Universe ButtonCorrectionsAssign instance Universe ButtonCorrectionsAssign
@ -1126,7 +1085,7 @@ assignHandler tid ssh csh cid assignSids = do
(btnWdgt, btnResult) <- runButtonForm FIDAssignSubmissions (btnWdgt, btnResult) <- runButtonForm FIDAssignSubmissions
-- gather data -- gather data
(nrParticipants, groupsPossible, infoMap, correctorMap, assignment) <- runDB $ do (assignSheetNames, nrParticipants, groupsPossible, infoMap, correctorMap, assignment) <- runDB $ do
-- cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh -- cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh
nrParticipants <- count [CourseParticipantCourse ==. cid] nrParticipants <- count [CourseParticipantCourse ==. cid]
@ -1137,6 +1096,7 @@ assignHandler tid ssh csh cid assignSids = do
groupsPossible = groupsPossible =
let foldFun (Entity _ Sheet{sheetGrouping=sgr}) acc = acc || sgr /= NoGroups let foldFun (Entity _ Sheet{sheetGrouping=sgr}) acc = acc || sgr /= NoGroups
in List.foldr foldFun False sheetList in List.foldr foldFun False sheetList
assignSheetNames = fmap sheetName $ mapMaybe (\sid -> Map.lookup sid sheets) assignSids
-- plan or assign unassigned submissions for given sheets -- plan or assign unassigned submissions for given sheets
let buildA :: (Map SheetName ((Set SubmissionId, Set SubmissionId), Map (Maybe UserId) Int, Map UserId Rational)) -> SheetId -> DB (Map SheetName ((Set SubmissionId, Set SubmissionId), Map (Maybe UserId) Int, Map UserId Rational)) let buildA :: (Map SheetName ((Set SubmissionId, Set SubmissionId), Map (Maybe UserId) Int, Map UserId Rational)) -> SheetId -> DB (Map SheetName ((Set SubmissionId, Set SubmissionId), Map (Maybe UserId) Int, Map UserId Rational))
@ -1166,7 +1126,10 @@ assignHandler tid ssh csh cid assignSids = do
addMessageI msg_status $ UniWorXMessages $ msg_header : catMaybes [alert_ok, alert_fail] addMessageI msg_status $ UniWorXMessages $ msg_header : catMaybes [alert_ok, alert_fail]
return status return status
return $ Map.insert shn (status, countMapElems plan, deficit) acc return $ Map.insert shn (status, countMapElems plan, deficit) acc
assignment <- foldM buildA Map.empty assignSids assignSids' <- if null assignSids -- assignAll; we distinguish assignSids' here avoid useless Alerts
then selectKeysList [SheetCourse ==. cid] [Asc SheetActiveTo]
else return assignSids
assignment <- foldM buildA Map.empty assignSids'
correctors <- E.select . E.from $ \(corrector `E.InnerJoin` user) -> do correctors <- E.select . E.from $ \(corrector `E.InnerJoin` user) -> do
E.on $ corrector E.^. SheetCorrectorUser E.==. user E.^. UserId E.on $ corrector E.^. SheetCorrectorUser E.==. user E.^. UserId
@ -1210,10 +1173,13 @@ assignHandler tid ssh csh cid assignSids = do
} }
in Map.insertWith (Map.unionWith (<>)) shnm cinf m in Map.insertWith (Map.unionWith (<>)) shnm cinf m
return (nrParticipants, groupsPossible, infoMap, correctorMap, assignment) return (assignSheetNames, nrParticipants, groupsPossible, infoMap, correctorMap, assignment)
let -- infoMap :: Map SheetName (Map (Maybe UserId) CorrectionInfo) -- repeated here for easier reference let -- infoMap :: Map SheetName (Map (Maybe UserId) CorrectionInfo) -- repeated here for easier reference
-- create aggregate maps -- create aggregate maps
sheetNames :: [SheetName]
sheetNames = Map.keys infoMap
sheetMap :: Map SheetName CorrectionInfo sheetMap :: Map SheetName CorrectionInfo
sheetMap = Map.map fold infoMap sheetMap = Map.map fold infoMap
@ -1230,7 +1196,10 @@ assignHandler tid ssh csh cid assignSids = do
corrMap :: Map (Maybe UserId) CorrectionInfo corrMap :: Map (Maybe UserId) CorrectionInfo
corrMap = Map.unionsWith (<>) $ Map.elems infoMap corrMap = Map.unionsWith (<>) $ Map.elems infoMap
sheetNames = Map.keys infoMap
corrMapSum :: CorrectionInfo
corrMapSum = fold corrMap
let -- whamlet convenience functions let -- whamlet convenience functions
-- avoid nestes hamlet $maybe with duplicated $nothing -- avoid nestes hamlet $maybe with duplicated $nothing
getCorrector :: Maybe UserId -> (Widget,Map SheetName SheetCorrector) getCorrector :: Maybe UserId -> (Widget,Map SheetName SheetCorrector)
@ -1256,10 +1225,9 @@ assignHandler tid ssh csh cid assignSids = do
getCorrDeficit _ = Nothing getCorrDeficit _ = Nothing
getLoadSum :: SheetName -> Text getLoadSum :: SheetName -> Text
getLoadSum shn getLoadSum shn | (Just load) <- Map.lookup shn sheetLoad
| (Just load) <- Map.lookup shn sheetLoad = showCompactCorrectorLoad load CorrectorNormal
= "Σ" <> showCompactCorrectorLoad load CorrectorNormal getLoadSum _ = mempty
getLoadSum _ = mempty
showDiffDays :: Maybe NominalDiffTime -> Text showDiffDays :: Maybe NominalDiffTime -> Text
showDiffDays = foldMap formatDiffDays showDiffDays = foldMap formatDiffDays
@ -1272,6 +1240,10 @@ assignHandler tid ssh csh cid assignSids = do
| 0 < Map.size assignment = MsgMenuCorrectionsAssignSheet $ Text.intercalate ", " $ fmap CI.original $ Map.keys assignment | 0 < Map.size assignment = MsgMenuCorrectionsAssignSheet $ Text.intercalate ", " $ fmap CI.original $ Map.keys assignment
| otherwise = MsgMenuCorrectionsAssign | otherwise = MsgMenuCorrectionsAssign
headingLong = prependCourseTitle tid ssh csh MsgMenuCorrectionsAssign headingLong = prependCourseTitle tid ssh csh MsgMenuCorrectionsAssign
unassignableSheets = filter (\shn -> Map.notMember shn assignment) assignSheetNames
unless (null unassignableSheets) $ addMessageI Warning $ MsgSheetsUnassignable $ Text.intercalate ", " $ fmap CI.original unassignableSheets
siteLayoutMsg headingShort $ do siteLayoutMsg headingShort $ do
setTitleI headingLong setTitleI headingLong
$(widgetFile "corrections-overview") $(widgetFile "corrections-overview")

View File

@ -63,7 +63,7 @@ getHealthR = do
<dd .deflist__dd>#{boolSymbol passed} <dd .deflist__dd>#{boolSymbol passed}
$of HealthLDAPAdmins (Just found) $of HealthLDAPAdmins (Just found)
<dt .deflist__dt>_{MsgHealthLDAPAdmins} <dt .deflist__dt>_{MsgHealthLDAPAdmins}
<dd .deflist__dd>#{textPercent found} <dd .deflist__dd>#{textPercent found 1}
$of HealthSMTPConnect (Just passed) $of HealthSMTPConnect (Just passed)
<dt .deflist__dt>_{MsgHealthSMTPConnect} <dt .deflist__dt>_{MsgHealthSMTPConnect}
<dd .deflist__dd>#{boolSymbol passed} <dd .deflist__dd>#{boolSymbol passed}
@ -80,7 +80,7 @@ getInstanceR = do
instanceInfo@(clusterId, instanceId) <- getsYesod $ (,) <$> appClusterID <*> appInstanceID instanceInfo@(clusterId, instanceId) <- getsYesod $ (,) <$> appClusterID <*> appInstanceID
setWeakEtagHashable (clusterId, instanceId) setWeakEtagHashable (clusterId, instanceId)
selectRep $ do selectRep $ do
provideRep $ provideRep $
siteLayoutMsg MsgInstanceIdentification $ do siteLayoutMsg MsgInstanceIdentification $ do

View File

@ -66,6 +66,6 @@ postHelpR = do
let formWidget = wrapForm formWidget' def let formWidget = wrapForm formWidget' def
{ formAction = Just $ SomeRoute HelpR { formAction = Just $ SomeRoute HelpR
, formEncoding = formEnctype , formEncoding = formEnctype
, formAttrs = [ ("data-ajax-submit", "") | isModal ] , formAttrs = [ asyncSubmitAttr | isModal ]
} }
$(widgetFile "help") $(widgetFile "help")

View File

@ -147,7 +147,7 @@ postProfileR = do
siteLayout [whamlet|_{MsgProfileFor} ^{nameWidget userDisplayName userSurname}|] $ do siteLayout [whamlet|_{MsgProfileFor} ^{nameWidget userDisplayName userSurname}|] $ do
setTitle . toHtml $ "Profil " <> userIdent setTitle . toHtml $ "Profil " <> userIdent
let settingsForm = let settingsForm =
wrapForm formWidget FormSettings wrapForm formWidget FormSettings
{ formMethod = POST { formMethod = POST
, formAction = Just . SomeRoute $ ProfileR :#: ProfileSettings , formAction = Just . SomeRoute $ ProfileR :#: ProfileSettings
@ -593,7 +593,7 @@ postUserNotificationR cID = do
let formWidget = wrapForm nsInnerWdgt def let formWidget = wrapForm nsInnerWdgt def
{ formAction = Just . SomeRoute $ UserNotificationR cID { formAction = Just . SomeRoute $ UserNotificationR cID
, formEncoding = nsEnc , formEncoding = nsEnc
, formAttrs = [ ("data-ajax-submit", "") | isModal ] , formAttrs = [ asyncSubmitAttr | isModal ]
} }
formResultModal nsRes (UserNotificationR cID, [ (toPathPiece GetBearer, toPathPiece jwt) | Just jwt <- pure mJwt ]) $ \ns -> do formResultModal nsRes (UserNotificationR cID, [ (toPathPiece GetBearer, toPathPiece jwt) | Just jwt <- pure mJwt ]) $ \ns -> do

View File

@ -257,9 +257,7 @@ getSheetListR tid ssh csh = do
(Just (Entity _ Submission{submissionRatingPoints=Just sPoints})) -> (Just (Entity _ Submission{submissionRatingPoints=Just sPoints})) ->
case preview (_grading . _maxPoints) sType of case preview (_grading . _maxPoints) sType of
Just maxPoints Just maxPoints
| maxPoints /= 0 -> | maxPoints /= 0 -> textCell $ textPercent sPoints maxPoints
let percent = sPoints / maxPoints
in textCell $ textPercent $ realToFrac percent
_other -> mempty _other -> mempty
_other -> mempty _other -> mempty
] ]

View File

@ -12,7 +12,7 @@ import qualified Data.Map as Map
import Utils.Lens import Utils.Lens
data OccurrenceScheduleKind = ScheduleKindWeekly data OccurrenceScheduleKind = ScheduleKindWeekly
deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic, Typeable) deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic, Typeable)
@ -36,7 +36,7 @@ embedRenderMessage ''UniWorX ''OccurrenceExceptionKind id
occurrencesAForm :: PathPiece ident => ident -> Maybe Occurrences -> AForm Handler Occurrences occurrencesAForm :: PathPiece ident => ident -> Maybe Occurrences -> AForm Handler Occurrences
occurrencesAForm (toPathPiece -> miIdent') mPrev = wFormToAForm $ do occurrencesAForm (toPathPiece -> miIdent') mPrev = wFormToAForm $ do
Just cRoute <- getCurrentRoute Just cRoute <- getCurrentRoute
let let
scheduled :: AForm Handler (Set OccurrenceSchedule) scheduled :: AForm Handler (Set OccurrenceSchedule)
scheduled = Set.fromList <$> massInputAccumA scheduled = Set.fromList <$> massInputAccumA
@ -89,13 +89,13 @@ occurrencesAForm (toPathPiece -> miIdent') mPrev = wFormToAForm $ do
miAdd' nudge submitView = over (mapped . mapped . _2) (\addWidget -> $(widgetFile "widgets/occurrence/form/except-add")) . renderAForm FormStandard . wFormToAForm $ do miAdd' nudge submitView = over (mapped . mapped . _2) (\addWidget -> $(widgetFile "widgets/occurrence/form/except-add")) . renderAForm FormStandard . wFormToAForm $ do
newExc <- multiActionW newExc <- multiActionW
(Map.fromList [ ( ExceptionKindOccur (Map.fromList [ ( ExceptionKindOccur
, ExceptOccurr , ExceptOccur
<$> apreq dayField (fslI MsgDay & addName (nudge "occur-day")) Nothing <$> apreq dayField (fslI MsgDay & addName (nudge "occur-day")) Nothing
<*> apreq timeFieldTypeTime (fslI MsgOccurrenceStart & addName (nudge "occur-start")) Nothing <*> apreq timeFieldTypeTime (fslI MsgOccurrenceStart & addName (nudge "occur-start")) Nothing
<*> apreq timeFieldTypeTime (fslI MsgOccurrenceEnd & addName (nudge "occur-end")) Nothing <*> apreq timeFieldTypeTime (fslI MsgOccurrenceEnd & addName (nudge "occur-end")) Nothing
) )
, ( ExceptionKindNoOccur , ( ExceptionKindNoOccur
, ExceptNoOccurr , ExceptNoOccur
<$> apreq localTimeField (fslI MsgExceptionNoOccurAt & addName (nudge "no-occur-time")) Nothing <$> apreq localTimeField (fslI MsgExceptionNoOccurAt & addName (nudge "no-occur-time")) Nothing
) )
] ]
@ -104,14 +104,14 @@ occurrencesAForm (toPathPiece -> miIdent') mPrev = wFormToAForm $ do
return $ newExc <&> \newExc' oldExcs -> if return $ newExc <&> \newExc' oldExcs -> if
| newExc' `elem` oldExcs -> FormFailure [mr MsgExceptionExists] | newExc' `elem` oldExcs -> FormFailure [mr MsgExceptionExists]
| otherwise -> FormSuccess $ pure newExc' | otherwise -> FormSuccess $ pure newExc'
miCell' :: OccurrenceException -> Widget miCell' :: OccurrenceException -> Widget
miCell' ExceptOccurr{..} = do miCell' ExceptOccur{..} = do
exceptStart' <- formatTime SelFormatDateTime (LocalTime exceptDay exceptStart) exceptStart' <- formatTime SelFormatDateTime (LocalTime exceptDay exceptStart)
exceptEnd' <- formatTime SelFormatTime exceptEnd exceptEnd' <- formatTime SelFormatTime exceptEnd
$(widgetFile "widgets/occurrence/form/except-occur") $(widgetFile "widgets/occurrence/form/except-occur")
miCell' ExceptNoOccurr{..} = do miCell' ExceptNoOccur{..} = do
exceptTime' <- formatTime SelFormatDateTime exceptTime exceptTime' <- formatTime SelFormatDateTime exceptTime
$(widgetFile "widgets/occurrence/form/except-no-occur") $(widgetFile "widgets/occurrence/form/except-no-occur")

View File

@ -256,11 +256,11 @@ occurrencesCell (normalizeOccurrences -> Occurrences{..}) = cell $ do
scheduleEnd' <- formatTime SelFormatTime scheduleEnd scheduleEnd' <- formatTime SelFormatTime scheduleEnd
$(widgetFile "widgets/occurrence/cell/weekly") $(widgetFile "widgets/occurrence/cell/weekly")
occurrencesExceptions' = flip map (Set.toList occurrencesExceptions) $ \case occurrencesExceptions' = flip map (Set.toList occurrencesExceptions) $ \case
ExceptOccurr{..} -> do ExceptOccur{..} -> do
exceptStart' <- formatTime SelFormatDateTime (LocalTime exceptDay exceptStart) exceptStart' <- formatTime SelFormatDateTime (LocalTime exceptDay exceptStart)
exceptEnd' <- formatTime SelFormatTime exceptStart exceptEnd' <- formatTime SelFormatTime exceptStart
$(widgetFile "widgets/occurrence/cell/except-occurr") $(widgetFile "widgets/occurrence/cell/except-occur")
ExceptNoOccurr{..} -> do ExceptNoOccur{..} -> do
exceptTime' <- formatTime SelFormatDateTime exceptTime exceptTime' <- formatTime SelFormatDateTime exceptTime
$(widgetFile "widgets/occurrence/cell/except-no-occurr") $(widgetFile "widgets/occurrence/cell/except-no-occur")
$(widgetFile "widgets/occurrence/cell") $(widgetFile "widgets/occurrence/cell")

View File

@ -166,14 +166,14 @@ deriveJSON defaultOptions
, sumEncoding = TaggedObject "repeat" "schedule" , sumEncoding = TaggedObject "repeat" "schedule"
} ''OccurrenceSchedule } ''OccurrenceSchedule
data OccurrenceException = ExceptOccurr data OccurrenceException = ExceptOccur
{ exceptDay :: Day { exceptDay :: Day
, exceptStart :: TimeOfDay , exceptStart :: TimeOfDay
, exceptEnd :: TimeOfDay , exceptEnd :: TimeOfDay
} }
| ExceptNoOccurr | ExceptNoOccur
{ exceptTime :: LocalTime { exceptTime :: LocalTime
} }
deriving (Eq, Ord, Read, Show, Generic, Typeable) deriving (Eq, Ord, Read, Show, Generic, Typeable)
deriveJSON defaultOptions deriveJSON defaultOptions

View File

@ -2,12 +2,13 @@ module Utils
( module Utils ( module Utils
) where ) where
import ClassyPrelude.Yesod hiding (foldlM) import ClassyPrelude.Yesod hiding (foldlM, Proxy)
-- import Data.Double.Conversion.Text -- faster implementation for textPercent? -- import Data.Double.Conversion.Text -- faster implementation for textPercent?
import qualified Data.Foldable as Fold import qualified Data.Foldable as Fold
import Data.Foldable as Utils (foldlM, foldrM) import Data.Foldable as Utils (foldlM, foldrM)
import Data.Monoid (Sum(..)) import Data.Monoid (Sum(..))
import Data.Proxy
import Data.CaseInsensitive (CI) import Data.CaseInsensitive (CI)
import qualified Data.CaseInsensitive as CI import qualified Data.CaseInsensitive as CI
@ -67,7 +68,7 @@ import qualified Crypto.Saltine.Class as Saltine
import qualified Crypto.Data.PKCS7 as PKCS7 import qualified Crypto.Data.PKCS7 as PKCS7
import Data.Fixed import Data.Fixed
import Data.Ratio ((%)) -- import Data.Ratio ((%))
import Data.Binary (Binary) import Data.Binary (Binary)
import qualified Data.Binary as Binary import qualified Data.Binary as Binary
@ -309,15 +310,28 @@ instance {-# OVERLAPPABLE #-} Show a => DisplayAble a where -- The easy way out
display = pack . show display = pack . show
-} -}
textPercent :: Real a => a -> Text -- slow, maybe use Data.Double.Conversion.Text.toFixed instead? -- | Convert `part` and `whole` into percentage including symbol
textPercent x = lz <> pack (show rx) <> "%" -- showing trailing zeroes and to decimal digits
where textPercent :: Real a => a -> a -> Text
rx :: Centi textPercent = textPercent' False 2
rx = realToFrac (x * 100)
lz = if rx < 10.0 then "0" else "" -- | Convert `part` and `whole` into percentage including symbol
-- `trailZero` shows trailing Zeros, `precision` is number of decimal digits
textPercent' :: Real a => Bool -> Int -> a -> a -> Text
textPercent' trailZero precision part whole
| precision == 0 = showPercent (frac :: Uni)
| precision == 1 = showPercent (frac :: Deci)
| precision == 2 = showPercent (frac :: Centi)
| precision == 3 = showPercent (frac :: Milli)
| precision == 4 = showPercent (frac :: Micro)
| otherwise = showPercent (frac :: Pico)
where
frac :: forall a . HasResolution a => Fixed a
frac = MkFixed $ round $ (* (fromInteger $ resolution (Proxy :: Proxy a))) $ (100*) $ toRational part / toRational whole
showPercent :: HasResolution a => Fixed a -> Text
showPercent f = pack $ showFixed trailZero f <> "%"
textPercentInt :: Integral a => a -> a -> Text -- slow, maybe use Data.Double.Conversion.Text.toFixed instead?
textPercentInt part whole = textPercent $ fromIntegral part % fromIntegral whole
-- | Convert number of bytes to human readable format -- | Convert number of bytes to human readable format
textBytes :: Integral a => a -> Text textBytes :: Integral a => a -> Text

View File

@ -168,6 +168,11 @@ inputReadonly = addAttr "readonly" ""
addAutosubmit :: FieldSettings site -> FieldSettings site addAutosubmit :: FieldSettings site -> FieldSettings site
addAutosubmit = addAttr "uw-auto-submit-input" "" addAutosubmit = addAttr "uw-auto-submit-input" ""
-- | Asynchronous Submit, e.g. use with forms in modals
asyncSubmitAttr :: (Text,Text)
asyncSubmitAttr = ("uw-async-form", "")
------------------------------------------------ ------------------------------------------------
-- Unique Form Identifiers to avoid accidents -- -- Unique Form Identifiers to avoid accidents --
------------------------------------------------ ------------------------------------------------

View File

@ -137,6 +137,6 @@ makeLenses_ ''UTCTime
class HasInstanceID s a | s -> a where class HasInstanceID s a | s -> a where
instanceID :: Lens' s a instanceID :: Lens' s a
class HasJSONWebKeySet s a | s -> a where class HasJSONWebKeySet s a | s -> a where
jsonWebKeySet :: Lens' s a jsonWebKeySet :: Lens' s a

View File

@ -21,7 +21,7 @@ import Data.Time.Calendar.WeekDate
normalizeOccurrences :: Occurrences -> Occurrences normalizeOccurrences :: Occurrences -> Occurrences
-- ^ -- ^
-- --
-- - Removes unnecessary exceptions -- - Removes unnecessary exceptions
-- - Merges overlapping schedules -- - Merges overlapping schedules
@ -57,7 +57,7 @@ normalizeOccurrences initial
exceptions <- view _occurrencesExceptions exceptions <- view _occurrencesExceptions
forM_ exceptions $ \case forM_ exceptions $ \case
needle@ExceptNoOccurr{..} -> do needle@ExceptNoOccur{..} -> do
let LocalTime{..} = exceptTime let LocalTime{..} = exceptTime
(_, _, toEnum . (`mod` 7) -> localWeekDay) = toWeekDate localDay (_, _, toEnum . (`mod` 7) -> localWeekDay) = toWeekDate localDay
needed <- views _occurrencesScheduled . any $ \case needed <- views _occurrencesScheduled . any $ \case
@ -68,10 +68,10 @@ normalizeOccurrences initial
] ]
unless needed $ unless needed $
throwE =<< asks (over _occurrencesExceptions $ Set.delete needle) throwE =<< asks (over _occurrencesExceptions $ Set.delete needle)
needle@ExceptOccurr{..} -> do needle@ExceptOccur{..} -> do
let (_, _, toEnum . (`mod` 7) -> localWeekDay) = toWeekDate exceptDay let (_, _, toEnum . (`mod` 7) -> localWeekDay) = toWeekDate exceptDay
-- | Does this ExceptNoOccur target within needle? -- | Does this ExceptNoOccur target within needle?
withinNeedle ExceptNoOccurr{..} = LocalTime exceptDay exceptStart <= exceptTime withinNeedle ExceptNoOccur{..} = LocalTime exceptDay exceptStart <= exceptTime
&& exceptTime <= LocalTime exceptDay exceptEnd && exceptTime <= LocalTime exceptDay exceptEnd
withinNeedle _ = False withinNeedle _ = False
needed <- views _occurrencesScheduled . none $ \case needed <- views _occurrencesScheduled . none $ \case

View File

@ -48,4 +48,6 @@ extra-deps:
- filepath-1.4.2 - filepath-1.4.2
- haskell-src-exts-util-0.2.1.2
resolver: lts-10.5 resolver: lts-10.5

View File

@ -45,7 +45,7 @@
<tr .table__row .table__row--head> <tr .table__row .table__row--head>
<th .table__th rowspan=2>_{MsgCorrector} <th .table__th rowspan=2>_{MsgCorrector}
<th .table__th colspan=2>_{MsgGenericAll} <th .table__th colspan=2>_{MsgGenericAll}
<th .table__th>_{MsgCorProportion} <th .table__th rowspan=2>_{MsgCorDeficitProportion}
<th .table__th colspan=3>_{MsgCorrectionTime} <th .table__th colspan=3>_{MsgCorrectionTime}
$forall shn <- sheetNames $forall shn <- sheetNames
<th .table__th colspan=5>#{shn} <th .table__th colspan=5>#{shn}
@ -53,7 +53,6 @@
<tr .table__row .table__row--head> <tr .table__row .table__row--head>
<th .table__th>_{MsgNrSubmissionsTotal} <th .table__th>_{MsgNrSubmissionsTotal}
<th .table__th>_{MsgNrSubmissionsNotCorrected} <th .table__th>_{MsgNrSubmissionsNotCorrected}
<th .table__th>_{MsgCorDeficit}
<th .table__th>_{MsgGenericMin} <th .table__th>_{MsgGenericMin}
<th .table__th>_{MsgGenericAvg} <th .table__th>_{MsgGenericAvg}
<th .table__th>_{MsgGenericMax} <th .table__th>_{MsgGenericMax}
@ -63,24 +62,33 @@
<th .table__th>_{MsgGenericNumChange} <th .table__th>_{MsgGenericNumChange}
<th .table__th>_{MsgNrSubmissionsNotCorrectedShort} <th .table__th>_{MsgNrSubmissionsNotCorrectedShort}
<th .table__th>_{MsgGenericAvg} <th .table__th>_{MsgGenericAvg}
$forall (CorrectionInfo{ciCorrector, ciSubmissions, ciCorrected, ciMin, ciTot, ciMax}) <- Map.elems corrMap $forall (CorrectionInfo{ciCorrector, ciSubmissions=ciSubmissionsNr, ciCorrected, ciMin, ciTot, ciMax}) <- Map.elems corrMap
$with (nameW,loadM) <- getCorrector ciCorrector $with (nameW,loadM) <- getCorrector ciCorrector
<tr .table__row> <tr .table__row>
<td .table__td>^{nameW} <td .table__td>^{nameW}
<td .table__td>#{ciSubmissions} <td .table__td>#{ciSubmissionsNr}
<td .table__td .heated style="--hotness: #{heat ciSubmissions ciCorrected}">#{ciSubmissions - ciCorrected} $with total <- ciSubmissions corrMapSum
$if total > 0
\ (#{textPercent' True 0 ciSubmissionsNr total})
<td .table__td .heated style="--hotness: #{heat ciSubmissionsNr ciCorrected}">#{ciSubmissionsNr - ciCorrected}
<td .table__td> <td .table__td>
$maybe deficit <- getCorrDeficit ciCorrector $maybe deficit <- getCorrDeficit ciCorrector
#{display deficit} #{display deficit}
<td .table__td>#{showDiffDays ciMin} <td .table__td>#{showDiffDays ciMin}
<td .table__td>#{showAvgsDays ciTot ciCorrected} <td .table__td>#{showAvgsDays ciTot ciCorrected}
<td .table__td>#{showDiffDays ciMax} <td .table__td>#{showDiffDays ciMax}
$forall shn <- sheetNames $forall (shn, CorrectionInfo{ciSubmissions=sheetSubmissionsNr}) <- Map.toList sheetMap
<td .table__td> <td .table__td>
$maybe SheetCorrector{sheetCorrectorLoad, sheetCorrectorState} <- Map.lookup shn loadM $maybe SheetCorrector{sheetCorrectorLoad, sheetCorrectorState} <- Map.lookup shn loadM
#{showCompactCorrectorLoad sheetCorrectorLoad sheetCorrectorState} #{showCompactCorrectorLoad sheetCorrectorLoad sheetCorrectorState}
$if sheetCorrectorState == CorrectorNormal
$maybe Load{byProportion=total} <- Map.lookup shn sheetLoad
$if total > 0
\ (#{textPercent' True 0 (byProportion sheetCorrectorLoad) total})
$maybe CorrectionInfo{ciSubmissions,ciCorrected,ciTot} <- getCorrSheetStatus ciCorrector shn $maybe CorrectionInfo{ciSubmissions,ciCorrected,ciTot} <- getCorrSheetStatus ciCorrector shn
<td .table__td>#{ciSubmissions} <td .table__td>#{ciSubmissions}
$if sheetSubmissionsNr > 0
\ (#{textPercent' True 0 ciSubmissions sheetSubmissionsNr})
$maybe nrNew <- getCorrNewAssignment ciCorrector shn $maybe nrNew <- getCorrNewAssignment ciCorrector shn
$# <td .table__td>#{ciAssigned} `ciSubmissions` is here always identical to `ciAssigned` and also works for `ciCorrector == Nothing`. ciAssigned only useful in aggregate maps like `sheetMap` $# <td .table__td>#{ciAssigned} `ciSubmissions` is here always identical to `ciAssigned` and also works for `ciCorrector == Nothing`. ciAssigned only useful in aggregate maps like `sheetMap`
<td .table__td .alert-info>(+#{nrNew}) <td .table__td .alert-info>(+#{nrNew})
@ -95,9 +103,17 @@
<td .table__td> <td .table__td>
$if 0 < length sheetNames $if 0 < length sheetNames
<tr .table__row> <tr .table__row>
<td colspan=6> <td .table__th>Σ
$with ciSubmissionsNr <- ciSubmissions corrMapSum
$with ciCorrectedNr <- ciCorrected corrMapSum
<td .table__th>#{ciSubmissionsNr}
<td .table__td .heated style="--hotness: #{heat ciSubmissionsNr ciCorrectedNr}">#{ciSubmissionsNr - ciCorrectedNr}
<td .table__th>#{ciCorrected corrMapSum}
<td .table__th>#{showDiffDays (ciMin corrMapSum)}
<td .table__th>#{showAvgsDays (ciTot corrMapSum) (ciCorrected corrMapSum)}
<td .table__th>#{showDiffDays (ciMax corrMapSum)}
$forall shn <- sheetNames $forall shn <- sheetNames
<td .table__td>#{getLoadSum shn} <td .table__th>#{getLoadSum shn}
<td .table__td colspan=4>^{simpleLinkI (SomeMessage MsgMenuCorrectorsChange) (CSheetR tid ssh csh shn SCorrR)} <td .table__td colspan=4>^{simpleLinkI (SomeMessage MsgMenuCorrectorsChange) (CSheetR tid ssh csh shn SCorrR)}
^{btnWdgt} ^{btnWdgt}
<div> <div>

View File

@ -19,7 +19,7 @@ $#
$with Sum pacv <- summary ^. _achievedPasses $with Sum pacv <- summary ^. _achievedPasses
<td .table__td> <td .table__td>
$if pmax > 0 $if pmax > 0
#{textPercentInt pacv pmax} #{textPercent pacv pmax}
<td .table__td> <td .table__td>
#{display pacv} / #{display pmax} #{display pacv} / #{display pmax}
$else $else
@ -35,7 +35,7 @@ $#
$with Sum pacv <- summary ^. _achievedPoints $with Sum pacv <- summary ^. _achievedPoints
<td .table__td> <td .table__td>
$if pmax > 0 $if pmax > 0
#{textPercent $ realToFrac $ pacv / pmax} #{textPercent pacv pmax}
<td .table__td> <td .table__td>
#{display pacv} / #{display pmax} #{display pacv} / #{display pmax}
$if ((summary ^. _numMarkedPoints) /= (summary ^. _numSheets)) $if ((summary ^. _numMarkedPoints) /= (summary ^. _numSheets))

View File

@ -1,11 +0,0 @@
$newline never
<table>
<tbody>
$forall coord <- review liveCoords lLength
<tr .massinput__cell>
^{cellWdgts ! coord}
<td>
^{fvInput (delButtons ! coord)}
<tfoot>
<tr .massinput__cell.massinput__cell--add>
^{addWdgts ! (0, 0)}

View File

@ -1,5 +0,0 @@
$newline never
<td colspan=2>
^{addWidget}
<td>
^{fvInput submitView}

View File

@ -0,0 +1,2 @@
$newline never
_{MsgExceptionKindNoOccur}: #{exceptTime'}

View File

@ -0,0 +1,2 @@
$newline never
_{MsgExceptionKindOccur}: #{exceptStart'}#{exceptEnd'}

View File

@ -605,7 +605,7 @@ fillDb = do
, tutorialCapacity = Just 30 , tutorialCapacity = Just 30
, tutorialRoom = "Hilbert-Raum" , tutorialRoom = "Hilbert-Raum"
, tutorialTime = Occurrences , tutorialTime = Occurrences
{ occurrencesScheduled = Set.singleton $ ScheduleWeekly Tuesday (TimeOfDay 10 15 00) (TimeOfDay 12 00 00) { occurrencesScheduled = Set.singleton $ ScheduleWeekly Tuesday (TimeOfDay 10 15 00) (TimeOfDay 12 00 00)
, occurrencesExceptions = Set.empty , occurrencesExceptions = Set.empty
} }
, tutorialRegGroup = Just "tutorium" , tutorialRegGroup = Just "tutorium"

View File

@ -38,6 +38,10 @@ instance Arbitrary TutorialR where
arbitrary = genericArbitrary arbitrary = genericArbitrary
shrink = genericShrink shrink = genericShrink
instance Arbitrary ExamR where
arbitrary = genericArbitrary
shrink = genericShrink
instance Arbitrary (Route UniWorX) where instance Arbitrary (Route UniWorX) where
arbitrary = genericArbitrary arbitrary = genericArbitrary
shrink = genericShrink shrink = genericShrink

View File

@ -26,7 +26,7 @@ import Time.Types (WeekDay(..))
instance (Arbitrary a, MonoFoldable a) => Arbitrary (NonNull a) where instance (Arbitrary a, MonoFoldable a) => Arbitrary (NonNull a) where
arbitrary = arbitrary `suchThatMap` fromNullable arbitrary = arbitrary `suchThatMap` fromNullable
instance Arbitrary Season where instance Arbitrary Season where
arbitrary = genericArbitrary arbitrary = genericArbitrary
shrink = genericShrink shrink = genericShrink
@ -71,7 +71,7 @@ instance Arbitrary SheetGradeSummary where
instance Arbitrary SheetGroup where instance Arbitrary SheetGroup where
arbitrary = genericArbitrary arbitrary = genericArbitrary
shrink = genericShrink shrink = genericShrink
instance Arbitrary SheetTypeSummary where instance Arbitrary SheetTypeSummary where
arbitrary = genericArbitrary arbitrary = genericArbitrary
shrink = genericShrink shrink = genericShrink
@ -79,7 +79,7 @@ instance Arbitrary SheetTypeSummary where
instance Arbitrary SheetFileType where instance Arbitrary SheetFileType where
arbitrary = genericArbitrary arbitrary = genericArbitrary
shrink = genericShrink shrink = genericShrink
instance Arbitrary SubmissionFileType where instance Arbitrary SubmissionFileType where
arbitrary = genericArbitrary arbitrary = genericArbitrary
shrink = genericShrink shrink = genericShrink
@ -147,7 +147,7 @@ instance Arbitrary AuthTag where
shrink = genericShrink shrink = genericShrink
instance CoArbitrary AuthTag where instance CoArbitrary AuthTag where
coarbitrary = genericCoarbitrary coarbitrary = genericCoarbitrary
instance Arbitrary AuthTagActive where instance Arbitrary AuthTagActive where
arbitrary = AuthTagActive <$> arbitrary arbitrary = AuthTagActive <$> arbitrary
shrink = genericShrink shrink = genericShrink
@ -176,7 +176,7 @@ instance Arbitrary AuthenticationMode where
authPWHash = unsafePerformIO . fmap decodeUtf8 $ makePasswordWith pwHashAlgorithm pw (pwHashStrength `div` 2) authPWHash = unsafePerformIO . fmap decodeUtf8 $ makePasswordWith pwHashAlgorithm pw (pwHashStrength `div` 2)
return $ AuthPWHash{..} return $ AuthPWHash{..}
] ]
shrink AuthLDAP = [] shrink AuthLDAP = []
shrink (AuthPWHash _) = [AuthLDAP] shrink (AuthPWHash _) = [AuthLDAP]
@ -195,18 +195,18 @@ instance Arbitrary Html where
instance Arbitrary WeekDay where instance Arbitrary WeekDay where
arbitrary = oneof $ map pure [minBound..maxBound] arbitrary = oneof $ map pure [minBound..maxBound]
instance Arbitrary OccurenceSchedule where instance Arbitrary OccurrenceSchedule where
arbitrary = genericArbitrary arbitrary = genericArbitrary
shrink = genericShrink shrink = genericShrink
instance Arbitrary OccurenceException where instance Arbitrary OccurrenceException where
arbitrary = genericArbitrary arbitrary = genericArbitrary
shrink = genericShrink shrink = genericShrink
instance Arbitrary Occurences where instance Arbitrary Occurrences where
arbitrary = genericArbitrary arbitrary = genericArbitrary
shrink = genericShrink shrink = genericShrink
spec :: Spec spec :: Spec
spec = do spec = do