From bb3a7fcda511bf04336d92ad16d0f728089a3f62 Mon Sep 17 00:00:00 2001 From: Amaia Anabitarte Date: Tue, 29 Nov 2022 15:40:03 +0100 Subject: [PATCH] MDL-76377 block_myoverview: Improve zero state --- admin/settings/appearance.php | 7 ++ admin/upgrade.txt | 4 + blocks/myoverview/classes/output/main.php | 103 ++++++++++++++++++ blocks/myoverview/classes/output/renderer.php | 8 ++ .../myoverview/lang/en/block_myoverview.php | 12 ++ blocks/myoverview/styles.css | 6 + .../myoverview/templates/zero-state.mustache | 67 ++++++++++++ .../block_myoverview_createnewcourse.feature | 44 -------- .../behat/block_myoverview_pagination.feature | 2 +- .../behat/block_myoverview_search.feature | 7 +- .../behat/block_myoverview_zerostate.feature | 72 ++++++++++++ lang/en/admin.php | 2 + version.php | 2 +- 13 files changed, 286 insertions(+), 50 deletions(-) create mode 100644 blocks/myoverview/templates/zero-state.mustache delete mode 100644 blocks/myoverview/tests/behat/block_myoverview_createnewcourse.feature create mode 100644 blocks/myoverview/tests/behat/block_myoverview_zerostate.feature diff --git a/admin/settings/appearance.php b/admin/settings/appearance.php index 6cfd6c70adc..49e40c61358 100644 --- a/admin/settings/appearance.php +++ b/admin/settings/appearance.php @@ -257,6 +257,13 @@ reports,core_reportbuilder|/reportbuilder/index.php', $ltemp += get_string_manager()->get_list_of_translations(true); $temp->add(new admin_setting_configselect('doclang', get_string('doclang', 'admin'), get_string('configdoclang', 'admin'), '', $ltemp)); $temp->add(new admin_setting_configcheckbox('doctonewwindow', new lang_string('doctonewwindow', 'admin'), new lang_string('configdoctonewwindow', 'admin'), 0)); + $temp->add(new admin_setting_configtext( + 'coursecreationguide', + new lang_string('coursecreationguide', 'admin'), + new lang_string('coursecreationguide_help', 'admin'), + 'https://moodle.academy/coursequickstart', + PARAM_URL + )); $ADMIN->add('appearance', $temp); if (!empty($CFG->enabledashboard)) { diff --git a/admin/upgrade.txt b/admin/upgrade.txt index 4bc57e8fe0a..7ca01139050 100644 --- a/admin/upgrade.txt +++ b/admin/upgrade.txt @@ -1,5 +1,9 @@ This files describes API changes in /admin/*. +=== 4.2 === + +* A new admin setting coursecreationguide allows admins to configure the URL of the Quickstart guide for admins and managers. + === 4.1 === * A new admin setting supportavailability allows admins to configure who the "contact site support" feature is available to diff --git a/blocks/myoverview/classes/output/main.php b/blocks/myoverview/classes/output/main.php index 16473569c4c..91c6512f2e7 100644 --- a/blocks/myoverview/classes/output/main.php +++ b/blocks/myoverview/classes/output/main.php @@ -24,6 +24,7 @@ namespace block_myoverview\output; defined('MOODLE_INTERNAL') || die(); +use core_competency\url; use renderable; use renderer_base; use templatable; @@ -478,4 +479,106 @@ class main implements renderable, templatable { return array_merge($defaultvariables, $preferences); } + + /** + * Export this data so it can be used as the context for a mustache template. + * + * @param \renderer_base $output + * @return array Context variables for the template + * @throws \coding_exception + * + */ + public function export_for_zero_state_template(renderer_base $output) { + global $CFG, $DB; + + $nocoursesimg = $output->image_url('courses', 'block_myoverview'); + + $coursecat = \core_course_category::user_top(); + if ($coursecat) { + $category = \core_course_category::get_nearest_editable_subcategory($coursecat, ['moodle/course:request']); + if ($category && $category->can_request_course()) { + // Add Request a course button. + $button = new \single_button( + new \moodle_url('/course/request.php', ['category' => $category->id]), + get_string('requestcourse'), + 'post', + true + ); + return $this->generate_zero_state_data($nocoursesimg, [$button], 'request'); + } + + $totalcourses = $DB->count_records_select('course', 'category > 0'); + if (!$totalcourses && ($category = \core_course_category::get_nearest_editable_subcategory($coursecat, ['create']))) { + // Add Quickstart guide and Create course buttons. + $quickstarturl = $CFG->coursecreationguide; + if ($quickstarturl) { + $quickstartbutton = new \single_button( + new \moodle_url($quickstarturl, ['lang' => current_language()]), + get_string('viewquickstart', 'block_myoverview'), + ); + $buttons = [$quickstartbutton->export_for_template($output)]; + } + + $createbutton = new \single_button( + new \moodle_url('/course/edit.php', ['category' => $category->id]), + get_string('createcourse', 'block_myoverview'), + 'post', + true + ); + $buttons[] = $createbutton->export_for_template($output); + return $this->generate_zero_state_data($nocoursesimg, $buttons, 'nocourses'); + } + + if ($categorytocreate = \core_course_category::get_nearest_editable_subcategory($coursecat, ['create'])) { + $createbutton = new \single_button( + new \moodle_url('/course/edit.php', ['category' => $categorytocreate->id]), + get_string('createcourse', 'block_myoverview'), + 'post', + true + ); + $buttons = [$createbutton->export_for_template($output)]; + if ($categorytomanage = \core_course_category::get_nearest_editable_subcategory($coursecat, ['manage'])) { + // Add a Manage course button. + $managebutton = new \single_button( + new \moodle_url('/course/management.php', ['category' => $categorytomanage->id]), + get_string('managecourses') + ); + $buttons[] = $managebutton->export_for_template($output); + return $this->generate_zero_state_data($nocoursesimg, array_reverse($buttons), 'createcourses'); + } + return $this->generate_zero_state_data($nocoursesimg, $buttons, 'nomanagecourses'); + } + } + + return $this->generate_zero_state_data($nocoursesimg, [], 'nopermission'); + } + + /** + * Generate the state zero data. + * + * @param \moodle_url $imageurl The URL to the image to show + * @param \single_button[] $buttons + * @param string $scenario the scenario name (used to get title and intro strings) + * @return array Context variables for the template + */ + private function generate_zero_state_data(\moodle_url $imageurl, array $buttons, string $scenario) { + global $CFG; + // Documentation data. + $dochref = new \moodle_url($CFG->docroot, ['lang' => current_language()]); + $quickstart = new \moodle_url($CFG->coursecreationguide, ['lang' => current_language()]); + $docparams = [ + 'quickhref' => $quickstart->out(), + 'quicktitle' => get_string('viewquickstart', 'block_myoverview'), + 'quicktarget' => '_blank', + 'dochref' => $dochref->out(), + 'doctitle' => get_string('documentation'), + 'doctarget' => $CFG->doctonewwindow ? '_blank' : '_self', + ]; + return [ + 'nocoursesimg' => $imageurl->out(), + 'title' => get_string("zero_{$scenario}_title", 'block_myoverview'), + 'intro' => get_string("zero_{$scenario}_intro", 'block_myoverview', $docparams), + 'buttons' => $buttons, + ]; + } } diff --git a/blocks/myoverview/classes/output/renderer.php b/blocks/myoverview/classes/output/renderer.php index 606dd3bf16d..f902390ab74 100644 --- a/blocks/myoverview/classes/output/renderer.php +++ b/blocks/myoverview/classes/output/renderer.php @@ -43,6 +43,14 @@ class renderer extends plugin_renderer_base { * @return string HTML string */ public function render_main(main $main) { + global $USER; + + if (!count(enrol_get_all_users_courses($USER->id, true))) { + return $this->render_from_template( + 'block_myoverview/zero-state', + $main->export_for_zero_state_template($this) + ); + } return $this->render_from_template('block_myoverview/main', $main->export_for_template($this)); } } diff --git a/blocks/myoverview/lang/en/block_myoverview.php b/blocks/myoverview/lang/en/block_myoverview.php index 50f9d692c02..5629d150a65 100644 --- a/blocks/myoverview/lang/en/block_myoverview.php +++ b/blocks/myoverview/lang/en/block_myoverview.php @@ -50,6 +50,7 @@ $string['card'] = 'Card'; $string['cards'] = 'Cards'; $string['courseprogress'] = 'Course progress:'; $string['completepercent'] = '{$a}% complete'; +$string['createcourse'] = 'Create course'; $string['customfield'] = 'Custom field'; $string['customfiltergrouping'] = 'Field to use'; $string['customfiltergrouping_nofields'] = 'This option requires a course custom field to be set up and visible to everyone.'; @@ -86,6 +87,17 @@ $string['sortbytitle'] = 'Sort by course name'; $string['sortbylastaccessed'] = 'Sort by last accessed'; $string['sortbyshortname'] = 'Sort by short name'; $string['privacy:request:preference:set'] = 'The value of the setting \'{$a->name}\' was \'{$a->value}\''; +$string['viewquickstart'] = 'View Quickstart guide'; +$string['zero_nopermission_title'] = 'You\'re not enroled in any course'; +$string['zero_nopermission_intro'] = 'Once you enrol in a course, it will appear here.'; +$string['zero_request_title'] = 'Request your first course'; +$string['zero_request_intro'] = 'Need help getting started? Check out the Moodle documentation or take your first steps with our Quickstart guide.'; +$string['zero_nocourses_title'] = 'Create your first course'; +$string['zero_nocourses_intro'] = 'Need help getting started? Check out the Moodle documentation or take your first steps with our Quickstart guide.'; +$string['zero_createcourses_title'] = 'You\'re not enroled in any course'; +$string['zero_createcourses_intro'] = 'Once you enrol in a course, it will appear here. To view all courses on this site, go to Manage courses.'; +$string['zero_nomanagecourses_title'] = 'You\'re not enroled in any course'; +$string['zero_nomanagecourses_intro'] = 'Once you enrol in a course, it will appear here.'; // Deprecated since Moodle 4.0. $string['clearsearch'] = "Clear search"; diff --git a/blocks/myoverview/styles.css b/blocks/myoverview/styles.css index 76daded2002..851282ec8a4 100644 --- a/blocks/myoverview/styles.css +++ b/blocks/myoverview/styles.css @@ -3,3 +3,9 @@ .block_myoverview button#groupingdropdown + .dropdown-menu li:first-of-type.dropdown-divider:first-of-type { display: none; } +.block_myoverview .whitebutton .btn-secondary { + background: white; + border-color: var(--primary); + color: var(--primary); +} + diff --git a/blocks/myoverview/templates/zero-state.mustache b/blocks/myoverview/templates/zero-state.mustache new file mode 100644 index 00000000000..494c0621b8a --- /dev/null +++ b/blocks/myoverview/templates/zero-state.mustache @@ -0,0 +1,67 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template block_myoverview/zero-state + + This template renders the main content area when there is no course to show. + + Example context (json): + { + "nocoursesimg": "https://moodle.org/img/nocourses.svg", + "title": "No courses", + "text": "Moodle community", + "intro": "Come back later", + "buttons": [ + { + "id": "buttons1", + "method": "get", + "url": "#", + "primary": true, + "label": "Button1" + }, + { + "id": "buttons2", + "method": "get", + "url": "#", + "primary": false, + "label": "Button2" + } + ] + } +}} + + diff --git a/blocks/myoverview/tests/behat/block_myoverview_createnewcourse.feature b/blocks/myoverview/tests/behat/block_myoverview_createnewcourse.feature deleted file mode 100644 index a5a8350f3cb..00000000000 --- a/blocks/myoverview/tests/behat/block_myoverview_createnewcourse.feature +++ /dev/null @@ -1,44 +0,0 @@ -@block @block_myoverview @javascript -Feature: If there is no course yet, users with capabilities have a link to create new course - In order to create a course quickly - As a course creator - I can follow a link to create new course from my overview block - - Background: - Given the following "users" exist: - | username | firstname | lastname | email | idnumber | - | creator1 | Course creator | X | creator1@example.com | CC1 | - | teacher1 | Teacher | X | teacher1@example.com | T1 | - And the following "system role assigns" exist: - | user | course | role | - | creator1 | Acceptance test site | coursecreator | - | teacher1 | Acceptance test site | editingteacher | - - Scenario: Course creators can see a link to new course form from my overview block - Given I am on the "My courses" page logged in as "creator1" - And I should see "No courses" - And I should see "Create new course" in the "region-main" "region" - And I should not see "Add a new course" - When I click on "Create new course" "link" in the "region-main" "region" - Then I should see "Add a new course" - - Scenario: Teachers don't see any link to create new course at my overview block - Given I am on the "My courses" page logged in as "teacher1" - When I should see "No courses" - Then I should not see "Create new course" - - Scenario: Course creators on a subcategory can see a link to new course form from my overview block - Given the following "categories" exist: - | name | category | idnumber | - | Cat 1 | 0 | CAT1 | - | Cat 2 | CAT1 | CAT2 | - And the following "role assigns" exist: - | user | role | contextlevel | reference | - | teacher1 | coursecreator | Category | CAT2 | - And I am on the "My courses" page logged in as "teacher1" - And I should see "No courses" - And I should see "Create new course" in the "region-main" "region" - And I should not see "Add a new course" - When I click on "Create new course" "link" in the "region-main" "region" - Then I should see "Add a new course" - And I should see "Cat 2" in the "page-header" "region" diff --git a/blocks/myoverview/tests/behat/block_myoverview_pagination.feature b/blocks/myoverview/tests/behat/block_myoverview_pagination.feature index d939fbe021a..4b3ee4e4ece 100644 --- a/blocks/myoverview/tests/behat/block_myoverview_pagination.feature +++ b/blocks/myoverview/tests/behat/block_myoverview_pagination.feature @@ -35,7 +35,7 @@ Feature: My overview block pagination Scenario: The pagination controls should be hidden if I am not enrolled in any courses When I am on the "My courses" page logged in as "student1" - Then I should see "No courses" in the "Course overview" "block" + Then I should see "You're not enroled in any course" in the "Course overview" "block" And I should not see "Show" in the "Course overview" "block" And ".block_myoverview .dropdown-menu.show" "css_element" should not be visible And ".block_myoverview [data-control='next']" "css_element" should not be visible diff --git a/blocks/myoverview/tests/behat/block_myoverview_search.feature b/blocks/myoverview/tests/behat/block_myoverview_search.feature index 03a96398e6d..dc640706c20 100644 --- a/blocks/myoverview/tests/behat/block_myoverview_search.feature +++ b/blocks/myoverview/tests/behat/block_myoverview_search.feature @@ -38,11 +38,10 @@ Feature: My overview block searching | student1 | C12 | student | | student1 | C13 | student | - Scenario: The search should return no courses if I am not enrolled in any + Scenario: There is no search if I am not enrolled in any course When I am on the "My courses" page logged in as "student2" - Then I should see "No courses" in the "Course overview" "block" - And I set the field "Search courses" in the "Course overview" "block" to "Fake example" - And I should see "No courses" in the "Course overview" "block" + Then I should see "You're not enroled in any course" in the "Course overview" "block" + And "Search courses" "field" should not exist in the "Course overview" "block" And I log out Scenario: Single page search diff --git a/blocks/myoverview/tests/behat/block_myoverview_zerostate.feature b/blocks/myoverview/tests/behat/block_myoverview_zerostate.feature new file mode 100644 index 00000000000..119f10afe83 --- /dev/null +++ b/blocks/myoverview/tests/behat/block_myoverview_zerostate.feature @@ -0,0 +1,72 @@ +@block @block_myoverview @javascript +Feature: Zero state on my overview block + In order to know what should be the next step + As a user + I should see the proper information based on my capabilities + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | idnumber | + | user | User | X | user@example.com | U1 | + | manager | Manager | X | manager@example.com | M1 | + And the following "role assigns" exist: + | user | role | contextlevel | reference | + | manager | manager | System | | + + Scenario: Users with no permissions don't see any CTA + Given I am on the "My courses" page logged in as "user" + When I should see "You're not enroled in any course" + Then I should see "Once you enrol in a course, it will appear here" + And I should not see "Create course" + And I should not see "Request a course" + + Scenario: Users with permissions to request a course should see a Request course button + Given the following "permission overrides" exist: + | capability | permission | role | contextlevel | reference | + | moodle/course:request | Allow | user | System | | + When I am on the "My courses" page logged in as "user" + Then I should see "Request your first course" + And "Moodle documentation" "link" should exist + And "Quickstart guide" "link" should exist + And "Request a course" "button" should exist + And I click on "Request a course" "button" + And I should see "Details of the course" + + Scenario: Users with permissions to create a course when there is no course created + Given I am on the "My courses" page logged in as "manager" + When I should see "Create your first course" + Then "Moodle documentation" "link" should exist + And "View Quickstart guide" "button" should exist + And "Create course" "button" should exist + And I click on "Create course" "button" + And I should see "Add a new course" + + Scenario: Users with permissions to create a course but is not enroled in any existing course + Given the following "course" exists: + | fullname | Course 1 | + | shortname | C1 | + When I am on the "My courses" page logged in as "manager" + Then I should see "You're not enroled in any course" + Then I should see "To view all courses on this site, go to Manage courses." + And "Manage courses" "button" should exist + And "Create course" "button" should exist + And I click on "Create course" "button" + And I should see "Add a new course" + And I am on the "My courses" page + And I click on "Manage courses" "button" + And I should see "Course 1" + + Scenario: Users with permissions to create but not to manage courses and is not enroled in any existing course + Given the following "permission overrides" exist: + | capability | permission | role | contextlevel | reference | + | moodle/category:manage | Prohibit | manager | System | | + And the following "course" exists: + | fullname | Course 1 | + | shortname | C1 | + When I am on the "My courses" page logged in as "manager" + Then I should see "You're not enroled in any course" + Then I should not see "To view all courses on this sie, go to Manage courses" + And "Manage courses" "button" should not exist + And "Create course" "button" should exist + And I click on "Create course" "button" + And I should see "Add a new course" diff --git a/lang/en/admin.php b/lang/en/admin.php index 1871b913c6d..35b8a43887f 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -519,6 +519,8 @@ $string['divertallemailsto'] = 'Divert all emails'; $string['divertallemailsto_desc'] = 'If set then all emails will be diverted to this single email address instead.'; $string['dndallowtextandlinks'] = 'Drag and drop upload of text/links'; $string['doclang'] = 'Language for docs'; +$string['coursecreationguide'] = 'Moodle course creation guide URL'; +$string['coursecreationguide_help'] = 'Defines the path to a Quickstart guide with short videos and general tips to create courses. A link to the guide is displayed on the My courses page when there are no courses to show. Only users with the capability to create courses will see the link.'; $string['docroot'] = 'Moodle Docs document root'; $string['doctonewwindow'] = 'Open in new window'; $string['doesnotfit'] = 'Email display settings'; diff --git a/version.php b/version.php index 88d97ae9d88..dc3ee2237fa 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2023010500.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2023010500.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes. $release = '4.2dev (Build: 20230105)'; // Human-friendly version name