From b84577984a9d9ed11ce033c35c1583a58af03d6d Mon Sep 17 00:00:00 2001 From: Steffen Jost Date: Thu, 20 Jul 2023 16:00:08 +0000 Subject: [PATCH] chore(lms): WIP V2 Learners --- .../categories/qualification/de-de-formal.msg | 4 +- .../categories/qualification/en-eu.msg | 4 +- src/Handler/LMS/Learners.hs | 47 ++++++++++++------- src/Handler/LMS/Users.hs | 2 +- 4 files changed, 37 insertions(+), 20 deletions(-) diff --git a/messages/uniworx/categories/qualification/de-de-formal.msg b/messages/uniworx/categories/qualification/de-de-formal.msg index d081fdc97..013a76a8a 100644 --- a/messages/uniworx/categories/qualification/de-de-formal.msg +++ b/messages/uniworx/categories/qualification/de-de-formal.msg @@ -61,6 +61,7 @@ TableLmsStatusTooltip mbMonth@(Maybe Int): Zeigt #{maybeToMessage "bis zu " (fma TableLmsStatusDay: Datum letzte Statusänderung E‑Learning TableLmsSuccess: Bestanden TableLmsLock: Gesperrt +TableLmsResetTries: E‑Learning Versuche zurücksetzen LmsStatusBlocked: Durchgefallen wegen zu vieler Fehlversuche LmsStatusExpired: Durchgefallen nach Fristablauf LmsStatusSuccess: E#{nonBreakableDash}Learning bestanden @@ -76,7 +77,8 @@ CsvColumnLmsResetPin: Wird das E-Learning Passwort bei der nächsten Synchronisa CsvColumnLmsDelete: Wird der Identifikator in der E‑Learning Plattform bei der nächsten Synchronisation gelöscht? CsvColumnLmsStaff: Handelt es sich um einen internen Mitarbeiter? (Aus historischen Gründen, wird momentan ignoriert.) CsvColumnLmsSuccess: Zeitstempel der erfolgreichen Teilnahme (UTC) -CsvColumnLmsLock: User was locked by LMS, usually due to too many attempts +CsvColumnLmsResetTries: Anzahl der bisher verbrauchten E‑Learning Prüfungsversuche zurücksetzen +CsvColumnLmsLock: E‑Learning Login gesperrt LmsUserlistInsert: Neuer LMS User LmsUserlistUpdate: LMS User aktualisierung LmsResultInsert: Neues LMS Ergebnis diff --git a/messages/uniworx/categories/qualification/en-eu.msg b/messages/uniworx/categories/qualification/en-eu.msg index 2987413ae..3d3e4a00b 100644 --- a/messages/uniworx/categories/qualification/en-eu.msg +++ b/messages/uniworx/categories/qualification/en-eu.msg @@ -61,6 +61,7 @@ TableLmsStatusTooltip mbMonth: Shows #{maybeToMessage "for up to " (fmap (flip p TableLmsStatusDay: Date of last e‑learning status change TableLmsSuccess: Completed TableLmsLock: Locked +TableLmsResetTries: Reset e‑learning attempts LmsStatusBlocked: Failed after too many attempts LmsStatusExpired: Failed due to expiry LmsStatusSuccess: Passed @@ -76,7 +77,8 @@ CsvColumnLmsResetPin: Will the e#{nonBreakableDash}learning password be reset up CsvColumnLmsDelete: Will the identifier be deleted from the E‑learning platfrom upon next synchronisation? CsvColumnLmsStaff: Is the user an internal staff member? (Legacy, currently ignored) CsvColumnLmsSuccess: Timestamp of successful completion (UTC) -CsvColumnLmsLock: Blockiert durch LMS, üblicherweise wegen zu vieler Fehlversuche +CsvColumnLmsResetTries: Reset number of used up e‑learning exam attempts +CsvColumnLmsLock: E‑learning login is not permitted LmsUserlistInsert: New LMS user LmsUserlistUpdate: Update of LMS user LmsResultInsert: New LMS result diff --git a/src/Handler/LMS/Learners.hs b/src/Handler/LMS/Learners.hs index 219f928ac..e27f8fde5 100644 --- a/src/Handler/LMS/Learners.hs +++ b/src/Handler/LMS/Learners.hs @@ -27,19 +27,22 @@ import qualified Database.Esqueleto.Utils as E data LmsUserTableCsv = LmsUserTableCsv -- for csv export only { csvLUTident :: LmsIdent , csvLUTpin :: Text - , csvLUTresetPin, csvLUTdelete, csvLUTstaff :: LmsBool + , csvLUTresetPin, csvLUTdelete, csvLUTstaff -- V1 + , csvLUTresetTries, csvLUTlock :: LmsBool -- V2 } deriving Generic makeLenses_ ''LmsUserTableCsv --- | Mundane conversion needed for direct download without dbTable onlu +-- | Mundane conversion needed for direct download without dbTable only lmsUser2csv :: Day -> LmsUser -> LmsUserTableCsv lmsUser2csv cutoff lu@LmsUser{..} = LmsUserTableCsv { csvLUTident = lmsUserIdent , csvLUTpin = lmsUserPin - , csvLUTresetPin = lmsUserResetPin & LmsBool - , csvLUTdelete = lmsUserToDelete cutoff lu & LmsBool - , csvLUTstaff = False & LmsBool + , csvLUTresetPin = LmsBool lmsUserResetPin + , csvLUTdelete = LmsBool (lmsUserToDelete cutoff lu) + , csvLUTstaff = LmsBool False + , csvLUTresetTries= LmsBool False -- TODO -- wie wird das festgelegt? Als Attribut in der DB? + , csvLUTlock = LmsBool False -- TODO -- kann dies rein aus der Zeit berechnet werden? } -- csv without headers @@ -48,15 +51,17 @@ instance Csv.FromRecord LmsUserTableCsv -- csv with headers lmsUserTableCsvHeader :: Csv.Header -lmsUserTableCsvHeader = Csv.header [ csvLmsIdent, csvLmsPin, csvLmsResetPin, csvLmsDelete, csvLmsStaff ] +lmsUserTableCsvHeader = Csv.header [ csvLmsIdent, csvLmsPin, csvLmsResetPin, csvLmsDelete, csvLmsStaff, csvLmsResetTries, csvLmsLock ] instance ToNamedRecord LmsUserTableCsv where toNamedRecord LmsUserTableCsv{..} = Csv.namedRecord - [ csvLmsIdent Csv..= csvLUTident - , csvLmsPin Csv..= csvLUTpin - , csvLmsResetPin Csv..= csvLUTresetPin - , csvLmsDelete Csv..= csvLUTdelete - , csvLmsStaff Csv..= csvLUTstaff + [ csvLmsIdent Csv..= csvLUTident + , csvLmsPin Csv..= csvLUTpin + , csvLmsResetPin Csv..= csvLUTresetPin + , csvLmsDelete Csv..= csvLUTdelete + , csvLmsStaff Csv..= csvLUTstaff + , csvLmsResetTries Csv..= csvLUTresetTries + , csvLmsLock Csv..= csvLUTlock ] instance FromNamedRecord LmsUserTableCsv where parseNamedRecord (lsfHeaderTranslate -> csv) @@ -66,14 +71,18 @@ instance FromNamedRecord LmsUserTableCsv where <*> csv Csv..: csvLmsResetPin <*> csv Csv..: csvLmsDelete <*> csv Csv..: csvLmsStaff + <*> csv Csv..: csvLmsResetTries + <*> csv Csv..: csvLmsLock instance CsvColumnsExplained LmsUserTableCsv where csvColumnsExplanations _ = mconcat - [ single csvLmsIdent MsgCsvColumnLmsIdent - , single csvLmsPin MsgCsvColumnLmsPin - , single csvLmsResetPin MsgCsvColumnLmsResetPin - , single csvLmsDelete MsgCsvColumnLmsDelete - , single csvLmsStaff MsgCsvColumnLmsStaff + [ single csvLmsIdent MsgCsvColumnLmsIdent + , single csvLmsPin MsgCsvColumnLmsPin + , single csvLmsResetPin MsgCsvColumnLmsResetPin + , single csvLmsDelete MsgCsvColumnLmsDelete + , single csvLmsStaff MsgCsvColumnLmsStaff + , single csvLmsResetTries MsgCsvColumnLmsResetTries + , single csvLmsLock MsgCsvColumnLmsLock ] where single :: RenderMessage UniWorX msg => Csv.Name -> msg -> Map Csv.Name Widget @@ -101,7 +110,9 @@ mkUserTable _sid qsh qid = do ) $ \(view $ _dbrOutput . _entityVal . _lmsUserPin -> pin ) -> textCell pin , sortable (Just csvLmsResetPin) (i18nCell MsgTableLmsResetPin) $ \(view $ _dbrOutput . _entityVal . _lmsUserResetPin -> reset) -> ifIconCell reset IconReset , sortable (Just csvLmsDelete) (i18nCell MsgTableLmsDelete) $ \(view $ _dbrOutput . _entityVal . _lmsUserToDelete cutoff -> del ) -> ifIconCell del IconRemoveUser - , sortable Nothing (i18nCell MsgTableLmsStaff) $ const mempty + , sortable Nothing (i18nCell MsgTableLmsStaff) $ const mempty + , sortable Nothing (i18nCell MsgTableLmsResetTries) $ const mempty -- TODO + , sortable Nothing (i18nCell MsgTableLmsLock) $ const mempty -- TODO ] dbtSorting = Map.fromList [ (csvLmsIdent , SortColumn (E.^. LmsUserIdent)) @@ -134,6 +145,8 @@ mkUserTable _sid qsh qid = do <*> view (_dbrOutput . _entityVal . _lmsUserResetPin . _lmsBool) <*> view (_dbrOutput . _entityVal . _lmsUserToDelete cutoff . _lmsBool) <*> const (LmsBool False) + <*> const (LmsBool False) -- TODO + <*> const (LmsBool False) -- TODO dbtCsvDecode = Nothing dbtExtraReps = [] diff --git a/src/Handler/LMS/Users.hs b/src/Handler/LMS/Users.hs index 395ad5d54..66a928727 100644 --- a/src/Handler/LMS/Users.hs +++ b/src/Handler/LMS/Users.hs @@ -32,7 +32,7 @@ data LmsUserTableCsv = LmsUserTableCsv -- for csv export only deriving Generic makeLenses_ ''LmsUserTableCsv --- | Mundane conversion needed for direct download without dbTable onlu +-- | Mundane conversion needed for direct download without dbTable only lmsUser2csv :: Day -> LmsUser -> LmsUserTableCsv lmsUser2csv cutoff lu@LmsUser{..} = LmsUserTableCsv { csvLUTident = lmsUserIdent