Merge branch 'MDL-76894-master' of https://github.com/ferranrecio/moodle

This commit is contained in:
Jun Pataleta 2023-03-20 10:43:04 +08:00
commit 109d902105
18 changed files with 637 additions and 26 deletions

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

View File

@ -211,11 +211,10 @@ export default class extends BaseComponent {
*/
async _requestMoveSection(target, event) {
// Check we have an id.
const sectionId = target.dataset.id;
if (!sectionId) {
const sectionIds = this._getTargetIds(target);
if (sectionIds.length == 0) {
return;
}
const sectionInfo = this.reactive.get('section', sectionId);
event.preventDefault();
@ -225,27 +224,38 @@ export default class extends BaseComponent {
// Collect section information from the state.
const exporter = this.reactive.getExporter();
const data = exporter.course(this.reactive.state);
let titleText = null;
// Add the target section id and title.
data.sectionid = sectionInfo.id;
data.sectiontitle = sectionInfo.title;
let sectionInfo = null;
if (sectionIds.length == 1) {
sectionInfo = this.reactive.get('section', sectionIds[0]);
data.sectionid = sectionInfo.id;
data.sectiontitle = sectionInfo.title;
data.information = await this.reactive.getFormatString('sectionmove_info', data.sectiontitle);
titleText = this.reactive.getFormatString('sectionmove_title');
} else {
data.information = await this.reactive.getFormatString('sectionsmove_info', sectionIds.length);
titleText = this.reactive.getFormatString('sectionsmove_title');
}
// Build the modal parameters from the event data.
const modalParams = {
title: getString('movecoursesection', 'core'),
title: titleText,
body: Templates.render('core_courseformat/local/content/movesection', data),
};
// Create the modal.
const modal = await this._modalBodyRenderedPromise(modalParams);
const modalBody = getList(modal.getBody())[0];
const modalBody = getFirst(modal.getBody());
// Disable current element and section zero.
const currentElement = modalBody.querySelector(`${this.selectors.SECTIONLINK}[data-id='${sectionId}']`);
this._disableLink(currentElement);
const generalSection = modalBody.querySelector(`${this.selectors.SECTIONLINK}[data-number='0']`);
this._disableLink(generalSection);
// Disable current selected section ids.
sectionIds.forEach(sectionId => {
const currentElement = modalBody.querySelector(`${this.selectors.SECTIONLINK}[data-id='${sectionId}']`);
this._disableLink(currentElement);
});
// Setup keyboard navigation.
new ContentTree(
@ -268,7 +278,7 @@ export default class extends BaseComponent {
return;
}
event.preventDefault();
this.reactive.dispatch('sectionMove', [sectionId], target.dataset.id);
this.reactive.dispatch('sectionMoveAfter', sectionIds, target.dataset.id);
this._destroyModal(modal, editTools);
});
}

View File

@ -245,6 +245,26 @@ export default class {
const course = stateManager.get('course');
this.sectionLock(stateManager, sectionIds, true);
const updates = await this._callEditWebservice('section_move', course.id, sectionIds, targetSectionId);
this.bulkReset(stateManager);
stateManager.processUpdates(updates);
this.sectionLock(stateManager, sectionIds, false);
}
/**
* Move course modules after a specific course location.
*
* @param {StateManager} stateManager the current state manager
* @param {array} sectionIds the list of section ids to move
* @param {number} targetSectionId the target section id
*/
async sectionMoveAfter(stateManager, sectionIds, targetSectionId) {
if (!targetSectionId) {
throw new Error(`Mutation sectionMoveAfter requires targetSectionId`);
}
const course = stateManager.get('course');
this.sectionLock(stateManager, sectionIds, true);
const updates = await this._callEditWebservice('section_move_after', course.id, sectionIds, targetSectionId);
this.bulkReset(stateManager);
stateManager.processUpdates(updates);
this.sectionLock(stateManager, sectionIds, false);
}

View File

@ -86,6 +86,8 @@ abstract class base {
private static $instances = array();
/** @var array plugin name => class name. */
private static $classesforformat = array('site' => 'site');
/** @var sectionmanager the format section manager. */
protected $sectionmanager = null;
/**
* Creates a new instance of class
@ -810,6 +812,10 @@ abstract class base {
'sectiondelete_info',
'sectionsdelete_title',
'sectionsdelete_info',
'sectionmove_title',
'sectionmove_info',
'sectionsmove_title',
'sectionsmove_info',
'selectsection'
];
foreach ($formatoverridbles as $key) {
@ -1546,6 +1552,31 @@ abstract class base {
course_delete_module($cm->id, $async);
}
/**
* Moves a section just after the target section.
*
* @param section_info $section the section to move
* @param section_info $destination the section that should be below the moved section
* @return boolean if the section can be moved or not
*/
public function move_section_after(section_info $section, section_info $destination): bool {
if ($section->section == $destination->section || $section->section == $destination->section + 1) {
return true;
}
// The move_section_to moves relative to the section to move. However, this
// method will move the target section always after the destination.
if ($section->section > $destination->section) {
$newsectionnumber = $destination->section + 1;
} else {
$newsectionnumber = $destination->section;
}
return move_section_to(
$this->get_course(),
$section->section,
$newsectionnumber
);
}
/**
* Prepares the templateable object to display section name
*

View File

@ -137,6 +137,7 @@ class bulkedittools implements named_templatable, renderable {
global $USER;
$format = $this->format;
$context = $format->get_context();
$sectionreturn = $format->get_section_number();
$user = $USER;
$controls = [];
@ -151,6 +152,15 @@ class bulkedittools implements named_templatable, renderable {
];
}
if (!$sectionreturn && has_capability('moodle/course:movesections', $context, $user)) {
$controls['move'] = [
'icon' => 'i/dragdrop',
'action' => 'moveSection',
'name' => get_string('move', 'moodle'),
'title' => $this->format->get_format_string('sectionsmove'),
'bulk' => 'section',
];
}
$deletecapabilities = ['moodle/course:movesections', 'moodle/course:update'];
if (has_all_capabilities($deletecapabilities, $context, $user)) {

View File

@ -164,6 +164,91 @@ class stateactions {
$updates->add_course_put();
}
/**
* Move course sections after to another location in the same course.
*
* @param stateupdates $updates the affected course elements track
* @param stdClass $course the course object
* @param int[] $ids the list of affected course module ids
* @param int $targetsectionid optional target section id
* @param int $targetcmid optional target cm id
*/
public function section_move_after(
stateupdates $updates,
stdClass $course,
array $ids,
?int $targetsectionid = null,
?int $targetcmid = null
): void {
// Validate target elements.
if (!$targetsectionid) {
throw new moodle_exception("Action section_move_after requires targetsectionid");
}
$this->validate_sections($course, $ids, __FUNCTION__);
$coursecontext = context_course::instance($course->id);
require_capability('moodle/course:movesections', $coursecontext);
// Section will move after the target section. This means it should be processed in
// descending order to keep the relative course order.
$this->validate_sections($course, [$targetsectionid], __FUNCTION__);
$ids = $this->sort_section_ids_by_section_number($course, $ids, true);
$format = course_get_format($course->id);
$affectedsections = [$targetsectionid => true];
foreach ($ids as $id) {
// An update section_info is needed as section numbers can change on every section movement.
$modinfo = get_fast_modinfo($course);
$section = $modinfo->get_section_info_by_id($id, MUST_EXIST);
$targetsection = $modinfo->get_section_info_by_id($targetsectionid, MUST_EXIST);
$affectedsections[$section->id] = true;
$format->move_section_after($section, $targetsection);
}
// Use section_state to return the section and activities updated state.
$this->section_state($updates, $course, $ids, $targetsectionid);
// All course sections can be renamed because of the resort.
$modinfo = get_fast_modinfo($course);
$allsections = $modinfo->get_section_info_all();
foreach ($allsections as $section) {
// Ignore the affected sections because they are already in the updates.
if (isset($affectedsections[$section->id])) {
continue;
}
$updates->add_section_put($section->id);
}
// The section order is at a course level.
$updates->add_course_put();
}
/**
* Sort the sections ids depending on the section number.
*
* Some actions like move should be done in an specific order.
*
* @param stdClass $course the course object
* @param int[] $sectionids the array of section $ids
* @param bool $descending if the sort order must be descending instead of ascending
* @return int[] the array of section ids sorted by section number
*/
protected function sort_section_ids_by_section_number(
stdClass $course,
array $sectionids,
bool $descending = false
): array {
$sorting = ($descending) ? -1 : 1;
$sortfunction = function ($asection, $bsection) use ($sorting) {
return ($asection->section <=> $bsection->section) * $sorting;
};
$modinfo = get_fast_modinfo($course);
$sections = $this->get_section_info($modinfo, $sectionids);
uasort($sections, $sortfunction);
return array_keys($sections);
}
/**
* Create a course section.
*

View File

@ -42,7 +42,11 @@
}
}}
<p data-for="sectionname">{{#str}} movefull, moodle, {{sectiontitle}} {{/str}}:</p>
{{#information}}
<p data-for="sectionname">
{{information}}:
</p>
{{/information}}
<nav class="collapse-list" id="destination-selector" role="tree">
{{#sections}}
<div

View File

@ -537,6 +537,131 @@ class base_test extends advanced_testcase {
],
];
}
/**
* Test for the move_section_after method.
*
* @covers ::move_section_after
* @dataProvider move_section_after_provider
* @param string $movesection the reference of the section to move
* @param string $destination the reference of the destination section
* @param string[] $order the references of the final section order
*/
public function test_move_section_after(string $movesection, string $destination, array $order) {
global $DB;
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
course_create_sections_if_missing($course, [0, 1, 2, 3, 4, 5]);
$format = course_get_format($course);
$modinfo = $format->get_modinfo();
$sectionsinfo = $modinfo->get_section_info_all();
$references = [];
foreach ($sectionsinfo as $section) {
$references["section{$section->section}"] = $section;
}
$result = $format->move_section_after(
$references[$movesection],
$references[$destination]
);
$this->assertEquals(true, $result);
// Check the updated course section list.
$modinfo = $format->get_modinfo();
$sectionsinfo = $modinfo->get_section_info_all();
$this->assertCount(count($order), $sectionsinfo);
foreach ($sectionsinfo as $key => $section) {
$sectionreference = $order[$key];
$oldinfo = $references[$sectionreference];
$this->assertEquals($oldinfo->id, $section->id);
}
}
/**
* Data provider for test_move_section_after.
*
* @return array the testing scenarios
*/
public function move_section_after_provider(): array {
return [
'Move top' => [
'movesection' => 'section3',
'destination' => 'section0',
'order' => [
'section0',
'section3',
'section1',
'section2',
'section4',
'section5',
],
],
'Move up' => [
'movesection' => 'section3',
'destination' => 'section1',
'order' => [
'section0',
'section1',
'section3',
'section2',
'section4',
'section5',
],
],
'Do not move' => [
'movesection' => 'section3',
'destination' => 'section2',
'order' => [
'section0',
'section1',
'section2',
'section3',
'section4',
'section5',
],
],
'Same position' => [
'movesection' => 'section3',
'destination' => 'section3',
'order' => [
'section0',
'section1',
'section2',
'section3',
'section4',
'section5',
],
],
'Move down' => [
'movesection' => 'section3',
'destination' => 'section4',
'order' => [
'section0',
'section1',
'section2',
'section4',
'section3',
'section5',
],
],
'Move bottom' => [
'movesection' => 'section3',
'destination' => 'section5',
'order' => [
'section0',
'section1',
'section2',
'section4',
'section5',
'section3',
],
],
];
}
}
/**

View File

@ -154,3 +154,58 @@ Feature: Bulk course section actions.
And I should not see "Activity sample 3" in the "Topic 2" "section"
And I should not see "Activity sample 4" in the "Topic 2" "section"
And I should see "0 selected" in the "sticky-footer" "region"
Scenario: Bulk move topics after general section
Given I set the field "Edit topic name" in the "Topic 2" "section" to "Move one"
And I set the field "Edit topic name" in the "Topic 3" "section" to "Move two"
And I click on "Select topic Move one" "checkbox"
And I click on "Select topic Move two" "checkbox"
And I should see "2 selected" in the "sticky-footer" "region"
When I click on "Move topics" "button" in the "sticky-footer" "region"
And I click on "General" "link" in the "Move selected topics" "dialogue"
# Check activities are moved with the topics.
Then I should see "Activity sample 1" in the "Topic 3" "section"
And I should see "Activity sample 2" in the "Topic 3" "section"
And I should see "Activity sample 3" in the "Move one" "section"
And I should see "Activity sample 4" in the "Move one" "section"
# Check new section order.
And "Move one" "section" should appear after "General" "section"
And "Move two" "section" should appear after "Move one" "section"
And "Topic 3" "section" should appear after "Move two" "section"
And "Topic 4" "section" should appear after "Topic 3" "section"
Scenario: Bulk move topics at the end of the course
Given I set the field "Edit topic name" in the "Topic 3" "section" to "Move me"
And I click on "Select topic Topic 2" "checkbox"
And I click on "Select topic Move me" "checkbox"
And I should see "2 selected" in the "sticky-footer" "region"
When I click on "Move topics" "button" in the "sticky-footer" "region"
And I click on "Topic 4" "link" in the "Move selected topics" "dialogue"
# Check activities are moved with the topics.
Then I should see "Activity sample 1" in the "Topic 1" "section"
And I should see "Activity sample 2" in the "Topic 1" "section"
And I should see "Activity sample 3" in the "Topic 3" "section"
And I should see "Activity sample 4" in the "Topic 3" "section"
# Check new section order.
And "Topic 1" "section" should appear after "General" "section"
And "Topic 2" "section" should appear after "Topic 1" "section"
And "Topic 3" "section" should appear after "Topic 2" "section"
And "Move me" "section" should appear after "Topic 3" "section"
Scenario: Bulk move topics in the middle of the course
Given I set the field "Edit topic name" in the "Topic 4" "section" to "Move me"
And I click on "Select topic Topic 1" "checkbox"
And I click on "Select topic Move me" "checkbox"
And I should see "2 selected" in the "sticky-footer" "region"
When I click on "Move topics" "button" in the "sticky-footer" "region"
And I click on "Topic 2" "link" in the "Move selected topics" "dialogue"
# Check activities are moved with the topics.
Then I should see "Activity sample 1" in the "Topic 2" "section"
And I should see "Activity sample 2" in the "Topic 2" "section"
And I should see "Activity sample 3" in the "Topic 1" "section"
And I should see "Activity sample 4" in the "Topic 1" "section"
# Check new section order.
And "Topic 1" "section" should appear after "General" "section"
And "Topic 2" "section" should appear after "Topic 1" "section"
And "Move me" "section" should appear after "Topic 2" "section"
And "Topic 4" "section" should appear after "Move me" "section"

View File

@ -27,8 +27,7 @@ Feature: Move a section using keyboard
# Focus on the modal content tree.
When I press the tab key
And I press the tab key
# Select the section 2.
And I press the down key
# Select the section 1.
And I press the down key
And I press enter
Then I should see "Activity sample 3" in the "Topic 2" "section"
@ -59,7 +58,5 @@ Feature: Move a section using keyboard
And I press the down key
# Go to the first section.
And I press the home key
# Move down to Topic 1
And I press the down key
And I press enter
Then I should see "Activity sample 3" in the "Topic 1" "section"

View File

@ -603,6 +603,8 @@ class stateactions_test extends \advanced_testcase {
* @param int|string|null $sectionvalue the section field value
* @param string|null $cmfield the cm field to check
* @param int|string|null $cmvalue the cm field value
* @param string|null $targetsection optional target section reference
* @param string|null $targetcm optional target cm reference
* @return array an array of elements to do extra validations (course, references, results)
*/
protected function basic_state_text(
@ -616,7 +618,9 @@ class stateactions_test extends \advanced_testcase {
?string $sectionfield = null,
$sectionvalue = 0,
?string $cmfield = null,
$cmvalue = 0
$cmvalue = 0,
?string $targetsection = null,
?string $targetcm = null
): array {
$this->resetAfterTest();
@ -651,6 +655,8 @@ class stateactions_test extends \advanced_testcase {
$updates,
$course,
$this->translate_references($references, $idrefs),
($targetsection) ? $references[$targetsection] : null,
($targetcm) ? $references[$targetcm] : null,
);
// Format results in a way we can compare easily.
@ -1130,4 +1136,206 @@ class stateactions_test extends \advanced_testcase {
0
);
}
/**
* Test for section_move_after
*
* @covers ::section_move_after
* @dataProvider section_move_after_provider
* @param string[] $sectiontomove the sections to move
* @param string $targetsection the target section reference
* @param string[] $finalorder the final sections order
* @param string[] $updatedcms the list of cms in the state updates
* @param int $totalputs the total amount of put updates
*/
public function test_section_move_after(
array $sectiontomove,
string $targetsection,
array $finalorder,
array $updatedcms,
int $totalputs
): void {
$this->resetAfterTest();
$course = $this->create_course('topics', 8, []);
$references = $this->course_references($course);
// Add some activities to the course. One visible and one hidden in both sections 1 and 2.
$references["cm0"] = $this->create_activity($course->id, 'assign', 1, true);
$references["cm1"] = $this->create_activity($course->id, 'book', 1, false);
$references["cm2"] = $this->create_activity($course->id, 'glossary', 2, true);
$references["cm3"] = $this->create_activity($course->id, 'page', 2, false);
$references["cm4"] = $this->create_activity($course->id, 'forum', 3, false);
$references["cm5"] = $this->create_activity($course->id, 'wiki', 3, false);
$user = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user->id, $course->id, 'editingteacher');
$this->setUser($user);
// Initialise stateupdates.
$courseformat = course_get_format($course->id);
$updates = new stateupdates($courseformat);
// Execute the method.
$actions = new stateactions();
$actions->section_move_after(
$updates,
$course,
$this->translate_references($references, $sectiontomove),
$references[$targetsection]
);
// Format results in a way we can compare easily.
$results = $this->summarize_updates($updates);
// Validate we have all the expected entries.
$this->assertEquals(0, $results['create']['count']);
$this->assertEquals(0, $results['remove']['count']);
// Moving a section puts:
// - The course state.
// - All sections state.
// - The cm states related to the moved and target sections.
$this->assertEquals($totalputs, $results['put']['count']);
// Course state should contain the sorted list of sections (section zero + 8 sections).
$finalsectionids = $this->translate_references($references, $finalorder);
$coursestate = reset($results['put']['course']);
$this->assertEquals($finalsectionids, $coursestate->sectionlist);
// All sections should be present in the update.
$this->assertCount(9, $results['put']['section']);
// Only cms from the affected sections should be updated.
$cmids = $this->translate_references($references, $updatedcms);
$cms = $results['put']['cm'];
foreach ($cmids as $cmid) {
$this->assertArrayHasKey($cmid, $cms);
}
}
/**
* Provider for test_section_move_after.
*
* @return array the testing scenarios
*/
public function section_move_after_provider(): array {
return [
'Move sections down' => [
'sectiontomove' => ['section2', 'section4'],
'targetsection' => 'section7',
'finalorder' => [
'section0',
'section1',
'section3',
'section5',
'section6',
'section7',
'section2',
'section4',
'section8',
],
'updatedcms' => ['cm2', 'cm3'],
'totalputs' => 12,
],
'Move sections up' => [
'sectiontomove' => ['section3', 'section5'],
'targetsection' => 'section1',
'finalorder' => [
'section0',
'section1',
'section3',
'section5',
'section2',
'section4',
'section6',
'section7',
'section8',
],
'updatedcms' => ['cm0', 'cm1', 'cm4', 'cm5'],
'totalputs' => 14,
],
'Move sections in the middle' => [
'sectiontomove' => ['section2', 'section5'],
'targetsection' => 'section3',
'finalorder' => [
'section0',
'section1',
'section3',
'section2',
'section5',
'section4',
'section6',
'section7',
'section8',
],
'updatedcms' => ['cm2', 'cm3', 'cm4', 'cm5'],
'totalputs' => 14,
],
'Move sections on top' => [
'sectiontomove' => ['section3', 'section5'],
'targetsection' => 'section0',
'finalorder' => [
'section0',
'section3',
'section5',
'section1',
'section2',
'section4',
'section6',
'section7',
'section8',
],
'updatedcms' => ['cm4', 'cm5'],
'totalputs' => 12,
],
'Move sections on bottom' => [
'sectiontomove' => ['section3', 'section5'],
'targetsection' => 'section8',
'finalorder' => [
'section0',
'section1',
'section2',
'section4',
'section6',
'section7',
'section8',
'section3',
'section5',
],
'updatedcms' => ['cm4', 'cm5'],
'totalputs' => 12,
],
];
}
/**
* Test for section_move_after capability checks.
*
* @covers ::section_move_after
* @dataProvider basic_role_provider
* @param string $role the user role
* @param bool $expectedexception if it will expect an exception.
*/
public function test_section_move_after_capabilities(
string $role = 'editingteacher',
bool $expectedexception = false
): void {
$this->resetAfterTest();
// We want modules to be deleted for good.
set_config('coursebinenable', 0, 'tool_recyclebin');
$info = $this->basic_state_text(
'section_move_after',
$role,
['section2'],
$expectedexception,
['put' => 9],
null,
0,
null,
0,
null,
0,
'section0'
);
}
}

View File

@ -37,9 +37,13 @@ $string['indentation'] = 'Allow indentation on course page';
$string['indentation_help'] = 'Allow teachers, and other users with the manage activities capability, to indent items on the course page.';
$string['section0name'] = 'General';
$string['sectiondelete_title'] = 'Delete topic?';
$string['sectionmove_title'] = 'Move topic';
$string['sectionname'] = 'Topic';
$string['sectionsdelete'] = 'Delete topics';
$string['sectionsdelete_info'] = 'This will delete {$a->count} topics and all the activities they contain.';
$string['sectionsdelete_title'] = 'Delete selected topics?';
$string['sectionsmove'] = 'Move topics';
$string['sectionsmove_info'] = 'Move {$a} topics after';
$string['sectionsmove_title'] = 'Move selected topics';
$string['selectsection'] = 'Select topic {$a}';
$string['showfromothers'] = 'Show topic';

View File

@ -39,9 +39,13 @@ $string['indentation'] = 'Allow indentation on course page';
$string['indentation_help'] = 'Allow teachers, and other users with the manage activities capability, to indent items on the course page.';
$string['section0name'] = 'General';
$string['sectiondelete_title'] = 'Delete week?';
$string['sectionmove_title'] = 'Move section';
$string['sectionname'] = 'Week';
$string['sectionsdelete'] = 'Delete weeks';
$string['sectionsdelete_info'] = 'This will delete {$a->count} weeks and all the activities they contain.';
$string['sectionsdelete_title'] = 'Delete selected weeks?';
$string['sectionsmove'] = 'Move weeks';
$string['sectionsmove_info'] = 'Move {$a} weeks after';
$string['sectionsmove_title'] = 'Move selected weeks';
$string['selectsection'] = 'Select week {$a}';
$string['showfromothers'] = 'Show week';

View File

@ -1,4 +1,4 @@
@core @core_courseformat @core_course @format_weeks @show_editor
@core @core_courseformat @core_course @format_weeks @show_editor @javascript
Feature: Weeks format bulk activity actions.
In order to edit the course weeks
As a teacher
@ -29,7 +29,6 @@ Feature: Weeks format bulk activity actions.
And I click on "Bulk edit" "button"
And I should see "0 selected" in the "sticky-footer" "region"
@javascript
Scenario: Delete a single week using bulk action
Given I should see "1 May - 7 May" in the "region-main" "region"
And I should see "8 May - 14 May" in the "region-main" "region"
@ -54,7 +53,6 @@ Feature: Weeks format bulk activity actions.
And I should not see "Activity sample 4" in the "8 May - 14 May" "section"
And I should see "0 selected" in the "sticky-footer" "region"
@javascript
Scenario: Delete several weeks in bulk
Given I should see "1 May - 7 May" in the "region-main" "region"
And I should see "8 May - 14 May" in the "region-main" "region"
@ -79,3 +77,58 @@ Feature: Weeks format bulk activity actions.
And I should not see "Activity sample 3" in the "8 May - 14 May" "section"
And I should not see "Activity sample 4" in the "8 May - 14 May" "section"
And I should see "0 selected" in the "sticky-footer" "region"
Scenario: Bulk move weeks after general section
Given I set the field "Edit week name" in the "8 May - 14 May" "section" to "Move one"
And I set the field "Edit week name" in the "15 May - 21 May" "section" to "Move two"
And I click on "Select week Move one" "checkbox"
And I click on "Select week Move two" "checkbox"
And I should see "2 selected" in the "sticky-footer" "region"
When I click on "Move weeks" "button" in the "sticky-footer" "region"
And I click on "General" "link" in the "Move selected weeks" "dialogue"
# Check activities are moved with the weeks.
Then I should see "Activity sample 1" in the "15 May - 21 May" "section"
And I should see "Activity sample 2" in the "15 May - 21 May" "section"
And I should see "Activity sample 3" in the "Move one" "section"
And I should see "Activity sample 4" in the "Move one" "section"
# Check new section order.
And "Move one" "section" should appear after "General" "section"
And "Move two" "section" should appear after "Move one" "section"
And "15 May - 21 May" "section" should appear after "Move two" "section"
And "22 May - 28 May" "section" should appear after "15 May - 21 May" "section"
Scenario: Bulk move weeks at the end of the course
Given I set the field "Edit week name" in the "15 May - 21 May" "section" to "Move me"
And I click on "Select week 8 May - 14 May" "checkbox"
And I click on "Select week Move me" "checkbox"
And I should see "2 selected" in the "sticky-footer" "region"
When I click on "Move weeks" "button" in the "sticky-footer" "region"
And I click on "22 May - 28 May" "link" in the "Move selected weeks" "dialogue"
# Check activities are moved with the weeks.
Then I should see "Activity sample 1" in the "1 May - 7 May" "section"
And I should see "Activity sample 2" in the "1 May - 7 May" "section"
And I should see "Activity sample 3" in the "15 May - 21 May" "section"
And I should see "Activity sample 4" in the "15 May - 21 May" "section"
# Check new section order.
And "1 May - 7 May" "section" should appear after "General" "section"
And "8 May - 14 May" "section" should appear after "1 May - 7 May" "section"
And "15 May - 21 May" "section" should appear after "8 May - 14 May" "section"
And "Move me" "section" should appear after "15 May - 21 May" "section"
Scenario: Bulk move weeks in the middle of the course
Given I set the field "Edit week name" in the "22 May - 28 May" "section" to "Move me"
And I click on "Select week 1 May - 7 May" "checkbox"
And I click on "Select week Move me" "checkbox"
And I should see "2 selected" in the "sticky-footer" "region"
When I click on "Move weeks" "button" in the "sticky-footer" "region"
And I click on "8 May - 14 May" "link" in the "Move selected weeks" "dialogue"
# Check activities are moved with the weeks.
Then I should see "Activity sample 1" in the "8 May - 14 May" "section"
And I should see "Activity sample 2" in the "8 May - 14 May" "section"
And I should see "Activity sample 3" in the "1 May - 7 May" "section"
And I should see "Activity sample 4" in the "1 May - 7 May" "section"
# Check new section order.
And "1 May - 7 May" "section" should appear after "General" "section"
And "8 May - 14 May" "section" should appear after "1 May - 7 May" "section"
And "Move me" "section" should appear after "8 May - 14 May" "section"
And "22 May - 28 May" "section" should appear after "Move me" "section"

View File

@ -46,7 +46,12 @@ $string['sectionavailability'] = 'Section availability';
$string['sectiondelete_info'] = 'This will delete "{$a->name}" and all the activities it contains.';
$string['sectiondelete_title'] = 'Delete section?';
$string['sectionsdelete'] = 'Delete sections';
$string['sectionmove_info'] = 'Move "{$a}" after';
$string['sectionmove_title'] = 'Move section';
$string['sectionsdelete_info'] = 'This will delete {$a->count} sections and all the activities they contain.';
$string['sectionsdelete_title'] = 'Delete selected sections?';
$string['sectionsmove'] = 'Move sections';
$string['sectionsmove_info'] = 'Move {$a} sections after';
$string['sectionsmove_title'] = 'Move selected sections';
$string['selectcm'] = 'Select activity {$a}';
$string['selectsection'] = 'Select section {$a}';