MDL-75335 mod_data: Zero state for Fields and Templates

This commit is contained in:
Amaia Anabitarte 2022-10-25 16:04:15 +02:00
parent 32c8f75c0d
commit ab97d41644
25 changed files with 266 additions and 120 deletions

View File

@ -4569,6 +4569,19 @@ class action_menu implements renderable, templatable {
} }
} }
/**
* Add classes to the action menu for an easier styling.
*
* @param string $class The class to add to attributes.
*/
public function set_additional_classes(string $class = '') {
if (!empty($this->attributes['class'])) {
$this->attributes['class'] .= " ".$class;
} else {
$this->attributes['class'] = $class;
}
}
/** /**
* Export for template. * Export for template.
* *

View File

@ -12,9 +12,6 @@ Declaration is as follow:
* coursemodinfo cache uses the new `requirelockingbeforewrite` option, and rebuilding the cache now uses the cache lock API, rather * coursemodinfo cache uses the new `requirelockingbeforewrite` option, and rebuilding the cache now uses the cache lock API, rather
than using the core lock factory directly. This allows the locks to be stored locally if the cache is stored locally, and than using the core lock factory directly. This allows the locks to be stored locally if the cache is stored locally, and
avoids the risk of delays and timeouts when multiple nodes need to rebuild the cache locally, but are waiting for a central lock. avoids the risk of delays and timeouts when multiple nodes need to rebuild the cache locally, but are waiting for a central lock.
=== 4.1 ===
* Final deprecation and removal of the class \admin_setting_managelicenses, please use \tool_licensemanager\manager instead. * Final deprecation and removal of the class \admin_setting_managelicenses, please use \tool_licensemanager\manager instead.
* Final deprecation and removal of the function license_manager::add(). Please use license_manager::save() instead. * Final deprecation and removal of the function license_manager::add(). Please use license_manager::save() instead.
* Final deprecation of the following functions behat_field_manager::get_node_type() and behat_field_manager::get_field() * Final deprecation of the following functions behat_field_manager::get_node_type() and behat_field_manager::get_field()
@ -60,6 +57,7 @@ Declaration is as follow:
* The function get_module_metadata() has been finally deprecated and can not be used anymore. * The function get_module_metadata() has been finally deprecated and can not be used anymore.
* New DML driver method `$DB->sql_order_by_null` for sorting nulls sort nulls first when ascending and last when descending. * New DML driver method `$DB->sql_order_by_null` for sorting nulls sort nulls first when ascending and last when descending.
* Allow plugins to callback on all pages just prior to the session start. * Allow plugins to callback on all pages just prior to the session start.
* New function set_additional_classes() has been implemented to add additional classes to action_menu.
=== 4.0 === === 4.0 ===

View File

@ -301,6 +301,19 @@ class manager {
return new template($this, $templatecontent, $options); return new template($this, $templatecontent, $options);
} }
/** Check if the user can manage templates on the current context.
*
* @param int $userid the user id to check ($USER->id if null).
* @return bool if the user can manage templates on current context.
*/
public function can_manage_templates(?int $userid = null): bool {
global $USER;
if (!$userid) {
$userid = $USER->id;
}
return has_capability('mod/data:managetemplates', $this->context, $userid);
}
/** /**
* Update the database templates. * Update the database templates.
* *

View File

@ -54,8 +54,11 @@ class action_bar {
* @param bool $hasexportpreset Whether the export as preset button element should be rendered. * @param bool $hasexportpreset Whether the export as preset button element should be rendered.
* @return string The HTML code for the action bar. * @return string The HTML code for the action bar.
*/ */
public function get_fields_action_bar(bool $hasfieldselect = false, bool $hassaveaspreset = false, public function get_fields_action_bar(
bool $hasexportpreset = false): string { bool $hasfieldselect = false,
bool $hassaveaspreset = false,
bool $hasexportpreset = false
): string {
global $PAGE, $DB; global $PAGE, $DB;
$createfieldlink = new moodle_url('/mod/data/field.php', ['d' => $this->id]); $createfieldlink = new moodle_url('/mod/data/field.php', ['d' => $this->id]);
@ -70,19 +73,7 @@ class action_bar {
$fieldselect = null; $fieldselect = null;
if ($hasfieldselect) { if ($hasfieldselect) {
// Get the list of possible fields (plugins). $fieldselect = $this->get_create_fields();
$plugins = \core_component::get_plugin_list('datafield');
$menufield = [];
foreach ($plugins as $plugin => $fulldir) {
$menufield[$plugin] = get_string('pluginname', "datafield_{$plugin}");
}
asort($menufield);
$fieldselecturl = new moodle_url('/mod/data/field.php', ['d' => $this->id, 'mode' => 'new']);
$fieldselect = new \single_select($fieldselecturl, 'newtype', $menufield, null, get_string('newfield', 'data'),
'fieldform');
$fieldselect->set_label(get_string('newfield', 'mod_data'), ['class' => 'sr-only']);
} }
$saveaspresetbutton = null; $saveaspresetbutton = null;
@ -105,12 +96,43 @@ class action_bar {
} }
} }
$renderer = $PAGE->get_renderer('mod_data'); $renderer = $PAGE->get_renderer('mod_data');
$fieldsactionbar = new fields_action_bar($this->id, $urlselect, $fieldselect, $saveaspresetbutton, $fieldsactionbar = new fields_action_bar($this->id, $urlselect, null, $saveaspresetbutton,
$exportpresetbutton); $exportpresetbutton, $fieldselect);
return $renderer->render_fields_action_bar($fieldsactionbar); return $renderer->render_fields_action_bar($fieldsactionbar);
} }
/**
* Generate the output for the create a new field action menu.
*
* @return \action_menu Action menu to create a new field
*/
public function get_create_fields(): \action_menu {
// Get the list of possible fields (plugins).
$plugins = \core_component::get_plugin_list('datafield');
$menufield = [];
foreach ($plugins as $plugin => $fulldir) {
$menufield[$plugin] = get_string('pluginname', "datafield_{$plugin}");
}
asort($menufield);
$fieldselect = new \action_menu();
$fieldselect->set_menu_trigger(get_string('newfield', 'mod_data'), 'btn btn-secondary');
$fieldselectparams = ['d' => $this->id, 'mode' => 'new'];
foreach ($menufield as $fieldtype => $fieldname) {
$fieldselectparams['newtype'] = $fieldtype;
$fieldselect->add(new \action_menu_link(
new \moodle_url('/mod/data/field.php', $fieldselectparams),
new \pix_icon('field/' . $fieldtype, $fieldname, 'data'),
$fieldname,
false
));
}
$fieldselect->set_additional_classes('singlebutton');
return $fieldselect;
}
/** /**
* Generate the output for the action selector in the view page. * Generate the output for the action selector in the view page.
* *

View File

@ -48,12 +48,19 @@ class fields_action_bar implements templatable, renderable {
* *
* @param int $id The database module id * @param int $id The database module id
* @param \url_select $urlselect The URL selector object * @param \url_select $urlselect The URL selector object
* @param \single_select|null $fieldselect The field selector object or null * @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 $saveaspresetbutton The save as preset single button object or null
* @param \single_button|null $exportpresetbutton The export preset single button object or null * @param \single_button|null $exportpresetbutton The export preset single button object or null
* @param \action_menu|null $fieldselect The field selector object or null
*/ */
public function __construct(int $id, \url_select $urlselect, ?\single_select $fieldselect = null, public function __construct(int $id, \url_select $urlselect, $unused = null,
?\single_button $saveaspresetbutton = null, ?\single_button $exportpresetbutton = null) { ?\single_button $saveaspresetbutton = null, ?\single_button $exportpresetbutton = null,
?\action_menu $fieldselect = null) {
if ($unused !== null) {
debugging('Deprecated argument passed to fields_action_bar constructor', DEBUG_DEVELOPER);
}
$this->id = $id; $this->id = $id;
$this->urlselect = $urlselect; $this->urlselect = $urlselect;
$this->fieldselect = $fieldselect; $this->fieldselect = $fieldselect;

View File

@ -52,7 +52,7 @@ class zero_state_action_bar implements templatable, renderable {
global $PAGE; global $PAGE;
$data = []; $data = [];
if (has_capability('mod/data:managetemplates', $PAGE->context)) { if ($this->manager->can_manage_templates()) {
$instance = $this->manager->get_instance(); $instance = $this->manager->get_instance();
$params = ['d' => $instance->id, 'backto' => $PAGE->url->out(false)]; $params = ['d' => $instance->id, 'backto' => $PAGE->url->out(false)];
@ -61,9 +61,8 @@ class zero_state_action_bar implements templatable, renderable {
get_string('usepreset', 'mod_data'), 'get', true); get_string('usepreset', 'mod_data'), 'get', true);
$data['usepresetbutton'] = $usepresetbutton->export_for_template($output); $data['usepresetbutton'] = $usepresetbutton->export_for_template($output);
$createfieldlink = new moodle_url('/mod/data/field.php', $params); $actionbar = new \mod_data\output\action_bar($instance->id, $PAGE->url);
$createfieldbutton = new \single_button($createfieldlink, $createfieldbutton = $actionbar->get_create_fields();
get_string('newfield', 'mod_data'), 'get', false);
$data['createfieldbutton'] = $createfieldbutton->export_for_template($output); $data['createfieldbutton'] = $createfieldbutton->export_for_template($output);
$params['action'] = 'import'; $params['action'] = 'import';

View File

@ -74,7 +74,7 @@ if (isguestuser()) {
} }
/// Can't use this if there are no fields /// Can't use this if there are no fields
if (has_capability('mod/data:managetemplates', $context)) { if ($manager->can_manage_templates()) {
if (!$manager->has_fields()) { if (!$manager->has_fields()) {
redirect($CFG->wwwroot.'/mod/data/field.php?d='.$data->id); // Redirect to field entry. redirect($CFG->wwwroot.'/mod/data/field.php?d='.$data->id); // Redirect to field entry.
} }

View File

@ -333,75 +333,79 @@ if (($mode == 'new') && (!empty($newtype))) { // Adding a new field.
$field->display_edit_field(); $field->display_edit_field();
} else { /// Display the main listing of all fields } else { /// Display the main listing of all fields
$hasfields = $manager->has_fields();
// Check if it is an empty database with no fields.
if (!$hasfields) {
$PAGE->set_title($data->name);
echo $OUTPUT->header();
echo $renderer->render_fields_zero_state($manager);
echo $OUTPUT->footer();
// 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, true, true);
data_print_header($course, $cm, $data, 'fields', $fieldactionbar); data_print_header($course, $cm, $data, 'fields', $fieldactionbar);
echo $OUTPUT->heading(get_string('managefields', 'data'), 2, 'mb-4'); echo $OUTPUT->heading(get_string('managefields', 'data'), 2, 'mb-4');
if (!$DB->record_exists('data_fields', array('dataid'=>$data->id))) { $table = new html_table();
echo $OUTPUT->notification(get_string('nofieldindatabase','data')); // nothing in database $table->head = [
echo $OUTPUT->notification(get_string('pleaseaddsome','data', 'preset.php?id='.$cm->id)); // link to presets 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];
} else { //else print quiz style list of fields $fieldrecords = $manager->get_field_records();
$missingfieldtypes = [];
foreach ($fieldrecords as $fieldrecord) {
$table = new html_table(); $field = data_get_field($fieldrecord, $data);
$table->head = array(
get_string('fieldname', 'data'),
get_string('type', 'data'),
get_string('required', 'data'),
get_string('fielddescription', 'data'),
get_string('action', 'data'),
);
$table->align = array('left', 'left', 'left', 'left');
$table->wrap = array(false,false,false,false);
if ($fff = $DB->get_records('data_fields', array('dataid'=>$data->id),'id')){ $baseurl = new moodle_url('/mod/data/field.php', array(
$missingfieldtypes = []; 'd' => $data->id,
foreach ($fff as $ff) { 'fid' => $field->field->id,
'sesskey' => sesskey(),
));
$field = data_get_field($ff, $data); $displayurl = new moodle_url($baseurl, array(
'mode' => 'display',
));
$baseurl = new moodle_url('/mod/data/field.php', array( $deleteurl = new moodle_url($baseurl, array(
'd' => $data->id, 'mode' => 'delete',
'fid' => $field->field->id, ));
'sesskey' => sesskey(),
));
$displayurl = new moodle_url($baseurl, array( // It display a notification when the field type does not exist.
'mode' => 'display', $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') {
$deleteurl = new moodle_url($baseurl, array( $missingfieldtypes[] = $field->field->name;
'mode' => 'delete', $fieldnamedata = $field->field->name;
)); $fieltypedata = $field->field->type;
$fieldlinkdata = $deletelink;
// It display a notification when the field type does not exist. } else {
$deletelink = html_writer::link($deleteurl, $OUTPUT->pix_icon('t/delete', get_string('delete'))); $fieldnamedata = html_writer::link($displayurl, $field->field->name);
$editlink = html_writer::link($displayurl, $OUTPUT->pix_icon('t/edit', get_string('edit'))); $fieltypedata = $field->image() . ' ' . $field->name();
if ($field->type === 'unknown') { $fieldlinkdata = $editlink . ' ' . $deletelink;
$missingfieldtypes[] = $field->field->name; }
$fieldnamedata = $field->field->name;
$fieltypedata = $field->field->type; $table->data[] = [
$fieldlinkdata = $deletelink; $fieldnamedata,
} else { $fieltypedata,
$fieldnamedata = html_writer::link($displayurl, $field->field->name); $field->field->required ? get_string('yes') : get_string('no'),
$fieltypedata = $field->image() . ' ' . $field->name(); shorten_text($field->field->description, 30),
$fieldlinkdata = $editlink . ' ' . $deletelink; $fieldlinkdata
} ];
$table->data[] = [ if (!empty($missingfieldtypes)) {
$fieldnamedata, echo $OUTPUT->notification(get_string('missingfieldtypes', 'data') . html_writer::alist($missingfieldtypes));
$fieltypedata,
$field->field->required ? get_string('yes') : get_string('no'),
shorten_text($field->field->description, 30),
$fieldlinkdata
];
}
if (!empty($missingfieldtypes)) {
echo $OUTPUT->notification(get_string('missingfieldtypes', 'data') . html_writer::alist($missingfieldtypes));
}
} }
echo html_writer::table($table);
} }
echo html_writer::table($table);
echo '<div class="sortdefault">'; echo '<div class="sortdefault">';
echo '<form id="sortdefault" action="'.$CFG->wwwroot.'/mod/data/field.php" method="get">'; echo '<form id="sortdefault" action="'.$CFG->wwwroot.'/mod/data/field.php" method="get">';

View File

@ -78,7 +78,9 @@ $string['configenablerssfeeds'] = 'This switch will enable the possibility of RS
$string['confirmdeletefield'] = 'You are about to delete this field, are you sure?'; $string['confirmdeletefield'] = 'You are about to delete this field, are you sure?';
$string['confirmdeleterecord'] = 'Are you sure you want to delete this entry?'; $string['confirmdeleterecord'] = 'Are you sure you want to delete this entry?';
$string['confirmdeleterecords'] = 'Are you sure you want to delete these entries?'; $string['confirmdeleterecords'] = 'Are you sure you want to delete these entries?';
$string['createfields'] = 'Create your own fields to collect data, or use a preset which includes fields already.'; $string['createactivity'] = 'Create your own fields to collect data, or use a preset which includes fields already.';
$string['createfields'] = 'Create fields to collect different types of data.';
$string['createtemplates'] = 'Create fields for your activity to generate a template, or import a preset with existing fields and templates.';
$string['csstemplate'] = 'CSS template'; $string['csstemplate'] = 'CSS template';
$string['csvfailed'] = 'Unable to read the raw data from the CSV file'; $string['csvfailed'] = 'Unable to read the raw data from the CSV file';
$string['csvfile'] = 'CSV file'; $string['csvfile'] = 'CSV file';
@ -291,7 +293,7 @@ $string['multientry'] = 'Repeated entry';
$string['multimenu'] = 'Menu (Multi-select)'; $string['multimenu'] = 'Menu (Multi-select)';
$string['multipletags'] = 'Multiple tags found! Template not saved'; $string['multipletags'] = 'Multiple tags found! Template not saved';
$string['newentry'] = 'New entry'; $string['newentry'] = 'New entry';
$string['newfield'] = 'Create a new field'; $string['newfield'] = 'Create a field';
$string['newfield_help'] = 'A field allows the input of data. Each entry in a database activity can have multiple fields of multiple types such as a date field, which allows participants to select a day, month and year from a drop-down menu, a picture field, which allows participants to upload an image file, or a checkbox field, which allows participants to select one or more options. $string['newfield_help'] = 'A field allows the input of data. Each entry in a database activity can have multiple fields of multiple types such as a date field, which allows participants to select a day, month and year from a drop-down menu, a picture field, which allows participants to upload an image file, or a checkbox field, which allows participants to select one or more options.
Each field must have a unique field name. The field description is optional.'; Each field must have a unique field name. The field description is optional.';
@ -299,6 +301,8 @@ $string['noaccess'] = 'You do not have access to this page';
$string['nodefinedfields'] = 'New preset has no defined fields!'; $string['nodefinedfields'] = 'New preset has no defined fields!';
$string['nofieldcontent'] = 'Field content not found'; $string['nofieldcontent'] = 'Field content not found';
$string['nofieldindatabase'] = 'There are no fields defined for this database.'; $string['nofieldindatabase'] = 'There are no fields defined for this database.';
$string['nofields'] = 'No fields yet';
$string['nolisttemplate'] = 'List template is not yet defined';
$string['nomatch'] = 'No matching entries found!'; $string['nomatch'] = 'No matching entries found!';
$string['nomaximum'] = 'No maximum'; $string['nomaximum'] = 'No maximum';
$string['nopreviewavailable'] = 'No preview available for {$a}'; $string['nopreviewavailable'] = 'No preview available for {$a}';
@ -306,6 +310,7 @@ $string['norecords'] = 'No entries yet';
$string['notapproved'] = 'Pending approval'; $string['notapproved'] = 'Pending approval';
$string['notapprovederror'] = 'Entry is not approved yet.'; $string['notapprovederror'] = 'Entry is not approved yet.';
$string['notinjectivemap'] = 'Not an injective map'; $string['notinjectivemap'] = 'Not an injective map';
$string['notemplates'] = 'Not templates yet';
$string['notopenyet'] = 'Sorry, this activity is not available until {$a}'; $string['notopenyet'] = 'Sorry, this activity is not available until {$a}';
$string['number'] = 'Number'; $string['number'] = 'Number';
$string['numberrssarticles'] = 'Entries in the RSS feed'; $string['numberrssarticles'] = 'Entries in the RSS feed';
@ -323,7 +328,6 @@ $string['page-mod-data-x'] = 'Any database activity module page';
$string['pagesize'] = 'Entries per page'; $string['pagesize'] = 'Entries per page';
$string['participants'] = 'Participants'; $string['participants'] = 'Participants';
$string['picture'] = 'Picture'; $string['picture'] = 'Picture';
$string['pleaseaddsome'] = 'Please create some below or <a href="{$a}">choose a predefined set</a> to get started.';
$string['pluginadministration'] = 'Database activity administration'; $string['pluginadministration'] = 'Database activity administration';
$string['pluginname'] = 'Database'; $string['pluginname'] = 'Database';
$string['portfolionotfile'] = 'Export to a portfolio rather than a file (csv and leap2a only)'; $string['portfolionotfile'] = 'Export to a portfolio rather than a file (csv and leap2a only)';
@ -455,6 +459,7 @@ $string['unsupportedexport'] = '({$a->fieldtype}) cannot be exported.';
$string['buttons'] = 'Actions'; $string['buttons'] = 'Actions';
$string['nolisttemplate'] = 'List template is not yet defined'; $string['nolisttemplate'] = 'List template is not yet defined';
$string['nosingletemplate'] = 'Single template is not yet defined'; $string['nosingletemplate'] = 'Single 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['blank'] = 'Blank';
$string['savetemplate'] = 'Save template'; $string['savetemplate'] = 'Save template';
$string['addedby'] = 'Added by'; $string['addedby'] = 'Added by';

View File

@ -2,6 +2,7 @@ unsupportedexport,mod_data
buttons,mod_data buttons,mod_data
nosingletemplate,mod_data nosingletemplate,mod_data
nolisttemplate,mod_data nolisttemplate,mod_data
pleaseaddsome,mod_data
blank,mod_data blank,mod_data
savetemplate,mod_data savetemplate,mod_data
addedby,mod_data addedby,mod_data

View File

@ -154,6 +154,9 @@ class mod_data_renderer extends plugin_renderer_base {
*/ */
public function render_fields_action_bar(\mod_data\output\fields_action_bar $actionbar): string { public function render_fields_action_bar(\mod_data\output\fields_action_bar $actionbar): string {
$data = $actionbar->export_for_template($this); $data = $actionbar->export_for_template($this);
$data['title'] = get_string('nofields', 'mod_data');
$data['intro'] = get_string('createfields', 'mod_data');
$data['noitemsimgurl'] = $this->output->image_url('nofields', 'mod_data')->out();
return $this->render_from_template('mod_data/fields_action_bar', $data); return $this->render_from_template('mod_data/fields_action_bar', $data);
} }
@ -233,7 +236,7 @@ class mod_data_renderer extends plugin_renderer_base {
* *
* @return string The HTML output * @return string The HTML output
*/ */
public function render_zero_state(\mod_data\manager $manager): string { public function render_database_zero_state(\mod_data\manager $manager): string {
$actionbar = new \mod_data\output\zero_state_action_bar($manager); $actionbar = new \mod_data\output\zero_state_action_bar($manager);
$data = $actionbar->export_for_template($this); $data = $actionbar->export_for_template($this);
if (empty($data)) { if (empty($data)) {
@ -242,7 +245,7 @@ class mod_data_renderer extends plugin_renderer_base {
$data['intro'] = get_string('comebacklater'); $data['intro'] = get_string('comebacklater');
} else { } else {
$data['title'] = get_string('startbuilding', 'mod_data'); $data['title'] = get_string('startbuilding', 'mod_data');
$data['intro'] = get_string('createfields', 'mod_data'); $data['intro'] = get_string('createactivity', 'mod_data');
} }
$data['noitemsimgurl'] = $this->output->image_url('nofields', 'mod_data')->out(); $data['noitemsimgurl'] = $this->output->image_url('nofields', 'mod_data')->out();
@ -263,4 +266,43 @@ class mod_data_renderer extends plugin_renderer_base {
return $this->render_from_template('mod_data/view_noentries', $data); return $this->render_from_template('mod_data/view_noentries', $data);
} }
/**
* Renders the action bar for the zero state (no fields created) page.
*
* @param \mod_data\manager $manager The manager instance.
*
* @return string The HTML output
*/
public function render_fields_zero_state(\mod_data\manager $manager): string {
$data = [
'noitemsimgurl' => $this->output->image_url('nofields', 'mod_data')->out(),
'title' => get_string('nofields', 'mod_data'),
'intro' => get_string('createfields', 'mod_data'),
];
if ($manager->can_manage_templates()) {
$actionbar = new \mod_data\output\action_bar($manager->get_instance()->id, $this->page->url);
$createfieldbutton = $actionbar->get_create_fields();
$data['createfieldbutton'] = $createfieldbutton->export_for_template($this);
}
return $this->render_from_template('mod_data/zero_state', $data);
}
/**
* Renders the action bar for the templates zero state (no fields created) page.
*
* @param \mod_data\manager $manager The manager instance.
*
* @return string The HTML output
*/
public function render_templates_zero_state(\mod_data\manager $manager): string {
$actionbar = new \mod_data\output\zero_state_action_bar($manager);
$data = $actionbar->export_for_template($this);
$data['title'] = get_string('notemplates', 'mod_data');
$data['intro'] = get_string('createtemplates', 'mod_data');
$data['noitemsimgurl'] = $this->output->image_url('nofields', 'mod_data')->out();
return $this->render_from_template('mod_data/zero_state', $data);
}
} }

View File

@ -188,3 +188,11 @@
.template-preview-content .data-field-html button { .template-preview-content .data-field-html button {
pointer-events: none; pointer-events: none;
} }
#page-mod-data-view .whitebutton .btn-secondary,
#page-mod-data-field- .whitebutton .btn-secondary,
#page-mod-data-templates .whitebutton .btn-secondary {
background: white;
border-color: var(--primary);
color: var(--primary);
}

View File

@ -56,11 +56,6 @@ $PAGE->set_url($url);
require_login($course, false, $cm); require_login($course, false, $cm);
require_capability('mod/data:managetemplates', $context); require_capability('mod/data:managetemplates', $context);
// Check if it is an empty database.
if (count($manager->get_field_records()) == 0) {
redirect($CFG->wwwroot.'/mod/data/field.php?d='.$instance->id);
}
$manager->set_template_viewed(); $manager->set_template_viewed();
if ($useeditor !== null) { if ($useeditor !== null) {
@ -78,6 +73,15 @@ $PAGE->add_body_class('limitedwidth');
echo $OUTPUT->header(); echo $OUTPUT->header();
$renderer = $manager->get_renderer();
// Check if it is an empty database with no fields.
if (!$manager->has_fields()) {
echo $renderer->render_templates_zero_state($manager);
echo $OUTPUT->footer();
// Don't check the rest of the options. There is no field, there is nothing else to work with.
exit;
}
$actionbar = new \mod_data\output\action_bar($instance->id, $url); $actionbar = new \mod_data\output\action_bar($instance->id, $url);
echo $actionbar->get_templates_action_bar(); echo $actionbar->get_templates_action_bar();
@ -104,7 +108,6 @@ if (($formdata = data_submitted()) && confirm_sesskey()) {
} }
} }
$renderer = $manager->get_renderer();
$templateeditor = new \mod_data\output\template_editor($manager, $mode); $templateeditor = new \mod_data\output\template_editor($manager, $mode);
echo $renderer->render($templateeditor); echo $renderer->render($templateeditor);

View File

@ -87,11 +87,6 @@
{{>core/url_select}} {{>core/url_select}}
</div> </div>
{{/urlselect}} {{/urlselect}}
{{#fieldselect}}
<div class='navitem fieldadd'>
{{>core/single_select}}
</div>
{{/fieldselect}}
</div> </div>
<div class="ml-sm-auto d-flex"> <div class="ml-sm-auto d-flex">
{{#saveaspreset}} {{#saveaspreset}}
@ -104,6 +99,9 @@
{{>core/single_button}} {{>core/single_button}}
</div> </div>
{{/exportpreset}} {{/exportpreset}}
{{#fieldselect}}
{{>core/action_menu}}
{{/fieldselect}}
</div> </div>
</div> </div>
</div> </div>

View File

@ -19,7 +19,7 @@
Context variables required for this template: Context variables required for this template:
* noitemsimgurl - The image url. * noitemsimgurl - The image url.
* importpresetbutton stdClass - Import preset single button to be rendered * importpresetbutton stdClass - Import preset single button to be rendered
* createfieldbutton stdClass - Create a new field single button to be rendered * createfieldbutton stdClass - Create a field action menu to be rendered
* usepresetbutton stdClass - Use a preset single button to be rendered * usepresetbutton stdClass - Use a preset single button to be rendered
Example context (json): Example context (json):
@ -77,15 +77,17 @@
style="height: 70px; width: 70px;" style="height: 70px; width: 70px;"
> >
<h5 class="h5 mt-3 mb-0">{{{ title }}}</h5> <h5 class="h5 mt-3 mb-0">{{{ title }}}</h5>
<p class="mt-3 mb-0">{{{ intro }}}</p> {{#intro}}
<p class="mt-3 mb-0">{{{ intro }}}</p>
{{/intro}}
<div class="mt-5 mb-0" id="action_bar"> <div class="mt-5 mb-0 whitebutton" id="action_bar">
{{#createfieldbutton}}
{{>core/action_menu}}
{{/createfieldbutton}}
{{#importpresetbutton}} {{#importpresetbutton}}
{{>core/single_button}} {{>core/single_button}}
{{/importpresetbutton}} {{/importpresetbutton}}
{{#createfieldbutton}}
{{>core/single_button}}
{{/createfieldbutton}}
{{#usepresetbutton}} {{#usepresetbutton}}
{{>core/single_button}} {{>core/single_button}}
{{/usepresetbutton}} {{/usepresetbutton}}

View File

@ -53,7 +53,10 @@ class behat_mod_data extends behat_base {
$fieldsstr = get_string('fields', 'mod_data'); $fieldsstr = get_string('fields', 'mod_data');
$this->execute("behat_navigation::i_navigate_to_in_current_page_administration", $fieldsstr); $this->execute("behat_navigation::i_navigate_to_in_current_page_administration", $fieldsstr);
$this->execute('behat_forms::i_set_the_field_to', array('newtype', $this->escape($fieldtype))); $this->execute('behat_general::i_click_on', [get_string('newfield', 'mod_data'), "button"]);
$this->execute('behat_general::i_click_on_in_the',
[$this->escape($fieldtype), "link", "#action_bar", "css_element"]
);
if (!$this->running_javascript()) { if (!$this->running_javascript()) {
$this->execute('behat_general::i_click_on_in_the', $this->execute('behat_general::i_click_on_in_the',

View File

@ -1,4 +1,4 @@
@mod @mod_data @core_completion @mod @mod_data @core_completion @javascript
Feature: View activity completion in the database activity Feature: View activity completion in the database activity
In order to have visibility of database completion requirements In order to have visibility of database completion requirements
As a student As a student
@ -77,7 +77,6 @@ Feature: View activity completion in the database activity
And I am on the "Music history" "data activity" page logged in as teacher1 And I am on the "Music history" "data activity" page logged in as teacher1
And I select "Single view" from the "jump" singleselect And I select "Single view" from the "jump" singleselect
And I set the field "rating" to "3" And I set the field "rating" to "3"
And I press "Rate"
And I log out And I log out
When I am on the "Music history" "data activity" page logged in as student1 When I am on the "Music history" "data activity" page logged in as student1

View File

@ -52,6 +52,7 @@ Feature: Completion pass grade
| Field name | Instrument types | | Field name | Instrument types |
And I log out And I log out
@javascript
Scenario: View automatic completion items as a teacher Scenario: View automatic completion items as a teacher
Given I am on the "Music history" "data activity" page logged in as teacher1 Given I am on the "Music history" "data activity" page logged in as teacher1
# We add an entry to let the user change to a different view. # We add an entry to let the user change to a different view.

View File

@ -140,6 +140,7 @@ Feature: Users can preview presets
And I click on "Image gallery" "link" And I click on "Image gallery" "link"
When I click on "Use a preset" "button" When I click on "Use a preset" "button"
Then I should see "image" Then I should see "image"
And I should see "image"
And I should see "title" And I should see "title"
@javascript @_file_upload @javascript @_file_upload

View File

@ -1,4 +1,4 @@
@mod @mod_data @mod @mod_data @javascript
Feature: Zero state page (no fields created) Feature: Zero state page (no fields created)
Background: Background:
@ -15,17 +15,45 @@ Feature: Zero state page (no fields created)
| activity | name | intro | course | idnumber | | activity | name | intro | course | idnumber |
| data | Test database name | n | C1 | data1 | | data | Test database name | n | C1 | data1 |
@javascript Scenario: Teachers see buttons to manage database when there is no field created on view page
Scenario: Teachers see buttons to manage database when there is no field created
Given I am on the "Test database name" "data activity" page logged in as "teacher1" Given I am on the "Test database name" "data activity" page logged in as "teacher1"
And "Import a preset" "button" should exist And "Import a preset" "button" should exist
When I click on "Import a preset" "button" When I click on "Import a preset" "button"
Then I should see "Import from zip file" Then I should see "Import from zip file"
And I am on the "Test database name" "data activity" page And I am on the "Test database name" "data activity" page
And "Create a new field" "button" should exist And "Create a field" "button" should exist
And I click on "Create a new field" "button" And I click on "Create a field" "button"
And I should see "Manage fields" And I click on "Short text" "link"
And I should see "Create a field"
And I am on the "Test database name" "data activity" page And I am on the "Test database name" "data activity" page
And "Use a preset" "button" should exist And "Use a preset" "button" should exist
And I click on "Use a preset" "button" And I click on "Use a preset" "button"
And I should see "Presets" And I should see "Presets"
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"
And I am on the "Test database name" "data activity" page
And I click on "Templates" "link"
And "Create a field" "button" should exist
And I click on "Create a field" "button"
And I click on "Short text" "link"
And I should see "Create a field"
And I am on the "Test database name" "data activity" page
And I click on "Templates" "link"
And "Use a preset" "button" should exist
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
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"

View File

@ -22,6 +22,8 @@ information provided here is intended especially for developers.
- data_preset_existing_importer - data_preset_existing_importer
- data_preset_upload_importer - data_preset_upload_importer
* import_setting_mappings() function has been deprecated. Use importing_preset() instead. * 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.
=== 3.7 === === 3.7 ===
* External functions get_entries, get_entry and search_entries now return an additional field "tags" containing the entry tags. * External functions get_entries, get_entry and search_entries now return an additional field "tags" containing the entry tags.

View File

@ -242,7 +242,7 @@ echo $OUTPUT->header();
if (!$manager->has_fields()) { if (!$manager->has_fields()) {
// It's a brand-new database. There are no fields. // It's a brand-new database. There are no fields.
$renderer = $manager->get_renderer(); $renderer = $manager->get_renderer();
echo $renderer->render_zero_state($manager); echo $renderer->render_database_zero_state($manager);
echo $OUTPUT->footer(); echo $OUTPUT->footer();
// Don't check the rest of the options. There is no field, there is nothing else to work with. // Don't check the rest of the options. There is no field, there is nothing else to work with.
exit; exit;

View File

@ -18,7 +18,6 @@ $thin-scroll-bg-hover: $gray-700 !default;
$font-size-xs: ($font-size-base * .75) !default; $font-size-xs: ($font-size-base * .75) !default;
#region-main { #region-main {
overflow-x: auto;
overflow-y: visible; overflow-y: visible;
background-color: $body-bg; background-color: $body-bg;
} }

View File

@ -9860,7 +9860,6 @@ a.text-dark:hover, a.text-dark:focus {
*/ */
/* core.less */ /* core.less */
#region-main { #region-main {
overflow-x: auto;
overflow-y: visible; overflow-y: visible;
background-color: #fff; } background-color: #fff; }

View File

@ -9860,7 +9860,6 @@ a.text-dark:hover, a.text-dark:focus {
*/ */
/* core.less */ /* core.less */
#region-main { #region-main {
overflow-x: auto;
overflow-y: visible; overflow-y: visible;
background-color: #fff; } background-color: #fff; }