feat(course-users): include tutorial in csv-export
This commit is contained in:
parent
ec4b3a8f54
commit
1d5ddd102c
@ -1559,6 +1559,7 @@ CsvColumnUserDegree: Abschluss, den der Teilnehmer im assoziierten Studienfach a
|
|||||||
CsvColumnUserSemester: Fachsemester des Teilnehmers im assoziierten Studienfach
|
CsvColumnUserSemester: Fachsemester des Teilnehmers im assoziierten Studienfach
|
||||||
CsvColumnUserRegistration: Zeitpunkt der Anmeldung zum Kurs (ISO 8601)
|
CsvColumnUserRegistration: Zeitpunkt der Anmeldung zum Kurs (ISO 8601)
|
||||||
CsvColumnUserNote: Notizen zum Teilnehmer
|
CsvColumnUserNote: Notizen zum Teilnehmer
|
||||||
|
CsvColumnUserTutorial: Tutorien zu denen der Teilnehmer angemeldet ist, als Semikolon (;) separierte Liste. Für Registrierungs-Gruppen unter den Tutorien gibt es jeweils eine weitere Spalte. Die Registrierungs-Gruppen-Spalten enthalten jeweils maximal ein Tutorium pro Teilnehmer. Sind alle Tutorien in Registrierungs-Gruppen, so gibt es keine Spalte "tutorial".
|
||||||
|
|
||||||
CsvColumnExamOfficeExamUserOccurrenceStart: Prüfungstermin (ISO 8601)
|
CsvColumnExamOfficeExamUserOccurrenceStart: Prüfungstermin (ISO 8601)
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import Data.Function ((&))
|
|||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
|
import qualified Data.Vector as Vector
|
||||||
|
|
||||||
import qualified Database.Esqueleto as E
|
import qualified Database.Esqueleto as E
|
||||||
|
|
||||||
@ -26,11 +27,17 @@ import qualified Data.Csv as Csv
|
|||||||
|
|
||||||
import qualified Data.Conduit.List as C
|
import qualified Data.Conduit.List as C
|
||||||
|
|
||||||
|
import qualified Data.CaseInsensitive as CI
|
||||||
|
|
||||||
type UserTableExpr = (E.SqlExpr (Entity User) `E.InnerJoin` E.SqlExpr (Entity CourseParticipant))
|
|
||||||
`E.LeftOuterJoin` E.SqlExpr (Maybe (Entity CourseUserNote))
|
type UserTableExpr = ( E.SqlExpr (Entity User)
|
||||||
`E.LeftOuterJoin`
|
`E.InnerJoin` E.SqlExpr (Entity CourseParticipant)
|
||||||
(E.SqlExpr (Maybe (Entity StudyFeatures)) `E.InnerJoin` E.SqlExpr (Maybe (Entity StudyDegree)) `E.InnerJoin`E.SqlExpr (Maybe (Entity StudyTerms)))
|
)
|
||||||
|
`E.LeftOuterJoin` E.SqlExpr (Maybe (Entity CourseUserNote))
|
||||||
|
`E.LeftOuterJoin` ( E.SqlExpr (Maybe (Entity StudyFeatures))
|
||||||
|
`E.InnerJoin` E.SqlExpr (Maybe (Entity StudyDegree))
|
||||||
|
`E.InnerJoin` E.SqlExpr (Maybe (Entity StudyTerms))
|
||||||
|
)
|
||||||
|
|
||||||
-- forceUserTableType :: (UserTableExpr -> a) -> (UserTableExpr -> a)
|
-- forceUserTableType :: (UserTableExpr -> a) -> (UserTableExpr -> a)
|
||||||
-- forceUserTableType = id
|
-- forceUserTableType = id
|
||||||
@ -70,7 +77,12 @@ userTableQuery cid ((user `E.InnerJoin` participant) `E.LeftOuterJoin` note `E.L
|
|||||||
return (user, participant E.^. CourseParticipantRegistration, note E.?. CourseUserNoteId, features)
|
return (user, participant E.^. CourseParticipantRegistration, note E.?. CourseUserNoteId, features)
|
||||||
|
|
||||||
|
|
||||||
type UserTableData = DBRow (Entity User, UTCTime, Maybe CourseUserNoteId, (Maybe StudyFeatures, Maybe StudyDegree, Maybe StudyTerms))
|
type UserTableData = DBRow ( Entity User
|
||||||
|
, UTCTime
|
||||||
|
, Maybe CourseUserNoteId
|
||||||
|
, (Maybe StudyFeatures, Maybe StudyDegree, Maybe StudyTerms)
|
||||||
|
, ([Entity Tutorial], Map (CI Text) (Maybe (Entity Tutorial)))
|
||||||
|
)
|
||||||
|
|
||||||
instance HasEntity UserTableData User where
|
instance HasEntity UserTableData User where
|
||||||
hasEntity = _dbrOutput . _1
|
hasEntity = _dbrOutput . _1
|
||||||
@ -91,11 +103,14 @@ _userTableFeatures = _dbrOutput . _4
|
|||||||
_rowUserSemester :: Traversal' UserTableData Int
|
_rowUserSemester :: Traversal' UserTableData Int
|
||||||
_rowUserSemester = _userTableFeatures . _1 . _Just . _studyFeaturesSemester
|
_rowUserSemester = _userTableFeatures . _1 . _Just . _studyFeaturesSemester
|
||||||
|
|
||||||
|
_userTutorials :: Lens' UserTableData ([Entity Tutorial], Map (CI Text) (Maybe (Entity Tutorial)))
|
||||||
|
_userTutorials = _dbrOutput . _5
|
||||||
|
|
||||||
|
|
||||||
colUserComment :: IsDBTable m c => TermId -> SchoolId -> CourseShorthand -> Colonnade Sortable UserTableData (DBCell m c)
|
colUserComment :: IsDBTable m c => TermId -> SchoolId -> CourseShorthand -> Colonnade Sortable UserTableData (DBCell m c)
|
||||||
colUserComment tid ssh csh =
|
colUserComment tid ssh csh =
|
||||||
sortable (Just "note") (i18nCell MsgCourseUserNote)
|
sortable (Just "note") (i18nCell MsgCourseUserNote)
|
||||||
$ \DBRow{ dbrOutput=(Entity uid _, _, mbNoteKey,_) } ->
|
$ \DBRow{ dbrOutput=(Entity uid _, _, mbNoteKey, _, _) } ->
|
||||||
maybeEmpty mbNoteKey $ const $
|
maybeEmpty mbNoteKey $ const $
|
||||||
anchorCellM (courseLink <$> encrypt uid) (hasComment True)
|
anchorCellM (courseLink <$> encrypt uid) (hasComment True)
|
||||||
where
|
where
|
||||||
@ -137,6 +152,7 @@ data UserTableCsv = UserTableCsv
|
|||||||
, csvUserStudyFeatures :: Either (Maybe UserTableCsvStudyFeature) (Set UserTableCsvStudyFeature)
|
, csvUserStudyFeatures :: Either (Maybe UserTableCsvStudyFeature) (Set UserTableCsvStudyFeature)
|
||||||
, csvUserRegistration :: UTCTime
|
, csvUserRegistration :: UTCTime
|
||||||
, csvUserNote :: Maybe Html
|
, csvUserNote :: Maybe Html
|
||||||
|
, csvUserTutorials :: ([TutorialName], Map (CI Text) (Maybe TutorialName))
|
||||||
} deriving (Eq, Ord, Read, Show, Generic, Typeable)
|
} deriving (Eq, Ord, Read, Show, Generic, Typeable)
|
||||||
makeLenses_ ''UserTableCsv
|
makeLenses_ ''UserTableCsv
|
||||||
|
|
||||||
@ -158,6 +174,12 @@ instance Csv.ToNamedRecord UserTableCsv where
|
|||||||
in [ "study-features" Csv..= featsStr
|
in [ "study-features" Csv..= featsStr
|
||||||
]
|
]
|
||||||
++
|
++
|
||||||
|
[ let tutsStr = Text.intercalate "; " . map CI.original $ csvUserTutorials ^. _1
|
||||||
|
in "tutorial" Csv..= tutsStr
|
||||||
|
] ++
|
||||||
|
[ encodeUtf8 (CI.foldedCase regGroup) Csv..= (CI.original <$> mTut)
|
||||||
|
| (regGroup, mTut) <- Map.toList $ csvUserTutorials ^. _2
|
||||||
|
] ++
|
||||||
[ "registration" Csv..= csvUserRegistration
|
[ "registration" Csv..= csvUserRegistration
|
||||||
, "note" Csv..= csvUserNote
|
, "note" Csv..= csvUserNote
|
||||||
]
|
]
|
||||||
@ -170,6 +192,7 @@ instance CsvColumnsExplained UserTableCsv where
|
|||||||
, single "field" MsgCsvColumnUserField
|
, single "field" MsgCsvColumnUserField
|
||||||
, single "degree" MsgCsvColumnUserDegree
|
, single "degree" MsgCsvColumnUserDegree
|
||||||
, single "semester" MsgCsvColumnUserSemester
|
, single "semester" MsgCsvColumnUserSemester
|
||||||
|
, single "tutorial" MsgCsvColumnUserTutorial
|
||||||
, single "registration" MsgCsvColumnUserRegistration
|
, single "registration" MsgCsvColumnUserRegistration
|
||||||
, single "note" MsgCsvColumnUserNote
|
, single "note" MsgCsvColumnUserNote
|
||||||
]
|
]
|
||||||
@ -183,12 +206,17 @@ newtype UserCsvExportData = UserCsvExportData
|
|||||||
instance Default UserCsvExportData where
|
instance Default UserCsvExportData where
|
||||||
def = UserCsvExportData True
|
def = UserCsvExportData True
|
||||||
|
|
||||||
userTableCsvHeader :: UserCsvExportData -> Csv.Header
|
userTableCsvHeader :: UserCsvExportData -> [Entity Tutorial] -> Csv.Header
|
||||||
userTableCsvHeader UserCsvExportData{..} = Csv.header $
|
userTableCsvHeader UserCsvExportData{..} tuts = Csv.header $
|
||||||
[ "name", "matriculation", "email"
|
[ "name", "matriculation", "email"
|
||||||
] ++ bool (pure "study-features") ["field", "degree", "semester"] csvUserSimplifiedFeaturesOfStudy ++
|
] ++ bool (pure "study-features") ["field", "degree", "semester"] csvUserSimplifiedFeaturesOfStudy ++
|
||||||
|
[ "tutorial" | hasEmptyRegGroup ] ++
|
||||||
|
map (encodeUtf8 . CI.foldedCase) regGroups ++
|
||||||
[ "registration", "note"
|
[ "registration", "note"
|
||||||
]
|
]
|
||||||
|
where
|
||||||
|
hasEmptyRegGroup = has (folded . _entityVal . _tutorialRegGroup . _Nothing) tuts
|
||||||
|
regGroups = Set.toList $ setOf (folded . _entityVal . _tutorialRegGroup . _Just) tuts
|
||||||
|
|
||||||
|
|
||||||
data CourseUserAction = CourseUserSendMail | CourseUserDeregister
|
data CourseUserAction = CourseUserSendMail | CourseUserDeregister
|
||||||
@ -215,17 +243,25 @@ makeCourseUserTable :: forall h act act'.
|
|||||||
-> (UserTableExpr -> E.SqlExpr (E.Value Bool))
|
-> (UserTableExpr -> E.SqlExpr (E.Value Bool))
|
||||||
-> Colonnade h UserTableData (DBCell (MForm Handler) (FormResult (First act', DBFormResult UserId Bool UserTableData)))
|
-> Colonnade h UserTableData (DBCell (MForm Handler) (FormResult (First act', DBFormResult UserId Bool UserTableData)))
|
||||||
-> PSValidator (MForm Handler) (FormResult (First act', DBFormResult UserId Bool UserTableData))
|
-> PSValidator (MForm Handler) (FormResult (First act', DBFormResult UserId Bool UserTableData))
|
||||||
|
-> Maybe (Csv.Name -> Bool)
|
||||||
-> DB (FormResult (act', Set UserId), Widget)
|
-> DB (FormResult (act', Set UserId), Widget)
|
||||||
makeCourseUserTable cid acts restrict colChoices psValidator = do
|
makeCourseUserTable cid acts restrict colChoices psValidator csvColumns = do
|
||||||
currentRoute <- fromMaybe (error "makeCourseUserTable called from 404-handler") <$> liftHandler getCurrentRoute
|
currentRoute <- fromMaybe (error "makeCourseUserTable called from 404-handler") <$> liftHandler getCurrentRoute
|
||||||
Course{..} <- getJust cid
|
Course{..} <- getJust cid
|
||||||
csvName <- getMessageRender <*> pure (MsgCourseUserCsvName courseTerm courseSchool courseShorthand)
|
csvName <- getMessageRender <*> pure (MsgCourseUserCsvName courseTerm courseSchool courseShorthand)
|
||||||
|
tutorials <- selectList [ TutorialCourse ==. cid ] []
|
||||||
-- -- psValidator has default sorting and filtering
|
-- -- psValidator has default sorting and filtering
|
||||||
let dbtIdent = "courseUsers" :: Text
|
let dbtIdent = "courseUsers" :: Text
|
||||||
dbtStyle = def { dbsFilterLayout = defaultDBSFilterLayout }
|
dbtStyle = def { dbsFilterLayout = defaultDBSFilterLayout }
|
||||||
dbtSQLQuery q = userTableQuery cid q <* E.where_ (restrict q)
|
dbtSQLQuery q = userTableQuery cid q <* E.where_ (restrict q)
|
||||||
dbtRowKey = queryUser >>> (E.^. UserId)
|
dbtRowKey = queryUser >>> (E.^. UserId)
|
||||||
dbtProj = traverse $ \(user, E.Value registrationTime , E.Value userNoteId, (feature,degree,terms)) -> return (user, registrationTime, userNoteId, (entityVal <$> feature, entityVal <$> degree, entityVal <$> terms))
|
dbtProj = traverse $ \(user, E.Value registrationTime , E.Value userNoteId, (feature,degree,terms)) -> do
|
||||||
|
tuts'' <- lift $ selectList [ TutorialParticipantUser ==. entityKey user, TutorialParticipantTutorial <-. map entityKey tutorials ] []
|
||||||
|
let
|
||||||
|
regGroups = setOf (folded . _entityVal . _tutorialRegGroup . _Just) tutorials
|
||||||
|
tuts' = filter (\(Entity tutId _) -> any ((== tutId) . tutorialParticipantTutorial . entityVal) tuts'') tutorials
|
||||||
|
tuts = foldr (\tut@(Entity _ Tutorial{..}) -> maybe (over _1 $ cons tut) (over _2 . flip (Map.insertWith (<|>)) (Just tut)) tutorialRegGroup) ([], Map.fromSet (const Nothing) regGroups) regGroups) tuts'
|
||||||
|
return (user, registrationTime, userNoteId, (entityVal <$> feature, entityVal <$> degree, entityVal <$> terms), tuts)
|
||||||
dbtColonnade = colChoices
|
dbtColonnade = colChoices
|
||||||
dbtSorting = Map.fromList
|
dbtSorting = Map.fromList
|
||||||
[ sortUserNameLink queryUser -- slower sorting through clicking name column header
|
[ sortUserNameLink queryUser -- slower sorting through clicking name column header
|
||||||
@ -294,50 +330,53 @@ makeCourseUserTable cid acts restrict colChoices psValidator = do
|
|||||||
, dbParamsFormResult = id
|
, dbParamsFormResult = id
|
||||||
, dbParamsFormIdent = def
|
, dbParamsFormIdent = def
|
||||||
}
|
}
|
||||||
dbtCsvEncode = Just DBTCsvEncode
|
dbtCsvEncode = do
|
||||||
{ dbtCsvExportForm = UserCsvExportData
|
csvColumns' <- csvColumns
|
||||||
<$> apopt checkBoxField (fslI MsgUserSimplifiedFeaturesOfStudyCsv & setTooltip MsgUserSimplifiedFeaturesOfStudyCsvTip) (Just $ csvUserSimplifiedFeaturesOfStudy def)
|
return $ DBTCsvEncode
|
||||||
, dbtCsvDoEncode = \UserCsvExportData{..} -> C.mapM $ \(E.Value uid, row) -> flip runReaderT row $
|
{ dbtCsvExportForm = UserCsvExportData
|
||||||
UserTableCsv
|
<$> apopt checkBoxField (fslI MsgUserSimplifiedFeaturesOfStudyCsv & setTooltip MsgUserSimplifiedFeaturesOfStudyCsvTip) (Just $ csvUserSimplifiedFeaturesOfStudy def)
|
||||||
<$> view (hasUser . _userDisplayName)
|
, dbtCsvDoEncode = \UserCsvExportData{..} -> C.mapM $ \(E.Value uid, row) -> flip runReaderT row $
|
||||||
<*> view (hasUser . _userMatrikelnummer)
|
UserTableCsv
|
||||||
<*> view (hasUser . _userEmail)
|
<$> view (hasUser . _userDisplayName)
|
||||||
<*> if
|
<*> view (hasUser . _userMatrikelnummer)
|
||||||
| csvUserSimplifiedFeaturesOfStudy -> fmap Left . runMaybeT $
|
<*> view (hasUser . _userEmail)
|
||||||
UserTableCsvStudyFeature
|
<*> if
|
||||||
<$> MaybeT (preview $ _userTableFeatures . _3 . _Just . _studyTermsName . _Just
|
| csvUserSimplifiedFeaturesOfStudy -> fmap Left . runMaybeT $
|
||||||
<> _userTableFeatures . _3 . _Just . _studyTermsKey . to tshow
|
|
||||||
)
|
|
||||||
<*> MaybeT (preview $ _userTableFeatures . _2 . _Just . _studyDegreeName . _Just
|
|
||||||
<> _userTableFeatures . _2 . _Just . _studyDegreeKey . to tshow
|
|
||||||
)
|
|
||||||
<*> MaybeT (preview $ _userTableFeatures . _1 . _Just . _studyFeaturesSemester)
|
|
||||||
<*> MaybeT (preview $ _userTableFeatures . _1 . _Just . _studyFeaturesType)
|
|
||||||
| otherwise -> Right <$> do
|
|
||||||
feats <- lift . E.select . E.from $ \(feat `E.InnerJoin` terms `E.InnerJoin` degree) -> do
|
|
||||||
E.on $ degree E.^. StudyDegreeId E.==. feat E.^. StudyFeaturesDegree
|
|
||||||
E.on $ terms E.^. StudyTermsId E.==. feat E.^. StudyFeaturesField
|
|
||||||
let registered = E.exists . E.from $ \participant ->
|
|
||||||
E.where_ $ participant E.^. CourseParticipantCourse E.==. E.val cid
|
|
||||||
E.&&. participant E.^. CourseParticipantUser E.==. E.val uid
|
|
||||||
E.&&. participant E.^. CourseParticipantField E.==. E.just (feat E.^. StudyFeaturesId)
|
|
||||||
E.where_ $ registered
|
|
||||||
E.||. feat E.^. StudyFeaturesValid
|
|
||||||
E.where_ $ feat E.^. StudyFeaturesUser E.==. E.val uid
|
|
||||||
return (terms, degree, feat)
|
|
||||||
return . Set.fromList . flip map feats $ \(Entity _ StudyTerms{..}, Entity _ StudyDegree{..}, Entity _ StudyFeatures{..}) ->
|
|
||||||
UserTableCsvStudyFeature
|
UserTableCsvStudyFeature
|
||||||
{ csvUserField = fromMaybe (tshow studyTermsKey) studyTermsName
|
<$> MaybeT (preview $ _userTableFeatures . _3 . _Just . _studyTermsName . _Just
|
||||||
, csvUserDegree = fromMaybe (tshow studyDegreeKey) studyDegreeName
|
<> _userTableFeatures . _3 . _Just . _studyTermsKey . to tshow
|
||||||
, csvUserSemester = studyFeaturesSemester
|
)
|
||||||
, csvUserType = studyFeaturesType
|
<*> MaybeT (preview $ _userTableFeatures . _2 . _Just . _studyDegreeName . _Just
|
||||||
}
|
<> _userTableFeatures . _2 . _Just . _studyDegreeKey . to tshow
|
||||||
<*> view _userTableRegistration
|
)
|
||||||
<*> userNote
|
<*> MaybeT (preview $ _userTableFeatures . _1 . _Just . _studyFeaturesSemester)
|
||||||
, dbtCsvName = unpack csvName
|
<*> MaybeT (preview $ _userTableFeatures . _1 . _Just . _studyFeaturesType)
|
||||||
, dbtCsvNoExportData = Nothing
|
| otherwise -> Right <$> do
|
||||||
, dbtCsvHeader = return . userTableCsvHeader . fromMaybe def
|
feats <- lift . E.select . E.from $ \(feat `E.InnerJoin` terms `E.InnerJoin` degree) -> do
|
||||||
}
|
E.on $ degree E.^. StudyDegreeId E.==. feat E.^. StudyFeaturesDegree
|
||||||
|
E.on $ terms E.^. StudyTermsId E.==. feat E.^. StudyFeaturesField
|
||||||
|
let registered = E.exists . E.from $ \participant ->
|
||||||
|
E.where_ $ participant E.^. CourseParticipantCourse E.==. E.val cid
|
||||||
|
E.&&. participant E.^. CourseParticipantUser E.==. E.val uid
|
||||||
|
E.&&. participant E.^. CourseParticipantField E.==. E.just (feat E.^. StudyFeaturesId)
|
||||||
|
E.where_ $ registered
|
||||||
|
E.||. feat E.^. StudyFeaturesValid
|
||||||
|
E.where_ $ feat E.^. StudyFeaturesUser E.==. E.val uid
|
||||||
|
return (terms, degree, feat)
|
||||||
|
return . Set.fromList . flip map feats $ \(Entity _ StudyTerms{..}, Entity _ StudyDegree{..}, Entity _ StudyFeatures{..}) ->
|
||||||
|
UserTableCsvStudyFeature
|
||||||
|
{ csvUserField = fromMaybe (tshow studyTermsKey) studyTermsName
|
||||||
|
, csvUserDegree = fromMaybe (tshow studyDegreeKey) studyDegreeName
|
||||||
|
, csvUserSemester = studyFeaturesSemester
|
||||||
|
, csvUserType = studyFeaturesType
|
||||||
|
}
|
||||||
|
<*> view _userTableRegistration
|
||||||
|
<*> userNote
|
||||||
|
<*> (over (_2.traverse._Just) (tutorialName . entityVal) . over (_1.traverse) (tutorialName . entityVal) <$> view _userTutorials)
|
||||||
|
, dbtCsvName = unpack csvName
|
||||||
|
, dbtCsvNoExportData = Nothing
|
||||||
|
, dbtCsvHeader = return . Vector.filter csvColumns' . flip userTableCsvHeader tutorials . fromMaybe def
|
||||||
|
}
|
||||||
where
|
where
|
||||||
userNote = runMaybeT $ do
|
userNote = runMaybeT $ do
|
||||||
noteId <- MaybeT . preview $ _userTableNote . _Just
|
noteId <- MaybeT . preview $ _userTableNote . _Just
|
||||||
@ -389,7 +428,7 @@ postCUsersR tid ssh csh = do
|
|||||||
-> mempty
|
-> mempty
|
||||||
]
|
]
|
||||||
numParticipants <- count [CourseParticipantCourse ==. cid]
|
numParticipants <- count [CourseParticipantCourse ==. cid]
|
||||||
table <- makeCourseUserTable cid acts (const E.true) colChoices psValidator
|
table <- makeCourseUserTable cid acts (const E.true) colChoices psValidator (Just $ const True)
|
||||||
return (ent, numParticipants, table)
|
return (ent, numParticipants, table)
|
||||||
formResult participantRes $ \case
|
formResult participantRes $ \case
|
||||||
(CourseUserSendMailData, selectedUsers) -> do
|
(CourseUserSendMailData, selectedUsers) -> do
|
||||||
|
|||||||
@ -50,9 +50,10 @@ postTUsersR tid ssh csh tutn = do
|
|||||||
isInTut q = E.exists . E.from $ \tutorialParticipant ->
|
isInTut q = E.exists . E.from $ \tutorialParticipant ->
|
||||||
E.where_ $ tutorialParticipant E.^. TutorialParticipantUser E.==. queryUser q E.^. UserId
|
E.where_ $ tutorialParticipant E.^. TutorialParticipantUser E.==. queryUser q E.^. UserId
|
||||||
E.&&. tutorialParticipant E.^. TutorialParticipantTutorial E.==. E.val tutid
|
E.&&. tutorialParticipant E.^. TutorialParticipantTutorial E.==. E.val tutid
|
||||||
|
csvColChoices = flip elem ["name", "matriculation", "email", "field", "degree", "semester", "study-features"]
|
||||||
|
|
||||||
cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh
|
cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh
|
||||||
table <- makeCourseUserTable cid (Map.fromList $ map (id &&& pure) universeF) isInTut colChoices psValidator
|
table <- makeCourseUserTable cid (Map.fromList $ map (id &&& pure) universeF) isInTut colChoices psValidator (Just csvColChoices)
|
||||||
return (tut, table)
|
return (tut, table)
|
||||||
|
|
||||||
formResult participantRes $ \case
|
formResult participantRes $ \case
|
||||||
|
|||||||
@ -208,6 +208,8 @@ makeLenses_ ''CourseUserExamOfficeOptOut
|
|||||||
makeLenses_ ''CourseNewsFile
|
makeLenses_ ''CourseNewsFile
|
||||||
|
|
||||||
makeLenses_ ''AllocationCourse
|
makeLenses_ ''AllocationCourse
|
||||||
|
|
||||||
|
makeLenses_ ''Tutorial
|
||||||
|
|
||||||
|
|
||||||
-- makeClassy_ ''Load
|
-- makeClassy_ ''Load
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user