From 599aca679b25a7dd9a0e910ded4d0533a11c7ebf Mon Sep 17 00:00:00 2001 From: Sara Arjona Date: Thu, 7 Jul 2022 17:16:33 +0200 Subject: [PATCH] MDL-75148 mod_data: Improve presets list page - Add a new help text. - Add captions to table columns. - Move action icons to action menu, and fix code to display the remove action only for presets created by users. - CSS improvements to fit the prototype. In order to achive the previous points, the renderer has been improved, to return the data and let the mustache to print it properly (instead of returning the formatted HTML table). --- mod/data/classes/output/presets.php | 57 ++++++++++------ mod/data/lang/en/data.php | 1 + mod/data/styles.css | 4 ++ mod/data/templates/presets.mustache | 55 +++++++++++++-- mod/data/tests/behat/data_presets.feature | 81 +++++++++++++++++++++++ 5 files changed, 174 insertions(+), 24 deletions(-) create mode 100644 mod/data/tests/behat/data_presets.feature diff --git a/mod/data/classes/output/presets.php b/mod/data/classes/output/presets.php index 2e0cf4de5cd1..7c1c6618b740 100644 --- a/mod/data/classes/output/presets.php +++ b/mod/data/classes/output/presets.php @@ -16,6 +16,8 @@ namespace mod_data\output; +use action_menu; +use action_menu_link_secondary; use moodle_url; use templatable; use renderable; @@ -64,54 +66,69 @@ public function __construct(int $id, array $presets, moodle_url $formactionurl, */ public function export_for_template(\renderer_base $output): array { + $presets = $this->get_presets(); return [ 'd' => $this->id, 'formactionul' => $this->formactionurl->out(), - 'presetstable' => $this->get_presets_table(), + 'showmanage' => $this->manage, + 'presets' => $presets, ]; } /** - * Generates and returns the HTML for the presets table. + * Returns the presets list with the information required to display them. * - * @return string + * @return array Presets list. */ - private function get_presets_table(): string { - global $OUTPUT, $PAGE, $DB; - - $presetstable = new \html_table(); - $presetstable->align = ['center', 'left', 'left']; - $presetstable->size = ['1%', '90%', '1%']; + private function get_presets(): array { + global $OUTPUT, $PAGE; + $presets = []; foreach ($this->presets as $preset) { $presetname = $preset->name; if (!empty($preset->userid)) { + // If the preset has the userid field, the full name of creator it will be added to the end of the name. $userfieldsapi = \core_user\fields::for_name(); $namefields = $userfieldsapi->get_sql('', false, '', '', false)->selects; - $presetuser = $DB->get_record('user', array('id' => $preset->userid), 'id, ' . $namefields, MUST_EXIST); + $fields = 'id, ' . $namefields; + $presetuser = \core_user::get_user($preset->userid, $fields, MUST_EXIST); $username = fullname($presetuser, true); $presetname = "{$presetname} ({$username})"; } - $deleteaction = ''; + $actions = []; if ($this->manage) { - if (data_user_can_delete_preset($PAGE->context, $preset) && $preset->name != 'Image gallery') { + // Only presets saved by users can be removed (so the datapreset plugins shouldn't display the delete button). + if (!$preset->isplugin && data_user_can_delete_preset($PAGE->context, $preset)) { $deleteactionurl = new moodle_url('/mod/data/preset.php', ['d' => $this->id, 'fullname' => "{$preset->userid}/{$preset->shortname}", 'action' => 'confirmdelete']); - $deleteaction = $OUTPUT->action_icon($deleteactionurl, - new \pix_icon('t/delete', get_string('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'] .= ' presets-actions'; + + $actionmenu->add(new action_menu_link_secondary( + $deleteactionurl, + null, + get_string('delete'), + )); + $actions = $actionmenu->export_for_template($OUTPUT); } } - $presetstable->data[] = [ - \html_writer::tag('input', '', array('type' => 'radio', 'name' => 'fullname', - 'value' => "{$preset->userid}/{$preset->shortname}")), - $presetname, - $deleteaction, + $presets[] = [ + 'id' => $this->id, + 'name' => $preset->name, + 'shortname' => $preset->shortname, + 'fullname' => $presetname, + 'userid' => $preset->userid, + 'actions' => $actions, ]; } - return \html_writer::table($presetstable); + return $presets; } } diff --git a/mod/data/lang/en/data.php b/mod/data/lang/en/data.php index d2ce2a79dda7..185a714f7ebe 100644 --- a/mod/data/lang/en/data.php +++ b/mod/data/lang/en/data.php @@ -320,6 +320,7 @@ $string['presetinfo'] = 'Saving as a preset will publish this template. Other users may be able to use it in their databases.'; $string['presetnotselected'] = 'No preset has been selected.'; $string['presets'] = 'Presets'; +$string['presetshelp'] = 'Choose a preset to use as a starting point.'; $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'; diff --git a/mod/data/styles.css b/mod/data/styles.css index 00494bd8e1bc..53026c90beac 100644 --- a/mod/data/styles.css +++ b/mod/data/styles.css @@ -148,3 +148,7 @@ #page-mod-data-edit .datatagcontrol { padding-left: 10px; } + +.preset_action_menu .dropdown-toggle::after { + display: none; +} diff --git a/mod/data/templates/presets.mustache b/mod/data/templates/presets.mustache index 3d1958a2af74..06754453dfea 100644 --- a/mod/data/templates/presets.mustache +++ b/mod/data/templates/presets.mustache @@ -19,22 +19,69 @@ Context variables required for this template: * formactionul - The form action url. * d - The database id. - * presetstable - The HTML output of the table with presets + * presets - List of presets containing id, name, fullname, shortname and actions. Example context (json): { "formactionul": "http://www.example.com", "d": 1, - "presetstable": "
" + "presets": [ + { + "id": 1, + "name": "Image gallery", + "shortname": "imagegallery", + "fullname": "Image gallery", + "userid": 0, + "actions": [] + }, + { + "id": 2, + "name": "Preset saved manually", + "shortname": "Preset saved manually", + "fullname": "Preset saved manually (admin)", + "userid": 2, + "actions": [] + } + ] } }} +{{#str}}presetshelp, mod_data{{/str}} +
- {{{presetstable}}} - + + + + + + + + + + + {{#presets}} + + + + + + {{/presets}} + +
{{#str}} name {{/str}}{{#showmanage}}{{#str}} action {{/str}}{{/showmanage}}
+ + {{fullname}} + {{#actions}} +
+ {{>core/action_menu}} +
+ {{/actions}} +
+ +
+ {{#js}} require(['mod_data/selectpreset'], function(selectPreset) { selectPreset.init(); diff --git a/mod/data/tests/behat/data_presets.feature b/mod/data/tests/behat/data_presets.feature new file mode 100644 index 000000000000..d8f5f09965de --- /dev/null +++ b/mod/data/tests/behat/data_presets.feature @@ -0,0 +1,81 @@ +@mod @mod_data +Feature: Users can view and manage data presets + In order to use presets + As a user + I need to view, manage and use presets + + 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 | + | data1 | Saved preset 1 | + | data1 | Saved preset 2 | + + @javascript + Scenario: Admins can delete saved presets + Given I am on the "Mountain landscapes" "data activity" page logged in as admin + When I follow "Presets" + Then I should see "Choose a preset to use as a starting point." + And I should see "Image gallery" + And I should see "Saved preset 1" + And I should see "Saved preset 2" + # Plugin presets can't be removed. + And I should not see "Actions" in the "Image gallery" "table_row" + # The admin should be able to delete saved presets. + But I open the action menu in "Saved preset 1" "table_row" + And I should see "Delete" + And I open the action menu in "Saved preset 2" "table_row" + And I should see "Delete" + + @javascript + Scenario: Teachers can see and use presets + Given the following "mod_data > fields" exist: + | database | type | name | description | + | 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" + And I click on "Save as preset" "button" + And I set the field "Name" to "Saved preset by teacher1" + And I click on "Save" "button" in the "Save all fields and templates as preset" "dialogue" + When I follow "Presets" + Then I should see "Choose a preset to use as a starting point." + And I should see "Image gallery" + And I should see "Saved preset 1" + And I should see "Saved preset 2" + And I should see "Saved preset by teacher1" + # Plugin presets can't be removed. + And I should not see "Actions" in the "Image gallery" "table_row" + # Teachers should be able to delete their saved presets. + And I open the action menu in "Saved preset by teacher1" "table_row" + 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 preset" button should be enabled only when a preset is selected. + And the "Use preset" "button" should be disabled + And I click on "fullname" "radio" in the "Image gallery" "table_row" + And the "Use preset" "button" should be enabled + + @javascript + Scenario: Only users with the viewalluserpresets capability can see presets created by other users + Given the following "permission override" exists: + | role | editingteacher | + | capability | mod/data:viewalluserpresets | + | permission | Prohibit | + | contextlevel | System | + | reference | | + When I am on the "Mountain landscapes" "data activity" page logged in as teacher1 + And I follow "Presets" + Then I should see "Image gallery" + And I should not see "Saved preset 1" + And I should not see "Saved preset 2"