Merge branch 'master' of gitlab.cip.ifi.lmu.de:jost/UniWorX
This commit is contained in:
commit
c3fc8a218a
16
.vscode/tasks.json
vendored
16
.vscode/tasks.json
vendored
@ -28,8 +28,20 @@
|
|||||||
"focus": false,
|
"focus": false,
|
||||||
"panel": "dedicated",
|
"panel": "dedicated",
|
||||||
"showReuseMessage": false
|
"showReuseMessage": false
|
||||||
},
|
}
|
||||||
"problemMatcher": []
|
},
|
||||||
|
{
|
||||||
|
"label": "test",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "./test.sh",
|
||||||
|
"group": "test",
|
||||||
|
"presentation": {
|
||||||
|
"echo": true,
|
||||||
|
"reveal": "always",
|
||||||
|
"focus": true,
|
||||||
|
"panel": "dedicated",
|
||||||
|
"showReuseMessage": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -1,3 +1,10 @@
|
|||||||
|
* Version 09.11.2018
|
||||||
|
|
||||||
|
Bugfix: Zahlreiche Knöpfe/Formulare funktionieren wieder bei eingeschaltetem Javascript
|
||||||
|
|
||||||
|
Verschiedene Verbesserungen für Korrektoren
|
||||||
|
|
||||||
|
|
||||||
* Version 19.10.2018
|
* Version 19.10.2018
|
||||||
|
|
||||||
Benutzer können sich in der Testphase komplett selbst löschen
|
Benutzer können sich in der Testphase komplett selbst löschen
|
||||||
|
|||||||
@ -274,6 +274,16 @@ RatingUpdated: Korrektur gespeichert
|
|||||||
RatingDeleted: Korrektur zurückgesetzt
|
RatingDeleted: Korrektur zurückgesetzt
|
||||||
RatingFilesUpdated: Korrigierte Dateien überschrieben
|
RatingFilesUpdated: Korrigierte Dateien überschrieben
|
||||||
|
|
||||||
|
RatingNotUnicode uexc@UnicodeException: Bewertungsdatei nicht in UTF-8 kodiert: #{tshow uexc}
|
||||||
|
RatingMissingSeparator: Could not split rating header from comments
|
||||||
|
RatingMultiple: Encountered multiple point values in rating
|
||||||
|
RatingInvalid parseErr@String: Failed to parse rating point value #{parseErr}
|
||||||
|
RatingFileIsDirectory: We do not expect this to, it's included for totality
|
||||||
|
RatingNegative: Rating points must be non-negative
|
||||||
|
RatingExceedsMax: Rating point must not exceed maximum points
|
||||||
|
RatingNotExpected: Rating not expected
|
||||||
|
RatingBinaryExpected: Rating must be 0 or 1
|
||||||
|
|
||||||
NoTableContent: Kein Tabelleninhalt
|
NoTableContent: Kein Tabelleninhalt
|
||||||
NoUpcomingSheetDeadlines: Keine anstehenden Übungsblätter
|
NoUpcomingSheetDeadlines: Keine anstehenden Übungsblätter
|
||||||
|
|
||||||
|
|||||||
@ -220,14 +220,16 @@ embedRenderMessage ''UniWorX ''NotificationTrigger $ ("NotificationTrigger" <>)
|
|||||||
embedRenderMessage ''UniWorX ''StudyFieldType id
|
embedRenderMessage ''UniWorX ''StudyFieldType id
|
||||||
embedRenderMessage ''UniWorX ''SheetFileType id
|
embedRenderMessage ''UniWorX ''SheetFileType id
|
||||||
embedRenderMessage ''UniWorX ''CorrectorState id
|
embedRenderMessage ''UniWorX ''CorrectorState id
|
||||||
|
embedRenderMessage ''UniWorX ''RatingException id
|
||||||
embedRenderMessage ''UniWorX ''SheetGrading ("SheetGrading" <>)
|
embedRenderMessage ''UniWorX ''SheetGrading ("SheetGrading" <>)
|
||||||
embedRenderMessage ''UniWorX ''SheetType ("SheetType" <>)
|
|
||||||
|
|
||||||
newtype SheetTypeComplete = SheetTypeComplete SheetType
|
newtype SheetTypeHeader = SheetTypeHeader SheetType
|
||||||
instance RenderMessage UniWorX (SheetTypeComplete) where
|
embedRenderMessageVariant ''UniWorX ''SheetTypeHeader ("SheetType" <>)
|
||||||
renderMessage foundation ls (SheetTypeComplete sheetType) = case sheetType of
|
|
||||||
NotGraded -> mr NotGraded
|
instance RenderMessage UniWorX (SheetType) where
|
||||||
other -> mr (grading other) <> ", " <> mr other
|
renderMessage foundation ls sheetType = case sheetType of
|
||||||
|
NotGraded -> mr $ SheetTypeHeader NotGraded
|
||||||
|
other -> mr (grading other) <> ", " <> mr (SheetTypeHeader other)
|
||||||
where
|
where
|
||||||
mr :: RenderMessage UniWorX msg => msg -> Text
|
mr :: RenderMessage UniWorX msg => msg -> Text
|
||||||
mr = renderMessage foundation ls
|
mr = renderMessage foundation ls
|
||||||
|
|||||||
@ -500,26 +500,31 @@ postCorrectionR tid ssh csh shn cid = do
|
|||||||
case corrResult of
|
case corrResult of
|
||||||
FormMissing -> return ()
|
FormMissing -> return ()
|
||||||
FormFailure errs -> mapM_ (addMessage Error . toHtml) errs
|
FormFailure errs -> mapM_ (addMessage Error . toHtml) errs
|
||||||
FormSuccess (rated, ratingPoints', ratingComment') -> do
|
FormSuccess (rated, ratingPoints', ratingComment')
|
||||||
runDBJobs $ do
|
| errs <- validateRating sheetType Rating'
|
||||||
uid <- liftHandlerT requireAuthId
|
{ ratingPoints=ratingPoints'
|
||||||
now <- liftIO getCurrentTime
|
, ratingComment=ratingComment'
|
||||||
|
, ratingTime=Nothing
|
||||||
update sub [ SubmissionRatingBy =. (uid <$ guard rated)
|
}
|
||||||
-- SJ: I don't think we need to update AssignedTime here, since this is just for correction upload
|
-> mapM_ (addMessageI Error) errs
|
||||||
-- , SubmissionRatingAssigned +=. (Just now) -- TODO: Should submissionRatingAssigned change here if userId changes?
|
| otherwise -> do
|
||||||
, SubmissionRatingTime =. (now <$ guard rated)
|
runDBJobs $ do
|
||||||
, SubmissionRatingPoints =. ratingPoints'
|
uid <- liftHandlerT requireAuthId
|
||||||
, SubmissionRatingComment =. ratingComment'
|
now <- liftIO getCurrentTime
|
||||||
]
|
|
||||||
|
update sub [ SubmissionRatingBy =. Just uid
|
||||||
|
, SubmissionRatingTime =. (now <$ guard rated)
|
||||||
|
, SubmissionRatingPoints =. ratingPoints'
|
||||||
|
, SubmissionRatingComment =. ratingComment'
|
||||||
|
]
|
||||||
|
|
||||||
addMessageI Success $ bool MsgRatingDeleted MsgRatingUpdated rated
|
addMessageI Success $ bool MsgRatingDeleted MsgRatingUpdated rated
|
||||||
|
|
||||||
when (rated && isNothing submissionRatingTime) $ do
|
when (rated && isNothing submissionRatingTime) $ do
|
||||||
$logDebugS "CorrectionR" [st|Rated #{tshow sub}|]
|
$logDebugS "CorrectionR" [st|Rated #{tshow sub}|]
|
||||||
queueDBJob . JobQueueNotification $ NotificationSubmissionRated sub
|
queueDBJob . JobQueueNotification $ NotificationSubmissionRated sub
|
||||||
|
|
||||||
redirect $ CSubmissionR tid ssh csh shn cid CorrectionR
|
redirect $ CSubmissionR tid ssh csh shn cid CorrectionR
|
||||||
|
|
||||||
case uploadResult of
|
case uploadResult of
|
||||||
FormMissing -> return ()
|
FormMissing -> return ()
|
||||||
|
|||||||
@ -162,7 +162,7 @@ getSheetListR tid ssh csh = do
|
|||||||
, sortable (Just "submission-until") (i18nCell MsgSheetActiveTo)
|
, sortable (Just "submission-until") (i18nCell MsgSheetActiveTo)
|
||||||
$ \(Entity _ Sheet{..}, _, _) -> timeCell sheetActiveTo
|
$ \(Entity _ Sheet{..}, _, _) -> timeCell sheetActiveTo
|
||||||
, sortable Nothing (i18nCell MsgSheetType)
|
, sortable Nothing (i18nCell MsgSheetType)
|
||||||
$ \(Entity _ Sheet{..}, _, _) -> i18nCell $ SheetTypeComplete sheetType
|
$ \(Entity _ Sheet{..}, _, _) -> i18nCell sheetType
|
||||||
, sortable Nothing (i18nCell MsgSubmission)
|
, sortable Nothing (i18nCell MsgSubmission)
|
||||||
$ \(Entity _ Sheet{..}, _, mbSub) -> case mbSub of
|
$ \(Entity _ Sheet{..}, _, mbSub) -> case mbSub of
|
||||||
Nothing -> mempty
|
Nothing -> mempty
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
module Handler.Utils.Rating
|
module Handler.Utils.Rating
|
||||||
( Rating(..), Rating'(..)
|
( Rating(..), Rating'(..)
|
||||||
|
, validateRating
|
||||||
, getRating
|
, getRating
|
||||||
, formatRating
|
, formatRating
|
||||||
, ratingFile
|
, ratingFile
|
||||||
@ -15,12 +16,10 @@ module Handler.Utils.Rating
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
|
|
||||||
import Text.PrettyPrint.Leijen.Text hiding ((<$>))
|
import Text.PrettyPrint.Leijen.Text hiding ((<$>))
|
||||||
|
|
||||||
import Control.Monad.Trans.Maybe
|
import Control.Monad.Trans.Maybe
|
||||||
|
|
||||||
import Data.Text (Text)
|
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
import qualified Data.Text.Encoding as Text
|
import qualified Data.Text.Encoding as Text
|
||||||
import Data.Text.Encoding.Error (UnicodeException(..))
|
import Data.Text.Encoding.Error (UnicodeException(..))
|
||||||
@ -35,9 +34,6 @@ import qualified Data.ByteString.Lazy as Lazy.ByteString
|
|||||||
|
|
||||||
import Text.Read (readEither)
|
import Text.Read (readEither)
|
||||||
|
|
||||||
import GHC.Generics (Generic)
|
|
||||||
import Data.Typeable (Typeable)
|
|
||||||
|
|
||||||
import System.FilePath
|
import System.FilePath
|
||||||
import qualified System.FilePath.Cryptographic as FilePath (decrypt)
|
import qualified System.FilePath.Cryptographic as FilePath (decrypt)
|
||||||
|
|
||||||
@ -61,29 +57,19 @@ instance Pretty SheetGrading where
|
|||||||
pretty PassBinary = pretty ( "Bestanden (1) / Nicht bestanden (0)" :: String )
|
pretty PassBinary = pretty ( "Bestanden (1) / Nicht bestanden (0)" :: String )
|
||||||
|
|
||||||
|
|
||||||
data Rating = Rating
|
validateRating :: SheetType -> Rating' -> [RatingException]
|
||||||
{ ratingCourseName :: CourseName
|
validateRating ratingSheetType Rating'{ratingPoints=Just rp, ..}
|
||||||
, ratingSheetName :: SheetName
|
| rp < 0
|
||||||
, ratingCorrectorName :: Maybe Text
|
= [RatingNegative]
|
||||||
, ratingSheetType :: SheetType
|
| NotGraded <- ratingSheetType
|
||||||
, ratingValues :: Rating'
|
= [RatingNotExpected]
|
||||||
} deriving (Read, Show, Eq, Generic, Typeable)
|
| (Just maxPoints ) <- ratingSheetType ^? _grading . _maxPoints
|
||||||
|
, rp > maxPoints
|
||||||
data Rating' = Rating'
|
= [RatingExceedsMax]
|
||||||
{ ratingPoints :: Maybe Points
|
| (Just PassBinary) <- ratingSheetType ^? _grading
|
||||||
, ratingComment :: Maybe Text
|
, not (rp == 0 || rp == 1)
|
||||||
, ratingTime :: Maybe UTCTime
|
= [RatingBinaryExpected]
|
||||||
} deriving (Read, Show, Eq, Generic, Typeable)
|
validateRating _ _ = []
|
||||||
|
|
||||||
data RatingException = RatingNotUnicode UnicodeException -- ^ Rating failed to parse as unicode
|
|
||||||
| RatingMissingSeparator -- ^ Could not split rating header from comments
|
|
||||||
| RatingMultiple -- ^ Encountered multiple point values in rating
|
|
||||||
| RatingInvalid String -- ^ Failed to parse rating point value
|
|
||||||
| RatingFileIsDirectory -- ^ We do not expect this to, it's included for totality
|
|
||||||
deriving (Show, Eq, Generic, Typeable)
|
|
||||||
|
|
||||||
instance Exception RatingException
|
|
||||||
|
|
||||||
|
|
||||||
getRating :: SubmissionId -> YesodDB UniWorX (Maybe Rating)
|
getRating :: SubmissionId -> YesodDB UniWorX (Maybe Rating)
|
||||||
getRating submissionId = runMaybeT $ do
|
getRating submissionId = runMaybeT $ do
|
||||||
|
|||||||
@ -395,7 +395,7 @@ sinkSubmission userId mExists isUpdate = do
|
|||||||
touchSubmission
|
touchSubmission
|
||||||
lift $ deleteWhere [ SubmissionFileId <-. [ sfId | (_, Entity sfId sf) <- collidingFiles, submissionFileIsDeletion sf ] ]
|
lift $ deleteWhere [ SubmissionFileId <-. [ sfId | (_, Entity sfId sf) <- collidingFiles, submissionFileIsDeletion sf ] ]
|
||||||
|
|
||||||
Right (submissionId', Rating'{..}) -> do
|
Right (submissionId', r'@Rating'{..}) -> do
|
||||||
$logDebugS "sinkSubmission" $ tshow submissionId'
|
$logDebugS "sinkSubmission" $ tshow submissionId'
|
||||||
|
|
||||||
unless (submissionId' == submissionId) $ do
|
unless (submissionId' == submissionId) $ do
|
||||||
@ -417,9 +417,12 @@ sinkSubmission userId mExists isUpdate = do
|
|||||||
-- 'ratingTime' is ignored for consistency with 'File's:
|
-- 'ratingTime' is ignored for consistency with 'File's:
|
||||||
--
|
--
|
||||||
-- 'fileModified' is simply stored and never inspected while
|
-- 'fileModified' is simply stored and never inspected while
|
||||||
-- 'submissionChanged' is always set to @now@.
|
-- 'submissionChanged' is always set to @now@.
|
||||||
|
|
||||||
when anyChanges $ do
|
when anyChanges $ do
|
||||||
|
|
||||||
|
Sheet{..} <- lift $ getJust submissionSheet
|
||||||
|
mapM_ throwM $ validateRating sheetType r'
|
||||||
|
|
||||||
touchSubmission
|
touchSubmission
|
||||||
lift $ update submissionId
|
lift $ update submissionId
|
||||||
[ SubmissionRatingPoints =. ratingPoints
|
[ SubmissionRatingPoints =. ratingPoints
|
||||||
|
|||||||
@ -83,9 +83,6 @@ sheetCell crse shn =
|
|||||||
link= CSheetR tid ssh csh shn SShowR
|
link= CSheetR tid ssh csh shn SShowR
|
||||||
in anchorCell link $ display2widget shn
|
in anchorCell link $ display2widget shn
|
||||||
|
|
||||||
sheetTypeCell :: IsDBTable m a => SheetType -> DBCell m a
|
|
||||||
sheetTypeCell sheetType = i18nCell $ SheetTypeComplete sheetType
|
|
||||||
|
|
||||||
submissionCell :: IsDBTable m a => CourseLink -> SheetName -> SubmissionId -> DBCell m a
|
submissionCell :: IsDBTable m a => CourseLink -> SheetName -> SubmissionId -> DBCell m a
|
||||||
submissionCell crse shn sid =
|
submissionCell crse shn sid =
|
||||||
let tid = crse ^. _1
|
let tid = crse ^. _1
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import ClassyPrelude.Yesod as Import hiding (formatTime, derivePersistFieldJS
|
|||||||
import Model as Import
|
import Model as Import
|
||||||
import Model.Types.JSON as Import
|
import Model.Types.JSON as Import
|
||||||
import Model.Migration as Import
|
import Model.Migration as Import
|
||||||
|
import Model.Rating as Import
|
||||||
import Settings as Import
|
import Settings as Import
|
||||||
import Settings.StaticFiles as Import
|
import Settings.StaticFiles as Import
|
||||||
import Yesod.Auth as Import
|
import Yesod.Auth as Import
|
||||||
@ -37,6 +38,7 @@ import GHC.Generics as Import (Generic)
|
|||||||
|
|
||||||
import Data.Hashable as Import
|
import Data.Hashable as Import
|
||||||
import Data.List.NonEmpty as Import (NonEmpty(..))
|
import Data.List.NonEmpty as Import (NonEmpty(..))
|
||||||
|
import Data.Text.Encoding.Error as Import(UnicodeException(..))
|
||||||
|
|
||||||
import Control.Monad.Morph as Import (MFunctor(..))
|
import Control.Monad.Morph as Import (MFunctor(..))
|
||||||
|
|
||||||
|
|||||||
37
src/Model/Rating.hs
Normal file
37
src/Model/Rating.hs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
module Model.Rating where
|
||||||
|
|
||||||
|
import ClassyPrelude.Yesod
|
||||||
|
import Model
|
||||||
|
|
||||||
|
-- import Data.Text (Text)
|
||||||
|
import Data.Text.Encoding.Error (UnicodeException(..))
|
||||||
|
import GHC.Generics (Generic)
|
||||||
|
import Data.Typeable (Typeable)
|
||||||
|
|
||||||
|
|
||||||
|
data Rating = Rating
|
||||||
|
{ ratingCourseName :: CourseName
|
||||||
|
, ratingSheetName :: SheetName
|
||||||
|
, ratingCorrectorName :: Maybe Text
|
||||||
|
, ratingSheetType :: SheetType
|
||||||
|
, ratingValues :: Rating'
|
||||||
|
} deriving (Read, Show, Eq, Generic, Typeable)
|
||||||
|
|
||||||
|
data Rating' = Rating'
|
||||||
|
{ ratingPoints :: Maybe Points
|
||||||
|
, ratingComment :: Maybe Text
|
||||||
|
, ratingTime :: Maybe UTCTime
|
||||||
|
} deriving (Read, Show, Eq, Generic, Typeable)
|
||||||
|
|
||||||
|
data RatingException = RatingNotUnicode UnicodeException -- ^ Rating failed to parse as unicode
|
||||||
|
| RatingMissingSeparator -- ^ Could not split rating header from comments
|
||||||
|
| RatingMultiple -- ^ Encountered multiple point values in rating
|
||||||
|
| RatingInvalid String -- ^ Failed to parse rating point value
|
||||||
|
| RatingFileIsDirectory -- ^ We do not expect this to, it's included for totality
|
||||||
|
| RatingNegative -- ^ Rating points must be non-negative
|
||||||
|
| RatingExceedsMax -- ^ Rating point must not exceed maximum points
|
||||||
|
| RatingNotExpected -- ^ Rating not expected
|
||||||
|
| RatingBinaryExpected -- ^ Rating must be 0 or 1
|
||||||
|
deriving (Show, Eq, Generic, Typeable)
|
||||||
|
|
||||||
|
instance Exception RatingException
|
||||||
@ -97,6 +97,9 @@ CryptoID
|
|||||||
Model.Migration
|
Model.Migration
|
||||||
: Manuelle Datenbank-Migration
|
: Manuelle Datenbank-Migration
|
||||||
|
|
||||||
|
Model.Rating
|
||||||
|
: Types for Submission Ratings that the Database does not depend on, but needed in Foundation
|
||||||
|
|
||||||
Jobs
|
Jobs
|
||||||
: `handleJobs` worker thread handling background jobs
|
: `handleJobs` worker thread handling background jobs
|
||||||
`JobQueueException`
|
`JobQueueException`
|
||||||
|
|||||||
@ -18,7 +18,7 @@ $maybe descr <- sheetDescription sheet
|
|||||||
<dt .deflist__dt>_{MsgSheetSolutionFrom}
|
<dt .deflist__dt>_{MsgSheetSolutionFrom}
|
||||||
<dd .deflist__dd>#{solution}
|
<dd .deflist__dd>#{solution}
|
||||||
<dt .deflist__dt>_{MsgSheetType}
|
<dt .deflist__dt>_{MsgSheetType}
|
||||||
<dd .deflist__dd>_{SheetTypeComplete (sheetType sheet)}
|
<dd .deflist__dd>_{sheetType sheet}
|
||||||
$if CorrectorSubmissions == sheetSubmissionMode sheet
|
$if CorrectorSubmissions == sheetSubmissionMode sheet
|
||||||
<dt .deflist__dt>_{MsgSheetPseudonym}
|
<dt .deflist__dt>_{MsgSheetPseudonym}
|
||||||
<dd .deflist__dd #pseudonym>
|
<dd .deflist__dd #pseudonym>
|
||||||
|
|||||||
Reference in New Issue
Block a user