Skip to content

Commit

Permalink
MDL-80220 core_courseformat: Add section badge template
Browse files Browse the repository at this point in the history
* Adjust badge style to look similar to the one in the activity
* Add visibility selection dropdown to section
  • Loading branch information
laurentdavid committed Apr 4, 2024
1 parent c895def commit 27a681c
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 20 deletions.
15 changes: 10 additions & 5 deletions course/format/classes/output/local/content/section.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ class section implements named_templatable, renderable {
/** @var optional move here output class */
protected $movehereclass;

/** @var optional visibility output class */
protected $visibilityclass;

/** @var bool if the title is hidden for some reason */
protected $hidetitle = false;

Expand Down Expand Up @@ -104,6 +107,7 @@ public function __construct(course_format $format, section_info $section) {
$this->controlmenuclass = $format->get_output_classname('content\\section\\controlmenu');
$this->availabilityclass = $format->get_output_classname('content\\section\\availability');
$this->movehereclass = $format->get_output_classname('content\\section\\movehere');
$this->visibilityclass = $format->get_output_classname('content\\section\\visibility');
}

/**
Expand Down Expand Up @@ -256,8 +260,6 @@ protected function add_availability_data(stdClass &$data, renderer_base $output)
protected function add_visibility_data(stdClass &$data, renderer_base $output): bool {
global $USER;
$result = false;
$course = $this->format->get_course();
$context = context_course::instance($course->id);
// Check if it is a stealth sections (orphaned).
if ($this->isstealth) {
$data->isstealth = true;
Expand All @@ -266,13 +268,16 @@ protected function add_visibility_data(stdClass &$data, renderer_base $output):
}
if (!$this->section->visible) {
$data->ishidden = true;
$data->notavailable = true;
$course = $this->format->get_course();
$context = context_course::instance($course->id);
if (has_capability('moodle/course:viewhiddensections', $context, $USER)) {
$data->hiddenfromstudents = true;
$data->notavailable = false;
$result = true;
}
}
/* @var \core_courseformat\output\local\content\section\visibility $visibility By default the visibility class used
* here but can be overriden by any course format */
$visibility = new $this->visibilityclass($this->format, $this->section);
$data->visibility = $visibility->export_for_template($output);
return $result;
}

Expand Down
133 changes: 133 additions & 0 deletions course/format/classes/output/local/content/section/visibility.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php
// 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 <http://www.gnu.org/licenses/>.
namespace core_courseformat\output\local\content\section;

use context_course;
use core\output\choicelist;
use core\output\local\dropdown\status;
use core\output\named_templatable;
use core_courseformat\base as course_format;
use core_courseformat\output\local\courseformat_named_templatable;
use pix_icon;
use renderable;
use section_info;
use stdClass;

/**
* Base class to render a section visibility inside a course format.
*
* @package core_courseformat
* @copyright 2024 Laurent David <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class visibility implements named_templatable, renderable {
use courseformat_named_templatable;

/** @var course_format the course format */
protected $format;

/** @var section_info the section object */
protected $section;

/**
* Constructor.
* @param course_format $format the course format
* @param section_info $section the section info
*/
public function __construct(course_format $format, section_info $section) {
$this->format = $format;
$this->section = $section;
}

/**
* Export this data so it can be used as the context for a mustache template.
*
* @param \renderer_base $output typically, the renderer that's calling this function
* @return stdClass|null data context for a mustache template
*/
public function export_for_template(\renderer_base $output): ?stdClass {
global $USER;
$context = context_course::instance($this->section->course);
$data = new stdClass();
$data->editing = $this->format->show_editor();
if (!$this->section->visible) {
$data->notavailable = true;
if (has_capability('moodle/course:sectionvisibility', $context, $USER)) {
$data->hiddenfromstudents = true;
$data->notavailable = false;
$badgetext = $output->sr_text(get_string('availability'));
$badgetext .= get_string("hiddenfromstudents");
$icon = $this->get_icon('hide');
$choice = new choicelist();
$choice->add_option(
'show',
get_string("availability_show", 'core_courseformat'),
$this->get_option_data('show', 'sectionShow')
);
$choice->add_option(
'hide',
get_string('availability_hide', 'core_courseformat'),
$this->get_option_data('hide', 'sectionHide')
);
$choice->set_selected_value('hide');
$dropdown = new status(
$output->render($icon) . ' ' . $badgetext,
$choice,
['dialogwidth' => status::WIDTH['big']],
);
$data->dropwdown = $dropdown->export_for_template($output);
}
}
return $data;
}

/**
* Get the data for the option.
*
* @param string $name the name of the option
* @param string $action the state action of the option
* @return array
*/
private function get_option_data(string $name, string $action): array {
$baseurl = course_get_url($this->section->course, $this->section);
$baseurl->param('sesskey', sesskey());
$baseurl->param($action, $this->section->section);
return [
'description' => get_string("availability_{$name}_help", 'core_courseformat'),
'icon' => $this->get_icon($name),
// Non-ajax behat is not smart enough to discrimante hidden links
// so we need to keep providing the non-ajax links.
'url' => $baseurl,
'extras' => [
'data-id' => $this->section->id,
'data-action' => $action,
],
];
}

/**
* Get the icon for the section visibility.
* @param string $selected the visibility selected value
* @return pix_icon
*/
protected function get_icon(string $selected): pix_icon {
if ($selected === 'hide') {
return new pix_icon('t/show', '');
} else {
return new pix_icon('t/hide', '');
}
}
}
59 changes: 44 additions & 15 deletions course/format/templates/local/content/section/badges.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,59 @@
Example context (json):
{
"iscurrent" : true,
"hiddenfromstudents" : "1",
"notavailable" : "0",
"highlightedlabel" : "Highlighted"
"highlightedlabel" : "Highlighted",
"visibility": {
"editing": "1",
"dropwdown": {
"buttonid": "dropwdownbutton_648b1549b929e30",
"buttoncontent": "Show on course page",
"choices": {
"description": null,
"options": [
{
"value": "show",
"name": "Show on course page",
"description": "Available to students.",
"url": null,
"icon": null,
"disabled": false,
"hasicon": false,
"hasurl": false,
"selected": true,
"optionnumber": 1,
"first": true,
"optionuniqid": "choice_option_648b1549b929e31"
},
{
"value": "hide",
"name": "Hide on course page",
"description": "Not available to students.",
"url": null,
"icon": null,
"disabled": false,
"hasicon": false,
"hasurl": false,
"optionnumber": 2,
"first": false,
"optionuniqid": "choice_option_648b1549b929e32"
}
],
"hasoptions": true
}
}
}
}
}}
{{#editing}}
<span class="badge rounded-pill bg-primary text-white order-1 {{^iscurrent}}d-none{{/iscurrent}}" data-type="iscurrent">
{{ highlightedlabel }}
</span>
<span class="badge rounded-pill bg-warning text-dark order-2 {{^hiddenfromstudents}}d-none{{/hiddenfromstudents}}" data-type="hiddenfromstudents">
{{#str}}hiddenfromstudents{{/str}}
</span>
<span class="badge rounded-pill bg-secondary text-dark order-3 {{^notavailable}}d-none{{/notavailable}}">
{{#str}}notavailable{{/str}}
</span>
{{/editing}}
{{^editing}}
{{#iscurrent}}
<span class="badge rounded-pill bg-primary text-white order-1">{{ highlightedlabel }}</span>
{{/iscurrent}}
{{#hiddenfromstudents}}
<span class="badge rounded-pill bg-warning text-dark order-2">{{#str}}hiddenfromstudents{{/str}}</span>
{{/hiddenfromstudents}}
{{#notavailable}}
<span class="badge rounded-pill bg-secondary text-dark order-3">{{#str}}notavailable{{/str}}</span>
{{/notavailable}}
{{/editing}}
{{#visibility}}
{{>core_courseformat/local/content/section/visibility}}
{{/visibility}}
85 changes: 85 additions & 0 deletions course/format/templates/local/content/section/visibility.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
{{!
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 <http://www.gnu.org/licenses/>.
}}
{{!
@template core_courseformat/local/content/section/visibility
Template to displays if an section is in hidden or not.
Example context (json):
{
"editing": "1",
"notavailable": 1,
"hiddenfromstudents": 0,
"dropwdown": {
"buttonid": "dropwdownbutton_648b1549b929e30",
"buttoncontent": "Show on course page",
"choices": {
"description": null,
"options": [
{
"value": "show",
"name": "Show on course page",
"description": "Available to students.",
"url": null,
"icon": null,
"disabled": false,
"hasicon": false,
"hasurl": false,
"selected": true,
"optionnumber": 1,
"first": true,
"optionuniqid": "choice_option_648b1549b929e31"
},
{
"value": "hide",
"name": "Hide on course page",
"description": "Not available to students.",
"url": null,
"icon": null,
"disabled": false,
"hasicon": false,
"hasurl": false,
"optionnumber": 2,
"first": false,
"optionuniqid": "choice_option_648b1549b929e32"
}
],
"hasoptions": true
}
}
}
}}
{{#editing}}
<div class="order-2" data-region="visibility">
{{#dropwdown}}
{{< core/local/dropdown/status}}
{{$ buttonclasses }} badge rounded-pill bg-secondary text-dark dropdown-toggle border-0{{/ buttonclasses }}
{{/ core/local/dropdown/status}}
{{/dropwdown}}
</div>
<span class="badge rounded-pill bg-secondary text-dark order-3 {{^notavailable}}d-none{{/notavailable}}">
{{#str}}notavailable{{/str}}
</span>
{{/editing}}
{{^editing}}
{{#hiddenfromstudents}}
<span class="badge rounded-pill bg-secondary text-dark order-2">{{#pix}}i/show, core{{/pix}}{{#str}}hiddenfromstudents{{/str}}</span>
{{/hiddenfromstudents}}
{{#notavailable}}
<span class="badge rounded-pill bg-secondary text-dark order-3">{{#str}}notavailable{{/str}}</span>
{{/notavailable}}
{{/editing}}
4 changes: 4 additions & 0 deletions course/format/upgrade.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ This files describes API changes for course formats
Overview of this plugin type at https://moodledev.io/docs/apis/plugintypes/format

=== 4.4 ===
* The core_courseformat\output\local\content\section::export_for_template() is not returning hiddenfromstudents and notavailable
directly in the data array anymore. Instead, it returns the visibility data in the 'visibility' key. It means that templates
derived from core should be adjusted to use $data->visibility->hiddenfromstudents and $data->visibility->notavailable instead
of $data->hiddenfromstudents and $data->notavailable.
* The state mutations sectionMove is deprecated. From now on sectionMoveAfter is the only
valid section move mutation.
* The state action core_courseformat\stateactions::section_move is deprecated and
Expand Down
6 changes: 6 additions & 0 deletions theme/boost/scss/moodle/course.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,12 @@ $divider-hover-color: $primary !default;

.sectionbadges .badge {
margin-left: map-get($spacers, 2);
font-weight: normal;
.icon {
font-size: 12px;
width: 12px;
height: 12px;
}
}

.course-section-header.draggable {
Expand Down
6 changes: 6 additions & 0 deletions theme/boost/style/moodle.css
Original file line number Diff line number Diff line change
Expand Up @@ -29024,6 +29024,12 @@ span.editinstructions .alert-link {
}
.course-section .sectionbadges .badge {
margin-left: 0.5rem;
font-weight: normal;
}
.course-section .sectionbadges .badge .icon {
font-size: 12px;
width: 12px;
height: 12px;
}
.course-section .course-section-header.draggable {
cursor: move;
Expand Down
6 changes: 6 additions & 0 deletions theme/classic/style/moodle.css
Original file line number Diff line number Diff line change
Expand Up @@ -29024,6 +29024,12 @@ span.editinstructions .alert-link {
}
.course-section .sectionbadges .badge {
margin-left: 0.5rem;
font-weight: normal;
}
.course-section .sectionbadges .badge .icon {
font-size: 12px;
width: 12px;
height: 12px;
}
.course-section .course-section-header.draggable {
cursor: move;
Expand Down

0 comments on commit 27a681c

Please sign in to comment.