MDL-75289 mod_data: Implement prototyped tertiary nav

On the Database page:
- The List/single view is displayed in the right.
- The buttons Import entries, export entries and Export to portfolio
have been moved to the Actions menu.
- The List/Single view headings have been removed.
- The "Save settings" secondary button is hidden when advanced search
is enabled.
- The result (Found X out of Y entries, No records found) are not
displayed as notifications anymore.

On the Presets page:
- The buttons (Import, Export and Save as preset) have been moved to an
actions menu to the tertiary navigation. Some of these options have been
renamed.
- Remove the Action column heading from the table.

On the Presets preview page:
- Move the preset name to the heading in the tertiary navigation (Preview
of xxxxx), and remove the current preset name from the page.
- Align the List/single template to the right in the tertiary navigation.
- Make primary the "Use this preset" button.

On the Fields page:
- Remove the "Manage fields" menu.
- Remove the Export and Save as preset from the tertiary navigation.
- Align Create a field to the right in the tertiary navigation.
- Add a description at the top of the page.
- Remove the Action column heading from the table.
- Move field actions (Edit and Delete) to ellipsis.

On the Templates page:
- Move Export and Save as preset to the Actions menu.
- Move the templates list to a tertiary navigation selector and remove
the template heading.
- Reorder the templates list (Add entry template should be displayed
at the begining, instead of List template).
- Rename "Enable editor" to "Enable code editor".
This commit is contained in:
Sara Arjona 2022-10-05 17:03:23 +02:00
parent 53c4fc9af0
commit 61e8b806ec
40 changed files with 805 additions and 501 deletions

View File

@ -314,6 +314,25 @@ class manager {
return has_capability('mod/data:managetemplates', $this->context, $userid);
}
/** Check if the user can export entries on the current context.
*
* @param int $userid the user id to check ($USER->id if null).
* @return bool if the user can export entries on current context.
*/
public function can_export_entries(?int $userid = null): bool {
global $USER, $DB;
if (!$userid) {
$userid = $USER->id;
}
// Exportallentries and exportentry are basically the same capability.
return has_capability('mod/data:exportallentries', $this->context) ||
has_capability('mod/data:exportentry', $this->context) ||
(has_capability('mod/data:exportownentry', $this->context) &&
$DB->record_exists('data_records', ['userid' => $userid, 'dataid' => $this->instance->id]));
}
/**
* Update the database templates.
*

View File

@ -17,6 +17,7 @@
namespace mod_data\output;
use mod_data\manager;
use mod_data\preset;
use moodle_url;
use url_select;
@ -55,57 +56,28 @@ class action_bar {
* Generate the output for the action bar in the field page.
*
* @param bool $hasfieldselect Whether the field selector element should be rendered.
* @param bool $hassaveaspreset Whether the save as preset button element should be rendered.
* @param bool $hasexportpreset Whether the export as preset button element should be rendered.
* @param null $unused1 This parameter has been deprecated since 4.1 and should not be used anymore.
* @param null $unused2 This parameter has been deprecated since 4.1 and should not be used anymore.
* @return string The HTML code for the action bar.
*/
public function get_fields_action_bar(
bool $hasfieldselect = false,
bool $hassaveaspreset = false,
bool $hasexportpreset = false
?bool $unused1 = null,
?bool $unused2 = null
): string {
global $PAGE, $DB;
global $PAGE;
$createfieldlink = new moodle_url('/mod/data/field.php', ['id' => $this->cmid]);
$presetslink = new moodle_url('/mod/data/preset.php', ['id' => $this->cmid]);
$menu = [
$createfieldlink->out(false) => get_string('managefields', 'mod_data'),
$presetslink->out(false) => get_string('usestandard', 'mod_data'),
];
$selected = $createfieldlink->out(false);
$urlselect = new url_select($menu, $selected, null, 'fieldactionselect');
$urlselect->set_label(get_string('fieldsnavigation', 'mod_data'), ['class' => 'sr-only']);
if ($unused1 !== null || $unused2 !== null) {
debugging('Deprecated argument passed to get_fields_action_bar method', DEBUG_DEVELOPER);
}
$fieldselect = null;
if ($hasfieldselect) {
$fieldselect = $this->get_create_fields();
}
$saveaspresetbutton = null;
$exportpresetbutton = null;
$hasfields = $DB->record_exists('data_fields', ['dataid' => $this->id]);
if ($hasfields) {
if ($hassaveaspreset) {
$saveaspresetlink = new moodle_url('/mod/data/preset.php',
['d' => $this->id, 'action' => 'export']);
$saveaspresetbutton = new \single_button($saveaspresetlink,
get_string('saveaspreset', 'mod_data'), 'post', false);
}
if ($hasexportpreset) {
$exportpresetlink = new moodle_url('/mod/data/preset.php',
['d' => $this->id, 'action' => 'export']);
$exportpresetbutton = new \single_button($exportpresetlink,
get_string('exportpreset', 'mod_data'), 'get', false);
}
}
$renderer = $PAGE->get_renderer('mod_data');
$fieldsactionbar = new fields_action_bar($this->id, $urlselect, null, $saveaspresetbutton,
$exportpresetbutton, $fieldselect);
$fieldsactionbar = new fields_action_bar($this->id, null, null, null, null, $fieldselect);
return $renderer->render_fields_action_bar($fieldsactionbar);
}
@ -130,7 +102,7 @@ class action_bar {
foreach ($menufield as $fieldtype => $fieldname) {
$fieldselectparams['newtype'] = $fieldtype;
$fieldselect->add(new \action_menu_link(
new \moodle_url('/mod/data/field.php', $fieldselectparams),
new moodle_url('/mod/data/field.php', $fieldselectparams),
new \pix_icon('field/' . $fieldtype, $fieldname, 'data'),
$fieldname,
false
@ -145,9 +117,10 @@ class action_bar {
* Generate the output for the action selector in the view page.
*
* @param bool $hasentries Whether entries exist.
* @param string $mode The current view mode (list, view...).
* @return string The HTML code for the action selector.
*/
public function get_view_action_bar(bool $hasentries): string {
public function get_view_action_bar(bool $hasentries, string $mode): string {
global $PAGE;
$viewlistlink = new moodle_url('/mod/data/view.php', ['d' => $this->id]);
@ -167,7 +140,7 @@ class action_bar {
$urlselect = new url_select($menu, $activeurl->out(false), null, 'viewactionselect');
$urlselect->set_label(get_string('viewnavigation', 'mod_data'), ['class' => 'sr-only']);
$renderer = $PAGE->get_renderer('mod_data');
$viewactionbar = new view_action_bar($this->id, $urlselect, $hasentries);
$viewactionbar = new view_action_bar($this->id, $urlselect, $hasentries, $mode);
return $renderer->render_view_action_bar($viewactionbar);
}
@ -178,7 +151,7 @@ class action_bar {
* @return string The HTML code for the action selector.
*/
public function get_templates_action_bar(): string {
global $PAGE, $DB;
global $PAGE;
$listtemplatelink = new moodle_url('/mod/data/templates.php', ['d' => $this->id,
'mode' => 'listtemplate']);
@ -192,38 +165,21 @@ class action_bar {
$jstemplatelink = new moodle_url('/mod/data/templates.php', ['d' => $this->id, 'mode' => 'jstemplate']);
$menu = [
$listtemplatelink->out(false) => get_string('listtemplate', 'mod_data'),
$singletemplatelink->out(false) => get_string('singletemplate', 'mod_data'),
$advancedsearchtemplatelink->out(false) => get_string('asearchtemplate', 'mod_data'),
$addtemplatelink->out(false) => get_string('addtemplate', 'mod_data'),
$rsstemplatelink->out(false) => get_string('rsstemplate', 'mod_data'),
$singletemplatelink->out(false) => get_string('singletemplate', 'mod_data'),
$listtemplatelink->out(false) => get_string('listtemplate', 'mod_data'),
$advancedsearchtemplatelink->out(false) => get_string('asearchtemplate', 'mod_data'),
$csstemplatelink->out(false) => get_string('csstemplate', 'mod_data'),
$jstemplatelink->out(false) => get_string('jstemplate', 'mod_data'),
$rsstemplatelink->out(false) => get_string('rsstemplate', 'mod_data'),
];
$urlselect = new url_select($menu, $this->currenturl->out(false), null, 'templatesactionselect');
$urlselect->set_label(get_string('templatesnavigation', 'mod_data'), ['class' => 'sr-only']);
$hasfields = $DB->record_exists('data_fields', ['dataid' => $this->id]);
$saveaspresetbutton = null;
$exportpresetbutton = null;
if ($hasfields) {
$saveaspresetlink = new moodle_url('/mod/data/preset.php',
['d' => $this->id, 'action' => 'export']);
$saveaspresetbutton = new \single_button($saveaspresetlink,
get_string('saveaspreset', 'mod_data'), 'post', false);
$exportpresetlink = new moodle_url('/mod/data/preset.php',
['d' => $this->id, 'action' => 'export', 'sesskey' => sesskey()]);
$exportpresetbutton = new \single_button($exportpresetlink,
get_string('exportpreset', 'mod_data'), 'get', false);
}
$selectmenu = new \core\output\select_menu('presetsactions', $menu, $this->currenturl->out(false));
$selectmenu->set_label(get_string('templatesnavigation', 'mod_data'), ['class' => 'sr-only']);
$renderer = $PAGE->get_renderer('mod_data');
$templatesactionbar = new templates_action_bar($this->id, $urlselect, $saveaspresetbutton,
$exportpresetbutton);
$presetsactions = $this->get_presets_actions_select(false);
$templatesactionbar = new templates_action_bar($this->id, $selectmenu, null, null, $presetsactions);
return $renderer->render_templates_action_bar($templatesactionbar);
}
@ -237,10 +193,8 @@ class action_bar {
global $PAGE;
$renderer = $PAGE->get_renderer('mod_data');
if (!has_capability('mod/data:managetemplates', \context_module::instance($this->cmid))) {
return '';
}
$presetsactionbar = new presets_action_bar($this->cmid);
$presetsactionbar = new presets_action_bar($this->cmid, $this->get_presets_actions_select(true));
return $renderer->render_presets_action_bar($presetsactionbar);
}
@ -277,7 +231,7 @@ class action_bar {
$urlselect->set_label(get_string('templatesnavigation', manager::PLUGINNAME), ['class' => 'sr-only']);
$data = [
'title' => get_string('preview', manager::PLUGINNAME),
'title' => get_string('preview', manager::PLUGINNAME, preset::get_name_from_plugin($fullname)),
'hasback' => true,
'backtitle' => get_string('back'),
'backurl' => new moodle_url('/mod/data/preset.php', ['id' => $cm->id]),
@ -285,4 +239,59 @@ class action_bar {
];
return $renderer->render_from_template('mod_data/action_bar', $data);
}
/**
* Helper method to get the selector for the presets action.
*
* @param bool $hasimport Whether the Import buttons must be included or not.
* @return \action_menu|null The selector object used to display the presets actions. Null when the import button is not
* displayed and the database hasn't any fields.
*/
protected function get_presets_actions_select(bool $hasimport = false): ?\action_menu {
global $DB;
$hasfields = $DB->record_exists('data_fields', ['dataid' => $this->id]);
// Early return if the database has no fields and the import action won't be displayed.
if (!$hasfields && !$hasimport) {
return null;
}
$actionsselect = new \action_menu();
$actionsselect->set_menu_trigger(get_string('actions'), 'btn btn-secondary');
if ($hasimport) {
// Import.
$actionsselectparams = ['id' => $this->cmid, 'action' => 'import'];
$actionsselect->add(new \action_menu_link(
new moodle_url('/mod/data/preset.php', $actionsselectparams),
null,
get_string('importpreset', 'mod_data'),
false,
['data-action' => 'importpresets', 'data-dataid' => $this->cmid]
));
}
// If the database has no fields, export and save as preset options shouldn't be displayed.
if ($hasfields) {
// Export.
$actionsselectparams = ['id' => $this->cmid, 'action' => 'export'];
$actionsselect->add(new \action_menu_link(
new moodle_url('/mod/data/preset.php', $actionsselectparams),
null,
get_string('exportpreset', 'mod_data'),
false
));
// Save as preset.
$actionsselect->add(new \action_menu_link(
new moodle_url('/mod/data/preset.php', $actionsselectparams),
null,
get_string('saveaspreset', 'mod_data'),
false,
['data-action' => 'saveaspreset', 'data-dataid' => $this->id]
));
}
return $actionsselect;
}
}

View File

@ -31,41 +31,29 @@ class fields_action_bar implements templatable, renderable {
/** @var int $id The database module id. */
private $id;
/** @var \url_select $urlselect The URL selector object. */
private $urlselect;
/** @var \single_select|null $fieldselect The field selector object or null. */
/** @var \action_menu|null $fieldselect The field selector object or null. */
private $fieldselect;
/** @var \single_button|null $saveaspresetbutton The save as preset single button object or null. */
private $saveaspresetbutton;
/** @var \single_button|null $exportpresetbutton The export preset single button object or null. */
private $exportpresetbutton;
/**
* The class constructor.
*
* @param int $id The database module id
* @param \url_select $urlselect The URL selector object
* @param null $unused This parameter has been deprecated since 4.0 and should not be used anymore.
* @param \single_button|null $saveaspresetbutton The save as preset single button object or null
* @param \single_button|null $exportpresetbutton The export preset single button object or null
* @param null $unused1 This parameter has been deprecated since 4.1 and should not be used anymore.
* @param null $unused2 This parameter has been deprecated since 4.1 and should not be used anymore.
* @param null $unused3 This parameter has been deprecated since 4.1 and should not be used anymore.
* @param null $unused4 This parameter has been deprecated since 4.1 and should not be used anymore.
* @param \action_menu|null $fieldselect The field selector object or null
*/
public function __construct(int $id, \url_select $urlselect, $unused = null,
?\single_button $saveaspresetbutton = null, ?\single_button $exportpresetbutton = null,
public function __construct(int $id, $unused1 = null, $unused2 = null,
$unused3 = null, $unused4 = null,
?\action_menu $fieldselect = null) {
if ($unused !== null) {
if ($unused1 !== null || $unused2 !== null || $unused3 !== null || $unused4 !== null) {
debugging('Deprecated argument passed to fields_action_bar constructor', DEBUG_DEVELOPER);
}
$this->id = $id;
$this->urlselect = $urlselect;
$this->fieldselect = $fieldselect;
$this->saveaspresetbutton = $saveaspresetbutton;
$this->exportpresetbutton = $exportpresetbutton;
}
/**
@ -78,19 +66,12 @@ class fields_action_bar implements templatable, renderable {
$data = [
'd' => $this->id,
'urlselect' => $this->urlselect->export_for_template($output),
];
if ($this->fieldselect) {
$data['fieldselect'] = $this->fieldselect->export_for_template($output);
}
$data['saveaspreset'] = $this->saveaspresetbutton;
if ($this->exportpresetbutton) {
$data['exportpreset'] = $this->exportpresetbutton->export_for_template($output);
}
return $data;
}
}

View File

@ -100,7 +100,7 @@ class presets implements templatable, renderable {
}
$actions = $this->get_preset_action_menu($output, $preset, $userid);
$fullname = "{$userid}/{$preset->shortname}";
$fullname = $preset->get_fullname();
$id = $this->manager->get_instance()->id;
$previewurl = new moodle_url(
'/mod/data/preset.php',

View File

@ -16,7 +16,6 @@
namespace mod_data\output;
use moodle_url;
use templatable;
use renderable;
@ -32,13 +31,18 @@ class presets_action_bar implements templatable, renderable {
/** @var int $id The database module id. */
private $cmid;
/** @var \action_menu $actionsselect The presets actions selector object. */
private $actionsselect;
/**
* The class constructor.
*
* @param int $cmid The database module id
* @param \action_menu|null $actionsselect The presets actions selector object.
*/
public function __construct(int $cmid) {
public function __construct(int $cmid, ?\action_menu $actionsselect) {
$this->cmid = $cmid;
$this->actionsselect = $actionsselect;
}
/**
@ -48,12 +52,14 @@ class presets_action_bar implements templatable, renderable {
* @return array
*/
public function export_for_template(\renderer_base $output): array {
$importpresetlink = new moodle_url('/mod/data/preset.php', [
'id' => $this->cmid, 'action' => 'import'
]);
return [
$data = [
'id' => $this->cmid,
'importpreseturl' => $importpresetlink->out(false),
];
if ($this->actionsselect) {
$data['actionsselect'] = $this->actionsselect->export_for_template($output);
}
return $data;
}
}

View File

@ -16,6 +16,7 @@
namespace mod_data\output;
use core\output\select_menu;
use templatable;
use renderable;
@ -31,29 +32,25 @@ class templates_action_bar implements templatable, renderable {
/** @var int $id The database module id. */
private $id;
/** @var \url_select $urlselect The URL selector object. */
private $urlselect;
/** @var select_menu $selectmenu The URL selector object. */
private $selectmenu;
/** @var \single_button|null $urlselect The save as preset single button object. */
private $saveaspresetbutton;
/** @var \single_button|null $urlselect The export preset single button object. */
private $exportpresetbutton;
/** @var \action_menu $actionsselect The presets actions selector object. */
private $actionsselect;
/**
* The class constructor.
*
* @param int $id The database module id.
* @param \url_select $urlselect The URL selector object.
* @param \single_button|null $saveaspresetbutton The save as preset single button object or null.
* @param \single_button|null $exportpresetbutton The export preset single button object or null.
* @param select_menu $selectmenu The URL selector object.
* @param null $unused1 This parameter has been deprecated since 4.1 and should not be used anymore.
* @param null $unused2 This parameter has been deprecated since 4.1 and should not be used anymore.
* @param \action_menu $actionsselect The presets actions selector object.
*/
public function __construct(int $id, \url_select $urlselect, ?\single_button $saveaspresetbutton,
?\single_button $exportpresetbutton) {
public function __construct(int $id, select_menu $selectmenu, $unused1, $unused2, \action_menu $actionsselect) {
$this->id = $id;
$this->urlselect = $urlselect;
$this->saveaspresetbutton = $saveaspresetbutton;
$this->exportpresetbutton = $exportpresetbutton;
$this->selectmenu = $selectmenu;
$this->actionsselect = $actionsselect;
}
/**
@ -64,17 +61,10 @@ class templates_action_bar implements templatable, renderable {
*/
public function export_for_template(\renderer_base $output): array {
$data = [
return [
'd' => $this->id,
'urlselect' => $this->urlselect->export_for_template($output),
'selectmenu' => $this->selectmenu->export_for_template($output),
'actionsselect' => $this->actionsselect->export_for_template($output),
];
$data['saveaspreset'] = $this->saveaspresetbutton;
if ($this->exportpresetbutton) {
$data['exportpreset'] = $this->exportpresetbutton->export_for_template($output);
}
return $data;
}
}

View File

@ -16,7 +16,10 @@
namespace mod_data\output;
use data_portfolio_caller;
use mod_data\manager;
use moodle_url;
use portfolio_add_button;
use templatable;
use renderable;
@ -38,17 +41,22 @@ class view_action_bar implements templatable, renderable {
/** @var bool $hasentries Whether entries exist. */
private $hasentries;
/** @var bool $mode The current view mode (list, view...). */
private $mode;
/**
* The class constructor.
*
* @param int $id The database module id.
* @param \url_select $urlselect The URL selector object.
* @param bool $hasentries Whether entries exist.
* @param string $mode The current view mode (list, view...).
*/
public function __construct(int $id, \url_select $urlselect, bool $hasentries) {
public function __construct(int $id, \url_select $urlselect, bool $hasentries, string $mode) {
$this->id = $id;
$this->urlselect = $urlselect;
$this->hasentries = $hasentries;
$this->mode = $mode;
}
/**
@ -58,26 +66,81 @@ class view_action_bar implements templatable, renderable {
* @return array
*/
public function export_for_template(\renderer_base $output): array {
global $PAGE;
global $PAGE, $DB, $CFG;
$data = [
'urlselect' => $this->urlselect->export_for_template($output),
];
if (has_capability('mod/data:manageentries', $PAGE->context)) {
$importentrieslink = new moodle_url('/mod/data/import.php',
['d' => $this->id, 'backto' => $PAGE->url->out(false)]);
$importentriesbutton = new \single_button($importentrieslink,
get_string('importentries', 'mod_data'), 'get', false);
$data['importentriesbutton'] = $importentriesbutton->export_for_template($output);
$activity = $DB->get_record('data', ['id' => $this->id], '*', MUST_EXIST);
$manager = manager::create_from_instance($activity);
$actionsselect = null;
// Import entries.
if (has_capability('mod/data:manageentries', $manager->get_context())) {
$actionsselect = new \action_menu();
$actionsselect->set_menu_trigger(get_string('actions'), 'btn btn-secondary');
$importentrieslink = new moodle_url('/mod/data/import.php', ['d' => $this->id, 'backto' => $PAGE->url->out(false)]);
$actionsselect->add(new \action_menu_link(
$importentrieslink,
null,
get_string('importentries', 'mod_data'),
false
));
}
if (has_capability(DATA_CAP_EXPORT, $PAGE->context) && $this->hasentries) {
$exportentrieslink = new moodle_url('/mod/data/export.php',
['d' => $this->id, 'backto' => $PAGE->url->out(false)]);
$exportentriesbutton = new \single_button($exportentrieslink, get_string('exportentries', 'mod_data'),
'get', false);
$data['exportentriesbutton'] = $exportentriesbutton->export_for_template($output);
// Export entries.
if (has_capability(DATA_CAP_EXPORT, $manager->get_context()) && $this->hasentries) {
if (!$actionsselect) {
$actionsselect = new \action_menu();
$actionsselect->set_menu_trigger(get_string('actions'), 'btn btn-secondary');
}
$exportentrieslink = new moodle_url('/mod/data/export.php', ['d' => $this->id, 'backto' => $PAGE->url->out(false)]);
$actionsselect->add(new \action_menu_link(
$exportentrieslink,
null,
get_string('exportentries', 'mod_data'),
false
));
}
// Export to portfolio. This is for exporting all records, not just the ones in the search.
if ($this->mode == '' && !empty($CFG->enableportfolios) && $this->hasentries) {
if ($manager->can_export_entries()) {
// Add the portfolio export button.
require_once($CFG->libdir . '/portfoliolib.php');
$cm = $manager->get_coursemodule();
$button = new portfolio_add_button();
$button->set_callback_options(
'data_portfolio_caller',
['id' => $cm->id],
'mod_data'
);
if (data_portfolio_caller::has_files($activity)) {
// No plain HTML.
$button->set_formats([PORTFOLIO_FORMAT_RICHHTML, PORTFOLIO_FORMAT_LEAP2A]);
}
$exporturl = $button->to_html(PORTFOLIO_ADD_MOODLE_URL);
if (!is_null($exporturl)) {
if (!$actionsselect) {
$actionsselect = new \action_menu();
$actionsselect->set_menu_trigger(get_string('actions'), 'btn btn-secondary');
}
$actionsselect->add(new \action_menu_link(
$exporturl,
null,
get_string('addtoportfolio', 'portfolio'),
false
));
}
}
}
if ($actionsselect) {
$data['actionsselect'] = $actionsselect->export_for_template($output);
}
return $data;

View File

@ -59,7 +59,7 @@ class zero_state_action_bar implements templatable, renderable {
$usepresetlink = new moodle_url('/mod/data/preset.php', $params);
$usepresetbutton = new \single_button($usepresetlink,
get_string('usepreset', 'mod_data'), 'get', true);
get_string('usestandard', 'mod_data'), 'get', true);
$data['usepresetbutton'] = $usepresetbutton->export_for_template($output);
$actionbar = new \mod_data\output\action_bar($instance->id, $PAGE->url);
@ -69,7 +69,7 @@ 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('importapreset', 'mod_data'), 'get', false, [
'data-action' => 'importpresets',
'data-dataid' => $cm->id,
]);
@ -79,4 +79,3 @@ class zero_state_action_bar implements templatable, renderable {
return $data;
}
}

View File

@ -576,7 +576,10 @@ class preset {
* @return string The plugin preset name to display.
*/
public static function get_name_from_plugin(string $pluginname): string {
if (get_string_manager()->string_exists('modulename', 'datapreset_'.$pluginname)) {
if ($pos = strpos($pluginname, '/')) {
$pluginname = substr($pluginname, $pos + 1);
}
if (!strpos(trim($pluginname), ' ') && get_string_manager()->string_exists('modulename', 'datapreset_'.$pluginname)) {
return get_string('modulename', 'datapreset_'.$pluginname);
} else {
return $pluginname;

View File

@ -23,20 +23,23 @@ function insert_field_tags(selectlist) {
*/
function showHideAdvSearch(checked) {
var divs = document.getElementsByTagName('div');
for(i=0;i<divs.length;i++) {
for (var i = 0; i < divs.length; i++) {
if(divs[i].id.match('data_adv_form')) {
if(checked) {
divs[i].style.display = 'inline';
}
else {
} else {
divs[i].style.display = 'none';
}
}
else if (divs[i].id.match('reg_search')) {
} else if (divs[i].id.match('reg_search')) {
if (!checked) {
divs[i].style.display = 'inline';
} else {
divs[i].style.display = 'none';
}
else {
} else if (divs[i].id.match('advsearch-save-sec')) {
if (!checked) {
divs[i].style.display = 'inline';
} else {
divs[i].style.display = 'none';
}
}

View File

@ -321,20 +321,23 @@ if (($mode == 'new') && (!empty($newtype))) { // Adding a new field.
// Don't check the rest of the options. There is no field, there is nothing else to work with.
exit;
}
$fieldactionbar = $actionbar->get_fields_action_bar(true, true, true);
$fieldactionbar = $actionbar->get_fields_action_bar(true);
data_print_header($course, $cm, $data, 'fields', $fieldactionbar);
echo $OUTPUT->heading(get_string('managefields', 'data'), 2, 'mb-4');
echo $OUTPUT->box_start('mb-4');
echo get_string('fieldshelp', 'data');
echo $OUTPUT->box_end();
$table = new html_table();
$table->head = [
get_string('fieldname', 'data'),
get_string('type', 'data'),
get_string('required', 'data'),
get_string('fielddescription', 'data'),
get_string('action', 'data'),
'',
];
$table->align = ['left', 'left', 'left', 'left'];
$table->wrap = [false,false,false,false];
$table->responsive = false;
$fieldrecords = $manager->get_field_records();
$missingfieldtypes = [];
@ -356,26 +359,40 @@ if (($mode == 'new') && (!empty($newtype))) { // Adding a new field.
'mode' => 'delete',
));
$actionmenu = new action_menu();
$icon = $OUTPUT->pix_icon('i/menu', get_string('actions'));
$actionmenu->set_menu_trigger($icon, 'btn btn-icon d-flex align-items-center justify-content-center');
$actionmenu->set_action_label(get_string('actions'));
$actionmenu->attributes['class'] .= ' fields-actions';
// It display a notification when the field type does not exist.
$deletelink = html_writer::link($deleteurl, $OUTPUT->pix_icon('t/delete', get_string('delete')));
$editlink = html_writer::link($displayurl, $OUTPUT->pix_icon('t/edit', get_string('edit')));
if ($field->type === 'unknown') {
$missingfieldtypes[] = $field->field->name;
$fieldnamedata = $field->field->name;
$fieltypedata = $field->field->type;
$fieldlinkdata = $deletelink;
} else {
$fieldnamedata = html_writer::link($displayurl, $field->field->name);
$fieltypedata = $field->image() . '&nbsp;' . $field->name();
$fieldlinkdata = $editlink . '&nbsp;' . $deletelink;
// Edit icon, only displayed when the field type is known.
$actionmenu->add(new action_menu_link_secondary(
$displayurl,
null,
get_string('edit'),
));
}
// Delete.
$actionmenu->add(new action_menu_link_secondary(
$deleteurl,
null,
get_string('delete'),
));
$actionmenutemplate = $actionmenu->export_for_template($OUTPUT);
$table->data[] = [
$fieldnamedata,
$field->field->name,
$fieltypedata,
$field->field->required ? get_string('yes') : get_string('no'),
shorten_text($field->field->description, 30),
$fieldlinkdata
$OUTPUT->render_from_template('core/action_menu', $actionmenutemplate)
];
if (!empty($missingfieldtypes)) {

View File

@ -132,7 +132,7 @@ $string['editcomment'] = 'Edit comment';
$string['editentry'] = 'Edit entry';
$string['editfield'] = 'Edit field';
$string['editordisable'] = 'Disable editor';
$string['editorenable'] = 'Enable editor';
$string['editorenable'] = 'Enable code editor';
$string['editpreset'] = 'Edit preset';
$string['emptyadd'] = 'The Add template is empty, generating a default form...';
$string['emptyaddform'] = 'You did not fill out any fields!';
@ -185,6 +185,7 @@ $string['fieldnametype'] = '{$a->name} ({$a->type})';
$string['fieldnotmatched'] = 'The following fields in your file are not known in this database: {$a}';
$string['fieldoptions'] = 'Options (one per line)';
$string['fields'] = 'Fields';
$string['fieldshelp'] = 'Create fields to collect different types of data for your entries or customise the existing ones if you used a preset.';
$string['fieldsnavigation'] = 'Fields tertiary navigation';
$string['fieldupdated'] = 'Field updated';
$string['fieldwidth'] = 'Width';
@ -195,8 +196,8 @@ $string['filesnotgenerated'] = 'Not all files were generated: {$a}';
$string['filtername'] = 'Database auto-linking';
$string['footer'] = 'Footer';
$string['forcelinkname'] = 'Forced name for the link';
$string['foundnorecords'] = 'No records found (<a href="{$a->reseturl}">Reset filters</a>)';
$string['foundrecords'] = 'Found records: {$a->num}/{$a->max} (<a href="{$a->reseturl}">Reset filters</a>)';
$string['foundnorecords'] = 'No records found. <a href="{$a->reseturl}">Clear all</a>';
$string['foundrecords'] = 'Found {$a->num} out of {$a->max} records. <a href="{$a->reseturl}">Clear all</a>';
$string['fromfile'] = 'Import from zip file';
$string['fromfile_help'] = 'The import from zip file feature allows you to browse for and upload a preset zip of templates and fields.';
$string['generateerror'] = 'Not all files generated!';
@ -216,7 +217,8 @@ $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['importpreset'] = 'Import preset';
$string['importapreset'] = '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';
@ -261,7 +263,7 @@ $string['latlonglinkservicesdisplayed'] = 'Link-out services to display';
$string['latlongotherfields'] = 'Other fields';
$string['list'] = 'View list';
$string['listview'] = 'List view';
$string['listtemplate'] = 'List template';
$string['listtemplate'] = 'List view template';
$string['longitude'] = 'Longitude';
$string['manageapproved'] = 'Allow editing of approved entries';
$string['managefields'] = 'Manage fields';
@ -307,7 +309,7 @@ $string['nodefinedfields'] = 'New preset has no defined fields!';
$string['nofieldcontent'] = 'Field content not found';
$string['nofieldindatabase'] = 'There are no fields defined for this database.';
$string['nofields'] = 'No fields yet';
$string['nolisttemplate'] = 'List template is not yet defined';
$string['nolisttemplate'] = 'List view template is not yet defined';
$string['nomatch'] = 'No matching entries found!';
$string['nomaximum'] = 'No maximum';
$string['nopreviewavailable'] = 'No preview available for {$a}';
@ -341,7 +343,7 @@ $string['presetinfo'] = 'Saving as a preset will publish this template. Other us
$string['presetnotselected'] = 'No preset has been selected.';
$string['presets'] = 'Presets';
$string['presetshelp'] = 'Choose a preset to use as a starting point.';
$string['preview'] = 'Preview';
$string['preview'] = 'Preview of {$a}';
$string['privacy:metadata:commentpurpose'] = 'Comments on database records';
$string['privacy:metadata:data_content'] = 'Represents one answer to one field in database activity module';
$string['privacy:metadata:data_content:fieldid'] = 'Field definition ID';
@ -394,7 +396,7 @@ $string['rsstype'] = 'RSS feed for this activity';
$string['save'] = 'Save';
$string['saveandadd'] = 'Save and add another';
$string['saveandview'] = 'Save and view';
$string['saveaspreset'] = 'Save as preset';
$string['saveaspreset'] = 'Publish preset on this site';
$string['saveaspreset_help'] = 'The save as preset feature publishes the templates and fields as a preset which others on the site can then use. (You may delete it from the list of presets at any time.)';
$string['savedataaspreset'] = 'Save all fields and templates as preset';
$string['saveaspresetmissingcapability'] = 'The user does not have permission to save the database as a preset.';
@ -410,7 +412,7 @@ $string['showall'] = 'Show all entries';
$string['showmore'] = 'Show more';
$string['single'] = 'View single';
$string['singleview'] = 'Single view';
$string['singletemplate'] = 'Single template';
$string['singletemplate'] = 'Single view template';
$string['startbuilding'] = 'Start building your activity';
$string['subplugintype_datafield'] = 'Database field type';
$string['subplugintype_datafield_plural'] = 'Database field types';
@ -447,7 +449,7 @@ $string['uploadrecords_link'] = 'mod/data/import';
$string['url'] = 'URL';
$string['usedate'] = 'Include in search.';
$string['usepredefinedset'] = 'Use predefined set';
$string['usepreset'] = 'Use a preset';
$string['usepreset'] = 'Use this preset';
$string['usestandard'] = 'Use a preset';
$string['usestandard_help'] = 'To use a preset available to the whole site, select it from the list. (If you have added a preset to the list using the save as preset feature then you have the option of deleting it.)';
$string['viewfromdate'] = 'Read only from';
@ -462,8 +464,8 @@ $string['unsupportedexport'] = '({$a->fieldtype}) cannot be exported.';
// Deprecated since Moodle 4.1.
$string['buttons'] = 'Actions';
$string['nolisttemplate'] = 'List template is not yet defined';
$string['nosingletemplate'] = 'Single template is not yet defined';
$string['nolisttemplate'] = 'List view template is not yet defined';
$string['nosingletemplate'] = 'Single view template is not yet defined';
$string['pleaseaddsome'] = 'Please create some below or <a href="{$a}">choose a predefined set</a> to get started.';
$string['blank'] = 'Blank';
$string['savetemplate'] = 'Save template';

View File

@ -606,12 +606,7 @@ class data_field_base { // Base class for Database Field Types (see field/*/
function image() {
global $OUTPUT;
$params = array('d'=>$this->data->id, 'fid'=>$this->field->id, 'mode'=>'display', 'sesskey'=>sesskey());
$link = new moodle_url('/mod/data/field.php', $params);
$str = '<a href="'.$link->out().'">';
$str .= $OUTPUT->pix_icon('field/' . $this->type, $this->type, 'data');
$str .= '</a>';
return $str;
return $OUTPUT->pix_icon('field/' . $this->type, $this->type, 'data');
}
/**
@ -1669,8 +1664,9 @@ function data_print_preference_form($data, $perpage, $search, $sort='', $order='
$cm = get_coursemodule_from_instance('data', $data->id);
$context = context_module::instance($cm->id);
echo '<div class="datapreferences mb-3">';
echo '<div class="datapreferences my-5">';
echo '<form id="options" action="view.php" method="get">';
echo '<div class="d-flex">';
echo '<div>';
echo '<input type="hidden" name="d" value="'.$data->id.'" />';
if ($mode =='asearch') {
@ -1750,7 +1746,12 @@ function data_print_preference_form($data, $perpage, $search, $sort='', $order='
echo '&nbsp;<input type="checkbox" id="advancedcheckbox" name="advanced" value="1" ' . $checked . ' ' .
'onchange="showHideAdvSearch(this.checked);" class="mx-1" />' .
'<label for="advancedcheckbox">' . get_string('advancedsearch', 'data') . '</label>';
echo '</div>';
echo '<div id="advsearch-save-sec" class="ml-auto '. $regsearchclass . '">';
echo '&nbsp;<input type="submit" class="btn btn-secondary" value="' . get_string('savesettings', 'data') . '" />';
echo '</div>';
echo '</div>';
echo '<div>';
echo '<br />';
echo '<div class="' . $advancedsearchclass . '" id="data_adv_form">';
@ -1833,9 +1834,9 @@ function data_print_preference_form($data, $perpage, $search, $sort='', $order='
'</td></tr>';
echo '</table>';
echo '</div>';
echo '</div>';
echo '</form>';
echo '</div>';
echo '<hr/>';
}
/**

View File

@ -146,7 +146,6 @@ if ($action === 'preview') {
echo $OUTPUT->header();
$actionbar = new action_bar($data->id, $url);
echo $actionbar->get_presets_preview_action_bar($manager, $fullname, $templatename);
echo $OUTPUT->heading(ucfirst($preset->name), 2, 'mb-4');
echo $renderer->render($preview);
echo $OUTPUT->footer();
exit(0);
@ -170,7 +169,6 @@ if ($action === 'finishimport') {
$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);

View File

@ -22,7 +22,7 @@ Feature: Users can use the Image gallery preset
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
And I follow "Presets"
And I click on "fullname" "radio" in the "Image gallery" "table_row"
And I click on "Use a preset" "button"
And I click on "Use this preset" "button"
And the following "mod_data > entries" exist:
| database | user | title | description | image |
| data1 | student1 | First image | This is the description text for image 1 | first.png |
@ -73,12 +73,12 @@ Feature: Users can use the Image gallery preset
And I should see "First name"
And I should see "Last name"
And I set the field "title" to "First image"
And I press "Save settings"
And I click on "Save settings" "button" in the "data_adv_form" "region"
Then I should see "First image"
And I should not see "Second image"
But I set the field "title" to "image"
And I set the field "Order" to "Descending"
And I press "Save settings"
And I click on "Save settings" "button" in the "data_adv_form" "region"
And "Second image" "text" should appear before "First image" "text"
@javascript

View File

@ -22,7 +22,7 @@ Feature: Users can use the Journal preset
And I am on the "Student reflections" "data activity" page logged in as teacher1
And I follow "Presets"
And I click on "fullname" "radio" in the "Journal" "table_row"
And I click on "Use a preset" "button"
And I click on "Use this preset" "button"
And the following "mod_data > entries" exist:
| database | user | Title | Content |
| data1 | student1 | Reflection created by student | This is the content for the entry 1 |
@ -59,12 +59,12 @@ Feature: Users can use the Journal preset
And I should see "First name"
And I should see "Last name"
And I set the field "Title" to "student"
And I press "Save settings"
And I click on "Save settings" "button" in the "data_adv_form" "region"
Then I should see "Reflection created by student"
And I should not see "Reflection created by teacher"
But I set the field "Title" to "Reflection"
And I set the field "Order" to "Descending"
And I press "Save settings"
And I click on "Save settings" "button" in the "data_adv_form" "region"
And "Reflection created by teacher" "text" should appear before "Reflection created by student" "text"
@javascript

View File

@ -22,7 +22,7 @@ Feature: Users can use the Proposals preset
And I am on the "Student projects" "data activity" page logged in as teacher1
And I follow "Presets"
And I click on "fullname" "radio" in the "Proposals" "table_row"
And I click on "Use a preset" "button"
And I click on "Use this preset" "button"
And the following "mod_data > entries" exist:
| database | user | Title | Summary | Content | Status |
| data1 | student1 | Project created by student | Summary 1 | Content for entry 1 | Pending |
@ -73,12 +73,12 @@ Feature: Users can use the Proposals preset
And I should see "First name"
And I should see "Last name"
And I set the field "Title" to "student"
And I press "Save settings"
And I click on "Save settings" "button" in the "data_adv_form" "region"
Then I should see "Project created by student"
And I should not see "Project created by teacher"
But I set the field "Title" to "Project"
And I set the field "Order" to "Descending"
And I press "Save settings"
And I click on "Save settings" "button" in the "data_adv_form" "region"
And "Project created by teacher" "text" should appear before "Project created by student" "text"
@javascript

View File

@ -22,7 +22,7 @@ Feature: Users can use the Resources preset
And I am on the "Student resources" "data activity" page logged in as teacher1
And I follow "Presets"
And I click on "fullname" "radio" in the "Resources" "table_row"
And I click on "Use a preset" "button"
And I click on "Use this preset" "button"
And the following "mod_data > entries" exist:
| database | user | Title | Description | Type | Author | Web link | Cover |
| data1 | student1 | My favourite book | Book content | Type1 | The book author | http://myfavouritebook.cat | first.png |
@ -77,12 +77,12 @@ Feature: Users can use the Resources preset
And I should see "First name"
And I should see "Last name"
And I set the field "Title" to "book"
And I press "Save settings"
And I click on "Save settings" "button" in the "data_adv_form" "region"
Then I should see "My favourite book"
And I should not see "My favourite podcast"
But I set the field "Title" to "favourite"
And I set the field "Order" to "Descending"
And I press "Save settings"
And I click on "Save settings" "button" in the "data_adv_form" "region"
And "My favourite podcast" "text" should appear before "My favourite book" "text"
@javascript

View File

@ -150,7 +150,8 @@
}
.preset_action_menu .dropdown-toggle::after,
.entry-actionsmenu .dropdown-toggle::after {
.entry-actionsmenu .dropdown-toggle::after,
.fields-actions .dropdown-toggle::after {
display: none;
}
@ -189,6 +190,13 @@
pointer-events: none;
}
/* Actions menu */
.presetsactions .dropdown-toggle,
.presetsactions .dropdown-toggle:hover,
.presetsactions .show > .btn-secondary.dropdown-toggle,
.entriesactions .dropdown-toggle,
.entriesactions .dropdown-toggle:hover,
.entriesactions .show > .btn-secondary.dropdown-toggle,
#page-mod-data-view .whitebutton .btn-secondary,
#page-mod-data-field- .whitebutton .btn-secondary,
#page-mod-data-templates .whitebutton .btn-secondary {

View File

@ -30,7 +30,7 @@ require_once('lib.php');
$id = optional_param('id', 0, PARAM_INT); // course module id
$d = optional_param('d', 0, PARAM_INT); // database id
$mode = optional_param('mode', 'listtemplate', PARAM_ALPHA);
$mode = optional_param('mode', 'addtemplate', PARAM_ALPHA);
$useeditor = optional_param('useeditor', null, PARAM_BOOL);
$url = new moodle_url('/mod/data/templates.php');
@ -85,8 +85,6 @@ if (!$manager->has_fields()) {
$actionbar = new \mod_data\output\action_bar($instance->id, $url);
echo $actionbar->get_templates_action_bar();
echo $OUTPUT->heading(get_string($mode, 'data'), 2, 'mb-4');
if (($formdata = data_submitted()) && confirm_sesskey()) {
$notificationstr = get_string('templatesaved', 'data');
if (!empty($formdata->defaultform)) {

View File

@ -84,34 +84,35 @@
<div class="row">
<div class="d-flex">
{{#hasback}}
<div class="navitem backbutton border-right">
<div class="navitem mb-0 backbutton border-right">
<a href="{{backurl}}" role="button" title="{{backtitle}}" class="d-flex align-items-center">{{!
}}{{#pix}} i/previous, moodle {{/pix}}{{!
}}</a>
</div>
{{/hasback}}
{{#urlselect}}
<div class="navitem">
<div class="navitem mb-0">
{{>core/url_select}}
</div>
{{/urlselect}}
{{#title}}
<div class="navitem title d-flex align-items-center">
{{title}}
<div class="navitem mb-0 title d-flex align-items-center">
<h2>{{title}}</h2>
</div>
{{/title}}
</div>
<div class="ml-sm-auto d-flex">
{{#extraurlselect}}
<div class="navitem">
<div class="navitem mb-0">
{{>core/url_select}}
</div>
{{/extraurlselect}}
{{#buttons}}
<div class="navitem">
<div class="navitem mb-0">
{{>core/single_button}}
</div>
{{/buttons}}
</div>
</div>
</div>
<hr/>

View File

@ -18,33 +18,11 @@
Context variables required for this template:
* d - The database id.
* urlselect - The data object containing the required properties to render core/url_select.
* fieldselect - The data object containing the required properties to render core/single_select.
* saveaspreset - Whether to display the save as preset button (mod_data/save_as_preset).
* exportpreset - The data object containing the required properties to render core/single_button.
Example context (json):
{
"d": 1,
"urlselect": {
"id": "url_select_test",
"action": "https://example.com/post",
"formid": "url_select_form",
"sesskey": "sesskey",
"classes": "urlselect",
"label": "",
"helpicon": false,
"showbutton": null,
"options": [
{
"name": "Some name",
"value": "/mod/data/someurl.php",
"selected": false
}
],
"disabled": false,
"title": null
},
"fieldselect": {
"id": "single_select_test",
"name": "fieldselector",
@ -65,43 +43,21 @@
],
"disabled": false,
"title": null
},
"saveaspreset": true,
"exportpreset": {
"id": "single_button_test",
"method" : "post",
"formid": "single_button_form",
"url" : "https://example.com/post",
"primary" : false,
"tooltip" : null,
"label" : "Label",
"attributes": []
}
}
}}
<div class="container-fluid tertiary-navigation">
<div class="row">
<div class="d-flex">
{{#urlselect}}
<div class="navitem">
{{>core/url_select}}
</div>
{{/urlselect}}
<div class="col">
<h2>{{#str}}managefields, mod_data{{/str}}</h2>
</div>
<div class="ml-sm-auto d-flex">
{{#saveaspreset}}
<div class="navitem">
{{>mod_data/save_as_preset}}
</div>
{{/saveaspreset}}
{{#exportpreset}}
<div class="navitem">
{{>core/single_button}}
</div>
{{/exportpreset}}
<div class="col-auto">
{{#fieldselect}}
{{>core/action_menu}}
<div class='navitem mb-0 fieldadd'>
{{>core/action_menu}}
</div>
{{/fieldselect}}
</div>
</div>
</div>
<hr/>

View File

@ -26,10 +26,7 @@
"shortname": "imagegallery"
}
}}
<div id="template-preview">
<div class="template-description mb-2">
{{description}}
</div>
<div id="template-preview" class="mt-4">
<div class="template-preview-content">
{{{preview}}}
</div>

View File

@ -61,7 +61,7 @@
<th class="pl-4 border-top-0" scope="col" style="width: 3%"></th>
<th class="pl-4 border-top-0" scope="col" style="width:30%">{{#str}} name {{/str}}</th>
<th class="pl-4 border-top-0" scope="col">{{#str}} description {{/str}}</th>
<th class="pl-4 border-top-0" scope="col" style="width: 3%">{{#showmanage}}{{#str}} action {{/str}}{{/showmanage}}</th>
<th class="pl-4 border-top-0" scope="col" style="width: 3%"></th>
</tr>
</thead>
<tbody>

View File

@ -17,24 +17,68 @@
Actions bar at the top of the presets page in the database activity.
Context variables required for this template:
* importpreseturl - The url to the import preset page.
* actionsselect - The presets actions selector.
* id - The database course module id (cmid).
Example context (json):
{
"importpreseturl": "http://www.example.com",
"actionsselect": {
"classes": "moodle-actionmenu",
"instance": "1",
"triggerrole": "button",
"primary": {
"attributes": [
{"name": "id", "value": "action-menu-1"},
{"name": "role", "value": "menu"}
],
"items": [
{
"attributes": [
{"name": "role", "value": "menuitem"}
],
"rawhtml": "Actions"
}
]
},
"secondary": {
"attributes": [
{"name": "id", "value": "action-menu-1-menu"},
{"name": "role", "value": "menuitem"}
],
"items": [
{
"rawhtml": "Import preset"
},
{
"rawhtml": "Export preset"
}
]
}
},
"id" : 1
}
}}
<div class="container-fluid tertiary-navigation">
<div class="row float-right">
<div class="navitem">
<a role="button" href="{{importpreseturl}}" class="btn btn-secondary" data-action="importpresets" data-dataid="{{id}}">{{#str}}import, core{{/str}}</a>
<div class="row">
<div class="col">
<h2>{{#str}}presets, mod_data{{/str}}</h2>
</div>
<div class="col-auto">
{{#actionsselect}}
<div class='navitem mb-0 presetsactions'>
{{>core/action_menu}}
</div>
{{/actionsselect}}
</div>
</div>
</div>
<hr/>
{{#js}}
require(['mod_data/saveaspreset'], function(saveAsPreset) {
saveAsPreset.init();
});
require(['mod_data/importpresets'], function(importPresetsModal) {
importPresetsModal.init();
});
{{/js}}
</div>

View File

@ -18,63 +18,87 @@
Context variables required for this template:
* d - The database id.
* urlselect - The data object containing the required properties to render core/url_select.
* saveaspreset - Whether to display the save as preset button (mod_data/save_as_preset).
* exportpreset - The data object containing the required properties to render core/single_button.
* selectmenu - The data object containing the required properties to render core/selectmenu.
* actionsselect - The presets actions selector.
Example context (json):
{
"d": 1,
"urlselect": {
"id": "url_select_test",
"action": "https://example.com/post",
"formid": "url_select_form",
"sesskey": "sesskey",
"classes": "urlselect",
"label": "",
"helpicon": false,
"showbutton": null,
"selectmenu": {
"name": "Templates tertiary navigation selector",
"value": "opt",
"baseid": "select-menu1",
"selectedoption": "Single view template",
"options": [
{
"name": "Some name",
"value": "/mod/data/someurl.php",
"selected": false
"selected": false,
"name": "Add entry template",
"id": "select-menu-group1"
},
{
"selected": true,
"name": "Single view template",
"value": "opt2",
"id": "select-menu-option2"
}
],
"disabled": false,
"title": null
]
},
"saveaspreset": true,
"exportpreset": {
"id": "single_button_test",
"method" : "post",
"formid": "single_button_form",
"url" : "https://example.com/post",
"primary" : false,
"tooltip" : null,
"label" : "Label",
"attributes": []
"actionsselect": {
"classes": "moodle-actionmenu",
"instance": "1",
"triggerrole": "button",
"primary": {
"attributes": [
{"name": "id", "value": "action-menu-1"},
{"name": "role", "value": "menu"}
],
"items": [
{
"attributes": [
{"name": "role", "value": "menuitem"}
],
"rawhtml": "Actions"
}
]
},
"secondary": {
"attributes": [
{"name": "id", "value": "action-menu-1-menu"},
{"name": "role", "value": "menuitem"}
],
"items": [
{
"rawhtml": "Import preset"
},
{
"rawhtml": "Export preset"
}
]
}
}
}
}}
<div class="container-fluid tertiary-navigation">
<div class="row">
{{#urlselect}}
<div class="navitem">
{{>core/url_select}}
</div>
{{/urlselect}}
<div class="ml-sm-auto d-flex">
{{#saveaspreset}}
<div class="navitem">
{{>mod_data/save_as_preset}}
<div class="navitem mb-0 col">
{{#selectmenu}}
<div>
{{>core/tertiary_navigation_selector}}
</div>
{{/saveaspreset}}
{{#exportpreset}}
<div class="navitem">
{{>core/single_button}}
{{/selectmenu}}
</div>
<div class="col-auto">
{{#actionsselect}}
<div class='navitem mb-0 presetsactions'>
{{>core/action_menu}}
</div>
{{/exportpreset}}
{{/actionsselect}}
</div>
</div>
</div>
<hr/>
{{#js}}
require(['mod_data/saveaspreset'], function(saveAsPreset) {
saveAsPreset.init();
});
{{/js}}

View File

@ -18,8 +18,7 @@
Context variables required for this template:
* urlselect - The data object containing the required properties to render core/url_select.
* importentriesbutton - The data object containing the required properties to render core/single_button.
* exportentriesbutton - The data object containing the required properties to render core/single_button.
* actionsselect - The presets actions selector.
Example context (json):
{
@ -34,59 +33,77 @@
"showbutton": null,
"options": [
{
"name": "Some name",
"name": "List view",
"value": "/mod/data/someurl.php",
"selected": false
},
{
"name": "Single view",
"value": "/mod/data/someurl.php",
"selected": true
}
],
"disabled": false,
"title": null
},
"importentriesbutton": {
"id": "single_button_test_1",
"method" : "post",
"formid": "single_button_form_1",
"url" : "http://example.com/post",
"primary" : false,
"tooltip" : null,
"label" : "Label",
"attributes": []
},
"exportentriesbutton": {
"id": "single_button_test_2",
"method" : "post",
"formid": "single_button_form_2",
"url" : "http://example.com/post",
"primary" : false,
"tooltip" : null,
"label" : "Label",
"attributes": []
"actionsselect": {
"classes": "moodle-actionmenu",
"instance": "1",
"triggerrole": "button",
"primary": {
"attributes": [
{"name": "id", "value": "action-menu-1"},
{"name": "role", "value": "menu"}
],
"items": [
{
"attributes": [
{"name": "role", "value": "menuitem"}
],
"rawhtml": "Actions"
}
]
},
"secondary": {
"attributes": [
{"name": "id", "value": "action-menu-1-menu"},
{"name": "role", "value": "menuitem"}
],
"items": [
{
"rawhtml": "Import entries"
},
{
"rawhtml": "Export entries"
}
]
}
}
}
}}
<div class="container-fluid tertiary-navigation">
<div class="row">
{{#urlselect}}
<div class="navitem">
{{>core/url_select}}
</div>
{{/urlselect}}
{{#addentrybutton}}
<div class="navitem">
{{>core/single_button}}
</div>
{{/addentrybutton}}
<div class="ml-sm-auto d-flex">
{{#importentriesbutton}}
<div class="navitem">
<div class="container-fluid tertiary-navigation d-flex">
<div class="row ml-auto">
<div class="col">
{{#addentrybutton}}
<div class="navitem mb-0">
{{>core/single_button}}
</div>
{{/importentriesbutton}}
{{#exportentriesbutton}}
<div class="navitem">
{{>core/single_button}}
{{/addentrybutton}}
</div>
<div class="col">
{{#urlselect}}
<div class="navitem mb-0">
{{>core/url_select}}
</div>
{{/exportentriesbutton}}
{{/urlselect}}
</div>
<div class="col">
{{#actionsselect}}
<div class='navitem mb-0 entriesactions'>
{{>core/action_menu}}
</div>
{{/actionsselect}}
</div>
</div>
</div>
<hr/>

View File

@ -36,14 +36,15 @@ Feature: Users can add the ##actionsmenu## replacement to the database templates
| data1 | teacher1 | Teacher entry 1 | Some teacher content 1 |
And I am on the "Test database name" "data activity" page logged in as teacher1
And I navigate to "Templates" in current page administration
And I set the field "Templates tertiary navigation" to "List view template"
And I set the following fields to these values:
| Header | <table> |
| Repeated entry | <tr><td>[[field1]]</td><td>##actionsmenu##</td><tr> |
| Footer | </table> |
And I click on "Save" "button" in the "sticky-footer" "region"
And I set the field "Templates tertiary navigation" to "Single template"
And I set the field "Templates tertiary navigation" to "Single view template"
And I set the following fields to these values:
| Single template | <table><tr><td>[[field1]]</td><td>[[field2]]</td><td>##actionsmenu##</td><tr></table> |
| Single view template | <table><tr><td>[[field1]]</td><td>[[field2]]</td><td>##actionsmenu##</td><tr></table> |
And I click on "Save" "button" in the "sticky-footer" "region"
@javascript

View File

@ -63,10 +63,10 @@ Feature: Users can view and manage data presets
And I should see "Delete"
# Teachers can't delete the presets they haven't created.
And I should not see "Actions" in the "Saved preset 1" "table_row"
# The "Use a preset" button should be enabled only when a preset is selected.
And the "Use a preset" "button" should be disabled
# The "Use this preset" button should be enabled only when a preset is selected.
And the "Use this preset" "button" should be disabled
And I click on "fullname" "radio" in the "Image gallery" "table_row"
And the "Use a preset" "button" should be enabled
And the "Use this preset" "button" should be enabled
@javascript
Scenario: Only users with the viewalluserpresets capability can see presets created by other users
@ -90,7 +90,8 @@ Feature: Users can view and manage data presets
| data1 | text | Test field name | Test field description |
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
And I follow "Templates"
When I click on "Save as preset" "button"
When I click on "Actions" "button"
And I choose "Publish preset on this site" in the open action menu
Then I should see "Name" in the "Save all fields and templates as preset" "dialogue"
And I should see "Description" in the "Save all fields and templates as preset" "dialogue"
And "Replace existing preset with this name and overwrite its contents" "checkbox" should not be visible
@ -104,7 +105,8 @@ Feature: Users can view and manage data presets
And I should see "My funny description goes here." in the "New saved preset" "table_row"
# Teacher can't overwrite an existing preset that they haven't created.
And I follow "Templates"
And I click on "Save as preset" "button"
And I click on "Actions" "button"
And I choose "Publish preset on this site" in the open action menu
And I set the field "Name" to "Saved preset 1"
And I click on "Save" "button" in the "Save all fields and templates as preset" "dialogue"
And I should see "A preset with this name already exists. Choose a different name."
@ -126,7 +128,8 @@ Feature: Users can view and manage data presets
And I should not see "This is a new description that shouldn't be saved."
# But teacher can overwrite existing presets created by them.
But I follow "Templates"
And I click on "Save as preset" "button"
And I click on "Actions" "button"
And I choose "Publish preset on this site" in the open action menu
And I set the field "Name" to "New saved preset"
And I set the field "Description" to "This is a new description that will be overwritten."
And I click on "Save" "button" in the "Save all fields and templates as preset" "dialogue"
@ -275,7 +278,8 @@ Feature: Users can view and manage data presets
| data1 | rsstemplate |
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
And I follow "Templates"
And I click on "Save as preset" "button"
And I click on "Actions" "button"
And I choose "Publish preset on this site" in the open action menu
And I set the field "Name" to "New saved preset"
And I set the field "Description" to "My funny description goes here."
And I click on "Save" "button" in the "Save all fields and templates as preset" "dialogue"
@ -283,10 +287,9 @@ Feature: Users can view and manage data presets
When I click on "Preview preset" "link"
Then I should see "Preview"
And I should see "New saved preset"
And I should see "My funny description goes here"
And I should see "Test field name"
And I should see "This is a short text"
Then "Use a preset" "button" should exist
Then "Use this preset" "button" should exist
@javascript
Scenario: Teachers can export any saved preset
@ -306,7 +309,8 @@ Feature: Users can view and manage data presets
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"
Then I click on "Actions" "button"
And I choose "Import preset" in the open action menu
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."

View File

@ -94,7 +94,8 @@ Feature: Users can use mod_data without editing the templates
And I should not see "Student entry 2"
And I should not see "Some content 2"
When I navigate to "Fields" in current page administration
And I click on "Delete" "link" in the "field2" "table_row"
And I click on "Actions" "button" in the "field2" "table_row"
And I choose "Delete" in the open action menu
And I click on "Continue" "button"
Then I navigate to "Database" in current page administration
And I should see "field1"
@ -127,6 +128,7 @@ Feature: Users can use mod_data without editing the templates
@javascript
Scenario: The dynamic default templates can be reset after a manual edition.
Given I navigate to "Templates" in current page administration
And I set the field "Templates tertiary navigation" to "List view template"
And I set the following fields to these values:
| Header | New header! |
| Repeated entry | This is the template content |
@ -139,6 +141,7 @@ Feature: Users can use mod_data without editing the templates
And I should not see "Student entry 1"
And I should not see "Some content 1"
When I navigate to "Templates" in current page administration
And I set the field "Templates tertiary navigation" to "List view template"
And I click on "Reset" "button" in the "sticky-footer" "region"
And I click on "Reset template" "button" in the "Reset template?" "dialogue"
And I should see "Template reset"

View File

@ -26,6 +26,7 @@ Feature: Users can edit the database templates
| data1 | Student entry 1 | Some content 1 |
And I am on the "Test database name" "data activity" page logged in as teacher1
And I navigate to "Templates" in current page administration
And I set the field "Templates tertiary navigation" to "List view template"
@javascript
Scenario: Edit list template
@ -41,9 +42,9 @@ Feature: Users can edit the database templates
@javascript
Scenario: Edit single template
Given I set the field "Templates tertiary navigation" to "Single template"
Given I set the field "Templates tertiary navigation" to "Single view template"
And I set the following fields to these values:
| Single template | [[field1]] and [[field2]] details! |
| Single view template | [[field1]] and [[field2]] details! |
And I click on "Save" "button" in the "sticky-footer" "region"
When I navigate to "Database" in current page administration
And I set the field "View mode tertiary navigation" to "Single view"
@ -71,7 +72,7 @@ Feature: Users can edit the database templates
@javascript
Scenario: Edit without the wysiwyg editor
Given I click on "Enable editor" "checkbox"
Given I click on "Enable code editor" "checkbox"
And I set the following fields to these values:
| Repeated entry | <span class="d-none">Nope</span>Yep! |
And I click on "Save" "button" in the "sticky-footer" "region"
@ -81,7 +82,7 @@ Feature: Users can edit the database templates
@javascript
Scenario: Edit CSS teamplate
Given I click on "Enable editor" "checkbox"
Given I click on "Enable code editor" "checkbox"
And I set the following fields to these values:
| Repeated entry | <span class="hideme">Nope</span>Yep! |
And I click on "Save" "button" in the "sticky-footer" "region"
@ -95,7 +96,7 @@ Feature: Users can edit the database templates
@javascript
Scenario: Edit Javascript template
Given I click on "Enable editor" "checkbox"
Given I click on "Enable code editor" "checkbox"
And I set the following fields to these values:
| Repeated entry | <span id="hideme">Nope</span>Yep! |
And I click on "Save" "button" in the "sticky-footer" "region"
@ -121,6 +122,7 @@ Feature: Users can edit the database templates
And I should not see "Student entry 1"
And I should not see "Some content 1"
When I navigate to "Templates" in current page administration
And I set the field "Templates tertiary navigation" to "List view template"
And I click on "Reset" "button" in the "sticky-footer" "region"
And I click on "Reset template" "button" in the "Reset template?" "dialogue"
Then I should see "Template reset"

View File

@ -25,7 +25,8 @@ Feature: Users can import presets
Scenario: Teacher can import from preset page on an empty database
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 click on "Actions" "button"
And I choose "Import preset" in the open action menu
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"
@ -37,7 +38,8 @@ Feature: Users can import presets
| data1 | text | Test field name | Test field description |
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 click on "Actions" "button"
And I choose "Import preset" in the open action menu
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"
@ -60,7 +62,8 @@ Feature: Users can import presets
| data1 | Student entry 1 |
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 click on "Actions" "button"
And I choose "Import preset" in the open action menu
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"
@ -70,7 +73,8 @@ Feature: Users can import presets
Scenario: Teacher can import from field page on an empty database
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 click on "Actions" "button"
And I choose "Import preset" in the open action menu
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"
@ -82,7 +86,8 @@ Feature: Users can import presets
| data1 | text | Test field name | Test field description |
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 click on "Actions" "button"
And I choose "Import preset" in the open action menu
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"
@ -105,7 +110,8 @@ Feature: Users can import presets
| data1 | Student entry 1 |
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 click on "Actions" "button"
And I choose "Import preset" in the open action menu
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"

View File

@ -25,18 +25,20 @@ Feature: Users can preview presets
@javascript @_file_upload
Scenario: Preview a user preset as list view template in database
Given I follow "Presets"
And I click on "Import" "button"
And I click on "Actions" "button"
And I choose "Import preset" in the open action menu
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 click on "Actions" "button"
And I choose "Publish preset on this site" in the open action menu
And I set the field "Name" to "Saved preset by teacher1"
And I set the field "Description" to "Behat test preset"
And I click on "Save" "button" in the "Save all fields and templates as preset" "dialogue"
When I follow "Presets"
And I click on "Saved preset by teacher1" "link"
# Check list template preview fields.
Then I should see "Behat test preset" in the "template-preview" "region"
Then I should see "Saved preset by teacher1"
And I should see "List header" in the "template-preview" "region"
And I should see "List footer" in the "template-preview" "region"
And I should see "List template content" in the "template-preview" "region"
@ -71,19 +73,21 @@ Feature: Users can preview presets
@javascript @_file_upload
Scenario: Preview a user preset as single view template in database
Given I follow "Presets"
And I click on "Import" "button"
And I click on "Actions" "button"
And I choose "Import preset" in the open action menu
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 click on "Actions" "button"
And I choose "Publish preset on this site" in the open action menu
And I set the field "Name" to "Saved preset by teacher1"
And I set the field "Description" to "Behat test preset"
And I click on "Save" "button" in the "Save all fields and templates as preset" "dialogue"
When I follow "Presets"
And I click on "Saved preset by teacher1" "link"
And I set the field "Templates tertiary navigation" to "Single template"
# Check single template preview fields.
Then I should see "Behat test preset" in the "template-preview" "region"
And I set the field "Templates tertiary navigation" to "Single view template"
# Check single view template preview fields.
Then I should see "Saved preset by teacher1"
And I should see "Single template content" in the "template-preview" "region"
And I should see "My text field" in the "template-preview" "region"
And I should see "This is a short text" in the "template-preview" "region"
@ -117,11 +121,10 @@ Feature: Users can preview presets
Scenario: Preview a plugin preset in database
Given I follow "Presets"
When I click on "Journal" "link"
Then I should see "Use this preset for a journal, diary, reflections tool or research log." in the "template-preview" "region"
Then I should see "Journal"
And I should see "This is a short text"
And I should see "This is a text area"
And I select "Single template" from the "Templates tertiary navigation" singleselect
And I should see "Use this preset for a journal, diary, reflections tool or research log." in the "template-preview" "region"
And I select "Single view template" from the "Templates tertiary navigation" singleselect
And I should see "This is a short text"
And I should see "This is a text area"
And I should see "This is a short text" in the "template-preview" "region"
@ -130,7 +133,7 @@ Feature: Users can preview presets
Scenario: Use back button to return to the presets page in database
Given I follow "Presets"
And I click on "Image gallery" "link"
And I should see "Use this preset to collect images." in the "template-preview" "region"
And I should see "Image gallery"
When I click on "Back" "button"
Then I should see "Choose a preset to use as a starting point."
@ -138,23 +141,25 @@ Feature: Users can preview presets
Scenario: Apply plugin preset from preview in database
Given I follow "Presets"
And I click on "Image gallery" "link"
When I click on "Use a preset" "button"
When I click on "Use this preset" "button"
Then I should see "image"
And I should see "image"
And I should see "title"
@javascript @_file_upload
Scenario: Apply user preset from preview in database
Given I follow "Presets"
And I click on "Import" "button"
And I click on "Actions" "button"
And I choose "Import preset" in the open action menu
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 click on "Actions" "button"
And I choose "Publish preset on this site" in the open action menu
And I set the field "Name" to "Saved preset by teacher1"
And I set the field "Description" to "Behat test preset"
And I click on "Save" "button" in the "Save all fields and templates as preset" "dialogue"
When I follow "Presets"
And I click on "Saved preset by teacher1" "link"
And I click on "Use a preset" "button"
Then I should see "My URL field"
And I click on "Use this preset" "button"
Then I should see "Field mappings"
And I should see "My URL field"

View File

@ -0,0 +1,129 @@
@mod @mod_data
Feature: Users can navigate through the database activity using the tertiary navigation
In order to use the database module
As a user
I need to navigate using the tertiary navigation.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@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 |
| student1 | C1 | student |
And the following "activities" exist:
| activity | name | intro | course | idnumber |
| data | Test database name | Database intro | C1 | data1 |
| data | Database without fields | Database intro | C1 | data2 |
And the following "mod_data > fields" exist:
| database | type | name | description |
| data1 | text | field1 | Test field description |
| data1 | text | field2 | Test field 2 description |
And the following "mod_data > entries" exist:
| database | user | field1 | field2 |
| data1 | teacher1 | Teacher entry 1 | Some content 1 |
| data1 | teacher1 | Teacher entry 2 | Some content 2 |
And the following "mod_data > presets" exist:
| database | name | description | user |
| data1 | Saved preset by teacher1 | This preset has also a description | teacher1 |
And I log in as "admin"
And the following config values are set as admin:
| enableportfolios | 1 |
And I navigate to "Plugins > Portfolios > Manage portfolios" in site administration
And I set portfolio instance "File download" to "Enabled and visible"
And I click on "Save" "button"
And I log out
And I am on the "Test database name" "data activity" page logged in as teacher1
@javascript
Scenario: The tertiary navigation in the Database page.
Given I navigate to "Database" in current page administration
# Teacher: List view.
And I should not see "List view" in the "data-listview-content" "region"
When I click on "Actions" "button"
Then I should see "Import entries" in the ".entriesactions" "css_element"
And I should see "Export entries" in the ".entriesactions" "css_element"
And I should see "Export to portfolio" in the ".entriesactions" "css_element"
And I press the escape key
# Teacher: Single view.
And I set the field "View mode tertiary navigation" to "Single view"
And I should not see "Single view" in the "data-singleview-content" "region"
And I click on "Actions" "button"
And I should see "Import entries" in the ".entriesactions" "css_element"
And I should see "Export entries" in the ".entriesactions" "css_element"
And I should not see "Export to portfolio" in the ".entriesactions" "css_element"
# Teacher: Database without fields.
And I am on the "Database without fields" "data activity" page
And I should not see "Actions"
# Student without entries: List view.
And I am on the "Test database name" "data activity" page logged in as student1
And I should not see "Actions"
# Student without entries: Single view.
And I set the field "View mode tertiary navigation" to "Single view"
And I should not see "Actions"
# Student with entries: Single view.
But the following "mod_data > entries" exist:
| database | user | field1 | field2 |
| data1 | student1 | Student entry 3 | Some content 3 |
And I should not see "Actions"
# Student with entries: List view.
And I set the field "View mode tertiary navigation" to "List view"
And I click on "Actions" "button"
And I should not see "Import entries" in the ".entriesactions" "css_element"
And I should not see "Export entries" in the ".entriesactions" "css_element"
And I should see "Export to portfolio" in the ".entriesactions" "css_element"
@javascript
Scenario: The tertiary navigation in the Presets page.
Given I navigate to "Presets" in current page administration
When I click on "Actions" "button"
Then I should see "Import preset" in the ".presetsactions" "css_element"
And I should see "Export preset" in the ".presetsactions" "css_element"
And I should see "Publish preset on this site" in the ".presetsactions" "css_element"
And I press the escape key
# Database without fields.
But I am on the "Database without fields" "data activity" page
And I navigate to "Presets" in current page administration
And I click on "Actions" "button"
And I should see "Import preset" in the ".presetsactions" "css_element"
And I should not see "Export preset" in the ".presetsactions" "css_element"
And I should not see "Publish preset on this site" in the ".presetsactions" "css_element"
Scenario: The tertiary navigation in the Presets preview page.
Given I navigate to "Presets" in current page administration
When I follow "Saved preset by teacher1"
Then I should see "Preview of Saved preset by teacher1"
And "Use this preset" "button" should exist
# Single view
And I set the field "Templates tertiary navigation" to "Single view template"
And I should see "Preview of Saved preset by teacher1"
And "Use this preset" "button" should exist
@javascript
Scenario: The tertiary navigation in the Fields page.
Given I navigate to "Fields" in current page administration
When I open the action menu in "field1" "table_row"
Then I should see "Edit"
And I should see "Delete"
And I press the escape key
And I should not see "Actions"
@javascript
Scenario: The tertiary navigation in the Templates page.
Given I navigate to "Templates" in current page administration
When I click on "Actions" "button"
Then I should see "Export preset" in the ".presetsactions" "css_element"
And I should see "Publish preset on this site" in the ".presetsactions" "css_element"
And I press the escape key
And I should see "Add entry template"
# List template.
And I set the field "Templates tertiary navigation" to "List view template"
And I should not see "Add entry template"
And I should see "Header"
And I should see "Repeated entry"
And I should see "Footer"

View File

@ -1,71 +0,0 @@
@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

@ -64,13 +64,13 @@ Feature: Users can view and search database entries
And I select "List view" from the "jump" singleselect
And I click on "Advanced search" "checkbox"
And I set the field "Test field name" to "Student entry 1"
And I press "Save settings"
And I click on "Save settings" "button" in the "data_adv_form" "region"
And I should see "Student entry 1"
And I should not see "Student entry 2"
And I should not see "Student entry 3"
And I set the field "Test field name" to "Student entry"
And I set the field "Order" to "Descending"
And I press "Save settings"
And I click on "Save settings" "button" in the "data_adv_form" "region"
And "Student entry 3" "text" should appear before "Student entry 2" "text"
And "Student entry 2" "text" should appear before "Student entry 1" "text"
@ -99,7 +99,7 @@ Feature: Users can view and search database entries
And I click on "Advanced search" "checkbox"
And I set the field with xpath "//div[@class='datatagcontrol']//input[@type='text']" to "Tag1"
And I click on "[data-value='Tag1']" "css_element"
When I press "Save settings"
When I click on "Save settings" "button" in the "data_adv_form" "region"
Then I should see "Student original entry tagged"
And I should see "Student original entry tagged 2"
And I should not see "Student original entry untagged"
@ -122,14 +122,29 @@ Feature: Users can view and search database entries
When I am on the "Test database name" "data activity" page logged in as teacher1
And I click on "Advanced search" "checkbox"
And I set the field "First name" to "Bob"
And I press "Save settings"
Then I should see "Student entry 1"
And I click on "Save settings" "button" in the "data_adv_form" "region"
Then I should see "Found 1 out of 2 records."
And I should see "Student entry 1"
And I should not see "Student entry 2"
And I set the field "First name" to ""
And I set the field "Last name" to "2"
And I press "Save settings"
And I click on "Save settings" "button" in the "data_adv_form" "region"
And I should see "Found 1 out of 2 records."
And I should not see "Student entry 1"
And I should see "Student entry 2"
# Search: no records found.
But I set the field "Last name" to ""
And I set the field "Test field name" to "Student entry 0"
And I click on "Save settings" "button" in the "data_adv_form" "region"
And I should see "No records found."
And I should not see "Student entry 1"
And I should not see "Student entry 2"
# Search all the entries.
And I set the field "Test field name" to "Student entry"
And I click on "Save settings" "button" in the "data_adv_form" "region"
And I should not see "Found 2 out of 2 records."
And I should see "Student entry 1"
And I should see "Student entry 2"
@javascript
Scenario: Database entries can be deleted in batch if delcheck is present
@ -139,6 +154,7 @@ Feature: Users can view and search database entries
| data1 | teacher1 | Teacher entry 2 | Some teacher content 2 | http://moodle.com |
And I am on the "Test database name" "data activity" page logged in as teacher1
And I navigate to "Templates" in current page administration
And I set the field "Templates tertiary navigation" to "List view template"
And I set the following fields to these values:
| Repeated entry | ##delcheck##[[Test field name]]! |
And I click on "Save" "button" in the "sticky-footer" "region"

View File

@ -55,3 +55,13 @@ Feature: Zero state page (no fields created)
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."
@javascript
Scenario: Teacher can use a preset from zero state page on an empty database
Given I am on the "Test database name" "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 this preset" "button" should be enabled
Then I click on "Use this preset" "button"
And I should not see "Field mappings"
And I should see "Image" in the "image" "table_row"

View File

@ -544,4 +544,69 @@ class manager_test extends \advanced_testcase {
],
];
}
/**
* Test for can_export_entries().
*
* @covers ::can_export_entries
*/
public function test_can_export_entries() {
global $DB;
$this->resetAfterTest();
// Create course with activity and enrol users.
$course = $this->getDataGenerator()->create_course();
$teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
$activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
$cm = get_coursemodule_from_id(manager::MODULE, $activity->cmid, 0, false, MUST_EXIST);
$manager = manager::create_from_coursemodule($cm);
// Add a field.
/** @var \mod_data_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
$fieldrecord = (object)[
'name' => 'myfield',
'type' => 'text',
];
$field = $generator->create_field($fieldrecord, $activity);
// Teacher with default capabilities can export entries.
$this->setUser($teacher);
$result = $manager->can_export_entries();
$this->assertEquals(true, $result);
// Teacher without exportallentries can still export entries.
unassign_capability('mod/data:exportallentries', $teacherrole->id);
$result = $manager->can_export_entries();
$this->assertEquals(true, $result);
// Teacher without exportallentries and exportentry can't export entries (unless they have created some entries).
unassign_capability('mod/data:exportentry', $teacherrole->id);
$result = $manager->can_export_entries();
$this->assertEquals(false, $result);
$generator->create_entry(
$activity,
[$field->field->id => 'Example entry'],
);
$result = $manager->can_export_entries();
$this->assertEquals(true, $result);
// Student without entries can't export.
$this->setUser($student);
$result = $manager->can_export_entries();
$this->assertEquals(false, $result);
// However, student who has created any entry, can export.
$generator->create_entry(
$activity,
[$field->field->id => 'Another example entry'],
);
$this->setUser($student);
$result = $manager->can_export_entries();
$this->assertEquals(true, $result);
}
}

View File

@ -24,6 +24,15 @@ information provided here is intended especially for developers.
* import_setting_mappings() function has been deprecated. Use importing_preset() instead.
* $fieldselect single_select type parameter has been deprecated for fields_action_bar class constructor, and a new action_menu
type parameter has been added.
* The $urlselect, $saveaspresetbutton and $exportpresetbutton parameters in the constructor of the fields_action_bar class
have been deprecated too and are not used anymore.
* The $saveaspresetbutton and $exportpresetbutton parameters in the constructor of the templates_action_bar class
have been deprecated and are not used anymore. Besides, a new parameter, $actionsselect, has been added to the
constructor of this class.
* A new parameter, $actionsselect, has been added to the presets_action_bar constructor.
* A new parameter, $mode, has been added to the view_action_bar constructor.
* The $hassaveaspreset and $haveexportpreset parameters in the get_fields_action_bar() action_bar class have been deprecated and
are not used anymore.
=== 3.7 ===
* External functions get_entries, get_entry and search_entries now return an additional field "tags" containing the entry tags.

View File

@ -396,7 +396,7 @@ if ($showactivity) {
}
$actionbar = new \mod_data\output\action_bar($data->id, $pageurl);
echo $actionbar->get_view_action_bar($hasrecords);
echo $actionbar->get_view_action_bar($hasrecords, $mode);
if ($groupmode) {
$returnurl = new moodle_url('/mod/data/view.php', ['d' => $data->id, 'mode' => $mode, 'search' => s($search),
@ -414,9 +414,13 @@ if ($showactivity) {
$a = new stdClass();
$a->max = $maxcount;
$a->reseturl = "view.php?id=$cm->id&amp;mode=$mode&amp;search=&amp;advanced=0";
echo $OUTPUT->notification(get_string('foundnorecords','data', $a));
echo $OUTPUT->box_start();
echo get_string('foundnorecords', 'data', $a);
echo $OUTPUT->box_end();
} else {
echo $OUTPUT->notification(get_string('norecords','data'));
echo $OUTPUT->box_start();
echo get_string('norecords', 'data');
echo $OUTPUT->box_end();
}
} else {
@ -429,7 +433,9 @@ if ($showactivity) {
$a->num = $totalcount;
$a->max = $maxcount;
$a->reseturl = "view.php?id=$cm->id&amp;mode=$mode&amp;search=&amp;advanced=0";
echo $OUTPUT->notification(get_string('foundrecords', 'data', $a), 'notifysuccess');
echo $OUTPUT->box_start();
echo get_string('foundrecords', 'data', $a);
echo $OUTPUT->box_end();
}
if ($mode == 'single') { // Single template
@ -443,6 +449,7 @@ if ($showactivity) {
}
$baseurl = new moodle_url($baseurl, $baseurlparams);
echo $OUTPUT->box_start('', 'data-singleview-content');
require_once($CFG->dirroot.'/rating/lib.php');
if ($data->assessed != RATING_AGGREGATE_NONE) {
$ratingoptions = new stdClass;
@ -468,6 +475,7 @@ if ($showactivity) {
];
$parser = $manager->get_template('singletemplate', $options);
echo $parser->parse_entries($records);
echo $OUTPUT->box_end();
} else {
// List template.
$baseurl = '/mod/data/view.php';
@ -477,6 +485,7 @@ if ($showactivity) {
}
$baseurl = new moodle_url($baseurl, $baseurlparams);
echo $OUTPUT->box_start('', 'data-listview-content');
echo $data->listtemplateheader;
$options = [
'search' => $search,
@ -487,6 +496,7 @@ if ($showactivity) {
echo $parser->parse_entries($records);
echo $data->listtemplatefooter;
echo $OUTPUT->box_end();
}
$stickyfooter = new mod_data\output\view_footer(
@ -507,27 +517,6 @@ if ($showactivity) {
if (empty($records)) {
$records = array();
}
// Check to see if we can export records to a portfolio. This is for exporting all records, not just the ones in the search.
if ($mode == '' && !empty($CFG->enableportfolios) && !empty($records)) {
$canexport = false;
// Exportallentries and exportentry are basically the same capability.
if (has_capability('mod/data:exportallentries', $context) || has_capability('mod/data:exportentry', $context)) {
$canexport = true;
} else if (has_capability('mod/data:exportownentry', $context) &&
$DB->record_exists('data_records', array('userid' => $USER->id))) {
$canexport = true;
}
if ($canexport) {
require_once($CFG->libdir . '/portfoliolib.php');
$button = new portfolio_add_button();
$button->set_callback_options('data_portfolio_caller', array('id' => $cm->id), 'mod_data');
if (data_portfolio_caller::has_files($data)) {
$button->set_formats(array(PORTFOLIO_FORMAT_RICHHTML, PORTFOLIO_FORMAT_LEAP2A)); // No plain html for us.
}
echo $button->to_html(PORTFOLIO_ADD_FULL_FORM);
}
}
}
echo $OUTPUT->footer();