module Handler.ExamOffice.Fields ( getEOFieldsR , postEOFieldsR ) where import Import import Utils.Form import qualified Database.Esqueleto as E import qualified Data.Set as Set import qualified Data.Map as Map data ExamOfficeFieldMode = EOFNotSubscribed | EOFSubscribed | EOFForced deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic, Typeable) embedRenderMessage ''UniWorX ''ExamOfficeFieldMode $ concat . set (ix 0) "ExamOfficeField" . splitCamel instance Universe ExamOfficeFieldMode instance Finite ExamOfficeFieldMode nullaryPathPiece ''ExamOfficeFieldMode $ camelToPathPiece' 1 instance Default ExamOfficeFieldMode where def = EOFNotSubscribed eofModeField :: (MonadHandler m, HandlerSite m ~ UniWorX) => Field m ExamOfficeFieldMode -- ^ Always required eofModeField = Field{..} where fieldEnctype = UrlEncoded fieldView = \theId name attrs val _isReq -> $(widgetFile "widgets/fields/examOfficeFieldMode") fieldParse = \e _ -> return $ parser e parser [] = Right Nothing parser (x:_) | Just mode <- fromPathPiece x = Right $ Just mode parser (x:_) = Left . SomeMessage $ MsgInvalidExamOfficeFieldMode x isChecked :: Eq a => a -> Either Text a -> Bool isChecked opt = either (const False) (== opt) makeExamOfficeFieldsForm :: UserId -> Maybe (Map StudyTermsId Bool) -> Form (Map StudyTermsId Bool) makeExamOfficeFieldsForm uid template = renderWForm FormStandard $ do availableFields <- liftHandler . runDB . E.select . E.from $ \(terms `E.InnerJoin` schoolTerms) -> do E.on $ terms E.^. StudyTermsId E.==. schoolTerms E.^. SchoolTermsTerms E.where_ . E.exists . E.from $ \userFunction -> E.where_ $ userFunction E.^. UserFunctionUser E.==. E.val uid E.&&. userFunction E.^. UserFunctionFunction E.==. E.val SchoolExamOffice E.&&. userFunction E.^. UserFunctionSchool E.==. schoolTerms E.^. SchoolTermsSchool return terms let available = imap (\k terms -> (terms, view forced $ template >>= Map.lookup k)) $ toMapOf (folded .> _entityVal) availableFields forced :: Iso' (Maybe Bool) ExamOfficeFieldMode forced = iso fromForced toForced where fromForced = maybe EOFNotSubscribed $ bool EOFSubscribed EOFForced toForced = \case EOFNotSubscribed -> Nothing EOFSubscribed -> Just False EOFForced -> Just True fmap (fmap (Map.mapMaybe $ review forced) . sequence) . forM available $ \(StudyTerms{..}, template') -> let label = fromMaybe (tshow studyTermsKey) $ studyTermsName <|> studyTermsShorthand in wpopt eofModeField (fsl label) $ Just template' -- | Manage the list of `StudyTerms` this user (in her function as exam-office) -- has an interest in, i.e. that authorize her to view an users grades, iff -- they study one of the selected fields getEOFieldsR, postEOFieldsR :: Handler Html getEOFieldsR = postEOFieldsR postEOFieldsR = do uid <- requireAuthId oldFields <- runDB $ do fields <- E.select . E.from $ \examOfficeField -> do E.where_ $ examOfficeField E.^. ExamOfficeFieldOffice E.==. E.val uid return (examOfficeField E.^. ExamOfficeFieldField, examOfficeField E.^. ExamOfficeFieldForced) return $ toMapOf (folded .> ito (over _1 E.unValue . over _2 E.unValue)) fields ((fieldsRes, fieldsView), fieldsEnc) <- runFormPost . makeExamOfficeFieldsForm uid $ Just oldFields formResult fieldsRes $ \newFields -> do runDB . forM_ (Map.keysSet newFields `Set.union` Map.keysSet oldFields) $ \fieldId -> if | Just forced <- Map.lookup fieldId newFields , fieldId `Map.member` oldFields -> do updateBy (UniqueExamOfficeField uid fieldId) [ ExamOfficeFieldForced =. forced ] audit $ TransactionExamOfficeFieldEdit uid fieldId | Just forced <- Map.lookup fieldId newFields -> do insert_ $ ExamOfficeField uid fieldId forced audit $ TransactionExamOfficeFieldEdit uid fieldId | otherwise -> do deleteBy $ UniqueExamOfficeField uid fieldId audit $ TransactionExamOfficeFieldDelete uid fieldId addMessageI Success $ MsgTransactionExamOfficeFieldsUpdated (Set.size . Set.map (view _1) $ (setSymmDiff `on` assocsSet) newFields oldFields) redirect $ ExamOfficeR EOExamsR let fieldsView' = wrapForm fieldsView def { formAction = Just . SomeRoute $ ExamOfficeR EOFieldsR , formEncoding = fieldsEnc } siteLayoutMsg MsgMenuExamOfficeFields $ do setTitleI MsgMenuExamOfficeFields [whamlet| $newline never
_{MsgExamOfficeSubscribedFieldsExplanation} ^{fieldsView'} |]