This repository has been archived on 2024-10-24. You can view files and clone it, but cannot push or open issues or pull requests.
fradrive-old/src/Foundation/Navigation.hs

2796 lines
114 KiB
Haskell

{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE UndecidableInstances #-} -- for `ChildrenNavChildren`
{-# LANGUAGE DuplicateRecordFields #-} -- for `navLabel`
module Foundation.Navigation
( NavQuickView(..), NavType(..), NavLevel(..), NavHeaderRole(..), NavLink(..), Nav(..), NavChildren
, _navModal, _navMethod, _navData, _navLabel, _navType, _navForceActive, _navHeaderRole, _navIcon, _navLink, _navChildren
, _NavHeader, _NavHeaderContainer, _NavPageActionPrimary, _NavPageActionSecondary, _NavFooter
, navBaseRoute, navLinkRoute
, pageActions
, pageQuickActions
, defaultLinks
, navAccess
, navQuick
, evalAccessCorrector
) where
import Import.NoFoundation
import Foundation.Type
import Foundation.Routes
import Foundation.I18n
import Foundation.Authorization
import Foundation.DB
import Handler.Utils.Memcached
import Handler.Utils.ExamOffice.Course
import Handler.Utils.Download
import Utils.Sheet
import qualified Data.CaseInsensitive as CI
import qualified Database.Esqueleto as E
import qualified Database.Esqueleto.Utils as E
import Control.Monad.Trans.State (execStateT)
import Yesod.Core.Types (HandlerContents)
import qualified Data.Conduit.Combinators as C
import Utils.Workflow
import Handler.Utils.Workflow.CanonicalRoute
-- Define breadcrumbs.
i18nCrumb :: (RenderMessage (HandlerSite m) msg, MonadHandler m)
=> msg
-> Maybe (Route (HandlerSite m))
-> m (Text, Maybe (Route (HandlerSite m)))
i18nCrumb msg mbR = do
mr <- getMessageRender
return (mr msg, mbR)
-- `breadcrumb` _really_ needs to be total for _all_ routes
--
-- Even if routes are POST only or don't usually use `siteLayout` they will if
-- an error occurs.
--
-- Keep in mind that Breadcrumbs are also shown by the 403-Handler,
-- i.e. information might be leaked by not performing permission checks if the
-- breadcrumb value depends on sensitive content (like an user's name).
instance BearerAuthSite UniWorX => YesodBreadcrumbs UniWorX where
breadcrumb (AuthR _) = i18nCrumb MsgMenuLogin $ Just NewsR
breadcrumb (StaticR _) = i18nCrumb MsgBreadcrumbStatic Nothing
breadcrumb (WellKnownR _) = i18nCrumb MsgBreadcrumbWellKnown Nothing
breadcrumb MetricsR = i18nCrumb MsgBreadcrumbMetrics Nothing
breadcrumb NewsR = i18nCrumb MsgMenuNews Nothing
breadcrumb UsersR = i18nCrumb MsgMenuUsers $ Just AdminR
breadcrumb AdminUserAddR = i18nCrumb MsgMenuUserAdd $ Just UsersR
breadcrumb (AdminUserR cID) = maybeT (i18nCrumb MsgBreadcrumbUser $ Just UsersR) $ do
guardM . hasReadAccessTo $ AdminUserR cID
uid <- decrypt cID
User{..} <- MaybeT . runDBRead $ get uid
return (userDisplayName, Just UsersR)
breadcrumb (AdminUserDeleteR cID) = i18nCrumb MsgBreadcrumbUserDelete . Just $ AdminUserR cID
breadcrumb (AdminHijackUserR cID) = i18nCrumb MsgBreadcrumbUserHijack . Just $ AdminUserR cID
breadcrumb (UserNotificationR cID) = do
mayList <- hasReadAccessTo UsersR
if
| mayList
-> i18nCrumb MsgMenuUserNotifications . Just $ AdminUserR cID
| otherwise
-> i18nCrumb MsgMenuUserNotifications $ Just ProfileR
breadcrumb (UserPasswordR cID) = do
mayList <- hasReadAccessTo UsersR
if
| mayList
-> i18nCrumb MsgMenuUserPassword . Just $ AdminUserR cID
| otherwise
-> i18nCrumb MsgMenuUserPassword $ Just ProfileR
breadcrumb AdminNewFunctionaryInviteR = i18nCrumb MsgMenuLecturerInvite $ Just UsersR
breadcrumb AdminFunctionaryInviteR = i18nCrumb MsgBreadcrumbFunctionaryInvite Nothing
breadcrumb AdminR = i18nCrumb MsgAdminHeading Nothing
breadcrumb AdminFeaturesR = i18nCrumb MsgAdminFeaturesHeading $ Just AdminR
breadcrumb AdminTestR = i18nCrumb MsgMenuAdminTest $ Just AdminR
breadcrumb AdminErrMsgR = i18nCrumb MsgMenuAdminErrMsg $ Just AdminR
breadcrumb AdminTokensR = i18nCrumb MsgMenuAdminTokens $ Just AdminR
breadcrumb AdminCrontabR = i18nCrumb MsgBreadcrumbAdminCrontab $ Just AdminR
breadcrumb SchoolListR = i18nCrumb MsgMenuSchoolList $ Just AdminR
breadcrumb (SchoolR ssh sRoute) = case sRoute of
SchoolEditR -> maybeT (i18nCrumb MsgBreadcrumbSchool $ Just SchoolListR) $ do
School{..} <- MaybeT . runDBRead $ get ssh
isAdmin <- hasReadAccessTo SchoolListR
return (CI.original schoolName, bool Nothing (Just SchoolListR) isAdmin)
SchoolWorkflowInstanceListR -> i18nCrumb MsgBreadcrumbWorkflowInstanceList . Just $ SchoolR ssh SchoolEditR
SchoolWorkflowInstanceNewR -> i18nCrumb MsgBreadcrumbWorkflowInstanceNew . Just $ SchoolR ssh SchoolWorkflowInstanceListR
SchoolWorkflowInstanceR win sRoute' -> case sRoute' of
SWIEditR -> i18nCrumb (MsgBreadcrumbWorkflowInstanceEdit win) . Just $ SchoolR ssh SchoolWorkflowInstanceListR
SWIDeleteR -> i18nCrumb MsgBreadcrumbWorkflowInstanceDelete . Just . SchoolR ssh $ SchoolWorkflowInstanceR win SWIEditR
SWIWorkflowsR -> i18nCrumb MsgBreadcrumbWorkflowInstanceWorkflowList . Just . SchoolR ssh $ SchoolWorkflowInstanceR win SWIEditR
SWIInitiateR -> do
mayEdit <- hasReadAccessTo . SchoolR ssh $ SchoolWorkflowInstanceR win SWIEditR
i18nCrumb MsgBreadcrumbWorkflowInstanceInitiate . Just . SchoolR ssh $ if
| mayEdit -> SchoolWorkflowInstanceR win SWIEditR
| otherwise -> SchoolWorkflowInstanceListR
SchoolWorkflowWorkflowListR -> i18nCrumb MsgBreadcrumbWorkflowWorkflowList . Just $ SchoolR ssh SchoolWorkflowInstanceListR
SchoolWorkflowWorkflowR cID sRoute' -> case sRoute' of
SWWWorkflowR -> i18nCrumb (MsgBreadcrumbWorkflowWorkflow cID) . Just $ SchoolR ssh SchoolWorkflowWorkflowListR
SWWFilesR _ _ -> i18nCrumb MsgBreadcrumbWorkflowWorkflowFiles . Just . SchoolR ssh $ SchoolWorkflowWorkflowR cID SWWWorkflowR
SWWEditR -> i18nCrumb MsgBreadcrumbWorkflowWorkflowEdit . Just . SchoolR ssh $ SchoolWorkflowWorkflowR cID SWWWorkflowR
SWWDeleteR -> i18nCrumb MsgBreadcrumbWorkflowWorkflowDelete . Just . SchoolR ssh $ SchoolWorkflowWorkflowR cID SWWWorkflowR
breadcrumb SchoolNewR = i18nCrumb MsgMenuSchoolNew $ Just SchoolListR
breadcrumb (ExamOfficeR EOExamsR) = i18nCrumb MsgMenuExamOfficeExams Nothing
breadcrumb (ExamOfficeR EOFieldsR) = i18nCrumb MsgMenuExamOfficeFields . Just $ ExamOfficeR EOExamsR
breadcrumb (ExamOfficeR EOUsersR) = i18nCrumb MsgMenuExamOfficeUsers . Just $ ExamOfficeR EOExamsR
breadcrumb (ExamOfficeR EOUsersInviteR) = i18nCrumb MsgBreadcrumbExamOfficeUserInvite Nothing
breadcrumb InfoR = i18nCrumb MsgMenuInformation Nothing
breadcrumb InfoLecturerR = i18nCrumb MsgInfoLecturerTitle $ Just InfoR
breadcrumb LegalR = i18nCrumb MsgMenuLegal $ Just InfoR
breadcrumb InfoAllocationR = i18nCrumb MsgBreadcrumbAllocationInfo $ Just InfoR
breadcrumb VersionR = i18nCrumb MsgMenuVersion $ Just InfoR
breadcrumb FaqR = i18nCrumb MsgBreadcrumbFaq $ Just InfoR
breadcrumb HelpR = i18nCrumb MsgMenuHelp Nothing
breadcrumb HealthR = i18nCrumb MsgMenuHealth Nothing
breadcrumb InstanceR = i18nCrumb MsgMenuInstance Nothing
breadcrumb ProfileR = i18nCrumb MsgBreadcrumbProfile Nothing
breadcrumb SetDisplayEmailR = i18nCrumb MsgUserDisplayEmail $ Just ProfileR
breadcrumb ProfileDataR = i18nCrumb MsgMenuProfileData $ Just ProfileR
breadcrumb AuthPredsR = i18nCrumb MsgMenuAuthPreds $ Just ProfileR
breadcrumb CsvOptionsR = i18nCrumb MsgCsvOptions $ Just ProfileR
breadcrumb LangR = i18nCrumb MsgMenuLanguage $ Just ProfileR
breadcrumb StorageKeyR = i18nCrumb MsgBreadcrumbStorageKey Nothing
breadcrumb TermShowR = i18nCrumb MsgMenuTermShow $ Just NewsR
breadcrumb TermCurrentR = i18nCrumb MsgMenuTermCurrent $ Just TermShowR
breadcrumb TermEditR = i18nCrumb MsgMenuTermCreate $ Just TermShowR
breadcrumb (TermEditExistR tid) = i18nCrumb MsgMenuTermEdit . Just $ TermCourseListR tid
breadcrumb (TermCourseListR tid) = maybeT (i18nCrumb MsgBreadcrumbTerm $ Just CourseListR) $ do -- redirect only, used in other breadcrumbs
guardM . lift . runDBRead $ isJust <$> get tid
i18nCrumb (ShortTermIdentifier $ unTermKey tid) $ Just CourseListR
breadcrumb (TermSchoolCourseListR tid ssh) = maybeT (i18nCrumb MsgBreadcrumbSchool . Just $ TermCourseListR tid) $ do -- redirect only, used in other breadcrumbs
guardM . lift . runDBRead $
(&&) <$> fmap isJust (get ssh)
<*> fmap isJust (get tid)
return (CI.original $ unSchoolKey ssh, Just $ TermCourseListR tid)
breadcrumb AllocationListR = i18nCrumb MsgAllocationListTitle $ Just NewsR
breadcrumb (AllocationR tid ssh ash sRoute) = case sRoute of
AShowR -> maybeT (i18nCrumb MsgBreadcrumbAllocation $ Just AllocationListR) $ do
mr <- getMessageRender
Entity _ Allocation{allocationName} <- MaybeT . runDBRead . getBy $ TermSchoolAllocationShort tid ssh ash
return ([st|#{allocationName} (#{mr (ShortTermIdentifier (unTermKey tid))}, #{CI.original (unSchoolKey ssh)})|], Just AllocationListR)
ARegisterR -> i18nCrumb MsgBreadcrumbAllocationRegister . Just $ AllocationR tid ssh ash AShowR
AApplyR cID -> maybeT (i18nCrumb MsgBreadcrumbCourse . Just $ AllocationR tid ssh ash AShowR) $ do
cid <- decrypt cID
Course{..} <- hoist runDBRead $ do
aid <- MaybeT . getKeyBy $ TermSchoolAllocationShort tid ssh ash
guardM . lift $ exists [ AllocationCourseAllocation ==. aid, AllocationCourseCourse ==. cid ]
MaybeT $ get cid
return (CI.original courseName, Just $ AllocationR tid ssh ash AShowR)
AUsersR -> i18nCrumb MsgBreadcrumbAllocationUsers . Just $ AllocationR tid ssh ash AShowR
APriosR -> i18nCrumb MsgBreadcrumbAllocationPriorities . Just $ AllocationR tid ssh ash AUsersR
AComputeR -> i18nCrumb MsgBreadcrumbAllocationCompute . Just $ AllocationR tid ssh ash AUsersR
AAcceptR -> i18nCrumb MsgBreadcrumbAllocationAccept . Just $ AllocationR tid ssh ash AUsersR
AAddUserR -> i18nCrumb MsgBreadcrumbAllocationAddUser . Just $ AllocationR tid ssh ash AUsersR
breadcrumb ParticipantsListR = i18nCrumb MsgBreadcrumbParticipantsList $ Just CourseListR
breadcrumb (ParticipantsR _ _) = i18nCrumb MsgBreadcrumbParticipants $ Just ParticipantsListR
breadcrumb ParticipantsIntersectR = i18nCrumb MsgMenuParticipantsIntersect $ Just ParticipantsListR
breadcrumb CourseListR = i18nCrumb MsgMenuCourseList Nothing
breadcrumb CourseNewR = i18nCrumb MsgMenuCourseNew $ Just CourseListR
breadcrumb (CourseR tid ssh csh CShowR) = maybeT (i18nCrumb MsgBreadcrumbCourse . Just $ TermSchoolCourseListR tid ssh) $ do
guardM . lift . runDBRead . existsBy $ TermSchoolCourseShort tid ssh csh
return (CI.original csh, Just $ TermSchoolCourseListR tid ssh)
breadcrumb (CourseR tid ssh csh CEditR) = i18nCrumb MsgMenuCourseEdit . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CUsersR) = i18nCrumb MsgMenuCourseMembers . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CAddUserR) = i18nCrumb MsgMenuCourseAddMembers . Just $ CourseR tid ssh csh CUsersR
breadcrumb (CourseR tid ssh csh CInviteR) = i18nCrumb MsgBreadcrumbCourseParticipantInvitation . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CExamOfficeR) = i18nCrumb MsgMenuCourseExamOffice . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh (CUserR cID)) = maybeT (i18nCrumb MsgBreadcrumbUser . Just $ CourseR tid ssh csh CUsersR) $ do
guardM . hasReadAccessTo . CourseR tid ssh csh $ CUserR cID
uid <- decrypt cID
User{userDisplayName} <- MaybeT . runDBRead $ get uid
return (userDisplayName, Just $ CourseR tid ssh csh CUsersR)
breadcrumb (CourseR tid ssh csh CCorrectionsR) = i18nCrumb MsgMenuSubmissions . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CAssignR) = i18nCrumb MsgMenuCorrectionsAssign . Just $ CourseR tid ssh csh CCorrectionsR
breadcrumb (CourseR tid ssh csh SheetListR) = i18nCrumb MsgMenuSheetList . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh SheetNewR ) = i18nCrumb MsgMenuSheetNew . Just $ CourseR tid ssh csh SheetListR
breadcrumb (CourseR tid ssh csh SheetCurrentR) = i18nCrumb MsgMenuSheetCurrent . Just $ CourseR tid ssh csh SheetListR
breadcrumb (CourseR tid ssh csh SheetOldUnassignedR) = i18nCrumb MsgMenuSheetOldUnassigned . Just $ CourseR tid ssh csh SheetListR
breadcrumb (CourseR tid ssh csh CCommR ) = i18nCrumb MsgMenuCourseCommunication . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CTutorialListR) = i18nCrumb MsgMenuTutorialList . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CTutorialNewR) = i18nCrumb MsgMenuTutorialNew . Just $ CourseR tid ssh csh CTutorialListR
breadcrumb (CourseR tid ssh csh CFavouriteR) = i18nCrumb MsgBreadcrumbCourseFavourite . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CRegisterR) = i18nCrumb MsgBreadcrumbCourseRegister . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CRegisterTemplateR) = i18nCrumb MsgBreadcrumbCourseRegisterTemplate . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CLecInviteR) = i18nCrumb MsgBreadcrumbLecturerInvite . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CDeleteR) = i18nCrumb MsgMenuCourseDelete . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CHiWisR) = i18nCrumb MsgBreadcrumbHiWis . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CNotesR) = i18nCrumb MsgBreadcrumbCourseNotes . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CNewsNewR) = i18nCrumb MsgMenuCourseNewsNew . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh (CourseNewsR cID sRoute)) = case sRoute of
CNShowR -> i18nCrumb MsgBreadcrumbCourseNews . Just $ CourseR tid ssh csh CShowR
CNEditR -> i18nCrumb MsgMenuCourseNewsEdit . Just $ CNewsR tid ssh csh cID CNShowR
CNDeleteR -> i18nCrumb MsgBreadcrumbCourseNewsDelete . Just $ CNewsR tid ssh csh cID CNShowR
CNArchiveR -> i18nCrumb MsgBreadcrumbCourseNewsArchive . Just $ CNewsR tid ssh csh cID CNShowR
CNFileR _ -> i18nCrumb MsgBreadcrumbCourseNewsFile . Just $ CNewsR tid ssh csh cID CNShowR
breadcrumb (CourseR tid ssh csh CEventsNewR) = i18nCrumb MsgMenuCourseEventNew . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh (CourseEventR _cID sRoute)) = case sRoute of
CEvEditR -> i18nCrumb MsgMenuCourseEventEdit . Just $ CourseR tid ssh csh CShowR
CEvDeleteR -> i18nCrumb MsgBreadcrumbCourseEventDelete . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CExamListR) = i18nCrumb MsgMenuExamList . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CExamNewR) = i18nCrumb MsgMenuExamNew . Just $ CourseR tid ssh csh CExamListR
breadcrumb (CourseR tid ssh csh CApplicationsR) = i18nCrumb MsgMenuCourseApplications . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh CAppsFilesR) = i18nCrumb MsgBreadcrumbCourseAppsFiles . Just $ CourseR tid ssh csh CApplicationsR
breadcrumb (CourseR tid ssh csh (CourseApplicationR cID sRoute)) = case sRoute of
CAEditR -> maybeT (i18nCrumb MsgBreadcrumbApplicant . Just $ CourseR tid ssh csh CApplicationsR) $ do
guardM . hasReadAccessTo $ CApplicationR tid ssh csh cID CAEditR
appId <- decrypt cID
User{..} <- hoist runDBRead $ MaybeT (get appId) >>= MaybeT . get . courseApplicationUser
return (userDisplayName, Just $ CourseR tid ssh csh CApplicationsR)
CAFilesR -> i18nCrumb MsgBreadcrumbApplicationFiles . Just $ CApplicationR tid ssh csh cID CAEditR
breadcrumb (CourseR tid ssh csh (ExamR examn sRoute)) = case sRoute of
EShowR -> maybeT (i18nCrumb MsgBreadcrumbExam . Just $ CourseR tid ssh csh CExamListR) $ do
guardM . hasReadAccessTo $ CExamR tid ssh csh examn EShowR
return (CI.original examn, Just $ CourseR tid ssh csh CExamListR)
EEditR -> i18nCrumb MsgMenuExamEdit . Just $ CExamR tid ssh csh examn EShowR
EUsersR -> i18nCrumb MsgMenuExamUsers . Just $ CExamR tid ssh csh examn EShowR
EAddUserR -> i18nCrumb MsgMenuExamAddMembers . Just $ CExamR tid ssh csh examn EUsersR
EGradesR -> i18nCrumb MsgMenuExamGrades . Just $ CExamR tid ssh csh examn EShowR
ECInviteR -> i18nCrumb MsgBreadcrumbExamCorrectorInvite . Just $ CExamR tid ssh csh examn EShowR
EInviteR -> i18nCrumb MsgBreadcrumbExamParticipantInvite . Just $ CExamR tid ssh csh examn EShowR
ERegisterR -> i18nCrumb MsgBreadcrumbExamRegister . Just $ CExamR tid ssh csh examn EShowR
ERegisterOccR _occn -> i18nCrumb MsgBreadcrumbExamRegister . Just $ CExamR tid ssh csh examn EShowR
EAutoOccurrenceR -> i18nCrumb MsgBreadcrumbExamAutoOccurrence . Just $ CExamR tid ssh csh examn EUsersR
ECorrectR -> i18nCrumb MsgMenuExamCorrect . Just $ CExamR tid ssh csh examn EShowR
breadcrumb (CourseR tid ssh csh (TutorialR tutn sRoute)) = case sRoute of
TUsersR -> maybeT (i18nCrumb MsgBreadcrumbTutorial . Just $ CourseR tid ssh csh CTutorialListR) $ do
guardM . hasReadAccessTo $ CTutorialR tid ssh csh tutn TUsersR
return (CI.original tutn, Just $ CourseR tid ssh csh CTutorialListR)
TEditR -> i18nCrumb MsgMenuTutorialEdit . Just $ CTutorialR tid ssh csh tutn TUsersR
TDeleteR -> i18nCrumb MsgMenuTutorialDelete . Just $ CTutorialR tid ssh csh tutn TUsersR
TCommR -> i18nCrumb MsgMenuTutorialComm . Just $ CTutorialR tid ssh csh tutn TUsersR
TRegisterR -> i18nCrumb MsgBreadcrumbTutorialRegister . Just $ CourseR tid ssh csh CShowR
TInviteR -> i18nCrumb MsgBreadcrumbTutorInvite . Just $ CTutorialR tid ssh csh tutn TUsersR
breadcrumb (CourseR tid ssh csh (SheetR shn sRoute)) = case sRoute of
SShowR -> maybeT (i18nCrumb MsgBreadcrumbSheet . Just $ CourseR tid ssh csh SheetListR) $ do
guardM . hasReadAccessTo $ CSheetR tid ssh csh shn SShowR
return (CI.original shn, Just $ CourseR tid ssh csh SheetListR)
SEditR -> i18nCrumb MsgMenuSheetEdit . Just $ CSheetR tid ssh csh shn SShowR
SDelR -> i18nCrumb MsgMenuSheetDelete . Just $ CSheetR tid ssh csh shn SShowR
SSubsR -> i18nCrumb MsgMenuSubmissions . Just $ CSheetR tid ssh csh shn SShowR
SAssignR -> i18nCrumb MsgMenuCorrectionsAssign . Just $ CSheetR tid ssh csh shn SSubsR
SubmissionNewR -> i18nCrumb MsgMenuSubmissionNew . Just $ CSheetR tid ssh csh shn SShowR
SubmissionOwnR -> i18nCrumb MsgMenuSubmissionOwn . Just $ CSheetR tid ssh csh shn SShowR
SubmissionR cid sRoute' -> case sRoute' of
SubShowR -> do
mayList <- hasReadAccessTo $ CSheetR tid ssh csh shn SSubsR
if
| mayList
-> i18nCrumb MsgBreadcrumbSubmission . Just $ CSheetR tid ssh csh shn SSubsR
| otherwise
-> i18nCrumb MsgBreadcrumbSubmission . Just $ CSheetR tid ssh csh shn SShowR
CorrectionR -> i18nCrumb MsgMenuCorrection . Just $ CSubmissionR tid ssh csh shn cid SubShowR
SubDelR -> i18nCrumb MsgMenuSubmissionDelete . Just $ CSubmissionR tid ssh csh shn cid SubShowR
SubAssignR -> i18nCrumb MsgCorrectorAssignTitle . Just $ CSubmissionR tid ssh csh shn cid SubShowR
SInviteR -> i18nCrumb MsgBreadcrumbSubmissionUserInvite . Just $ CSubmissionR tid ssh csh shn cid SubShowR
SubArchiveR sft -> i18nCrumb sft . Just $ CSubmissionR tid ssh csh shn cid SubShowR
SubDownloadR _ _ -> i18nCrumb MsgBreadcrumbSubmissionFile . Just $ CSubmissionR tid ssh csh shn cid SubShowR
SArchiveR -> i18nCrumb MsgBreadcrumbSheetArchive . Just $ CSheetR tid ssh csh shn SShowR
SIsCorrR -> i18nCrumb MsgBreadcrumbSheetIsCorrector . Just $ CSheetR tid ssh csh shn SShowR
SPseudonymR -> i18nCrumb MsgBreadcrumbSheetPseudonym . Just $ CSheetR tid ssh csh shn SShowR
SCorrInviteR -> i18nCrumb MsgBreadcrumbSheetCorrectorInvite . Just $ CSheetR tid ssh csh shn SShowR
SZipR sft -> i18nCrumb sft . Just $ CSheetR tid ssh csh shn SShowR
SFileR _ _ -> i18nCrumb MsgBreadcrumbSheetFile . Just $ CSheetR tid ssh csh shn SShowR
SPersonalFilesR -> i18nCrumb MsgBreadcrumbSheetPersonalisedFiles . Just $ CSheetR tid ssh csh shn SShowR
breadcrumb (CourseR tid ssh csh MaterialListR) = i18nCrumb MsgMenuMaterialList . Just $ CourseR tid ssh csh CShowR
breadcrumb (CourseR tid ssh csh MaterialNewR ) = i18nCrumb MsgMenuMaterialNew . Just $ CourseR tid ssh csh MaterialListR
breadcrumb (CourseR tid ssh csh (MaterialR mnm sRoute)) = case sRoute of
MShowR -> maybeT (i18nCrumb MsgBreadcrumbMaterial . Just $ CourseR tid ssh csh MaterialListR) $ do
guardM . hasReadAccessTo $ CMaterialR tid ssh csh mnm MShowR
return (CI.original mnm, Just $ CourseR tid ssh csh MaterialListR)
MEditR -> i18nCrumb MsgMenuMaterialEdit . Just $ CMaterialR tid ssh csh mnm MShowR
MDelR -> i18nCrumb MsgMenuMaterialDelete . Just $ CMaterialR tid ssh csh mnm MShowR
MArchiveR -> i18nCrumb MsgBreadcrumbMaterialArchive . Just $ CMaterialR tid ssh csh mnm MShowR
MFileR _ -> i18nCrumb MsgBreadcrumbMaterialFile . Just $ CMaterialR tid ssh csh mnm MShowR
MVideoR _ -> i18nCrumb MsgBreadcrumbMaterialVideo . Just $ CMaterialR tid ssh csh mnm MShowR
breadcrumb (CourseR tid ssh csh CPersonalFilesR) = i18nCrumb MsgBreadcrumbCourseSheetPersonalisedFiles . Just $ CourseR tid ssh csh CShowR
breadcrumb CorrectionsR = i18nCrumb MsgMenuCorrections Nothing
breadcrumb CorrectionsUploadR = i18nCrumb MsgMenuCorrectionsUpload $ Just CorrectionsR
breadcrumb CorrectionsCreateR = i18nCrumb MsgMenuCorrectionsCreate $ Just CorrectionsR
breadcrumb CorrectionsGradeR = i18nCrumb MsgMenuCorrectionsGrade $ Just CorrectionsR
breadcrumb CorrectionsDownloadR = i18nCrumb MsgMenuCorrectionsDownload $ Just CorrectionsR
breadcrumb (CryptoUUIDDispatchR _) = i18nCrumb MsgBreadcrumbCryptoIDDispatch Nothing
breadcrumb (MessageR _) = do
mayList <- (== Authorized) <$> evalAccess MessageListR False
if
| mayList -> i18nCrumb MsgBreadcrumbSystemMessage $ Just MessageListR
| otherwise -> i18nCrumb MsgBreadcrumbSystemMessage $ Just NewsR
breadcrumb MessageListR = i18nCrumb MsgMenuMessageList $ Just AdminR
breadcrumb (MessageHideR cID) = i18nCrumb MsgBreadcrumbMessageHide . Just $ MessageR cID
breadcrumb GlossaryR = i18nCrumb MsgMenuGlossary $ Just InfoR
breadcrumb EExamListR = i18nCrumb MsgMenuExternalExamList Nothing
breadcrumb EExamNewR = do
isEO <- hasReadAccessTo $ ExamOfficeR EOExamsR
i18nCrumb MsgBreadcrumbExternalExamNew . Just $ if
| isEO -> ExamOfficeR EOExamsR
| otherwise -> EExamListR
breadcrumb (EExamR tid ssh coursen examn sRoute) = case sRoute of
EEShowR -> do
isEO <- hasReadAccessTo $ ExamOfficeR EOExamsR
maybeT (i18nCrumb MsgBreadcrumbExternalExam . Just $ bool EExamListR (ExamOfficeR EOExamsR) isEO) $ do
guardM . hasReadAccessTo $ EExamR tid ssh coursen examn EEShowR
i18nCrumb (MsgBreadcrumbExternalExamShow coursen examn) . Just $ if
| isEO -> ExamOfficeR EOExamsR
| otherwise -> EExamListR
EEEditR -> i18nCrumb MsgBreadcrumbExternalExamEdit . Just $ EExamR tid ssh coursen examn EEShowR
EEUsersR -> i18nCrumb MsgBreadcrumbExternalExamUsers . Just $ EExamR tid ssh coursen examn EEShowR
EEGradesR -> i18nCrumb MsgBreadcrumbExternalExamGrades . Just $ EExamR tid ssh coursen examn EEShowR
EEStaffInviteR -> i18nCrumb MsgBreadcrumbExternalExamStaffInvite . Just $ EExamR tid ssh coursen examn EEShowR
EECorrectR -> i18nCrumb MsgBreadcrumbExternalExamCorrect . Just $ EExamR tid ssh coursen examn EEShowR
breadcrumb AdminWorkflowDefinitionListR = i18nCrumb MsgBreadcrumbAdminWorkflowDefinitionList $ Just AdminR
breadcrumb AdminWorkflowDefinitionNewR = i18nCrumb MsgBreadcrumbAdminWorkflowDefinitionNew $ Just AdminWorkflowDefinitionListR
breadcrumb (AdminWorkflowDefinitionR wfdScope wfdName sRoute) = case sRoute of
AWDEditR -> do
MsgRenderer mr <- getMsgRenderer
i18nCrumb (MsgBreadcrumbAdminWorkflowDefinitionEdit (mr wfdScope) wfdName) $ Just AdminWorkflowDefinitionListR
AWDDeleteR -> i18nCrumb MsgBreadcrumbAdminWorkflowDefinitionDelete . Just $ AdminWorkflowDefinitionR wfdScope wfdName AWDEditR
AWDInstantiateR -> i18nCrumb MsgBreadcrumbAdminWorkflowDefinitionInstantiate . Just $ AdminWorkflowDefinitionR wfdScope wfdName AWDEditR
breadcrumb AdminWorkflowInstanceListR = i18nCrumb MsgBreadcrumbAdminWorkflowInstanceList $ Just AdminWorkflowDefinitionListR
breadcrumb AdminWorkflowInstanceNewR = i18nCrumb MsgBreadcrumbAdminWorkflowInstanceNew $ Just AdminWorkflowInstanceListR
breadcrumb (AdminWorkflowInstanceR _cID sRoute) = case sRoute of
AWIEditR -> i18nCrumb MsgBreadcrumbAdminWorkflowInstanceEdit $ Just AdminWorkflowInstanceListR
breadcrumb AdminWorkflowWorkflowListR = i18nCrumb MsgBreadcrumbAdminWorkflowWorkflowList $ Just AdminWorkflowInstanceListR
breadcrumb AdminWorkflowWorkflowNewR = i18nCrumb MsgBreadcrumbAdminWorkflowWorkflowNew $ Just AdminWorkflowWorkflowListR
breadcrumb GlobalWorkflowInstanceListR = i18nCrumb MsgBreadcrumbGlobalWorkflowInstanceList Nothing
breadcrumb GlobalWorkflowInstanceNewR = i18nCrumb MsgBreadcrumbWorkflowInstanceNew $ Just GlobalWorkflowInstanceListR
breadcrumb (GlobalWorkflowInstanceR win sRoute) = case sRoute of
GWIEditR -> i18nCrumb (MsgBreadcrumbWorkflowInstanceEdit win) $ Just GlobalWorkflowInstanceListR
GWIDeleteR -> i18nCrumb MsgBreadcrumbWorkflowInstanceDelete . Just $ GlobalWorkflowInstanceR win GWIEditR
GWIWorkflowsR -> i18nCrumb MsgBreadcrumbWorkflowInstanceWorkflowList . Just $ GlobalWorkflowInstanceR win GWIEditR
GWIInitiateR -> do
mayEdit <- hasReadAccessTo $ GlobalWorkflowInstanceR win GWIEditR
i18nCrumb MsgBreadcrumbWorkflowInstanceInitiate . Just $ if
| mayEdit -> GlobalWorkflowInstanceR win GWIEditR
| otherwise -> GlobalWorkflowInstanceListR
breadcrumb GlobalWorkflowWorkflowListR = i18nCrumb MsgBreadcrumbWorkflowWorkflowList $ Just GlobalWorkflowInstanceListR
breadcrumb (GlobalWorkflowWorkflowR cID sRoute) = case sRoute of
GWWWorkflowR -> i18nCrumb (MsgBreadcrumbWorkflowWorkflow cID) $ Just GlobalWorkflowWorkflowListR
GWWFilesR _ _ -> i18nCrumb MsgBreadcrumbWorkflowWorkflowFiles . Just $ GlobalWorkflowWorkflowR cID GWWWorkflowR
GWWEditR -> i18nCrumb MsgBreadcrumbWorkflowWorkflowEdit . Just $ GlobalWorkflowWorkflowR cID GWWWorkflowR
GWWDeleteR -> i18nCrumb MsgBreadcrumbWorkflowWorkflowDelete . Just $ GlobalWorkflowWorkflowR cID GWWWorkflowR
breadcrumb TopWorkflowInstanceListR = i18nCrumb MsgBreadcrumbTopWorkflowInstanceList Nothing
breadcrumb TopWorkflowWorkflowListR = i18nCrumb MsgBreadcrumbTopWorkflowWorkflowList $ Just TopWorkflowInstanceListR
data NavQuickView
= NavQuickViewFavourite
| NavQuickViewPageActionSecondary
deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic, Typeable)
deriving (Universe, Finite)
navQuick :: NavQuickView -> (NavQuickView -> Any)
navQuick x x' = Any $ x == x'
data NavType
= NavTypeLink
{ navModal :: Bool
}
| NavTypeButton
{ navMethod :: StdMethod
, navData :: [(Text, Text)]
}
deriving (Eq, Ord, Read, Show, Generic, Typeable)
deriving anyclass (Binary)
makeLenses_ ''NavType
makePrisms ''NavType
data NavLevel = NavLevelTop | NavLevelInner
deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic, Typeable)
data NavHeaderRole = NavHeaderPrimary | NavHeaderSecondary
deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic, Typeable)
data NavLink = forall msg route. (RenderMessage UniWorX msg, HasRoute UniWorX route, RedirectUrl UniWorX route) => NavLink
{ navLabel :: msg
, navRoute :: route
, navDownload :: Maybe (Maybe (ConduitT () (Either FileReference DBFile) Handler ()))
, navAccess' :: Handler Bool
, navType :: NavType
, navQuick' :: NavQuickView -> Any
, navForceActive :: Bool
}
makeLenses_ ''NavLink
-- instance HasRoute UniWorX NavLink where
-- urlRoute NavLink{..} = urlRoute navRoute
-- instance RedirectUrl UniWorX NavLink where
-- toTextUrl NavLink{..} = toTextUrl navRoute
instance RenderMessage UniWorX NavLink where
renderMessage app ls NavLink{..} = renderMessage app ls navLabel
navBaseRoute :: NavLink -> Route UniWorX
navBaseRoute NavLink{navRoute} = urlRoute navRoute
navLinkRoute :: ( MonadHandler m, HandlerSite m ~ UniWorX
, MonadCrypto m
, MonadCryptoKey m ~ CryptoIDKey
, YesodAuthPersist UniWorX, AuthEntity UniWorX ~ User, AuthId UniWorX ~ UserId
)
=> NavLink -> m (SomeRoute UniWorX)
navLinkRoute NavLink{..} = case navDownload of
Nothing -> return $ SomeRoute navRoute
Just mSource -> withFileDownloadTokenMaybe' (transPipe liftHandler <$> mSource) navRoute
data Nav
= NavHeader
{ navHeaderRole :: NavHeaderRole
, navIcon :: Icon
, navLink :: NavLink
}
| NavHeaderContainer
{ navHeaderRole :: NavHeaderRole
, navLabel :: SomeMessage UniWorX
, navIcon :: Icon
, navChildren :: [NavLink]
}
| NavPageActionPrimary
{ navLink :: NavLink
, navChildren :: [NavLink]
}
| NavPageActionSecondary
{ navLink :: NavLink
}
| NavFooter
{ navLink :: NavLink
} deriving (Generic, Typeable)
makeLenses_ ''Nav
makePrisms ''Nav
data NavChildren
type instance Children NavChildren a = ChildrenNavChildren a
type family ChildrenNavChildren a where
ChildrenNavChildren (SomeMessage UniWorX) = '[]
ChildrenNavChildren a = Children ChGeneric a
navAccess :: (MonadHandler m, HandlerSite m ~ UniWorX, MonadCatch m, BearerAuthSite UniWorX) => Nav -> MaybeT m Nav
navAccess = execStateT $ do
guardM $ preuse _navLink >>= maybe (return True) navLinkAccess
_navChildren <~ (filterM navLinkAccess =<< use _navChildren)
whenM (hasn't _navLink <$> use id) $
guardM $ not . null <$> use _navChildren
navLinkAccess :: forall m. (MonadHandler m, HandlerSite m ~ UniWorX, MonadCatch m, BearerAuthSite UniWorX) => NavLink -> m Bool
navLinkAccess NavLink{..} = handle shortCircuit $ liftHandler navAccess' `and2M` accessCheck navType navRoute
where
shortCircuit :: HandlerContents -> m Bool
shortCircuit _ = return False
accessCheck :: HasRoute UniWorX route => NavType -> route -> m Bool
accessCheck nt (urlRoute -> route) = do
authCtx <- getAuthContext
$memcachedByHere (Just $ Right 120) (authCtx, nt, route) $
bool hasWriteAccessTo hasReadAccessTo (is _NavTypeLink nt) route
defaultLinks :: ( MonadHandler m
, HandlerSite m ~ UniWorX
, BearerAuthSite UniWorX
, BackendCompatible SqlReadBackend (YesodPersistBackend UniWorX)
) => m [Nav]
defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the header.
[ return NavHeader
{ navHeaderRole = NavHeaderSecondary
, navIcon = IconMenuLogout
, navLink = NavLink
{ navLabel = MsgMenuLogout
, navRoute = AuthR LogoutR
, navDownload = Nothing
, navAccess' = is _Just <$> maybeAuthId
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
, return NavHeader
{ navHeaderRole = NavHeaderSecondary
, navIcon = IconMenuLogin
, navLink = NavLink
{ navLabel = MsgMenuLogin
, navRoute = AuthR LoginR
, navDownload = Nothing
, navAccess' = is _Nothing <$> maybeAuthId
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
}
, return NavHeader
{ navHeaderRole = NavHeaderSecondary
, navIcon = IconMenuProfile
, navLink = NavLink
{ navLabel = MsgMenuProfile
, navRoute = ProfileR
, navDownload = Nothing
, navAccess' = is _Just <$> maybeAuthId
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
, do
mCurrentRoute <- getCurrentRoute
activeLang <- selectLanguage appLanguages
let navChildren = flip map (toList appLanguages) $ \lang -> NavLink
{ navLabel = MsgLanguage lang
, navRoute = (LangR, [(toPathPiece GetReferer, toPathPiece currentRoute) | currentRoute <- hoistMaybe mCurrentRoute ])
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeButton
{ navMethod = POST
, navData = [(toPathPiece PostLanguage, lang)]
}
, navQuick' = mempty
, navForceActive = lang == activeLang
}
guard $ length navChildren > 1
return NavHeaderContainer
{ navHeaderRole = NavHeaderSecondary
, navLabel = SomeMessage MsgMenuLanguage
, navIcon = IconLanguage
, navChildren
}
, do
mCurrentRoute <- getCurrentRoute
return NavHeader
{ navHeaderRole = NavHeaderSecondary
, navIcon = IconMenuHelp
, navLink = NavLink
{ navLabel = MsgMenuHelp
, navRoute = (HelpR, [(toPathPiece GetReferer, toPathPiece currentRoute) | currentRoute <- hoistMaybe mCurrentRoute ])
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
}
, return $ NavFooter NavLink
{ navLabel = MsgMenuDataProt
, navRoute = LegalR :#: ("data-protection" :: Text)
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, return $ NavFooter NavLink
{ navLabel = MsgMenuTermsUse
, navRoute = LegalR :#: ("terms-of-use" :: Text)
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, return $ NavFooter NavLink
{ navLabel = MsgMenuCopyright
, navRoute = LegalR :#: ("copyright" :: Text)
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, return $ NavFooter NavLink
{ navLabel = MsgMenuImprint
, navRoute = LegalR :#: ("imprint" :: Text)
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, return $ NavFooter NavLink
{ navLabel = MsgMenuInformation
, navRoute = InfoR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, return $ NavFooter NavLink
{ navLabel = MsgMenuFaq
, navRoute = FaqR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, return $ NavFooter NavLink
{ navLabel = MsgMenuGlossary
, navRoute = GlossaryR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, return NavHeader
{ navHeaderRole = NavHeaderPrimary
, navIcon = IconMenuNews
, navLink = NavLink
{ navLabel = MsgMenuNews
, navRoute = NewsR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
, return NavHeader
{ navHeaderRole = NavHeaderPrimary
, navIcon = IconMenuCourseList
, navLink = NavLink
{ navLabel = MsgMenuCourseList
, navRoute = CourseListR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
, return NavHeader
{ navHeaderRole = NavHeaderPrimary
, navIcon = IconMenuCorrections
, navLink = NavLink
{ navLabel = MsgMenuCorrections
, navRoute = CorrectionsR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
, return NavHeader
{ navHeaderRole = NavHeaderPrimary
, navIcon = IconMenuExams
, navLink = NavLink
{ navLabel = MsgMenuExamOfficeExams
, navRoute = ExamOfficeR EOExamsR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
, do
(haveInstances, haveWorkflows) <- liftHandler . runDB $ (,)
<$> haveTopWorkflowInstances
<*> haveTopWorkflowWorkflows
if | haveInstances -> return NavHeader
{ navHeaderRole = NavHeaderPrimary
, navIcon = IconMenuWorkflows
, navLink = NavLink
{ navLabel = MsgMenuTopWorkflowInstanceList
, navRoute = TopWorkflowInstanceListR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
| haveWorkflows -> return NavHeader
{ navHeaderRole = NavHeaderPrimary
, navIcon = IconMenuWorkflows
, navLink = NavLink
{ navLabel = MsgMenuTopWorkflowWorkflowListHeader
, navRoute = TopWorkflowWorkflowListR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
| otherwise -> mzero
, return NavHeaderContainer
{ navHeaderRole = NavHeaderPrimary
, navLabel = SomeMessage MsgAdminHeading
, navIcon = IconMenuAdmin
, navChildren =
[ NavLink
{ navLabel = MsgMenuUsers
, navRoute = UsersR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, NavLink
{ navLabel = MsgMenuSchoolList
, navRoute = SchoolListR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, NavLink
{ navLabel = MsgAdminFeaturesHeading
, navRoute = AdminFeaturesR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, NavLink
{ navLabel = MsgMenuMessageList
, navRoute = MessageListR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, NavLink
{ navLabel = MsgMenuAdminErrMsg
, navRoute = AdminErrMsgR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, NavLink
{ navLabel = MsgMenuAdminTokens
, navRoute = AdminTokensR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, NavLink
{ navLabel = MsgMenuAdminWorkflowDefinitionList
, navRoute = AdminWorkflowDefinitionListR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, NavLink
{ navLabel = MsgMenuAdminCrontab
, navRoute = AdminCrontabR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, NavLink
{ navLabel = MsgMenuAdminTest
, navRoute = AdminTestR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
]
}
, return NavHeaderContainer
{ navHeaderRole = NavHeaderPrimary
, navLabel = SomeMessage (mempty :: Text)
, navIcon = IconMenuExtra
, navChildren =
[ NavLink
{ navLabel = MsgMenuCourseNew
, navRoute = CourseNewR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, NavLink
{ navLabel = MsgMenuExternalExamList
, navRoute = EExamListR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, NavLink
{ navLabel = MsgMenuTermShow
, navRoute = TermShowR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, NavLink
{ navLabel = MsgMenuAllocationList
, navRoute = AllocationListR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, NavLink
{ navLabel = MsgInfoLecturerTitle
, navRoute = InfoLecturerR
, navDownload = Nothing
, navAccess' = hasWriteAccessTo CourseNewR
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
]
}
]
pageActions :: ( MonadHandler m
, HandlerSite m ~ UniWorX
, MonadCatch m
, BearerAuthSite UniWorX
, BackendCompatible SqlReadBackend (YesodPersistBackend UniWorX)
)
=> Route UniWorX -> m [Nav]
pageActions NewsR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuOpenCourses
, navRoute = (CourseListR, [("courses-openregistration", toPathPiece True)])
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuOpenAllocations
, navRoute = (AllocationListR, [("allocations-active", toPathPiece True)])
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions (CourseR tid ssh csh CShowR) = do
materialListSecondary <- pageQuickActions NavQuickViewPageActionSecondary $ CourseR tid ssh csh MaterialListR
tutorialListSecondary <- pageQuickActions NavQuickViewPageActionSecondary $ CourseR tid ssh csh CTutorialListR
sheetListSecondary <- pageQuickActions NavQuickViewPageActionSecondary $ CourseR tid ssh csh SheetListR
examListSecondary <- pageQuickActions NavQuickViewPageActionSecondary $ CourseR tid ssh csh CExamListR
membersSecondary <- pageQuickActions NavQuickViewPageActionSecondary $ CourseR tid ssh csh CUsersR
let examListBound :: Num a => a
examListBound = 4 -- guaranteed random; chosen by fair dice roll
examListExams <- liftHandler . runDBRead $ do
examNames <- E.select . E.from $ \(course `E.InnerJoin` exam) -> do
E.on $ exam E.^. ExamCourse E.==. course E.^. CourseId
E.where_ $ course E.^. CourseTerm E.==. E.val tid
E.&&. course E.^. CourseSchool E.==. E.val ssh
E.&&. course E.^. CourseShorthand E.==. E.val csh
E.limit $ succ examListBound
return $ exam E.^. ExamName
return $ do
E.Value examn <- examNames
return NavLink
{ navLabel = examn
, navRoute = CExamR tid ssh csh examn EShowR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewFavourite
, navForceActive = False
}
let showExamList = length examListExams <= examListBound
let
navMembers = NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCourseMembers
, navRoute = CourseR tid ssh csh CUsersR
, navDownload = Nothing
, navAccess' =
let courseWhere course = course <$ do
E.where_ $ course E.^. CourseTerm E.==. E.val tid
E.&&. course E.^. CourseSchool E.==. E.val ssh
E.&&. course E.^. CourseShorthand E.==. E.val csh
hasParticipants = E.selectExists . E.from $ \(course `E.InnerJoin` courseParticipant) -> do
E.on $ course E.^. CourseId E.==. courseParticipant E.^. CourseParticipantCourse
E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
void $ courseWhere course
mayRegister = hasWriteAccessTo $ CourseR tid ssh csh CAddUserR
in runDBRead $ mayRegister `or2M` hasParticipants
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewFavourite
, navForceActive = False
}
, navChildren = membersSecondary
}
showMembers <- maybeT (return False) $ True <$ navAccess navMembers
return $
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuMaterialList
, navRoute = CourseR tid ssh csh MaterialListR
, navDownload = Nothing
, navAccess' =
let lecturerAccess = hasWriteAccessTo $ CourseR tid ssh csh MaterialNewR -- Always show for lecturers to create new material
materialAccess mnm = hasReadAccessTo $ CMaterialR tid ssh csh mnm MShowR -- otherwise show only if the user can see at least one of the contents
existsVisible = do
matNames <- E.select . E.from $ \(course `E.InnerJoin` material) -> do
E.on $ course E.^. CourseId E.==. material E.^. MaterialCourse
E.where_ $ course E.^. CourseTerm E.==. E.val tid
E.&&. course E.^. CourseSchool E.==. E.val ssh
E.&&. course E.^. CourseShorthand E.==. E.val csh
return $ material E.^. MaterialName
anyM matNames (materialAccess . E.unValue)
in runDBRead $ lecturerAccess `or2M` existsVisible
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewFavourite
, navForceActive = False
}
, navChildren = materialListSecondary
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuSheetList
, navRoute = CourseR tid ssh csh SheetListR
, navDownload = Nothing
, navAccess' =
let lecturerAccess = hasWriteAccessTo $ CourseR tid ssh csh SheetNewR -- Always show for lecturers to create new sheets
sheetAccess shn = hasReadAccessTo $ CSheetR tid ssh csh shn SShowR -- othwerwise show only if the user can see at least one of the contents
existsVisible = do
sheetNames <- E.select . E.from $ \(course `E.InnerJoin` sheet) -> do
E.on $ course E.^. CourseId E.==. sheet E.^. SheetCourse
E.where_ $ course E.^. CourseTerm E.==. E.val tid
E.&&. course E.^. CourseSchool E.==. E.val ssh
E.&&. course E.^. CourseShorthand E.==. E.val csh
return $ sheet E.^. SheetName
anyM sheetNames $ sheetAccess . E.unValue
in runDBRead $ lecturerAccess `or2M` existsVisible
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewFavourite
, navForceActive = False
}
, navChildren = sheetListSecondary
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuTutorialList
, navRoute = CourseR tid ssh csh CTutorialListR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewFavourite
, navForceActive = False
}
, navChildren = tutorialListSecondary
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamList
, navRoute = CourseR tid ssh csh CExamListR
, navDownload = Nothing
, navAccess' =
let lecturerAccess = hasWriteAccessTo $ CourseR tid ssh csh CExamNewR
examAccess examn = hasReadAccessTo $ CExamR tid ssh csh examn EShowR
existsVisible = do
examNames <- E.select . E.from $ \(course `E.InnerJoin` exam) -> do
E.on $ course E.^. CourseId E.==. exam E.^. ExamCourse
E.where_ $ course E.^. CourseTerm E.==. E.val tid
E.&&. course E.^. CourseSchool E.==. E.val ssh
E.&&. course E.^. CourseShorthand E.==. E.val csh
return $ exam E.^. ExamName
anyM examNames $ examAccess . E.unValue
in runDBRead $ lecturerAccess `or2M` existsVisible
, navType = NavTypeLink { navModal = False }
, navQuick' = bool (navQuick NavQuickViewFavourite) mempty showExamList
, navForceActive = False
}
, navChildren = examListSecondary ++ guardOnM showExamList examListExams
}
, navMembers
] ++ guardOnM (not showMembers) [ NavPageActionPrimary{ navLink, navChildren = [] } | navLink <- membersSecondary ] ++
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCourseCommunication
, navRoute = CourseR tid ssh csh CCommR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewFavourite
, navForceActive = False
}
, navChildren = []
}
, NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuCourseExamOffice
, navRoute = CourseR tid ssh csh CExamOfficeR
, navDownload = Nothing
, navAccess' = do
uid <- requireAuthId
runDBRead $ do
cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh
E.selectExists $ do
(_school, isForced) <- courseExamOfficeSchools (E.val uid) (E.val cid)
E.where_ $ E.not_ isForced
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
}
, NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuCourseEdit
, navRoute = CourseR tid ssh csh CEditR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
, NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuCourseClone
, navRoute = ( CourseNewR
, [("tid", toPathPiece tid), ("ssh", toPathPiece ssh), ("csh", toPathPiece csh)]
)
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
, NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuCourseDelete
, navRoute = CourseR tid ssh csh CDeleteR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
]
pageActions (ExamOfficeR EOExamsR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamOfficeFields
, navRoute = ExamOfficeR EOFieldsR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamOfficeUsers
, navRoute = ExamOfficeR EOUsersR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions SchoolListR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuSchoolNew
, navRoute = SchoolNewR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions UsersR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuLecturerInvite
, navRoute = AdminNewFunctionaryInviteR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuUserAdd
, navRoute = AdminUserAddR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions (AdminUserR cID) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuUserNotifications
, navRoute = UserNotificationR cID
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuUserPassword
, navRoute = UserPasswordR cID
, navDownload = Nothing
, navAccess' = do
uid <- decrypt cID
User{userAuthentication} <- runDBRead $ get404 uid
return $ is _AuthPWHash userAuthentication
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions InfoR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgInfoLecturerTitle
, navRoute = InfoLecturerR
, navDownload = Nothing
, navAccess' = hasWriteAccessTo CourseNewR
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuLegal
, navRoute = LegalR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuFaq
, navRoute = FaqR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuGlossary
, navRoute = GlossaryR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions VersionR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgInfoLecturerTitle
, navRoute = InfoLecturerR
, navDownload = Nothing
, navAccess' = hasWriteAccessTo CourseNewR
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuLegal
, navRoute = LegalR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuFaq
, navRoute = FaqR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuGlossary
, navRoute = GlossaryR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions HealthR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuInstance
, navRoute = InstanceR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions InstanceR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuHealth
, navRoute = HealthR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions HelpR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuFaq
, navRoute = FaqR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgInfoLecturerTitle
, navRoute = InfoLecturerR
, navDownload = Nothing
, navAccess' = hasWriteAccessTo CourseNewR
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = do
(section, navLabel) <-
[ ("courses", MsgInfoLecturerCourses)
, ("exercises", MsgInfoLecturerExercises)
, ("tutorials", MsgInfoLecturerTutorials)
, ("exams", MsgInfoLecturerExams)
, ("allocations", MsgInfoLecturerAllocations)
] :: [(Text, UniWorXMessage)]
return NavLink
{ navLabel
, navRoute = InfoLecturerR :#: section
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuGlossary
, navRoute = GlossaryR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions ProfileR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuProfileData
, navRoute = ProfileDataR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuAuthPreds
, navRoute = AuthPredsR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgCsvOptions
, navRoute = CsvOptionsR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions TermShowR = do
participantsSecondary <- pageQuickActions NavQuickViewPageActionSecondary ParticipantsListR
return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuTermCreate
, navRoute = TermEditR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuParticipantsList
, navRoute = ParticipantsListR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = participantsSecondary
}
]
pageActions (AllocationR tid ssh ash AShowR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuAllocationInfo
, navRoute = InfoAllocationR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuAllocationUsers
, navRoute = AllocationR tid ssh ash AUsersR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuAllocationCompute
, navRoute = AllocationR tid ssh ash AComputeR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions (AllocationR tid ssh ash AUsersR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuAllocationPriorities
, navRoute = AllocationR tid ssh ash APriosR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuAllocationCompute
, navRoute = AllocationR tid ssh ash AComputeR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuAllocationAddUser
, navRoute = AllocationR tid ssh ash AAddUserR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions CourseListR = do
participantsSecondary <- pageQuickActions NavQuickViewPageActionSecondary ParticipantsListR
return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCourseNew
, navRoute = CourseNewR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuAllocationList
, navRoute = AllocationListR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuParticipantsList
, navRoute = ParticipantsListR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = participantsSecondary
}
]
pageActions CourseNewR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgInfoLecturerTitle
, navRoute = InfoLecturerR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions (CourseR tid ssh csh CCorrectionsR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCorrectionsAssign
, navRoute = CourseR tid ssh csh CAssignR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary <> navQuick NavQuickViewFavourite
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCorrectionsOwn
, navRoute = ( CorrectionsR
, [ ("corrections-term", toPathPiece tid)
, ("corrections-school", toPathPiece ssh)
, ("corrections-course", toPathPiece csh)
]
)
, navDownload = Nothing
, navAccess' = do
muid <- maybeAuthId
case muid of
Nothing -> return False
(Just uid) -> do
runDBRead . E.selectExists . E.from $ \(course `E.InnerJoin` sheet `E.InnerJoin` submission) -> do
E.on $ submission E.^. SubmissionSheet E.==. sheet E.^. SheetId
E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId
E.where_ $ submission E.^. SubmissionRatingBy E.==. E.just (E.val uid)
E.&&. course E.^. CourseTerm E.==. E.val tid
E.&&. course E.^. CourseSchool E.==. E.val ssh
E.&&. course E.^. CourseShorthand E.==. E.val csh
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
]
pageActions (CourseR tid ssh csh SheetListR) = do
correctionsSecondary <- pageQuickActions NavQuickViewPageActionSecondary $ CourseR tid ssh csh CCorrectionsR
let
navCorrections = NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuSubmissions
, navRoute = CourseR tid ssh csh CCorrectionsR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary <> navQuick NavQuickViewFavourite
, navForceActive = False
}
, navChildren = correctionsSecondary
}
showCorrections <- maybeT (return False) $ True <$ navAccess navCorrections
return $
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuSheetCurrent
, navRoute = CourseR tid ssh csh SheetCurrentR
, navDownload = Nothing
, navAccess' =
runDBRead . maybeT (return False) $ do
void . MaybeT $ sheetCurrent tid ssh csh
return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary <> navQuick NavQuickViewFavourite
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuSheetOldUnassigned
, navRoute = CourseR tid ssh csh SheetOldUnassignedR
, navDownload = Nothing
, navAccess' =
runDBRead . maybeT (return False) $ do
void . MaybeT $ sheetOldUnassigned tid ssh csh
return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary <> navQuick NavQuickViewFavourite
, navForceActive = False
}
, navChildren = []
}
, navCorrections
] ++ guardOnM (not showCorrections) [ NavPageActionPrimary{ navLink, navChildren = [] } | navLink <- correctionsSecondary ] ++
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuSheetNew
, navRoute = CourseR tid ssh csh SheetNewR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary <> navQuick NavQuickViewFavourite
, navForceActive = False
}
, navChildren = []
}
]
pageActions (CourseR tid ssh csh CUsersR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCourseAddMembers
, navRoute = CourseR tid ssh csh CAddUserR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCourseApplications
, navRoute = CourseR tid ssh csh CApplicationsR
, navDownload = Nothing
, navAccess' =
let courseWhere course = course <$ do
E.where_ $ course E.^. CourseTerm E.==. E.val tid
E.&&. course E.^. CourseSchool E.==. E.val ssh
E.&&. course E.^. CourseShorthand E.==. E.val csh
existsApplications = E.selectExists . E.from $ \(course `E.InnerJoin` courseApplication) -> do
E.on $ course E.^. CourseId E.==. courseApplication E.^. CourseApplicationCourse
void $ courseWhere course
courseApplications = fmap (any E.unValue) . E.select . E.from $ \course -> do
void $ courseWhere course
return $ course E.^. CourseApplicationsRequired
courseAllocation = E.selectExists . E.from $ \(course `E.InnerJoin` allocationCourse) -> do
E.on $ course E.^. CourseId E.==. allocationCourse E.^. AllocationCourseCourse
void $ courseWhere course
in runDBRead $ courseAllocation `or2M` courseApplications `or2M` existsApplications
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary <> navQuick NavQuickViewFavourite
, navForceActive = False
}
, navChildren = []
}
]
pageActions (CourseR tid ssh csh MaterialListR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuMaterialNew
, navRoute = CourseR tid ssh csh MaterialNewR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
]
pageActions (CMaterialR tid ssh csh mnm MShowR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuMaterialEdit
, navRoute = CMaterialR tid ssh csh mnm MEditR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuMaterialDelete
, navRoute = CMaterialR tid ssh csh mnm MDelR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
}
]
pageActions (CourseR tid ssh csh CTutorialListR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuTutorialNew
, navRoute = CourseR tid ssh csh CTutorialNewR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
]
pageActions (CTutorialR tid ssh csh tutn TEditR) = return
[ NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuTutorialDelete
, navRoute = CTutorialR tid ssh csh tutn TDeleteR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
]
pageActions (CTutorialR tid ssh csh tutn TUsersR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuTutorialComm
, navRoute = CTutorialR tid ssh csh tutn TCommR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuTutorialEdit
, navRoute = CTutorialR tid ssh csh tutn TEditR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuTutorialDelete
, navRoute = CTutorialR tid ssh csh tutn TDeleteR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
]
pageActions (CourseR tid ssh csh CExamListR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamNew
, navRoute = CourseR tid ssh csh CExamNewR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
]
pageActions (CExamR tid ssh csh examn EShowR) = do
usersSecondary <- pageQuickActions NavQuickViewPageActionSecondary $ CExamR tid ssh csh examn EUsersR
return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamEdit
, navRoute = CExamR tid ssh csh examn EEditR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamUsers
, navRoute = CExamR tid ssh csh examn EUsersR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = usersSecondary
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamGrades
, navRoute = CExamR tid ssh csh examn EGradesR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamCorrect
, navRoute = CExamR tid ssh csh examn ECorrectR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions (CExamR tid ssh csh examn ECorrectR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamUsers
, navRoute = CExamR tid ssh csh examn EUsersR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamGrades
, navRoute = CExamR tid ssh csh examn EGradesR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuExamEdit
, navRoute = CExamR tid ssh csh examn EEditR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
]
pageActions (CExamR tid ssh csh examn EUsersR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamAddMembers
, navRoute = CExamR tid ssh csh examn EAddUserR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamGrades
, navRoute = CExamR tid ssh csh examn EGradesR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamCorrect
, navRoute = CExamR tid ssh csh examn ECorrectR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions (CExamR tid ssh csh examn EGradesR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamUsers
, navRoute = CExamR tid ssh csh examn EUsersR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExamCorrect
, navRoute = CExamR tid ssh csh examn ECorrectR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions (CSheetR tid ssh csh shn SShowR) = do
subsSecondary <- pageQuickActions NavQuickViewPageActionSecondary $ CSheetR tid ssh csh shn SSubsR
let
navSubmissions = NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuSubmissions
, navRoute = CSheetR tid ssh csh shn SSubsR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = subsSecondary
}
showSubmissions <- maybeT (return False) $ True <$ navAccess navSubmissions
return $
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuSubmissionOwn
, navRoute = CSheetR tid ssh csh shn SubmissionOwnR
, navDownload = Nothing
, navAccess' =
runDBRead . maybeT (return False) $ do
uid <- MaybeT $ liftHandler maybeAuthId
submissions <- lift $ submissionList tid csh shn uid
guard . not $ null submissions
return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, navSubmissions
] ++ guardOnM (not showSubmissions) [ NavPageActionPrimary{ navLink, navChildren = [] } | navLink <- subsSecondary ] ++
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuSheetPersonalisedFiles
, navRoute = CSheetR tid ssh csh shn SPersonalFilesR
, navDownload = Nothing
, navAccess' =
let onlyPersonalised = fmap (maybe False $ not . E.unValue) . E.selectMaybe . E.from $ \(sheet `E.InnerJoin` course) -> do
E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId
E.where_$ sheet E.^. SheetName E.==. E.val shn
E.&&. course E.^. CourseTerm E.==. E.val tid
E.&&. course E.^. CourseSchool E.==. E.val ssh
E.&&. course E.^. CourseShorthand E.==. E.val csh
return $ sheet E.^. SheetAllowNonPersonalisedSubmission
hasPersonalised = E.selectExists . E.from $ \(sheet `E.InnerJoin` course `E.InnerJoin` personalisedSheetFile) -> do
E.on $ personalisedSheetFile E.^. PersonalisedSheetFileSheet E.==. sheet E.^. SheetId
E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId
E.where_$ sheet E.^. SheetName E.==. E.val shn
E.&&. course E.^. CourseTerm E.==. E.val tid
E.&&. course E.^. CourseSchool E.==. E.val ssh
E.&&. course E.^. CourseShorthand E.==. E.val csh
in runDBRead $ or2M onlyPersonalised hasPersonalised
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuSheetEdit
, navRoute = CSheetR tid ssh csh shn SEditR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuSheetClone
, navRoute = (CourseR tid ssh csh SheetNewR, [("shn", toPathPiece shn)])
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
, NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuSheetDelete
, navRoute = CSheetR tid ssh csh shn SDelR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
]
pageActions (CSheetR tid ssh csh shn SSubsR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuSubmissionNew
, navRoute = CSheetR tid ssh csh shn SubmissionNewR
, navDownload = Nothing
, navAccess' =
let submissionAccess = hasWriteAccessTo $ CSheetR tid ssh csh shn SSubsR
hasNoSubmission = maybeT (return False) $ do
uid <- MaybeT $ liftHandler maybeAuthId
submissions <- lift $ submissionList tid csh shn uid
guard $ null submissions
return True
in runDBRead $ hasNoSubmission `or2M` submissionAccess
, navType = NavTypeLink { navModal = True }
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCorrectionsOwn
, navRoute = ( CorrectionsR
, [ ("corrections-term", toPathPiece tid)
, ("corrections-school", toPathPiece ssh)
, ("corrections-course", toPathPiece csh)
, ("corrections-sheet", toPathPiece shn)
]
)
, navDownload = Nothing
, navAccess' = (== Authorized) <$> evalAccessCorrector tid ssh csh
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCorrectionsAssign
, navRoute = CSheetR tid ssh csh shn SAssignR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
]
pageActions (CSubmissionR tid ssh csh shn cid SubShowR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCorrection
, navRoute = CSubmissionR tid ssh csh shn cid CorrectionR
, navDownload = Nothing
, navAccess' = hasWriteAccessTo $ CSubmissionR tid ssh csh shn cid CorrectionR
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgCorrectorAssignTitle
, navRoute = CSubmissionR tid ssh csh shn cid SubAssignR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuSubmissionDelete
, navRoute = CSubmissionR tid ssh csh shn cid SubDelR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
]
pageActions (CSubmissionR tid ssh csh shn cid CorrectionR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgCorrectorAssignTitle
, navRoute = CSubmissionR tid ssh csh shn cid SubAssignR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuSubmissionDelete
, navRoute = CSubmissionR tid ssh csh shn cid SubDelR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
]
pageActions (CourseR tid ssh csh CApplicationsR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCourseApplicationsFiles
, navRoute = CourseR tid ssh csh CAppsFilesR
, navDownload = Just Nothing -- If `navAccess'` is True, we definitely have either exactly one generated file or more than one file
, navAccess' =
let appAccess (E.Value appId) = do
cID <- encrypt appId
hasReadAccessTo $ CApplicationR tid ssh csh cID CAFilesR
appSource = E.selectSource . E.from $ \(course `E.InnerJoin` courseApplication) -> do
E.on $ course E.^. CourseId E.==. courseApplication E.^. CourseApplicationCourse
E.where_ $ course E.^. CourseTerm E.==. E.val tid
E.&&. course E.^. CourseSchool E.==. E.val ssh
E.&&. course E.^. CourseShorthand E.==. E.val csh
E.where_ . E.exists . E.from $ \courseApplicationFile ->
E.where_ $ courseApplicationFile E.^. CourseApplicationFileApplication E.==. courseApplication E.^. CourseApplicationId
return $ courseApplication E.^. CourseApplicationId
in runDBRead . runConduit $ appSource .| anyMC appAccess
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCourseMembers
, navRoute = CourseR tid ssh csh CUsersR
, navDownload = Nothing
, navAccess' =
runDBRead $ do
cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh
exists [ CourseParticipantCourse ==. cid ]
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions CorrectionsR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCorrectionsDownload
, navRoute = CorrectionsDownloadR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCorrectionsUpload
, navRoute = CorrectionsUploadR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCorrectionsCreate
, navRoute = CorrectionsCreateR
, navDownload = Nothing
, navAccess' = runDBRead . maybeT (return False) $ do
uid <- MaybeT $ liftHandler maybeAuthId
sheets <- lift . E.select . E.from $ \(course `E.InnerJoin` sheet) -> do
E.on $ course E.^. CourseId E.==. sheet E.^. SheetCourse
let
isCorrector' = E.exists . E.from $ \sheetCorrector -> E.where_
$ sheetCorrector E.^. SheetCorrectorUser E.==. E.val uid
E.&&. sheetCorrector E.^. SheetCorrectorSheet E.==. sheet E.^. SheetId
isLecturer = E.exists . E.from $ \lecturer -> E.where_
$ lecturer E.^. LecturerUser E.==. E.val uid
E.&&. lecturer E.^. LecturerCourse E.==. course E.^. CourseId
E.where_ $ isCorrector' E.||. isLecturer
return $ sheet E.^. SheetSubmissionMode
return $ orOf (traverse . _Value . _submissionModeCorrector) sheets
, navType = NavTypeLink { navModal = False }
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCorrectionsGrade
, navRoute = CorrectionsGradeR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions CorrectionsGradeR = do
correctionsSecondary <- pageQuickActions NavQuickViewPageActionSecondary CorrectionsR
return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuCorrections
, navRoute = CorrectionsR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = correctionsSecondary
}
]
pageActions EExamListR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamNew
, navRoute = EExamNewR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions (EExamR tid ssh coursen examn EEShowR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamEdit
, navRoute = EExamR tid ssh coursen examn EEEditR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamUsers
, navRoute = EExamR tid ssh coursen examn EEUsersR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamGrades
, navRoute = EExamR tid ssh coursen examn EEGradesR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamCorrect
, navRoute = EExamR tid ssh coursen examn EECorrectR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions (EExamR tid ssh coursen examn EEGradesR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamCorrect
, navRoute = EExamR tid ssh coursen examn EECorrectR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamUsers
, navRoute = EExamR tid ssh coursen examn EEUsersR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamEdit
, navRoute = EExamR tid ssh coursen examn EEEditR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions (EExamR tid ssh coursen examn EECorrectR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamGrades
, navRoute = EExamR tid ssh coursen examn EEGradesR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamUsers
, navRoute = EExamR tid ssh coursen examn EEUsersR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamEdit
, navRoute = EExamR tid ssh coursen examn EEEditR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions (EExamR tid ssh coursen examn EEUsersR) = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamGrades
, navRoute = EExamR tid ssh coursen examn EEGradesR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamCorrect
, navRoute = EExamR tid ssh coursen examn EECorrectR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuExternalExamEdit
, navRoute = EExamR tid ssh coursen examn EEEditR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions ParticipantsListR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgCsvOptions
, navRoute = CsvOptionsR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuParticipantsIntersect
, navRoute = ParticipantsIntersectR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False}
, navQuick' = navQuick NavQuickViewPageActionSecondary
, navForceActive = False
}
, navChildren = []
}
]
pageActions AdminWorkflowDefinitionListR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuAdminWorkflowDefinitionNew
, navRoute = AdminWorkflowDefinitionNewR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuAdminWorkflowInstanceList
, navRoute = AdminWorkflowInstanceListR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions (AdminWorkflowDefinitionR wds wdn AWDEditR) = return
[ NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuAdminWorkflowDefinitionDelete
, navRoute = AdminWorkflowDefinitionR wds wdn AWDDeleteR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuAdminWorkflowDefinitionInstantiate
, navRoute = AdminWorkflowDefinitionR wds wdn AWDInstantiateR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = True }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions AdminWorkflowInstanceListR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuAdminWorkflowInstanceNew
, navRoute = AdminWorkflowInstanceNewR
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions route | Just (rScope, WorkflowInstanceListR) <- route ^? _WorkflowScopeRoute = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuWorkflowWorkflowList
, navRoute = _WorkflowScopeRoute # (rScope, WorkflowWorkflowListR)
, navDownload = Nothing
, navAccess' = runDB $ haveWorkflowWorkflows rScope
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions route | Just (rScope, WorkflowInstanceR win WIEditR) <- route ^? _WorkflowScopeRoute = return
[ NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuWorkflowInstanceDelete
, navRoute = _WorkflowScopeRoute # (rScope, WorkflowInstanceR win WIDeleteR)
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuWorkflowInstanceWorkflows
, navRoute = _WorkflowScopeRoute # (rScope, WorkflowInstanceR win WIWorkflowsR)
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
, NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuWorkflowInstanceInitiate
, navRoute = _WorkflowScopeRoute # (rScope, WorkflowInstanceR win WIInitiateR)
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions route | Just (rScope, WorkflowWorkflowR cID WWWorkflowR) <- route ^? _WorkflowScopeRoute = return
[ NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuWorkflowWorkflowEdit
, navRoute = _WorkflowScopeRoute # (rScope, WorkflowWorkflowR cID WWEditR)
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
, NavPageActionSecondary
{ navLink = NavLink
{ navLabel = MsgMenuWorkflowWorkflowDelete
, navRoute = _WorkflowScopeRoute # (rScope, WorkflowWorkflowR cID WWDeleteR)
, navDownload = Nothing
, navAccess' = return True
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
}
]
pageActions TopWorkflowInstanceListR = return
[ NavPageActionPrimary
{ navLink = NavLink
{ navLabel = MsgMenuTopWorkflowWorkflowList
, navRoute = TopWorkflowWorkflowListR
, navDownload = Nothing
, navAccess' = runDB haveTopWorkflowWorkflows
, navType = NavTypeLink { navModal = False }
, navQuick' = mempty
, navForceActive = False
}
, navChildren = []
}
]
pageActions _ = return []
submissionList :: ( MonadIO m
, BackendCompatible SqlReadBackend backend
)
=> TermId -> CourseShorthand -> SheetName -> UserId -> ReaderT backend m [E.Value SubmissionId]
submissionList tid csh shn uid = withReaderT (projectBackend @SqlReadBackend) . E.select . E.from $ \(course `E.InnerJoin` sheet `E.InnerJoin` submission `E.InnerJoin` submissionUser) -> do
E.on $ submissionUser E.^. SubmissionUserSubmission E.==. submission E.^. SubmissionId
E.on $ submission E.^. SubmissionSheet E.==. sheet E.^. SheetId
E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId
E.where_ $ submissionUser E.^. SubmissionUserUser E.==. E.val uid
E.&&. sheet E.^. SheetName E.==. E.val shn
E.&&. course E.^. CourseShorthand E.==. E.val csh
E.&&. course E.^. CourseTerm E.==. E.val tid
return $ submission E.^. SubmissionId
pageQuickActions :: ( MonadCatch m
, MonadHandler m
, HandlerSite m ~ UniWorX
, BearerAuthSite UniWorX
, BackendCompatible SqlReadBackend (YesodPersistBackend UniWorX)
)
=> NavQuickView -> Route UniWorX -> m [NavLink]
pageQuickActions qView route = do
items'' <- pageActions route
items' <- catMaybes <$> mapM (runMaybeT . navAccess) items''
filterM navLinkAccess $ items' ^.. typesUsing @NavChildren @NavLink . filtered (getAny . ($ qView) . navQuick')
-- | Verify that the currently logged in user is lecturer or corrector for at least one sheet for the given course
evalAccessCorrector
:: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX)
=> TermId -> SchoolId -> CourseShorthand -> m AuthResult
evalAccessCorrector tid ssh csh = evalAccess (CourseR tid ssh csh CNotesR) False
_haveWorkflowInstances, haveWorkflowWorkflows
:: ( MonadHandler m, HandlerSite m ~ UniWorX
, BackendCompatible SqlReadBackend backend
, BearerAuthSite UniWorX
)
=> RouteWorkflowScope
-> ReaderT backend m Bool
_haveWorkflowInstances rScope = hoist liftHandler . withReaderT (projectBackend @SqlReadBackend) . maybeT (return False) $ do
scope <- fromRouteWorkflowScope rScope
let checkAccess (Entity _ WorkflowInstance{..})
= hasReadAccessTo $ _WorkflowScopeRoute # (rScope, WorkflowInstanceR workflowInstanceName WIInitiateR)
getInstances = E.selectSource . E.from $ \workflowInstance -> do
E.where_ $ workflowInstance E.^. WorkflowInstanceScope E.==. E.val (scope ^. _DBWorkflowScope)
return workflowInstance
$cachedHereBinary scope . runConduit $ transPipe lift getInstances .| C.mapM checkAccess .| C.or
haveWorkflowWorkflows rScope = hoist liftHandler . withReaderT (projectBackend @SqlReadBackend) . maybeT (return False) $ do
scope <- fromRouteWorkflowScope rScope
let checkAccess (E.Value wwId) = do
cID <- lift . lift $ encrypt wwId
hasReadAccessTo $ _WorkflowScopeRoute # (rScope, WorkflowWorkflowR cID WWWorkflowR)
getWorkflows = E.selectSource . E.from $ \workflowWorkflow -> do
E.where_ $ workflowWorkflow E.^. WorkflowWorkflowScope E.==. E.val (scope ^. _DBWorkflowScope)
return $ workflowWorkflow E.^. WorkflowWorkflowId
$cachedHereBinary scope . runConduit $ transPipe lift getWorkflows .| C.mapM checkAccess .| C.or
haveTopWorkflowInstances, haveTopWorkflowWorkflows
:: ( MonadHandler m, HandlerSite m ~ UniWorX
, BackendCompatible SqlReadBackend backend
, BearerAuthSite UniWorX
)
=> ReaderT backend m Bool
haveTopWorkflowInstances = hoist liftHandler . withReaderT (projectBackend @SqlReadBackend) . maybeT (return False) $
let checkAccess (Entity _ WorkflowInstance{..}) = do
rScope <- toRouteWorkflowScope $ _DBWorkflowScope # workflowInstanceScope
hasReadAccessTo $ _WorkflowScopeRoute # (rScope, WorkflowInstanceR workflowInstanceName WIInitiateR)
getInstances = selectSource [] []
isTop (Entity _ WorkflowInstance{..}) = isTopWorkflowScope workflowInstanceScope
in $cachedHere . runConduit $ transPipe lift getInstances .| C.filter isTop .| C.mapM checkAccess .| C.or
haveTopWorkflowWorkflows = hoist liftHandler . withReaderT (projectBackend @SqlReadBackend) . maybeT (return False) $
let checkAccess (Entity wwId WorkflowWorkflow{..}) = do
rScope <- toRouteWorkflowScope $ _DBWorkflowScope # workflowWorkflowScope
cID <- lift . lift $ encrypt wwId
hasReadAccessTo $ _WorkflowScopeRoute # (rScope, WorkflowWorkflowR cID WWWorkflowR)
getWorkflows = selectSource [] []
isTop (Entity _ WorkflowWorkflow{..}) = isTopWorkflowScope workflowWorkflowScope
in $cachedHere . runConduit $ transPipe lift getWorkflows .| C.filter isTop .| C.mapM checkAccess .| C.or