From 78db6bbce81e101dc104a3e61fcaab8837d42a29 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mikel=20Mart=C3=ADn?= Date: Wed, 8 May 2024 13:37:29 +0200 Subject: [PATCH] MDL-81597 theme_boost: Fix header bar alignment - Refactot context_header class to implement named templatable so render_context_header in core and theme_boost can be removed - Refactor context_header to use templates - Fix context header layout and styles --- .upgradenotes/MDL-81597-2024052802370704.yml | 5 ++ lib/outputcomponents.php | 54 +++++++++++++- lib/outputrenderers.php | 74 ++----------------- lib/templates/contextheader.mustache | 75 ++++++++++++++++++++ theme/boost/classes/output/core_renderer.php | 64 +---------------- theme/boost/scss/moodle/core.scss | 18 ++--- theme/boost/style/moodle.css | 13 +--- theme/classic/style/moodle.css | 13 +--- 8 files changed, 149 insertions(+), 167 deletions(-) create mode 100644 .upgradenotes/MDL-81597-2024052802370704.yml create mode 100644 lib/templates/contextheader.mustache diff --git a/.upgradenotes/MDL-81597-2024052802370704.yml b/.upgradenotes/MDL-81597-2024052802370704.yml new file mode 100644 index 00000000000..c8fd71394ec --- /dev/null +++ b/.upgradenotes/MDL-81597-2024052802370704.yml @@ -0,0 +1,5 @@ +issueNumber: MDL-81597 +notes: + theme: + - message: New `core/contextheader` mustache template has been added. This template can be overridden by themes to modify the context header + type: improved diff --git a/lib/outputcomponents.php b/lib/outputcomponents.php index 50db844c528..6af82ec8f6a 100644 --- a/lib/outputcomponents.php +++ b/lib/outputcomponents.php @@ -27,6 +27,7 @@ */ use core\output\local\action_menu\subpanel; + use core\output\named_templatable; defined('MOODLE_INTERNAL') || die(); @@ -4109,7 +4110,7 @@ class tabobject implements renderable, templatable { * @copyright 2015 Adrian Greeve * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class context_header implements renderable { +class context_header implements renderable, named_templatable { /** * @var string $heading Main heading. @@ -4190,6 +4191,57 @@ class context_header implements renderable { array('class' => $class)); } } + + /** + * Export for template. + * + * @param renderer_base $output Renderer. + * @return array + */ + public function export_for_template(renderer_base $output): array { + // Heading. + $headingtext = isset($this->heading) ? $this->heading : $output->get_page()->heading; + $heading = $output->heading($headingtext, $this->headinglevel, "h2 mb-0"); + + // Buttons. + if (isset($this->additionalbuttons)) { + $additionalbuttons = []; + foreach ($this->additionalbuttons as $button) { + if (!isset($button->page)) { + // Include js for messaging. + if ($button['buttontype'] === 'togglecontact') { + \core_message\helper::togglecontact_requirejs(); + } + if ($button['buttontype'] === 'message') { + \core_message\helper::messageuser_requirejs(); + } + } + foreach ($button['linkattributes'] as $key => $value) { + $button['attributes'][] = ['name' => $key, 'value' => $value]; + } + $additionalbuttons[] = $button; + } + } + + return [ + 'heading' => $heading, + 'headinglevel' => $this->headinglevel, + 'imagedata' => $this->imagedata, + 'prefix' => $this->prefix, + 'hasadditionalbuttons' => !empty($additionalbuttons), + 'additionalbuttons' => $additionalbuttons ?? [], + ]; + } + + /** + * Get the template name. + * + * @param renderer_base $renderer Renderer. + * @return string + */ + public function get_template_name(renderer_base $renderer): string { + return 'core/contextheader'; + } } /** diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 3224512d3bb..a4bbe2bcf85 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -4589,9 +4589,13 @@ EOD; } } + // Return the heading wrapped in an sr-only element so it is only visible to screen-readers for nocontextheader layouts. + if (!empty($this->page->layout_options['nocontextheader'])) { + return html_writer::div($heading, 'sr-only'); + } $contextheader = new context_header($heading, $headinglevel, $imagedata, $userbuttons); - return $this->render_context_header($contextheader); + return $this->render($contextheader); } /** @@ -4610,74 +4614,6 @@ EOD; return $this->render_from_template('core/skip_links', $context); } - /** - * Renders the header bar. - * - * @param context_header $contextheader Header bar object. - * @return string HTML for the header bar. - */ - protected function render_context_header(context_header $contextheader) { - - // Generate the heading first and before everything else as we might have to do an early return. - if (!isset($contextheader->heading)) { - $heading = $this->heading($this->page->heading, $contextheader->headinglevel); - } else { - $heading = $this->heading($contextheader->heading, $contextheader->headinglevel); - } - - $showheader = empty($this->page->layout_options['nocontextheader']); - if (!$showheader) { - // Return the heading wrapped in an sr-only element so it is only visible to screen-readers. - return html_writer::div($heading, 'sr-only'); - } - - // All the html stuff goes here. - $html = html_writer::start_div('page-context-header'); - - // Image data. - if (isset($contextheader->imagedata)) { - // Header specific image. - $html .= html_writer::div($contextheader->imagedata, 'page-header-image icon-size-7'); - } - - // Headings. - if (isset($contextheader->prefix)) { - $prefix = html_writer::div($contextheader->prefix, 'text-muted'); - $heading = $prefix . $heading; - } - $html .= html_writer::tag('div', $heading, array('class' => 'page-header-headings')); - - // Buttons. - if (isset($contextheader->additionalbuttons)) { - $html .= html_writer::start_div('btn-group header-button-group'); - foreach ($contextheader->additionalbuttons as $button) { - if (!isset($button->page)) { - // Include js for messaging. - if ($button['buttontype'] === 'togglecontact') { - \core_message\helper::togglecontact_requirejs(); - } - if ($button['buttontype'] === 'message') { - \core_message\helper::messageuser_requirejs(); - } - $image = $this->pix_icon($button['formattedimage'], '', 'moodle', array( - 'class' => 'iconsmall', - )); - $image .= html_writer::span($button['title'], 'header-button-title'); - } else { - $image = html_writer::empty_tag('img', array( - 'src' => $button['formattedimage'], - 'alt' => $button['title'], - )); - } - $html .= html_writer::link($button['url'], html_writer::tag('span', $image), $button['linkattributes']); - } - $html .= html_writer::end_div(); - } - $html .= html_writer::end_div(); - - return $html; - } - /** * Wrapper for header elements. * diff --git a/lib/templates/contextheader.mustache b/lib/templates/contextheader.mustache new file mode 100644 index 00000000000..69364aae1af --- /dev/null +++ b/lib/templates/contextheader.mustache @@ -0,0 +1,75 @@ +{{! + 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/contextheader + + Context header template. + + Example context (json): + { + "heading": "

Page title

", + "prefix": "Page prefix", + "hasadditionalbuttons": true, + "additionalbuttons": [ + { + "url": "http://example.com", + "title": "Button title", + "formattedimage": "http://example.com/image.jpg", + "attributes": [ + { + "name": "data-attribute", + "value": "attribute value" + }, + { + "name": "class", + "value": "btn btn-primary" + } + ] + } + ] + } +}} +
+ {{#imagedata}} +
+ {{{imagedata}}} +
+ {{/imagedata}} +
+ {{#prefix}} +
+ {{{prefix}}} +
+ {{/prefix}} + {{{heading}}} +
+ {{#hasadditionalbuttons}} + + {{/hasadditionalbuttons}} +
diff --git a/theme/boost/classes/output/core_renderer.php b/theme/boost/classes/output/core_renderer.php index 38ea3b9852f..b5811eef836 100644 --- a/theme/boost/classes/output/core_renderer.php +++ b/theme/boost/classes/output/core_renderer.php @@ -179,69 +179,7 @@ class core_renderer extends \core_renderer { } $contextheader = new \context_header($heading, $headinglevel, $imagedata, $userbuttons, $prefix); - return $this->render_context_header($contextheader); - } - - /** - * Renders the header bar. - * - * @param context_header $contextheader Header bar object. - * @return string HTML for the header bar. - */ - protected function render_context_header(\context_header $contextheader) { - - // Generate the heading first and before everything else as we might have to do an early return. - if (!isset($contextheader->heading)) { - $heading = $this->heading($this->page->heading, $contextheader->headinglevel, 'h2'); - } else { - $heading = $this->heading($contextheader->heading, $contextheader->headinglevel, 'h2'); - } - - // All the html stuff goes here. - $html = html_writer::start_div('page-context-header'); - - // Image data. - if (isset($contextheader->imagedata)) { - // Header specific image. - $html .= html_writer::div($contextheader->imagedata, 'page-header-image mr-2'); - } - - // Headings. - if (isset($contextheader->prefix)) { - $prefix = html_writer::div($contextheader->prefix, 'text-muted text-uppercase small line-height-3'); - $heading = $prefix . $heading; - } - $html .= html_writer::tag('div', $heading, array('class' => 'page-header-headings')); - - // Buttons. - if (isset($contextheader->additionalbuttons)) { - $html .= html_writer::start_div('btn-group header-button-group'); - foreach ($contextheader->additionalbuttons as $button) { - if (!isset($button->page)) { - // Include js for messaging. - if ($button['buttontype'] === 'togglecontact') { - \core_message\helper::togglecontact_requirejs(); - } - if ($button['buttontype'] === 'message') { - \core_message\helper::messageuser_requirejs(); - } - $image = $this->pix_icon($button['formattedimage'], '', 'moodle', array( - 'class' => 'iconsmall', - )); - $image .= html_writer::span($button['title'], 'header-button-title'); - } else { - $image = html_writer::empty_tag('img', array( - 'src' => $button['formattedimage'], - 'alt' => $button['title'], - )); - } - $html .= html_writer::link($button['url'], html_writer::tag('span', $image), $button['linkattributes']); - } - $html .= html_writer::end_div(); - } - $html .= html_writer::end_div(); - - return $html; + return $this->render($contextheader); } /** diff --git a/theme/boost/scss/moodle/core.scss b/theme/boost/scss/moodle/core.scss index 12278c2b686..fd79fc60fd4 100644 --- a/theme/boost/scss/moodle/core.scss +++ b/theme/boost/scss/moodle/core.scss @@ -1955,24 +1955,14 @@ nav.navbar .logo img { overflow: hidden; padding: 0.25rem 0; - display: flex; - .page-header-image { & > a { display: inline-block; } - } - - .page-header-headings, - .header-button-group { - position: relative; - line-height: 24px; - vertical-align: middle; - } - - .header-button-group { - display: block; - float: left; + .userinitials, + .userpicture { + margin-right: map-get($spacers, 3); + } } } diff --git a/theme/boost/style/moodle.css b/theme/boost/style/moodle.css index d2db14b2741..bdeb4c0fd60 100644 --- a/theme/boost/style/moodle.css +++ b/theme/boost/style/moodle.css @@ -24954,20 +24954,13 @@ nav.navbar .logo img { .page-context-header { overflow: hidden; padding: 0.25rem 0; - display: flex; } .page-context-header .page-header-image > a { display: inline-block; } -.page-context-header .page-header-headings, -.page-context-header .header-button-group { - position: relative; - line-height: 24px; - vertical-align: middle; -} -.page-context-header .header-button-group { - display: block; - float: left; +.page-context-header .page-header-image .userinitials, +.page-context-header .page-header-image .userpicture { + margin-right: 1rem; } ul.dragdrop-keyboard-drag li { diff --git a/theme/classic/style/moodle.css b/theme/classic/style/moodle.css index 009232f9704..b481b044b13 100644 --- a/theme/classic/style/moodle.css +++ b/theme/classic/style/moodle.css @@ -24954,20 +24954,13 @@ nav.navbar .logo img { .page-context-header { overflow: hidden; padding: 0.25rem 0; - display: flex; } .page-context-header .page-header-image > a { display: inline-block; } -.page-context-header .page-header-headings, -.page-context-header .header-button-group { - position: relative; - line-height: 24px; - vertical-align: middle; -} -.page-context-header .header-button-group { - display: block; - float: left; +.page-context-header .page-header-image .userinitials, +.page-context-header .page-header-image .userpicture { + margin-right: 1rem; } ul.dragdrop-keyboard-drag li { -- 2.43.0