Skip to content

Commit

Permalink
MDL-78204 course: Use 'showmore' component in course restrictions
Browse files Browse the repository at this point in the history
- Create new availability template, so it can be reused from both
section/availability and cm/availability mustaches.

- When rendering activity or section restrictions with long or multiline text
display a condensed version (excerpt) and use 'showmore' component to add
showmore/showless behaviour.

Co-authored-by: Ferran Recio <ferran@moodle.com>
  • Loading branch information
roland04 and ferranrecio committed Jun 28, 2023
1 parent fb49de8 commit 045f8cb
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Feature: Confirm that conditions on completion no longer cause a bug
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I set the field with xpath "//div[contains(concat(' ', normalize-space(@class), ' '), ' availability-item ')][preceding-sibling::div]//select[@name='cm']" to "Page2"
And I press "Save and return to course"
And I click on "Show more" "button" in the "#section-1 .availabilityinfo" "css_element"
Then I should see "Not available unless:" in the ".activity.glossary" "css_element"
And I should see "The activity Page1 is marked complete" in the ".activity.glossary" "css_element"
And I should see "The activity Page2 is marked complete" in the ".activity.glossary" "css_element"
Expand Down
17 changes: 15 additions & 2 deletions availability/tests/behat/display_availability.feature
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,17 @@ Feature: display_availability
And I should see "2013" in the "#section-1 .availabilityinfo" "css_element"
And I should see "2013" in the "#section-1 .availabilityinfo" "css_element"
And "li" "css_element" should not exist in the "#section-1 .availabilityinfo" "css_element"
And "Show more" "button" should not exist in the "#section-1 .availabilityinfo" "css_element"

# Page 2 should show in list format.
And "li" "css_element" should exist in the "#section-2 .availabilityinfo" "css_element"
And I should see "Not available unless:" in the "#section-2 .availabilityinfo" "css_element"
And I should see "It is before" in the "#section-2 .availabilityinfo" "css_element"
And I should see "hidden otherwise" in the "#section-2 .availabilityinfo" "css_element"
And I click on "Show more" "button" in the "Page 2" "activity"
And I should see "Email address" in the "#section-2 .availabilityinfo" "css_element"
And I click on "Show less" "button" in the "#section-2 .availabilityinfo" "css_element"
And I should not see "Email address" in the "#section-2 .availabilityinfo" "css_element"

# Page 3 should not have available info.
And "#section-3 .availabilityinfo" "css_element" should not exist
Expand Down Expand Up @@ -114,6 +118,11 @@ Feature: display_availability
And I click on "Date" "button" in the "Add restriction..." "dialogue"
And I set the field "direction" to "until"
And I set the field "x[year]" to "2013"
And I press "Add restriction..."
And I click on "User profile" "button" in the "Add restriction..." "dialogue"
And I set the field "User profile field" to "Email address"
And I set the field "Value to compare against" to "email@example.com"
And I set the field "Method of comparison" to "is equal to"
And I press "Save changes"

# Section 2 is the same but hidden from students
Expand All @@ -130,7 +139,7 @@ Feature: display_availability
And I am on "Course 1" course homepage

# Check display
Then I should see "Available until" in the "#section-1 .availabilityinfo" "css_element"
Then I should see "Not available unless" in the "#section-1 .availabilityinfo" "css_element"
And I should see "Available until" in the "#section-2 .availabilityinfo" "css_element"
And I should see "hidden otherwise" in the "#section-2 .availabilityinfo" "css_element"

Expand All @@ -144,7 +153,11 @@ Feature: display_availability

# Section 1 should be visible and show info.
And I should see "Topic 1" in the "region-main" "region"
And I should see "Available until" in the "#section-1 .availabilityinfo" "css_element"
And I should see "Not available unless" in the "#section-1 .availabilityinfo" "css_element"
And I click on "Show more" "button" in the "#section-1 .availabilityinfo" "css_element"
And I should see "Email address" in the "#section-1 .availabilityinfo" "css_element"
And I click on "Show less" "button" in the "#section-1 .availabilityinfo" "css_element"
And I should not see "Email address" in the "#section-1 .availabilityinfo" "css_element"

# Section 2 should not be available at all
And I should not see "Topic 2" in the "region-main" "region"
12 changes: 2 additions & 10 deletions course/format/classes/output/local/content/cm/availability.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,7 @@ protected function user_availability_info(\renderer_base $output): array {
}

$info = [];
$formattedinfo = \core_availability\info::format_info(
$this->mod->availableinfo,
$this->mod->get_course()
);
$info[] = $this->availability_info($formattedinfo, 'isrestricted');
$info[] = $this->get_availability_data($output, $this->mod->availableinfo, 'isrestricted');
return $info;
}

Expand Down Expand Up @@ -151,11 +147,7 @@ protected function conditional_availability_info(\renderer_base $output): array
if (!$mod->visible) {
$hidinfoclass .= ' hide';
}
$formattedinfo = info::format_info(
$fullinfo,
$mod->get_course()
);
$info[] = $this->availability_info($formattedinfo, $hidinfoclass);
$info[] = $this->get_availability_data($output, $fullinfo, $hidinfoclass);

return $info;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
namespace core_courseformat\output\local\content\section;

use context_course;
use core_availability_multiple_messages;
use core\output\named_templatable;
use core_availability\info;
use core_availability\info_section;
Expand Down Expand Up @@ -57,6 +58,9 @@ class availability implements named_templatable, renderable {
/** @var stdClass|null the instance export data */
protected $data = null;

/** @var int Availability excerpt text max size treshold */
protected const AVAILABILITY_EXCERPT_MAXSIZE = 100;

/**
* Constructor.
*
Expand Down Expand Up @@ -124,7 +128,7 @@ protected function build_export_data(\renderer_base $output) {
* are going to be unavailable etc). This logic is the same as for
* activities.
*
* @param renderer_base $output typically, the renderer that's calling this function
* @param \renderer_base $output typically, the renderer that's calling this function
* @return stdclass data context for a mustache template
*/
protected function get_info(\renderer_base $output): array {
Expand All @@ -142,30 +146,115 @@ protected function get_info(\renderer_base $output): array {
if ($section->availableinfo) {
// Note: We only get to this function if availableinfo is non-empty,
// so there is definitely something to print.
$formattedinfo = info::format_info($section->availableinfo, $section->course);
$info[] = $this->availability_info($formattedinfo, 'isrestricted');
$info[] = $this->get_availability_data($output, $section->availableinfo, 'isrestricted');
}
} else if ($canviewhidden && !empty($CFG->enableavailability)) {
// Check if there is an availability restriction.
$ci = new info_section($section);
$fullinfo = $ci->get_full_information();
if ($fullinfo) {
$formattedinfo = info::format_info($fullinfo, $section->course);
$info[] = $this->availability_info($formattedinfo, 'isrestricted isfullinfo');
$info[] = $this->get_availability_data($output, $fullinfo, 'isrestricted isfullinfo');
}
}

return $info;
}

/**
* Get the basic availability information data.
*
* @param \renderer_base $output typically, the renderer that's calling this function
* @param string|core_availability_multiple_messages $availabilityinfo the avalability info
* @param string $additionalclasses additional css classes
* @return stdClass the availability information data
*/
protected function get_availability_data($output, $availabilityinfo, $additionalclasses = ''): stdClass {
// At this point, availabilityinfo is either a string or a renderable. We need to handle both cases in a different way.
if (is_string($availabilityinfo)) {
$data = $this->availability_info_from_string($output, $availabilityinfo);
} else {
$data = $this->availability_info_from_output($output, $availabilityinfo);
}

$data->classes = $additionalclasses;

$additionalclasses = array_filter(explode(' ', $additionalclasses));
if (in_array('ishidden', $additionalclasses)) {
$data->ishidden = 1;
} else if (in_array('isstealth', $additionalclasses)) {
$data->isstealth = 1;
} else if (in_array('isrestricted', $additionalclasses)) {
$data->isrestricted = 1;
if (in_array('isfullinfo', $additionalclasses)) {
$data->isfullinfo = 1;
}
}

return $data;
}

/**
* Generate the basic availability information data from a string.
* Just shorten availability text to generate the excerpt text.
*
* @param \renderer_base $output typically, the renderer that's calling this function
* @param string $availabilityinfo the avalability info
* @return stdClass the availability information data
*/
protected function availability_info_from_string(\renderer_base $output, string $availabilityinfo): stdClass {
$course = $this->format->get_course();

$text = info::format_info($availabilityinfo, $course);
$data = ['text' => $text];

if (strlen(html_to_text($text)) > self::AVAILABILITY_EXCERPT_MAXSIZE) {
$data['excerpt'] = shorten_text($text, self::AVAILABILITY_EXCERPT_MAXSIZE);
}

return (object) $data;
}

/**
* Generate the basic availability information data from a renderable.
* Use the header and the first item to generate the excerpt text.
*
* @param \renderer_base $output typically, the renderer that's calling this function
* @param core_availability_multiple_messages $availabilityinfo the avalability info
* @return stdClass the availability information data
*/
protected function availability_info_from_output(
\renderer_base $output,
core_availability_multiple_messages $availabilityinfo
): stdClass {
$course = $this->format->get_course();

$renderable = new \core_availability\output\availability_info($availabilityinfo);
// We need to export_for_template() instead of directly render, to reuse the info for both 'text' and 'excerpt'.
$info = $renderable->export_for_template($output);

$text = $output->render_from_template('core_availability/availability_info', $info);
$data = ['text' => info::format_info($text, $course)];

if (!empty($info->items)) {
$excerpttext = $info->header . ' ' . $info->items[0]->header;
$data['excerpt'] = info::format_info($excerpttext, $course);
}

return (object) $data;
}

/**
* Generate the basic availability information data.
*
* @deprecated since Moodle 4.3 MDL-78204. Please use {@see self::get_availability_data} instead.
* @todo MDL-78489 This will be deleted in Moodle 4.7.
* @param string $text the formatted avalability text
* @param string $additionalclasses additional css classes
* @return stdClass the availability information data
*/
protected function availability_info($text, $additionalclasses = ''): stdClass {
debugging('Use of ' . __FUNCTION__ . '() have been deprecated, ' .
'please use core_courseformat\output\local\content\section\availability::get_availability_data()', DEBUG_DEVELOPER);

$data = (object)[
'text' => $text,
Expand Down
43 changes: 43 additions & 0 deletions course/format/templates/local/content/availability.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{{!
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/availability
Displays the availability contents with excerpt version if needed.
Example context (json):
{
"text": "Not available unless: <ul><li>It is on or after <strong>8 June 2012</strong></li><li>You achieve higher than a certain score in <strong>Course total</strong></li></ul>",
"excerpt": "Not available unless: It is on or after <strong>8 June 2012</strong>"
}
}}
{{^excerpt}}
{{#pix}}t/unlock, core{{/pix}} {{{text}}}
{{/excerpt}}
{{#excerpt}}
{{< core/showmore }}
{{$collapsedcontent}}
{{#pix}}t/unlock, core{{/pix}} <span class="availability-excerpt"> {{{excerpt}}} ... </span>
{{/collapsedcontent}}
{{$expandedcontent}}
{{#pix}}t/unlock, core{{/pix}} {{{text}}}
{{/expandedcontent}}
{{$buttonextraclasses}}font-weight-bold{{/buttonextraclasses}}
{{$collapsedextraclasses}}text-truncate pr-2{{/collapsedextraclasses}}
{{$expandedextraclasses}}py-2{{/expandedextraclasses}}
{{/core/showmore }}
{{/excerpt}}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<span class="badge badge-pill badge-warning">{{{text}}}</span>
{{/isrestricted}}
{{#isrestricted}}
<div> {{#pix}}t/unlock, core{{/pix}} {{{text}}} </div>
{{> core_courseformat/local/content/availability }}
{{/isrestricted}}
</div>
{{/info}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<span class="badge badge-pill badge-warning">{{{text}}}</span>
{{/isrestricted}}
{{#isrestricted}}
<div> {{#pix}}t/unlock, core{{/pix}} {{{text}}} </div>
{{> core_courseformat/local/content/availability }}
{{/isrestricted}}
</div>
{{/info}}
Expand Down
2 changes: 2 additions & 0 deletions course/format/upgrade.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Some considerations about the activitybadge feature:
- An optional URL to redirect the user when the badge is clicked.
- An optional ID to add the element in case the module wants to add some JS to the badge events.
- Optionally, any other extra HTML attributes to the badge element (for example, data attributes).
* Protected function `core_courseformat\output\local\content\section\availability::availability_info()` has been deprecated,
`core_courseformat\output\local\content\section\availability::get_availability_data()` should be used instead.

=== 4.2 ===
* New core_courseformat\base::get_context() to get the course context directly from the format instance.
Expand Down

0 comments on commit 045f8cb

Please sign in to comment.