diff --git a/CHANGES.md b/CHANGES.md index a9151170117..1fafe801d5e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,7 +7,7 @@ Changes ### Unreleased * 2024-03-13 - Bugfix: Custom course fields of type "Textarea" were not conditionally hidden in the smart menu configuration, resolves #576. -* 2024-03-01 - Improvement: implement new setting to show starred courses in a popover menu in navbar, solves #289. +* 2024-03-01 - Feature: Show starred courses popover in the navbar, resolves #289. ### v4.3-r8 diff --git a/README.md b/README.md index 9720ec2bf6d..7f6ca478e3e 100644 --- a/README.md +++ b/README.md @@ -321,7 +321,9 @@ With this setting, you can set an alternative link URL which will be used as lin With this setting, you can add a 'Set preferred language' setting to the language menu within the user menu. Understandably, this setting is only processed if the language menu is enabled at all. -###### Show starred courses in primary navigation bar +##### Navbar + +###### Show starred courses popover in the navbar With this setting, you can show a popover menu with links to starred courses next to the messages and notifications menus. @@ -779,6 +781,5 @@ Moodle an Hochschulen e.V. would like to thank these main contributors (in alpha * University of Graz, André Menrath: Code * University of Lübeck, Christian Wolters: Code, Peer Review, Ideating * Zurich University of Applied Sciences (ZHAW): Funding, Ideating -* Academic Moodle Cooperation (AMC): Code, Ideating Additionally, we thank all other contributors who contributed ideas, feedback and code snippets within the Github issues and pull requests as well as all contributors who contributed additional translations in AMOS, the Moodle translation tool. diff --git a/lang/en/theme_boost_union.php b/lang/en/theme_boost_union.php index 52d8759751a..0edbb9282a2 100644 --- a/lang/en/theme_boost_union.php +++ b/lang/en/theme_boost_union.php @@ -398,9 +398,13 @@ $string['addpreferredlangsetting'] = 'Add preferred language link to language menu'; $string['addpreferredlangsetting_desc'] = 'With this setting, you can add a \'Set preferred language\' setting to the language menu within the user menu. Understandably, this setting is only processed if the setting Display language menu is enabled, and if at least a second language pack is installed and offered for selection.'; $string['setpreferredlanglink'] = 'Set preferred language'; -// ... ... Settings: show a popover menu with starred courses next to the messages and notifications menus. -$string['shownavbarstarredcoursessetting'] = 'Show starred courses in primary navigation bar'; -$string['shownavbarstarredcoursessetting_desc'] = 'Show a popover menu with links to starred courses next to the messages and notifications menus.'; +// ... Section: Navbar heading. +$string['navbarheading'] = 'Navbar'; +// ... ... Setting: Show starred courses popover in the navbar. +$string['shownavbarstarredcoursessetting'] = 'Show starred courses popover in the navbar'; +$string['shownavbarstarredcoursessetting_desc'] = 'With this setting, you can show a popover menu with links to starred courses next to the messages and notifications menus.'; +$string['shownavbarstarredcourses_config'] = 'Set starred courses on the \'My courses\' page'; +$string['shownavbarstarredcourses_label'] = 'Starred courses'; // ... Section: Breadcrumbs. $string['breadcrumbsheading'] = 'Breadcrumbs'; // ... ... Setting: Course category breadcrumb. diff --git a/lib.php b/lib.php index b05b05af99b..65c8967a68a 100644 --- a/lib.php +++ b/lib.php @@ -609,6 +609,17 @@ function theme_boost_union_user_preferences(): array { * @return string */ function theme_boost_union_render_navbar_output() { - require_once(__DIR__ . '/locallib.php'); - return theme_boost_union_get_favourites_popover_menu(); + global $CFG; + + // Require local library. + require_once($CFG->dirroot . '/theme/boost_union/locallib.php'); + + // Initialize the navbar content. + $content = ''; + + // Setting: Show starred courses popover in the navbar. + $content .= theme_boost_union_get_navbar_starredcoursespopover(); + + // Return. + return $content; } diff --git a/locallib.php b/locallib.php index e03539bbf28..f6f8abd446b 100644 --- a/locallib.php +++ b/locallib.php @@ -1869,48 +1869,95 @@ function theme_boost_union_yesno_to_boolstring($var) { } /** - * Function that fetches all favorite courses, and renders them as a popover menu. + * Returns the HTML code for the starred courses popover. + * It fetches all favorite courses and renders them as a popover menu. * - * @return string HTML to display the main header. + * This function is copied and modified from block_starredcourses_external::get_starred_courses() + * + * @return string HTML to display in the navbar. */ -function theme_boost_union_get_favourites_popover_menu() { - global $USER, $DB, $OUTPUT; - // Menu is relevant only for logged in users. - if (isloggedin()) { - $settings = get_config('theme_boost_union'); - if (!isset($settings->shownavbarstarredcourses) || $settings->shownavbarstarredcourses == 'no') { - return ''; - } - // Get all favourite courses. - $ufservice = \core_favourites\service_factory::get_service_for_user_context(\context_user::instance($USER->id)); - $favourites = $ufservice->find_favourites_by_type('core_course', 'courses'); - if (!$favourites) { - return ''; - } - $favouritecourseids = array_map( - function($favourite) { - return $favourite->itemid; - }, $favourites); - $coursefields = 'id, shortname, fullname, visible'; - $courses = $DB->get_records_list('course', 'id', $favouritecourseids, 'visible DESC,sortorder ASC', $coursefields); - - // Sort courses by visibility and name. - usort($courses, function($a, $b) { - if ($a->visible != $b->visible) { - return $a->visible == 0 ? 1 : -1; - } - return strcasecmp(trim($a->fullname), trim($b->fullname)); - }); - $menu = []; - foreach ($courses as $course) { - $menu[] = [ +function theme_boost_union_get_navbar_starredcoursespopover() { + global $USER, $OUTPUT; + + // The popover is relevant only for logged-in users. If the user is not logged in, return directly. + if (!isloggedin()) { + return ''; + } + + // If the popover is disabled, return directly. + $setting = get_config('theme_boost_union', 'shownavbarstarredcourses'); + if (!isset($setting) || $setting != THEME_BOOST_UNION_SETTING_SELECT_YES) { + return ''; + } + + // Get the user context. + $usercontext = context_user::instance($USER->id); + + // Get the user favourites service, scoped to a single user (their favourites only). + $userservice = \core_favourites\service_factory::get_service_for_user_context($usercontext); + + // Get the favourites, by type, for the user. + $favourites = $userservice->find_favourites_by_type('core_course', 'courses'); + + // If there aren't any favourite courses, return directly. + if (!$favourites) { + return ''; + } + + // Pick the course IDs from the course objects. + $favouritecourseids = array_map( + function($favourite) { + return $favourite->itemid; + }, $favourites); + + // Get all courses that the current user is enrolled in, restricted down to favourites. + $filteredcourses = []; + if ($favouritecourseids) { + $courses = course_get_enrolled_courses_for_logged_in_user(0, 0, null, null, + COURSE_DB_QUERY_LIMIT, $favouritecourseids); + list($filteredcourses, $processedcount) = course_filter_courses_by_favourites( + $courses, + $favouritecourseids, + 0 + ); + } + // Grab the course ids. + $filteredcourseids = array_column($filteredcourses, 'id'); + + // Filter out any favourites that are not in the list of enroled courses. + $filteredfavourites = array_filter($favourites, function($favourite) use ($filteredcourseids) { + return in_array($favourite->itemid, $filteredcourseids); + }); + + // Compose the template context. + $coursesfortemplate = []; + foreach ($filteredfavourites as $favourite) { + $course = get_course($favourite->itemid); + $context = \context_course::instance($favourite->itemid); + $canviewhiddencourses = has_capability('moodle/course:viewhiddencourses', $context); + + if ($course->visible || $canviewhiddencourses) { + $coursesfortemplate[] = [ 'url' => new \moodle_url('/course/view.php', ['id' => $course->id]), 'fullname' => $course->fullname, 'visible' => $course->visible == 1, ]; } - $html = $OUTPUT->render_from_template('theme_boost_union/favourites-popover', ['favourites' => $menu]); - return $html; } - return ''; + + // Sort the favourites by name (if there is anything to be sorted). + if (count($coursesfortemplate) > 1) { + usort($coursesfortemplate, function($a, $b) { + if ($a['fullname'] == $b['fullname']) { + return 0; + } + + return strcasecmp(trim($a['fullname']), trim($b['fullname'])); + }); + } + + // Compose the popover menu. + $html = $OUTPUT->render_from_template('theme_boost_union/popover-favourites', ['favourites' => $coursesfortemplate]); + + return $html; } diff --git a/scss/boost_union/post.scss b/scss/boost_union/post.scss index c19b3ec1ca9..aa7b58e6821 100644 --- a/scss/boost_union/post.scss +++ b/scss/boost_union/post.scss @@ -473,42 +473,49 @@ body.hascourseindexcplsol.editing { } /*--------------------------------------- - * Setting: show a popover menu with starred courses next to the messages and notifications menus. + * Setting: Show starred courses popover in the navbar. --------------------------------------*/ -.navbar #nav-favourites-popover-container { +.navbar #nav-popover-favourites-container { .popover-region-container { + /* Make sure that the popover is only as high an necessary*/ height: auto; + /* Limit the width to some reasonable size to avoid that the popover menu is too wide. */ - max-width: 78vw; - border-radius: 0.5rem; - right: -5vw; + min-width: 250px; + max-width: 450px; width: auto; - @include media-breakpoint-down(lg) { - max-width: 73vw; - } - @include media-breakpoint-down(md) { - max-width: 68vw; - } - @include media-breakpoint-down(xs) { - right: -35vw; - top: 60px; - } - /* Hide overflowing course names. */ - .dropdown-item { - overflow-x: hidden; - text-overflow: ellipsis; - } } + .popover-region-header-container { - display: none; + /* Grant the popover header some more space.*/ + height: 35px; + padding-left: 10px; + padding-top: 5px; } + .popover-region-content-container { + /* Make sure that the popover is only as high an necessary. + (Full browser height minus navbar height minus popover header height minus some space at the bottom. */ height: auto; - min-width: 10rem; + max-height: calc(100vh - #{$navbar-height} - 35px - 1em); + + /* Improve the course list items. */ + .dropdown-item { + /* Fix the left padding of the dropdown item. */ + padding-left: 10px; + + /* Hide overflowing course names. */ + overflow-x: hidden; + text-overflow: ellipsis; + + /* Keep dimmed courses white when hovered. */ + &.dimmed:hover { + color: #FFFFFF; + } + } } } - /*--------------------------------------- * Setting: Back to top button. --------------------------------------*/ diff --git a/settings.php b/settings.php index cecfee49e1d..13790a7e5f1 100644 --- a/settings.php +++ b/settings.php @@ -1259,11 +1259,17 @@ $setting = new admin_setting_configselect($name, $title, $description, THEME_BOOST_UNION_SETTING_SELECT_NO, $yesnooption); $tab->add($setting); - // Setting: show a popover menu with starred courses next to the messages and notifications menus. + // Create navbar heading. + $name = 'theme_boost_union/navbarheading'; + $title = get_string('navbarheading', 'theme_boost_union', null, true); + $setting = new admin_setting_heading($name, $title, null); + $tab->add($setting); + + // Setting: Show starred courses popover in the navbar. $name = 'theme_boost_union/shownavbarstarredcourses'; $title = get_string('shownavbarstarredcoursessetting', 'theme_boost_union', null, true); $description = get_string('shownavbarstarredcoursessetting_desc', 'theme_boost_union', null, true); - $setting = new admin_setting_configselect($name, $title, $description, THEME_BOOST_UNION_SETTING_SELECT_YES, $yesnooption); + $setting = new admin_setting_configselect($name, $title, $description, THEME_BOOST_UNION_SETTING_SELECT_NO, $yesnooption); $setting->set_updatedcallback('theme_reset_all_caches'); $tab->add($setting); diff --git a/templates/favourites-popover.mustache b/templates/favourites-popover.mustache deleted file mode 100644 index 929f6a39e61..00000000000 --- a/templates/favourites-popover.mustache +++ /dev/null @@ -1,27 +0,0 @@ -{{< core/popover_region }} - {{$classes}}popover-region-favourites{{/classes}} - {{$attributes}}id="nav-favourites-popover-container" {{/attributes}} - - {{$togglelabel}}{{#str}} favourites {{/str}}{{/togglelabel}} - {{$togglecontent}} - - {{/togglecontent}} - - {{$containerlabel}}{{#str}} favourites {{/str}}{{/containerlabel}} - - - {{$content}} -