mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 21:49:15 +01:00
MDL-74977 core_courseformat: add expanded section update actions
This also fix the Random "Course content preferences" Behat failure
This commit is contained in:
parent
b621a7e4b3
commit
6d40f11806
2
course/format/amd/build/local/content.min.js
vendored
2
course/format/amd/build/local/content.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -179,15 +179,12 @@ export default class Component extends BaseComponent {
|
||||
const toggler = section.querySelector(this.selectors.COLLAPSE);
|
||||
const isCollapsed = toggler?.classList.contains(this.classes.COLLAPSED) ?? false;
|
||||
|
||||
if (isChevron || isCollapsed) {
|
||||
// Update the state.
|
||||
const sectionId = section.getAttribute('data-id');
|
||||
this.reactive.dispatch(
|
||||
'sectionContentCollapsed',
|
||||
[sectionId],
|
||||
!isCollapsed
|
||||
);
|
||||
}
|
||||
const sectionId = section.getAttribute('data-id');
|
||||
this.reactive.dispatch(
|
||||
'sectionContentCollapsed',
|
||||
[sectionId],
|
||||
!isCollapsed,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,12 +572,16 @@ export default class {
|
||||
* @param {boolean} collapsed the new collapsed value
|
||||
*/
|
||||
async sectionIndexCollapsed(stateManager, sectionIds, collapsed) {
|
||||
const collapsedIds = this._updateStateSectionPreference(stateManager, 'indexcollapsed', sectionIds, collapsed);
|
||||
if (!collapsedIds) {
|
||||
const affectedSections = this._updateStateSectionPreference(stateManager, 'indexcollapsed', sectionIds, collapsed);
|
||||
if (!affectedSections) {
|
||||
return;
|
||||
}
|
||||
const course = stateManager.get('course');
|
||||
await this._callEditWebservice('section_index_collapsed', course.id, collapsedIds);
|
||||
let actionName = 'section_index_collapsed';
|
||||
if (!collapsed) {
|
||||
actionName = 'section_index_expanded';
|
||||
}
|
||||
await this._callEditWebservice(actionName, course.id, affectedSections);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -599,12 +603,16 @@ export default class {
|
||||
* @param {boolean} collapsed the new collapsed value
|
||||
*/
|
||||
async sectionContentCollapsed(stateManager, sectionIds, collapsed) {
|
||||
const collapsedIds = this._updateStateSectionPreference(stateManager, 'contentcollapsed', sectionIds, collapsed);
|
||||
if (!collapsedIds) {
|
||||
const affectedSections = this._updateStateSectionPreference(stateManager, 'contentcollapsed', sectionIds, collapsed);
|
||||
if (!affectedSections) {
|
||||
return;
|
||||
}
|
||||
const course = stateManager.get('course');
|
||||
await this._callEditWebservice('section_content_collapsed', course.id, collapsedIds);
|
||||
let actionName = 'section_content_collapsed';
|
||||
if (!collapsed) {
|
||||
actionName = 'section_content_expanded';
|
||||
}
|
||||
await this._callEditWebservice(actionName, course.id, affectedSections);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -618,32 +626,22 @@ export default class {
|
||||
*/
|
||||
_updateStateSectionPreference(stateManager, preferenceName, sectionIds, preferenceValue) {
|
||||
stateManager.setReadOnly(false);
|
||||
const affectedSections = new Set();
|
||||
const affectedSections = [];
|
||||
// Check if we need to update preferences.
|
||||
sectionIds.forEach(sectionId => {
|
||||
const section = stateManager.get('section', sectionId);
|
||||
if (section === undefined) {
|
||||
stateManager.setReadOnly(true);
|
||||
return null;
|
||||
}
|
||||
const newValue = preferenceValue ?? section[preferenceName];
|
||||
if (section[preferenceName] != newValue) {
|
||||
section[preferenceName] = newValue;
|
||||
affectedSections.add(section.id);
|
||||
affectedSections.push(section.id);
|
||||
}
|
||||
});
|
||||
stateManager.setReadOnly(true);
|
||||
if (affectedSections.size == 0) {
|
||||
return null;
|
||||
}
|
||||
// Get all collapsed section ids.
|
||||
const collapsedSectionIds = [];
|
||||
const state = stateManager.state;
|
||||
state.section.forEach(section => {
|
||||
if (section[preferenceName]) {
|
||||
collapsedSectionIds.push(section.id);
|
||||
}
|
||||
});
|
||||
return collapsedSectionIds;
|
||||
return affectedSections;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,9 +131,9 @@ export default class Component extends BaseComponent {
|
||||
const toggler = section.querySelector(this.selectors.COLLAPSE);
|
||||
const isCollapsed = toggler?.classList.contains(this.classes.COLLAPSED) ?? false;
|
||||
|
||||
if (isChevron || isCollapsed) {
|
||||
// Update the state.
|
||||
const sectionId = section.getAttribute('data-id');
|
||||
// Update the state.
|
||||
const sectionId = section.getAttribute('data-id');
|
||||
if (!sectionlink || isCollapsed) {
|
||||
this.reactive.dispatch(
|
||||
'sectionIndexCollapsed',
|
||||
[sectionId],
|
||||
|
@ -726,8 +726,9 @@ abstract class base {
|
||||
global $USER;
|
||||
$course = $this->get_course();
|
||||
try {
|
||||
$sectionpreferences = (array) json_decode(
|
||||
get_user_preferences("coursesectionspreferences_{$course->id}", '', $USER->id)
|
||||
$sectionpreferences = json_decode(
|
||||
get_user_preferences("coursesectionspreferences_{$course->id}", '', $USER->id),
|
||||
true,
|
||||
);
|
||||
if (empty($sectionpreferences)) {
|
||||
$sectionpreferences = [];
|
||||
@ -746,10 +747,65 @@ abstract class base {
|
||||
*
|
||||
*/
|
||||
public function set_sections_preference(string $preferencename, array $sectionids) {
|
||||
global $USER;
|
||||
$course = $this->get_course();
|
||||
$sectionpreferences = $this->get_sections_preferences_by_preference();
|
||||
$sectionpreferences[$preferencename] = $sectionids;
|
||||
$this->persist_to_user_preference($sectionpreferences);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add section preference ids.
|
||||
*
|
||||
* @param string $preferencename preference name
|
||||
* @param array $sectionids affected section ids
|
||||
*/
|
||||
public function add_section_preference_ids(
|
||||
string $preferencename,
|
||||
array $sectionids,
|
||||
): void {
|
||||
$sectionpreferences = $this->get_sections_preferences_by_preference();
|
||||
if (!isset($sectionpreferences[$preferencename])) {
|
||||
$sectionpreferences[$preferencename] = [];
|
||||
}
|
||||
foreach ($sectionids as $sectionid) {
|
||||
if (!in_array($sectionid, $sectionpreferences[$preferencename])) {
|
||||
$sectionpreferences[$preferencename][] = $sectionid;
|
||||
}
|
||||
}
|
||||
$this->persist_to_user_preference($sectionpreferences);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove section preference ids.
|
||||
*
|
||||
* @param string $preferencename preference name
|
||||
* @param array $sectionids affected section ids
|
||||
*/
|
||||
public function remove_section_preference_ids(
|
||||
string $preferencename,
|
||||
array $sectionids,
|
||||
): void {
|
||||
$sectionpreferences = $this->get_sections_preferences_by_preference();
|
||||
if (!isset($sectionpreferences[$preferencename])) {
|
||||
$sectionpreferences[$preferencename] = [];
|
||||
}
|
||||
foreach ($sectionids as $sectionid) {
|
||||
if (($key = array_search($sectionid, $sectionpreferences[$preferencename])) !== false) {
|
||||
unset($sectionpreferences[$preferencename][$key]);
|
||||
}
|
||||
}
|
||||
$this->persist_to_user_preference($sectionpreferences);
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist the section preferences to the user preferences.
|
||||
*
|
||||
* @param array $sectionpreferences the section preferences
|
||||
*/
|
||||
private function persist_to_user_preference(
|
||||
array $sectionpreferences,
|
||||
): void {
|
||||
global $USER;
|
||||
$course = $this->get_course();
|
||||
set_user_preference('coursesectionspreferences_' . $course->id, json_encode($sectionpreferences), $USER->id);
|
||||
// Invalidate section preferences cache.
|
||||
$coursesectionscache = cache::make('core', 'coursesectionspreferences');
|
||||
|
@ -832,7 +832,7 @@ class stateactions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the course content section collapsed value.
|
||||
* Update the course content section state to collapse.
|
||||
*
|
||||
* @param stateupdates $updates the affected course elements track
|
||||
* @param stdClass $course the course object
|
||||
@ -845,17 +845,40 @@ class stateactions {
|
||||
stdClass $course,
|
||||
array $ids = [],
|
||||
?int $targetsectionid = null,
|
||||
?int $targetcmid = null
|
||||
?int $targetcmid = null,
|
||||
): void {
|
||||
if (!empty($ids)) {
|
||||
$this->validate_sections($course, $ids, __FUNCTION__);
|
||||
}
|
||||
$format = course_get_format($course->id);
|
||||
$format->set_sections_preference('contentcollapsed', $ids);
|
||||
$format->add_section_preference_ids('contentcollapsed', $ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the course index section collapsed value.
|
||||
* Update the course content section state to expand.
|
||||
*
|
||||
* @param stateupdates $updates the affected course elements track
|
||||
* @param stdClass $course the course object
|
||||
* @param int[] $ids the collapsed section ids
|
||||
* @param int|null $targetsectionid not used
|
||||
* @param int|null $targetcmid not used
|
||||
*/
|
||||
public function section_content_expanded(
|
||||
stateupdates $updates,
|
||||
stdClass $course,
|
||||
array $ids = [],
|
||||
?int $targetsectionid = null,
|
||||
?int $targetcmid = null,
|
||||
): void {
|
||||
if (!empty($ids)) {
|
||||
$this->validate_sections($course, $ids, __FUNCTION__);
|
||||
}
|
||||
$format = course_get_format($course->id);
|
||||
$format->remove_section_preference_ids('contentcollapsed', $ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the course index section state to collapse.
|
||||
*
|
||||
* @param stateupdates $updates the affected course elements track
|
||||
* @param stdClass $course the course object
|
||||
@ -868,13 +891,36 @@ class stateactions {
|
||||
stdClass $course,
|
||||
array $ids = [],
|
||||
?int $targetsectionid = null,
|
||||
?int $targetcmid = null
|
||||
?int $targetcmid = null,
|
||||
): void {
|
||||
if (!empty($ids)) {
|
||||
$this->validate_sections($course, $ids, __FUNCTION__);
|
||||
}
|
||||
$format = course_get_format($course->id);
|
||||
$format->set_sections_preference('indexcollapsed', $ids);
|
||||
$format->add_section_preference_ids('indexcollapsed', $ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the course index section state to expand.
|
||||
*
|
||||
* @param stateupdates $updates the affected course elements track
|
||||
* @param stdClass $course the course object
|
||||
* @param int[] $ids the collapsed section ids
|
||||
* @param int|null $targetsectionid not used
|
||||
* @param int|null $targetcmid not used
|
||||
*/
|
||||
public function section_index_expanded(
|
||||
stateupdates $updates,
|
||||
stdClass $course,
|
||||
array $ids = [],
|
||||
?int $targetsectionid = null,
|
||||
?int $targetcmid = null,
|
||||
): void {
|
||||
if (!empty($ids)) {
|
||||
$this->validate_sections($course, $ids, __FUNCTION__);
|
||||
}
|
||||
$format = course_get_format($course->id);
|
||||
$format->remove_section_preference_ids('indexcollapsed', $ids);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -366,6 +366,73 @@ class base_test extends advanced_testcase {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test add_section_preference_ids() method.
|
||||
*
|
||||
* @covers \core_courseformat\base::persist_to_user_preference
|
||||
*/
|
||||
public function test_add_section_preference_ids(): void {
|
||||
$this->resetAfterTest();
|
||||
// Create initial data.
|
||||
$generator = $this->getDataGenerator();
|
||||
$course = $generator->create_course();
|
||||
$user = $generator->create_and_enrol($course);
|
||||
// Get the course format.
|
||||
$format = course_get_format($course);
|
||||
// Login as the user.
|
||||
$this->setUser($user);
|
||||
|
||||
// Add section preference ids.
|
||||
$format->add_section_preference_ids('pref1', [1, 2]);
|
||||
$format->add_section_preference_ids('pref1', [3]);
|
||||
$format->add_section_preference_ids('pref2', [1]);
|
||||
|
||||
// Get section preferences.
|
||||
$sectionpreferences = $format->get_sections_preferences_by_preference();
|
||||
$this->assertCount(3, $sectionpreferences['pref1']);
|
||||
$this->assertContains(1, $sectionpreferences['pref1']);
|
||||
$this->assertContains(2, $sectionpreferences['pref1']);
|
||||
$this->assertContains(3, $sectionpreferences['pref1']);
|
||||
$this->assertCount(1, $sectionpreferences['pref2']);
|
||||
$this->assertContains(1, $sectionpreferences['pref1']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test remove_section_preference_ids() method.
|
||||
*
|
||||
* @covers \core_courseformat\base::persist_to_user_preference
|
||||
*/
|
||||
public function test_remove_section_preference_ids(): void {
|
||||
$this->resetAfterTest();
|
||||
// Create initial data.
|
||||
$generator = $this->getDataGenerator();
|
||||
$course = $generator->create_course();
|
||||
$user = $generator->create_and_enrol($course);
|
||||
// Get the course format.
|
||||
$format = course_get_format($course);
|
||||
// Login as the user.
|
||||
$this->setUser($user);
|
||||
// Set initial preferences.
|
||||
$format->set_sections_preference('pref1', [1, 2, 3]);
|
||||
$format->set_sections_preference('pref2', [1]);
|
||||
|
||||
// Remove section with id = 3 out of the pref1.
|
||||
$format->remove_section_preference_ids('pref1', [3]);
|
||||
// Get section preferences.
|
||||
$sectionpreferences = $format->get_sections_preferences_by_preference();
|
||||
$this->assertCount(2, $sectionpreferences['pref1']);
|
||||
$this->assertCount(1, $sectionpreferences['pref2']);
|
||||
|
||||
// Remove section with id = 2 out of the pref1.
|
||||
$format->remove_section_preference_ids('pref1', [2]);
|
||||
// Remove section with id = 1 out of the pref2.
|
||||
$format->remove_section_preference_ids('pref2', [1]);
|
||||
// Get section preferences.
|
||||
$sectionpreferences = $format->get_sections_preferences_by_preference();
|
||||
$this->assertCount(1, $sectionpreferences['pref1']);
|
||||
$this->assertEmpty($sectionpreferences['pref2']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that retrieving last section number for a course
|
||||
*
|
||||
|
@ -59,6 +59,8 @@ plugins can now include the string 'plugin_description' to provide a description
|
||||
* A new item, initsections, has been added to the testing_data_generator::create_course() function, to let the generator rename
|
||||
the sections to "Section X".
|
||||
* The core_courseformat\base::get_format_string last parameter has been removed because it was erroneous.
|
||||
* New core_courseformat\base::add_section_preference_ids() to add the section ids to course format preferences.
|
||||
* New core_courseformat\base::remove_section_preference_ids() to remove the section ids out of course format preferences.
|
||||
|
||||
=== 4.3 ===
|
||||
* New core_courseformat\output\activitybadge class that can be extended by any module to display content near the activity name.
|
||||
|
Loading…
x
Reference in New Issue
Block a user