Skip to content
Snippets Groups Projects
Commit a38bfe98 authored by Jan-Hendrik Willms's avatar Jan-Hendrik Willms
Browse files

restructure avatar menu and account for personal notifications being disabled, fixes #5065

Closes #5065

Merge request studip/studip!3792
parent 8a97b384
No related branches found
No related tags found
No related merge requests found
...@@ -17,7 +17,7 @@ class NavigationWidget extends LinksWidget ...@@ -17,7 +17,7 @@ class NavigationWidget extends LinksWidget
* @param Icon $icon (not used) * @param Icon $icon (not used)
* @param array $attributes Optional attributes fot the generated link * @param array $attributes Optional attributes fot the generated link
* @param mixed $index Index to use for the element * @param mixed $index Index to use for the element
* @return String * @return LinkElement
*/ */
public function &addLink($label, $url, $icon = null, $attributes = [], $index = null) public function &addLink($label, $url, $icon = null, $attributes = [], $index = null)
{ {
......
...@@ -132,14 +132,16 @@ class PersonalNotifications extends SimpleORMap ...@@ -132,14 +132,16 @@ class PersonalNotifications extends SimpleORMap
* Returns all notifications fitting to the parameters. * Returns all notifications fitting to the parameters.
* @param boolean $only_unread : true for getting only unread notifications, false for all. * @param boolean $only_unread : true for getting only unread notifications, false for all.
* @param null|string $user_id : ID of special user the notification should belong to or (default:) null for current user * @param null|string $user_id : ID of special user the notification should belong to or (default:) null for current user
* @return array of \PersonalNotifications in ascending order of mkdate * @return static[] array of \PersonalNotifications in ascending order of mkdate
*/ */
public static function getMyNotifications($only_unread = true, $user_id = null, $limit = 15) public static function getMyNotifications($only_unread = true, $user_id = null, $limit = 15)
{ {
if (!$user_id) { if (!self::isActivated($user_id)) {
$user_id = $GLOBALS['user']->id; return [];
} }
$user_id ??= $GLOBALS['user']->id;
$cached = self::getCache($user_id); $cached = self::getCache($user_id);
if ($cached === false) { if ($cached === false) {
$query = "SELECT pn.*, COUNT(DISTINCT personal_notification_id) - 1 AS unseen $query = "SELECT pn.*, COUNT(DISTINCT personal_notification_id) - 1 AS unseen
...@@ -373,7 +375,7 @@ class PersonalNotifications extends SimpleORMap ...@@ -373,7 +375,7 @@ class PersonalNotifications extends SimpleORMap
if (!$user_id) { if (!$user_id) {
$user_id = $GLOBALS['user']->id; $user_id = $GLOBALS['user']->id;
} }
return (new UserConfig($user_id))->getValue('PERSONAL_NOTIFICATIONS_DEACTIVATED') ? false : true; return !UserConfig::get($user_id)->getValue('PERSONAL_NOTIFICATIONS_DEACTIVATED');
} }
/** /**
...@@ -385,13 +387,32 @@ class PersonalNotifications extends SimpleORMap ...@@ -385,13 +387,32 @@ class PersonalNotifications extends SimpleORMap
*/ */
public static function isAudioActivated($user_id = null) public static function isAudioActivated($user_id = null)
{ {
if (!PersonalNotifications::isGloballyActivated()) { if (!PersonalNotifications::isGloballyActivated() || !self::isActivated($user_id)) {
return false; return false;
} }
if (!$user_id) { if (!$user_id) {
$user_id = $GLOBALS['user']->id; $user_id = $GLOBALS['user']->id;
} }
return UserConfig::get($user_id)->getValue("PERSONAL_NOTIFICATIONS_AUDIO_DEACTIVATED") ? false : true; return ! UserConfig::get($user_id)->getValue("PERSONAL_NOTIFICATIONS_AUDIO_DEACTIVATED");
}
/**
* Returns whether there are any new/unseen notifications for the given
* user id.
*/
public static function hasUnseenNotifications(?string $user_id = null): bool
{
if (!self::isActivated($user_id)) {
return false;
}
$user_id ??= User::findCurrent()->id;
$lastvisit = (int) UserConfig::get($user_id)->getValue('NOTIFICATIONS_SEEN_LAST_DATE');
return array_any(
self::getMyNotifications(user_id: $user_id),
fn($notification) => $notification['mkdate'] > $lastvisit
);
} }
/** /**
......
...@@ -222,13 +222,9 @@ ...@@ -222,13 +222,9 @@
img { img {
height: 26px; height: 26px;
width: 26px; width: 26px;
border-top-right-radius: var(--border-radius-avatar-menu); border-radius: var(--border-radius-avatar-menu);
border-bottom-right-radius: var(--border-radius-avatar-menu);
} }
#notification-container + & {
border-left: 0;
}
} }
.action-menu-title { .action-menu-title {
...@@ -259,6 +255,13 @@ ...@@ -259,6 +255,13 @@
} }
} }
} }
#notification-container + #avatar-menu {
.action-menu-icon img {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
} }
// Fix header covering relevant other areas // Fix header covering relevant other areas
......
...@@ -118,38 +118,35 @@ if ($navigation) { ...@@ -118,38 +118,35 @@ if ($navigation) {
<? endif; ?> <? endif; ?>
<? endif; ?> <? endif; ?>
<? if (is_object($GLOBALS['perm']) && $GLOBALS['perm']->have_perm('user')): ?> <? if (is_object($GLOBALS['perm']) && $GLOBALS['perm']->have_perm('user')): ?>
<? $active = Navigation::hasItem('/profile') <? $active = Navigation::getItem('/profile')?->isActive() ?? false; ?>
&& Navigation::getItem('/profile')->isActive();
?>
<? if (is_object($GLOBALS['perm']) && PersonalNotifications::isActivated() && $GLOBALS['perm']->have_perm('autor')) : ?>
<? if ($GLOBALS['perm']->have_perm('autor')) : ?>
<li id="avatar-menu-container"
class="header_avatar_container <?= PersonalNotifications::hasUnseenNotifications() ? 'alert' : '' ?>"
>
<? if (PersonalNotifications::isActivated()): ?>
<? $notifications = PersonalNotifications::getMyNotifications() ?> <? $notifications = PersonalNotifications::getMyNotifications() ?>
<? $lastvisit = (int)UserConfig::get($GLOBALS['user']->id)->getValue('NOTIFICATIONS_SEEN_LAST_DATE') ?>
<? foreach ($notifications as $notification) {
if ($notification['mkdate'] > $lastvisit) {
$alert = true;
}
} ?>
<!-- User-Avatar -->
<li class="header_avatar_container <?= !empty($alert) ? 'alert' : '' ?> <? if ($active) echo 'active'; ?>" id="avatar-menu-container">
<div id="notification-container" <?= count($notifications) > 0 ? ' class="hoverable"' : '' ?>> <div id="notification-container" <?= count($notifications) > 0 ? ' class="hoverable"' : '' ?>>
<button id="notification_marker"
<button id="notification_marker" data-toggles="#notification_checkbox" <?= !empty($alert) ? ' class="alert"' : "" ?> data-toggles="#notification_checkbox"
title="<?= sprintf( title="<?= sprintf(
ngettext('%u Benachrichtigung', '%u Benachrichtigungen', count($notifications)), ngettext('%u Benachrichtigung', '%u Benachrichtigungen', count($notifications)),
count($notifications) count($notifications)
) ?>" data-lastvisit="<?= $lastvisit ?>" ) ?>"
<?= count($notifications) == 0 ? 'disabled' : '' ?> aria-controls="notification-list" aria-controls="notification-list"
aria-expanded="false"> data-lastvisit="<?= UserConfig::get($GLOBALS['user']->id)->getValue('NOTIFICATIONS_SEEN_LAST_DATE') ?>"
<? if (count($notifications) === 0) echo 'disabled'; ?>
<? if (PersonalNotifications::hasUnseenNotifications()) echo 'class="alert"'; ?>
aria-expanded="false"
>
<span class="count" aria-hidden="true"><?= count($notifications) ?></span> <span class="count" aria-hidden="true"><?= count($notifications) ?></span>
</button> </button>
<input type="checkbox" id="notification_checkbox"> <input type="checkbox" id="notification_checkbox">
<div class="list below" id="notification_list"> <div class="list below" id="notification_list">
<a class="mark-all-as-read <? if (count($notifications) < 2) echo 'invisible'; ?>" href="<?= URLHelper::getLink('dispatch.php/jsupdater/mark_notification_read/all', ['return_to' => $_SERVER['REQUEST_URI']]) ?>"> <a class="mark-all-as-read <? if (count($notifications) < 2) echo 'invisible'; ?>"
href="<?= URLHelper::getLink('dispatch.php/jsupdater/mark_notification_read/all', ['return_to' => $_SERVER['REQUEST_URI']]) ?>"
>
<?= _('Alle Benachrichtigungen als gelesen markieren') ?> <?= _('Alle Benachrichtigungen als gelesen markieren') ?>
</a> </a>
<a class="enable-desktop-notifications" href="#" style="display: none;"> <a class="enable-desktop-notifications" href="#" style="display: none;">
...@@ -173,43 +170,44 @@ if ($navigation) { ...@@ -173,43 +170,44 @@ if ($navigation) {
<? if (Navigation::hasItem('/avatar')): ?> <? if (Navigation::hasItem('/avatar')): ?>
<form id="avatar-menu" method="post"> <form id="avatar-menu" method="post">
<?php <?php
$action_menu = ContentGroupMenu::get(); $action_menu = ContentGroupMenu::get();
$action_menu->addCSSClass('avatar-menu'); $action_menu->addCSSClass('avatar-menu');
$action_menu->addAttribute('data-action-menu-reposition', 'false'); $action_menu->addAttribute('data-action-menu-reposition', 'false');
$action_menu->setLabel(User::findCurrent()->getFullName()); $action_menu->setLabel(User::findCurrent()->getFullName());
$action_menu->setAriaLabel(_('Profilmenü')); $action_menu->setAriaLabel(_('Profilmenü'));
$action_menu->setIcon( $action_menu->setIcon(
Avatar::getAvatar(User::findCurrent()->id)->getImageTag(Avatar::MEDIUM), Avatar::getAvatar(User::findCurrent()->id)->getImageTag(),
['id' => 'header_avatar_image_link'] ['id' => 'header_avatar_image_link']
); );
foreach (Navigation::getItem('/avatar') as $subnav) { foreach (Navigation::getItem('/avatar') as $subnav) {
if ($subnav->getRenderAsButton()) { if ($subnav->getRenderAsButton()) {
$action_menu->addButton( $action_menu->addButton(
'logout', 'logout',
$subnav->getTitle(), $subnav->getTitle(),
$subnav->getImage(), $subnav->getImage(),
array_merge( array_merge(
$subnav->getLinkAttributes(), $subnav->getLinkAttributes(),
['formaction' => URLHelper::getURL($subnav->getURL(), [], true)] ['formaction' => URLHelper::getURL($subnav->getURL(), [], true)]
) )
); );
} else { } else {
$action_menu->addLink( $action_menu->addLink(
URLHelper::getURL($subnav->getURL(), [], true), URLHelper::getURL($subnav->getURL(), [], true),
$subnav->getTitle(), $subnav->getTitle(),
$subnav->getImage(), $subnav->getImage(),
$subnav->getLinkAttributes() $subnav->getLinkAttributes()
); );
}
} }
} SkipLinks::addIndex(_('Profilmenü'), 'header_avatar_image_link', 1, false);
SkipLinks::addIndex(_('Profilmenü'), 'header_avatar_image_link', 1, false);
?> ?>
<?= $action_menu->render(); ?> <?= $action_menu->render(); ?>
</form> </form>
<? endif; ?> <? endif; ?>
</li> </li>
<? else: ?> <? endif; ?>
<? else: ?>
<li> <li>
<form method="post" action="<?= URLHelper::getLink(Request::url(), ['cancel_login' => null]) ?>"> <form method="post" action="<?= URLHelper::getLink(Request::url(), ['cancel_login' => null]) ?>">
<? try {echo CSRFProtection::tokenTag();} catch (SessionRequiredException){}?> <? try {echo CSRFProtection::tokenTag();} catch (SessionRequiredException){}?>
...@@ -229,18 +227,18 @@ if ($navigation) { ...@@ -229,18 +227,18 @@ if ($navigation) {
</form> </form>
</li> </li>
<li><?= $this->render_partial('login/_header_languages') ?></li> <li><?= $this->render_partial('login/_header_languages') ?></li>
<? endif; ?> <? endif; ?>
<li id="responsive-toggle-fullscreen"> <li id="responsive-toggle-fullscreen">
<button class="styleless" id="fullscreen-off" <button class="styleless" id="fullscreen-off"
title="<?= _('Kompakte Navigation ausschalten') ?>"> title="<?= _('Kompakte Navigation ausschalten') ?>">
<?= Icon::create('screen-standard', ICON::ROLE_INFO_ALT)->asImg(24) ?> <?= Icon::create('screen-standard', Icon::ROLE_INFO_ALT)->asImg(24) ?>
</button> </button>
</li> </li>
<li id="responsive-toggle-focusmode"> <li id="responsive-toggle-focusmode">
<button class="styleless consuming_mode_trigger" id="focusmode-on" <button class="styleless consuming_mode_trigger" id="focusmode-on"
title="<?= _('Vollbild aktivieren') ?>"> title="<?= _('Vollbild aktivieren') ?>">
<?= Icon::create('screen-full', ICON::ROLE_INFO_ALT)->asImg(24) ?> <?= Icon::create('screen-full', Icon::ROLE_INFO_ALT)->asImg(24) ?>
</button> </button>
</li> </li>
</ul> </ul>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment