From 0f248b545c40fa37435892ced33f120a9066028b Mon Sep 17 00:00:00 2001 From: Sara Arjona Date: Wed, 11 Feb 2026 19:01:52 +0100 Subject: [PATCH] MDL-87931 course: Move dates above secondary nav in activity page --- .upgradenotes/MDL-87662-2026012705202377.yml | 15 +++--- .../course/classes/output/activity_dates.php | 11 +++-- .../course/templates/activity_dates.mustache | 46 +++++++++++++++++++ .../course/templates/activity_info.mustache | 8 ---- public/lib/classes/output/activity_header.php | 35 ++++++++++++-- public/theme/classic/config.php | 2 +- .../templates/core/activity_header.mustache | 4 ++ 7 files changed, 98 insertions(+), 23 deletions(-) create mode 100644 public/course/templates/activity_dates.mustache diff --git a/.upgradenotes/MDL-87662-2026012705202377.yml b/.upgradenotes/MDL-87662-2026012705202377.yml index 6a47f02a2f9..5ada6e1172e 100644 --- a/.upgradenotes/MDL-87662-2026012705202377.yml +++ b/.upgradenotes/MDL-87662-2026012705202377.yml @@ -2,11 +2,12 @@ issueNumber: MDL-87662 notes: theme: - message: >- - The manual completion button has been moved to the activity header - to improve visibility and proximity to the activity name. A new - theme layout option, `completioninheader`, has been introduced to - control this behaviour and is enabled by default. Themes that set - completioninheader to false must manually override the relevant - template (such as `activity_header` or `activity_info`) to ensure - the completion information is displayed correctly. + The manual completion button and activity dates have been moved + to the activity header to improve visibility and proximity to the + activity name. A new theme layout option, `activityinfoinheader`, + has been introduced to control this behaviour and is enabled by + default. Themes that set `activityinfoinheader` to false must + manually override the relevant template (such as `activity_header` + or `activity_info`) to ensure the completion information and the + activity dates are displayed correctly. type: improved diff --git a/public/course/classes/output/activity_dates.php b/public/course/classes/output/activity_dates.php index 3d00a6fe964..826cd4ced95 100644 --- a/public/course/classes/output/activity_dates.php +++ b/public/course/classes/output/activity_dates.php @@ -29,14 +29,14 @@ use templatable; * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class activity_dates implements renderable, templatable { - /** * Constructor. * * @param array $activitydates The activity dates. */ public function __construct( - protected array $activitydates + /** @var array $activitydates the activity dates information. */ + protected array $activitydates, ) { } @@ -64,9 +64,14 @@ class activity_dates implements renderable, templatable { $activitydates[] = $date; } - return (object) [ + $result = (object) [ 'hasdates' => !empty($this->activitydates), 'activitydates' => $activitydates, ]; + if ($output->get_page()->cm) { + $result->activityname = $output->get_page()->cm->get_formatted_name(); + } + + return $result; } } diff --git a/public/course/templates/activity_dates.mustache b/public/course/templates/activity_dates.mustache new file mode 100644 index 00000000000..9f410c56bfd --- /dev/null +++ b/public/course/templates/activity_dates.mustache @@ -0,0 +1,46 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core_course/activity_dates + + Template for displaying the activity's dates. + + Example context (json): + { + "activityname": "Forum", + "hasdates": true, + "activitydates": [ + { + "label": "Opens:", + "datestring": "Monday, 1 January 2024, 12:00 AM" + }, + { + "label": "Closes:", + "datestring": "Monday, 26 February 2024, 12:00 AM" + } + ] + } +}} +{{#hasdates}} +
+
+ {{#activitydates}} + {{>core_course/activity_date}} + {{/activitydates}} +
+
+{{/hasdates}} diff --git a/public/course/templates/activity_info.mustache b/public/course/templates/activity_info.mustache index e3a553ed7cc..2925a4b04b0 100644 --- a/public/course/templates/activity_info.mustache +++ b/public/course/templates/activity_info.mustache @@ -50,14 +50,6 @@ } }}
- {{#hasdates}} -
- {{#activitydates}} - {{>core_course/activity_date}} - {{/activitydates}} -
- {{/hasdates}} -
{{#description}}
diff --git a/public/lib/classes/output/activity_header.php b/public/lib/classes/output/activity_header.php index 78fcdaff7ec..771e106745c 100644 --- a/public/lib/classes/output/activity_header.php +++ b/public/lib/classes/output/activity_header.php @@ -188,6 +188,7 @@ class activity_header implements renderable, templatable { $activityinfo = null; $activitycompletiondata = []; + $activitydatesdata = []; if (!$this->hidecompletion) { $completiondetails = \core_completion\cm_completion_details::get_instance($this->page->cm, $this->user->id); $activitydates = \core\activity_dates::get_dates_for_module($this->page->cm, $this->user->id); @@ -211,6 +212,7 @@ class activity_header implements renderable, templatable { } $activityinfo = $output->render_from_template('core_course/activity_info', $data); + $this->add_dates_to_page_header($output, $activitydatesdata); } $format = course_get_format($this->page->course); @@ -230,6 +232,7 @@ class activity_header implements renderable, templatable { 'title' => $this->title, 'description' => $this->description, 'completion' => $activityinfo, + 'activitydates' => $activitydatesdata, 'additional_items' => $additionalitems, ], $activitycompletiondata); } @@ -243,8 +246,8 @@ class activity_header implements renderable, templatable { */ private function add_manual_completion_to_page_header(renderer_base $output, array $data): bool { // Some themes may not use completion in the header, so we check first. - $showcompletion = $this->page?->layout_options['completioninheader'] ?? true; - if (!$showcompletion) { + $showinheader = $this->page?->layout_options['activityinfoinheader'] ?? true; + if (!$showinheader) { return false; } @@ -269,8 +272,8 @@ class activity_header implements renderable, templatable { */ private function add_completion_status_to_page_header(renderer_base $output, array $data): bool { // Some themes may not use completion in the header, so we check first. - $showcompletion = $this->page?->layout_options['completioninheader'] ?? true; - if (!$showcompletion) { + $showinheader = $this->page?->layout_options['activityinfoinheader'] ?? true; + if (!$showinheader) { return false; } @@ -280,6 +283,30 @@ class activity_header implements renderable, templatable { return true; } + /** + * Adds the dates component to the page header. + * + * @param renderer_base $output + * @param array $data the template data for the dates component + * @return bool if the dates were added + */ + private function add_dates_to_page_header(renderer_base $output, array $data): bool { + // Some themes may not use dates in the header, so we check first. + $showinheader = $this->page?->layout_options['activityinfoinheader'] ?? true; + if (!$showinheader) { + return false; + } + + // Only add dates if there are dates to show. + if (!$data['hasdates']) { + return false; + } + + $dates = $output->render_from_template('core_course/activity_dates', $data); + $this->page->add_header_extras($dates); + return true; + } + /** * Get the heading level for a given heading depending on whether the theme's activity header displays a heading * (usually the activity name). diff --git a/public/theme/classic/config.php b/public/theme/classic/config.php index c44190aa124..a7820f510ca 100644 --- a/public/theme/classic/config.php +++ b/public/theme/classic/config.php @@ -58,7 +58,7 @@ $THEME->layouts = [ 'file' => 'columns.php', 'regions' => array('side-pre', 'side-post'), 'defaultregion' => 'side-pre', - 'options' => ['completioninheader' => false], + 'options' => ['activityinfoinheader' => false], ), // The site home page. 'frontpage' => array( diff --git a/public/theme/classic/templates/core/activity_header.mustache b/public/theme/classic/templates/core/activity_header.mustache index 0de078debe6..c82fa4d8f9c 100644 --- a/public/theme/classic/templates/core/activity_header.mustache +++ b/public/theme/classic/templates/core/activity_header.mustache @@ -90,6 +90,10 @@
+{{#activitydates}} + {{>core_course/activity_dates}} +{{/activitydates}} +
{{#completion}} {{#str}} overallaggregation, completion {{/str}}