MDL-75188 mod_data: Move import preset for to a modal

* Use a modal instead of a standard page to select the preset file
   and import it.
 * Change the zero state import button to a modal dialog so it uses the same
   workflow as on the preset page
This commit is contained in:
Laurent David 2022-08-22 09:55:56 +02:00 committed by Laurent David
parent 5a9a6dd090
commit d67fbbb80d
24 changed files with 469 additions and 159 deletions

10
mod/data/amd/build/importpresets.min.js vendored Normal file
View File

@ -0,0 +1,10 @@
define("mod_data/importpresets",["exports","core_form/modalform","core/notification","core/str"],(function(_exports,_modalform,_notification,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
/**
* Javascript module for importing presets.
*
* @module mod_data/importpreset
* @copyright 2022 Laurent David <laurent.david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modalform=_interopRequireDefault(_modalform),_notification=_interopRequireDefault(_notification);const selectors_importPresetButton='[data-action="importpresets"]';_exports.init=()=>{const importPresetButton=document.querySelector(selectors_importPresetButton);importPresetButton.addEventListener("click",(event=>{event.preventDefault();const modalForm=new _modalform.default({modalConfig:{title:(0,_str.get_string)("importpreset","mod_data")},formClass:"mod_data\\form\\import_presets",args:{d:importPresetButton.getAttribute("data-dataid")},saveButtonText:(0,_str.get_string)("importandapply","mod_data")});modalForm.addEventListener(modalForm.events.FORM_SUBMITTED,(event=>{event.detail.result?window.location.assign(event.detail.url):_notification.default.addNotification({type:"error",message:event.detail.errors.join("<br>")})})),modalForm.show()}))}}));
//# sourceMappingURL=importpresets.min.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"importpresets.min.js","sources":["../src/importpresets.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Javascript module for importing presets.\n *\n * @module mod_data/importpreset\n * @copyright 2022 Laurent David <laurent.david@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport Notification from 'core/notification';\nimport {get_string as getString} from 'core/str';\n\nconst selectors = {\n importPresetButton: '[data-action=\"importpresets\"]',\n};\n\n/**\n * Initialize module\n */\nexport const init = () => {\n const importPresetButton = document.querySelector(selectors.importPresetButton);\n\n importPresetButton.addEventListener('click', event => {\n event.preventDefault();\n\n const modalForm = new ModalForm({\n modalConfig: {\n title: getString('importpreset', 'mod_data'),\n },\n formClass: 'mod_data\\\\form\\\\import_presets',\n args: {d: importPresetButton.getAttribute('data-dataid')},\n saveButtonText: getString('importandapply', 'mod_data'),\n });\n\n modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, event => {\n if (event.detail.result) {\n window.location.assign(event.detail.url);\n } else {\n Notification.addNotification({\n type: 'error',\n message: event.detail.errors.join('<br>')\n });\n }\n });\n modalForm.show();\n });\n};\n"],"names":["selectors","importPresetButton","document","querySelector","addEventListener","event","preventDefault","modalForm","ModalForm","modalConfig","title","formClass","args","d","getAttribute","saveButtonText","events","FORM_SUBMITTED","detail","result","window","location","assign","url","addNotification","type","message","errors","join","show"],"mappings":";;;;;;;0LA2BMA,6BACkB,8CAMJ,WACVC,mBAAqBC,SAASC,cAAcH,8BAElDC,mBAAmBG,iBAAiB,SAASC,QACzCA,MAAMC,uBAEAC,UAAY,IAAIC,mBAAU,CAC5BC,YAAa,CACTC,OAAO,mBAAU,eAAgB,aAErCC,UAAW,iCACXC,KAAM,CAACC,EAAGZ,mBAAmBa,aAAa,gBAC1CC,gBAAgB,mBAAU,iBAAkB,cAGhDR,UAAUH,iBAAiBG,UAAUS,OAAOC,gBAAgBZ,QACpDA,MAAMa,OAAOC,OACbC,OAAOC,SAASC,OAAOjB,MAAMa,OAAOK,2BAEvBC,gBAAgB,CACzBC,KAAM,QACNC,QAASrB,MAAMa,OAAOS,OAAOC,KAAK,aAI9CrB,UAAUsB"}

View File

@ -0,0 +1,62 @@
// 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/>.
/**
* Javascript module for importing presets.
*
* @module mod_data/importpreset
* @copyright 2022 Laurent David <laurent.david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import ModalForm from 'core_form/modalform';
import Notification from 'core/notification';
import {get_string as getString} from 'core/str';
const selectors = {
importPresetButton: '[data-action="importpresets"]',
};
/**
* Initialize module
*/
export const init = () => {
const importPresetButton = document.querySelector(selectors.importPresetButton);
importPresetButton.addEventListener('click', event => {
event.preventDefault();
const modalForm = new ModalForm({
modalConfig: {
title: getString('importpreset', 'mod_data'),
},
formClass: 'mod_data\\form\\import_presets',
args: {d: importPresetButton.getAttribute('data-dataid')},
saveButtonText: getString('importandapply', 'mod_data'),
});
modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, event => {
if (event.detail.result) {
window.location.assign(event.detail.url);
} else {
Notification.addNotification({
type: 'error',
message: event.detail.errors.join('<br>')
});
}
});
modalForm.show();
});
};

View File

@ -0,0 +1,119 @@
<?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/>.
namespace mod_data\form;
use context;
use moodle_exception;
use moodle_url;
use core_form\dynamic_form;
/**
* Import presets form.
*
* @package mod_data
* @copyright 2022 Laurent David <laurent.david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class import_presets extends dynamic_form {
/**
* Process the form submission
*
* @return array
* @throws moodle_exception
*/
public function process_dynamic_submission(): array {
global $CFG;
$filepath = $this->save_temp_file('importfile');
$context = $this->get_context_for_dynamic_submission();
$cm = get_coursemodule_from_id('data', $context->instanceid);
$returnurl = new moodle_url('/mod/data/preset.php', [
'd' => $cm->instance,
'action' => 'importzip',
'filepath' => str_replace($CFG->tempdir, '', $filepath)
]);
return [
'result' => true,
'url' => $returnurl->out(false),
];
}
/**
* Get context
*
* @return context
*/
protected function get_context_for_dynamic_submission(): context {
global $DB;
$d = $this->optional_param('d', null, PARAM_INT);
$data = $DB->get_record('data', ['id' => $d], '*', MUST_EXIST);
$course = $DB->get_record('course', ['id' => $data->course], '*', MUST_EXIST);
$cm = get_coursemodule_from_instance('data', $data->id, $course->id, null, MUST_EXIST);
return \context_module::instance($cm->id);
}
/**
* Set data
*
* @return void
*/
public function set_data_for_dynamic_submission(): void {
$data = (object) [
'd' => $this->optional_param('d', 0, PARAM_INT),
];
$this->set_data($data);
}
/**
* Has access ?
*
* @return void
* @throws moodle_exception
*/
protected function check_access_for_dynamic_submission(): void {
if (!has_capability('mod/data:managetemplates', $this->get_context_for_dynamic_submission())) {
throw new moodle_exception('importpresetmissingcapability', 'data');
}
}
/**
* Get page URL
*
* @return moodle_url
*/
protected function get_page_url_for_dynamic_submission(): moodle_url {
$d = $this->optional_param('d', null, PARAM_INT);
return new moodle_url('/mod/data/preset.php', ['d' => $d]);
}
/**
* Form definition
*
* @return void
*/
protected function definition() {
$mform = $this->_form;
$mform->addElement('html', \html_writer::div(get_string('importpreset_desc', 'data'), 'py-3'));
$mform->addElement('hidden', 'd');
$mform->setType('d', PARAM_INT);
$mform->addElement('filepicker', 'importfile', get_string('choosepreset', 'data'), null,
['accepted_types' => '.zip']);
$mform->addRule('importfile', null, 'required');
}
}

View File

@ -51,7 +51,7 @@ class preset_existing_importer extends preset_importer {
throw new \coding_exception('Invalid preset provided');
}
$this->userid = $userid;
$this->userid = intval($userid);
$this->fullname = $fullname;
$cm = $manager->get_coursemodule();
$course = $cm->get_course();
@ -62,9 +62,9 @@ class preset_existing_importer extends preset_importer {
/**
* Returns user ID
*
* @return int|string userid or empty string
* @return int userid
*/
public function get_userid() {
public function get_userid(): int {
return $this->userid;
}

View File

@ -354,4 +354,48 @@ abstract class preset_importer {
public function get_preset_selector(): array {
return ['name' => 'directory', 'value' => $this->get_directory()];
}
/**
* Helper function to finish up the import routine.
*
* Called from fields and presets pages.
*
* @param bool $overwritesettings Whether to overwrite activity settings or not.
* @param stdClass $instance database instance object
* @return void
*/
public function finish_import_process(bool $overwritesettings, stdClass $instance): void {
global $DB;
$this->import($overwritesettings);
$strimportsuccess = get_string('importsuccess', 'data');
$straddentries = get_string('addentries', 'data');
$strtodatabase = get_string('todatabase', 'data');
if (!$DB->get_records('data_records', ['dataid' => $instance->id])) {
\core\notification::success("$strimportsuccess <a href='edit.php?d=$instance->id'>$straddentries</a> $strtodatabase");
} else {
\core\notification::success($strimportsuccess);
}
}
/**
* Get the right importer instance from the provided parameters (POST or GET)
*
* @param manager $manager the current database manager
* @return preset_importer the relevant preset_importer instance
* @throws \moodle_exception when the file provided as parameter (POST or GET) does not exist
*/
public static function create_from_parameters(manager $manager): preset_importer {
global $CFG;
$fullname = optional_param('fullname', '', PARAM_PATH); // Directory the preset is in.
if (!$fullname) {
$presetdir = $CFG->tempdir . '/forms/' . required_param('directory', PARAM_FILE);
if (!file_exists($presetdir) || !is_dir($presetdir)) {
throw new \moodle_exception('cannotimport');
}
$importer = new preset_upload_importer($manager, $presetdir);
} else {
$importer = new preset_existing_importer($manager, $fullname);
}
return $importer;
}
}

View File

@ -62,8 +62,11 @@ class action_bar {
global $PAGE, $DB;
$createfieldlink = new moodle_url('/mod/data/field.php', ['d' => $this->id]);
$presetslink = new moodle_url('/mod/data/preset.php', ['d' => $this->id]);
$menu = [
$createfieldlink->out(false) => get_string('managefields', 'mod_data'),
$presetslink->out(false) => get_string('usestandard', 'mod_data'),
];
$selected = $createfieldlink->out(false);
@ -226,11 +229,15 @@ class action_bar {
* @return string The HTML code for the action selector.
*/
public function get_presets_action_bar(): string {
global $PAGE;
global $PAGE, $DB;
$renderer = $PAGE->get_renderer('mod_data');
$data = $DB->get_record('data', ['id' => $this->id], '*', MUST_EXIST);
$cm = get_coursemodule_from_instance('data', $data->id, $data->course, null, MUST_EXIST);
if (!has_capability('mod/data:managetemplates', \context_module::instance($cm->id))) {
return '';
}
$presetsactionbar = new presets_action_bar($this->id);
return $renderer->render_presets_action_bar($presetsactionbar);
}

View File

@ -18,6 +18,7 @@ namespace mod_data\output;
use action_menu;
use action_menu_link_secondary;
use mod_data\manager;
use mod_data\preset;
use moodle_url;
use templatable;
@ -34,8 +35,8 @@ use stdClass;
*/
class presets implements templatable, renderable {
/** @var int $id The database module id. */
private $id;
/** @var manager $manager The database module manager. */
private $manager;
/** @var array $presets The array containing the existing presets. */
private $presets;
@ -49,13 +50,13 @@ class presets implements templatable, renderable {
/**
* The class constructor.
*
* @param int $id The database module id
* @param manager $manager The database manager
* @param array $presets The array containing the existing presets
* @param moodle_url $formactionurl The the action url for the form
* @param moodle_url $formactionurl The action url for the form
* @param bool $manage Whether the manage preset options should be displayed
*/
public function __construct(int $id, array $presets, moodle_url $formactionurl, bool $manage = false) {
$this->id = $id;
public function __construct(manager $manager, array $presets, moodle_url $formactionurl, bool $manage = false) {
$this->manager = $manager;
$this->presets = $presets;
$this->formactionurl = $formactionurl;
$this->manage = $manage;
@ -68,10 +69,9 @@ class presets implements templatable, renderable {
* @return array
*/
public function export_for_template(renderer_base $output): array {
$presets = $this->get_presets($output);
return [
'd' => $this->id,
'id' => $this->manager->get_coursemodule()->id,
'formactionurl' => $this->formactionurl->out(),
'showmanage' => $this->manage,
'presets' => $presets,
@ -101,13 +101,14 @@ class presets implements templatable, renderable {
$actions = $this->get_preset_action_menu($output, $preset, $userid);
$fullname = "{$userid}/{$preset->shortname}";
$id = $this->manager->get_instance()->id;
$previewurl = new moodle_url(
'/mod/data/preset.php',
['d' => $this->id, 'fullname' => $fullname, 'action' => 'preview']
'/mod/data/preset.php',
['d' => $id, 'fullname' => $fullname, 'action' => 'preview']
);
$presets[] = [
'id' => $this->id,
'id' => $id,
'name' => $preset->name,
'url' => $previewurl->out(),
'shortname' => $preset->shortname,
@ -134,6 +135,7 @@ class presets implements templatable, renderable {
$actions = new stdClass();
$actionmenu = null;
$id = $this->manager->get_instance()->id;
// Only presets saved by users can be edited or removed (so the datapreset plugins shouldn't display these buttons).
if ($this->manage && !$preset->isplugin) {
$actionmenu = new action_menu();
@ -146,13 +148,13 @@ class presets implements templatable, renderable {
// Edit.
if ($canmanage) {
$params = [
'd' => $this->id,
'd' => $id,
'action' => 'edit',
];
$editactionurl = new moodle_url('/mod/data/preset.php', $params);
$attributes = [
'data-action' => 'editpreset',
'data-dataid' => $this->id,
'data-dataid' => $id,
"data-presetname" => $preset->name,
"data-presetdescription" => $preset->description,
];
@ -167,7 +169,7 @@ class presets implements templatable, renderable {
// Export.
$params = [
'd' => $this->id,
'd' => $id,
'presetname' => $preset->name,
'action' => 'export',
];
@ -181,13 +183,13 @@ class presets implements templatable, renderable {
// Delete.
if ($canmanage) {
$params = [
'd' => $this->id,
'd' => $id,
'action' => 'delete',
];
$deleteactionurl = new moodle_url('/mod/data/preset.php', $params);
$attributes = [
'data-action' => 'deletepreset',
'data-dataid' => $this->id,
'data-dataid' => $id,
"data-presetname" => $preset->name,
];
$actionmenu->add(new action_menu_link_secondary(

View File

@ -49,8 +49,8 @@ class presets_action_bar implements templatable, renderable {
*/
public function export_for_template(\renderer_base $output): array {
$importpresetlink = new moodle_url('/mod/data/preset.php', ['d' => $this->id, 'action' => 'import']);
return [
'd' => $this->id,
'importpreseturl' => $importpresetlink->out(false),
];
}

View File

@ -68,7 +68,10 @@ class zero_state_action_bar implements templatable, renderable {
$params['action'] = 'import';
$importpresetlink = new moodle_url('/mod/data/preset.php', $params);
$importpresetbutton = new \single_button($importpresetlink,
get_string('importpreset', 'mod_data'), 'get', false);
get_string('importpreset', 'mod_data'), 'get', false, [
'data-action' => 'importpresets',
'data-dataid' => $instance->id
]);
$data['importpresetbutton'] = $importpresetbutton->export_for_template($output);
}

View File

@ -23,9 +23,11 @@
* @package mod_data
*/
use mod_data\manager;
use core\notification;
use mod_data\local\importer\preset_existing_importer;
use mod_data\local\importer\preset_importer;
use mod_data\local\importer\preset_upload_importer;
use mod_data\manager;
require_once('../../config.php');
require_once('lib.php');
@ -88,9 +90,6 @@ $context = $manager->get_context();
require_login($course, true, $cm);
require_capability('mod/data:managetemplates', $context);
$formimportzip = new data_import_preset_zip_form();
$formimportzip->set_data(array('d' => $data->id));
$actionbar = new \mod_data\output\action_bar($data->id, $PAGE->url);
$PAGE->add_body_class('mediumwidth');
@ -111,34 +110,11 @@ $renderer = $manager->get_renderer();
if ($action == 'finishimport' && confirm_sesskey()) {
data_print_header($course, $cm, $data, false);
$overwritesettings = optional_param('overwritesettings', false, PARAM_BOOL);
if (!$fullname) {
$presetdir = $CFG->tempdir . '/forms/' . required_param('directory', PARAM_FILE);
if (!file_exists($presetdir) || !is_dir($presetdir)) {
throw new moodle_exception('cannotimport', 'error');
}
$importer = new preset_upload_importer($manager, $presetdir);
} else {
$importer = new preset_existing_importer($manager, $fullname);
}
if ($importer->needs_mapping()) {
$importer->import($overwritesettings);
$strimportsuccess = get_string('importsuccess', 'data');
$straddentries = get_string('addentries', 'data');
$strtodatabase = get_string('todatabase', 'data');
if (!$DB->get_records('data_records', array('dataid' => $data->id))) {
echo $OUTPUT->notification("$strimportsuccess <a href='edit.php?d=$data->id'>$straddentries</a> $strtodatabase",
'notifysuccess');
} else {
echo $OUTPUT->notification("$strimportsuccess", 'notifysuccess');
}
echo $OUTPUT->continue_button(new moodle_url('/mod/data/field.php', ['d' => $data->id]));
echo $OUTPUT->footer();
exit;
}
$importer = preset_importer::create_from_parameters($manager);
$importer->finish_import_process($overwritesettings, $data);
echo $OUTPUT->continue_button(new moodle_url('/mod/data/field.php', ['d' => $data->id]));
echo $OUTPUT->footer();
exit;
}
switch ($mode) {
@ -278,13 +254,13 @@ switch ($mode) {
break;
case 'usepreset':
$importer = new preset_existing_importer($manager, $fullname);
$importer = preset_importer::create_from_parameters($manager);
if (!$importer->needs_mapping()) {
$backurl = new moodle_url('/mod/data/field.php', ['id' => $cm->id]);
if ($importer->import(false)) {
\core\notification::success(get_string('importsuccess', 'mod_data'));
notification::success(get_string('importsuccess', 'mod_data'));
} else {
\core\notification::error(get_string('presetapplied', 'mod_data'));
notification::error(get_string('presetapplied', 'mod_data'));
}
redirect($backurl);
}

View File

@ -213,10 +213,12 @@ $string['id'] = 'Entry ID';
$string['chooseexportfields'] = 'Choose the fields you wish to export';
$string['chooseexportformat'] = 'Choose the format you wish to export to';
$string['chooseorupload'] = 'Choose file';
$string['choosepreset'] = 'Preset file';
$string['expired'] = 'Sorry, this activity closed on {$a} and is no longer available';
$string['importentries'] = 'Import entries';
$string['importpreset'] = 'Import a preset';
$string['importsuccess'] = 'The preset has been successfully applied.';
$string['importpresetmissingcapability'] = 'You don\'t have permission to import a preset.';
$string['includeapproval'] = 'Include approval status';
$string['includetags'] = 'Include tags';
$string['includetime'] = 'Include time added/modified';
@ -246,6 +248,9 @@ $string['unknown'] = 'Unknown field';
$string['invalidpreset'] = '{$a} is not a preset.';
$string['invalidrecord'] = 'Incorrect record';
$string['invalidurl'] = 'The URL you just entered is not valid';
$string['importandapply'] = 'Import preset and apply';
$string['importpreset_desc'] = 'The preset will be applied to this activity, creating fields and templates.
It won\'t appear in the list of presets.';
$string['jstemplate'] = 'Javascript template';
$string['latitude'] = 'Latitude';
$string['latlong'] = 'Coordinates';

View File

@ -2625,6 +2625,7 @@ class data_preset_upload_importer extends data_preset_importer {
}
parent::__construct($course, $cm, $module, $filepath);
}
public function cleanup() {
return fulldelete($this->directory);
}

View File

@ -28,12 +28,12 @@
* @package mod_data
*/
use mod_data\local\importer\preset_importer;
use mod_data\local\importer\preset_upload_importer;
use mod_data\manager;
use mod_data\preset;
use mod_data\output\action_bar;
use mod_data\output\preset_preview;
use mod_data\local\importer\preset_upload_importer;
use mod_data\local\importer\preset_existing_importer;
require_once('../../config.php');
require_once($CFG->dirroot.'/mod/data/lib.php');
@ -57,7 +57,7 @@ if ($id) {
}
$action = optional_param('action', 'view', PARAM_ALPHA); // The page action.
$allowedactions = ['view', 'import', 'importzip', 'finishimport',
$allowedactions = ['view', 'importzip', 'finishimport',
'export', 'preview'];
if (!in_array($action, $allowedactions)) {
throw new moodle_exception('invalidaccess');
@ -113,11 +113,22 @@ if ($action === 'export') {
exit(0);
}
$formimportzip = new data_import_preset_zip_form();
$formimportzip->set_data(array('d' => $data->id));
if ($formimportzip->is_cancelled()) {
redirect(new moodle_url('/mod/data/preset.php', ['d' => $data->id]));
if ($action == 'importzip') {
$filepath = optional_param('filepath', '', PARAM_PATH);
$manager = manager::create_from_coursemodule($cm);
$importer = new preset_upload_importer($manager, $CFG->tempdir . $filepath);
if ($importer->needs_mapping()) {
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('importpreset', 'data'), 2, 'mb-4');
echo $renderer->importing_preset($data, $importer);
echo $OUTPUT->footer();
exit(0);
}
$importer->import(false);
core\notification::success(get_string('importsuccess', 'mod_data'));
redirect(new moodle_url('/mod/data/field.php', ['id' => $cm->id]));
exit(0);
}
// Preset preview injects CSS and JS to the page and should be done before the page header.
@ -142,55 +153,15 @@ if ($action === 'preview') {
exit(0);
}
if ($formdata = $formimportzip->get_data()) {
$file = new stdClass;
$file->name = $formimportzip->get_new_filename('importfile');
$file->path = $formimportzip->save_temp_file('importfile');
$importer = new preset_upload_importer($manager, $file->path);
if ($importer->needs_mapping()) {
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('importpreset', 'data'), 2, 'mb-4');
echo $renderer->importing_preset($data, $importer);
echo $OUTPUT->footer();
exit(0);
}
$importer->import(false);
redirect(new moodle_url('/mod/data/field.php', ['id' => $cm->id]));
}
echo $OUTPUT->header();
if ($action === 'finishimport') {
$fullname = optional_param('fullname', '' , PARAM_PATH); // The directory the preset is in.
// Find out preset owner userid and shortname.
$parts = explode('/', $fullname, 2);
$userid = empty($parts[0]) ? 0 : (int)$parts[0];
$shortname = empty($parts[1]) ? '' : $parts[1];
echo html_writer::start_div('overflow-hidden');
if (!confirm_sesskey()) {
throw new moodle_exception('invalidsesskey');
}
$overwritesettings = optional_param('overwritesettings', false, PARAM_BOOL);
if (!$fullname) {
$presetdir = $CFG->tempdir.'/forms/'.required_param('directory', PARAM_FILE);
if (!file_exists($presetdir) || !is_dir($presetdir)) {
throw new \moodle_exception('cannotimport');
}
$importer = new preset_upload_importer($manager, $presetdir);
} else {
$importer = new preset_existing_importer($manager, $fullname);
}
$importer->import($overwritesettings);
$strimportsuccess = get_string('importsuccess', 'data');
$straddentries = get_string('addentries', 'data');
$strtodatabase = get_string('todatabase', 'data');
if (!$DB->get_records('data_records', ['dataid' => $data->id])) {
echo $OUTPUT->notification("$strimportsuccess <a href='edit.php?d=$data->id'>$straddentries</a> $strtodatabase", 'notifysuccess');
} else {
echo $OUTPUT->notification("$strimportsuccess", 'notifysuccess');
}
$importer = preset_importer::create_from_parameters($manager);
$importer->finish_import_process($overwritesettings, $data);
echo $OUTPUT->continue_button(new moodle_url('/mod/data/preset.php', ['d' => $data->id]));
echo html_writer::end_div();
@ -198,15 +169,10 @@ if ($action === 'finishimport') {
exit(0);
}
if ($action === 'import') {
echo $OUTPUT->heading(get_string('importpreset', 'data'), 2, 'mb-4');
echo $formimportzip->display();
} else {
$actionbar = new \mod_data\output\action_bar($data->id, $url);
echo $actionbar->get_presets_action_bar();
echo $OUTPUT->heading(get_string('presets', 'data'), 2, 'mb-4');
$presets = new \mod_data\output\presets($data->id, $presets, new \moodle_url('/mod/data/field.php'), true);
echo $renderer->render_presets($presets);
}
$actionbar = new \mod_data\output\action_bar($data->id, $url);
echo $actionbar->get_presets_action_bar();
echo $OUTPUT->heading(get_string('presets', 'data'), 2, 'mb-4');
$presets = new \mod_data\output\presets($manager, $presets, new \moodle_url('/mod/data/field.php'), true);
echo $renderer->render_presets($presets);
echo $OUTPUT->footer();

View File

@ -46,7 +46,22 @@ class data_existing_preset_form extends moodleform {
}
}
/**
* Import preset class
*
*
* @package mod_data
* @deprecated since 4.1 This is deprecated since MDL-75188, please use the dynamic_form
* form (\mod_data\form\import_presets)
* @todo MDL-75189 This will be deleted in Moodle 4.5.
*/
class data_import_preset_zip_form extends moodleform {
/**
* Form definition
*
* @return void
* @throws coding_exception
*/
public function definition() {
$this->_form->addElement('header', 'uploadpreset', get_string('fromfile', 'data'));
$this->_form->addHelpButton('uploadpreset', 'fromfile', 'data');

View File

@ -63,17 +63,17 @@ class mod_data_renderer extends plugin_renderer_base {
$newfields = $params->importfields;
$currentfields = $params->currentfields;
$html = html_writer::start_tag('div', ['class'=>'presetmapping']);
$html .= html_writer::start_tag('form', ['method'=>'post', 'action'=>'']);
$html = html_writer::start_tag('div', ['class' => 'presetmapping']);
$html .= html_writer::start_tag('form', ['method' => 'post', 'action' => '']);
$html .= html_writer::start_tag('div');
$html .= html_writer::empty_tag('input', ['type'=>'hidden', 'name'=>'action', 'value'=>'finishimport']);
$html .= html_writer::empty_tag('input', ['type'=>'hidden', 'name'=>'sesskey', 'value'=>sesskey()]);
$html .= html_writer::empty_tag('input', ['type'=>'hidden', 'name'=>'d', 'value'=>$datamodule->id]);
$html .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'action', 'value' => 'finishimport']);
$html .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()]);
$html .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'd', 'value' => $datamodule->id]);
$inputselector = $importer->get_preset_selector();
$html .= html_writer::empty_tag(
'input',
['type'=>'hidden', 'name'=> $inputselector['name'], 'value' => $inputselector['value']]
'input',
['type' => 'hidden', 'name' => $inputselector['name'], 'value' => $inputselector['value']]
);
if (!empty($newfields)) {

View File

@ -18,16 +18,23 @@
Context variables required for this template:
* importpreseturl - The url to the import preset page.
* d - The database id.
Example context (json):
{
"importpreseturl": "http://www.example.com"
"importpreseturl": "http://www.example.com",
"d" : 1
}
}}
<div class="container-fluid tertiary-navigation">
<div class="row float-right">
<div class="navitem">
<a role="button" href="{{importpreseturl}}" class="btn btn-secondary">{{#str}}import, core{{/str}}</a>
<a role="button" href="{{importpreseturl}}" class="btn btn-secondary" data-action="importpresets" data-dataid="{{d}}">{{#str}}import, core{{/str}}</a>
</div>
</div>
{{#js}}
require(['mod_data/importpresets'], function(importPresetsModal) {
importPresetsModal.init();
});
{{/js}}
</div>

View File

@ -25,6 +25,7 @@
Example context (json):
{
"noitemsimgurl": "https://moodlesite/theme/image.php/boost/mod_data/1535727318/nofields",
"title": "Title",
"importpresetbutton": {
"id" : "id1",
"method" : "get",
@ -92,4 +93,9 @@
{{>core/single_button}}
{{/usepresetbutton}}
</div>
{{#js}}
require(['mod_data/importpresets'], function(importPresetsModal) {
importPresetsModal.init();
});
{{/js}}
</div>

View File

@ -301,3 +301,20 @@ Feature: Users can view and manage data presets
And I open the action menu in "Saved preset 1" "table_row"
And I should see "Export"
And following "Export" "link" in the "Saved preset 1" "table_row" should download between "1" and "5000" bytes
@javascript @_file_upload
Scenario Outline: Admins and Teachers can load a preset from a file
Given I am on the "Mountain landscapes" "data activity" page logged in as <user>
When I follow "Presets"
Then I click on "Import" "link"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
Then I click on "Import preset and apply" "button" in the ".modal-dialog" "css_element"
Then I should see "The preset has been successfully applied."
# I am on the field page.
And I should see "Manage fields"
Then I should see "The preset has been successfully applied."
Examples:
| user |
| admin |
| teacher1 |

View File

@ -26,8 +26,8 @@ Feature: Users can import presets
Given I am on the "Mountain landscapes" "data activity" page logged in as teacher1
And I follow "Presets"
And I click on "Import" "link"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Choose file" filemanager
When I click on "Save" "button"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
When I click on "Import preset and apply" "button"
Then I should not see "Field mappings"
And I should see "Image" in the "image" "table_row"
@ -38,8 +38,8 @@ Feature: Users can import presets
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
And I follow "Presets"
And I click on "Import" "link"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Choose file" filemanager
When I click on "Save" "button"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
When I click on "Import preset and apply" "button"
Then I should see "Field mappings"
And I should see "image"
And I should see "Create a new field" in the "image" "table_row"
@ -61,8 +61,8 @@ Feature: Users can import presets
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
And I follow "Presets"
And I click on "Import" "link"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Choose file" filemanager
When I click on "Save" "button"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
When I click on "Import preset and apply" "button"
Then I should see "Field mappings"
And I should see "image"
And I should see "Create a new field" in the "image" "table_row"
@ -71,8 +71,8 @@ Feature: Users can import presets
Given I am on the "Mountain landscapes" "data activity" page logged in as teacher1
And I follow "Presets"
And I click on "Import" "button"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Choose file" filemanager
When I click on "Save" "button"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
When I click on "Import preset and apply" "button"
Then I should not see "Field mappings"
And I should see "Image" in the "image" "table_row"
@ -83,8 +83,8 @@ Feature: Users can import presets
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
And I follow "Presets"
And I click on "Import" "button"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Choose file" filemanager
When I click on "Save" "button"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
When I click on "Import preset and apply" "button"
Then I should see "Field mappings"
And I should see "image"
And I should see "Create a new field" in the "image" "table_row"
@ -106,8 +106,8 @@ Feature: Users can import presets
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
And I follow "Presets"
And I click on "Import" "button"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Choose file" filemanager
When I click on "Save" "button"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
When I click on "Import preset and apply" "button"
Then I should see "Field mappings"
And I should see "image"
And I should see "Create a new field" in the "image" "table_row"
@ -115,7 +115,7 @@ Feature: Users can import presets
Scenario: Teacher can import from zero state page on an empty database
Given I am on the "Mountain landscapes" "data activity" page logged in as teacher1
And I click on "Import a preset" "button"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Choose file" filemanager
When I click on "Save" "button"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
When I click on "Import preset and apply" "button"
Then I should not see "Field mappings"
And I should see "Image" in the "image" "table_row"

View File

@ -26,8 +26,8 @@ Feature: Users can preview presets
Scenario: Preview a user preset as list view template in database
Given I follow "Presets"
And I click on "Import" "button"
And I upload "mod/data/tests/fixtures/behat_preset.zip" file to "Choose file" filemanager
And I click on "Save" "button"
And I upload "mod/data/tests/fixtures/behat_preset.zip" file to "Preset file" filemanager
When I click on "Import preset and apply" "button"
And I follow "Templates"
And I click on "Save as preset" "button"
And I set the field "Name" to "Saved preset by teacher1"
@ -72,8 +72,8 @@ Feature: Users can preview presets
Scenario: Preview a user preset as single view template in database
Given I follow "Presets"
And I click on "Import" "button"
And I upload "mod/data/tests/fixtures/behat_preset.zip" file to "Choose file" filemanager
And I click on "Save" "button"
And I upload "mod/data/tests/fixtures/behat_preset.zip" file to "Preset file" filemanager
When I click on "Import preset and apply" "button"
And I follow "Templates"
And I click on "Save as preset" "button"
And I set the field "Name" to "Saved preset by teacher1"
@ -147,8 +147,8 @@ Feature: Users can preview presets
Scenario: Apply user preset from preview in database
Given I follow "Presets"
And I click on "Import" "button"
And I upload "mod/data/tests/fixtures/behat_preset.zip" file to "Choose file" filemanager
And I click on "Save" "button"
And I upload "mod/data/tests/fixtures/behat_preset.zip" file to "Preset file" filemanager
When I click on "Import preset and apply" "button"
And I follow "Templates"
And I click on "Save as preset" "button"
And I set the field "Name" to "Saved preset by teacher1"

View File

@ -0,0 +1,71 @@
@mod @mod_data @javascript @_file_upload
Feature: Users can use predefined presets
In order to use presets
As a user
I need to select an existing preset
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "activities" exist:
| activity | name | intro | course | idnumber |
| data | Mountain landscapes | n | C1 | data1 |
And the following "mod_data > presets" exist:
| database | name | description |
| data1 | Saved preset 1 | The preset1 has description |
| data1 | Saved preset 2 | |
Scenario: Teacher can use a preset from field page on a database with fields
Given the following "mod_data > fields" exist:
| database | type | name | description |
| data1 | text | Test field name | Test field description |
Given I am on the "Mountain landscapes" "data activity" page logged in as teacher1
And I follow "Fields"
And I set the field "Fields tertiary navigation" to "Use a preset"
And I click on "fullname" "radio" in the "Image gallery" "table_row"
And the "Use a preset" "button" should be enabled
Then I click on "Use a preset" "button"
Then I should see "Field mappings"
And I should see "image"
And I should see "Create a new field" in the "image" "table_row"
Scenario: Teacher can use a preset from field page on a database with entries
And the following "mod_data > fields" exist:
| database | type | name | description |
| data1 | text | field1 | Test field description |
And the following "mod_data > templates" exist:
| database | name |
| data1 | singletemplate |
| data1 | listtemplate |
| data1 | addtemplate |
| data1 | asearchtemplate |
| data1 | rsstemplate |
And the following "mod_data > entries" exist:
| database | field1 |
| data1 | Student entry 1 |
Given I am on the "Mountain landscapes" "data activity" page logged in as teacher1
And I follow "Fields"
And I set the field "Fields tertiary navigation" to "Use a preset"
And I click on "fullname" "radio" in the "Image gallery" "table_row"
And the "Use a preset" "button" should be enabled
Then I click on "Use a preset" "button"
Then I should see "Field mappings"
And I should see "image"
And I should see "Create a new field" in the "image" "table_row"
Scenario: Teacher can use a preset from zero state page on an empty database
Given I am on the "Mountain landscapes" "data activity" page logged in as teacher1
And I click on "Use a preset" "button"
And I click on "fullname" "radio" in the "Image gallery" "table_row"
And the "Use a preset" "button" should be enabled
Then I click on "Use a preset" "button"
Then I should not see "Field mappings"
And I should see "image"
And I should see "Image" in the "image" "table_row"

View File

@ -1,4 +1,4 @@
@mod @mod_data @javascript
@mod @mod_data
Feature: Zero state page (no fields created)
Background:
@ -18,8 +18,6 @@ Feature: Zero state page (no fields created)
Scenario: Teachers see buttons to manage database when there is no field created on view page
Given I am on the "Test database name" "data activity" page logged in as "teacher1"
And "Import a preset" "button" should exist
When I click on "Import a preset" "button"
Then I should see "Import from zip file"
And I am on the "Test database name" "data activity" page
And "Create a field" "button" should exist
And I click on "Create a field" "button"
@ -30,11 +28,12 @@ Feature: Zero state page (no fields created)
And I click on "Use a preset" "button"
And I should see "Presets"
@javascript
Scenario: Teachers see buttons to manage database when there is no field created on templates page
Given I am on the "Test database name" "data activity" page logged in as "teacher1"
And "Import a preset" "button" should exist
When I click on "Import a preset" "button"
Then I should see "Import from zip file"
Then I should see "Preset file"
And I am on the "Test database name" "data activity" page
And I click on "Templates" "link"
And "Create a field" "button" should exist
@ -47,13 +46,12 @@ Feature: Zero state page (no fields created)
And I click on "Use a preset" "button"
And I should see "Presets"
Scenario: Teachers see buttons to manage database when there is no field created on fields page
@javascript @_file_upload
Scenario: Teachers can import preset from the zero state page
Given I am on the "Test database name" "data activity" page logged in as "teacher1"
And I click on "Fields" "link"
And "Import a preset" "button" should not exist
And "Use a preset" "button" should not exist
And "Create a field" "button" should exist
Then I should see "No fields yet"
And I click on "Create a field" "button"
And I click on "Short text" "link"
And I should see "Create a field"
And "Import a preset" "button" should exist
When I click on "Import a preset" "button"
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
Then I click on "Import preset and apply" "button" in the ".modal-dialog" "css_element"
And I should see "Manage fields"
Then I should see "The preset has been successfully applied."

Binary file not shown.