MDL-79915 backup: Improve the Restore main page

Júlia, from the PX team, has suggested a few improvements to make it easier to
understand the Restore main page:

- Displaying a notification instead of the empty table when there are no files
in an area.
- Improve the copy, removing the help buttons and moving this information to the
main page.
- Replacing "Import a backup file" with "Upload a backup file".
- Adding some space between the different areas.
- Displaying a different text in the different "Manage backup files" buttons.
This commit is contained in:
Sara Arjona 2023-10-27 14:47:34 +02:00
parent 6374475dc3
commit 9e3acd9f06
No known key found for this signature in database
10 changed files with 204 additions and 135 deletions

View File

@ -66,7 +66,23 @@ if ($context->contextlevel == CONTEXT_COURSECAT) {
// Set the restore course node active in the settings navigation block.
navigation_node::override_active_url(new moodle_url('/backup/restorefile.php', ['contextid' => $contextid]));
$title = get_string('managefiles', 'backup');
switch($filearea) {
case 'activity':
$title = get_string('managefiles_activity', 'backup');
break;
case 'course':
$title = get_string('managefiles_course', 'backup');
break;
case 'backup':
$title = get_string('managefiles_backup', 'backup');
break;
case 'automated':
$title = get_string('managefiles_automated', 'backup');
break;
default:
$title = get_string('managefiles', 'backup');
}
$PAGE->navbar->add($title);
$PAGE->set_title($title);
$PAGE->set_pagelayout('admin');
@ -91,7 +107,7 @@ echo $OUTPUT->header();
\backup_helper::print_coursereuse_selector('restore');
echo $OUTPUT->container_start();
echo $OUTPUT->heading($title);
echo $OUTPUT->heading($title, 2, 'mt-4');
$form->display();
echo $OUTPUT->container_end();

View File

@ -9,7 +9,7 @@ Feature: Backup and restore of the question that was tagged
@javascript @_file_upload
Scenario: Restore the quiz containing the question that was tagged
Given I am on the "Course 1" "restore" page logged in as "admin"
And I press "Manage backup files"
And I press "Manage course backups"
And I upload "backup/moodle2/tests/fixtures/test_tags_backup.mbz" file to "Files" filemanager
And I press "Save changes"
And I restore "test_tags_backup.mbz" backup into a new course using this options:

View File

@ -149,64 +149,58 @@ if (has_capability('moodle/restore:uploadfile', $context)) {
echo $OUTPUT->container_end();
}
// Activity backup area.
if ($context->contextlevel == CONTEXT_MODULE) {
echo $OUTPUT->heading_with_help(get_string('choosefilefromactivitybackup', 'backup'), 'choosefilefromuserbackup', 'backup');
echo $OUTPUT->container_start();
$treeview_options = array();
$user_context = context_user::instance($USER->id);
$treeview_options['filecontext'] = $context;
$treeview_options['currentcontext'] = $context;
$treeview_options['component'] = 'backup';
$treeview_options['context'] = $context;
$treeview_options['filearea'] = 'activity';
$treeviewoptions = [
'filecontext' => $context,
'currentcontext' => $context,
'component' => 'backup',
'context' => $context,
'filearea' => 'activity',
];
$renderer = $PAGE->get_renderer('core', 'backup');
echo $renderer->backup_files_viewer($treeview_options);
echo $OUTPUT->container_end();
echo $renderer->backup_files_viewer($treeviewoptions);
// Update the course context with the proper value, because $context contains the module context.
$coursecontext = \context_course::instance($course->id);
} else {
$coursecontext = $context;
}
echo $OUTPUT->heading_with_help(get_string('choosefilefromcoursebackup', 'backup'), 'choosefilefromcoursebackup', 'backup');
echo $OUTPUT->container_start();
$treeview_options = array();
$treeview_options['filecontext'] = $coursecontext;
$treeview_options['currentcontext'] = $context;
$treeview_options['component'] = 'backup';
$treeview_options['context'] = $context;
$treeview_options['filearea'] = 'course';
// Course backup area.
$treeviewoptions = [
'filecontext' => $coursecontext,
'currentcontext' => $context,
'component' => 'backup',
'context' => $context,
'filearea' => 'course',
];
$renderer = $PAGE->get_renderer('core', 'backup');
echo $renderer->backup_files_viewer($treeview_options);
echo $OUTPUT->container_end();
echo $renderer->backup_files_viewer($treeviewoptions);
echo $OUTPUT->heading_with_help(get_string('choosefilefromuserbackup', 'backup'), 'choosefilefromuserbackup', 'backup');
echo $OUTPUT->container_start();
$treeview_options = array();
$user_context = context_user::instance($USER->id);
$treeview_options['filecontext'] = $user_context;
$treeview_options['currentcontext'] = $context;
$treeview_options['component'] = 'user';
$treeview_options['context'] = 'backup';
$treeview_options['filearea'] = 'backup';
// Private backup area.
$usercontext = context_user::instance($USER->id);
$treeviewoptions = [
'filecontext' => $usercontext,
'currentcontext' => $context,
'component' => 'user',
'context' => 'backup',
'filearea' => 'backup',
];
$renderer = $PAGE->get_renderer('core', 'backup');
echo $renderer->backup_files_viewer($treeview_options);
echo $OUTPUT->container_end();
echo $renderer->backup_files_viewer($treeviewoptions);
// Automated backup area.
$automatedbackups = get_config('backup', 'backup_auto_active');
if (!empty($automatedbackups)) {
echo $OUTPUT->heading_with_help(get_string('choosefilefromautomatedbackup', 'backup'), 'choosefilefromautomatedbackup', 'backup');
echo $OUTPUT->container_start();
$treeview_options = array();
$user_context = context_user::instance($USER->id);
$treeview_options['filecontext'] = $context;
$treeview_options['currentcontext'] = $context;
$treeview_options['component'] = 'backup';
$treeview_options['context'] = $context;
$treeview_options['filearea'] = 'automated';
$treeviewoptions = [
'filecontext' => $context,
'currentcontext' => $context,
'component' => 'backup',
'context' => $context,
'filearea' => 'automated',
];
$renderer = $PAGE->get_renderer('core', 'backup');
echo $renderer->backup_files_viewer($treeview_options);
echo $OUTPUT->container_end();
echo $renderer->backup_files_viewer($treeviewoptions);
}
// In progress course restores.

View File

@ -29,7 +29,7 @@ class course_restore_form extends moodleform {
$contextid = $this->_customdata['contextid'];
$mform->addElement('hidden', 'contextid', $contextid);
$mform->setType('contextid', PARAM_INT);
$mform->addElement('filepicker', 'backupfile', get_string('files'));
$mform->addElement('filepicker', 'backupfile', get_string('backupfile', 'backup'));
$mform->addRule('backupfile', get_string('required'), 'required');
$submit_string = get_string('restore');
$this->add_action_buttons(false, $submit_string);

View File

@ -621,91 +621,140 @@ class core_backup_renderer extends plugin_renderer_base {
public function render_backup_files_viewer(backup_files_viewer $viewer) {
$files = $viewer->files;
$filestodisplay = false;
foreach ($files as $file) {
if (!$file->is_directory()) {
$filestodisplay = true;
break;
}
}
$async = \async_helper::is_async_enabled();
$tablehead = array(
switch($viewer->filearea) {
case 'activity':
$title = get_string('choosefilefromactivitybackup', 'backup');
$description = get_string('choosefilefromactivitybackup_help', 'backup');
$button = get_string('managefiles_activity', 'backup');
$nofilesstring = get_string('restorenofilesbackuparea_activity', 'backup');
break;
case 'course':
$title = get_string('choosefilefromcoursebackup', 'backup');
$description = get_string('choosefilefromcoursebackup_help', 'backup');
$button = get_string('managefiles_course', 'backup');
$nofilesstring = get_string('restorenofilesbackuparea_course', 'backup');
break;
case 'backup':
$title = get_string('choosefilefromuserbackup', 'backup');
$description = get_string('choosefilefromuserbackup_help', 'backup');
$button = get_string('managefiles_backup', 'backup');
$nofilesstring = get_string('restorenofilesbackuparea_backup', 'backup');
break;
case 'automated':
$title = get_string('choosefilefromautomatedbackup', 'backup');
$description = get_string('choosefilefromautomatedbackup_help', 'backup');
$button = get_string('managefiles_automated', 'backup');
$nofilesstring = get_string('restorenofilesbackuparea_automated', 'backup');
break;
default:
$title = '';
$description = '';
$button = get_string('managefiles', 'backup');
$nofilesstring = get_string('restorenofilesbackuparea', 'backup');
}
$html = html_writer::tag('h3', $title, ['class' => 'mt-6']);
$html .= html_writer::tag('div', $description, ['class' => 'mb-3']);
if ($filestodisplay || $async) {
$tablehead = [
get_string('filename', 'backup'),
get_string('time'),
get_string('size'),
get_string('download'),
get_string('restore'));
if ($async) {
$tablehead[] = get_string('status', 'backup');
}
$table = new html_table();
$table->attributes['class'] = 'backup-files-table generaltable';
$table->head = $tablehead;
$table->width = '100%';
$table->data = [];
// First add in progress asynchronous backups.
// Only if asynchronous backups are enabled.
if ($async) {
$tabledata = [];
$backups = \async_helper::get_async_backups($viewer->filearea, $viewer->filecontext->instanceid);
// For each backup get, new item name, time restore created and progress.
foreach ($backups as $backup) {
$status = $this->get_status_display($backup->status, $backup->backupid);
$timecreated = $backup->timecreated;
$tablerow = [$backup->filename, userdate($timecreated), '-', '-', '-', $status];
$tabledata[] = $tablerow;
}
$table->data = $tabledata;
}
// Add completed backups.
foreach ($files as $file) {
if ($file->is_directory()) {
continue;
}
$fileurl = moodle_url::make_pluginfile_url(
$file->get_contextid(),
$file->get_component(),
$file->get_filearea(),
null,
$file->get_filepath(),
$file->get_filename(),
true
);
$params = array();
$params['action'] = 'choosebackupfile';
$params['filename'] = $file->get_filename();
$params['filepath'] = $file->get_filepath();
$params['component'] = $file->get_component();
$params['filearea'] = $file->get_filearea();
$params['filecontextid'] = $file->get_contextid();
$params['contextid'] = $viewer->currentcontext->id;
$params['itemid'] = $file->get_itemid();
$restoreurl = new moodle_url('/backup/restorefile.php', $params);
$restorelink = html_writer::link($restoreurl, get_string('restore'));
$downloadlink = html_writer::link($fileurl, get_string('download'));
// Conditional display of the restore and download links, initially only for the 'automated' filearea.
if ($params['filearea'] == 'automated') {
if (!has_capability('moodle/restore:viewautomatedfilearea', $viewer->currentcontext)) {
$restorelink = '';
}
if (!can_download_from_backup_filearea($params['filearea'], $viewer->currentcontext)) {
$downloadlink = '';
}
}
$tabledata = array(
$file->get_filename(),
userdate ($file->get_timemodified()),
display_size ($file->get_filesize()),
$downloadlink,
$restorelink
);
get_string('restore'),
];
if ($async) {
$tabledata[] = $this->get_status_display(backup::STATUS_FINISHED_OK, null);
$tablehead[] = get_string('status', 'backup');
}
$table->data[] = $tabledata;
}
$table = new html_table();
$table->attributes['class'] = 'backup-files-table generaltable';
$table->head = $tablehead;
$table->width = '100%';
$table->data = [];
$html = html_writer::table($table);
// First add in progress asynchronous backups.
// Only if asynchronous backups are enabled.
if ($async) {
$tabledata = [];
$backups = \async_helper::get_async_backups($viewer->filearea, $viewer->filecontext->instanceid);
// For each backup get, new item name, time restore created and progress.
foreach ($backups as $backup) {
$status = $this->get_status_display($backup->status, $backup->backupid);
$timecreated = $backup->timecreated;
$tablerow = [$backup->filename, userdate($timecreated), '-', '-', '-', $status];
$tabledata[] = $tablerow;
}
$table->data = $tabledata;
}
// Add completed backups.
foreach ($files as $file) {
if ($file->is_directory()) {
continue;
}
$fileurl = moodle_url::make_pluginfile_url(
$file->get_contextid(),
$file->get_component(),
$file->get_filearea(),
null,
$file->get_filepath(),
$file->get_filename(),
true
);
$params = [];
$params['action'] = 'choosebackupfile';
$params['filename'] = $file->get_filename();
$params['filepath'] = $file->get_filepath();
$params['component'] = $file->get_component();
$params['filearea'] = $file->get_filearea();
$params['filecontextid'] = $file->get_contextid();
$params['contextid'] = $viewer->currentcontext->id;
$params['itemid'] = $file->get_itemid();
$restoreurl = new moodle_url('/backup/restorefile.php', $params);
$restorelink = html_writer::link($restoreurl, get_string('restore'));
$downloadlink = html_writer::link($fileurl, get_string('download'));
// Conditional display of the restore and download links, initially only for the 'automated' filearea.
if ($params['filearea'] == 'automated') {
if (!has_capability('moodle/restore:viewautomatedfilearea', $viewer->currentcontext)) {
$restorelink = '';
}
if (!can_download_from_backup_filearea($params['filearea'], $viewer->currentcontext)) {
$downloadlink = '';
}
}
$tabledata = [
$file->get_filename(),
userdate ($file->get_timemodified()),
display_size ($file->get_filesize()),
$downloadlink,
$restorelink,
];
if ($async) {
$tabledata[] = $this->get_status_display(backup::STATUS_FINISHED_OK, null);
}
$table->data[] = $tabledata;
}
$html .= html_writer::table($table);
} else {
// There are no files to display.
$html .= $this->notification($nofilesstring, 'notifymessage');
}
// For automated backups, the ability to manage backup files is controlled by the ability to download them.
// All files must be from the same file area in a backup_files_viewer.
@ -725,7 +774,7 @@ class core_backup_renderer extends plugin_renderer_base {
'component' => $viewer->component,
'returnurl' => $this->page->url->out())
),
get_string('managefiles', 'backup'),
$button,
'post'
);
}

View File

@ -32,7 +32,7 @@ Feature: Backup and restore the activity with the completion
@javascript @_file_upload
Scenario: Restore the legacy assignment with completion condition.
Given I am on the "Course 1" "restore" page logged in as "admin"
And I press "Manage backup files"
And I press "Manage course backups"
And I upload "completion/tests/fixtures/legacy_course_completion.mbz" file to "Files" filemanager
And I press "Save changes"
And I restore "legacy_course_completion.mbz" backup into a new course using this options:

View File

@ -216,21 +216,21 @@ Feature: Course category breadcrumbs navigation
And I should see "Cat 1" in the ".breadcrumb" "css_element"
And I should see "Restore course" in the ".breadcrumb" "css_element"
And I should see "Cat 1" in the ".page-context-header" "css_element"
And I should see "Import a backup file" in the "region-main" "region"
And I should see "Upload a backup file" in the "region-main" "region"
And I should see "Cat 1" in the ".block_navigation .active_tree_node" "css_element"
Scenario: Admin user navigates to category 'manage backup files' page
Scenario: Admin user navigates to category Manage course backups page
Given I log in as "admin"
And I navigate to "Courses > Manage courses and categories" in site administration
And I follow "Cat 1"
And I navigate to "Restore course" in current page administration
When I press "Manage backup files"
When I press "Manage course backups"
Then I should see "Courses" in the ".breadcrumb" "css_element"
And I should see "Cat 1" in the ".breadcrumb" "css_element"
And I should see "Restore course" in the ".breadcrumb" "css_element"
And I should see "Manage backup files" in the ".breadcrumb" "css_element"
And I should see "Manage course backups" in the ".breadcrumb" "css_element"
And I should see "Cat 1" in the ".page-context-header" "css_element"
And I should see "Manage backup files" in the "region-main" "region"
And I should see "Manage course backups" in the "region-main" "region"
And I should see "Cat 1" in the ".block_navigation .active_tree_node" "css_element"
Scenario: Admin user navigates to category 'content bank' page

View File

@ -77,6 +77,7 @@ $string['backupcoursesections'] = 'Course sections';
$string['backupdate'] = 'Date taken';
$string['backupdetails'] = 'Backup details';
$string['backupdetailsnonstandardinfo'] = 'The selected file is not a standard Moodle backup file. The restore process will try to convert the backup file into the standard format and then restore it.';
$string['backupfile'] = 'Backup file';
$string['backupformat'] = 'Format';
$string['backupformatmoodle1'] = 'Moodle 1';
$string['backupformatmoodle2'] = 'Moodle 2';
@ -108,13 +109,13 @@ $string['backuptypesection'] = 'Section';
$string['backupversion'] = 'Backup version';
$string['cannotfindassignablerole'] = 'The {$a} role in the backup file cannot be mapped to any of the roles that you are allowed to assign.';
$string['choosefilefromcoursebackup'] = 'Course backup area';
$string['choosefilefromcoursebackup_help'] = 'Course backups made using default settings are stored here.';
$string['choosefilefromcoursebackup_help'] = 'Backup files for this course.';
$string['choosefilefromuserbackup'] = 'User private backup area';
$string['choosefilefromuserbackup_help'] = 'Backup files with anonymized user information are stored here.';
$string['choosefilefromuserbackup_help'] = 'Private backup files for all courses, with anonymised user information.';
$string['choosefilefromactivitybackup'] = 'Activity backup area';
$string['choosefilefromactivitybackup_help'] = 'Activity backups made using default settings are stored here.';
$string['choosefilefromactivitybackup_help'] = 'Backup files for this activity.';
$string['choosefilefromautomatedbackup'] = 'Automated backups';
$string['choosefilefromautomatedbackup_help'] = 'Contains automatically generated backups.';
$string['choosefilefromautomatedbackup_help'] = 'Backup files automatically generated.';
$string['config_keep_groups_and_groupings'] = 'By default keep current groups and groupings.';
$string['config_keep_roles_and_enrolments'] = 'By default keep current roles and enrolments.';
$string['config_overwrite_conf'] = 'Allows user to overwrite the current course configuration';
@ -252,7 +253,7 @@ $string['importgeneralmaxresults'] = 'Maximum number of courses listed for impor
$string['importgeneralmaxresults_desc'] = 'This controls the number of courses that are listed during the first step of the import process';
$string['importgeneralduplicateadminallowed'] = 'Allow admin conflict resolution';
$string['importgeneralduplicateadminallowed_desc'] = 'If the site has an account with username \'admin\', then attempting to restore a backup file containing an account with username \'admin\' can cause a conflict. If this setting is enabled, the conflict will be resolved by changing the username in the backup file to \'admin_xyz\'.';
$string['importfile'] = 'Import a backup file';
$string['importfile'] = 'Upload a backup file';
$string['importbackupstage1action'] = 'Next';
$string['importbackupstage2action'] = 'Next';
$string['importbackupstage4action'] = 'Perform import';
@ -283,6 +284,10 @@ $string['lockedbyconfig'] = 'This setting has been locked by the default backup
$string['lockedbyhierarchy'] = 'Locked by dependencies';
$string['loglifetime'] = 'Keep logs for';
$string['managefiles'] = 'Manage backup files';
$string['managefiles_activity'] = 'Manage activity backups';
$string['managefiles_course'] = 'Manage course backups';
$string['managefiles_backup'] = 'Manage private backups';
$string['managefiles_automated'] = 'Manage automated backups';
$string['keptroles'] = 'Include role enrolments';
$string['keptroles_help'] = 'Users with the selected roles will be enrolled into the new course. No user data will be copied unless \'Include user data\' is enabled.';
$string['missingfilesinpool'] = 'Some files could not be saved during the backup, and so it will not be possible to restore them.';
@ -320,6 +325,11 @@ $string['restorefileweremissing'] = 'Some files could not be restored because th
$string['restorenewcoursefullname'] = 'New course name';
$string['restorenewcourseshortname'] = 'New course short name';
$string['restorenewcoursestartdate'] = 'New start date';
$string['restorenofilesbackuparea'] = 'There are no backup files yet.';
$string['restorenofilesbackuparea_activity'] = 'There are no backup files for this activity yet.';
$string['restorenofilesbackuparea_course'] = 'There are no backup files for this course yet.';
$string['restorenofilesbackuparea_backup'] = 'You have no private backup files yet.';
$string['restorenofilesbackuparea_automated'] = 'There are no automated backup files yet.';
$string['restorerootsettings'] = 'Restore settings';
$string['restoresection'] = 'Restore section';
$string['restorestage1'] = 'Confirm';

View File

@ -67,7 +67,7 @@ Feature: Backup and restore of quizzes
@javascript @_file_upload
Scenario: Restore a Moodle 2.8 quiz backup
When I am on the "Course 1" "restore" page
And I press "Manage backup files"
And I press "Manage course backups"
And I upload "mod/quiz/tests/fixtures/moodle_28_quiz.mbz" file to "Files" filemanager
And I press "Save changes"
And I restore "moodle_28_quiz.mbz" backup into "Course 1" course using this options:

View File

@ -34,7 +34,7 @@ Feature: Course reuse navigation
Examples:
| adminpage | content |
| Backup | Backup settings |
| Restore | Import a backup file |
| Restore | Upload a backup file |
| Import | Find a course to import data from: |
| Reset | Delete all user data and reset this course to its original state |