diff --git a/messages/uniworx/categories/courses/courses/de-de-formal.msg b/messages/uniworx/categories/courses/courses/de-de-formal.msg index f558a6707..6999f2684 100644 --- a/messages/uniworx/categories/courses/courses/de-de-formal.msg +++ b/messages/uniworx/categories/courses/courses/de-de-formal.msg @@ -70,9 +70,9 @@ CourseInvalidInput: Eingaben bitte korrigieren. CourseEditTitle: Kursart editieren/anlegen CourseEditOk tid@TermId ssh@SchoolId csh@CourseShorthand: Kursart #{tid}-#{ssh}-#{csh} wurde erfolgreich geändert. CourseEditDupShort tid@TermId ssh@SchoolId csh@CourseShorthand: Kursart #{tid}-#{ssh}-#{csh} konnte nicht geändert werden: Es gibt bereits einen andere Kursart mit dem selben Kürzel oder Titel in diesem Jahr und Bereich. -CourseEditQualificationFail: Eine Qualifikation konnte uas unbekanntem Grund nicht mit diesem Kurs assoziert werden. -CourseEditQualificationFailRights qsh@QualificationShorthand ssh@SchoolId: Qualifikation #{qsh} konnte nicht mit diesem Kurs assoziert werden, da Ihre Berechtigungen für Bereich #{ssh} dazu nicht ausreichen. -CourseEditQualificationFailExists: Diese Qualifikation ist bereits assoziert +CourseEditQualificationFail: Eine Qualifikation konnte uas unbekanntem Grund nicht mit diesem Kurs assoziiert werden. +CourseEditQualificationFailRights qsh@QualificationShorthand ssh@SchoolId: Qualifikation #{qsh} konnte nicht mit diesem Kurs assoziiert werden, da Ihre Berechtigungen für Bereich #{ssh} dazu nicht ausreichen. +CourseEditQualificationFailExists: Diese Qualifikation ist bereits assoziiert CourseEditQualificationFailOrder: Diese Sortierpriorität existiert bereits CourseLecturer: Kursverwalter:in MailSubjectParticipantInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Einladung zur Kursartteilnahme diff --git a/messages/uniworx/categories/courses/exam/exam/de-de-formal.msg b/messages/uniworx/categories/courses/exam/exam/de-de-formal.msg index 5f8db47cf..eec50dfed 100644 --- a/messages/uniworx/categories/courses/exam/exam/de-de-formal.msg +++ b/messages/uniworx/categories/courses/exam/exam/de-de-formal.msg @@ -223,7 +223,7 @@ ExamRegisteredCountOf num@Int64 count@Int64 !ident-ok: #{num}/#{count} ExamOccurrences: Termine ExamOccurrencesCopied num@Int: #{pluralDEeN num "Prüfungstermin"} kopiert ExamOccurrencesEdited num@Int del@Int: #{pluralENsN num "Prüfungstermin"} geändert #{guardMonoid (del > 0) ("und " <> pluralENsN num "Prüfungstermin" <> " gelöscht")} -ExamOccurrenceCopyNoStartDate: Dieser Kurs hat noch keine eigene Termine um Prüfungstermine zeitlich damit zu assozieren +ExamOccurrenceCopyNoStartDate: Dieser Kurs hat noch keine eigene Termine um Prüfungstermine zeitlich damit zu assoziieren ExamOccurrenceCopyFail: Keine passenden Prüfungstermine zum Kopieren gefunden GradingFrom: Ab ExamNoShow: Nicht erschienen diff --git a/messages/uniworx/categories/firm/de-de-formal.msg b/messages/uniworx/categories/firm/de-de-formal.msg index 6ced6f20d..a182b3471 100644 --- a/messages/uniworx/categories/firm/de-de-formal.msg +++ b/messages/uniworx/categories/firm/de-de-formal.msg @@ -81,3 +81,5 @@ CompanyUserPriorityTip: Firmenpriorität ist lediglich relativ zu anderen Firmen CompanyUserUseCompanyAddress: Verwendet Firmenkontaktaddresse CompanyUserUseCompanyAddressTip: sofern im Benutzer keine Postanschrift hinterlegt ist CompanyUserUseCompanyPostalError: Postalische Adresse muss leer bleiben, damit die Firmenanschrift genutzt wird! +CompanySupervisorCompanyMissing fsh@CompanyShorthand: Empfänger ist nicht mit Firma #{fsh} aus Ansprechpartnerbeziehung assoziiert +CompanySuperviseeCompanyMissing fsh@CompanyShorthand: Betroffener ist nicht mit Firma #{fsh} aus Ansprechpartnerbeziehung assoziiert diff --git a/messages/uniworx/categories/firm/en-eu.msg b/messages/uniworx/categories/firm/en-eu.msg index 63159a817..4b29c9734 100644 --- a/messages/uniworx/categories/firm/en-eu.msg +++ b/messages/uniworx/categories/firm/en-eu.msg @@ -81,3 +81,5 @@ CompanyUserPriorityTip: Company priority is relative to other company associatio CompanyUserUseCompanyAddress: Use company postal address CompanyUserUseCompanyAddressTip: if and only if the postal address of the user is empty CompanyUserUseCompanyPostalError: Individual postal address must left empty for the company address to be used! +CompanySupervisorCompanyMissing fsh: Reciver is not associated with #{fsh} given as reroute reason +CompanySuperviseeCompanyMissing fsh: Supervisee is not associated with #{fsh} detailed as supervisonship reason \ No newline at end of file diff --git a/messages/uniworx/categories/settings/personal_settings/en-eu.msg b/messages/uniworx/categories/settings/personal_settings/en-eu.msg index 067811ab4..9a1974d2a 100644 --- a/messages/uniworx/categories/settings/personal_settings/en-eu.msg +++ b/messages/uniworx/categories/settings/personal_settings/en-eu.msg @@ -36,7 +36,7 @@ ProfileSuperviseeRemark n m: This person supervises #{pluralENsN n "person"}#{no UserTelephone: Phone UserMobile: Mobile -Company: Company affilitaion +Company: Company affiliation CompanyPersonalNumber: Personnel number CompanyPersonalNumberFraport: Personnel number (Fraport AG only) CompanyDepartment: Department \ No newline at end of file diff --git a/messages/uniworx/categories/user/de-de-formal.msg b/messages/uniworx/categories/user/de-de-formal.msg index 7d93442d5..b7cfebbe7 100644 --- a/messages/uniworx/categories/user/de-de-formal.msg +++ b/messages/uniworx/categories/user/de-de-formal.msg @@ -117,4 +117,5 @@ UserCompanyReason: Begründung der Firmenassoziation UserCompanyReasonTooltip: Optionale Notiz für besondere Fälle. Kann ggf. autmatische Entfernung bei AVS Firmenwechsel verhindern. UserSupervisorReason: Begründung Ansprechpartner UserSupervisorReasonTooltip: Optionale Notiz für besondere Fälle. Kann ggf. autmatische Entfernung bei AVS Firmenwechsel verhindern. +UserSupervisorCompany: Ansprechpartner wegen Firma AdminUserAllNotifications: Alle Benachrichtigungen and diesen Benutzer \ No newline at end of file diff --git a/messages/uniworx/categories/user/en-eu.msg b/messages/uniworx/categories/user/en-eu.msg index 61efbbb6d..5ca0bbf1c 100644 --- a/messages/uniworx/categories/user/en-eu.msg +++ b/messages/uniworx/categories/user/en-eu.msg @@ -117,4 +117,5 @@ UserCompanyReason: Reason for company association UserCompanyReasonTooltip: Optional note for special cases. In some case this may prevent automatic removel upon AVS user company changes. UserSupervisorReason: Reason for supervision UserSupervisorReasonTooltip: Optional note for special cases. In some case this may prevent automatic removel upon AVS user company changes. +UserSupervisorCompany: Supervisor for company AdminUserAllNotifications: All notification sent to this user \ No newline at end of file diff --git a/src/Handler/Profile.hs b/src/Handler/Profile.hs index 05ebfaa7c..7b75e3b7e 100644 --- a/src/Handler/Profile.hs +++ b/src/Handler/Profile.hs @@ -1130,7 +1130,7 @@ mkSupervisorsTable uid = dbTableWidget' validator DBTable{..} in if isReroute then iconCell IconReroute <> blankCell <> cellMailPrefPin (row ^. resultUser) else mempty - , sortable (Just "cshort") (i18nCell MsgTableCompany) $ \(view $ resultUserSupervisor . _entityVal . _userSupervisorCompany -> mc) -> maybeCell mc (\(unCompanyKey -> c) -> anchorCell (FirmUsersR c) $ citext2widget c) + , sortable (Just "cshort") (i18nCell MsgTableCompany) $ \(view $ resultUserSupervisor . _entityVal . _userSupervisorCompany -> mc) -> maybeCell mc companyIdCell , sortable (Just "reason") (i18nCell MsgTableReason) $ \(view $ resultUserSupervisor . _entityVal . _userSupervisorReason -> mr) -> maybeCell mr textCell ] validator = def & defaultSorting [ SortAscBy "cshort", SortAscBy "user-name" ] @@ -1180,7 +1180,7 @@ mkSuperviseesTable userPrefersPostal uid = dbTableWidget' validator DBTable{..} , sortable (Just "reroute") (i18nCell MsgTableRerouteActive) $ \row -> let isReroute = row ^. resultUserSupervisor . _entityVal ._userSupervisorRerouteNotifications in boolCell isReroute $ iconCell IconReroute <> iconCellLetterOrEmail - , sortable (Just "cshort") (i18nCell MsgTableCompany) $ \(view $ resultUserSupervisor . _entityVal . _userSupervisorCompany -> mc) -> maybeCell mc (\(unCompanyKey -> c) -> anchorCell (FirmUsersR c) $ citext2widget c) + , sortable (Just "cshort") (i18nCell MsgTableCompany) $ \(view $ resultUserSupervisor . _entityVal . _userSupervisorCompany -> mc) -> maybeCell mc companyIdCell , sortable (Just "reason") (i18nCell MsgTableReason) $ \(view $ resultUserSupervisor . _entityVal . _userSupervisorReason -> mr) -> maybeCell mr textCell ] validator = def & defaultSorting [ SortAscBy "cshort", SortAscBy "user-name" ] @@ -1213,8 +1213,8 @@ instance HasUser TblReceiverData where hasUser = _dbrOutput . _1 . _entityVal -- | Table listing all supervisor of the given user -mkReceiversTable :: UserId -> [Entity User] -> DB Widget -mkReceiversTable uid receivers = dbTableDB' validator DBTable{..} +mkReceiversTable :: UserId -> [CompanyShorthand] -> [Entity User] -> DB Widget +mkReceiversTable uid usrCmps receivers = dbTableDB' validator DBTable{..} where dbtIdent = "receivers" :: Text dbtStyle = def @@ -1240,6 +1240,7 @@ mkReceiversTable uid receivers = dbTableDB' validator DBTable{..} dbtColonnade = mconcat [ colUserNameModalHdr MsgCommRecipients ForProfileDataR -- , colUserEmail + -- , colUserLetterEmailPin , sortable Nothing (i18nCell MsgAddress) $ \(view resultReceiver -> rcvr) -> sqlCell $ -- recall: requires dbTableDB' above! getPostalPreferenceAndAddress' rcvr >>= \case (False, _, (Just eml, auto)) -> do -- email @@ -1259,39 +1260,49 @@ mkReceiversTable uid receivers = dbTableDB' validator DBTable{..} #{postal} |] _ -> return $ msg2widget MsgNoContactAddress - , sortable (Just "user-company") (i18nCell MsgTableCompanies) $ \(view $ resultReceiver . _entityKey -> ruid) -> sqlCell - (maybeMonoid <$> wgtCompanies ruid) -- TODO: user wgtCompanies' to check mismatch in companies - -- , colUserLetterEmailPin - -- , sortable (Just "rerouted") (i18nCell MsgTableRerouteActive) $ \(view $ resultUserSupervisor . _entityVal . _userSupervisorRerouteNotifications -> b) -> indicatorCell <> ifIconCell b IconReroute - -- , sortable (Just "postal-pref") (i18nCell MsgPrefersPostal) $ \(view $ resultUser . _userPrefersPostal -> b) -> iconFixedCell $ iconLetterOrEmail b - -- , sortable (Just "reroute") (i18nCell MsgTableRerouteActive) $ \row -> - -- let isReroute = row ^. resultUserSupervisor . _entityVal ._userSupervisorRerouteNotifications - -- in if isReroute - -- then iconCell IconReroute <> blankCell <> cellMailPrefPin (row ^. resultUser) - -- else mempty - , sortable (Just "cshort") (i18nCell MsgTableCompany) $ \(preview $ resultReceiverSupervisor . _entityVal . _userSupervisorCompany . _Just -> mc) -> maybeCell mc (\(unCompanyKey -> c) -> anchorCell (FirmUsersR c) $ citext2widget c) - , sortable (Just "reason") (i18nCell MsgTableReason) $ \(preview $ resultReceiverSupervisor . _entityVal . _userSupervisorReason . _Just -> mr) -> maybeCell mr textCell + , sortable (Just "user-company") (i18nCell MsgTableCompanies) $ \row -> sqlCell $ do + let ruid = row ^. resultReceiver . _entityKey + rcmp = row ^? resultReceiverSupervisor . _entityVal . _userSupervisorCompany . _Just . to unCompanyKey + errWgt fsh = let emsg = MsgCompanySupervisorCompanyMissing fsh + in [whamlet|^{messageTooltip =<< messageI Error emsg} _{emsg}|] + cmps <- wgtCompanies' ruid + return $ case (cmps, rcmp) of + (Just (cwgt, cmpsData), Just svcsh) + | svcsh `notElem` (cmpsData ^.. traverse . _1) -> + [whamlet|$newline never +
+ ^{errWgt svcsh} + |] + (Just (cwgt,_),_) -> [whamlet|
^{messageTooltip =<< messageI Error emsg} _{emsg}|] + in case mc of + Nothing -> mempty + (Just sfid@(unCompanyKey -> sfsh)) + | notNull usrCmps + , sfsh `notElem` usrCmps -> companyIdCell sfid <> wgtCell (errWgt sfsh) + | otherwise -> companyIdCell sfid ] validator = def -- & defaultSorting [ SortAscBy "cshort", SortAscBy "user-name" ] dbtSorting = Map.fromList [ sortUserNameLink queryReceiver -- , sortUserLetterEmailPin queryReceiver - , sortUserEmail queryReceiver + -- , sortUserEmail queryReceiver , ("user-company" , SortColumn (\row -> E.subSelect $ do (cmp :& usrCmp) <- E.from $ E.table @Company `E.innerJoin` E.table @UserCompany `E.on` (\(cmp :& usrCmp) -> cmp E.^. CompanyId E.==. usrCmp E.^. UserCompanyCompany) E.where_ $ usrCmp E.^. UserCompanyUser E.==. queryReceiver row E.^. UserId E.orderBy [E.asc $ cmp E.^. CompanyName] return (cmp E.^. CompanyName) )) - -- , singletonMap "postal-pref" $ SortColumn $ queryUser >>> (E.^. UserPrefersPostal) - -- , singletonMap "rerouted" $ SortColumn $ queryUserSupervisor >>> (E.^. UserSupervisorRerouteNotifications) - -- -- , singletonMap "reroute" $ SortColumn $ queryUserSupervisor &&& queryUser >>> (\(spr,usr) -> mTuple (spr E.^. UserSupervisorRerouteNotifications) (usr E.^. UserPrefersPostal)) - -- , singletonMap "reroute" $ SortColumns $ \row -> - -- [ SomeExprValue $ queryUserSupervisor row E.^. UserSupervisorRerouteNotifications - -- , SomeExprValue $ queryUser row E.^. UserPrefersPostal - -- ] - , ("cshort", SortColumn $ queryReceiverSupervisor >>> (E.?. UserSupervisorCompany)) , ("reason", SortColumn $ queryReceiverSupervisor >>> (E.?. UserSupervisorReason)) + , ("cshort", SortColumn $ queryReceiverSupervisor >>> (E.?. UserSupervisorCompany)) ] dbtFilter = mconcat [ singletonMap & uncurry $ fltrUserNameEmail queryReceiver @@ -1458,16 +1469,18 @@ postLangR = do getUserRecipientsR :: CryptoUUIDUser -> Handler Html getUserRecipientsR uuid = do uid <- decrypt uuid - (usr, receivers, usrReceives) <- updateReceivers uid -- if this is two due to the AVS queries, try Handler.Utils.getReceivers instead + (usr, receivers, usrReceives) <- updateReceivers uid -- use Handler.Utils.getReceivers instead to avoid AVS queries mrtbl <- case receivers of [] -> return Nothing -- no receivers [_] | usrReceives -> return Nothing -- only user receives for themself - _ -> Just <$> runDB (mkReceiversTable uid receivers) + _ -> runDB $ do + usrCmps <- wgtCompanies' uid + let fshs :: [CompanyShorthand] = usrCmps ^.. _Just . _2 . traverse . _1 + rtbl <- mkReceiversTable uid fshs receivers + return $ Just (rtbl, fst <$> usrCmps) let heading = MsgUserRecipientsTitle $ usr ^. _userDisplayName - usrWgt = userWidget usr - hasPwd = isJust $ usr ^. _userPinPassword + usrWgt = userWidget usr + hasPwd = isJust $ usr ^. _userPinPassword siteLayoutMsg heading $ do setTitleI heading $(i18nWidgetFile "user-receivers") - - diff --git a/src/Handler/Utils/Company.hs b/src/Handler/Utils/Company.hs index 21f9a4ef8..99ed65a7a 100644 --- a/src/Handler/Utils/Company.hs +++ b/src/Handler/Utils/Company.hs @@ -2,6 +2,7 @@ -- -- SPDX-License-Identifier: AGPL-3.0-or-later +{-# LANGUAGE BlockArguments #-} -- do starts is own block {-# OPTIONS_GHC -fno-warn-orphans #-} module Handler.Utils.Company where @@ -38,38 +39,40 @@ company2msg :: CompanyId -> SomeMessage UniWorX company2msg = text2message . ciOriginal . unCompanyKey wgtCompanies :: UserId -> DB (Maybe Widget) -wgtCompanies = (fst <<$>>) . wgtCompanies' +wgtCompanies = (wrapUL . fst <<$>>) . wgtCompanies' + where + wrapUL wgt = [whamlet|
+
+
^{tbl} +
+ $maybe usrCmps <- mbUsrCmps +
^{tbl} +
+ $maybe usrCmps <- mbUsrCmps +