MDL-79912 backup: Create Course reuse index page

The backup/view.php page has been created to display the list of
course reuse actions available for users.
That way, the "Course reuse" option in the secondary navigation
will display this page instead of redirecting to the first action
available.

Apart from that, the headers for all the Course reuse actions have
been homogenised and the tertiary navigation selector has been included,
to replace headers and make it easier navigate between actions.
This commit is contained in:
Sara Arjona
2023-11-22 18:11:43 +01:00
parent b58d1fd4e2
commit 424c9cb1bd
17 changed files with 269 additions and 86 deletions
+3 -1
View File
@@ -81,7 +81,7 @@ require_login($course, false, $cm);
switch ($type) {
case backup::TYPE_1COURSE :
require_capability('moodle/backup:backupcourse', $coursecontext);
$heading = get_string('backupcourse', 'backup', $course->shortname);
$heading = $course->fullname;
$PAGE->set_secondary_active_tab('coursereuse');
break;
case backup::TYPE_1SECTION :
@@ -112,6 +112,8 @@ $PAGE->activityheader->disable();
if (empty($cancel)) {
// Do not print the header if user cancelled the process, as we are going to redirect the user.
echo $OUTPUT->header();
\backup_helper::print_coursereuse_selector('backup');
echo html_writer::tag('div', get_string('backupinfo'), ['class' => 'pb-3']);
}
// Only let user perform a backup if we aren't in async mode, or if we are
+1
View File
@@ -88,6 +88,7 @@ if ($data) {
}
echo $OUTPUT->header();
\backup_helper::print_coursereuse_selector('restore');
echo $OUTPUT->container_start();
echo $OUTPUT->heading($title);
+3 -3
View File
@@ -53,11 +53,10 @@ if ($returnurl != '') {
// Setup the page.
$title = get_string('copycoursetitle', 'backup', $course->shortname);
$heading = get_string('copycourseheading', 'backup');
$PAGE->set_url($url);
$PAGE->set_pagelayout('admin');
$PAGE->set_title($title);
$PAGE->set_heading($heading);
$PAGE->set_heading($course->fullname);
$PAGE->set_secondary_active_tab('coursereuse');
// Get data ready for mform.
@@ -91,7 +90,8 @@ if ($mform->is_cancelled()) {
// Build the page output.
echo $OUTPUT->header();
echo $OUTPUT->heading($title);
\backup_helper::print_coursereuse_selector('copycourse');
$mform->display();
echo $OUTPUT->footer();
}
+3 -1
View File
@@ -45,13 +45,15 @@ $title = get_string('copyprogresstitle', 'backup');
$PAGE->set_url($url);
$PAGE->set_pagelayout('admin');
$PAGE->set_title($title);
$PAGE->set_heading($title);
$PAGE->set_heading($course->fullname);
$PAGE->set_secondary_active_tab('coursereuse');
$PAGE->requires->js_call_amd('core_backup/async_backup', 'asyncCopyAllStatus');
$PAGE->secondarynav->set_overflow_selected_node('copy');
// Build the page output.
echo $OUTPUT->header();
\backup_helper::print_coursereuse_selector('copycourse');
echo $OUTPUT->heading_with_help(get_string('copyprogressheading', 'backup'), 'copyprogressheading', 'backup');
echo $OUTPUT->container_start();
$renderer = $PAGE->get_renderer('core', 'backup');
+12 -1
View File
@@ -69,6 +69,10 @@ if ($importcourseid === false || $searchcourses) {
// show the course selector
echo $OUTPUT->header();
\backup_helper::print_coursereuse_selector('import');
echo html_writer::tag('div', get_string('importinfo'), ['class' => 'pb-3']);
$backup = new import_ui(false, array());
echo $renderer->progress_bar($backup->get_progress_bar());
$html = $renderer->import_course_selector($url, $search);
@@ -118,6 +122,9 @@ if ($backup->get_stage() == backup_ui::STAGE_CONFIRMATION) {
// If it's the final stage process the import
if ($backup->get_stage() == backup_ui::STAGE_FINAL) {
echo $OUTPUT->header();
\backup_helper::print_coursereuse_selector('import');
echo html_writer::tag('div', get_string('importinfo'), ['class' => 'pb-3']);
// Display an extra progress bar so that we can show the current stage.
echo html_writer::start_div('', array('id' => 'executionprogress'));
@@ -233,8 +240,12 @@ if ($backup->get_stage() == backup_ui::STAGE_FINAL) {
$backup->save_controller();
}
// Display the current stage
// Display the current stage.
echo $OUTPUT->header();
\backup_helper::print_coursereuse_selector('import');
echo html_writer::tag('div', get_string('importinfo'), ['class' => 'pb-3']);
if ($backup->enforce_changed_dependencies()) {
debugging('Your settings have been altered due to unmet dependencies', DEBUG_DEVELOPER);
}
+2
View File
@@ -138,6 +138,8 @@ if ($data && has_capability('moodle/restore:uploadfile', $context)) {
}
echo $OUTPUT->header();
\backup_helper::print_coursereuse_selector('restore');
echo html_writer::tag('div', get_string('restoreinfo'), ['class' => 'pb-3']);
// require uploadfile cap to use file picker
if (has_capability('moodle/restore:uploadfile', $context)) {
@@ -380,6 +380,62 @@ abstract class backup_helper {
public static function get_inforef_itemnames() {
return array('user', 'grouping', 'group', 'role', 'file', 'scale', 'outcome', 'grade_item', 'question_category');
}
/**
* Print the course reuse dropdown.
*
* @param string $current The current course reuse option where the header is modified
*/
public static function print_coursereuse_selector(string $current):void {
global $OUTPUT, $PAGE;
if ($coursereusenode = $PAGE->settingsnav->find('coursereuse', \navigation_node::TYPE_CONTAINER)) {
$menuarray = \core\navigation\views\secondary::create_menu_element([$coursereusenode]);
if (empty($menuarray)) {
return;
}
$coursereuse = get_string('coursereuse');
$activeurl = '';
if (isset($menuarray[0])) {
// Remove the "Course reuse" entry.
$result = array_search($coursereuse, $menuarray[0][$coursereuse]);
unset($menuarray[0][$coursereuse][$result]);
// Find the active node.
foreach ($menuarray[0] as $key => $value) {
$check = array_search($current, $value);
if ($check !== false) {
$activeurl = $check;
}
}
} else {
$result = array_search($coursereuse, $menuarray);
unset($menuarray[$result]);
$check = array_search(get_string($current), $menuarray);
if ($check !== false) {
$activeurl = $check;
}
}
$selectmenu = new \core\output\select_menu('coursereusetype', $menuarray, $activeurl);
$selectmenu->set_label(get_string('coursereusenavigationmenu'), ['class' => 'sr-only']);
$options = \html_writer::tag(
'div',
$OUTPUT->render_from_template('core/tertiary_navigation_selector', $selectmenu->export_for_template($OUTPUT)),
['class' => 'row pb-3']
);
echo \html_writer::tag(
'div',
$options,
['class' => 'tertiary-navigation full-width-bottom-border ml-0', 'id' => 'tertiary-navigation']);
} else {
echo $OUTPUT->heading($current, 2, 'mb-3');
}
}
}
/*
+1 -1
View File
@@ -86,7 +86,7 @@ class copy_form extends \moodleform {
$mform->setConstant('returnurl', $returnurl);
// Form heading.
$mform->addElement('html', \html_writer::div(get_string('copycoursedesc', 'backup'), 'form-description mb-3'));
$mform->addElement('html', \html_writer::div(get_string('copycoursedesc', 'backup'), 'form-description mb-6'));
// Course fullname.
$mform->addElement('text', 'fullname', get_string('fullnamecourse'), 'maxlength="254" size="50"');
+73
View File
@@ -0,0 +1,73 @@
<?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/>.
/**
* Page to view the course reuse actions.
*
* @package core_backup
* @copyright 2023 Sara Arjona <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(__DIR__ . '/../config.php');
// Course id.
$courseid = required_param('id', PARAM_INT);
$PAGE->set_url(new moodle_url('/backup/view.php', ['id' => $courseid]));
// Basic access checks.
if (!$course = $DB->get_record('course', ['id' => $courseid])) {
throw new \moodle_exception('invalidcourseid');
}
require_login($course);
$title = get_string('coursereuse');
// Only append the course name if the course ID is not the site ID.
if ($courseid != SITEID) {
$title .= moodle_page::TITLE_SEPARATOR . $course->fullname;
}
// Otherwise, output the page with a notification stating that there are no available course reuse actions.
$PAGE->set_title($title);
$PAGE->set_pagelayout('incourse');
$PAGE->set_heading($course->fullname);
$PAGE->set_pagetype('course-view-' . $course->format);
$PAGE->add_body_class('limitedwidth');
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('coursereuse'));
// Check if there is at least one displayable course reuse action.
$hasactions = false;
if ($coursereusenode = $PAGE->settingsnav->find('coursereuse', \navigation_node::TYPE_CONTAINER)) {
foreach ($coursereusenode->children as $child) {
if ($child->display) {
$hasactions = true;
break;
}
}
}
if ($hasactions) {
echo $OUTPUT->render_from_template('core/report_link_page', ['node' => $coursereusenode]);
} else {
throw new \moodle_exception(
'accessdenied',
'admin',
new moodle_url('/course/view.php', ['id' => $courseid])
);
}
echo $OUTPUT->footer();
+6 -5
View File
@@ -29,6 +29,9 @@
require('../config.php');
require_once('reset_form.php');
require_once($CFG->dirroot . '/backup/util/interfaces/checksumable.class.php');
require_once($CFG->dirroot . '/backup/backup.class.php');
require_once($CFG->dirroot . '/backup/util/helper/backup_helper.class.php');
$id = required_param('id', PARAM_INT);
@@ -47,7 +50,7 @@ $strresetcourse = get_string('resetcourse');
$strremove = get_string('remove');
$PAGE->set_title($course->fullname.': '.$strresetcourse);
$PAGE->set_heading($course->fullname.': '.$strresetcourse);
$PAGE->set_heading($course->fullname);
$PAGE->set_secondary_active_tab('coursereuse');
$mform = new course_reset_form();
@@ -68,7 +71,7 @@ if ($mform->is_cancelled()) {
} else {
echo $OUTPUT->header();
echo $OUTPUT->heading($strresetcourse);
\backup_helper::print_coursereuse_selector('reset');
$data->reset_start_date_old = $course->startdate;
$data->reset_end_date_old = $course->enddate;
@@ -98,11 +101,9 @@ if ($mform->is_cancelled()) {
}
echo $OUTPUT->header();
echo $OUTPUT->heading($strresetcourse);
\backup_helper::print_coursereuse_selector('reset');
echo $OUTPUT->box(get_string('resetinfo'));
$mform->display();
echo $OUTPUT->footer();
+5 -3
View File
@@ -71,7 +71,6 @@ $string['automatedstorage'] = 'Automated backup storage';
$string['automatedstoragehelp'] = 'Choose the location where you want backups to be stored when they are automatically created.';
$string['backupactivity'] = 'Backup activity: {$a}';
$string['backupautoactivitiesdescription'] = 'Sets the default for including activities in a backup. For the recycle bin to work, this setting must be enabled.';
$string['backupcourse'] = 'Backup course: {$a}';
$string['backupcoursedetails'] = 'Course details';
$string['backupcoursesection'] = 'Section: {$a}';
$string['backupcoursesections'] = 'Course sections';
@@ -170,8 +169,7 @@ $string['confirmcancelno'] = 'Do not cancel';
$string['confirmnewcoursecontinue'] = 'New course warning';
$string['confirmnewcoursecontinuequestion'] = 'A temporary (hidden) course will be created by the course restoration process. To abort restoration click cancel. Do not close the browser while restoring.';
$string['copiesinprogress'] = 'This course has copies in progress. <a href="{$a}">View in progress copies.</a>';
$string['copycoursedesc'] = 'This course will be duplicated and put into the selected course category.';
$string['copycourseheading'] = 'Copy a course';
$string['copycoursedesc'] = 'Create a copy of this course in any course category.';
$string['copycoursetitle'] = 'Copy course: {$a}';
$string['copydest'] = 'Destination';
$string['copyingcourse'] = 'Course copying in progress';
@@ -421,3 +419,7 @@ $string['userinfo'] = 'Userinfo';
$string['module'] = 'Module';
$string['morecoursesearchresults'] = 'More than {$a} courses found, showing first {$a} results';
$string['recyclebin_desc'] = 'Note that these settings will also be used for the recycle bin.';
// Deprecated since Moodle 4.4.
$string['copycourseheading'] = 'Copy a course';
$string['backupcourse'] = 'Backup course: {$a}';
+2
View File
@@ -112,3 +112,5 @@ passwordconfirmchange,core
passwordnohelp,core
grade,core_grades
taskdeletecachetext,core_admin
copycourseheading,core_backup
backupcourse,core_backup
+5 -1
View File
@@ -199,6 +199,7 @@ $string['backupfromthissite'] = 'Backup was made on this site?';
$string['backupgradebookhistoryhelp'] = 'If enabled then gradebook history will be included in automated backups. Note that grade history must not be disabled in server settings (disablegradehistory) in order for this to work';
$string['backupincludemoduleshelp'] = 'Choose whether you want to include course modules, with or without user data, in automated backups';
$string['backupincludemoduleuserdatahelp'] = 'Choose whether you want to include module user data in automated backups.';
$string['backupinfo'] = 'Make a copy of this course, including all content and activity up to date. You can use the backup file to restore this course or to use in a different site.';
$string['backuplogdetailed'] = 'Detailed execution log';
$string['backuploglaststatus'] = 'Last execution log';
$string['backupmissinguserinfoperms'] = 'Note: This backup contains no user data. Exercise and Workshop activities will not be included in the backup, since these modules are not compatible with this type of backup.';
@@ -419,6 +420,7 @@ $string['courserequestsupport'] = 'Supporting information to help the administra
$string['courserequestwarning'] = 'The user requesting this course will be automatically enrolled and assigned the role of {$a}.';
$string['courserestore'] = 'Course restore';
$string['coursereuse'] = 'Course reuse';
$string['coursereusenavigationmenu'] = 'Course reuse navigation menu';
$string['courses'] = 'Courses';
$string['coursesectionsummaries'] = 'Course section summaries';
$string['coursesectiontitle'] = '{$a->sectionname}: {$a->sectiontitle} | {$a->course}';
@@ -1113,6 +1115,7 @@ $string['importdata'] = 'Import course data';
$string['importdataexported'] = 'Exported data from \'from\' course successfully.<br /> Continue to import into your \'to\' course.';
$string['importdatafinished'] = 'Import complete! Continue to your course';
$string['importdatafrom'] = 'Find a course to import data from:';
$string['importinfo'] = 'Import items from other courses, such as activities, blocks or calendar events. No user data will be imported.';
$string['inactive'] = 'Inactive';
$string['include'] = 'Include';
$string['includeallusers'] = 'Include all users';
@@ -1861,7 +1864,7 @@ $string['resendemail'] = 'Resend email';
$string['reset'] = 'Reset';
$string['resetcomponent'] = 'Component';
$string['resetcourse'] = 'Reset course';
$string['resetinfo'] = 'This page allows you to empty a course of user data, while retaining the activities and other settings. Please be warned that by choosing items below and submitting this page you will delete your chosen user data from this course forever!';
$string['resetinfo'] = 'Delete all user data and reset this course to its original state, keeping activities and settings intact.';
$string['resetnotimplemented'] = 'Reset not implemented';
$string['resetrecordexpired'] = 'The password reset link you used is more than {$a} minutes old and has expired. Please initiate a new password reset.';
$string['resetstartdate'] = 'Reset start date';
@@ -1894,6 +1897,7 @@ $string['restorecoursenow'] = 'Restore this course now!';
$string['restoredaccount'] = 'Restored account';
$string['restoredaccountinfo'] = 'This account was imported from another server and the password has been lost. To set a new password by email, please click "Continue"';
$string['restorefinished'] = 'Restore completed successfully';
$string['restoreinfo'] = 'Use a backup file to restore a previous version of a course, or to create a new course.';
$string['restoreto'] = 'Restore to';
$string['restoretositeadding'] = 'Warning: You are about to restore to the site home, adding data to it!';
$string['restoretositedeleting'] = 'Warning: You are about to restore to the site home, deleting data from it first!';
@@ -425,18 +425,6 @@ class secondary extends view {
}
}
// Move some nodes into a 'course reuse' node.
$overflownode = $this->get_course_overflow_nodes($rootnode);
if (!is_null($overflownode)) {
$actionnode = $this->get_first_action_for_node($overflownode);
if ($actionnode) {
// All additional nodes will be available under the 'Course reuse' page.
$text = get_string('coursereuse');
$rootnode->add($text, $actionnode->action, navigation_node::TYPE_COURSE, null, 'coursereuse',
new \pix_icon('t/edit', $text));
}
}
// Add the respective first node, provided there are other nodes included.
if (!empty($nodekeys = $rootnode->children->get_key_list())) {
$rootnode->add_node(
+78 -42
View File
@@ -4747,36 +4747,6 @@ class settings_navigation extends navigation_node {
badges_add_course_navigation($coursenode, $course);
}
// Import data from other courses.
if ($adminoptions->import) {
$url = new moodle_url('/backup/import.php', array('id' => $course->id));
$coursenode->add(get_string('import'), $url, self::TYPE_SETTING, null, 'import', new pix_icon('i/import', ''));
}
// Backup this course
if ($adminoptions->backup) {
$url = new moodle_url('/backup/backup.php', array('id'=>$course->id));
$coursenode->add(get_string('backup'), $url, self::TYPE_SETTING, null, 'backup', new pix_icon('i/backup', ''));
}
// Restore to this course
if ($adminoptions->restore) {
$url = new moodle_url('/backup/restorefile.php', array('contextid'=>$coursecontext->id));
$coursenode->add(get_string('restore'), $url, self::TYPE_SETTING, null, 'restore', new pix_icon('i/restore', ''));
}
// Copy this course.
if ($adminoptions->copy) {
$url = new moodle_url('/backup/copy.php', array('id' => $course->id));
$coursenode->add(get_string('copycourse'), $url, self::TYPE_SETTING, null, 'copy', new pix_icon('t/copy', ''));
}
// Reset this course
if ($adminoptions->reset) {
$url = new moodle_url('/course/reset.php', array('id'=>$course->id));
$coursenode->add(get_string('reset'), $url, self::TYPE_SETTING, null, 'reset', new pix_icon('i/return', ''));
}
// Questions
require_once($CFG->libdir . '/questionlib.php');
question_extend_settings_navigation($coursenode, $coursecontext)->trim_if_empty();
@@ -4828,6 +4798,56 @@ class settings_navigation extends navigation_node {
$coursenode->get('download')->set_force_into_more_menu(true);
}
// Course reuse options.
if ($adminoptions->import
|| $adminoptions->backup
|| $adminoptions->restore
|| $adminoptions->copy
|| $adminoptions->reset) {
$coursereusenav = $coursenode->add(
get_string('coursereuse'),
new moodle_url('/backup/view.php', ['id' => $course->id]),
self::TYPE_CONTAINER, null, 'coursereuse', new pix_icon('t/edit', ''),
);
// Import data from other courses.
if ($adminoptions->import) {
$url = new moodle_url('/backup/import.php', ['id' => $course->id]);
$coursereusenav->add(get_string('import'), $url, self::TYPE_SETTING, null, 'import', new pix_icon('i/import', ''));
}
// Backup this course.
if ($adminoptions->backup) {
$url = new moodle_url('/backup/backup.php', ['id' => $course->id]);
$coursereusenav->add(get_string('backup'), $url, self::TYPE_SETTING, null, 'backup', new pix_icon('i/backup', ''));
}
// Restore to this course.
if ($adminoptions->restore) {
$url = new moodle_url('/backup/restorefile.php', ['contextid' => $coursecontext->id]);
$coursereusenav->add(
get_string('restore'),
$url,
self::TYPE_SETTING,
null,
'restore',
new pix_icon('i/restore', ''),
);
}
// Copy this course.
if ($adminoptions->copy) {
$url = new moodle_url('/backup/copy.php', ['id' => $course->id]);
$coursereusenav->add(get_string('copycourse'), $url, self::TYPE_SETTING, null, 'copy', new pix_icon('t/copy', ''));
}
// Reset this course.
if ($adminoptions->reset) {
$url = new moodle_url('/course/reset.php', ['id' => $course->id]);
$coursereusenav->add(get_string('reset'), $url, self::TYPE_SETTING, null, 'reset', new pix_icon('i/return', ''));
}
}
// Return we are done
return $coursenode;
}
@@ -5721,18 +5741,6 @@ class settings_navigation extends navigation_node {
}
}
// Backup this course
if ($adminoptions->backup) {
$url = new moodle_url('/backup/backup.php', array('id'=>$course->id));
$frontpage->add(get_string('backup'), $url, self::TYPE_SETTING, null, 'backup', new pix_icon('i/backup', ''));
}
// Restore to this course
if ($adminoptions->restore) {
$url = new moodle_url('/backup/restorefile.php', array('contextid'=>$coursecontext->id));
$frontpage->add(get_string('restore'), $url, self::TYPE_SETTING, null, 'restore', new pix_icon('i/restore', ''));
}
// Questions
require_once($CFG->libdir . '/questionlib.php');
question_extend_settings_navigation($frontpage, $coursecontext)->trim_if_empty();
@@ -5752,6 +5760,34 @@ class settings_navigation extends navigation_node {
}
}
// Course reuse options.
if ($adminoptions->backup || $adminoptions->restore) {
$coursereusenav = $frontpage->add(
get_string('coursereuse'),
new moodle_url('/backup/view.php', ['id' => $course->id]),
self::TYPE_CONTAINER, null, 'coursereuse', new pix_icon('t/edit', ''),
);
// Backup this course.
if ($adminoptions->backup) {
$url = new moodle_url('/backup/backup.php', ['id' => $course->id]);
$coursereusenav->add(get_string('backup'), $url, self::TYPE_SETTING, null, 'backup', new pix_icon('i/backup', ''));
}
// Restore to this course.
if ($adminoptions->restore) {
$url = new moodle_url('/backup/restorefile.php', ['contextid' => $coursecontext->id]);
$coursereusenav->add(
get_string('restore'),
$url,
self::TYPE_SETTING,
null,
'restore',
new pix_icon('i/restore', ''),
);
}
}
return $frontpage;
}
@@ -917,7 +917,6 @@ class secondary_test extends \advanced_testcase {
$pageurl = new \moodle_url($url, [$contextidentifier => $id]);
$PAGE->set_url($pageurl);
navigation_node::override_active_url($pageurl);
$PAGE->set_course($pagecourse);
$PAGE->set_context($contextrecord);
$node = new secondary($PAGE);
@@ -941,27 +940,27 @@ class secondary_test extends \advanced_testcase {
"Backup page returns overflow" => [
'/backup/backup.php',
'id',
true
false,
],
"Restore course page returns overflow" => [
'/backup/restorefile.php',
'contextid',
true
false,
],
"Import course page returns overflow" => [
'/backup/import.php',
'id',
true
false,
],
"Course copy page returns overflow" => [
'/backup/copy.php',
'id',
true
false,
],
"Course reset page returns overflow" => [
'/course/reset.php',
'id',
true
false,
],
// The following pages should not return the overflow menu.
"Course page returns nothing" => [
+14 -10
View File
@@ -18,25 +18,29 @@ Feature: Course reuse navigation
Given I log in as "teacher1"
When I am on "Course 1" course homepage
And I navigate to "Course reuse" in current page administration
Then I should see "Find a course to import data from:"
Then I should not see "Find a course to import data from:"
And I should see "Import"
And I should see "Backup"
And I should see "Restore"
And I should not see "Copy course"
Scenario Outline: A Teacher can navigate to other Course reuse pages.
Given I log in as "teacher1"
When I am on "Course 1" course homepage
And I navigate to "Course reuse" in current page administration
And I select "<adminpage>" from the "jump" singleselect
Then I should see "<title>"
And I follow "<adminpage>"
Then I should see "<content>"
Examples:
| adminpage | title |
| Backup | Backup settings |
| Restore | Import a backup file |
| Import | Find a course to import data from: |
| Reset | Reset course |
| adminpage | content |
| Backup | Backup settings |
| Restore | Import a backup file |
| Import | Find a course to import data from: |
| Reset | Delete all user data and reset this course to its original state |
Scenario: An Administrator can view the course copy page.
Given I log in as "admin"
When I am on "Course 1" course homepage
And I navigate to "Course reuse" in current page administration
And I select "Copy course" from the "jump" singleselect
Then I should see "This course will be duplicated and put into the selected course category"
And I follow "Copy course"
Then I should see "Create a copy of this course in any course category"