MDL-82541 core_courseformat: fix orphaned sections display

This commit is contained in:
ferranrecio
2024-09-12 16:12:13 +02:00
parent 9c55a02fb1
commit 9f9f5f6821
13 changed files with 171 additions and 21 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -300,6 +300,9 @@ export default class Component extends BaseComponent {
_refreshSectionCmlist({element}) {
const cmlist = element.cmlist ?? [];
const listparent = this.getElement(this.selectors.SECTION_CMLIST, element.id);
if (!listparent) {
return;
}
this._fixOrder(listparent, cmlist, this.cms);
}
@@ -19,6 +19,7 @@ namespace core_courseformat\output\local;
use core\output\named_templatable;
use core_courseformat\base as course_format;
use course_modinfo;
use section_info;
use renderable;
/**
@@ -142,7 +143,7 @@ class content implements named_templatable, renderable {
/**
* Export sections array data.
*
* @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 array data context for a mustache template
*/
protected function export_sections(\renderer_base $output): array {
@@ -154,7 +155,6 @@ class content implements named_templatable, renderable {
// Generate section list.
$sections = [];
$stealthsections = [];
$numsections = $format->get_last_section_number();
foreach ($this->get_sections_to_display($modinfo) as $sectionnum => $thissection) {
// The course/view.php check the section existence but the output can be called
// from other parts so we need to check it.
@@ -163,9 +163,14 @@ class content implements named_templatable, renderable {
format_string($course->fullname));
}
if (!$format->is_section_visible($thissection)) {
continue;
}
/** @var \core_courseformat\output\local\content\section $section */
$section = new $this->sectionclass($format, $thissection);
if ($sectionnum > $numsections) {
if ($section->is_stealth()) {
// Activities inside this section are 'orphaned', this section will be printed as 'stealth' below.
if (!empty($modinfo->sections[$sectionnum])) {
$stealthsections[] = $section->export_for_template($output);
@@ -173,10 +178,6 @@ class content implements named_templatable, renderable {
continue;
}
if (!$format->is_section_visible($thissection)) {
continue;
}
$sections[] = $section->export_for_template($output);
}
if (!empty($stealthsections)) {
@@ -95,9 +95,7 @@ class section implements named_templatable, renderable {
$this->format = $format;
$this->section = $section;
if ($section->section > $format->get_last_section_number()) {
$this->isstealth = true;
}
$this->isstealth = $section->is_orphan();
// Load output classes names from format.
$this->headerclass = $format->get_output_classname('content\\section\\header');
@@ -110,6 +108,15 @@ class section implements named_templatable, renderable {
$this->visibilityclass = $format->get_output_classname('content\\section\\visibility');
}
/**
* Check if the section is considered stealth.
*
* @return bool
*/
public function is_stealth(): bool {
return $this->isstealth;
}
/**
* Hide the section title.
*
@@ -98,7 +98,7 @@ class controlmenu extends basecontrolmenu {
$usecomponents = $format->supports_components();
$coursecontext = context_course::instance($course->id);
$numsections = $format->get_last_section_number();
$isstealth = $section->section > $numsections;
$isstealth = $section->is_orphan();
$baseurl = course_get_url($course, $sectionreturn);
$baseurl->param('sesskey', sesskey());
@@ -26,7 +26,7 @@
}
}}
{{#hasmenu}}
<div class="section_action_menu bulk-hidden ms-auto" data-sectionid="{{id}}">
<div class="section_action_menu bulk-hidden ms-auto" data-sectionid="{{id}}" data-region="sectionactionsmmenu">
{{{menu}}}
</div>
{{/hasmenu}}
@@ -50,6 +50,9 @@ class behat_courseformat extends behat_base {
new behat_component_named_selector('Section visibility', [
".//*[@data-sectionname=%locator%]//*[@data-region='sectionvisibility']",
]),
new behat_component_named_selector('Section actions menu', [
".//*[@data-sectionname=%locator%]//*[@data-for='section_title']//*[@data-region='sectionactionsmmenu']",
]),
];
}
}
@@ -55,12 +55,16 @@ class controlmenu extends controlmenu_base {
$section = $this->section;
$coursecontext = $format->get_context();
$controls = [];
if ($section->section && has_capability('moodle/course:setcurrentsection', $coursecontext)) {
$controls['highlight'] = $this->get_highlight_control();
$parentcontrols = parent::section_control_items();
if ($section->is_orphan() || !$section->section) {
return $parentcontrols;
}
$parentcontrols = parent::section_control_items();
$controls = [];
if (has_capability('moodle/course:setcurrentsection', $coursecontext)) {
$controls['highlight'] = $this->get_highlight_control();
}
// If the edit key exists, we are going to insert our controls after it.
if (array_key_exists("edit", $parentcontrols)) {
@@ -0,0 +1,131 @@
@mod @mod_subsection
Feature: Courses should not lose subsection contents when mod_subsection is disabled
In order to disable subsections
As an admin
Courses needs to be usable with mod_subsection disabled
Background:
Given I enable "subsection" "mod" plugin
And the following "users" exist:
| username | firstname | lastname |
| teacher1 | Teacher | 1 |
| student1 | Student | 1 |
And the following "courses" exist:
| fullname | shortname | category | numsections | initsections |
| Course 1 | C1 | 0 | 2 | 1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activities" exist:
| activity | name | course | idnumber | section |
| forum | Activity Sample | C1 | forum1 | 1 |
| subsection | Subsection1 | C1 | Subsection1 | 1 |
| data | Subactivity | C1 | data1 | 3 |
And I disable "subsection" "mod" plugin
Scenario: Teachers should see subsections as orphaned
When I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
And I should see "Activity Sample" in the "Section 1" "section"
And I should not see "Subsection1" in the "Section 1" "section"
And I should see "Subsection1" in the "page-content" "region"
Then I should see "Subactivity" in the "Subsection1" "section"
And "Section 2" "section" should appear before "Subsection1" "section"
And "Edit settings" "link" should not exist in the "Subsection1" "core_courseformat > Section actions menu"
And "Duplicate" "link" should not exist in the "Subsection1" "core_courseformat > Section actions menu"
And "Hide" "link" should not exist in the "Subsection1" "core_courseformat > Section actions menu"
And "Move" "link" should not exist in the "Subsection1" "core_courseformat > Section actions menu"
And "View" "link" should exist in the "Subsection1" "core_courseformat > Section actions menu"
And "Delete" "link" should exist in the "Subsection1" "core_courseformat > Section actions menu"
Scenario: Students should not see orphaned subsections
When I log in as "student1"
And I am on "Course 1" course homepage
Then I should see "Activity Sample" in the "page-content" "region"
And I should not see "Subsection1" in the "page-content" "region"
And I should not see "Subactivity" in the "page-content" "region"
Scenario: Enabling again subsections should show the course as before
Given I log in as "teacher1"
And I am on "Course 1" course homepage
And I should see "Activity Sample" in the "Section 1" "section"
And I should not see "Subsection1" in the "Section 1" "section"
And I should see "Subsection1" in the "page-content" "region"
And I should see "Subactivity" in the "Subsection1" "section"
And "Section 2" "section" should appear before "Subsection1" "section"
When I enable "subsection" "mod" plugin
And I am on "Course 1" course homepage with editing mode on
Then I should see "Activity Sample" in the "Section 1" "section"
And I should see "Subsection1" in the "Section 1" "section"
And I should see "Subactivity" in the "Subsection1" "section"
And "Subsection1" "section" should appear before "Section 2" "section"
And "Edit settings" "link" should exist in the "Subsection1" "core_courseformat > Section actions menu"
And "Duplicate" "link" should not exist in the "Subsection1" "core_courseformat > Section actions menu"
And "Hide" "link" should exist in the "Subsection1" "core_courseformat > Section actions menu"
And "Move" "link" should exist in the "Subsection1" "core_courseformat > Section actions menu"
And "View" "link" should exist in the "Subsection1" "core_courseformat > Section actions menu"
And "Delete" "link" should exist in the "Subsection1" "core_courseformat > Section actions menu"
@javascript
Scenario: Deleting the subsections with mod_subsection disabled should not break the course
Given I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
# Perform teacher actions instead of fast steps to validate delete
# an orphaned subsection does not break the course.
And I click on "Edit" "icon" in the "Subsection1" "core_courseformat > Section actions menu"
When I choose "Delete" in the open action menu
And I click on "Delete" "button" in the "Delete section?" "dialogue"
Then I enable "subsection" "mod" plugin
And I am on "Course 1" course homepage
And I should see "Activity Sample" in the "Section 1" "section"
And I should see "Subsection1" in the "page-content" "region"
And I should not see "Subactivity" in the "page-content" "region"
@javascript
Scenario: Access restrictions are restored when a subsection is deleted while mod_subsection is disabled
Given I enable "subsection" "mod" plugin
And the following "groups" exist:
| course | name | idnumber |
| C1 | G1 | GI1 |
And the following "group members" exist:
| user | group |
| student1 | GI1 |
And the following "groupings" exist:
| name | course | idnumber |
| GX1 | C1 | GXI1 |
And the following "grouping groups" exist:
| grouping | group |
| GXI1 | GI1 |
And I log in as "teacher1"
And I am on the "C1 > Subsection1" "course > section settings" page
And I set the following fields to these values:
| Access restrictions | Grouping: GX1 |
And I press "Save changes"
And I should see "Not available unless: You belong to a group in GX1"
And I disable "subsection" "mod" plugin
When I am on the "C1 > Subsection1" "course > section" page
And I turn editing mode on
And I click on "Edit" "icon" in the "[data-region='header-actions-container']" "css_element"
And I choose "Delete" in the open action menu
And I click on "Delete" "button" in the "Delete section?" "dialogue"
And I enable "subsection" "mod" plugin
Then I am on "Course 1" course homepage
And I should see "Not available unless: You belong to a group in GX1"
@javascript
Scenario: Visibility is restored when a subsection is deleted while mod_subsection is disabled
Given I enable "subsection" "mod" plugin
And the following "activities" exist:
| activity | name | course | idnumber | section | visible |
| subsection | Subsection2 | C1 | Subsection2 | 1 | 0 |
And I log in as "teacher1"
And I disable "subsection" "mod" plugin
When I am on the "C1 > Subsection2" "course > section" page
And I turn editing mode on
And I click on "Edit" "icon" in the "[data-region='header-actions-container']" "css_element"
And I choose "Delete" in the open action menu
And I click on "Delete" "button" in the "Delete section?" "dialogue"
And I enable "subsection" "mod" plugin
Then I am on "Course 1" course homepage
And I should see "Hidden from students"
+2 -1
View File
@@ -1150,7 +1150,8 @@ $divider-hover-color: $primary !default;
@include border-radius($activity-border-radius);
}
&.hidden {
&.hidden,
&.orphaned {
.section-item {
background-color: $gray-100;
}
+1 -1
View File
@@ -29065,7 +29065,7 @@ span.editinstructions .alert-link {
border: 1px solid #dee2e6;
border-radius: 1rem;
}
.course-section.hidden .section-item {
.course-section.hidden .section-item, .course-section.orphaned .section-item {
background-color: #f8f9fa;
}
.course-section .sectionname > a {
+1 -1
View File
@@ -29065,7 +29065,7 @@ span.editinstructions .alert-link {
border: 1px solid #dee2e6;
border-radius: 1rem;
}
.course-section.hidden .section-item {
.course-section.hidden .section-item, .course-section.orphaned .section-item {
background-color: #f8f9fa;
}
.course-section .sectionname > a {