diff --git a/admin/tool/behat/tests/behat/i_am_on_page.feature b/admin/tool/behat/tests/behat/i_am_on_page.feature index 8f4abc23ac4..422cb86e56f 100644 --- a/admin/tool/behat/tests/behat/i_am_on_page.feature +++ b/admin/tool/behat/tests/behat/i_am_on_page.feature @@ -22,18 +22,18 @@ Feature: Use core page resolvers for the I am on the page steps Then I should see "" Examples: - | description | identifier | type | shouldsee | - | Course Category idnumber | CAT1 | category | Add a new course | - | Course Category name | "Cat 1" | Category | Add a new course | - | Course Full name | "Economics 101" | course | Fundamentals of Economics | - | Course Short name | ECON101 | COURSE | Fundamentals of Economics | - | Course idnumber | "2021-econ101" | Course | Fundamentals of Economics | - | Forum idnumber | fundamentalsofeconomics | Activity | Add a new discussion | - | Generic activity editing | fundamentalsofeconomics | "Activity editing" | Updating: Forum | - | Forum name | "Fundamentals of Economics" | "Forum activity" | Add a new discussion | - | Forum name editing | "Fundamentals of Economics" | "Forum activity editing" | Updating: Forum | - | Forum name permissions | "Fundamentals of Economics" | "Forum activity permissions" | Permissions in Forum: Fun | - | Forum name roles | "Fundamentals of Economics" | "Forum activity roles" | Assign roles in Forum: Fun | + | description | identifier | type | shouldsee | + | Course Category idnumber | CAT1 | category | Add a new course | + | Course Category name | "Cat 1" | Category | Add a new course | + | Course Full name | "Economics 101" | course | Fundamentals of Economics | + | Course Short name | ECON101 | COURSE | Fundamentals of Economics | + | Course idnumber | "2021-econ101" | Course | Fundamentals of Economics | + | Forum idnumber | fundamentalsofeconomics | Activity | Add discussion topic | + | Generic activity editing | fundamentalsofeconomics | "Activity editing" | Updating: Forum | + | Forum name | "Fundamentals of Economics" | "Forum activity" | Add discussion topic | + | Forum name editing | "Fundamentals of Economics" | "Forum activity editing" | Updating: Forum | + | Forum name permissions | "Fundamentals of Economics" | "Forum activity permissions" | Permissions in Forum: Fun | + | Forum name roles | "Fundamentals of Economics" | "Forum activity roles" | Assign roles in Forum: Fun | Scenario Outline: When I am on an instance logged in as Given the following "categories" exist: @@ -58,9 +58,9 @@ Feature: Use core page resolvers for the I am on the page steps | Course Full name | "Economics 101" | course | Fundamentals of Economics | | Course Short name | ECON101 | COURSE | Fundamentals of Economics | | Course idnumber | "2021-econ101" | Course | Fundamentals of Economics | - | Forum idnumber | fundamentalsofeconomics | Activity | Add a new discussion | + | Forum idnumber | fundamentalsofeconomics | Activity | Add discussion topic | | Generic activity editing | fundamentalsofeconomics | "Activity editing" | Updating: Forum | - | Forum name | "Fundamentals of Economics" | "Forum activity" | Add a new discussion | + | Forum name | "Fundamentals of Economics" | "Forum activity" | Add discussion topic | | Forum name editing | "Fundamentals of Economics" | "Forum activity editing" | Updating: Forum | | Forum name permissions | "Fundamentals of Economics" | "Forum activity permissions" | Permissions in Forum: Fun | | Forum name roles | "Fundamentals of Economics" | "Forum activity roles" | Assign roles in Forum: Fun | diff --git a/admin/tool/recyclebin/tests/behat/backup_user_data.feature b/admin/tool/recyclebin/tests/behat/backup_user_data.feature index c24900d8592..c5cd73951e3 100644 --- a/admin/tool/recyclebin/tests/behat/backup_user_data.feature +++ b/admin/tool/recyclebin/tests/behat/backup_user_data.feature @@ -43,7 +43,7 @@ Feature: Backup user data | Feedback for the response 'False'. | So you think it is false | And I log out When I am on the "Quiz 1" "quiz activity" page logged in as student1 - And I press "Attempt quiz now" + And I follow "Attempt quiz" And I click on "True" "radio" in the "First question" "question" And I click on "False" "radio" in the "Second question" "question" And I press "Finish attempt" diff --git a/badges/tests/behat/criteria_activity.feature b/badges/tests/behat/criteria_activity.feature index 98cae5e8fb7..bc7379f8b0a 100644 --- a/badges/tests/behat/criteria_activity.feature +++ b/badges/tests/behat/criteria_activity.feature @@ -57,7 +57,7 @@ Feature: Award badges based on activity completion And the "Receive a passing grade" completion condition of "Test quiz name" is displayed as "failed" And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "todo" When I am on the "Test quiz name" "quiz activity" page - And I press "Re-attempt quiz" + And I follow "Attempt quiz" And I set the field "False" to "1" And I press "Finish attempt ..." And I press "Submit all and finish" diff --git a/course/format/social/tests/behat/social_adjust_discussion_count.feature b/course/format/social/tests/behat/social_adjust_discussion_count.feature index fe0ccd160fa..2fec3514751 100644 --- a/course/format/social/tests/behat/social_adjust_discussion_count.feature +++ b/course/format/social/tests/behat/social_adjust_discussion_count.feature @@ -16,7 +16,9 @@ Feature: Change number of discussions displayed | teacher1 | C1 | editingteacher | And I log in as "teacher1" And I am on "Course 1" course homepage - And I follow "Add a new discussion topic" + And I turn editing mode on + And I click on "Social forum" "link" + And I follow "Add discussion topic" And I set the following fields to these values: | Subject | Forum Post 10 | | Message | This is forum post ten | @@ -24,7 +26,8 @@ Feature: Change number of discussions displayed And I wait to be redirected And I am on "Course 1" course homepage And I wait "1" seconds - And I follow "Add a new discussion topic" + And I click on "Social forum" "link" + And I follow "Add discussion topic" And I set the following fields to these values: | Subject | Forum Post 9 | | Message | This is forum post nine | @@ -32,7 +35,8 @@ Feature: Change number of discussions displayed And I wait to be redirected And I am on "Course 1" course homepage And I wait "1" seconds - And I follow "Add a new discussion topic" + And I click on "Social forum" "link" + And I follow "Add discussion topic" And I set the following fields to these values: | Subject | Forum Post 8 | | Message | This is forum post eight | @@ -40,7 +44,8 @@ Feature: Change number of discussions displayed And I wait to be redirected And I am on "Course 1" course homepage And I wait "1" seconds - And I follow "Add a new discussion topic" + And I click on "Social forum" "link" + And I follow "Add discussion topic" And I set the following fields to these values: | Subject | Forum Post 7 | | Message | This is forum post seven | @@ -48,7 +53,8 @@ Feature: Change number of discussions displayed And I wait to be redirected And I am on "Course 1" course homepage And I wait "1" seconds - And I follow "Add a new discussion topic" + And I click on "Social forum" "link" + And I follow "Add discussion topic" And I set the following fields to these values: | Subject | Forum Post 6 | | Message | This is forum post six | @@ -56,7 +62,8 @@ Feature: Change number of discussions displayed And I wait to be redirected And I am on "Course 1" course homepage And I wait "1" seconds - And I follow "Add a new discussion topic" + And I click on "Social forum" "link" + And I follow "Add discussion topic" And I set the following fields to these values: | Subject | Forum Post 5 | | Message | This is forum post five | @@ -64,7 +71,8 @@ Feature: Change number of discussions displayed And I wait to be redirected And I am on "Course 1" course homepage And I wait "1" seconds - And I follow "Add a new discussion topic" + And I click on "Social forum" "link" + And I follow "Add discussion topic" And I set the following fields to these values: | Subject | Forum Post 4 | | Message | This is forum post four | @@ -72,7 +80,8 @@ Feature: Change number of discussions displayed And I wait to be redirected And I am on "Course 1" course homepage And I wait "1" seconds - And I follow "Add a new discussion topic" + And I click on "Social forum" "link" + And I follow "Add discussion topic" And I set the following fields to these values: | Subject | Forum Post 3 | | Message | This is forum post three | @@ -80,7 +89,8 @@ Feature: Change number of discussions displayed And I wait to be redirected And I am on "Course 1" course homepage And I wait "1" seconds - And I follow "Add a new discussion topic" + And I click on "Social forum" "link" + And I follow "Add discussion topic" And I set the following fields to these values: | Subject | Forum Post 2 | | Message | This is forum post two | @@ -88,7 +98,8 @@ Feature: Change number of discussions displayed And I wait to be redirected And I am on "Course 1" course homepage And I wait "1" seconds - And I follow "Add a new discussion topic" + And I click on "Social forum" "link" + And I follow "Add discussion topic" And I set the following fields to these values: | Subject | Forum Post 1 | | Message | This is forum post one | diff --git a/course/tests/behat/course_creation.feature b/course/tests/behat/course_creation.feature index 40b384c6055..0eaf09cd2c5 100644 --- a/course/tests/behat/course_creation.feature +++ b/course/tests/behat/course_creation.feature @@ -21,7 +21,7 @@ Feature: Managers can create courses And I am on "Course 1" course homepage with editing mode on And I add the "Latest announcements" block And I am on the Announcements "forum activity" page - And "Add a new topic" "link" should exist + And "Add discussion topic" "link" should exist And "Subscription mode > Forced subscription" "link" should not exist in current page administration And "Subscription mode > Forced subscription" "text" should exist in current page administration And I log out diff --git a/grade/report/grader/tests/behat/ajax_grader.feature b/grade/report/grader/tests/behat/ajax_grader.feature index 3c8d514559e..bb0db25f9b5 100644 --- a/grade/report/grader/tests/behat/ajax_grader.feature +++ b/grade/report/grader/tests/behat/ajax_grader.feature @@ -118,6 +118,10 @@ Feature: Using the AJAX grading feature of Grader report to update grades and fe And I set the field "ajaxgrade" to "33" And I set the field "ajaxfeedback" to "Student 2 VU feedback" And I press the enter key + And I click on student "Student 2" for grade item "Item SU" + And I set the field "ajaxgrade" to "Very good" + And I set the field "ajaxfeedback" to "Student 2 SU feedback" + And I press the enter key And I click on student "Student 3" for grade item "Item VL" And I should not see a grade field for "Student 3" and grade item "Item VL" And I should not see a feedback field for "Student 3" and grade item "Item VL" @@ -126,10 +130,6 @@ Feature: Using the AJAX grading feature of Grader report to update grades and fe And I should see a feedback field for "Student 3" and grade item "Item TU" And I set the field "ajaxfeedback" to "Student 3 TU feedback" And I press the enter key - And I click on student "Student 2" for grade item "Item SU" - And I set the field "ajaxgrade" to "Very good" - And I set the field "ajaxfeedback" to "Student 2 SU feedback" - And I press the enter key # Reload grader report: And I navigate to "View > User report" in the course gradebook And I navigate to "View > Grader report" in the course gradebook diff --git a/lib/form/tests/behat/modgrade_validation.feature b/lib/form/tests/behat/modgrade_validation.feature index fa2fbe253aa..07dd527a289 100644 --- a/lib/form/tests/behat/modgrade_validation.feature +++ b/lib/form/tests/behat/modgrade_validation.feature @@ -75,7 +75,7 @@ Feature: Using the activity grade form element | Group mode | No groups | And I log out And I am on the "Test forum name" "forum activity" page logged in as student1 - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I set the following fields to these values: | Subject | Discussion subject | | Message | Discussion message | @@ -135,7 +135,7 @@ Feature: Using the activity grade form element And I press "Save and return to course" And I log out And I am on the "Test forum name" "forum activity" page logged in as student1 - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I set the following fields to these values: | Subject | Discussion subject | | Message | Discussion message | diff --git a/lib/tests/behat/action_modal.feature b/lib/tests/behat/action_modal.feature index d94d1b8806e..84ee2bdaa10 100644 --- a/lib/tests/behat/action_modal.feature +++ b/lib/tests/behat/action_modal.feature @@ -13,7 +13,7 @@ Feature: Close modals by clicking outside them | activity | name | intro | course | idnumber | | quiz | Test quiz name | Test quiz description | C1 | quiz1 | And I am on the "quiz1" "Activity" page logged in as "admin" - And I click on "Edit quiz" "button" + And I follow "Add question" And I click on "Add" "link" And I click on "a new question" "link" # Cannot use the normal ‘I click on’ here, because the pop-up gets in the way. @@ -42,8 +42,5 @@ Feature: Close modals by clicking outside them | activity | name | intro | course | idnumber | | quiz | Test quiz name | Test quiz description | C1 | quiz1 | And I am on the "quiz1" "Activity" page logged in as "admin" - And I click on "Edit quiz" "button" - And I click on "Help with Editing quiz" "icon" - And I should see "More help" - And I click on "body" "css_element" + And I follow "Add question" Then I should not see "More help" diff --git a/lib/tests/behat/locking.feature b/lib/tests/behat/locking.feature index 718beaa6d06..be22ac4bdad 100644 --- a/lib/tests/behat/locking.feature +++ b/lib/tests/behat/locking.feature @@ -39,22 +39,22 @@ Feature: Context freezing apply to child contexts Scenario: Freeze course module module should freeze just that module Given I am on the "courseaa1" "Course" page logged in as "admin" And I follow "faa1" - And "Add a new discussion topic" "link" should exist + And "Add discussion topic" "link" should exist When I follow "Freeze this context" And I click on "Continue" "button" - Then "Add a new discussion topic" "link" should not exist + Then "Add discussion topic" "link" should not exist When I am on "courseaa1" course homepage Then edit mode should be available on the current page When I follow "faa1b" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist When I am on "courseaa2" course homepage Then edit mode should be available on the current page When I follow "faa2" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist When I am on "courseb" course homepage Then edit mode should be available on the current page When I follow "fb" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist And I log out When I am on the "courseaa1" "Course" page logged in as "teacher" @@ -63,15 +63,15 @@ Feature: Context freezing apply to child contexts When I am on "courseaa1" course homepage Then edit mode should be available on the current page When I follow "faa1b" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist When I am on "courseaa2" course homepage Then edit mode should be available on the current page When I follow "faa2" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist When I am on "courseb" course homepage Then edit mode should be available on the current page When I follow "fb" - And "Add a new discussion topic" "link" should exist + And "Add discussion topic" "link" should exist And I log out When I am on the "courseaa1" "Course" page logged in as "student1" @@ -79,13 +79,13 @@ Feature: Context freezing apply to child contexts Then "Add a new discussion topic" "link" should not exist When I am on "courseaa1" course homepage When I follow "faa1b" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist When I am on "courseaa2" course homepage When I follow "faa2" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist When I am on "courseb" course homepage When I follow "fb" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist Scenario: Freeze course should freeze all children Given I am on the "courseaa1" "Course" page logged in as "admin" @@ -103,11 +103,11 @@ Feature: Context freezing apply to child contexts When I am on "courseaa2" course homepage Then edit mode should be available on the current page When I follow "faa2" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist When I am on "courseb" course homepage Then edit mode should be available on the current page When I follow "fb" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist And I log out When I am on the "courseaa1" "Course" page logged in as "teacher" @@ -120,11 +120,11 @@ Feature: Context freezing apply to child contexts When I am on "courseaa2" course homepage Then edit mode should be available on the current page When I follow "faa2" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist When I am on "courseb" course homepage Then edit mode should be available on the current page When I follow "fb" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist And I log out When I am on the "courseaa1" "Course" page logged in as "student1" @@ -135,10 +135,10 @@ Feature: Context freezing apply to child contexts Then "Add a new discussion topic" "link" should not exist When I am on "courseaa2" course homepage When I follow "faa2" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist When I am on "courseb" course homepage When I follow "fb" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist Scenario: Freeze course category should freeze all children Given I log in as "admin" @@ -162,7 +162,7 @@ Feature: Context freezing apply to child contexts When I am on "courseb" course homepage Then edit mode should be available on the current page When I follow "fb" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist And I log out When I am on the "courseaa1" "Course" page logged in as "teacher" @@ -180,7 +180,7 @@ Feature: Context freezing apply to child contexts When I am on "courseb" course homepage Then edit mode should be available on the current page When I follow "fb" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist And I log out When I am on the "courseaa1" "Course" page logged in as "student1" @@ -194,4 +194,4 @@ Feature: Context freezing apply to child contexts Then "Add a new discussion topic" "link" should not exist When I am on "courseb" course homepage When I follow "fb" - Then "Add a new discussion topic" "link" should exist + Then "Add discussion topic" "link" should exist diff --git a/mod/forum/classes/local/renderers/discussion.php b/mod/forum/classes/local/renderers/discussion.php index 808f30f49df..817379f0bbf 100644 --- a/mod/forum/classes/local/renderers/discussion.php +++ b/mod/forum/classes/local/renderers/discussion.php @@ -417,7 +417,7 @@ class discussion { if ($this->capabilitymanager->must_post_before_viewing_discussion($user, $discussion)) { $notifications[] = (new notification( get_string('qandanotify', 'forum') - ))->set_show_closebutton(true); + ))->set_show_closebutton(true)->set_extra_classes(['mt-3']); } } diff --git a/mod/forum/classes/local/renderers/discussion_list.php b/mod/forum/classes/local/renderers/discussion_list.php index a3b85541e3b..6c57ab736b1 100644 --- a/mod/forum/classes/local/renderers/discussion_list.php +++ b/mod/forum/classes/local/renderers/discussion_list.php @@ -37,6 +37,7 @@ use mod_forum\local\vaults\discussion_list as discussion_list_vault; use renderer_base; use stdClass; use core\output\notification; +use mod_forum\local\data_mappers\legacy\forum; use mod_forum\local\factories\builder as builder_factory; require_once($CFG->dirroot . '/mod/forum/lib.php'); @@ -145,6 +146,7 @@ class discussion_list { * @param int $pageno The zero-indexed page number to use * @param int $pagesize The number of discussions to show on the page * @param int $displaymode The discussion display mode + * @param bool $enablediscussioncreation To show the discussion button. * @return string The rendered content for display */ public function render( @@ -154,7 +156,8 @@ class discussion_list { ?int $sortorder, ?int $pageno, ?int $pagesize, - int $displaymode = null + int $displaymode = null, + bool $enablediscussioncreation = true ) : string { global $PAGE; @@ -209,7 +212,8 @@ class discussion_list { ], 'totaldiscussioncount' => $alldiscussionscount, 'userid' => $user->id, - 'visiblediscussioncount' => count($discussions) + 'visiblediscussioncount' => count($discussions), + 'enablediscussioncreation' => $enablediscussioncreation, ]; if ($forumview['forum']['capabilities']['create']) { @@ -241,6 +245,27 @@ class discussion_list { return $this->renderer->render_from_template($this->template, $forumview); } + /** + * Add new discussion button to the action bar for tertiary nav. + * + * @param stdClass $user The user object. + * @param int|null $groupid The group id. + * @return string rendered HTML string + */ + public function render_new_discussion(stdClass $user, ?int $groupid): string { + $forumexporter = $this->exporterfactory->get_forum_exporter( + $user, + $this->forum, + $groupid + ); + + $forumview = [ + 'forum' => (array) $forumexporter->export($this->renderer), + ]; + + return $this->renderer->render_from_template('mod_forum/forum_new_discussion_actionbar', $forumview); + } + /** * Get the mod_forum_post_form. This is the default boiler plate from mod_forum/post_form.php with the inpage flag caveat * @@ -335,7 +360,7 @@ class discussion_list { * @param int|null $groupid The forum's group id * @return array */ - private function get_notifications(stdClass $user, ?int $groupid) : array { + private function get_notifications(stdClass $user, ?int $groupid): array { $notifications = $this->notifications; $forum = $this->forum; $capabilitymanager = $this->capabilitymanager; @@ -381,7 +406,7 @@ class discussion_list { $notifications[] = (new notification( get_string('qandanotify', 'forum'), notification::NOTIFY_INFO - ))->set_show_closebutton(); + ))->set_show_closebutton()->set_extra_classes(['mt-3']); } if ('eachuser' === $forum->get_type()) { diff --git a/mod/forum/classes/output/forum_actionbar.php b/mod/forum/classes/output/forum_actionbar.php new file mode 100644 index 00000000000..05c5c327140 --- /dev/null +++ b/mod/forum/classes/output/forum_actionbar.php @@ -0,0 +1,135 @@ +. + +namespace mod_forum\output; + +use renderable; +use renderer_base; +use templatable; +use moodle_url; +use help_icon; +use mod_forum\local\entities\forum as forum_entity; + +/** + * Render activity page for tertiary nav + * + * Render elements search forum, add new discussion button and subscribe all + * to the page action. + * + * @package mod_forum + * @copyright 2021 Sujith Haridasan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class forum_actionbar implements renderable, templatable { + /** + * @var forum_entity $forum + */ + private $forum; + + /** + * @var \stdClass $course + */ + private $course; + + /** + * @var mixed $groupid + */ + private $groupid; + + /** + * @var string $search + */ + private $search; + + /** + * forum_actionbar constructor. + * + * @param forum_entity $forum The forum object. + * @param \stdClass $course The course object. + * @param int|null $groupid The group id. + * @param string $search The search string. + */ + public function __construct(forum_entity $forum, \stdClass $course, ?int $groupid, string $search) { + $this->forum = $forum; + $this->course = $course; + $this->groupid = $groupid; + $this->search = $search; + } + + /** + * Render the new discussion button. + * + * @return string HTML button + */ + private function get_new_discussion_topic_button(): string { + global $USER; + $renderfactory = \mod_forum\local\container::get_renderer_factory(); + $discussionrenderer = $renderfactory->get_discussion_list_renderer($this->forum); + return $discussionrenderer->render_new_discussion($USER, $this->groupid); + } + + /** + * Data for the template. + * + * @param renderer_base $output The render_base object. + * @return array data for the template + */ + public function export_for_template(renderer_base $output): array { + global $USER; + $actionurl = (new moodle_url('/mod/forum/search.php'))->out(false); + $helpicon = new help_icon('search', 'core'); + $hiddenfields = [ + (object) ['name' => 'id', 'value' => $this->course->id], + ]; + $shownewdiscussionbtn = ''; + if ($this->forum->get_type() !== 'single') { + $shownewdiscussionbtn = $this->get_new_discussion_topic_button(); + } + $data = [ + 'action' => $actionurl, + 'hiddenfields' => $hiddenfields, + 'query' => $this->search, + 'helpicon' => $helpicon->export_for_template($output), + 'inputname' => 'search', + 'searchstring' => get_string('searchforums', 'mod_forum'), + 'newdiscussionbtn' => $shownewdiscussionbtn, + ]; + + $legacydatamapperfactory = \mod_forum\local\container::get_legacy_data_mapper_factory(); + $forumobject = $legacydatamapperfactory->get_forum_data_mapper()->to_legacy_object($this->forum); + $context = $this->forum->get_context(); + $activeenrolled = is_enrolled($context, $USER, '', true); + $canmanage = has_capability('mod/forum:managesubscriptions', $context); + $cansubscribe = $activeenrolled && !($this->forum->get_subscription_mode() === FORUM_FORCESUBSCRIBE) && + (!($this->forum->get_subscription_mode() === FORUM_DISALLOWSUBSCRIBE) || $canmanage); + if ($cansubscribe) { + $returnurl = + (new moodle_url('/mod/forum/view.php', ['id' => $this->forum->get_course_module_record()->id]))->out(false); + if (!\mod_forum\subscriptions::is_subscribed($USER->id, $forumobject, null, $this->forum->get_course_module_record())) { + $data['subscribetoforum'] = (new moodle_url( + '/mod/forum/subscribe.php', + ['id' => $forumobject->id, 'sesskey' => sesskey(), 'returnurl' => $returnurl] + ))->out(false); + } else { + $data['unsubscribefromforum'] = (new moodle_url( + '/mod/forum/subscribe.php', + ['id' => $forumobject->id, 'sesskey' => sesskey(), 'returnurl' => $returnurl] + ))->out(false); + } + } + return $data; + } +} diff --git a/mod/forum/classes/output/subscription_actionbar.php b/mod/forum/classes/output/subscription_actionbar.php new file mode 100644 index 00000000000..33276281cf4 --- /dev/null +++ b/mod/forum/classes/output/subscription_actionbar.php @@ -0,0 +1,143 @@ +. + +namespace mod_forum\output; + +use moodle_url; +use renderer_base; +use url_select; +use renderable; +use templatable; + +/** + * Renders the subscribers page for this activity. + * + * @package mod_forum + * @copyright 2021 Sujith Haridasan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class subscription_actionbar implements renderable, templatable { + /** @var int course id */ + private $id; + + /** @var moodle_url */ + private $currenturl; + + /** @var \stdClass */ + private $forum; + + /** + * subscription_actionbar constructor. + * + * @param int $id The forum id. + * @param moodle_url $currenturl Current URL. + * @param \stdClass $forum The forum object. + */ + public function __construct(int $id, moodle_url $currenturl, \stdClass $forum) { + $this->id = $id; + $this->currenturl = $currenturl; + $this->forum = $forum; + } + + /** + * Create url select menu for subscription option + * + * @return url_select the url_select object + */ + private function create_subscription_menu(): url_select { + $sesskey = sesskey(); + $modeset = \mod_forum\subscriptions::get_subscription_mode($this->forum); + $optionallink = new moodle_url('/mod/forum/subscribe.php', ['id' => $this->id, 'mode' => 0, 'sesskey' => $sesskey]); + $forcedlink = new moodle_url('/mod/forum/subscribe.php', ['id' => $this->id, 'mode' => 1, 'sesskey' => $sesskey]); + $autolink = new moodle_url('/mod/forum/subscribe.php', ['id' => $this->id, 'mode' => 2, 'sesskey' => $sesskey]); + $disabledlink = new moodle_url('/mod/forum/subscribe.php', ['id' => $this->id, 'mode' => 3, 'sesskey' => $sesskey]); + + $menu = [ + $optionallink->out(false) => get_string('subscriptionoptional', 'forum'), + $forcedlink->out(false) => get_string('subscriptionforced', 'forum'), + $autolink->out(false) => get_string('subscriptionauto', 'forum'), + $disabledlink->out(false) => get_string('subscriptiondisabled', 'forum'), + ]; + + switch ($modeset) { + case FORUM_CHOOSESUBSCRIBE: + $set = get_string('subscriptionoptional', 'forum'); + break; + case FORUM_FORCESUBSCRIBE: + $set = get_string('subscriptionforced', 'forum'); + break; + case FORUM_INITIALSUBSCRIBE: + $set = get_string('subscriptionauto', 'forum'); + break; + case FORUM_DISALLOWSUBSCRIBE: + $set = get_string('subscriptiondisabled', 'forum'); + break; + default: + throw new \moodle_exception(get_string('invalidforcesubscribe', 'forum')); + } + + $menu = array_filter($menu, function($key) use ($set) { + if ($key !== $set) { + return true; + } + }); + $urlselect = new url_select($menu, $this->currenturl, ['' => $set], 'selectsubscriptionoptions'); + $urlselect->set_label(get_string('subscriptions', 'mod_forum'), ['class' => 'accesshide']); + $urlselect->class .= ' float-right'; + return $urlselect; + } + + /** + * Create view and manage subscribers select menu. + * + * @return url_select get url_select object. + */ + private function create_view_manage_menu(): url_select { + $viewlink = new moodle_url('/mod/forum/subscribers.php', ['id' => $this->id, 'edit' => 'off']); + $managelink = new moodle_url('/mod/forum/subscribers.php', ['id' => $this->id, 'edit' => 'on']); + + $menu = [ + $viewlink->out(false) => get_string('forum:viewsubscribers', 'forum'), + $managelink->out(false) => get_string('managesubscriptionson', 'forum'), + ]; + + if ($this->currenturl->get_param('edit') === 'off') { + $this->currenturl = $viewlink; + } else { + $this->currenturl = $managelink; + } + + $urlselect = new url_select($menu, $this->currenturl->out(false), null, 'selectviewandmanagesubscribers'); + $urlselect->set_label(get_string('subscribers', 'forum'), ['class' => 'accesshide']); + return $urlselect; + } + + /** + * Data for the template. + * + * @param renderer_base $output The render_base object. + * @return array data for template + */ + public function export_for_template(renderer_base $output): array { + $subscribeoptionselect = $this->create_subscription_menu(); + $viewmanageselect = $this->create_view_manage_menu(); + $data = [ + 'subscriptionoptions' => $subscribeoptionselect->export_for_template($output), + 'viewandmanageselect' => $viewmanageselect->export_for_template($output), + ]; + return $data; + } +} diff --git a/mod/forum/discuss.php b/mod/forum/discuss.php index 053ada350db..b645ba32fe2 100644 --- a/mod/forum/discuss.php +++ b/mod/forum/discuss.php @@ -320,7 +320,9 @@ if ($isnestedv2displaymode) { echo $OUTPUT->header(); if (!$isnestedv2displaymode) { - echo $OUTPUT->heading(format_string($forum->get_name()), 2); + if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($forum->get_name()), 2); + } echo $OUTPUT->heading(format_string($discussion->get_name()), 3, 'discussionname'); } diff --git a/mod/forum/export.php b/mod/forum/export.php index 00ab85bacfa..0caf7ff45c0 100644 --- a/mod/forum/export.php +++ b/mod/forum/export.php @@ -184,7 +184,9 @@ $PAGE->set_pagelayout('admin'); $PAGE->set_heading($pagetitle); echo $OUTPUT->header(); -echo $OUTPUT->heading($pagetitle); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading($pagetitle); +} // It is possible that the following fields have been provided in the URL. $form->set_data(['useridsselected' => $userids, 'discussionids' => $discussionids, 'from' => $from, 'to' => $to]); diff --git a/mod/forum/index.php b/mod/forum/index.php index c05884b0d0b..eb06638195f 100644 --- a/mod/forum/index.php +++ b/mod/forum/index.php @@ -35,6 +35,7 @@ if ($subscribe !== null) { $url->param('subscribe', $subscribe); } $PAGE->set_url($url); +$PAGE->set_secondary_active_tab('coursehome'); if ($id) { if (!$course = $DB->get_record('course', array('id' => $id))) { @@ -454,9 +455,12 @@ if ($course->id != SITEID) { // Only real courses have learning forums $PAGE->navbar->add($strforums); $PAGE->set_title("$course->shortname: $strforums"); $PAGE->set_heading($course->fullname); -$PAGE->add_header_action($searchform); echo $OUTPUT->header(); +echo html_writer::start_div('input-group mr-5'); +echo $searchform; +echo html_writer::end_div(); + if (!isguestuser() && isloggedin() && $showsubscriptioncolumns) { // Show the subscribe all options only to non-guest, enrolled users. echo $OUTPUT->box_start('subscription'); diff --git a/mod/forum/lang/en/forum.php b/mod/forum/lang/en/forum.php index 34e25f1b323..3fb8067418c 100644 --- a/mod/forum/lang/en/forum.php +++ b/mod/forum/lang/en/forum.php @@ -27,7 +27,7 @@ $string['activitydate:due'] = 'Due:'; $string['activityoverview'] = 'There are new forum posts'; $string['actionsforgraderinterface'] = 'Actions for the grader interface'; $string['actionsforpost'] = 'Actions for post'; -$string['addanewdiscussion'] = 'Add a new discussion topic'; +$string['addanewdiscussion'] = 'Add discussion topic'; $string['addanewquestion'] = 'Add a new question'; $string['addanewtopic'] = 'Add a new topic'; $string['addtofavourites'] = 'Star this discussion'; @@ -664,7 +664,7 @@ $string['smallmessage'] = '{$a->user} posted in {$a->forumname}'; $string['smallmessagedigest'] = 'Forum digest containing {$a} messages'; $string['startedby'] = 'Started by'; $string['subject'] = 'Subject'; -$string['subscribe'] = 'Subscribe to this forum'; +$string['subscribe'] = 'Subscribe to forum'; $string['subscribediscussion'] = 'Subscribe to this discussion'; $string['subscribeall'] = 'Subscribe everyone to this forum'; $string['subscribeenrolledonly'] = 'Sorry, only enrolled users are allowed to subscribe to forum post notifications.'; @@ -722,7 +722,7 @@ $string['unreadpost'] = 'Unread post'; $string['unreadposts'] = 'Unread posts'; $string['unreadpostsnumber'] = '{$a} unread posts'; $string['unreadpostsone'] = '1 unread post'; -$string['unsubscribe'] = 'Unsubscribe from this forum'; +$string['unsubscribe'] = 'Unsubscribe from forum'; $string['unsubscribelink'] = 'Unsubscribe from this forum: {$a}'; $string['unsubscribediscussion'] = 'Unsubscribe from this discussion'; $string['unsubscribediscussionlink'] = 'Unsubscribe from this discussion: {$a}'; diff --git a/mod/forum/lib.php b/mod/forum/lib.php index 3348ac8efa1..e4758ff4d6f 100644 --- a/mod/forum/lib.php +++ b/mod/forum/lib.php @@ -20,6 +20,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +use mod_forum\local\entities\forum as forum_entity; + defined('MOODLE_INTERNAL') || die(); /** Include required files */ @@ -2599,6 +2601,22 @@ function forum_search_form($course, $search='') { return $output->render($forumsearch); } +/** + * Retrieve HTML for the page action + * + * @param forum_entity|null $forum The forum entity. + * @param mixed $groupid false if groups not used, int if groups used, 0 means all groups + * @param stdClass $course The course object. + * @param string $search The search string. + * @return string rendered HTML string. + */ +function forum_activity_actionbar(?forum_entity $forum, $groupid, stdClass $course, string $search=''): string { + global $PAGE; + + $actionbar = new mod_forum\output\forum_actionbar($forum, $course, $groupid, $search); + $output = $PAGE->get_renderer('mod_forum'); + return $output->render($actionbar); +} /** * @global object @@ -5472,22 +5490,6 @@ function forum_extend_settings_navigation(settings_navigation $settingsnav, navi $discussionid = $params['d']; } - // Display all forum reports user has access to. - if (isloggedin() && !isguestuser()) { - $reportnames = array_keys(core_component::get_plugin_list('forumreport')); - - foreach ($reportnames as $reportname) { - if (has_capability("forumreport/{$reportname}:view", $PAGE->cm->context)) { - $reportlinkparams = [ - 'courseid' => $forumobject->course, - 'forumid' => $forumobject->id, - ]; - $reportlink = new moodle_url("/mod/forum/report/{$reportname}/index.php", $reportlinkparams); - $forumnode->add(get_string('nodetitle', "forumreport_{$reportname}"), $reportlink, navigation_node::TYPE_CONTAINER); - } - } - } - // For some actions you need to be enrolled, being admin is not enough sometimes here. $enrolled = is_enrolled($PAGE->cm->context, $USER, '', false); $activeenrolled = is_enrolled($PAGE->cm->context, $USER, '', true); @@ -5500,6 +5502,7 @@ function forum_extend_settings_navigation(settings_navigation $settingsnav, navi if ($canmanage) { $mode = $forumnode->add(get_string('subscriptionmode', 'forum'), null, navigation_node::TYPE_CONTAINER); $mode->add_class('subscriptionmode'); + $mode->set_show_in_secondary_navigation(false); // Optional subscription mode. $allowchoicestring = get_string('subscriptionoptional', 'forum'); @@ -5594,34 +5597,25 @@ function forum_extend_settings_navigation(settings_navigation $settingsnav, navi } } - if ($cansubscribe) { - if (\mod_forum\subscriptions::is_subscribed($USER->id, $forumobject, null, $PAGE->cm)) { - $linktext = get_string('unsubscribe', 'forum'); - } else { - $linktext = get_string('subscribe', 'forum'); - } - $url = new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'sesskey'=>sesskey())); - $forumnode->add($linktext, $url, navigation_node::TYPE_SETTING); - - if (isset($discussionid)) { - if (\mod_forum\subscriptions::is_subscribed($USER->id, $forumobject, $discussionid, $PAGE->cm)) { - $linktext = get_string('unsubscribediscussion', 'forum'); - } else { - $linktext = get_string('subscribediscussion', 'forum'); - } - $url = new moodle_url('/mod/forum/subscribe.php', array( - 'id' => $forumobject->id, - 'sesskey' => sesskey(), - 'd' => $discussionid, - 'returnurl' => $PAGE->url->out(), - )); - $forumnode->add($linktext, $url, navigation_node::TYPE_SETTING); - } + if (has_capability('mod/forum:viewsubscribers', $PAGE->cm->context)) { + $url = new moodle_url('/mod/forum/subscribers.php', ['id' => $forumobject->id, 'edit' => 'off']); + $forumnode->add(get_string('subscriptions', 'forum'), $url, navigation_node::TYPE_SETTING, null, 'forumsubscriptions'); } - if (has_capability('mod/forum:viewsubscribers', $PAGE->cm->context)){ - $url = new moodle_url('/mod/forum/subscribers.php', array('id'=>$forumobject->id)); - $forumnode->add(get_string('showsubscribers', 'forum'), $url, navigation_node::TYPE_SETTING); + // Display all forum reports user has access to. + if (isloggedin() && !isguestuser()) { + $reportnames = array_keys(core_component::get_plugin_list('forumreport')); + + foreach ($reportnames as $reportname) { + if (has_capability("forumreport/{$reportname}:view", $PAGE->cm->context)) { + $reportlinkparams = [ + 'courseid' => $forumobject->course, + 'forumid' => $forumobject->id, + ]; + $reportlink = new moodle_url("/mod/forum/report/{$reportname}/index.php", $reportlinkparams); + $forumnode->add(get_string('reports'), $reportlink, navigation_node::TYPE_CONTAINER); + } + } } if ($enrolled && forum_tp_can_track_forums($forumobject)) { // keep tracking info for users with suspended enrolments diff --git a/mod/forum/post.php b/mod/forum/post.php index 7d9e3abc288..5b0c81cd2f6 100644 --- a/mod/forum/post.php +++ b/mod/forum/post.php @@ -464,7 +464,9 @@ if (!empty($forum)) { } echo $OUTPUT->header(); - echo $OUTPUT->heading(format_string($forum->name), 2); + if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($forum->name), 2); + } echo $OUTPUT->confirm(get_string("deletesureplural", "forum", $replycount + 1), "post.php?delete=$delete&confirm=$delete", $CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.'#p'.$post->id); @@ -487,7 +489,9 @@ if (!empty($forum)) { echo $postsrenderer->render($USER, [$forumentity], [$discussionentity], $postentities); } else { echo $OUTPUT->header(); - echo $OUTPUT->heading(format_string($forum->name), 2); + if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($forum->name), 2); + } echo $OUTPUT->confirm(get_string("deletesure", "forum", $replycount), "post.php?delete=$delete&confirm=$delete", $CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.'#p'.$post->id); @@ -634,7 +638,9 @@ if (!empty($forum)) { $PAGE->set_title(format_string($discussion->name).": ".format_string($post->subject)); $PAGE->set_heading($course->fullname); echo $OUTPUT->header(); - echo $OUTPUT->heading(format_string($forum->name), 2); + if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($forum->name), 2); + } echo $OUTPUT->heading(get_string('pruneheading', 'forum'), 3); $prunemform->display(); @@ -1087,9 +1093,12 @@ if ($edit) { $PAGE->set_title("{$course->shortname}: {$strdiscussionname}{$titlesubject}"); $PAGE->set_heading($course->fullname); +$PAGE->set_secondary_active_tab("modulepage"); echo $OUTPUT->header(); -echo $OUTPUT->heading(format_string($forum->name), 2); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($forum->name), 2); +} // Checkup. if (!empty($parententity) && !$capabilitymanager->can_view_post($USER, $discussionentity, $parententity)) { diff --git a/mod/forum/renderer.php b/mod/forum/renderer.php index ff5f9948405..cc653e1bcaf 100644 --- a/mod/forum/renderer.php +++ b/mod/forum/renderer.php @@ -234,10 +234,35 @@ class mod_forum_renderer extends plugin_renderer_base { * Render quick search form. * * @param \mod_forum\output\quick_search_form $form The renderable. - * @return string + * @return string rendered HTML string from the template. */ public function render_quick_search_form(\mod_forum\output\quick_search_form $form) { - return $this->render_from_template('mod_forum/quick_search_form', $form->export_for_template($this)); + if (strpos($this->page->url->get_path(), "index.php")) { + return $this->render_from_template('mod_forum/quick_search_form', $form->export_for_template($this)); + } + + return $this->render_from_template('mod_forum/forum_new_discussion_actionbar', $form->export_for_template($this)); + } + + /** + * Render the view action area. + * + * @param \mod_forum\output\forum_actionbar $actionbar forum_actionbar object. + * @return string rendered HTML string + */ + public function render_activity_actionbar(\mod_forum\output\forum_actionbar $actionbar): string { + return $this->render_from_template('mod_forum/forum_actionbar', $actionbar->export_for_template($this)); + } + + /** + * Render the subscription action area. + * + * @param \mod_forum\output\subscription_actionbar $subscriptionactionbar subscription_actionbar object. + * @return bool|string rendered HTML string. + */ + public function subscription_actionbar(\mod_forum\output\subscription_actionbar $subscriptionactionbar): string { + return $this->render_from_template('mod_forum/forum_subscription_action', + $subscriptionactionbar->export_for_template($this)); } /** diff --git a/mod/forum/report/summary/index.php b/mod/forum/report/summary/index.php index 9159430f5e8..37d037ec36f 100644 --- a/mod/forum/report/summary/index.php +++ b/mod/forum/report/summary/index.php @@ -109,6 +109,10 @@ $PAGE->set_title($title); $PAGE->set_heading($course->fullname); $PAGE->navbar->add(get_string('nodetitle', 'forumreport_summary')); +// Activate the secondary nav tab. +navigation_node::override_active_url(new moodle_url('/mod/forum/report/summary/index.php', + ['courseid' => $courseid, 'forumid' => $forumid])); + $allowbulkoperations = !$download && !empty($CFG->messaging) && has_capability('moodle/course:bulkmessaging', $context); $canseeprivatereplies = false; $hasviewall = false; diff --git a/mod/forum/report/summary/tests/behat/bulk_message.feature b/mod/forum/report/summary/tests/behat/bulk_message.feature index e9332b7a410..0055ad5b01a 100644 --- a/mod/forum/report/summary/tests/behat/bulk_message.feature +++ b/mod/forum/report/summary/tests/behat/bulk_message.feature @@ -41,7 +41,7 @@ Feature: Message users in the summary report | user | course | role | | student3 | C1 | student | When I am on the forum1 "forum activity" page logged in as teacher1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration And I click on "Select 'Student 1'" "checkbox" And I click on "Select 'Student 3'" "checkbox" And I set the field "With selected users..." to "Send a message" @@ -61,7 +61,7 @@ Feature: Message users in the summary report @javascript Scenario: Message all users When I am on the forum1 "forum activity" page logged in as teacher1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration And I click on "Select all" "checkbox" And I set the field "With selected users..." to "Send a message" Then I should see "Send message to 3 people" @@ -71,6 +71,6 @@ Feature: Message users in the summary report Given the following config values are set as admin: | messaging | 0 | When I am on the forum1 "forum activity" page logged in as teacher1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then I should not see "With selected users..." And I should not see "Select all" diff --git a/mod/forum/report/summary/tests/behat/course_summary.feature b/mod/forum/report/summary/tests/behat/course_summary.feature index 73ee19d326c..f4374cfdd26 100644 --- a/mod/forum/report/summary/tests/behat/course_summary.feature +++ b/mod/forum/report/summary/tests/behat/course_summary.feature @@ -56,7 +56,7 @@ Feature: Course level forum summary report Scenario: Course forum summary report can be viewed by teacher and contains accurate data When I am on the forum2 "forum activity" page logged in as teacher1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration And I should see "Export posts" And the following should exist in the "forumreport_summary_table" table: # | | Discussions | Replies | | | @@ -91,7 +91,7 @@ Feature: Course level forum summary report When I log in as "student1" And I am on "Course 1" course homepage And I follow "forum1" - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration And the following should exist in the "forumreport_summary_table" table: # | | Discussions | Replies | | | | First name / Surname | -2- | -3- | Earliest post | Most recent post | diff --git a/mod/forum/report/summary/tests/behat/double_enrolments_summary_data.feature b/mod/forum/report/summary/tests/behat/double_enrolments_summary_data.feature index 294af2303b4..2bd204f375f 100644 --- a/mod/forum/report/summary/tests/behat/double_enrolments_summary_data.feature +++ b/mod/forum/report/summary/tests/behat/double_enrolments_summary_data.feature @@ -47,7 +47,7 @@ Feature: forum report shows post/reply/word counts correctly When I log in as "teacher1" And I am on "Course 1" course homepage And I follow "forum1" - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then "Teacher 1" row "Number of attachments" column of "forumreport_summary_table" table should contain "6" And "Student 1" row "Number of attachments" column of "forumreport_summary_table" table should contain "5" And "Student 1" row "Word count" column of "forumreport_summary_table" table should contain "4" diff --git a/mod/forum/report/summary/tests/behat/private_replies.feature b/mod/forum/report/summary/tests/behat/private_replies.feature index e282d01a31d..d59567a4129 100644 --- a/mod/forum/report/summary/tests/behat/private_replies.feature +++ b/mod/forum/report/summary/tests/behat/private_replies.feature @@ -42,7 +42,7 @@ Feature: Include private replies in the summary report Scenario: Private replies are counted for Teacher When I am on the forum1 "forum activity" page logged in as teacher2 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then "Teacher 1" row "Number of replies posted" column of "forumreport_summary_table" table should contain "3" Scenario: Private replies are not counted when Teacher has not capability @@ -50,5 +50,5 @@ Feature: Include private replies in the summary report | capability | permission | role | contextlevel | reference | | mod/forum:readprivatereplies | Prevent | editingteacher | Course | C1 | When I am on the forum1 "forum activity" page logged in as teacher2 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then "Teacher 1" row "Number of replies posted" column of "forumreport_summary_table" table should contain "2" diff --git a/mod/forum/report/summary/tests/behat/summary_data_access.feature b/mod/forum/report/summary/tests/behat/summary_data_access.feature index 21ee76967dc..fcd9397793d 100644 --- a/mod/forum/report/summary/tests/behat/summary_data_access.feature +++ b/mod/forum/report/summary/tests/behat/summary_data_access.feature @@ -34,7 +34,7 @@ Feature: Report relevant content availability @javascript Scenario: Teachers can access report data about other users by default Given I am on the "forum1" "forum activity" page logged in as teacher1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then the following should exist in the "forumreport_summary_table" table: | -2- | -3- | -4- | -5- | -6- | -7- | -8- | | Student 1 | 1 | 1 | 5 | 0 | 3 | 14 | @@ -64,7 +64,7 @@ Feature: Report relevant content availability | capability | permission | role | contextlevel | reference | | forumreport/summary:view | Allow | student | Course | C1 | When I am on the "forum1" "forum activity" page logged in as student1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then the following should exist in the "forumreport_summary_table" table: | -1- | -2- | -3- | -4- | -5- | -6- | -7- | | Student 1 | 1 | 1 | 5 | 1 | 3 | 14 | diff --git a/mod/forum/report/summary/tests/behat/summary_data_attachments.feature b/mod/forum/report/summary/tests/behat/summary_data_attachments.feature index ba572c3e676..95fef9eb4b6 100644 --- a/mod/forum/report/summary/tests/behat/summary_data_attachments.feature +++ b/mod/forum/report/summary/tests/behat/summary_data_attachments.feature @@ -42,7 +42,7 @@ Feature: Attachments count column data available | user | forum | name | message | attachments | inlineattachments | | teacher1 | forum1 | discussion1 | message1 | att1.jpg, att2.txt | | When I am on the forum1C1 "forum activity" page logged in as teacher1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then "Teacher 1" row "Number of attachments" column of "forumreport_summary_table" table should contain "6" And "Student 1" row "Number of attachments" column of "forumreport_summary_table" table should contain "5" And "Student 2" row "Number of attachments" column of "forumreport_summary_table" table should contain "0" diff --git a/mod/forum/report/summary/tests/behat/summary_data_post_dates.feature b/mod/forum/report/summary/tests/behat/summary_data_post_dates.feature index 1fbae563910..1864c44e8a1 100644 --- a/mod/forum/report/summary/tests/behat/summary_data_post_dates.feature +++ b/mod/forum/report/summary/tests/behat/summary_data_post_dates.feature @@ -44,7 +44,7 @@ Feature: Post date columns data available | teacher1 | forum1 | discussion1 | t1 other course | ##2017-01-01 03:00:00## | | teacher1 | forum1 | discussion2 | t1 other course | ##2019-09-13 23:59:00## | When I am on the forum1C1 "forum activity" page logged in as teacher1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then "Teacher 1" row "Earliest post" column of "forumreport_summary_table" table should contain "Tuesday, 2 January 2018, 9:00" Then "Teacher 1" row "Most recent post" column of "forumreport_summary_table" table should contain "Sunday, 1 September 2019, 7:00" Then "Student 1" row "Earliest post" column of "forumreport_summary_table" table should contain "Wednesday, 27 March 2019, 4:00" diff --git a/mod/forum/report/summary/tests/behat/summary_filter_groups.feature b/mod/forum/report/summary/tests/behat/summary_filter_groups.feature index 323230e4d43..34d1a94decd 100644 --- a/mod/forum/report/summary/tests/behat/summary_filter_groups.feature +++ b/mod/forum/report/summary/tests/behat/summary_filter_groups.feature @@ -63,7 +63,7 @@ Feature: Groups report filter is available if groups exist @javascript Scenario: All groups can be selected or cleared together in the groups filter, and are unchecked by default When I am on the "c1forum1" "forum activity" page logged in as teacher1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then "Groups" "button" should exist And the following should exist in the "forumreport_summary_table" table: # | | Discussions | Replies | @@ -111,7 +111,7 @@ Feature: Groups report filter is available if groups exist @javascript Scenario: The summary report can be filtered by a subset of groups, and re-ordering the results retains the filter When I am on the "c1forum1" "forum activity" page logged in as teacher1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then "Groups" "button" should exist And the following should exist in the "forumreport_summary_table" table: # | | Discussions | Replies | @@ -145,7 +145,7 @@ Feature: Groups report filter is available if groups exist @javascript Scenario: The summary report can be filtered as a mixture of groups and no groups When I am on the "c1forum2" "forum activity" page logged in as teacher1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then "Groups" "button" should exist And the following should exist in the "forumreport_summary_table" table: # | | Discussions | Replies | @@ -169,7 +169,7 @@ Feature: Groups report filter is available if groups exist @javascript Scenario: The summary report can be filtered by no groups only When I am on the "c1forum2" "forum activity" page logged in as teacher1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then the following should exist in the "forumreport_summary_table" table: # | | Discussions | Replies | | First name / Surname | -3- | -4- | @@ -192,7 +192,7 @@ Feature: Groups report filter is available if groups exist Scenario: Filtering by a group containing no users still allows the page to render # Log in as admin so Teacher 1 not existing on page can be confirmed. When I am on the "c1forum1" "forum activity" page logged in as admin - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then "Groups" "button" should exist And the following should exist in the "forumreport_summary_table" table: # | | Discussions | Replies | @@ -215,7 +215,7 @@ Feature: Groups report filter is available if groups exist @javascript Scenario: Course forum summary report can be filtered by group When I am on the "c1forum2" "forum activity" page logged in as teacher1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration And I select "All forums in course" from the "Forum selected" singleselect And I click on "Groups" "button" And I click on "Clear" "button" in the "filter-groups-popover" "region" diff --git a/mod/forum/report/summary/tests/behat/summary_filter_no_groups.feature b/mod/forum/report/summary/tests/behat/summary_filter_no_groups.feature index 5ba84b6d5dc..ec81545e3ce 100644 --- a/mod/forum/report/summary/tests/behat/summary_filter_no_groups.feature +++ b/mod/forum/report/summary/tests/behat/summary_filter_no_groups.feature @@ -50,7 +50,7 @@ Feature: Groups report filter is not available if no groups exist | teacher1 | forum1 | discussion1 | D1 other course | ## 1 week ago ## | | teacher1 | forum1 | discussion2 | D2 other course | ## 4 days ago ## | When I am on the forum1C1 "forum activity" page logged in as teacher1 - And I navigate to "Forum summary report" in current page administration + And I navigate to "Reports" in current page administration Then "Groups" "button" should not exist And the following should exist in the "forumreport_summary_table" table: # | | Discussions | diff --git a/mod/forum/search.php b/mod/forum/search.php index 19049fa4b8f..b0757eb045b 100644 --- a/mod/forum/search.php +++ b/mod/forum/search.php @@ -71,6 +71,7 @@ $starredonly = optional_param('starredonly', false, PARAM_BOOL); // Include only $PAGE->set_pagelayout('standard'); $PAGE->set_url($FULLME); //TODO: this is very sloppy --skodak +$PAGE->set_secondary_active_tab("coursehome"); if (empty($search)) { // Check the other parameters instead if (!empty($words)) { @@ -166,7 +167,9 @@ if (!$posts = forum_search_posts($searchterms, $course->id, $page*$perpage, $per $PAGE->set_title($strsearchresults); $PAGE->set_heading($course->fullname); echo $OUTPUT->header(); - echo $OUTPUT->heading($strforums, 2); + if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading($strforums, 2); + } echo $OUTPUT->heading($strsearchresults, 3); echo $OUTPUT->heading(get_string("noposts", "forum"), 4); @@ -220,7 +223,9 @@ echo html_writer::link($url, get_string('advancedsearch', 'forum').'...'); echo ''; -echo $OUTPUT->heading($strforums, 2); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading($strforums, 2); +} echo $OUTPUT->heading("$strsearchresults: $totalcount", 3); $url = new moodle_url('search.php', array('search' => $search, 'id' => $course->id, 'perpage' => $perpage)); diff --git a/mod/forum/subscribers.php b/mod/forum/subscribers.php index 2e62c44df5a..4ed7dc26c87 100644 --- a/mod/forum/subscribers.php +++ b/mod/forum/subscribers.php @@ -35,8 +35,11 @@ if ($group !== 0) { $url->param('group', $group); } if ($edit !== 0) { - $url->param('edit', $edit); + $url->param('edit', 'on'); +} else { + $url->param('edit', 'off'); } + $PAGE->set_url($url); $forum = $DB->get_record('forum', array('id'=>$id), '*', MUST_EXIST); @@ -100,21 +103,20 @@ $strsubscribers = get_string("subscribers", "forum"); $PAGE->navbar->add($strsubscribers, $url); $PAGE->set_title($strsubscribers); $PAGE->set_heading($COURSE->fullname); -if (has_capability('mod/forum:managesubscriptions', $context) && \mod_forum\subscriptions::is_forcesubscribed($forum) === false) { - if ($edit != -1) { - $USER->subscriptionsediting = $edit; - } - $updatesubscriptionsbutton = forum_update_subscriptions_button($course->id, $id); -} else { - $updatesubscriptionsbutton = ''; - unset($USER->subscriptionsediting); -} + +// Activate the secondary nav tab. +$PAGE->set_secondary_active_tab("forumsubscriptions"); + +// Output starts from here. +$actionbar = new \mod_forum\output\subscription_actionbar($id, $url, $forum); echo $OUTPUT->header(); -echo $OUTPUT->heading(get_string('forum', 'forum').' '.$strsubscribers); -if (!empty($updatesubscriptionsbutton)) { - echo \html_writer::div($updatesubscriptionsbutton, 'float-right'); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(get_string('forum', 'forum') . ' ' . $strsubscribers); } -if (empty($USER->subscriptionsediting)) { +echo $forumoutput->subscription_actionbar($actionbar); + + +if ($edit === 0) { $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum, $currentgroup, $context); if (\mod_forum\subscriptions::is_forcesubscribed($forum)) { $subscribers = mod_forum_filter_hidden_users($cm, $context, $subscribers); @@ -123,9 +125,7 @@ if (empty($USER->subscriptionsediting)) { } else { echo $forumoutput->subscriber_selection_form($existingselector, $subscriberselector); } -if (!empty($updatesubscriptionsbutton)) { - echo $updatesubscriptionsbutton; -} + echo $OUTPUT->footer(); /** diff --git a/mod/forum/templates/discussion_list.mustache b/mod/forum/templates/discussion_list.mustache index d63e483b666..a7b284e4596 100644 --- a/mod/forum/templates/discussion_list.mustache +++ b/mod/forum/templates/discussion_list.mustache @@ -52,11 +52,13 @@
{{#forum.capabilities.create}} - - {{$discussion_create_text}} - {{#str}}addanewdiscussion, forum{{/str}} - {{/discussion_create_text}} - + {{#enablediscussioncreation}} + + {{$discussion_create_text}} + {{#str}}addanewdiscussion, forum{{/str}} + {{/discussion_create_text}} + + {{/enablediscussioncreation}} {{/forum.capabilities.create}} {{^forum.capabilities.create}} {{#forum.capabilities.selfenrol}} diff --git a/mod/forum/templates/forum_actionbar.mustache b/mod/forum/templates/forum_actionbar.mustache new file mode 100644 index 00000000000..79b5d8429a5 --- /dev/null +++ b/mod/forum/templates/forum_actionbar.mustache @@ -0,0 +1,69 @@ +{{! + 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 mod_forum/forum_actionbar + Simple search input. + Context variables required for this template: + * see mod/forum/classes/output/forum_actionbar.php + Example context (json): + { + "action": "https://moodle.local/mod/forum/search.php", + "inputname": "search", + "searchstring": "Search settings", + "query": "themedesigner", + "hiddenfields": [{ + "name": "id", + "value": "11" + }], + "helpicon": { + "heading": "Search", + "text": "

For basic searching .

", + "alt": "Help with search", + "icon": [{ + "attributes": [{ + "name": "alt", + "value": "Help with Search" + }, { + "name": "src", + "value": "http://localhost/theme/image.php?theme=boost&component=core&image=help" + }] + }] + }, + "newdiscussionbtn": "Add discussion topic", + "subscribetoforum": "http://localhost/moodle/mod/forum/subscribe.php?id=7&sesskey=abcd&returnurl=http//localhost/moodle/mod/forum/view.php?id=4", + "unsubscribefromforum": "http://localhost/moodle/mod/forum/subscribe.php?id=7&sesskey=abcd&returnurl=http//localhost/moodle/mod/forum/view.php?id=4" + } +}} + +
+
+
+ {{> mod_forum/quick_search_form }} +
+
+ {{{newdiscussionbtn}}} +
+
+ {{#subscribetoforum}} + {{#str}}subscribe, mod_forum {{/str}} + {{/subscribetoforum}} + {{#unsubscribefromforum}} + {{#str}}unsubscribe, mod_forum {{/str}} + {{/unsubscribefromforum}} +
+
+
diff --git a/mod/forum/templates/forum_new_discussion_actionbar.mustache b/mod/forum/templates/forum_new_discussion_actionbar.mustache new file mode 100644 index 00000000000..2f561b227ce --- /dev/null +++ b/mod/forum/templates/forum_new_discussion_actionbar.mustache @@ -0,0 +1,49 @@ +{{! + 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 mod_forum/forum_new_discussion_actionbar + Add button to create a new discussion in the forum activity. + Classes required for JS: + * none + Data attributes required for JS: + * none + Context variables required for this template: + * see mod/forum/classes/output/activity_actionbar.php + Example context (json): + { + "forum": { + "id": 3, + "name": "Forum test", + "state": [], + "userstate": "", + "capabilities": [{ + "viewdiscussions": true, + "create": true, + "selfenrol": false + }], + "urls": [{ + "create": "http://localhost/mod/forum/post.php?forum=11" + }] + } + } +}} + +{{#forum.capabilities.create}} + + {{#str}}addanewdiscussion, forum{{/str}} + +{{/forum.capabilities.create}} diff --git a/mod/forum/templates/forum_subscription_action.mustache b/mod/forum/templates/forum_subscription_action.mustache new file mode 100644 index 00000000000..2fca1384ef3 --- /dev/null +++ b/mod/forum/templates/forum_subscription_action.mustache @@ -0,0 +1,82 @@ +{{! + 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 mod_forum/forum_subscription_action + Actions bar for the subscribers page UI. + Classes required for JS: + * none + Data attributes required for JS: + * data-region + Context variables required for this template: + * see mod/forum/classes/output/subscription_actionbar.php + Example context (json): + { + "subscriptionoptions": { + "formid": "selectsubscriptions", + "classes": "urlselect float-right", + "disabled": false, + "sesskey": "abcdef", + "action": "http://localhost/course/jumpto.php", + "helpicon": false, + "options": [ + { + "name": "Subscription disabled", + "value": "" + }, + { + "name": "Optional subscrition", + "value": "/mod/forum/subscribe.php?id=3&mode=0&sesskey=abc123" + } + ] + }, + "viewandmanageselect": { + "formid": "selectviewandmanagesubscribers", + "classes": "urlselect", + "label": "Subscribers", + "disabled": false, + "sesskey": "abcdef", + "action": "http://localhost/course/jumpto.php", + "options": [ + { + "name": "View subscribers", + "value": "/mod/forum/subscribers.php?id=3&edit=off", + "selected": true + }, + { + "name": "Manage subscribers", + "value": "/mod/forum/subscribers.php?id=3&edit=on", + "selected": false + } + ] + } + } +}} +
+
+
+ {{#viewandmanageselect}} + {{>core/url_select}} + {{/viewandmanageselect}} +
+
+ {{#subscriptionoptions}} + {{>core/url_select}} + {{/subscriptionoptions}} +
+
+
+
diff --git a/mod/forum/templates/quick_search_form.mustache b/mod/forum/templates/quick_search_form.mustache index 21b22c6f32c..5d230110e42 100644 --- a/mod/forum/templates/quick_search_form.mustache +++ b/mod/forum/templates/quick_search_form.mustache @@ -30,5 +30,4 @@ {{#helpicon}} {{>core/help_icon}} {{/helpicon}} -{{< core/search_input }} -{{/ core/search_input }} +{{>core/search_input}} diff --git a/mod/forum/tests/behat/advanced_search.feature b/mod/forum/tests/behat/advanced_search.feature index c7667fff8be..b6ce9edd329 100644 --- a/mod/forum/tests/behat/advanced_search.feature +++ b/mod/forum/tests/behat/advanced_search.feature @@ -39,20 +39,20 @@ Feature: The forum search allows users to perform advanced searches for forum po Scenario: Perform an advanced search using any term Given I am on the "Announcements" "forum activity" page logged in as student1 - And I press "Search forums" + And I press "Search" And I should see "Advanced search" And I set the field "words" to "subject" - When I press "Search forums" + When I press "Search" Then I should see "My subject" And I should see "Your subjective" Scenario: Perform an advanced search avoiding words Given I am on the "Announcements" "forum activity" page logged in as student1 - And I press "Search forums" + And I press "Search" And I should see "Advanced search" And I set the field "words" to "My" And I set the field "notwords" to "subjective" - When I press "Search forums" + When I press "Search" Then I should see "My subject" And I should not see "Your subjective" @@ -61,19 +61,19 @@ Feature: The forum search allows users to perform advanced searches for forum po | mysql | | postgres | And I am on the "Announcements" "forum activity" page logged in as student1 - And I press "Search forums" + And I press "Search" And I should see "Advanced search" And I set the field "fullwords" to "subject" - When I press "Search forums" + When I press "Search" Then I should see "My subject" And I should not see "Your subjective" Scenario: Perform an advanced search matching the subject Given I am on the "Announcements" "forum activity" page logged in as student1 - And I press "Search forums" + And I press "Search" And I should see "Advanced search" And I set the field "subject" to "subjective" - When I press "Search forums" + When I press "Search" Then I should not see "My message" And I should see "Your subjective" @@ -85,19 +85,19 @@ Feature: The forum search allows users to perform advanced searches for forum po | Message | My message | And I log out When I am on the "Announcements" "forum activity" page logged in as student1 - And I press "Search forums" + And I press "Search" And I should see "Advanced search" And I set the field "user" to "TWO" - And I press "Search forums" + And I press "Search" Then I should see "Teacher TWO" And I should not see "Teacher ONE" Scenario: Perform an advanced search with multiple words Given I am on the "Announcements" "forum activity" page logged in as student1 - And I press "Search forums" + And I press "Search" And I should see "Advanced search" And I set the field "subject" to "your subjective" - When I press "Search forums" + When I press "Search" Then I should not see "My message" And I should see "Your subjective" @@ -111,10 +111,10 @@ Feature: The forum search allows users to perform advanced searches for forum po And I press "Save changes" And I log out And I am on the "Announcements" "forum activity" page logged in as student1 - And I press "Search forums" + And I press "Search" And I should see "Advanced search" And I set the field "Is tagged with" to "SearchedTag" - When I press "Search forums" + When I press "Search" Then I should see "My subject" And I should not see "Your subjective" @@ -123,10 +123,10 @@ Feature: The forum search allows users to perform advanced searches for forum po Given I am on the "Announcements" "forum activity" page logged in as student1 And I click on "Your subjective" action menu And I follow "Star this discussion" - And I press "Search forums" + And I press "Search" And I should see "Advanced search" And I set the field "starredonly" to "1" - When I press "Search forums" + When I press "Search" Then I should not see "My message" And I should see "Your subjective" @@ -135,10 +135,10 @@ Feature: The forum search allows users to perform advanced searches for forum po Given I am on the "Announcements" "forum activity" page logged in as student1 And I click on "Your subjective" action menu And I follow "Star this discussion" - And I press "Search forums" + And I press "Search" And I should see "Advanced search" And I set the field "words" to "message" And I set the field "starredonly" to "1" - When I press "Search forums" + When I press "Search" Then I should not see "My message" And I should see "Your subjective" diff --git a/mod/forum/tests/behat/behat_mod_forum.php b/mod/forum/tests/behat/behat_mod_forum.php index f6025b6ec62..9173933426c 100644 --- a/mod/forum/tests/behat/behat_mod_forum.php +++ b/mod/forum/tests/behat/behat_mod_forum.php @@ -46,7 +46,7 @@ class behat_mod_forum extends behat_base { * @param TableNode $table */ public function i_add_a_new_topic_to_forum_with($forumname, TableNode $table) { - $this->add_new_discussion($forumname, $table, get_string('addanewtopic', 'forum')); + $this->add_new_discussion($forumname, $table, get_string('addanewdiscussion', 'forum')); } /** @@ -57,7 +57,7 @@ class behat_mod_forum extends behat_base { * @param TableNode $table */ public function i_add_a_new_question_to_forum_with($forumname, TableNode $table) { - $this->add_new_discussion($forumname, $table, get_string('addanewquestion', 'forum')); + $this->add_new_discussion($forumname, $table, get_string('addanewdiscussion', 'forum')); } /** @@ -273,15 +273,7 @@ class behat_mod_forum extends behat_base { * @Given /^I can subscribe to this forum$/ */ public function i_can_subscribe_to_this_forum() { - if ($this->running_javascript()) { - $this->execute('behat_general::i_click_on', [get_string('actionsmenu'), 'link']); - } - $this->execute('behat_general::assert_page_contains_text', [get_string('subscribe', 'mod_forum')]); - - if ($this->running_javascript()) { - $this->execute('behat_general::i_click_on', [get_string('actionsmenu'), 'link']); - } } /** @@ -290,15 +282,7 @@ class behat_mod_forum extends behat_base { * @Given /^I can unsubscribe from this forum$/ */ public function i_can_unsubscribe_from_this_forum() { - if ($this->running_javascript()) { - $this->execute('behat_general::i_click_on', [get_string('actionsmenu'), 'link']); - } - $this->execute('behat_general::assert_page_contains_text', [get_string('unsubscribe', 'mod_forum')]); - - if ($this->running_javascript()) { - $this->execute('behat_general::i_click_on', [get_string('actionsmenu'), 'link']); - } } /** @@ -307,10 +291,6 @@ class behat_mod_forum extends behat_base { * @Given /^I subscribe to this forum$/ */ public function i_subscribe_to_this_forum() { - if ($this->running_javascript()) { - $this->execute('behat_general::i_click_on', [get_string('actionsmenu'), 'link']); - } - $this->execute('behat_general::click_link', [get_string('subscribe', 'mod_forum')]); } @@ -320,10 +300,6 @@ class behat_mod_forum extends behat_base { * @Given /^I unsubscribe from this forum$/ */ public function i_unsubscribe_from_this_forum() { - if ($this->running_javascript()) { - $this->execute('behat_general::i_click_on', [get_string('actionsmenu'), 'link']); - } - $this->execute('behat_general::click_link', [get_string('unsubscribe', 'mod_forum')]); } diff --git a/mod/forum/tests/behat/discussion_subscriptions.feature b/mod/forum/tests/behat/discussion_subscriptions.feature index 7f26d1150a0..df82afa2858 100644 --- a/mod/forum/tests/behat/discussion_subscriptions.feature +++ b/mod/forum/tests/behat/discussion_subscriptions.feature @@ -50,7 +50,7 @@ Feature: A user can control their own subscription preferences for a discussion And I can subscribe to this forum And "Unsubscribe from this discussion" "checkbox" should exist in the "Test post subject one" "table_row" And "Subscribe to this discussion" "checkbox" should exist in the "Test post subject two" "table_row" - And I subscribe to this forum + And I follow "Subscribe to forum" And I should see "Student One will be notified of new posts in 'Test forum name'" And I can unsubscribe from this forum And "Unsubscribe from this discussion" "checkbox" should exist in the "Test post subject one" "table_row" @@ -149,50 +149,6 @@ Feature: A user can control their own subscription preferences for a discussion And "Unsubscribe from this discussion" "checkbox" should exist in the "Test post subject one" "table_row" And "Subscribe to this discussion" "checkbox" should exist in the "Test post subject two" "table_row" - @javascript - Scenario: A user does not lose their preferences when a forum is switch from optional to automatic - Given the following "activity" exists: - | activity | forum | - | course | C1 | - | idnumber | forum1 | - | name | Test forum name | - | intro | Test forum description | - | type | general | - | forcesubscribe | 0 | - And I am on "Course 1" course homepage - And I add a new discussion to "Test forum name" forum with: - | Subject | Test post subject one | - | Message | Test post message one | - And I add a new discussion to "Test forum name" forum with: - | Subject | Test post subject two | - | Message | Test post message two | - And I log out - And I am on the "Test forum name" "forum activity" page logged in as student1 - And I can subscribe to this forum - And "Subscribe to this discussion" "checkbox" should exist in the "Test post subject one" "table_row" - And "Subscribe to this discussion" "checkbox" should exist in the "Test post subject two" "table_row" - And I click on "input[id^=subscription-toggle]" "css_element" in the "Test post subject one" "table_row" - And I can subscribe to this forum - And "Unsubscribe from this discussion" "checkbox" should exist in the "Test post subject one" "table_row" - And "Subscribe to this discussion" "checkbox" should exist in the "Test post subject two" "table_row" - And I log out - And I log in as "admin" - And I am on the "Test forum name" "forum activity" page - And I navigate to "Settings" in current page administration - And I set the following fields to these values: - | Subscription mode | Auto subscription | - And I press "Save and return to course" - And I log out - And I am on the "Test forum name" "forum activity" page logged in as student1 - And I can unsubscribe from this forum - And "Unsubscribe from this discussion" "checkbox" should exist in the "Test post subject one" "table_row" - And "Unsubscribe from this discussion" "checkbox" should exist in the "Test post subject two" "table_row" - When I unsubscribe from this forum - And I should see "Student One will NOT be notified of new posts in 'Test forum name'" - And I can subscribe to this forum - And "Unsubscribe from this discussion" "checkbox" should exist in the "Test post subject one" "table_row" - And "Subscribe to this discussion" "checkbox" should exist in the "Test post subject two" "table_row" - Scenario: An optional forum prompts a user to subscribe to a discussion when posting unless they have already chosen not to subscribe Given the following "activity" exists: | activity | forum | @@ -211,7 +167,7 @@ Feature: A user can control their own subscription preferences for a discussion | Message | Test post message two | And I log out When I am on the "Test forum name" "forum activity" page logged in as student1 - And I should see "Subscribe to this forum" + And I should see "Subscribe to forum" And I reply "Test post subject one" post from "Test forum name" forum with: | Subject | Reply 1 to discussion 1 | | Message | Discussion contents 1, second message | @@ -247,17 +203,24 @@ Feature: A user can control their own subscription preferences for a discussion And I add a new discussion to "Test forum name" forum with: | Subject | Test post subject two | | Message | Test post message two | + # added for this scenario + And the following "users" exist: + | username | firstname | lastname | email | + | student2 | Student | Two | student.two@example.com | + And the following "course enrolments" exist: + | user | course | role | + | student2 | C1 | student | And I log out - When I am on the "Test forum name" "forum activity" page logged in as student1 - And I should see "Unsubscribe from this forum" + When I am on the "Test forum name" "forum activity" page logged in as student2 + And I should see "Unsubscribe from forum" And I reply "Test post subject one" post from "Test forum name" forum with: - | Subject | Reply 1 to discussion 1 | - | Message | Discussion contents 1, second message | - | Discussion subscription | 1 | + | Subject | Reply 1 to discussion 1 | + | Message | Discussion contents 1, second message | + | Discussion subscription | 1 | And I reply "Test post subject two" post from "Test forum name" forum with: - | Subject | Reply 1 to discussion 1 | - | Message | Discussion contents 1, second message | - | Discussion subscription | 0 | + | Subject | Reply 1 to discussion 1 | + | Message | Discussion contents 1, second message | + | Discussion subscription | 0 | And I am on the "Test forum name" "forum activity" page Then "Unsubscribe from this discussion" "checkbox" should exist in the "Test post subject one" "table_row" And "Subscribe to this discussion" "checkbox" should exist in the "Test post subject two" "table_row" @@ -276,8 +239,8 @@ Feature: A user can control their own subscription preferences for a discussion And I am on site homepage And I turn editing mode on And I add a new discussion to "Test forum name" forum with: - | Subject | Test post subject one | - | Message | Test post message one | + | Subject | Test post subject one | + | Message | Test post message one | And I log out When I log in as "guest" And I follow "Test forum name" @@ -294,8 +257,8 @@ Feature: A user can control their own subscription preferences for a discussion And I am on site homepage And I turn editing mode on And I add a new discussion to "Test forum name" forum with: - | Subject | Test post subject one | - | Message | Test post message one | + | Subject | Test post subject one | + | Message | Test post message one | And I log out When I follow "Test forum name" Then "Subscribe to this discussion" "checkbox" should not exist in the "Test post subject one" "table_row" @@ -319,13 +282,13 @@ Feature: A user can control their own subscription preferences for a discussion | Message | Test post message one | And I log out When I am on the "Test forum name" "forum activity" page logged in as student1 - Then "Subscribe to this forum" "link" should exist in current page administration + Then "Subscribe to forum" "link" should exist And I follow "Test post subject one" And "You are not subscribed to this discussion. Click to subscribe" "link" should exist And I follow "Test forum name" - And I navigate to "Subscribe to this forum" in current page administration + And I follow "Subscribe to forum" And I should see "Student One will be notified of new posts in 'Test forum name'" - And "Unsubscribe from this forum" "link" should exist in current page administration + And "Unsubscribe from forum" "link" should exist And I follow "Test post subject one" And "You are subscribed to this discussion. Click to unsubscribe" "link" should exist And I follow "You are subscribed to this discussion. Click to unsubscribe" @@ -333,22 +296,22 @@ Feature: A user can control their own subscription preferences for a discussion And I follow "Test post subject one" And "You are not subscribed to this discussion. Click to subscribe" "link" should exist And I follow "Test forum name" - And I navigate to "Unsubscribe from this forum" in current page administration + And I follow "Unsubscribe from forum" And I should see "Student One will NOT be notified of new posts in 'Test forum name'" - And "Subscribe to this forum" "link" should exist in current page administration + And "Subscribe to forum" "link" should exist And I follow "Test post subject one" And "You are not subscribed to this discussion. Click to subscribe" "link" should exist And I follow "You are not subscribed to this discussion. Click to subscribe" And I should see "Student One will be notified of new posts in 'Test post subject one' of 'Test forum name'" And "Unsubscribe from this discussion" "checkbox" should exist in the "Test post subject one" "table_row" - And I navigate to "Subscribe to this forum" in current page administration + And I follow "Subscribe to forum" And I should see "Student One will be notified of new posts in 'Test forum name'" - And "Unsubscribe from this forum" "link" should exist in current page administration + And "Unsubscribe from forum" "link" should exist And I follow "Test post subject one" And "You are subscribed to this discussion. Click to unsubscribe" "link" should exist And I follow "Test forum name" - And I navigate to "Unsubscribe from this forum" in current page administration + And I follow "Unsubscribe from forum" And I should see "Student One will NOT be notified of new posts in 'Test forum name'" - And "Subscribe to this forum" "link" should exist in current page administration + And "Subscribe to forum" "link" should exist And I follow "Test post subject one" And "You are not subscribed to this discussion. Click to subscribe" "link" should exist diff --git a/mod/forum/tests/behat/edit_tags.feature b/mod/forum/tests/behat/edit_tags.feature index a6e522c94a8..849e9bedd6f 100644 --- a/mod/forum/tests/behat/edit_tags.feature +++ b/mod/forum/tests/behat/edit_tags.feature @@ -48,7 +48,7 @@ Feature: Edited forum posts handle tags correctly And I press "Continue" And I log out And I am on the "Test forum name" "forum activity" page logged in as teacher1 - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I click on "Advanced" "button" And I expand all fieldsets And I open the autocomplete suggestions list diff --git a/mod/forum/tests/behat/forum_subscriptions.feature b/mod/forum/tests/behat/forum_subscriptions.feature index ef40a0829c2..4f360e6b948 100644 --- a/mod/forum/tests/behat/forum_subscriptions.feature +++ b/mod/forum/tests/behat/forum_subscriptions.feature @@ -92,12 +92,12 @@ Feature: A user can control their own subscription preferences for a forum When I log in as "student1" And I am on "Course 1" course homepage And I follow "Test forum name" - Then I should see "Subscribe to this forum" - And I should not see "Unsubscribe from this forum" - And I follow "Subscribe to this forum" + Then I should see "Subscribe to forum" + And I should not see "Unsubscribe from forum" + And I follow "Subscribe to forum" And I should see "Student One will be notified of new posts in 'Test forum name'" - And I should see "Unsubscribe from this forum" - And I should not see "Subscribe to this forum" + And I should see "Unsubscribe from forum" + And I should not see "Subscribe to forum" Scenario: An Automatic forum can be unsubscribed from Given the following "activity" exists: @@ -121,9 +121,9 @@ Feature: A user can control their own subscription preferences for a forum When I log in as "student1" And I am on "Course 1" course homepage And I follow "Test forum name" - Then I should see "Unsubscribe from this forum" - And I should not see "Subscribe to this forum" - And I follow "Unsubscribe from this forum" + Then I should see "Unsubscribe from forum" + And I should not see "Subscribe to forum" + And I follow "Unsubscribe from forum" And I should see "Student One will NOT be notified of new posts in 'Test forum name'" - And I should see "Subscribe to this forum" - And I should not see "Unsubscribe from this forum" + And I should see "Subscribe to forum" + And I should not see "Unsubscribe from forum" diff --git a/mod/forum/tests/behat/forum_subscriptions_availability.feature b/mod/forum/tests/behat/forum_subscriptions_availability.feature index c94f8f02395..71d5bec5160 100644 --- a/mod/forum/tests/behat/forum_subscriptions_availability.feature +++ b/mod/forum/tests/behat/forum_subscriptions_availability.feature @@ -45,7 +45,7 @@ Feature: As a teacher I need to see an accurate list of subscribed users | Description | Test forum description | | Subscription mode | Forced subscription | And I am on the "Forced Forum 1" "forum activity" page - And I navigate to "Show/edit current subscribers" in current page administration + And I navigate to "Subscriptions" in current page administration Then I should see "Student 1" And I should see "Teacher Teacher" And I should see "Student 2" @@ -56,7 +56,7 @@ Feature: As a teacher I need to see an accurate list of subscribed users And I click on "Grouping" "button" in the "Add restriction..." "dialogue" And I set the field with xpath "//select[@name='id']" to "Grouping 1" And I press "Save and display" - And I navigate to "Show/edit current subscribers" in current page administration + And I navigate to "Subscriptions" in current page administration And I should see "Student 1" And I should see "Teacher Teacher" And I should not see "Student 2" @@ -78,12 +78,12 @@ Feature: As a teacher I need to see an accurate list of subscribed users | Availability | Show on course page | And I press "Save and return to course" And I am on the "Forced Forum 2" "forum activity" page - And I navigate to "Show/edit current subscribers" in current page administration + And I navigate to "Subscriptions" in current page administration Then I should see "Teacher Teacher" And I should see "Student 1" And I should see "Student 2" And I should see "Student 3" - And I should not see "Manage subscribers" + And the "Subscribers" select box should contain "View subscribers" Scenario: A forced and hidden forum lists only teachers Given the following "activity" exists: @@ -101,7 +101,7 @@ Feature: As a teacher I need to see an accurate list of subscribed users | Availability | Hide from students | And I press "Save and return to course" And I am on the "Forced Forum 2" "forum activity" page - And I navigate to "Show/edit current subscribers" in current page administration + And I navigate to "Subscriptions" in current page administration Then I should see "Teacher Teacher" And I should not see "Student 1" And I should not see "Student 2" @@ -115,7 +115,7 @@ Feature: As a teacher I need to see an accurate list of subscribed users | Description | Test forum description | | Subscription mode | Auto subscription | And I am on the "Forced Forum 1" "forum activity" page - And I navigate to "Show/edit current subscribers" in current page administration + And I navigate to "Subscriptions" in current page administration Then I should see "Student 1" And I should see "Teacher Teacher" And I should see "Student 2" @@ -127,7 +127,7 @@ Feature: As a teacher I need to see an accurate list of subscribed users And I click on "Grouping" "button" in the "Add restriction..." "dialogue" And I set the field with xpath "//select[@name='id']" to "Grouping 1" And I press "Save and display" - And I navigate to "Show/edit current subscribers" in current page administration + And I navigate to "Subscriptions" in current page administration And I should see "Student 1" And I should see "Teacher Teacher" And I should not see "Student 2" diff --git a/mod/forum/tests/behat/forum_subscriptions_default.feature b/mod/forum/tests/behat/forum_subscriptions_default.feature index c350aa6b84b..76a84a0bda9 100644 --- a/mod/forum/tests/behat/forum_subscriptions_default.feature +++ b/mod/forum/tests/behat/forum_subscriptions_default.feature @@ -27,12 +27,12 @@ Feature: A user can control their default discussion subscription settings Scenario: Creating a new discussion in an optional forum follows user preferences Given I am on the "Test forum name" "forum activity" page logged in as student1 - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" Then "input[name=discussionsubscribe][checked=checked]" "css_element" should exist And I log out And I am on the "Test forum name" "forum activity" page logged in as student2 - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I click on "Advanced" "button" And "input[name=discussionsubscribe]:not([checked=checked])" "css_element" should exist @@ -59,12 +59,12 @@ Feature: A user can control their default discussion subscription settings And I press "Save and return to course" And I log out And I am on the "Test forum name" "forum activity" page logged in as student1 - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" Then "input[name=discussionsubscribe][checked=checked]" "css_element" should exist And I log out And I am on the "Test forum name" "forum activity" page logged in as student2 - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I click on "Advanced" "button" And "input[name=discussionsubscribe][checked=checked]" "css_element" should exist diff --git a/mod/forum/tests/behat/forum_subscriptions_management.feature b/mod/forum/tests/behat/forum_subscriptions_management.feature index 6e877d32184..0deb3413665 100644 --- a/mod/forum/tests/behat/forum_subscriptions_management.feature +++ b/mod/forum/tests/behat/forum_subscriptions_management.feature @@ -29,26 +29,12 @@ Feature: A teacher can control the subscription to a forum When I log in as "teacher" And I am on "Course 1" course homepage And I follow "Test forum name" - And I navigate to "Settings" in current page administration - And I set the following fields to these values: - | Subscription mode | Auto subscription | - And I press "Save and return to course" - And I follow "Test forum name" - And I follow "Show/edit current subscribers" - Then ".userselector" "css_element" should not exist - And "Manage subscribers" "button" should exist - And I press "Manage subscribers" - And ".userselector" "css_element" should exist - And "Finish managing subscriptions" "button" should exist - And I press "Finish managing subscriptions" - And ".userselector" "css_element" should not exist - And "Manage subscribers" "button" should exist - And I press "Manage subscribers" - And ".userselector" "css_element" should exist - And "Finish managing subscriptions" "button" should exist - And I press "Finish managing subscriptions" - And ".userselector" "css_element" should not exist - And "Manage subscribers" "button" should exist + And I navigate to "Subscriptions" in current page administration + Then I select "Manage subscribers" from the "Subscribers" singleselect + And "Add" "button" should exist + And "Remove" "button" should exist + And I select "View subscribers" from the "Subscribers" singleselect + And the "Subscribers" select box should contain "View subscribers" @javascript Scenario Outline: Toggle forum subscription mode via settings navigation diff --git a/mod/forum/tests/behat/forum_subscriptions_mode_behaviour.feature b/mod/forum/tests/behat/forum_subscriptions_mode_behaviour.feature index 559a655e8d1..dbeba1f5d76 100644 --- a/mod/forum/tests/behat/forum_subscriptions_mode_behaviour.feature +++ b/mod/forum/tests/behat/forum_subscriptions_mode_behaviour.feature @@ -28,9 +28,10 @@ Feature: Changes to the subscription mode of a forum can change subcribers of a Scenario: A change from Forced subscription to Auto subcription causes all participants to be subscribed Given I follow "Test forum name" - And I navigate to "Subscription mode > Auto subscription" in current page administration - When I navigate to "Show/edit current subscribers" in current page administration + And I navigate to "Subscriptions" in current page administration + When I select "Auto subscription" from the "Subscriptions" singleselect Then I should not see "There are no subscribers yet for this forum" + And I navigate to "Subscriptions" in current page administration And I should see "Student 1" And I should see "student.1@example.com" And I should see "Student 2" diff --git a/mod/forum/tests/behat/groups_in_course_no_groups_in_forum.feature b/mod/forum/tests/behat/groups_in_course_no_groups_in_forum.feature index ae8af762fae..beca11cbbd3 100644 --- a/mod/forum/tests/behat/groups_in_course_no_groups_in_forum.feature +++ b/mod/forum/tests/behat/groups_in_course_no_groups_in_forum.feature @@ -35,7 +35,7 @@ Feature: Forums in 'No groups' mode allow posting to All participants for all us And I follow "Standard forum name" And I should not see "Group A" And I should not see "Group B" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" Then I should not see "Post a copy to all groups" And I should not see "Group" in the "form" "css_element" And I set the following fields to these values: @@ -51,7 +51,7 @@ Feature: Forums in 'No groups' mode allow posting to All participants for all us And I follow "Standard forum name" And I should not see "Group A" And I should not see "Group B" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" Then I should not see "Post a copy to all groups" And I should not see "Group" in the "form" "css_element" And I set the following fields to these values: diff --git a/mod/forum/tests/behat/h5p_inline_editing_content.feature b/mod/forum/tests/behat/h5p_inline_editing_content.feature index f59e5814152..759861df7ce 100644 --- a/mod/forum/tests/behat/h5p_inline_editing_content.feature +++ b/mod/forum/tests/behat/h5p_inline_editing_content.feature @@ -80,7 +80,7 @@ Feature: Inline editing H5P content in mod_forum Given I am on the "C1" "Course" page logged in as "admin" # Add H5P content to a forum post as admin. And I am on the "ForumName1" "forum activity" page - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I set the following fields to these values: | Subject | Forum post by admin | And I click on "Insert H5P" "button" in the "#fitem_id_message" "css_element" diff --git a/mod/forum/tests/behat/no_groups_in_course.feature b/mod/forum/tests/behat/no_groups_in_course.feature index 37148ac3e8d..887dddc35c0 100644 --- a/mod/forum/tests/behat/no_groups_in_course.feature +++ b/mod/forum/tests/behat/no_groups_in_course.feature @@ -23,7 +23,7 @@ Feature: Posting to forums in a course with no groups behaves correctly Given I log in as "teacher1" And I am on "Course 1" course homepage And I follow "Standard forum" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" Then I should not see "Post a copy to all groups" And I set the following fields to these values: | Subject | Teacher -> All participants | @@ -36,7 +36,7 @@ Feature: Posting to forums in a course with no groups behaves correctly Given I log in as "teacher1" And I am on "Course 1" course homepage And I follow "Separate forum" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" Then I should not see "Post a copy to all groups" And I set the following fields to these values: | Subject | Teacher -> All participants | @@ -49,7 +49,7 @@ Feature: Posting to forums in a course with no groups behaves correctly Given I log in as "teacher1" And I am on "Course 1" course homepage And I follow "Visible forum" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" Then I should not see "Post a copy to all groups" And I set the following fields to these values: | Subject | Teacher -> All participants | @@ -62,7 +62,7 @@ Feature: Posting to forums in a course with no groups behaves correctly Given I log in as "student1" And I am on "Course 1" course homepage And I follow "Standard forum" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" Then I should not see "Post a copy to all groups" And I set the following fields to these values: | Subject | Student -> All participants | @@ -76,11 +76,11 @@ Feature: Posting to forums in a course with no groups behaves correctly And I am on "Course 1" course homepage When I follow "Separate forum" Then I should see "You are not able to create a discussion because you are not a member of any group." - And I should not see "Add a new discussion topic" + And I should not see "Add discussion topic" Scenario: Students cannot post in forum with visible groups Given I log in as "student1" And I am on "Course 1" course homepage When I follow "Visible forum" Then I should see "You are not able to create a discussion because you are not a member of any group." - And I should not see "Add a new discussion topic" + And I should not see "Add discussion topic" diff --git a/mod/forum/tests/behat/post_to_multiple_groups.feature b/mod/forum/tests/behat/post_to_multiple_groups.feature index 2862144a015..04ec0f8d677 100644 --- a/mod/forum/tests/behat/post_to_multiple_groups.feature +++ b/mod/forum/tests/behat/post_to_multiple_groups.feature @@ -112,7 +112,7 @@ Feature: A user with access to multiple groups should be able to post a copy of Given I log in as "teacher1" And I am on "Course 1" course homepage And I follow "No group forum" - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" Then I should not see "Post a copy to all groups" Scenario: Posts to all groups that have groupings should only display within the grouping and not to other groups diff --git a/mod/forum/tests/behat/separate_group_discussions.feature b/mod/forum/tests/behat/separate_group_discussions.feature index aa5164ef816..bd1fa247c53 100644 --- a/mod/forum/tests/behat/separate_group_discussions.feature +++ b/mod/forum/tests/behat/separate_group_discussions.feature @@ -56,7 +56,7 @@ Feature: Posting to all groups in a separate group discussion is restricted to u Given I log in as "teacher1" And I am on "Course 1" course homepage And I follow "Standard forum name" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" Then the "Group" select box should contain "All participants" And the "Group" select box should contain "Group A" @@ -69,7 +69,7 @@ Feature: Posting to all groups in a separate group discussion is restricted to u And I am on "Course 1" course homepage And I follow "Standard forum name" And I select "Group A" from the "Separate groups" singleselect - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" Then I should see "Post a copy to all groups" And I set the following fields to these values: @@ -100,7 +100,7 @@ Feature: Posting to all groups in a separate group discussion is restricted to u And I am on "Course 1" course homepage And I follow "Standard forum name" And I select "Group A" from the "Separate groups" singleselect - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" Then I should see "Post a copy to all groups" And I set the following fields to these values: @@ -130,7 +130,7 @@ Feature: Posting to all groups in a separate group discussion is restricted to u Given I log in as "teacher1" And I am on "Course 1" course homepage And I follow "Standard forum name" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" And I set the following fields to these values: | Subject | Teacher 1 -> Post to all | @@ -159,7 +159,7 @@ Feature: Posting to all groups in a separate group discussion is restricted to u And I am on "Course 1" course homepage When I follow "Standard forum name" Then I should see "Group A" - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I should see "Group A" And I should not see "Group B" And I should not see "Group C" @@ -177,7 +177,7 @@ Feature: Posting to all groups in a separate group discussion is restricted to u And I am on "Course 1" course homepage When I follow "Standard forum name" And I select "Group A" from the "Separate groups" singleselect - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I click on "Advanced" "button" And the "Group" select box should not contain "All participants" And the "Group" select box should contain "Group A" @@ -198,7 +198,7 @@ Feature: Posting to all groups in a separate group discussion is restricted to u And I should not see "Student -> B" # Now try posting in Group A (starting at Group B) And I select "Group B" from the "Separate groups" singleselect - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I click on "Advanced" "button" And the "Group" select box should not contain "All participants" And the "Group" select box should contain "Group A" @@ -226,7 +226,7 @@ Feature: Posting to all groups in a separate group discussion is restricted to u Given I log in as "noneditor1" And I am on "Course 1" course homepage And I follow "Standard forum name" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" Then the "Group" select box should not contain "All participants" And the "Group" select box should contain "Group A" @@ -241,7 +241,7 @@ Feature: Posting to all groups in a separate group discussion is restricted to u Given I log in as "noneditor1" And I am on "Course 1" course homepage And I follow "Standard forum name" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" Then the "Group" select box should not contain "All participants" And the "Group" select box should contain "Group A" diff --git a/mod/forum/tests/behat/separate_group_grade_forum.feature b/mod/forum/tests/behat/separate_group_grade_forum.feature index d591ce2f0d0..5a7acb3471e 100644 --- a/mod/forum/tests/behat/separate_group_grade_forum.feature +++ b/mod/forum/tests/behat/separate_group_grade_forum.feature @@ -88,13 +88,13 @@ Feature: I can grade a students by group with separate groups And I log out When I am on the "Test Forum 1" "forum activity" page logged in as student1 And I select "Group A" from the "Separate groups" singleselect - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I set the following fields to these values: | Subject | Discussion subject A | | Message | Discussion message A | And I press "Post to forum" And I select "Group C" from the "Separate groups" singleselect - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I set the following fields to these values: | Subject | Discussion subject C | | Message | Discussion message C | diff --git a/mod/forum/tests/behat/separate_group_single_group_discussions.feature b/mod/forum/tests/behat/separate_group_single_group_discussions.feature index 9a3e7b27b90..c302f7727dc 100644 --- a/mod/forum/tests/behat/separate_group_single_group_discussions.feature +++ b/mod/forum/tests/behat/separate_group_single_group_discussions.feature @@ -47,14 +47,14 @@ Feature: Posting to groups in a separate group discussion when restricted to gro Given I log in as "teacher1" And I am on "Course 1" course homepage And I follow "Multiple groups forum" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" Then the "Group" select box should contain "All participants" And the "Group" select box should contain "G1G1" And the "Group" select box should contain "G1G2" And I am on "Course 1" course homepage And I follow "Single groups forum" - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I click on "Advanced" "button" And the "Group" select box should contain "All participants" And the "Group" select box should contain "G2G1" @@ -64,14 +64,14 @@ Feature: Posting to groups in a separate group discussion when restricted to gro Given I log in as "teacher2" And I am on "Course 1" course homepage And I follow "Multiple groups forum" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" Then the "Group" select box should not contain "All participants" And the "Group" select box should contain "G1G1" And the "Group" select box should contain "G1G2" And I am on "Course 1" course homepage And I follow "Single groups forum" - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I click on "Advanced" "button" And I should see "G2G1" And "Group" "select" should not exist diff --git a/mod/forum/tests/behat/visible_group_discussions.feature b/mod/forum/tests/behat/visible_group_discussions.feature index f9452a39625..d18013e35a4 100644 --- a/mod/forum/tests/behat/visible_group_discussions.feature +++ b/mod/forum/tests/behat/visible_group_discussions.feature @@ -47,7 +47,7 @@ Feature: Posting to all groups in a visible group discussion is restricted to us Given I log in as "teacher1" And I am on "Course 1" course homepage And I follow "Standard forum name" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" Then the "Group" select box should contain "All participants" And the "Group" select box should contain "Group A" @@ -60,7 +60,7 @@ Feature: Posting to all groups in a visible group discussion is restricted to us And I am on "Course 1" course homepage And I follow "Standard forum name" And I select "Group A" from the "Visible groups" singleselect - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" Then I should see "Post a copy to all groups" And I set the following fields to these values: @@ -91,7 +91,7 @@ Feature: Posting to all groups in a visible group discussion is restricted to us And I am on "Course 1" course homepage And I follow "Standard forum name" And I select "Group A" from the "Visible groups" singleselect - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" Then I should see "Post a copy to all groups" And I set the following fields to these values: @@ -121,7 +121,7 @@ Feature: Posting to all groups in a visible group discussion is restricted to us Given I log in as "teacher1" And I am on "Course 1" course homepage And I follow "Standard forum name" - When I click on "Add a new discussion topic" "link" + When I click on "Add discussion topic" "link" And I click on "Advanced" "button" And I set the following fields to these values: | Subject | Teacher 1 -> Post to all | @@ -159,7 +159,7 @@ Feature: Posting to all groups in a visible group discussion is restricted to us And I am on "Course 1" course homepage When I follow "Standard forum name" Then I should see "Group A" - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I click on "Advanced" "button" And I should see "Group A" And I should not see "Group B" @@ -178,7 +178,7 @@ Feature: Posting to all groups in a visible group discussion is restricted to us And I am on "Course 1" course homepage When I follow "Standard forum name" And I select "Group A" from the "Visible groups" singleselect - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I click on "Advanced" "button" And the "Group" select box should not contain "All participants" And the "Group" select box should contain "Group A" @@ -199,7 +199,7 @@ Feature: Posting to all groups in a visible group discussion is restricted to us And I should not see "Student -> B" # Now try posting in Group A (starting at Group B) And I select "Group B" from the "Visible groups" singleselect - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I click on "Advanced" "button" And the "Group" select box should not contain "All participants" And the "Group" select box should contain "Group A" diff --git a/mod/forum/version.php b/mod/forum/version.php index 962ba41d9a4..626b149876b 100644 --- a/mod/forum/version.php +++ b/mod/forum/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2021101101; // The current module version (Date: YYYYMMDDXX). +$plugin->version = 2021101102; // The current module version (Date: YYYYMMDDXX). $plugin->requires = 2021052500; // Requires this Moodle version. $plugin->component = 'mod_forum'; // Full name of the plugin (used for diagnostics) diff --git a/mod/forum/view.php b/mod/forum/view.php index 711ca6a9cc9..d856562b832 100644 --- a/mod/forum/view.php +++ b/mod/forum/view.php @@ -158,27 +158,34 @@ if (!empty($CFG->enablerssfeeds) && !empty($CFG->forum_enablerssfeeds) && $forum rss_add_http_header($forum->get_context(), 'mod_forum', $forumrecord, $rsstitle); } +// Output starts from here. echo $OUTPUT->header(); -echo $OUTPUT->heading(format_string($forum->get_name()), 2); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($forum->get_name()), 2); +} // Render the activity information. $completiondetails = \core_completion\cm_completion_details::get_instance($cm, $USER->id); $activitydates = \core\activity_dates::get_dates_for_module($cm, $USER->id); echo $OUTPUT->activity_information($cm, $completiondetails, $activitydates); +// Fetch the current groupid. +$groupid = groups_get_activity_group($cm, true) ?: null; + if (!$istypesingle && !empty($forum->get_intro())) { echo $OUTPUT->box(format_module_intro('forum', $forumrecord, $cm->id), 'generalbox', 'intro'); } +$rendererfactory = mod_forum\local\container::get_renderer_factory(); +// The elements for view action are rendered and added to the page. +echo forum_activity_actionbar($forum, $groupid, $course, $search); + if ($sortorder) { set_user_preference('forum_discussionlistsortorder', $sortorder); } $sortorder = get_user_preferences('forum_discussionlistsortorder', $discussionlistvault::SORTORDER_LASTPOST_DESC); -// Fetch the current groupid. -$groupid = groups_get_activity_group($cm, true) ?: null; -$rendererfactory = mod_forum\local\container::get_renderer_factory(); switch ($forum->get_type()) { case 'single': $forumgradeitem = forum_gradeitem::load_from_forum_entity($forum); @@ -243,7 +250,7 @@ switch ($forum->get_type()) { $discussionsrenderer = $rendererfactory->get_blog_discussion_list_renderer($forum); // Blog forums always show discussions newest first. echo $discussionsrenderer->render($USER, $cm, $groupid, $discussionlistvault::SORTORDER_CREATED_DESC, - $pageno, $pagesize); + $pageno, $pagesize, null, false); if (!$CFG->forum_usermarksread && forum_tp_is_tracked($forumrecord, $USER)) { $discussions = mod_forum_get_discussion_summaries($forum, $USER, $groupid, null, $pageno, $pagesize); @@ -255,7 +262,7 @@ switch ($forum->get_type()) { break; default: $discussionsrenderer = $rendererfactory->get_discussion_list_renderer($forum); - echo $discussionsrenderer->render($USER, $cm, $groupid, $sortorder, $pageno, $pagesize, $displaymode); + echo $discussionsrenderer->render($USER, $cm, $groupid, $sortorder, $pageno, $pagesize, $displaymode, false); } echo $OUTPUT->footer(); diff --git a/mod/quiz/attempt.php b/mod/quiz/attempt.php index ba521d9f740..e1fca018b2b 100644 --- a/mod/quiz/attempt.php +++ b/mod/quiz/attempt.php @@ -47,6 +47,8 @@ $PAGE->set_url($attemptobj->attempt_url(null, $page)); // During quiz attempts, the browser back/forwards buttons should force a reload. $PAGE->set_cacheable(false); +$PAGE->set_secondary_active_tab("modulepage"); + // Check login. require_login($attemptobj->get_course(), false, $attemptobj->get_cm()); diff --git a/mod/quiz/classes/output/edit_renderer.php b/mod/quiz/classes/output/edit_renderer.php index 6f0cdda398b..e58956e4819 100644 --- a/mod/quiz/classes/output/edit_renderer.php +++ b/mod/quiz/classes/output/edit_renderer.php @@ -55,11 +55,6 @@ class edit_renderer extends \plugin_renderer_base { \question_edit_contexts $contexts, \moodle_url $pageurl, array $pagevars) { $output = ''; - // Page title. - $output .= $this->heading_with_help(get_string('editingquizx', 'quiz', - format_string($quizobj->get_quiz_name())), 'editingquiz', 'quiz', '', - get_string('basicideasofquiz', 'quiz'), 2); - // Information at the top. $output .= $this->quiz_state_warnings($structure); diff --git a/mod/quiz/classes/output/overridesaction.php b/mod/quiz/classes/output/overridesaction.php new file mode 100644 index 00000000000..7a678bf6df8 --- /dev/null +++ b/mod/quiz/classes/output/overridesaction.php @@ -0,0 +1,98 @@ +. + +namespace mod_quiz\output; + +use moodle_url; +use renderable; +use renderer_base; +use templatable; +use url_select; + +/** + * Render overrides action + * + * @package mod_quiz + * @copyright 2021 Sujith Haridasan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class overridesaction implements renderable, templatable { + /** @var int */ + private $cmid; + + /** @var string */ + private $mode; + + /** @var bool */ + private $canedit; + + /** @var array */ + private $options; + + /** + * overridesaction constructor. + * + * @param int $cmid The course module id. + * @param string $mode The mode passed for the overrides url. + * @param bool $canedit Does the user have capabilities to list overrides. + * @param array $options The options passed to single button. + */ + public function __construct(int $cmid, string $mode, bool $canedit, array $options) { + $this->cmid = $cmid; + $this->mode = $mode; + $this->canedit = $canedit; + $this->options = $options; + } + + /** + * Get the data for the template + * + * @param renderer_base $output renderer_base object. + * @return array data for the template. + */ + public function export_for_template(renderer_base $output): array { + global $PAGE; + + $useroverride = new moodle_url('/mod/quiz/overrides.php', ['cmid' => $this->cmid, 'mode' => 'user']); + $groupoverride = new moodle_url('/mod/quiz/overrides.php', ['cmid' => $this->cmid, 'mode' => 'group']); + + $menu = [ + $useroverride->out(false) => get_string('useroverrides', 'quiz'), + $groupoverride->out(false) => get_string('groupoverrides', 'quiz') + ]; + + $urlselect = new url_select($menu, $PAGE->url->out(false), null, 'quizoverrides'); + + $overridesbuttonurl = + new moodle_url('/mod/quiz/overrideedit.php', ['cmid' => $this->cmid, 'action' => 'add' . $this->mode]); + if ($this->mode === 'group') { + $overridesbutton = new \single_button($overridesbuttonurl, get_string( 'addnewgroupoverride', 'quiz'), + 'post', true); + } else { + $overridesbutton = new \single_button($overridesbuttonurl, get_string( 'addnewuseroverride', 'quiz'), + 'get', true); + } + if (isset($this->options['disabled'])) { + $overridesbutton->disabled = true; + } + + return [ + 'overrides' => $urlselect->export_for_template($output), + 'canedit' => $this->canedit, + 'overridesbtn' => $overridesbutton->export_for_template($output), + ]; + } +} diff --git a/mod/quiz/classes/output/overwriteedit.php b/mod/quiz/classes/output/overwriteedit.php new file mode 100644 index 00000000000..3e65eec9c1f --- /dev/null +++ b/mod/quiz/classes/output/overwriteedit.php @@ -0,0 +1,68 @@ +. + +namespace mod_quiz\output; + +use renderable; +use renderer_base; +use templatable; +use moodle_url; + +/** + * Render the tertiary elements for the edit page + * + * @package mod_quiz + * @copyright 2021 Sujith Haridasan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class overwriteedit implements templatable, renderable { + + /** @var int */ + private $cmid; + + /** @var bool */ + private $quizhasquestion; + + /** + * overwriteedit constructor. + * + * @param int $cmid The course module id. + * @param bool $quizhasquestion Check if quiz has question. + */ + public function __construct(int $cmid, bool $quizhasquestion) { + $this->cmid = $cmid; + $this->quizhasquestion = $quizhasquestion; + } + + /** + * Provides the data for the template. + * + * @param renderer_base $output renderer_base object + * @return array data for the template + */ + public function export_for_template(renderer_base $output): array { + $data = []; + $data = [ + 'back' => (new moodle_url('/mod/quiz/view.php', ['id' => $this->cmid]))->out(false), + ]; + if ($this->quizhasquestion) { + $data['previewlink'] = + (new moodle_url('/mod/quiz/startattempt.php', ['cmid' => $this->cmid, 'sesskey' => sesskey()]))->out(false); + $data['previewquiz'] = get_string('previewquiz', 'mod_quiz'); + } + return $data; + } +} diff --git a/mod/quiz/classes/output/overwritepreview.php b/mod/quiz/classes/output/overwritepreview.php new file mode 100644 index 00000000000..741c043783c --- /dev/null +++ b/mod/quiz/classes/output/overwritepreview.php @@ -0,0 +1,65 @@ +. + +namespace mod_quiz\output; + +use renderable; +use renderer_base; +use templatable; +use moodle_url; + +/** + * Output the preview action area of this activity + * + * @package mod_quiz + * @copyright 2021 Sujith Haridasan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class overwritepreview implements templatable, renderable { + + /** @var int */ + private $cmid; + + /** @var bool */ + private $canedit; + + /** + * overwritepreview constructor. + * + * @param int $cmid The course module id. + * @param bool $canedit Can edit the quiz. + */ + public function __construct(int $cmid, bool $canedit) { + $this->cmid = $cmid; + $this->canedit = $canedit; + } + + /** + * Provide data for the template + * + * @param renderer_base $output + * @return array data for the template + */ + public function export_for_template(renderer_base $output): array { + $data = [ + 'back' => (new moodle_url('/mod/quiz/view.php', ['id' => $this->cmid]))->out(false), + ]; + if ($this->canedit) { + $data['editlink'] = (new moodle_url('/mod/quiz/edit.php', ['cmid' => $this->cmid]))->out(false); + } + return $data; + } +} diff --git a/mod/quiz/classes/output/previeweditaction.php b/mod/quiz/classes/output/previeweditaction.php new file mode 100644 index 00000000000..185d0610f5e --- /dev/null +++ b/mod/quiz/classes/output/previeweditaction.php @@ -0,0 +1,99 @@ +. + +namespace mod_quiz\output; + +use moodle_url; +use renderer_base; +use templatable; +use renderable; + +/** + * Render view action with preview and edit buttons + * + * @package mod_quiz + * @copyright 2021 Sujith Haridasan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class previeweditaction implements templatable, renderable { + /** @var int */ + private $cmid; + + /** @var bool */ + private $canedit; + + /** @var bool */ + private $canattempt; + + /** @var bool */ + private $canpreview; + + /** @var bool */ + private $quizhasquestions; + + /** @var int */ + private $attempts; + + /** + * previeweditaction constructor. + * + * @param int $cmid The course module id. + * @param bool $canedit Can edit the quiz. + * @param bool $canattempt can attempt the quiz. + * @param bool $canpreview Can preview the quiz. + * @param bool $quizhasquestions If quiz has questions. + * @param int $attempts The attempts made. + */ + public function __construct(int $cmid, bool $canedit, bool $canattempt, + bool $canpreview, bool $quizhasquestions, int $attempts) { + $this->cmid = $cmid; + $this->canedit = $canedit; + $this->canattempt = $canattempt; + $this->canpreview = $canpreview; + $this->quizhasquestions = $quizhasquestions; + $this->attempts = $attempts; + } + + /** + * Provide data for the template + * + * @param renderer_base $output renderer_base objects. + * @return array data for template + */ + public function export_for_template(renderer_base $output): array { + $data = []; + if ($this->quizhasquestions) { + if ($this->canpreview) { + $data['previewlink'] = (new moodle_url('/mod/quiz/startattempt.php', + ['attempt' => $this->attempts, 'cmid' => $this->cmid, 'sesskey' => sesskey()]))->out(false); + $data['previewquiz'] = get_string('previewquiz', 'mod_quiz'); + } + + if ($this->canedit) { + $data['editlink'] = (new moodle_url('/mod/quiz/edit.php', ['cmid' => $this->cmid]))->out(false); + } + + if ($this->canattempt && !$this->canpreview) { + $data['attemptlink'] = + (new moodle_url('/mod/quiz/startattempt.php', ['cmid' => $this->cmid, 'sesskey' => sesskey()]))->out(false); + } + } else { + $data['addquestionlink'] = (new moodle_url('/mod/quiz/edit.php', ['cmid' => $this->cmid]))->out(false); + } + + return $data; + } +} diff --git a/mod/quiz/classes/output/resultsaction.php b/mod/quiz/classes/output/resultsaction.php new file mode 100644 index 00000000000..02e330270cb --- /dev/null +++ b/mod/quiz/classes/output/resultsaction.php @@ -0,0 +1,73 @@ +. + +namespace mod_quiz\output; + +use templatable; +use renderable; +use renderer_base; +use moodle_url; +use url_select; + +/** + * Render results action + * + * @package mod_quiz + * @copyright 2021 Sujith Haridasan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class resultsaction implements templatable, renderable { + /** @var int */ + private $id; + + /** + * resultsaction constructor. + * + * @param int $id The course module id. + */ + public function __construct(int $id) { + $this->id = $id; + } + + /** + * Provide data for the template + * + * @param renderer_base $output renderer_base object. + * @return array data for template. + */ + public function export_for_template(renderer_base $output): array { + global $PAGE; + + $gradeslink = new moodle_url('/mod/quiz/report.php', ['id' => $this->id, 'mode' => 'overview']); + $responseslink = new moodle_url('/mod/quiz/report.php', ['id' => $this->id, 'mode' => 'responses']); + $statisticslink = new moodle_url('/mod/quiz/report.php', ['id' => $this->id, 'mode' => 'statistics']); + $manualgrading = new moodle_url('/mod/quiz/report.php', ['id' => $this->id, 'mode' => 'grading']); + + $menu = [ + $gradeslink->out(false) => get_string('grades', 'grades'), + $responseslink->out(false) => get_string('responses', 'quiz_responses'), + $statisticslink->out(false) => get_string('statistics', 'quiz_statistics'), + $manualgrading->out(false) => get_string('grading', 'quiz_grading') + ]; + + $urlselect = new url_select($menu, $PAGE->url->out(false), null, 'quizresults'); + + $data = [ + 'resultaction' => $urlselect->export_for_template($output) + ]; + return $data; + } +} diff --git a/mod/quiz/edit.php b/mod/quiz/edit.php index 49f71597ca0..485dca0a3bb 100644 --- a/mod/quiz/edit.php +++ b/mod/quiz/edit.php @@ -59,6 +59,7 @@ $defaultcategory = $defaultcategoryobj->id . ',' . $defaultcategoryobj->contexti $quizhasattempts = quiz_has_attempts($quiz->id); $PAGE->set_url($thispageurl); +$PAGE->set_secondary_active_tab("modulepage"); // Get the course object and related bits. $course = $DB->get_record('course', array('id' => $quiz->course), '*', MUST_EXIST); @@ -185,8 +186,14 @@ $node = $PAGE->settingsnav->find('mod_quiz_edit', navigation_node::TYPE_SETTING) if ($node) { $node->make_active(); } + +$overwriteedit = new \mod_quiz\output\overwriteedit($cmid, quiz_has_questions($quiz->id)); + echo $OUTPUT->header(); +$renderer = $PAGE->get_renderer('mod_quiz'); +echo $renderer->overwrite_edit_action($overwriteedit); + // Initialise the JavaScript. $quizeditconfig = new stdClass(); $quizeditconfig->url = $thispageurl->out(true, array('qbanktool' => '0')); diff --git a/mod/quiz/index.php b/mod/quiz/index.php index 6c87002f62c..035b6ada1e1 100644 --- a/mod/quiz/index.php +++ b/mod/quiz/index.php @@ -47,7 +47,10 @@ $PAGE->navbar->add($strquizzes); $PAGE->set_title($strquizzes); $PAGE->set_heading($course->fullname); echo $OUTPUT->header(); -echo $OUTPUT->heading($strquizzes, 2); + +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading($strquizzes, 2); +} // Get all the appropriate data. if (!$quizzes = get_all_instances_in_course("quiz", $course)) { diff --git a/mod/quiz/lang/en/deprecated.txt b/mod/quiz/lang/en/deprecated.txt index bc4aac1394c..6d496655a7b 100644 --- a/mod/quiz/lang/en/deprecated.txt +++ b/mod/quiz/lang/en/deprecated.txt @@ -7,3 +7,4 @@ completionpassdesc,mod_quiz completionpass_help,mod_quiz completiondetail:passgrade,mod_quiz gradetopassnotset,mod_quiz +basicideasofquiz,mod_quiz diff --git a/mod/quiz/lang/en/quiz.php b/mod/quiz/lang/en/quiz.php index 5933eed1b39..d1e2206066f 100644 --- a/mod/quiz/lang/en/quiz.php +++ b/mod/quiz/lang/en/quiz.php @@ -100,6 +100,7 @@ $string['attemptincomplete'] = 'That attempt (by {$a}) is not yet completed.'; $string['attemptlast'] = 'Last attempt'; $string['attemptnumber'] = 'Attempt'; $string['attemptquiznow'] = 'Attempt quiz now'; +$string['attemptquiz'] = 'Attempt quiz'; $string['attemptreviewtitle'] = '{$a}: Attempt review'; $string['attemptreviewtitlepaged'] = '{$a->name}: Attempt review (page {$a->currentpage} of {$a->totalpages})'; $string['attempts'] = 'Attempts'; @@ -124,7 +125,6 @@ $string['back'] = 'Back to preview question'; $string['backtocourse'] = 'Back to the course'; $string['backtoquestionlist'] = 'Back to question list'; $string['backtoquiz'] = 'Back to quiz editing'; -$string['basicideasofquiz'] = 'The basic ideas of quiz-making'; $string['bestgrade'] = 'Best grade'; $string['bothattempts'] = 'Show students with and without attempts'; $string['browsersecurity'] = 'Browser security'; @@ -673,7 +673,7 @@ $string['popupnotice'] = 'Students will see this quiz in a secure window'; $string['preprocesserror'] = 'Error occurred during pre-processing!'; $string['preview'] = 'Preview'; $string['previewquestion'] = 'Preview question'; -$string['previewquiz'] = 'Preview {$a}'; +$string['previewquiz'] = 'Preview quiz'; $string['previewquiznow'] = 'Preview quiz now'; $string['previous'] = 'Previous state'; $string['privacy:metadata:core_question'] = 'The quiz activity stores question usage information in the core_question subsystem.'; @@ -1054,3 +1054,4 @@ $string['completionpassdesc'] = 'Student must achieve a passing grade to complet $string['completionpass_help'] = 'If enabled, this activity is considered complete when the student receives a pass grade (as specified in the Grade section of the quiz settings) or higher.'; $string['completiondetail:passgrade'] = 'Receive a pass grade'; $string['gradetopassnotset'] = 'This quiz does not yet have a grade to pass set. It may be set in the Grade section of the quiz settings.'; +$string['basicideasofquiz'] = 'The basic ideas of quiz-making'; diff --git a/mod/quiz/lib.php b/mod/quiz/lib.php index c15fb254c4a..77046b460fe 100644 --- a/mod/quiz/lib.php +++ b/mod/quiz/lib.php @@ -1731,15 +1731,9 @@ function quiz_extend_settings_navigation($settings, $quiznode) { } if (has_any_capability(['mod/quiz:manageoverrides', 'mod/quiz:viewoverrides'], $PAGE->cm->context)) { - $url = new moodle_url('/mod/quiz/overrides.php', array('cmid'=>$PAGE->cm->id)); - $node = navigation_node::create(get_string('groupoverrides', 'quiz'), - new moodle_url($url, array('mode'=>'group')), - navigation_node::TYPE_SETTING, null, 'mod_quiz_groupoverrides'); - $quiznode->add_node($node, $beforekey); - - $node = navigation_node::create(get_string('useroverrides', 'quiz'), - new moodle_url($url, array('mode'=>'user')), - navigation_node::TYPE_SETTING, null, 'mod_quiz_useroverrides'); + $url = new moodle_url('/mod/quiz/overrides.php', array('cmid' => $PAGE->cm->id)); + $node = navigation_node::create(get_string('overrides', 'quiz'), + $url, navigation_node::TYPE_SETTING, null, 'mod_quiz_useroverrides'); $quiznode->add_node($node, $beforekey); } @@ -1748,7 +1742,8 @@ function quiz_extend_settings_navigation($settings, $quiznode) { new moodle_url('/mod/quiz/edit.php', array('cmid'=>$PAGE->cm->id)), navigation_node::TYPE_SETTING, null, 'mod_quiz_edit', new pix_icon('t/edit', '')); - $quiznode->add_node($node, $beforekey); + $editquiznode = $quiznode->add_node($node, $beforekey); + $editquiznode->set_show_in_secondary_navigation(false); } if (has_capability('mod/quiz:preview', $PAGE->cm->context)) { @@ -1757,9 +1752,12 @@ function quiz_extend_settings_navigation($settings, $quiznode) { $node = navigation_node::create(get_string('preview', 'quiz'), $url, navigation_node::TYPE_SETTING, null, 'mod_quiz_preview', new pix_icon('i/preview', '')); - $quiznode->add_node($node, $beforekey); + $previewnode = $quiznode->add_node($node, $beforekey); + $previewnode->set_show_in_secondary_navigation(false); } + question_extend_settings_navigation($quiznode, $PAGE->cm->context)->trim_if_empty(); + if (has_any_capability(array('mod/quiz:viewreports', 'mod/quiz:grade'), $PAGE->cm->context)) { require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php'); $reportlist = quiz_report_list($PAGE->cm->context); @@ -1768,7 +1766,7 @@ function quiz_extend_settings_navigation($settings, $quiznode) { array('id' => $PAGE->cm->id, 'mode' => reset($reportlist))); $reportnode = $quiznode->add_node(navigation_node::create(get_string('results', 'quiz'), $url, navigation_node::TYPE_SETTING, - null, null, new pix_icon('i/report', '')), $beforekey); + null, null, new pix_icon('i/report', ''))); foreach ($reportlist as $report) { $url = new moodle_url('/mod/quiz/report.php', @@ -1778,8 +1776,6 @@ function quiz_extend_settings_navigation($settings, $quiznode) { null, 'quiz_report_' . $report, new pix_icon('i/item', ''))); } } - - question_extend_settings_navigation($quiznode, $PAGE->cm->context)->trim_if_empty(); } /** diff --git a/mod/quiz/overridedelete.php b/mod/quiz/overridedelete.php index 2c675c551a6..c163046b947 100644 --- a/mod/quiz/overridedelete.php +++ b/mod/quiz/overridedelete.php @@ -89,7 +89,9 @@ $PAGE->set_title($title); $PAGE->set_heading($course->fullname); echo $OUTPUT->header(); -echo $OUTPUT->heading(format_string($quiz->name, true, array('context' => $context))); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($quiz->name, true, array('context' => $context))); +} if ($override->groupid) { $group = $DB->get_record('groups', ['id' => $override->groupid], 'id, name'); diff --git a/mod/quiz/overrideedit.php b/mod/quiz/overrideedit.php index d02bba6d7e8..693f71c8b9d 100644 --- a/mod/quiz/overrideedit.php +++ b/mod/quiz/overrideedit.php @@ -66,6 +66,9 @@ if ($overrideid) { $PAGE->set_url($url); +// Activate the secondary nav tab. +$PAGE->set_secondary_active_tab("mod_quiz_useroverrides"); + require_login($course, false, $cm); $context = context_module::instance($cm->id); @@ -239,7 +242,9 @@ $PAGE->set_pagelayout('admin'); $PAGE->set_title($pagetitle); $PAGE->set_heading($course->fullname); echo $OUTPUT->header(); -echo $OUTPUT->heading(format_string($quiz->name, true, array('context' => $context))); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($quiz->name, true, array('context' => $context))); +} $mform->display(); diff --git a/mod/quiz/overrides.php b/mod/quiz/overrides.php index ab2d4b83e73..0ac24319826 100644 --- a/mod/quiz/overrides.php +++ b/mod/quiz/overrides.php @@ -69,6 +69,9 @@ $PAGE->set_pagelayout('admin'); $PAGE->set_title($title); $PAGE->set_heading($course->fullname); +// Activate the secondary nav tab. +$PAGE->set_secondary_active_tab("mod_quiz_useroverrides"); + // Delete orphaned group overrides. $sql = 'SELECT o.id FROM {quiz_overrides} o @@ -303,32 +306,32 @@ echo $OUTPUT->header(); echo $OUTPUT->heading($title); // Output the table and button. -echo html_writer::start_tag('div', ['id' => 'quizoverrides']); +$output = ''; + +$output .= html_writer::start_tag('div', ['id' => 'quizoverrides']); if (count($table->data)) { - echo html_writer::table($table); + $output .= html_writer::table($table); } else { if ($groupmode) { - echo $OUTPUT->notification(get_string('overridesnoneforgroups', 'quiz'), 'info', false); + $output .= $OUTPUT->notification(get_string('overridesnoneforgroups', 'quiz'), 'info', false); } else { - echo $OUTPUT->notification(get_string('overridesnoneforusers', 'quiz'), 'info', false); + $output .= $OUTPUT->notification(get_string('overridesnoneforusers', 'quiz'), 'info', false); } } if ($hasinactive) { - echo $OUTPUT->notification(get_string('inactiveoverridehelp', 'quiz'), 'info', false); + $output .= $OUTPUT->notification(get_string('inactiveoverridehelp', 'quiz'), 'info', false); } +$addbutton = ''; +$options = []; if ($canedit) { - echo html_writer::start_tag('div', ['class' => 'buttons']); - $options = []; + $output .= html_writer::start_tag('div', ['class' => 'buttons']); if ($groupmode) { if (empty($groups)) { // There are no groups. - echo $OUTPUT->notification(get_string('groupsnone', 'quiz'), 'error'); + $output .= $OUTPUT->notification(get_string('groupsnone', 'quiz'), 'error'); $options['disabled'] = true; } - echo $OUTPUT->single_button($overrideediturl->out(true, - ['action' => 'addgroup', 'cmid' => $cm->id]), - get_string('addnewgroupoverride', 'quiz'), 'post', $options); } else { $users = []; // See if there are any students in the quiz. @@ -346,17 +349,22 @@ if ($canedit) { if (empty($users)) { // There are no students. - echo $OUTPUT->notification($nousermessage, 'error'); + $output .= $OUTPUT->notification($nousermessage, 'error'); $options['disabled'] = true; } - echo $OUTPUT->single_button($overrideediturl->out(true, - ['action' => 'adduser', 'cmid' => $cm->id]), - get_string('addnewuseroverride', 'quiz'), 'get', $options); } - echo html_writer::end_tag('div'); + $output .= html_writer::end_tag('div'); } -echo html_writer::end_tag('div'); +$output .= html_writer::end_tag('div'); + +// Outputs overrides action. +$overridesaction = new \mod_quiz\output\overridesaction($cmid, $mode, $canedit, $options); +$renderer = $PAGE->get_renderer('mod_quiz'); +echo $renderer->overrides_action($overridesaction); + +// Now output what we captured after the overrides action. +echo $output; // Finish the page. echo $OUTPUT->footer(); diff --git a/mod/quiz/renderer.php b/mod/quiz/renderer.php index e212893585b..ce0e2136bb1 100644 --- a/mod/quiz/renderer.php +++ b/mod/quiz/renderer.php @@ -449,8 +449,17 @@ class mod_quiz_renderer extends plugin_renderer_base { */ public function attempt_page($attemptobj, $page, $accessmanager, $messages, $slots, $id, $nextpage) { + $context = $attemptobj->get_quizobj()->get_context(); + $cmid = $attemptobj->get_quizobj()->get_cmid(); + $canedit = has_capability('mod/quiz:manage', $context); + $overwritepreview = new \mod_quiz\output\overwritepreview($cmid, $canedit); + $output = ''; $output .= $this->header(); + + $renderer = $this->page->get_renderer('mod_quiz'); + $output .= $renderer->overwrite_preview_action($overwritepreview); + $output .= $this->quiz_notices($messages); $output .= $this->countdown_timer($attemptobj, time()); $output .= $this->attempt_form($attemptobj, $page, $slots, $id, $nextpage); @@ -540,7 +549,7 @@ class mod_quiz_renderer extends plugin_renderer_base { protected function attempt_navigation_buttons($page, $lastpage, $navmethod = 'free') { $output = ''; - $output .= html_writer::start_tag('div', array('class' => 'submitbtns')); + $output .= html_writer::start_tag('div', array('class' => 'submitbtns mb-4')); if ($page > 0 && $navmethod == 'free') { $output .= html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'previous', 'value' => get_string('navigateprevious', 'quiz'), 'class' => 'mod_quiz-prev-nav btn btn-secondary', @@ -625,7 +634,7 @@ class mod_quiz_renderer extends plugin_renderer_base { public function access_messages($messages) { $output = ''; foreach ($messages as $message) { - $output .= html_writer::tag('p', $message) . "\n"; + $output .= html_writer::tag('p', $message, ['class' => 'float-left']) . "\n"; } return $output; } @@ -677,21 +686,19 @@ class mod_quiz_renderer extends plugin_renderer_base { foreach ($slots as $slot) { // Add a section headings if we need one here. $heading = $attemptobj->get_heading_before_slot($slot); - if ($heading) { - $heading = format_string($heading); - } - $sections = $attemptobj->get_quizobj()->get_sections(); - if (!is_null($heading) && empty($heading) && count($sections) > 1) { + if (!is_null($heading) && empty($heading)) { $heading = get_string('sectionnoname', 'quiz'); - $heading = \html_writer::span($heading, 'dimmed_text'); } - if ($heading) { - $cell = new html_table_cell($heading); + $cell = new html_table_cell(format_string($heading)); $cell->header = true; $cell->colspan = $tablewidth; $table->data[] = array($cell); - $table->rowclasses[] = 'quizsummaryheading'; + $classes = 'quizsummaryheading'; + if ($heading === get_string('sectionnoname', 'quiz')) { + $classes .= ' dimmed_text'; + } + $table->rowclasses[] = $classes; } // Don't display information items. @@ -799,10 +806,14 @@ class mod_quiz_renderer extends plugin_renderer_base { */ public function view_page($course, $quiz, $cm, $context, $viewobj) { $output = ''; - $output .= $this->view_information($quiz, $cm, $context, $viewobj->infomessages); + $output .= $this->view_information($quiz, $cm, $context, $viewobj->infomessages, $viewobj->quizhasquestions); $output .= $this->view_table($quiz, $context, $viewobj); $output .= $this->view_result_info($quiz, $context, $cm, $viewobj); $output .= $this->box($this->view_page_buttons($viewobj), 'quizattempt'); + // Output any access messages. + if ($viewobj->infomessages) { + $output .= $this->box($this->access_messages($viewobj->infomessages), 'quizinfo'); + } return $output; } @@ -814,27 +825,11 @@ class mod_quiz_renderer extends plugin_renderer_base { * @return string HTML to output. */ public function view_page_buttons(mod_quiz_view_object $viewobj) { - global $CFG; $output = ''; if (!$viewobj->quizhasquestions) { - $output .= $this->no_questions_message($viewobj->canedit, $viewobj->editurl); + $output .= $this->generate_no_questions_message(); } - - $output .= $this->access_messages($viewobj->preventmessages); - - if ($viewobj->buttontext) { - $output .= $this->start_attempt_button($viewobj->buttontext, - $viewobj->startattempturl, $viewobj->preflightcheckform, - $viewobj->popuprequired, $viewobj->popupoptions); - } - - if ($viewobj->showbacktocourse) { - $output .= $this->single_button($viewobj->backtocourseurl, - get_string('backtocourse', 'quiz'), 'get', - array('class' => 'continuebutton')); - } - return $output; } @@ -890,9 +885,13 @@ class mod_quiz_renderer extends plugin_renderer_base { * @param object $quiz the quiz settings. * @param object $cm the course_module object. * @param object $context the quiz context. + * @deprecated since Moodle 4.0 MDL-71915 - please do not use this function any more. + * * @return string HTML to output. */ public function no_questions_message($canedit, $editurl) { + debugging('no_questions_message() is deprecated, please use generate_no_questions_message() instead.', DEBUG_DEVELOPER); + $output = html_writer::start_tag('div', array('class' => 'card text-center mb-3')); $output .= html_writer::start_tag('div', array('class' => 'card-body')); @@ -906,6 +905,21 @@ class mod_quiz_renderer extends plugin_renderer_base { return $output; } + /** + * Generate a message saying that this quiz has no questions + * + * @return string HTML to output. + */ + public function generate_no_questions_message() { + $output = html_writer::start_tag('div', array('class' => 'text-left mb-3')); + + $output .= $this->notification(get_string('noquestions', 'quiz'), 'warning', false); + + $output .= html_writer::end_tag('div'); + + return $output; + } + /** * Outputs an error message for any guests accessing the quiz * @@ -914,10 +928,11 @@ class mod_quiz_renderer extends plugin_renderer_base { * @param int $cm Course Module ID * @param int $context The page contect ID * @param array $messages Array containing any messages + * @param bool $quizhasquestions If quiz has questions */ - public function view_page_guest($course, $quiz, $cm, $context, $messages) { + public function view_page_guest($course, $quiz, $cm, $context, $messages, $quizhasquestions = false) { $output = ''; - $output .= $this->view_information($quiz, $cm, $context, $messages); + $output .= $this->view_information($quiz, $cm, $context, $messages, $quizhasquestions); $guestno = html_writer::tag('p', get_string('guestsno', 'quiz')); $liketologin = html_writer::tag('p', get_string('liketologin')); $referer = get_local_referer(false); @@ -933,11 +948,12 @@ class mod_quiz_renderer extends plugin_renderer_base { * @param int $cm Course Module ID * @param int $context The page contect ID * @param array $messages Array containing any messages + * @param bool $quizhasquestions If quiz has questions */ - public function view_page_notenrolled($course, $quiz, $cm, $context, $messages) { + public function view_page_notenrolled($course, $quiz, $cm, $context, $messages, $quizhasquestions = false) { global $CFG; $output = ''; - $output .= $this->view_information($quiz, $cm, $context, $messages); + $output .= $this->view_information($quiz, $cm, $context, $messages, $quizhasquestions); $youneedtoenrol = html_writer::tag('p', get_string('youneedtoenrol', 'quiz')); $button = html_writer::tag('p', $this->continue_button($CFG->wwwroot . '/course/view.php?id=' . $course->id)); @@ -952,15 +968,18 @@ class mod_quiz_renderer extends plugin_renderer_base { * @param object $cm the course_module object. * @param context $context the quiz context. * @param array $messages any access messages that should be described. + * @param bool $quizhasquestions does quiz has questions added. * @return string HTML to output. */ - public function view_information($quiz, $cm, $context, $messages) { + public function view_information($quiz, $cm, $context, $messages, bool $quizhasquestions = false) { global $USER; $output = ''; // Print quiz name. - $output .= $this->heading(format_string($quiz->name)); + if (!$this->page->has_secondary_navigation()) { + $output .= $this->heading(format_string($quiz->name)); + } // Print any activity information (eg completion requirements / dates). $cminfo = cm_info::create($cm); @@ -971,10 +990,14 @@ class mod_quiz_renderer extends plugin_renderer_base { // Print quiz description. $output .= $this->quiz_intro($quiz, $cm); - // Output any access messages. - if ($messages) { - $output .= $this->box($this->access_messages($messages), 'quizinfo'); - } + // Print the preview, quiz buttons for tertiary nav. + $canedit = has_capability('mod/quiz:manage', $context); + $canpreview = has_capability('mod/quiz:preview', $context); + $canattempt = has_capability('mod/quiz:attempt', $context); + $previeweditaction = new \mod_quiz\output\previeweditaction($cm->id, $canedit, $canattempt, $canpreview, $quizhasquestions, + $quiz->attempts); + $renderer = $this->page->get_renderer('mod_quiz'); + $output .= $renderer->preview_edit_action($previeweditaction); // Show number of attempts summary to those who can view reports. if (has_capability('mod/quiz:viewreports', $context)) { @@ -1360,6 +1383,56 @@ class mod_quiz_renderer extends plugin_renderer_base { array('id' => 'connection-error', 'style' => 'display: none;', 'role' => 'alert')) . html_writer::tag('div', $ok, array('id' => 'connection-ok', 'style' => 'display: none;', 'role' => 'alert')); } + + /** + * Get the rendered HTML for the action area of view.php + * + * @param \mod_quiz\output\previeweditaction $previeweditaction previeweditaction object. + * @return string rendered HTML for the action area of view.php + */ + public function preview_edit_action(\mod_quiz\output\previeweditaction $previeweditaction):string { + return $this->render_from_template('mod_quiz/quiz_preview_edit_action', $previeweditaction->export_for_template($this)); + } + + /** + * Get the rendered HTML for the action area of preview page + * + * @param \mod_quiz\output\overwritepreview $overwritepreview overwritepreview object. + * @return string rendered HTML for the preview page + */ + public function overwrite_preview_action(\mod_quiz\output\overwritepreview $overwritepreview): string { + return $this->render_from_template('mod_quiz/quiz_preview_action', $overwritepreview->export_for_template($this)); + } + + /** + * Get the rendered HTML for the action area of the edit page. + * + * @param \mod_quiz\output\overwriteedit $overwriteedit overwriteedit object. + * @return string rendered HTML for the edit page + */ + public function overwrite_edit_action(\mod_quiz\output\overwriteedit $overwriteedit): string { + return $this->render_from_template('mod_quiz/quiz_edit_action', $overwriteedit->export_for_template($this)); + } + + /** + * Get rendered HTML for the action area of the results page. + * + * @param \mod_quiz\output\resultsaction $resultsaction resultsaction object. + * @return string rendered HTML string from the template. + */ + public function get_results_action(\mod_quiz\output\resultsaction $resultsaction): string { + return $this->render_from_template('mod_quiz/quiz_results_action', $resultsaction->export_for_template($this)); + } + + /** + * Get rendered HTML for the action area of the overrides page. + * + * @param \mod_quiz\output\overridesaction $overridesaction the overridesaction object. + * @return string rendered HTML string from the template. + */ + public function overrides_action(\mod_quiz\output\overridesaction $overridesaction): string { + return $this->render_from_template('mod_quiz/quiz_overrides', $overridesaction->export_for_template($this)); + } } diff --git a/mod/quiz/report/default.php b/mod/quiz/report/default.php index 55ce4356f88..6b45bfdd08e 100644 --- a/mod/quiz/report/default.php +++ b/mod/quiz/report/default.php @@ -68,7 +68,12 @@ abstract class quiz_default_report { $PAGE->set_heading($course->fullname); echo $OUTPUT->header(); $context = context_module::instance($cm->id); - echo $OUTPUT->heading(format_string($quiz->name, true, array('context' => $context))); + if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($quiz->name, true, array('context' => $context))); + } + $resultsaction = new \mod_quiz\output\resultsaction($cm->id); + $renderer = $PAGE->get_renderer('mod_quiz'); + echo $renderer->get_results_action($resultsaction); if (!empty($CFG->enableplagiarism)) { require_once($CFG->libdir . '/plagiarismlib.php'); echo plagiarism_update_status($course, $cm); diff --git a/mod/quiz/review.php b/mod/quiz/review.php index 1c1d42fde15..16cf84dd360 100644 --- a/mod/quiz/review.php +++ b/mod/quiz/review.php @@ -42,6 +42,7 @@ if ($page !== 0) { $url->param('showall', $showall); } $PAGE->set_url($url); +$PAGE->set_secondary_active_tab("modulepage"); $attemptobj = quiz_create_attempt_handling_errors($attemptid, $cmid); $attemptobj->preload_all_attempt_step_users(); diff --git a/mod/quiz/summary.php b/mod/quiz/summary.php index f68fb7dc19e..01461dccbf0 100644 --- a/mod/quiz/summary.php +++ b/mod/quiz/summary.php @@ -32,6 +32,7 @@ $cmid = optional_param('cmid', null, PARAM_INT); $PAGE->set_url('/mod/quiz/summary.php', array('attempt' => $attemptid)); // During quiz attempts, the browser back/forwards buttons should force a reload. $PAGE->set_cacheable(false); +$PAGE->set_secondary_active_tab("modulepage"); $attemptobj = quiz_create_attempt_handling_errors($attemptid, $cmid); diff --git a/mod/quiz/templates/quiz_edit_action.mustache b/mod/quiz/templates/quiz_edit_action.mustache new file mode 100644 index 00000000000..ef64bb25420 --- /dev/null +++ b/mod/quiz/templates/quiz_edit_action.mustache @@ -0,0 +1,39 @@ +{{! + 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 mod_quiz/quiz_edit_action + Actions bar at the top of the quiz edit page UI. + Classes required for JS: + * none + Data attributes required for JS: + * none + Context variables required for this template: + * see mod/quiz/classes/output/overwriteedit.php + Example context (json): + { + "back": "http://localhost/mod/quiz/view.php?id=2", + "previewlink": "http://localhost/mod/quiz/startattempt.php?cmid=2&sesskey=G8FPNoJz9r" + } +}} +
+
+ {{#str}}back, core {{/str}} + {{#previewlink}} + {{#str}}previewquiz, quiz{{/str}} + {{/previewlink}} +
+
diff --git a/mod/quiz/templates/quiz_overrides.mustache b/mod/quiz/templates/quiz_overrides.mustache new file mode 100644 index 00000000000..f0037d669a8 --- /dev/null +++ b/mod/quiz/templates/quiz_overrides.mustache @@ -0,0 +1,75 @@ +{{! + 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 mod_quiz/quiz_overrides + Actions bar at the top of the overrides page UI. + Classes required for JS: + * none + Data attributes required for JS: + * none + Context variables required for this template: + * see mod/quiz/classes/output/overridesaction.php + Example context (json): + { + "overrides": { + "options": [{ + "name": "User overrides", + "value": "/mod/quiz/overrides.php?cmid=71&mode=user" + }, + { + "name": "Group overrrides", + "value": "/mod/quiz/overrides.php?cmid=71&mode=group" + } + ] + }, + "canedit": true, + "overridesbtn": { + "id": "single_button1234", + "method": "get", + "url": "http://localhost/moodle/mod/quiz/overrideedit.php", + "lablel": "Add user override", + "classes": "singlebutton", + "disabled": false, + "params": [ + { + "name": "cmid", + "value": "73" + }, + { + "name": "action", + "value": "adduser" + } + ] + } + } +}} +
+
+ {{#overrides}} +
+ {{>core/url_select}} +
+ {{/overrides}} + {{#canedit}} + {{#overridesbtn}} +
+ {{>core/single_button}} +
+ {{/overridesbtn}} + {{/canedit}} +
+
diff --git a/mod/quiz/templates/quiz_preview_action.mustache b/mod/quiz/templates/quiz_preview_action.mustache new file mode 100644 index 00000000000..5be58935eed --- /dev/null +++ b/mod/quiz/templates/quiz_preview_action.mustache @@ -0,0 +1,39 @@ +{{! + 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 mod_quiz/quiz_preview_action + Action bar at the top of the quiz attempt page UI. + Classes required for JS: + * none + Data attributes required for JS: + * none + Context variables required for this template: + * see mod/quiz/classes/output/overwritepreview.php + Example context (json): + { + "back": "http://localhost/mod/quiz/view.php?id=2", + "editlink": "http://localhost/mod/quiz/edit.php?cmid=3" + } +}} +
+
+ {{#str}}back, core {{/str}} + {{#editlink}} + {{#str}}editquiz, quiz{{/str}} + {{/editlink}} +
+
diff --git a/mod/quiz/templates/quiz_preview_edit_action.mustache b/mod/quiz/templates/quiz_preview_edit_action.mustache new file mode 100644 index 00000000000..12f6f655435 --- /dev/null +++ b/mod/quiz/templates/quiz_preview_edit_action.mustache @@ -0,0 +1,49 @@ +{{! + 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 mod_quiz/quiz_preview_edit_action + Actions bar at the top of the quiz view page + Classes required for JS: + * none + Data attributes required for JS: + * none + Context variables required for this template: + * see mod/quiz/classes/output/previeweditaction.php + Example context (json): + { + "previewlink": "http://localhost/mod/quiz/startattempt.php?cmid=2&sesskey=G8FPNoJz9r", + "editlink": "http://localhost/mod/quiz/edit.php?cmid=3", + "attemptlink": "http://localhost/mod/quiz/startattempt.php?cmid=5&sesskey=psqFTeG0Hi", + "addquestionlink": "http://localhost/mod/quiz/edit.php?cmid=3" + } +}} +
+
+ {{#previewlink}} + {{#str}}previewquiz, quiz{{/str}} + {{/previewlink}} + {{#editlink}} + {{#str}}editquiz, quiz{{/str}} + {{/editlink}} + {{#attemptlink}} + {{#str}}attemptquiz, quiz{{/str}} + {{/attemptlink}} + {{#addquestionlink}} + {{#str}}addquestion, quiz{{/str}} + {{/addquestionlink}} +
+
diff --git a/mod/quiz/templates/quiz_results_action.mustache b/mod/quiz/templates/quiz_results_action.mustache new file mode 100644 index 00000000000..8caa96ff6b4 --- /dev/null +++ b/mod/quiz/templates/quiz_results_action.mustache @@ -0,0 +1,58 @@ +{{! + 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 mod_quiz/quiz_results_action + Actions bar at the top of the report page UI. + Classes required for JS: + * none + Data attributes required for JS: + * none + Context variables required for this template: + * see mod/quiz/classes/output/resultsaction.php + Example context (json): + { + "resultaction": { + "id": "url_select_test", + "options": [{ + "name": "Grades", + "value": "/mod/quiz/report.php?id=4&mode=overview" + }, + { + "name": "Responses", + "value": "/mod/quiz/report.php?id=4&mode=responses" + }, + { + "name": "Statistics", + "value": "/mod/quiz/report.php?id=4&mode=statistics" + }, + { + "name": "Manual grading", + "value": "/mod/quiz/report.php?id=4&mode=grading" + } + ] + } + } +}} +
+
+
+ {{#resultaction}} + {{>core/url_select}} + {{/resultaction}} +
+
+
diff --git a/mod/quiz/tests/behat/add_quiz.feature b/mod/quiz/tests/behat/add_quiz.feature index 946486ff6f3..11e9e32c6d1 100644 --- a/mod/quiz/tests/behat/add_quiz.feature +++ b/mod/quiz/tests/behat/add_quiz.feature @@ -36,7 +36,7 @@ Feature: Add a quiz And I log out And I am on the "Test quiz name" "quiz activity" page logged in as student1 - And I press "Attempt quiz now" + And I follow "Attempt quiz" Then I should see "Question 1" And I should see "Answer the first question" And I set the field "True" to "1" diff --git a/mod/quiz/tests/behat/attempt_basic.feature b/mod/quiz/tests/behat/attempt_basic.feature index 03472d41ff1..8bdbbe48bff 100644 --- a/mod/quiz/tests/behat/attempt_basic.feature +++ b/mod/quiz/tests/behat/attempt_basic.feature @@ -45,7 +45,7 @@ Feature: Attempt a quiz And I should see "Grade" And I should see "25.00 out of 100.00" And I follow "Finish review" - And I press "Re-attempt quiz" + And I follow "Attempt quiz" @javascript Scenario: Attempt a quiz with mulitple sections @@ -73,7 +73,7 @@ Feature: Attempt a quiz | Section 3 | 5 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" Then I should see "Section 1" in the "Quiz navigation" "block" And I should see question "1" in section "Section 1" in the quiz navigation @@ -125,7 +125,7 @@ Feature: Attempt a quiz | TF1 | 1 | | TF2 | 2 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" Then I should see "Text of the first question" And I should not see "Text of the second question" And I press "Next page" diff --git a/mod/quiz/tests/behat/attempt_begin.feature b/mod/quiz/tests/behat/attempt_begin.feature index 2f72ced854e..0ab9a89dd32 100644 --- a/mod/quiz/tests/behat/attempt_begin.feature +++ b/mod/quiz/tests/behat/attempt_begin.feature @@ -30,7 +30,7 @@ Feature: The various checks that may happen when an attept is started | question | page | | TF1 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" Then I should see "Text of the first question" @javascript @@ -42,11 +42,11 @@ Feature: The various checks that may happen when an attept is started | question | page | | TF1 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" - Then I should see "To attempt this quiz you need to know the quiz password" in the "Start attempt" "dialogue" - And I should see "Your attempt will have a time limit of 1 hour. When you " in the "Start attempt" "dialogue" + And I follow "Attempt quiz" + Then I should see "To attempt this quiz you need to know the quiz password" in the "region-main" "region" + And I should see "Your attempt will have a time limit of 1 hour. When you " in the "region-main" "region" And I set the field "Quiz password" to "Frog" - And I click on "Start attempt" "button" in the "Start attempt" "dialogue" + And I click on "Start attempt" "button" in the "region-main" "region" And I should see "Text of the first question" @javascript @@ -58,10 +58,10 @@ Feature: The various checks that may happen when an attept is started | question | page | | TF1 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" - And I click on "Cancel" "button" in the "Start attempt" "dialogue" + And I follow "Attempt quiz" + And I click on "Cancel" "button" in the "region-main" "region" Then I should see "Quiz 1 description" - And "Attempt quiz now" "button" should be visible + And "Attempt quiz" "link" should be visible @javascript Scenario: Start a quiz with time limit and password, get the password wrong first time @@ -72,9 +72,9 @@ Feature: The various checks that may happen when an attept is started | question | page | | TF1 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" And I set the field "Quiz password" to "Toad" - And I click on "Start attempt" "button" in the "Start attempt" "dialogue" + And I click on "Start attempt" "button" in the "region-main" "region" Then I should see "Quiz 1 description" And I should see "To attempt this quiz you need to know the quiz password" And I should see "Your attempt will have a time limit of 1 hour. When you " @@ -94,9 +94,9 @@ Feature: The various checks that may happen when an attept is started | question | page | | TF1 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" And I set the field "Quiz password" to "Toad" - And I click on "Start attempt" "button" in the "Start attempt" "dialogue" + And I click on "Start attempt" "button" in the "region-main" "region" And I should see "Quiz 1 description" And I should see "To attempt this quiz you need to know the quiz password" And I should see "Your attempt will have a time limit of 1 hour. When you " @@ -106,4 +106,4 @@ Feature: The various checks that may happen when an attept is started And I press tab key in "Quiz password" "field" And I press "Cancel" Then I should see "Quiz 1 description" - And "Attempt quiz now" "button" should be visible + And "Attempt quiz" "link" should be visible diff --git a/mod/quiz/tests/behat/attempt_redo_questions.feature b/mod/quiz/tests/behat/attempt_redo_questions.feature index dcf73cd7dfd..f59c402e80b 100644 --- a/mod/quiz/tests/behat/attempt_redo_questions.feature +++ b/mod/quiz/tests/behat/attempt_redo_questions.feature @@ -34,7 +34,7 @@ Feature: Allow students to redo questions in a practice quiz, without starting a @javascript Scenario: After completing a question, there is a redo question button that restarts the question Given I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - When I press "Attempt quiz now" + When I follow "Attempt quiz" And I click on "False" "radio" in the "First question" "question" And I click on "Check" "button" in the "First question" "question" And I press "Try another question like this one" @@ -44,7 +44,7 @@ Feature: Allow students to redo questions in a practice quiz, without starting a @javascript Scenario: The redo question button is visible but disabled for teachers Given I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - When I press "Attempt quiz now" + When I follow "Attempt quiz" And I click on "False" "radio" in the "First question" "question" And I click on "Check" "button" in the "First question" "question" And I log out @@ -56,7 +56,7 @@ Feature: Allow students to redo questions in a practice quiz, without starting a @javascript Scenario: The redo question buttons are no longer visible after the attempt is submitted. Given I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - When I press "Attempt quiz now" + When I follow "Attempt quiz" And I click on "False" "radio" in the "First question" "question" And I click on "Check" "button" in the "First question" "question" And I press "Finish attempt ..." @@ -67,7 +67,7 @@ Feature: Allow students to redo questions in a practice quiz, without starting a @javascript @_switch_window Scenario: Teachers reviewing can see all the questions attempted in a slot Given I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - When I press "Attempt quiz now" + When I follow "Attempt quiz" And I click on "False" "radio" in the "First question" "question" And I click on "Check" "button" in the "First question" "question" And I press "Try another question like this one" @@ -96,7 +96,7 @@ Feature: Allow students to redo questions in a practice quiz, without starting a @javascript Scenario: Redoing question 1 should save any changes to question 2 on the same page Given I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - When I press "Attempt quiz now" + When I follow "Attempt quiz" And I click on "False" "radio" in the "First question" "question" And I click on "Check" "button" in the "First question" "question" And I click on "True" "radio" in the "Second question" "question" @@ -119,7 +119,7 @@ Feature: Allow students to redo questions in a practice quiz, without starting a | slot | actualquestion | | 1 | TF1 | And I am on the "Quiz 2" "mod_quiz > View" page logged in as "student" - When I press "Continue the last attempt" + When I follow "Attempt quiz" And I should see "First question" And I click on "False" "radio" And I click on "Check" "button" diff --git a/mod/quiz/tests/behat/attempt_require_previous.feature b/mod/quiz/tests/behat/attempt_require_previous.feature index 0caf8aff346..46930e2e73a 100644 --- a/mod/quiz/tests/behat/attempt_require_previous.feature +++ b/mod/quiz/tests/behat/attempt_require_previous.feature @@ -35,7 +35,7 @@ Feature: Attempt a quiz where some questions require that the previous question | TF2 | 1 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" Then I should see "First question" And I should see "This question cannot be attempted until the previous question has been completed." @@ -63,7 +63,7 @@ Feature: Attempt a quiz where some questions require that the previous question | TF2 | 1 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" And I click on "True" "radio" in the "First question" "question" And I press "Check" @@ -88,7 +88,7 @@ Feature: Attempt a quiz where some questions require that the previous question | TF2 | 1 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" And I press "Finish attempt ..." And I press "Submit all and finish" And I click on "Submit all and finish" "button" in the "Confirmation" "dialogue" @@ -111,7 +111,7 @@ Feature: Attempt a quiz where some questions require that the previous question | TF2 | 1 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" Then I should see "First question" And I should see "Second question" @@ -135,7 +135,7 @@ Feature: Attempt a quiz where some questions require that the previous question | Section 1 | 1 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" Then I should see "First question" And I should see "Second question" @@ -160,7 +160,7 @@ Feature: Attempt a quiz where some questions require that the previous question | Section 2 | 2 | 0 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" And I press "Next page" Then I should see "Second question" @@ -181,7 +181,7 @@ Feature: Attempt a quiz where some questions require that the previous question | TF2 | 1 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" Then I should see "First question" And I should see "Second question" @@ -202,7 +202,7 @@ Feature: Attempt a quiz where some questions require that the previous question | TF2 | 1 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" Then I should see "First question" And I should see "Second question" @@ -223,7 +223,7 @@ Feature: Attempt a quiz where some questions require that the previous question | TF1 | 1 | 1 | When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" - And I press "Attempt quiz now" + And I follow "Attempt quiz" Then I should see "Read me" And I should see "First question" diff --git a/mod/quiz/tests/behat/completion_condition_attempts_used.feature b/mod/quiz/tests/behat/completion_condition_attempts_used.feature index c58e3387d64..7c5944f0c73 100644 --- a/mod/quiz/tests/behat/completion_condition_attempts_used.feature +++ b/mod/quiz/tests/behat/completion_condition_attempts_used.feature @@ -41,7 +41,7 @@ Feature: Set a quiz to be marked complete when the student uses all attempts all And the "Receive a passing grade" completion condition of "Test quiz name" is displayed as "failed" And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "todo" And I follow "Test quiz name" - And I press "Re-attempt quiz" + And I follow "Attempt quiz" And I set the field "" to "1" And I press "Finish attempt ..." And I press "Submit all and finish" diff --git a/mod/quiz/tests/behat/completion_condition_minimum_attempts.feature b/mod/quiz/tests/behat/completion_condition_minimum_attempts.feature index 1c5df692704..cc9267ae7b6 100644 --- a/mod/quiz/tests/behat/completion_condition_minimum_attempts.feature +++ b/mod/quiz/tests/behat/completion_condition_minimum_attempts.feature @@ -43,7 +43,7 @@ Feature: Set a quiz to be marked complete when the student completes a minimum a And I am on "Course 1" course homepage And the "Make attempts: 2" completion condition of "Test quiz name" is displayed as "todo" And I follow "Test quiz name" - And I press "Re-attempt quiz" + And I follow "Attempt quiz" And I set the field "False" to "1" And I press "Finish attempt ..." And I press "Submit all and finish" diff --git a/mod/quiz/tests/behat/editing_add.feature b/mod/quiz/tests/behat/editing_add.feature index c93e14dc7f4..47b5254441c 100644 --- a/mod/quiz/tests/behat/editing_add.feature +++ b/mod/quiz/tests/behat/editing_add.feature @@ -18,7 +18,6 @@ Feature: Edit quiz page - adding things | activity | name | intro | course | idnumber | | quiz | Quiz 1 | Quiz 1 for testing the Add menu | C1 | quiz1 | And I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher1" - And I should see "Editing quiz: Quiz 1" @javascript Scenario: Add some new question to the quiz using '+ a new question' options of the 'Add' menu. @@ -30,7 +29,6 @@ Feature: Edit quiz page - adding things And I set the field "Question name" to "Essay 01 new" And I set the field "Question text" to "Please write 200 words about Essay 01" And I press "id_submitbutton" - Then I should see "Editing quiz: Quiz 1" And I should see "Essay 01 new" on quiz page "1" And I open the "Page 1" add to quiz menu @@ -41,7 +39,6 @@ Feature: Edit quiz page - adding things And I set the field "Question name" to "Essay 02 new" And I set the field "Question text" to "Please write 200 words about Essay 02" And I press "id_submitbutton" - Then I should see "Editing quiz: Quiz 1" And I should see "Essay 01 new" on quiz page "1" And I should see "Essay 02 new" on quiz page "1" @@ -53,7 +50,6 @@ Feature: Edit quiz page - adding things And I set the field "Question name" to "Essay 03 new" And I set the field "Question text" to "Please write 300 words about Essay 03" And I press "id_submitbutton" - Then I should see "Editing quiz: Quiz 1" And I should see "Essay 01 new" on quiz page "1" And I should see "Essay 02 new" on quiz page "1" And I should see "Essay 03 new" on quiz page "1" @@ -66,7 +62,6 @@ Feature: Edit quiz page - adding things And I set the field "Question name" to "Essay 04 new" And I set the field "Question text" to "Please write 300 words about Essay 04" And I press "id_submitbutton" - Then I should see "Editing quiz: Quiz 1" And I should see "Essay 01 new" on quiz page "1" And I should see "Essay 02 new" on quiz page "1" And I should see "Essay 03 new" on quiz page "1" @@ -77,7 +72,7 @@ Feature: Edit quiz page - adding things When I press "Repaginate" Then I should see "Repaginate with" And I set the field "menuquestionsperpage" to "2" - When I click on "Go" "button" in the "Repaginate" "dialogue" + And I click on "Go" "button" in the "Repaginate" "dialogue" And I should see "Essay 01 new" on quiz page "1" And I should see "Essay 02 new" on quiz page "1" And I should see "Essay 03 new" on quiz page "2" @@ -89,10 +84,9 @@ Feature: Edit quiz page - adding things And I set the field "item_qtype_essay" to "1" And I press "submitbutton" Then I should see "Adding an Essay question" - When I set the field "Question name" to "Essay for page 2" + And I set the field "Question name" to "Essay for page 2" And I set the field "Question text" to "Please write 200 words about Essay for page 2" And I press "id_submitbutton" - Then I should see "Editing quiz: Quiz 1" And I should see "Essay 01 new" on quiz page "1" And I should see "Essay 02 new" on quiz page "1" And I should see "Essay 03 new" on quiz page "2" @@ -106,22 +100,23 @@ Feature: Edit quiz page - adding things # Create a couple of sub categories. When I am on "Course 1" course homepage - And I navigate to "Question bank > Categories" in current page administration + And I navigate to "Question bank" in current page administration + And I select "Categories" from the "questionbankactionselect" singleselect Then I should see "Add category" Then I set the field "Parent category" to "Default for C1" And I set the field "Name" to "Subcat 1" And I set the field "Category info" to "This is sub category 1" - Then I press "id_submitbutton" + And I press "id_submitbutton" And I should see "Subcat 1" Then I set the field "Parent category" to "Default for C1" And I set the field "Name" to "Subcat 2" And I set the field "Category info" to "This is sub category 2" - Then I press "id_submitbutton" + And I press "id_submitbutton" And I should see "Subcat 2" - And I click on "Questions" "link" - Then I should see "Question bank" + And I select "Questions" from the "questionbankactionselect" singleselect + And I should see "Question bank" And I should see "Select a category" # Create the Essay 01 question. @@ -194,14 +189,12 @@ Feature: Edit quiz page - adding things And I click on "Essay 03" "checkbox" Then the "Add selected questions to the quiz" "button" should be enabled And I click on "Add to quiz" "link" in the "Essay 03" "table_row" - Then I should see "Editing quiz: Quiz 1" And I should see "Essay 03" on quiz page "1" # Add Essay 01 from question bank. And I open the "Page 1" add to quiz menu And I follow "from question bank" And I click on "Add to quiz" "link" in the "Essay 01" "table_row" - Then I should see "Editing quiz: Quiz 1" And I should see "Essay 03" on quiz page "1" And I should see "Essay 01" on quiz page "1" @@ -211,7 +204,6 @@ Feature: Edit quiz page - adding things And I should see "Select a category" And I set the field "Select a category" to "Subcat 1" And I click on "Add to quiz" "link" in the "Essay 02" "table_row" - Then I should see "Editing quiz: Quiz 1" And I should see "Essay 03" on quiz page "1" And I should see "Essay 01" on quiz page "1" And I should see "Essay 02" on quiz page "1" @@ -220,7 +212,6 @@ Feature: Edit quiz page - adding things And I open the "Page 1" add to quiz menu And I follow "a random question" And I press "Add random question" - Then I should see "Editing quiz: Quiz 1" And I should see "Essay 03" on quiz page "1" And I should see "Essay 01" on quiz page "1" And I should see "Essay 02" on quiz page "1" @@ -246,7 +237,6 @@ Feature: Edit quiz page - adding things And I set the field "Question name" to "Essay for page 4" And I set the field "Question text" to "Please write 200 words about Essay for page 4" And I press "id_submitbutton" - Then I should see "Editing quiz: Quiz 1" And I should see "Essay 03" on quiz page "1" And I should see "Essay 01" on quiz page "2" And I should see "Essay 02" on quiz page "3" diff --git a/mod/quiz/tests/behat/editing_repaginate.feature b/mod/quiz/tests/behat/editing_repaginate.feature index 37e4ac78057..4309f7481ba 100644 --- a/mod/quiz/tests/behat/editing_repaginate.feature +++ b/mod/quiz/tests/behat/editing_repaginate.feature @@ -25,8 +25,6 @@ Feature: Edit quiz page - pagination Scenario: Repaginate questions with N question(s) per page as well as clicking on "add page break" or "Remove page break" icons to repaginate in any desired format. - Then I should see "Editing quiz: Quiz 1" - # Add the first Essay question. And I open the action menu in ".page-add-actions" "css_element" And I follow "a new question" @@ -36,8 +34,7 @@ Feature: Edit quiz page - pagination And I set the field "Question name" to "Essay 01 new" And I set the field "Question text" to "Please write 100 words about Essay 01" And I press "id_submitbutton" - Then I should see "Editing quiz: Quiz 1" - And I should see "Essay 01 new" on quiz page "1" + Then I should see "Essay 01 new" on quiz page "1" # Add the second Essay question. And I open the action menu in ".page-add-actions" "css_element" @@ -48,8 +45,7 @@ Feature: Edit quiz page - pagination And I set the field "Question name" to "Essay 02 new" And I set the field "Question text" to "Please write 200 words about Essay 02" And I press "id_submitbutton" - Then I should see "Editing quiz: Quiz 1" - And I should see "Essay 01 new" on quiz page "1" + Then I should see "Essay 01 new" on quiz page "1" And I should see "Essay 02 new" on quiz page "1" # Start repaginating. @@ -73,8 +69,7 @@ Feature: Edit quiz page - pagination And I set the field "Question name" to "Essay 03 new" And I set the field "Question text" to "Please write 200 words about Essay 03" And I press "id_submitbutton" - Then I should see "Editing quiz: Quiz 1" - And I should see "Essay 01 new" on quiz page "1" + Then I should see "Essay 01 new" on quiz page "1" And I should see "Essay 02 new" on quiz page "1" And I should see "Essay 03 new" on quiz page "1" And I should not see "Page 2" @@ -121,8 +116,7 @@ Feature: Edit quiz page - pagination When I set the field "Question name" to "Essay 04 new" And I set the field "Question text" to "Please write 300 words about Essay 04" And I press "id_submitbutton" - Then I should see "Editing quiz: Quiz 1" - And I should see "Essay 01 new" on quiz page "1" + Then I should see "Essay 01 new" on quiz page "1" And I should see "Essay 02 new" on quiz page "2" And I should see "Essay 03 new" on quiz page "3" And I should see "Essay 04 new" on quiz page "3" diff --git a/mod/quiz/tests/behat/editing_set_marks_with_attempts.feature b/mod/quiz/tests/behat/editing_set_marks_with_attempts.feature index f48fbb5fef2..b5ab4450c02 100644 --- a/mod/quiz/tests/behat/editing_set_marks_with_attempts.feature +++ b/mod/quiz/tests/behat/editing_set_marks_with_attempts.feature @@ -31,7 +31,7 @@ Feature: Edit quiz marks with attempts | Default mark | 3.0 | And I log out And I am on the "Quiz 1" "mod_quiz > View" page logged in as "student1" - And I press "Attempt quiz now" + And I follow "Attempt quiz" And I log out And I log in as "teacher1" And I am on the "Quiz 1" "mod_quiz > Edit" page diff --git a/mod/quiz/tests/behat/manually_mark_question.feature b/mod/quiz/tests/behat/manually_mark_question.feature index 755e824109e..3b8fa99dd6b 100644 --- a/mod/quiz/tests/behat/manually_mark_question.feature +++ b/mod/quiz/tests/behat/manually_mark_question.feature @@ -29,7 +29,7 @@ Feature: Teachers can override the grade for any question | question | page | | TF1 | 1 | And I am on the "Quiz 1" "mod_quiz > View" page logged in as "student1" - And I press "Attempt quiz now" + And I follow "Attempt quiz" And I follow "Finish attempt ..." And I press "Submit all and finish" And I click on "Submit all and finish" "button" in the "Confirmation" "dialogue" diff --git a/mod/quiz/tests/behat/preview.feature b/mod/quiz/tests/behat/preview.feature index f16980eb84a..56969773d0d 100644 --- a/mod/quiz/tests/behat/preview.feature +++ b/mod/quiz/tests/behat/preview.feature @@ -44,6 +44,6 @@ Feature: Preview a quiz as a teacher @javascript Scenario: Preview the quiz Given I am on the "Quiz 1" "mod_quiz > View" page logged in as "teacher" - When I press "Preview quiz now" + When I follow "Preview quiz" Then I should see "Question 1" And "Start a new preview" "button" should exist diff --git a/mod/quiz/tests/behat/quiz_activity_completion.feature b/mod/quiz/tests/behat/quiz_activity_completion.feature index 7845ea74c75..2460e3f122e 100644 --- a/mod/quiz/tests/behat/quiz_activity_completion.feature +++ b/mod/quiz/tests/behat/quiz_activity_completion.feature @@ -62,7 +62,7 @@ Feature: View activity completion in the quiz activity And the "Receive a grade" completion condition of "Test quiz name" is displayed as "done" And the "Receive a passing grade" completion condition of "Test quiz name" is displayed as "failed" And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "todo" - And I press "Re-attempt quiz" + And I follow "Attempt quiz" And I set the field "" to "1" And I press "Finish attempt ..." And I press "Submit all and finish" diff --git a/mod/quiz/tests/behat/quiz_user_override.feature b/mod/quiz/tests/behat/quiz_user_override.feature index 15d3bcd34c4..a12de46eec7 100644 --- a/mod/quiz/tests/behat/quiz_user_override.feature +++ b/mod/quiz/tests/behat/quiz_user_override.feature @@ -33,7 +33,7 @@ Feature: Quiz user override | quiz | Test quiz | C1 | quiz1 | And I am on the "Test quiz" "mod_quiz > View" page logged in as "teacher" And I change window size to "large" - And I navigate to "User overrides" in current page administration + And I navigate to "Overrides" in current page administration And I press "Add user override" And I set the following fields to these values: | Override user | Student One (student1@example.com) | @@ -147,7 +147,7 @@ Feature: Quiz user override | Test quiz | student1 | 2 | | Test quiz | student2 | 2 | And I am on the "Test quiz" "mod_quiz > View" page logged in as "helper" - When I navigate to "User overrides" in current page administration + When I navigate to "Overrides" in current page administration Then "Student One" "table_row" should exist And "Student Two" "table_row" should exist And "Add user override" "button" should not exist diff --git a/mod/quiz/tests/behat/settings_form_fields_disableif.feature b/mod/quiz/tests/behat/settings_form_fields_disableif.feature index 1f04d6cba4f..72f6bab5481 100644 --- a/mod/quiz/tests/behat/settings_form_fields_disableif.feature +++ b/mod/quiz/tests/behat/settings_form_fields_disableif.feature @@ -52,7 +52,7 @@ Feature: Settings form fields disabled if not required # And the "id_delay2_enabled" "field" should be enabled When I press "Save and display" - And I navigate to "User overrides" in current page administration + And I navigate to "Overrides" in current page administration And I press "Add user override" And I set the following fields to these values: | Override user | Student1 | @@ -67,7 +67,7 @@ Feature: Settings form fields disabled if not required And the "id_delay2_enabled" "field" should be enabled When I press "Save and display" - And I navigate to "User overrides" in current page administration + And I navigate to "Overrides" in current page administration And I click on "Edit" "link" in the "region-main" "region" And I set the field "Attempts allowed" to "2" And I press "Save" @@ -80,7 +80,7 @@ Feature: Settings form fields disabled if not required And the "id_delay2_enabled" "field" should be disabled When I press "Save and display" - And I navigate to "User overrides" in current page administration + And I navigate to "Overrides" in current page administration And I press "Add user override" And I set the following fields to these values: | Override user | Student2 | diff --git a/mod/quiz/upgrade.txt b/mod/quiz/upgrade.txt index e15a91141df..9eab59f1c28 100644 --- a/mod/quiz/upgrade.txt +++ b/mod/quiz/upgrade.txt @@ -8,6 +8,11 @@ This files describes API changes in the quiz code. - quiz_send_notification_messages() in mod/quiz/locallib.php * The completionpass criteria has been moved to core as 'completionpassgrade'. Refer to completion/upgrade.txt for further information. +* New argument quizhasquestions has been added to public methods: view_information, view_page_notenrolled and view_page_guest + in mod/quiz/renderer.php. +* The function no_questions_message() in class mod_quiz_renderer is deprecated. Please use generate_no_questions_message() + in the same class. + === 3.11 === diff --git a/mod/quiz/version.php b/mod/quiz/version.php index 46de661b92f..3be42b78443 100644 --- a/mod/quiz/version.php +++ b/mod/quiz/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2021101900; +$plugin->version = 2021101901; $plugin->requires = 2021052500; $plugin->component = 'mod_quiz'; diff --git a/mod/quiz/view.php b/mod/quiz/view.php index 94f609ee231..59f6d191122 100644 --- a/mod/quiz/view.php +++ b/mod/quiz/view.php @@ -250,11 +250,11 @@ echo $OUTPUT->header(); if (isguestuser()) { // Guests can't do a quiz, so offer them a choice of logging in or going back. - echo $output->view_page_guest($course, $quiz, $cm, $context, $viewobj->infomessages); + echo $output->view_page_guest($course, $quiz, $cm, $context, $viewobj->infomessages, $viewobj->quizhasquestions); } else if (!isguestuser() && !($canattempt || $canpreview || $viewobj->canreviewmine)) { // If they are not enrolled in this course in a good enough role, tell them to enrol. - echo $output->view_page_notenrolled($course, $quiz, $cm, $context, $viewobj->infomessages); + echo $output->view_page_notenrolled($course, $quiz, $cm, $context, $viewobj->infomessages, $viewobj->quizhasquestions); } else { echo $output->view_page($course, $quiz, $cm, $context, $viewobj); } diff --git a/mod/scorm/classes/event/tracks_viewed.php b/mod/scorm/classes/event/tracks_viewed.php index 25364c3f741..6554bb85878 100644 --- a/mod/scorm/classes/event/tracks_viewed.php +++ b/mod/scorm/classes/event/tracks_viewed.php @@ -92,8 +92,8 @@ class tracks_viewed extends \core\event\base { */ protected function get_legacy_logdata() { return array($this->courseid, 'scorm', 'userreporttracks', 'report/userreporttracks.php?id=' . $this->contextinstanceid - . '&user=' . $this->relateduserid . '&attempt=' . $this->other['attemptid'] . '&scoid=' . $this->other['scoid'], - $this->other['instanceid'], $this->contextinstanceid); + . '&user=' . $this->relateduserid . '&attempt=' . $this->other['attemptid'] . '&scoid=' . $this->other['scoid'] + . '&mode=' . $this->other['mode'], $this->other['instanceid'], $this->contextinstanceid); } /** diff --git a/mod/scorm/classes/output/actionbar.php b/mod/scorm/classes/output/actionbar.php new file mode 100644 index 00000000000..ae2c278c18d --- /dev/null +++ b/mod/scorm/classes/output/actionbar.php @@ -0,0 +1,120 @@ +. + +namespace mod_scorm\output; + +use renderable; +use renderer_base; +use templatable; +use moodle_url; +use url_select; + +/** + * Render HTML elements for tertiary nav for scorm. + * + * @package mod_scorm + * @copyright 2021 Sujith Haridasan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class actionbar implements renderable, templatable { + /** @var int */ + private $id; + + /** @var string */ + private $download; + + /** @var int */ + private $attemptsmode; + + /** + * actionbar constructor. + * + * @param int $id The course module id. + * @param bool $download Show download button or not. + * @param int $attemptsmode attempts mode for scorm. + */ + public function __construct(int $id, bool $download = false, int $attemptsmode = 0) { + $this->id = $id; + $this->download = $download; + $this->attemptsmode = $attemptsmode; + } + + /** + * Provide data for the template + * + * @param renderer_base $output renderer_base object. + * @return array data for the template + */ + public function export_for_template(renderer_base $output): array { + global $PAGE; + + $basicreportlink = new moodle_url('/mod/scorm/report.php', ['id' => $this->id, 'mode' => 'basic']); + $graphreportlink = new moodle_url('/mod/scorm/report.php', ['id' => $this->id, 'mode' => 'graphs']); + $interactionreportlink = new moodle_url('/mod/scorm/report.php', ['id' => $this->id, 'mode' => 'interactions']); + $objectivesreportlink = new moodle_url('/mod/scorm/report.php', ['id' => $this->id, 'mode' => 'objectives']); + + $reportmenu = [ + $basicreportlink->out(false) => get_string('pluginname', 'scormreport_basic'), + $graphreportlink->out(false) => get_string('pluginname', 'scormreport_graphs'), + $interactionreportlink->out(false) => get_string('pluginname', 'scormreport_interactions'), + $objectivesreportlink->out(false) => get_string('pluginname', 'scormreport_objectives'), + ]; + + $sesskey = sesskey(); + if ($this->download) { + $mode = $PAGE->url->get_param('mode'); + if ($mode === 'basic') { + $options = [ + 'id' => $this->id, 'mode' => $mode, + 'attemptsmode' => $this->attemptsmode, 'sesskey' => $sesskey + ]; + } else if ($mode === 'interactions') { + $options = [ + 'id' => $this->id, 'mode' => $mode, 'qtext' => '0', + 'resp' => '1', 'right' => '0', 'result' => '0', + 'attemptsmode' => $this->attemptsmode, 'sesskey' => $sesskey + ]; + } else if ($mode === 'objectives') { + $options = [ + 'id' => $this->id, 'mode' => $mode, + 'attemptsmode' => $this->attemptsmode, 'objectivescore' => '0', + 'sesskey' => $sesskey + ]; + } + + $options['download'] = 'ODS'; + $downloadodslink = new moodle_url($PAGE->url, $options); + + $options['download'] = 'Excel'; + $downloadexcellink = new moodle_url($PAGE->url, $options); + + $options['download'] = 'CSV'; + $downloadtextlink = new moodle_url($PAGE->url, $options); + } + + $url = new moodle_url('/mod/scorm/report.php', $PAGE->url->remove_params('attemptsmode')); + $urlselect = new url_select($reportmenu, $url->out(false), null, 'selectscormreports'); + + $data = [ + 'scormreports' => $urlselect->export_for_template($output), + 'candownload' => $this->download, + 'downloadods' => ($this->download) ? $downloadodslink->out(false) : '', + 'downloadexcel' => ($this->download) ? $downloadexcellink->out(false) : '', + 'downloadtext' => ($this->download) ? $downloadtextlink->out(false) : '' + ]; + return $data; + } +} diff --git a/mod/scorm/classes/output/userreportsactionbar.php b/mod/scorm/classes/output/userreportsactionbar.php new file mode 100644 index 00000000000..443128124f3 --- /dev/null +++ b/mod/scorm/classes/output/userreportsactionbar.php @@ -0,0 +1,101 @@ +. + +namespace mod_scorm\output; + +use renderable; +use renderer_base; +use templatable; +use moodle_url; +use url_select; + +/** + * Render HTML elements for reports page on tertiary nav. + * + * @package mod_scorm + * @copyright 2021 Sujith Haridasan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class userreportsactionbar implements renderable, templatable { + /** @var int */ + private $id; + + /** @var int */ + private $userid; + + /** @var int */ + private $attempt; + + /** @var string */ + private $reporttype; + + /** @var string */ + private $mode; + + /** @var int */ + private $scoid; + + /** + * userreportsactionbar constructor + * + * @param int $id Course module id. + * @param int $userid User id. + * @param int $attempt Number of attempts. + * @param string $reporttype The report type can be either learning/interact. + * @param string $mode The mode view to set the back button. + * @param int|null $scoid The scorm id. + */ + public function __construct(int $id, int $userid, int $attempt, string $reporttype, string $mode, ?int $scoid = null) { + $this->id = $id; + $this->userid = $userid; + $this->attempt = $attempt; + $this->reporttype = $reporttype; + $this->mode = $mode; + $this->scoid = $scoid; + } + + /** + * Provide data for the template + * + * @param renderer_base $output renderer_base object. + * @return array data for the template. + */ + public function export_for_template(renderer_base $output): array { + $data = [ + 'backurl' => (new moodle_url('/mod/scorm/report.php', ['id' => $this->id, 'mode' => $this->mode]))->out(false) + ]; + + if (!$this->scoid) { + $learnobjects = new moodle_url('/mod/scorm/report/userreport.php', + ['id' => $this->id, 'user' => $this->userid, 'attempt' => $this->attempt, 'mode' => $this->mode]); + $interactions = new moodle_url('/mod/scorm/report/userreportinteractions.php', + ['id' => $this->id, 'user' => $this->userid, 'attempt' => $this->attempt, 'mode' => $this->mode]); + + $reportmenu[$learnobjects->out(false)] = get_string('scoes', 'scorm'); + $reportmenu[$interactions->out(false)] = get_string('interactions', 'scorm'); + + if ($this->reporttype === 'learning') { + $userreporturl = $learnobjects->out(false); + } else { + $userreporturl = $interactions->out(false); + } + $urlselect = new url_select($reportmenu, $userreporturl, [], 'userscormreport'); + $data ['userreport'] = $urlselect->export_for_template($output); + } + + return $data; + } +} diff --git a/mod/scorm/index.php b/mod/scorm/index.php index 34b8418423b..214b94c04c7 100644 --- a/mod/scorm/index.php +++ b/mod/scorm/index.php @@ -48,7 +48,9 @@ $PAGE->set_title($strscorms); $PAGE->set_heading($course->fullname); $PAGE->navbar->add($strscorms); echo $OUTPUT->header(); -echo $OUTPUT->heading($strscorms); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading($strscorms); +} $usesections = course_format_uses_sections($course->format); diff --git a/mod/scorm/lang/en/deprecated.txt b/mod/scorm/lang/en/deprecated.txt index 32ff438da92..f6ed0081dd5 100644 --- a/mod/scorm/lang/en/deprecated.txt +++ b/mod/scorm/lang/en/deprecated.txt @@ -1 +1,2 @@ -duedate,mod_scorm \ No newline at end of file +duedate,mod_scorm +info,mod_scorm diff --git a/mod/scorm/lang/en/scorm.php b/mod/scorm/lang/en/scorm.php index a1265ae0f12..aa61d09f1a4 100644 --- a/mod/scorm/lang/en/scorm.php +++ b/mod/scorm/lang/en/scorm.php @@ -213,7 +213,7 @@ $string['indicator:socialbreadth_help'] = 'This indicator is based on the social $string['indicator:socialbreadthdef'] = 'SCORM social'; $string['indicator:socialbreadthdef_help'] = 'The participant has reached this percentage of the social engagement offered by the SCORM activities during this analysis interval (Levels = No participation, Participant alone)'; $string['indicator:socialbreadthdef_link'] = 'Learning_analytics_indicators#Social_breadth'; -$string['info'] = 'Info'; + $string['interactions'] = 'Interactions'; $string['masteryoverride'] = 'Mastery score overrides status'; $string['masteryoverride_help'] = 'If enabled and a mastery score is provided, when LMSFinish is called and a raw score has been set, status will be recalculated using the raw score and mastery score and any status provided by the SCORM (including "incomplete") will be overridden.'; @@ -458,3 +458,6 @@ $string['youmustselectastatus'] = 'You must select a status to require'; // Deprecated since Moodle 3.8. $string['duedate'] = 'Due date'; + +// Deprecated since Moodle 4.0. +$string['info'] = 'Info'; diff --git a/mod/scorm/lib.php b/mod/scorm/lib.php index 99c5c7b33ba..b04179c83c7 100644 --- a/mod/scorm/lib.php +++ b/mod/scorm/lib.php @@ -1828,3 +1828,22 @@ function mod_scorm_core_calendar_get_event_action_string(string $eventtype): str return get_string($identifier, 'scorm', $modulename); } + +/** + * This function extends the settings navigation block for the site. + * + * It is safe to rely on PAGE here as we will only ever be within the module + * context when this is called + * + * @param navigation_node $settings navigation_node object. + * @param navigation_node $scormnode navigation_node object. + * @return void + */ +function scorm_extend_settings_navigation(navigation_node $settings, navigation_node $scormnode): void { + global $PAGE; + + if (has_capability('mod/scorm:viewreport', $PAGE->cm->context)) { + $url = new moodle_url('/mod/scorm/report.php', ['id' => $PAGE->cm->id]); + $scormnode->add(get_string("reports", "scorm"), $url, navigation_node::TYPE_CUSTOM, null, 'scormreport'); + } +} diff --git a/mod/scorm/locallib.php b/mod/scorm/locallib.php index 6647a2baa96..9508df7252b 100644 --- a/mod/scorm/locallib.php +++ b/mod/scorm/locallib.php @@ -995,16 +995,16 @@ function scorm_print_launch ($user, $scorm, $action, $cm) { 'action' => $CFG->wwwroot.'/mod/scorm/player.php', 'class' => 'container')); if ($scorm->hidebrowse == 0) { - print_string('mode', 'scorm'); - echo ': '.html_writer::empty_tag('input', array('type' => 'radio', 'id' => 'b', 'name' => 'mode', - 'value' => 'browse', 'class' => 'mr-1')). - html_writer::label(get_string('browse', 'scorm'), 'b'); - echo html_writer::empty_tag('input', array('type' => 'radio', - 'id' => 'n', 'name' => 'mode', - 'value' => 'normal', 'checked' => 'checked', - 'class' => 'mx-1')). - html_writer::label(get_string('normal', 'scorm'), 'n'); - + echo html_writer::empty_tag('button', + [ + 'class' => 'btn btn-secondary mr-1', 'name' => 'mode', + 'type' => 'submit', 'id' => 'b', 'value' => 'browse']) . + get_string('browse', 'scorm') . html_writer::end_tag('button'); + echo html_writer::empty_tag('button', + [ + 'class' => 'btn btn-primary mx-1', 'name' => 'mode', + 'type' => 'submit', 'id' => 'n', 'value' => 'normal']) . + get_string('enter', 'scorm') . html_writer::end_tag('button'); } else { echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'mode', 'value' => 'normal')); } @@ -1026,8 +1026,6 @@ function scorm_print_launch ($user, $scorm, $action, $cm) { echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'scoid', 'value' => $launchsco)); echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'cm', 'value' => $cm->id)); echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'currentorg', 'value' => $orgidentifier)); - echo html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('enter', 'scorm'), - 'class' => 'btn btn-primary')); echo html_writer::end_tag('form'); echo html_writer::end_div(); } diff --git a/mod/scorm/player.php b/mod/scorm/player.php index f0cc78e674f..dcad9235939 100644 --- a/mod/scorm/player.php +++ b/mod/scorm/player.php @@ -83,6 +83,8 @@ if ($displaymode !== '') { $url->param('display', $displaymode); } $PAGE->set_url($url); +$PAGE->set_secondary_active_tab("modulepage"); + $forcejs = get_config('scorm', 'forcejavascript'); if (!empty($forcejs)) { $PAGE->add_body_class('forcejavascript'); @@ -191,7 +193,7 @@ if (file_exists($CFG->dirroot.'/mod/scorm/datamodels/'.$scorm->version.'.js')) { } echo $OUTPUT->header(); -if (!empty($scorm->displayactivityname)) { +if (!empty($scorm->displayactivityname) && !$PAGE->has_secondary_navigation()) { echo $OUTPUT->heading(format_string($scorm->name)); } @@ -203,7 +205,11 @@ $PAGE->requires->string_for_js('popupsblocked', 'scorm'); $name = false; -echo html_writer::start_div('', array('id' => 'scormpage')); +$scrompagestyle = "margin-top: 1em"; +if ($mode === 'normal') { + $scrompagestyle = "margin-top: 3em"; +} +echo html_writer::start_div('', array('id' => 'scormpage', 'style' => $scrompagestyle)); echo html_writer::start_div('', array('id' => 'tocbox')); echo html_writer::div(html_writer::tag('script', '', array('id' => 'external-scormapi', 'type' => 'text/JavaScript')), '', array('id' => 'scormapi-parent')); diff --git a/mod/scorm/renderer.php b/mod/scorm/renderer.php index 4f5a2fa8c75..a3355873101 100644 --- a/mod/scorm/renderer.php +++ b/mod/scorm/renderer.php @@ -76,6 +76,25 @@ class mod_scorm_renderer extends plugin_renderer_base { return html_writer::tag('div', $output, array('class' => 'paging')); } + /** + * Rendered HTML for the report action is provided. + * + * @param \mod_scorm\output\actionbar $actionbar actionbar object. + * @return bool|string rendered HTML for the report action. + */ + public function report_actionbar(\mod_scorm\output\actionbar $actionbar): string { + return $this->render_from_template('mod_scorm/report_actionbar', $actionbar->export_for_template($this)); + } + + /** + * Rendered HTML for the user report action is provided + * + * @param \mod_scorm\output\userreportsactionbar $userreportsactionbar userreportsactionbar object + * @return string rendered HTML for the user report action. + */ + public function user_report_actionbar(\mod_scorm\output\userreportsactionbar $userreportsactionbar): string { + return $this->render_from_template('mod_scorm/user_report_actionbar', $userreportsactionbar->export_for_template($this)); + } } /** diff --git a/mod/scorm/report.php b/mod/scorm/report.php index 7e39f2ed1cf..8e4aeab26c7 100644 --- a/mod/scorm/report.php +++ b/mod/scorm/report.php @@ -56,6 +56,9 @@ $PAGE->set_pagelayout('report'); require_capability('mod/scorm:viewreport', $contextmodule); +// Activate the secondary nav tab. +navigation_node::override_active_url(new moodle_url('/mod/scorm/report.php', ['id' => $id])); + if (count($reportlist) < 1) { print_error('erroraccessingreport', 'scorm'); } @@ -86,9 +89,9 @@ if (empty($noheader)) { $PAGE->navbar->add($strreport, new moodle_url('/mod/scorm/report.php', array('id' => $cm->id))); echo $OUTPUT->header(); - echo $OUTPUT->heading(format_string($scorm->name)); - $currenttab = 'reports'; - require($CFG->dirroot . '/mod/scorm/tabs.php'); + if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($scorm->name)); + } } // Open the selected Scorm report and display it. diff --git a/mod/scorm/report/basic/classes/report.php b/mod/scorm/report/basic/classes/report.php index d315929da83..a62e645ba46 100644 --- a/mod/scorm/report/basic/classes/report.php +++ b/mod/scorm/report/basic/classes/report.php @@ -43,6 +43,13 @@ class report extends \mod_scorm\report { $attemptsmode = optional_param('attemptsmode', SCORM_REPORT_ATTEMPTS_ALL_STUDENTS, PARAM_INT); $PAGE->set_url(new \moodle_url($PAGE->url, array('attemptsmode' => $attemptsmode))); + // Scorm action bar for report. + if ($download === '') { + $actionbar = new \mod_scorm\output\actionbar($cm->id, true, $attemptsmode); + $renderer = $PAGE->get_renderer('mod_scorm'); + echo $renderer->report_actionbar($actionbar); + } + if ($action == 'delete' && has_capability('mod/scorm:deleteresponses', $contextmodule) && confirm_sesskey()) { if (scorm_delete_responses($attemptids, $scorm)) { // Delete responses. echo $OUTPUT->notification(get_string('scormresponsedeleted', 'scorm'), 'notifysuccess'); @@ -401,7 +408,7 @@ class report extends \mod_scorm\report { } else { if (!$download) { $url = new \moodle_url('/mod/scorm/report/userreport.php', array('id' => $cm->id, - 'user' => $scouser->userid, 'attempt' => $scouser->attempt)); + 'user' => $scouser->userid, 'attempt' => $scouser->attempt, 'mode' => 'basic')); $row[] = \html_writer::link($url, $scouser->attempt); } else { $row[] = $scouser->attempt; @@ -445,7 +452,8 @@ class report extends \mod_scorm\report { } if (!$download) { $url = new \moodle_url('/mod/scorm/report/userreporttracks.php', array('id' => $cm->id, - 'scoid' => $sco->id, 'user' => $scouser->userid, 'attempt' => $scouser->attempt)); + 'scoid' => $sco->id, 'user' => $scouser->userid, 'attempt' => $scouser->attempt, + 'mode' => 'basic')); $row[] = $OUTPUT->pix_icon($trackdata->status, $strstatus, 'scorm') . '
' . \html_writer::link($url, $score, array('title' => get_string('details', 'scorm'))); } else { @@ -488,28 +496,6 @@ class report extends \mod_scorm\report { echo \html_writer::end_tag('div'); echo \html_writer::end_tag('form'); } - echo \html_writer::end_div(); - if (!empty($attempts)) { - echo \html_writer::start_tag('table', array('class' => 'boxaligncenter')).\html_writer::start_tag('tr'); - echo \html_writer::start_tag('td'); - echo $OUTPUT->single_button(new \moodle_url($PAGE->url, - array('download' => 'ODS') + $displayoptions), - get_string('downloadods')); - echo \html_writer::end_tag('td'); - echo \html_writer::start_tag('td'); - echo $OUTPUT->single_button(new \moodle_url($PAGE->url, - array('download' => 'Excel') + $displayoptions), - get_string('downloadexcel')); - echo \html_writer::end_tag('td'); - echo \html_writer::start_tag('td'); - echo $OUTPUT->single_button(new \moodle_url($PAGE->url, - array('download' => 'CSV') + $displayoptions), - get_string('downloadtext')); - echo \html_writer::end_tag('td'); - echo \html_writer::start_tag('td'); - echo \html_writer::end_tag('td'); - echo \html_writer::end_tag('tr').\html_writer::end_tag('table'); - } } } else { if ($candelete && !$download) { diff --git a/mod/scorm/report/graphs/classes/report.php b/mod/scorm/report/graphs/classes/report.php index b295f00c423..f88f013e5e3 100644 --- a/mod/scorm/report/graphs/classes/report.php +++ b/mod/scorm/report/graphs/classes/report.php @@ -135,6 +135,10 @@ class report extends \mod_scorm\report { $contextmodule = context_module::instance($cm->id); + $actionbar = new \mod_scorm\output\actionbar($cm->id, false, 0); + $renderer = $PAGE->get_renderer('mod_scorm'); + echo $renderer->report_actionbar($actionbar); + if ($groupmode = groups_get_activity_groupmode($cm)) { // Groups are being used. groups_print_activity_menu($cm, new moodle_url($PAGE->url)); } diff --git a/mod/scorm/report/interactions/classes/report.php b/mod/scorm/report/interactions/classes/report.php index 43fd42b5c1b..24e195739c4 100644 --- a/mod/scorm/report/interactions/classes/report.php +++ b/mod/scorm/report/interactions/classes/report.php @@ -44,6 +44,13 @@ class report extends \mod_scorm\report { $attemptsmode = optional_param('attemptsmode', SCORM_REPORT_ATTEMPTS_ALL_STUDENTS, PARAM_INT); $PAGE->set_url(new \moodle_url($PAGE->url, array('attemptsmode' => $attemptsmode))); + // Scorm action bar for report. + if ($download === '') { + $actionbar = new \mod_scorm\output\actionbar($cm->id, true, $attemptsmode); + $renderer = $PAGE->get_renderer('mod_scorm'); + echo $renderer->report_actionbar($actionbar); + } + if ($action == 'delete' && has_capability('mod/scorm:deleteresponses', $contextmodule) && confirm_sesskey()) { if (scorm_delete_responses($attemptids, $scorm)) { // Delete responses. echo $OUTPUT->notification(get_string('scormresponsedeleted', 'scorm'), 'notifysuccess'); @@ -446,9 +453,10 @@ class report extends \mod_scorm\report { } else { if (!$download) { $url = new \moodle_url('/mod/scorm/report/userreport.php', - array('id' => $cm->id, - 'user' => $scouser->userid, - 'attempt' => $scouser->attempt)); + array('id' => $cm->id, + 'user' => $scouser->userid, + 'attempt' => $scouser->attempt, + 'mode' => 'interactions')); $row[] = \html_writer::link($url, $scouser->attempt); } else { $row[] = $scouser->attempt; @@ -486,7 +494,8 @@ class report extends \mod_scorm\report { } if (!$download) { $url = new \moodle_url('/mod/scorm/report/userreporttracks.php', array('id' => $cm->id, - 'scoid' => $sco->id, 'user' => $scouser->userid, 'attempt' => $scouser->attempt)); + 'scoid' => $sco->id, 'user' => $scouser->userid, 'attempt' => $scouser->attempt, + 'mode' => 'interactions')); $row[] = $OUTPUT->pix_icon($trackdata->status, $strstatus, 'scorm') . '
' . \html_writer::link($url, $score, array('title' => get_string('details', 'scorm'))); } else { @@ -578,34 +587,6 @@ class report extends \mod_scorm\report { echo \html_writer::end_tag('div'); echo \html_writer::end_tag('form'); } - echo \html_writer::end_div(); - if (!empty($attempts)) { - echo \html_writer::start_tag('table', array('class' => 'boxaligncenter')).\html_writer::start_tag('tr'); - echo \html_writer::start_tag('td'); - echo $OUTPUT->single_button(new \moodle_url($PAGE->url, - array('download' => 'ODS') + $displayoptions), - get_string('downloadods'), - 'post', - ['class' => 'mt-1']); - echo \html_writer::end_tag('td'); - echo \html_writer::start_tag('td'); - echo $OUTPUT->single_button(new \moodle_url($PAGE->url, - array('download' => 'Excel') + $displayoptions), - get_string('downloadexcel'), - 'post', - ['class' => 'mt-1']); - echo \html_writer::end_tag('td'); - echo \html_writer::start_tag('td'); - echo $OUTPUT->single_button(new \moodle_url($PAGE->url, - array('download' => 'CSV') + $displayoptions), - get_string('downloadtext'), - 'post', - ['class' => 'mt-1']); - echo \html_writer::end_tag('td'); - echo \html_writer::start_tag('td'); - echo \html_writer::end_tag('td'); - echo \html_writer::end_tag('tr').\html_writer::end_tag('table'); - } } } else { if ($candelete && !$download) { diff --git a/mod/scorm/report/objectives/classes/report.php b/mod/scorm/report/objectives/classes/report.php index f901d951764..eaaa4bb925b 100644 --- a/mod/scorm/report/objectives/classes/report.php +++ b/mod/scorm/report/objectives/classes/report.php @@ -50,6 +50,13 @@ class report extends \mod_scorm\report { $attemptsmode = optional_param('attemptsmode', SCORM_REPORT_ATTEMPTS_ALL_STUDENTS, PARAM_INT); $PAGE->set_url(new \moodle_url($PAGE->url, array('attemptsmode' => $attemptsmode))); + // Scorm action bar for report. + if ($download === '') { + $actionbar = new \mod_scorm\output\actionbar($cm->id, true, $attemptsmode); + $renderer = $PAGE->get_renderer('mod_scorm'); + echo $renderer->report_actionbar($actionbar); + } + if ($action == 'delete' && has_capability('mod/scorm:deleteresponses', $contextmodule) && confirm_sesskey()) { if (scorm_delete_responses($attemptids, $scorm)) { // Delete responses. echo $OUTPUT->notification(get_string('scormresponsedeleted', 'scorm'), 'notifysuccess'); @@ -436,7 +443,7 @@ class report extends \mod_scorm\report { } else { if (!$download) { $url = new \moodle_url('/mod/scorm/report/userreport.php', array('id' => $cm->id, - 'user' => $scouser->userid, 'attempt' => $scouser->attempt)); + 'user' => $scouser->userid, 'attempt' => $scouser->attempt, 'mode' => 'objectives')); $row[] = \html_writer::link($url, $scouser->attempt); } else { $row[] = $scouser->attempt; @@ -474,7 +481,8 @@ class report extends \mod_scorm\report { } if (!$download) { $url = new \moodle_url('/mod/scorm/report/userreporttracks.php', array('id' => $cm->id, - 'scoid' => $sco->id, 'user' => $scouser->userid, 'attempt' => $scouser->attempt)); + 'scoid' => $sco->id, 'user' => $scouser->userid, 'attempt' => $scouser->attempt, + 'mode' => 'objectives')); $row[] = $OUTPUT->pix_icon($trackdata->status, $strstatus, 'scorm') . '
' . \html_writer::link($url, $score, array('title' => get_string('details', 'scorm'))); } else { @@ -577,34 +585,6 @@ class report extends \mod_scorm\report { echo \html_writer::end_tag('div'); echo \html_writer::end_tag('form'); } - echo \html_writer::end_div(); - if (!empty($attempts)) { - echo \html_writer::start_tag('table', array('class' => 'boxaligncenter')).\html_writer::start_tag('tr'); - echo \html_writer::start_tag('td'); - echo $OUTPUT->single_button(new \moodle_url($PAGE->url, - array('download' => 'ODS') + $displayoptions), - get_string('downloadods'), - 'post', - ['class' => 'mt-1']); - echo \html_writer::end_tag('td'); - echo \html_writer::start_tag('td'); - echo $OUTPUT->single_button(new \moodle_url($PAGE->url, - array('download' => 'Excel') + $displayoptions), - get_string('downloadexcel'), - 'post', - ['class' => 'mt-1']); - echo \html_writer::end_tag('td'); - echo \html_writer::start_tag('td'); - echo $OUTPUT->single_button(new \moodle_url($PAGE->url, - array('download' => 'CSV') + $displayoptions), - get_string('downloadtext'), - 'post', - ['class' => 'mt-1']); - echo \html_writer::end_tag('td'); - echo \html_writer::start_tag('td'); - echo \html_writer::end_tag('td'); - echo \html_writer::end_tag('tr').\html_writer::end_tag('table'); - } } } else { if ($candelete && !$download) { diff --git a/mod/scorm/report/userreport.php b/mod/scorm/report/userreport.php index ec91a483be5..922a845f879 100644 --- a/mod/scorm/report/userreport.php +++ b/mod/scorm/report/userreport.php @@ -28,14 +28,16 @@ require_once($CFG->dirroot.'/mod/scorm/locallib.php'); $id = required_param('id', PARAM_INT); // Course Module ID. $userid = required_param('user', PARAM_INT); // User ID. $attempt = optional_param('attempt', 1, PARAM_INT); // attempt number. +$mode = optional_param('mode', '', PARAM_ALPHA); // Scorm mode from which reached here. // Building the url to use for links.+ data details buildup. $url = new moodle_url('/mod/scorm/report/userreport.php', array('id' => $id, - 'user' => $userid, - 'attempt' => $attempt)); + 'user' => $userid, + 'attempt' => $attempt)); $tracksurl = new moodle_url('/mod/scorm/report/userreporttracks.php', array('id' => $id, - 'user' => $userid, - 'attempt' => $attempt)); + 'user' => $userid, + 'attempt' => $attempt, + 'mode' => $mode)); $cm = get_coursemodule_from_id('scorm', $id, 0, false, MUST_EXIST); $course = get_course($cm->course); $scorm = $DB->get_record('scorm', array('id' => $cm->instance), '*', MUST_EXIST); @@ -44,6 +46,7 @@ $user = $DB->get_record('user', array('id' => $userid), implode(',', \core_user\ $attemptids = scorm_get_all_attempts($scorm->id, $userid); $PAGE->set_url($url); +$PAGE->set_secondary_active_tab('scormreport'); // END of url setting + data buildup. // Checking login +logging +getting context. @@ -76,10 +79,15 @@ $PAGE->navbar->add($strreport, new moodle_url('/mod/scorm/report.php', array('id $PAGE->navbar->add(fullname($user). " - $strattempt $attempt"); echo $OUTPUT->header(); -echo $OUTPUT->heading(format_string($scorm->name)); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($scorm->name)); +} // End of Print the page header. $currenttab = 'scoes'; -require($CFG->dirroot . '/mod/scorm/report/userreporttabs.php'); + +$renderer = $PAGE->get_renderer('mod_scorm'); +$useractionreport = new \mod_scorm\output\userreportsactionbar($id, $userid, $attempt, 'learning', $mode); +echo $renderer->user_report_actionbar($useractionreport); // Printing user details. $output = $PAGE->get_renderer('mod_scorm'); diff --git a/mod/scorm/report/userreportinteractions.php b/mod/scorm/report/userreportinteractions.php index 501bf7e710d..d03a5a66749 100644 --- a/mod/scorm/report/userreportinteractions.php +++ b/mod/scorm/report/userreportinteractions.php @@ -31,6 +31,7 @@ $id = required_param('id', PARAM_INT); // Course Module ID. $userid = required_param('user', PARAM_INT); // User ID. $attempt = optional_param('attempt', 1, PARAM_INT); // attempt number. $download = optional_param('download', '', PARAM_ALPHA); +$mode = optional_param('mode', '', PARAM_ALPHA); // Scorm mode from which reached here. // Building the url to use for links.+ data details buildup. $url = new moodle_url('/mod/scorm/report/userreportinteractions.php', array('id' => $id, @@ -45,6 +46,7 @@ $user = $DB->get_record('user', array('id' => $userid), implode(',', \core_user\ $attemptids = scorm_get_all_attempts($scorm->id, $userid); $PAGE->set_url($url); +$PAGE->set_secondary_active_tab('scormreport'); // END of url setting + data buildup. // Checking login +logging +getting context. @@ -96,7 +98,10 @@ if (!$table->is_downloading($download, $exportfilename)) { echo $OUTPUT->heading(format_string($scorm->name)); // End of Print the page header. $currenttab = 'interactions'; - require($CFG->dirroot . '/mod/scorm/report/userreporttabs.php'); + + $renderer = $PAGE->get_renderer('mod_scorm'); + $useractionreport = new \mod_scorm\output\userreportsactionbar($id, $userid, $attempt, 'interact', $mode); + echo $renderer->user_report_actionbar($useractionreport); // Printing user details. $output = $PAGE->get_renderer('mod_scorm'); diff --git a/mod/scorm/report/userreporttabs.php b/mod/scorm/report/userreporttabs.php deleted file mode 100644 index b54957b9c1e..00000000000 --- a/mod/scorm/report/userreporttabs.php +++ /dev/null @@ -1,47 +0,0 @@ -. - -/** - * Sets up the tabs used by the scorm pages based on the users capabilities. - * - * @author Dan Marsden and others. - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package mod_scorm - */ - -if (empty($scorm)) { - print_error('cannotaccess', 'mod_scorm'); -} -if (!isset($currenttab)) { - $currenttab = ''; -} -$tabs = array(); -$row = array(); -$inactive = array(); -$activated = array(); - -$scoesurl = new moodle_url('/mod/scorm/report/userreport.php', array('id' => $id, - 'user' => $userid, - 'attempt' => $attempt)); - -$interactionssurl = new moodle_url('/mod/scorm/report/userreportinteractions.php', array('id' => $id, - 'user' => $userid, - 'attempt' => $attempt)); -$row[] = new tabobject('scoes', $scoesurl, get_string('scoes', 'scorm')); -$row[] = new tabobject('interactions', $interactionssurl, get_string('interactions', 'scorm')); - -$tabs[] = $row; -print_tabs($tabs, $currenttab, $inactive, $activated); diff --git a/mod/scorm/report/userreporttracks.php b/mod/scorm/report/userreporttracks.php index 3856fd423b5..5b115756491 100644 --- a/mod/scorm/report/userreporttracks.php +++ b/mod/scorm/report/userreporttracks.php @@ -29,6 +29,7 @@ require_once($CFG->libdir.'/tablelib.php'); $id = required_param('id', PARAM_INT); // Course Module ID. $userid = required_param('user', PARAM_INT); // User ID. $scoid = required_param('scoid', PARAM_INT); // SCO ID. +$mode = required_param('mode', PARAM_ALPHA); // Scorm mode. $attempt = optional_param('attempt', 1, PARAM_INT); // attempt number. $download = optional_param('download', '', PARAM_ALPHA); @@ -36,7 +37,8 @@ $download = optional_param('download', '', PARAM_ALPHA); $url = new moodle_url('/mod/scorm/report/userreporttracks.php', array('id' => $id, 'user' => $userid, 'attempt' => $attempt, - 'scoid' => $scoid)); + 'scoid' => $scoid, + 'mode' => $mode)); $cm = get_coursemodule_from_id('scorm', $id, 0, false, MUST_EXIST); $course = get_course($cm->course); $scorm = $DB->get_record('scorm', array('id' => $cm->instance), '*', MUST_EXIST); @@ -60,7 +62,7 @@ if (!groups_user_groups_visible($course, $userid, $cm)) { $event = \mod_scorm\event\tracks_viewed::create(array( 'context' => $contextmodule, 'relateduserid' => $userid, - 'other' => array('attemptid' => $attempt, 'instanceid' => $scorm->id, 'scoid' => $scoid) + 'other' => array('attemptid' => $attempt, 'instanceid' => $scorm->id, 'scoid' => $scoid, 'mode' => $mode) )); $event->add_record_snapshot('course_modules', $cm); $event->add_record_snapshot('scorm', $scorm); @@ -76,6 +78,7 @@ $PAGE->navbar->add($strreport, new moodle_url('/mod/scorm/report.php', array('id $PAGE->navbar->add("$strattempt $attempt - ".fullname($user), new moodle_url('/mod/scorm/report/userreport.php', array('id' => $id, 'user' => $userid, 'attempt' => $attempt))); $PAGE->navbar->add($selsco->title . ' - '. get_string('details', 'scorm')); +$PAGE->set_secondary_active_tab('scormreport'); if ($trackdata = scorm_get_tracks($selsco->id, $userid, $attempt)) { if ($trackdata->status == '') { @@ -95,9 +98,13 @@ $table = new flexible_table('mod_scorm-userreporttracks'); if (!$table->is_downloading($download, $exportfilename)) { echo $OUTPUT->header(); - echo $OUTPUT->heading(format_string($scorm->name)); + if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($scorm->name)); + } $currenttab = ''; - require($CFG->dirroot . '/mod/scorm/report/userreporttabs.php'); + $renderer = $PAGE->get_renderer('mod_scorm'); + $useractionreport = new \mod_scorm\output\userreportsactionbar($id, $userid, $attempt, 'attempt', $mode, $scoid); + echo $renderer->user_report_actionbar($useractionreport); echo $OUTPUT->box_start('generalbox boxaligncenter'); echo $OUTPUT->heading("$strattempt $attempt - ". fullname($user).': '. format_string($selsco->title). ' - '. get_string('details', 'scorm'), 3); diff --git a/mod/scorm/tabs.php b/mod/scorm/tabs.php deleted file mode 100644 index 8062949c580..00000000000 --- a/mod/scorm/tabs.php +++ /dev/null @@ -1,62 +0,0 @@ -. - -/** - * Sets up the tabs used by the scorm pages based on the users capabilities. - * - * @author Dan Marsden and others. - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package mod_scorm - */ - -if (empty($scorm)) { - print_error('cannotaccess', 'mod_scorm'); -} -if (!isset($currenttab)) { - $currenttab = ''; -} -if (!isset($cm)) { - $cm = get_coursemodule_from_instance('scorm', $scorm->id); -} - -$contextmodule = context_module::instance($cm->id); - -$tabs = array(); -$row = array(); -$inactive = array(); -$activated = array(); - -if (has_capability('mod/scorm:savetrack', $contextmodule)) { - $row[] = new tabobject('info', "$CFG->wwwroot/mod/scorm/view.php?id=$cm->id", get_string('info', 'scorm')); -} -if (has_capability('mod/scorm:viewreport', $contextmodule)) { - $row[] = new tabobject('reports', "$CFG->wwwroot/mod/scorm/report.php?id=$cm->id", get_string('reports', 'scorm')); -} - -if (!($currenttab == 'info' && count($row) == 1)) { - $tabs[] = $row; -} - -if ($currenttab == 'reports' && !empty($reportlist) && count($reportlist) > 1) { - $row2 = array(); - foreach ($reportlist as $rep) { - $row2[] = new tabobject('scorm_'.$rep, $CFG->wwwroot."/mod/scorm/report.php?id=$cm->id&mode=$rep", - get_string('pluginname', 'scormreport_'.$rep)); - } - $tabs[] = $row2; -} - -print_tabs($tabs, $currenttab, $inactive, $activated); diff --git a/mod/scorm/templates/report_actionbar.mustache b/mod/scorm/templates/report_actionbar.mustache new file mode 100644 index 00000000000..78dc0ef49fe --- /dev/null +++ b/mod/scorm/templates/report_actionbar.mustache @@ -0,0 +1,63 @@ +{{! + 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 mod_scorm/report_actionbar + Actions bar for the reports page UI. + Classes required for JS: + * none + Data attributes required for JS: + * none + Context variables required for this template: + * see mod/scorm/classes/output/actionbar.php + Example context (json): + { + "scormreports": { + "id": "url_select_test", + "options": [ + {"name": "Basic Report", "value": "/mod/scorm/report.php?id=69&mode=basic"}, + {"name": "Graph Report", "value": "/mod/scorm/report.php?id=69&mode=graphs"}, + {"name": "Interactions Report", "value": "/mod/scorm/report.php?id=69&mode=interactions"}, + {"name": "Objectives Report", "value": "/mod/scorm/report.php?id=69&mode=objectives"} + ] + }, + "candownload": true, + "downloadods": "http://localhost/moodle/mod/scorm/report.php?id=143&mode=basic&attemptsmode=0&sesskey=AmfcC7riSb&download=ODS", + "downloadexcel": "http://localhost/moodle/mod/scorm/report.php?id=143&mode=basic&attemptsmode=0&sesskey=AmfcC7riSb&download=Excel", + "downloadtext": "http://localhost/moodle/mod/scorm/report.php?id=143&mode=basic&attemptsmode=0&sesskey=AmfcC7riSb&download=CSV" + } +}} +
+
+
+ {{#scormreports}} + {{>core/url_select}} + {{/scormreports}} +
+ +
+
diff --git a/mod/scorm/templates/user_report_actionbar.mustache b/mod/scorm/templates/user_report_actionbar.mustache new file mode 100644 index 00000000000..5c81cb17841 --- /dev/null +++ b/mod/scorm/templates/user_report_actionbar.mustache @@ -0,0 +1,42 @@ +{{! + 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 mod_scorm/report_actionbar + Actions bar for the user reports page UI. + Classes required for JS: + * none + Data attributes required for JS: + * none + Context variables required for this template: + * see mod/scorm/classes/output/userreportsactionbar.php + Example context (json): + { + "userreport": { + "id": "url_select_test", + "options": [ + {"name": "Learning objects", "value": "/mod/scorm/report/userreport.php?id=70&user=13&attempt=1"}, + {"name": "Interactions", "value": "/mod/scorm/report/userreportinteractions.php?id=70&user=13&attempt=1"} + ] + }, + "backurl": "http://localhost/moodle/mod/scorm/report.php?id=70&mode=interactions" + } +}} +
+
+ {{#str}}back, core {{/str}} + {{#userreport}} + {{>core/url_select}} + {{/userreport}} +
+
diff --git a/mod/scorm/tests/behat/add_scorm.feature b/mod/scorm/tests/behat/add_scorm.feature index c60c1f1ea29..3cdbdfbb626 100644 --- a/mod/scorm/tests/behat/add_scorm.feature +++ b/mod/scorm/tests/behat/add_scorm.feature @@ -26,11 +26,11 @@ Feature: Add scorm activity And I upload "mod/scorm/tests/packages/singlesco_scorm12.zip" file to "Package file" filemanager And I click on "Save and display" "button" Then I should see "Awesome SCORM package" - And I should see "Normal" + And I should see "Enter" And I should see "Preview" And I log out And I am on the "Awesome SCORM package" "scorm activity" page logged in as student1 - And I should see "Normal" + And I should see "Enter" And I press "Enter" And I switch to "scorm_object" iframe And I should see "Not implemented yet" diff --git a/mod/scorm/tests/behat/completion_condition_require_status.feature b/mod/scorm/tests/behat/completion_condition_require_status.feature index 3341f22e23d..89f57465667 100644 --- a/mod/scorm/tests/behat/completion_condition_require_status.feature +++ b/mod/scorm/tests/behat/completion_condition_require_status.feature @@ -29,7 +29,7 @@ Feature: Scorm multi-sco completion | packagefilepath | mod/scorm/tests/packages/RuntimeMinimumCalls_SCORM12.zip | | completionstatusrequired | 4 | And I am on the "Basic Multi-sco SCORM package" "scorm activity" page logged in as student1 - And I should see "Normal" + And I should see "Enter" And I press "Enter" And I switch to "scorm_object" iframe And I should see "Play of the game" @@ -53,7 +53,7 @@ Feature: Scorm multi-sco completion | packagefilepath | mod/scorm/tests/packages/RuntimeMinimumCalls_SCORM12.zip | | completionstatusallscos | 1 | And I am on the "ADV Multi-sco SCORM package" "scorm activity" page logged in as student1 - And I should see "Normal" + And I should see "Enter" And I press "Enter" And I switch to "scorm_object" iframe And I should see "Play of the game" @@ -68,7 +68,7 @@ Feature: Scorm multi-sco completion Then "Student 1" user has not completed "ADV Multi-sco SCORM package" activity And I log out And I am on the "ADV Multi-sco SCORM package" "scorm activity" page logged in as student1 - And I should see "Normal" + And I should see "Enter" And I press "Enter" And I switch to "scorm_object" iframe And I should see "Par" diff --git a/mod/scorm/tests/behat/missing_org.feature b/mod/scorm/tests/behat/missing_org.feature index ae02ab0f0d0..85f7c7292d9 100644 --- a/mod/scorm/tests/behat/missing_org.feature +++ b/mod/scorm/tests/behat/missing_org.feature @@ -24,11 +24,11 @@ Feature: Check a SCORM package with missing Organisational structure. And I upload "mod/scorm/tests/packages/singlescobasic_missingorg.zip" file to "Package file" filemanager And I click on "Save and display" "button" Then I should see "MissingOrg SCORM package" - And I should see "Normal" + And I should see "Enter" And I should see "Preview" And I log out And I am on the "Missingorg" Activity page logged in as student1 - And I should see "Normal" + And I should see "Enter" And I press "Enter" And I switch to "scorm_object" iframe And I switch to "contentFrame" iframe diff --git a/mod/scorm/tests/behat/multisco_review_mode.feature b/mod/scorm/tests/behat/multisco_review_mode.feature index d2adda8f44b..9ac8ca9b880 100644 --- a/mod/scorm/tests/behat/multisco_review_mode.feature +++ b/mod/scorm/tests/behat/multisco_review_mode.feature @@ -33,7 +33,7 @@ Feature: Scorm multi-sco review mode. And I should see "Basic Multi-sco SCORM package" And I log out And I am on the "Basic Multi-sco SCORM package" "scorm activity" page logged in as student1 - And I should see "Normal" + And I should see "Enter" And I press "Enter" And I switch to "scorm_object" iframe And I should see "Play of the game" @@ -42,7 +42,7 @@ Feature: Scorm multi-sco review mode. And I wait until the page is ready And I should see "Basic Multi-sco SCORM package" And I am on the "Basic Multi-sco SCORM package" "scorm activity" page - And I should see "Normal" + And I should see "Enter" And I press "Enter" Then I should not see "Review mode" @@ -67,7 +67,7 @@ Feature: Scorm multi-sco review mode. And I should see "ADV Multi-sco SCORM package" And I log out And I am on the "ADV Multi-sco SCORM package" "scorm activity" page logged in as student1 - And I should see "Normal" + And I should see "Enter" And I press "Enter" And I switch to "scorm_object" iframe And I should see "Play of the game" @@ -161,7 +161,7 @@ Feature: Scorm multi-sco review mode. And I wait until the page is ready And I should see "ADV Multi-sco SCORM package" And I am on the "ADV Multi-sco SCORM package" "scorm activity" page - And I should see "Normal" + And I should see "Enter" And I press "Enter" Then I should see "Review mode" @@ -179,7 +179,7 @@ Feature: Scorm multi-sco review mode. And I should see "Basic Multi-sco SCORM package" And I log out And I am on the "Basic Multi-sco SCORM package" "scorm activity" page logged in as student1 - And I should see "Normal" + And I should see "Enter" And I press "Enter" And I switch to "scorm_object" iframe And I should see "Play of the game" @@ -188,7 +188,7 @@ Feature: Scorm multi-sco review mode. And I wait until the page is ready And I should see "Basic Multi-sco SCORM package" And I am on the "Basic Multi-sco SCORM package" "scorm activity" page - And I should see "Normal" + And I should see "Enter" And I should not see "Start a new attempt" And I press "Enter" Then I should not see "Review mode" @@ -209,7 +209,7 @@ Feature: Scorm multi-sco review mode. And I should see "Basic Multi-sco SCORM package" And I log out And I am on the "Basic Multi-sco SCORM package" "scorm activity" page logged in as student1 - And I should see "Normal" + And I should see "Enter" And I press "Enter" And I switch to "scorm_object" iframe And I should see "Play of the game" @@ -218,7 +218,7 @@ Feature: Scorm multi-sco review mode. And I wait until the page is ready And I should see "Basic Multi-sco SCORM package" And I am on the "Basic Multi-sco SCORM package" "scorm activity" page - And I should see "Normal" + And I should see "Enter" And I should not see "Start a new attempt" And I press "Enter" And I should not see "Review mode" @@ -264,7 +264,7 @@ Feature: Scorm multi-sco review mode. And I wait until the page is ready And I should see "Basic Multi-sco SCORM package" And I am on the "Basic Multi-sco SCORM package" "scorm activity" page - And I should see "Normal" + And I should see "Enter" And I press "Enter" Then I should not see "Review mode" And I switch to "scorm_object" iframe diff --git a/mod/scorm/tests/behat/save_progress_on_unload.feature b/mod/scorm/tests/behat/save_progress_on_unload.feature index 6b46caff08e..48b7b2acb52 100644 --- a/mod/scorm/tests/behat/save_progress_on_unload.feature +++ b/mod/scorm/tests/behat/save_progress_on_unload.feature @@ -32,7 +32,7 @@ Feature: Confirm progress gets saved on unload events When I log in as "student1" And I am on "Course 1" course homepage And I am on the "Runtime Basic Calls SCORM 2004 3rd Edition package" "scorm activity" page - Then I should see "Normal" + Then I should see "Enter" And I press "Enter" And I switch to "scorm_object" iframe And I press "Next" @@ -41,7 +41,7 @@ Feature: Confirm progress gets saved on unload events And I should see "Scoring" And I switch to the main frame And I am on the "Runtime Basic Calls SCORM 2004 3rd Edition package" "scorm activity" page - And I should see "Normal" + And I should see "Enter" And I click on "Enter" "button" confirming the dialogue And I switch to "scorm_object" iframe And I switch to "contentFrame" iframe diff --git a/mod/scorm/tests/behat/scorm_activity_completion.feature b/mod/scorm/tests/behat/scorm_activity_completion.feature index ae5ad04b331..059ae7330f2 100644 --- a/mod/scorm/tests/behat/scorm_activity_completion.feature +++ b/mod/scorm/tests/behat/scorm_activity_completion.feature @@ -72,8 +72,6 @@ Feature: View activity completion in the SCORM activity And I switch to "scorm_object" iframe And I click on "[id='question_com.scorm.golfsamples.interactions.fun_1_False']" "css_element" And I press "Submit Answers" - And I switch to the main frame - And I follow "Exit activity" When I am on the "Music history" "scorm activity" page Then the "View" completion condition of "Music history" is displayed as "done" # Conditions that are not possible to achieve (eg score below requirement but all attempts used) are marked as failed. diff --git a/mod/scorm/tests/events_test.php b/mod/scorm/tests/events_test.php index b7562792266..b5fc360fef5 100644 --- a/mod/scorm/tests/events_test.php +++ b/mod/scorm/tests/events_test.php @@ -271,7 +271,7 @@ class mod_scorm_event_testcase extends advanced_testcase { 'relateduserid' => 5, 'context' => context_module::instance($this->eventcm->id), 'courseid' => $this->eventcourse->id, - 'other' => array('attemptid' => 2, 'instanceid' => $this->eventscorm->id, 'scoid' => 3) + 'other' => array('attemptid' => 2, 'instanceid' => $this->eventscorm->id, 'scoid' => 3, 'mode' => 'interactions') )); // Trigger and capture the event. @@ -282,7 +282,8 @@ class mod_scorm_event_testcase extends advanced_testcase { // Check that the legacy log data is valid. $expected = array($this->eventcourse->id, 'scorm', 'userreporttracks', 'report/userreporttracks.php?id=' . - $this->eventcm->id . '&user=5&attempt=' . 2 . '&scoid=3', $this->eventscorm->id, $this->eventcm->id); + $this->eventcm->id . '&user=5&attempt=' . 2 . '&scoid=3' . '&mode=interactions', + $this->eventscorm->id, $this->eventcm->id); $this->assertEventLegacyLogData($expected, $event); $this->assertEventContextNotUsed($event); } diff --git a/mod/scorm/view.php b/mod/scorm/view.php index 1311cad387e..f83ccef99f4 100644 --- a/mod/scorm/view.php +++ b/mod/scorm/view.php @@ -137,7 +137,9 @@ if (empty($preventskip) && empty($launch) && (has_capability('mod/scorm:skipview $PAGE->set_title($pagetitle); $PAGE->set_heading($course->fullname); echo $OUTPUT->header(); -echo $OUTPUT->heading(format_string($scorm->name)); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($scorm->name)); +} // Display any activity information (eg completion requirements / dates). $cminfo = cm_info::create($cm); @@ -159,16 +161,13 @@ if (!empty($action) && confirm_sesskey() && has_capability('mod/scorm:deleteownr } } -$currenttab = 'info'; -require($CFG->dirroot . '/mod/scorm/tabs.php'); - // Print the main part of the page. $attemptstatus = ''; if (empty($launch) && ($scorm->displayattemptstatus == SCORM_DISPLAY_ATTEMPTSTATUS_ALL || $scorm->displayattemptstatus == SCORM_DISPLAY_ATTEMPTSTATUS_ENTRY)) { $attemptstatus = scorm_get_attempt_status($USER, $scorm, $cm); } -echo $OUTPUT->box(format_module_intro('scorm', $scorm, $cm->id).$attemptstatus, 'container', 'intro'); +echo $OUTPUT->box(format_module_intro('scorm', $scorm, $cm->id), 'container', 'intro'); // Check if SCORM available. No need to display warnings because activity dates are displayed at the top of the page. list($available, $warnings) = scorm_get_availability_status($scorm); @@ -176,6 +175,9 @@ list($available, $warnings) = scorm_get_availability_status($scorm); if ($available && empty($launch)) { scorm_print_launch($USER, $scorm, 'view.php?id='.$cm->id, $cm); } + +echo $OUTPUT->box($attemptstatus, 'container'); + if (!empty($forcejs)) { $message = $OUTPUT->box(get_string("forcejavascriptmessage", "scorm"), "container forcejavascriptmessage"); echo html_writer::tag('noscript', $message); diff --git a/mod/survey/classes/output/actionbar.php b/mod/survey/classes/output/actionbar.php new file mode 100644 index 00000000000..ca231c8c8bd --- /dev/null +++ b/mod/survey/classes/output/actionbar.php @@ -0,0 +1,128 @@ +. + +namespace mod_survey\output; + +use moodle_url; +use renderable; +use renderer_base; +use templatable; +use url_select; + +/** + * Output the rendered elements for the tertiary nav page action + * + * @package mod_survey + * @copyright 2021 Sujith Haridasan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class actionbar implements renderable, templatable { + /** + * The course id. + * + * @var int $id + */ + private $id; + + /** + * The action decides the url to navigate to. + * + * @var string $action + */ + private $action; + + /** + * Current url. + * + * @var moodle_url $currenturl + */ + private $currenturl; + + /** + * actionbar constructor. + * + * @param int $id The course module id. + * @param string $action The action string. + * @param moodle_url $currenturl The current URL. + */ + public function __construct(int $id, string $action, moodle_url $currenturl) { + $this->id = $id; + $this->action = $action; + $this->currenturl = $currenturl; + } + + /** + * Create select menu for the reports + * + * @return url_select url_select object. + */ + private function create_select_menu(): url_select { + $summarylink = new moodle_url('/mod/survey/report.php', ['id' => $this->id, 'action' => 'summary']); + $scaleslink = new moodle_url('/mod/survey/report.php', ['id' => $this->id, 'action' => 'scales']); + $questionslink = new moodle_url('/mod/survey/report.php', ['id' => $this->id, 'action' => 'questions']); + $participantslink = new moodle_url('/mod/survey/report.php', ['id' => $this->id, 'action' => 'students']); + + $menu = [ + $summarylink->out(false) => get_string('summary', 'survey'), + $scaleslink->out(false) => get_string('scales', 'survey'), + $questionslink->out(false) => get_string('questions', 'survey'), + $participantslink->out(false) => get_string('participants'), + ]; + + switch ($this->action) { + case 'summary': + $activeurl = $summarylink; + break; + case 'scales': + $activeurl = $scaleslink; + break; + case 'questions': + $activeurl = $questionslink; + break; + case 'students': + $activeurl = $participantslink; + break; + default: + $activeurl = $this->currenturl; + } + + return new url_select($menu, $activeurl->out(false), null, 'surveyresponseselect'); + } + + /** + * Data for the template. + * + * @param renderer_base $output renderer_base object. + * @return array data for the template + */ + public function export_for_template(renderer_base $output): array { + global $PAGE; + + $selecturl = $this->create_select_menu(); + $data = [ + 'urlselect' => $selecturl->export_for_template($output) + ]; + + if (has_capability('mod/survey:download', $PAGE->cm->context)) { + $downloadlink = (new moodle_url('/mod/survey/report.php', ['id' => $this->id, 'action' => 'download']))->out(false); + $data['download'] = [ + 'link' => $downloadlink, + 'text' => get_string('downloadresults', 'mod_survey'), + ]; + } + return $data; + } +} diff --git a/mod/survey/index.php b/mod/survey/index.php index 79ada054cae..a3e9f257fcc 100644 --- a/mod/survey/index.php +++ b/mod/survey/index.php @@ -31,7 +31,9 @@ $PAGE->set_title($strsurveys); $PAGE->set_heading($course->fullname); echo $OUTPUT->header(); - echo $OUTPUT->heading($strsurveys); + if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading($strsurveys); + } if (! $surveys = get_all_instances_in_course("survey", $course)) { notice(get_string('thereareno', 'moodle', $strsurveys), "../../course/view.php?id=$course->id"); diff --git a/mod/survey/lang/en/deprecated.txt b/mod/survey/lang/en/deprecated.txt new file mode 100644 index 00000000000..33e83dd7fa8 --- /dev/null +++ b/mod/survey/lang/en/deprecated.txt @@ -0,0 +1,2 @@ +clicktocontinue,mod_survey +viewsurveyresponses,mod_survey diff --git a/mod/survey/lang/en/survey.php b/mod/survey/lang/en/survey.php index 3d0321cc2da..6b4929db3e9 100644 --- a/mod/survey/lang/en/survey.php +++ b/mod/survey/lang/en/survey.php @@ -96,7 +96,6 @@ $string['ciq4'] = 'What action from anyone in the forums did you find most puzzl $string['ciq4short'] = 'Confusing moment'; $string['ciq5'] = 'What event surprised you most?'; $string['ciq5short'] = 'Suprising moment'; -$string['clicktocontinue'] = 'Click here to continue'; $string['clicktocontinuecheck'] = 'Click here to check and continue'; $string['collesaintro'] = 'The purpose of this survey is to help us understand how well the online delivery of this unit enabled you to learn. @@ -281,6 +280,9 @@ $string['surveytype_help'] = 'There are 3 available survey types: $string['surveytype_link'] = 'mod/survey/mod'; $string['thanksforanswers'] = 'Thanks for answering this survey, {$a}'; $string['time'] = 'Time'; -$string['viewsurveyresponses'] = 'View {$a} survey responses'; $string['notyetanswered'] = 'Not yet answered'; $string['allquestionrequireanswer'] = 'All questions are required and must be answered.'; + +// Deprecated since Moodle 4.0. +$string['clicktocontinue'] = 'Click here to continue'; +$string['viewsurveyresponses'] = 'View {$a} survey responses'; diff --git a/mod/survey/lib.php b/mod/survey/lib.php index 49319b5daa5..a6fe8ff4504 100644 --- a/mod/survey/lib.php +++ b/mod/survey/lib.php @@ -813,24 +813,8 @@ function survey_extend_settings_navigation($settings, $surveynode) { global $PAGE; if (has_capability('mod/survey:readresponses', $PAGE->cm->context)) { - $responsesnode = $surveynode->add(get_string("responsereports", "survey")); - - $url = new moodle_url('/mod/survey/report.php', array('id' => $PAGE->cm->id, 'action'=>'summary')); - $responsesnode->add(get_string("summary", "survey"), $url); - - $url = new moodle_url('/mod/survey/report.php', array('id' => $PAGE->cm->id, 'action'=>'scales')); - $responsesnode->add(get_string("scales", "survey"), $url); - - $url = new moodle_url('/mod/survey/report.php', array('id' => $PAGE->cm->id, 'action'=>'questions')); - $responsesnode->add(get_string("question", "survey"), $url); - - $url = new moodle_url('/mod/survey/report.php', array('id' => $PAGE->cm->id, 'action'=>'students')); - $responsesnode->add(get_string('participants'), $url); - - if (has_capability('mod/survey:download', $PAGE->cm->context)) { - $url = new moodle_url('/mod/survey/report.php', array('id' => $PAGE->cm->id, 'action'=>'download')); - $surveynode->add(get_string('downloadresults', 'survey'), $url); - } + $url = new moodle_url('/mod/survey/report.php', array('id' => $PAGE->cm->id, 'action' => 'summary')); + $surveynode->add(get_string("responsereports", "survey"), $url); } } diff --git a/mod/survey/renderer.php b/mod/survey/renderer.php new file mode 100644 index 00000000000..db873a08740 --- /dev/null +++ b/mod/survey/renderer.php @@ -0,0 +1,39 @@ +. + +/** + * Output the actionbar for this activity. + * + * @package mod_survey + * @copyright 2021 Sujith Haridasan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Renderer for the mod_survey tertiary nav + */ +class mod_survey_renderer extends plugin_renderer_base { + + /** + * Renders the action bar for the mod_survey report page. + * + * @param \mod_survey\output\actionbar $actionbar Data for the template + * @return bool|string rendered HTML string from the template. + */ + public function response_actionbar( \mod_survey\output\actionbar $actionbar) { + return $this->render_from_template('mod_survey/response_action_bar', $actionbar->export_for_template($this)); + } +} diff --git a/mod/survey/report.php b/mod/survey/report.php index a3ad94541c7..c289363e523 100644 --- a/mod/survey/report.php +++ b/mod/survey/report.php @@ -92,33 +92,19 @@ $strseemoredetail = get_string("seemoredetail", "survey"); $strnotes = get_string("notes", "survey"); - switch ($action) { - case 'download': - $PAGE->navbar->add(get_string('downloadresults', 'survey')); - break; - case 'summary': - case 'scales': - case 'questions': - $PAGE->navbar->add($strreport); - $PAGE->navbar->add(${'str'.$action}); - break; - case 'students': - $PAGE->navbar->add($strreport); - $PAGE->navbar->add(get_string('participants')); - break; - case '': - $PAGE->navbar->add($strreport); - $PAGE->navbar->add($strsummary); - break; - default: - $PAGE->navbar->add($strreport); - break; - } - $PAGE->set_title("$course->shortname: ".format_string($survey->name)); $PAGE->set_heading($course->fullname); + + // Activate the secondary nav tab. + navigation_node::override_active_url(new moodle_url('/mod/survey/report.php', ['id' => $id, 'action' => 'summary'])); + + $actionbar = new \mod_survey\output\actionbar($id, $action, $url); echo $OUTPUT->header(); +if (!$PAGE->has_secondary_navigation()) { echo $OUTPUT->heading(format_string($survey->name)); +} + $renderer = $PAGE->get_renderer('mod_survey'); + echo $renderer->response_actionbar($actionbar); /// Check to see if groups are being used in this survey if ($groupmode = groups_get_activity_groupmode($cm)) { // Groups are being used @@ -152,30 +138,6 @@ $groupingid = $cm->groupingid; - echo $OUTPUT->box_start("generalbox boxaligncenter"); - if ($showscales) { - echo "$strsummary"; - echo "    $strscales"; - echo "    $strquestions"; - echo "    ".get_string('participants').""; - if (has_capability('mod/survey:download', $context)) { - echo "    $strdownload"; - } - if (empty($action)) { - $action = "summary"; - } - } else { - echo "$strquestions"; - echo "    ".get_string('participants').""; - if (has_capability('mod/survey:download', $context)) { - echo "    $strdownload"; - } - if (empty($action)) { - $action = "questions"; - } - } - echo $OUTPUT->box_end(); - echo $OUTPUT->spacer(array('height'=>30, 'width'=>30, 'br'=>true)); // should be done with CSS instead @@ -519,4 +481,3 @@ } echo $OUTPUT->footer(); - diff --git a/mod/survey/templates/response_action_bar.mustache b/mod/survey/templates/response_action_bar.mustache new file mode 100644 index 00000000000..fe8dccf9f8f --- /dev/null +++ b/mod/survey/templates/response_action_bar.mustache @@ -0,0 +1,72 @@ +{{! + 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 mod_survey/response_action_bar + Actions bar for the reports page UI. + Classes required for JS: + * none + Context variables required for this template: + * see mod/survey/classes/output/actionbar.php + Example context (json): + { + "download": { + "link": "http://foobar", + "text": "foobar site", + "urlselect": { + "id": "url_select123", + "sesskey": "sesskey", + "action": "http://localhost/moodle/course/jumpto.php", + "disabled": false, + "formid": "surveyresponseselect", + "classes": "urlselect", + "options": [ + { + "name": "Summary", + "value": "/mod/survey/report.php?id=12&action=summary", + "selected": true + }, + { + "name": "Scales", + "value": "/mod/survey/report.php?id=12&action=scales", + "selected": false + }, + { + "name": "Questions", + "value": "/mod/survey/report.php?id=12&action=questions", + "selected": false + }, + { + "name": "Participants", + "value": "/mod/survey/report.php?id=12&action=students", + "selected": false + } + ] + } + } + } +}} +
+
+
+ {{#urlselect}} + {{>core/url_select}} + {{/urlselect}} +
+ {{#download}} +
+ {{text}} +
+ {{/download}} +
+
diff --git a/mod/survey/tests/behat/survey_completion.feature b/mod/survey/tests/behat/survey_completion.feature index 96f6135fe9a..3bbbe39f4fc 100644 --- a/mod/survey/tests/behat/survey_completion.feature +++ b/mod/survey/tests/behat/survey_completion.feature @@ -62,7 +62,7 @@ Feature: A teacher can use activity completion to track a student progress And the "Submit answers" completion condition of "Test survey name" is displayed as "todo" And I follow "Test survey name" And the "Submit answers" completion condition of "Test survey name" is displayed as "todo" - And I press "Click here to continue" + And I press "Submit" And I am on "Course 1" course homepage And the "Submit answers" completion condition of "Test survey name" is displayed as "done" And I follow "Test survey name" diff --git a/mod/survey/version.php b/mod/survey/version.php index 65a2bda40b0..5dbb31e62b0 100644 --- a/mod/survey/version.php +++ b/mod/survey/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2021052500; // The current module version (Date: YYYYMMDDXX). +$plugin->version = 2021052501; // The current module version (Date: YYYYMMDDXX). $plugin->requires = 2021052500; // Requires this Moodle version. $plugin->component = 'mod_survey'; // Full name of the plugin (used for diagnostics) $plugin->cron = 0; diff --git a/mod/survey/view.php b/mod/survey/view.php index 837b1ea96f4..2ddfe863ca0 100644 --- a/mod/survey/view.php +++ b/mod/survey/view.php @@ -71,7 +71,9 @@ $strsurvey = get_string("modulename", "survey"); $PAGE->set_title($survey->name); $PAGE->set_heading($course->fullname); echo $OUTPUT->header(); -echo $OUTPUT->heading(format_string($survey->name)); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($survey->name)); +} // Render the activity information. $completiondetails = \core_completion\cm_completion_details::get_instance($cm, $USER->id); @@ -90,11 +92,7 @@ if (has_capability('mod/survey:readresponses', $context) or ($groupmode == VISIB $currentgroup = 0; } -if (has_capability('mod/survey:readresponses', $context)) { - $numusers = survey_count_responses($survey->id, $currentgroup, $groupingid); - echo ""; -} else if (!$cm->visible) { +if (!$cm->visible) { notice(get_string("activityiscurrentlyhidden")); } @@ -103,9 +101,7 @@ if (!is_enrolled($context)) { } if ($surveyalreadydone) { - $numusers = survey_count_responses($survey->id, $currentgroup, $groupingid); - if ($showscales) { // Ensure that graph.php will allow the user to see the graph. if (has_capability('mod/survey:readresponses', $context) || !$groupmode || groups_is_member($currentgroup)) { @@ -183,7 +179,7 @@ if (!is_enrolled($context)) { $PAGE->requires->js_call_amd('mod_survey/validation', 'ensureRadiosChosen', array('surveyform')); echo '
'; -echo ''; +echo ''; echo '
'; echo ""; diff --git a/mod/url/index.php b/mod/url/index.php index 8062ebbb194..869eed21a3e 100644 --- a/mod/url/index.php +++ b/mod/url/index.php @@ -50,7 +50,9 @@ $PAGE->set_title($course->shortname.': '.$strurls); $PAGE->set_heading($course->fullname); $PAGE->navbar->add($strurls); echo $OUTPUT->header(); -echo $OUTPUT->heading($strurls); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading($strurls); +} if (!$urls = get_all_instances_in_course('url', $course)) { notice(get_string('thereareno', 'moodle', $strurls), "$CFG->wwwroot/course/view.php?id=$course->id"); diff --git a/mod/url/locallib.php b/mod/url/locallib.php index c7c455e5baf..7aca2eb4c59 100644 --- a/mod/url/locallib.php +++ b/mod/url/locallib.php @@ -266,10 +266,13 @@ EOF; * @return does not return */ function url_print_workaround($url, $cm, $course) { - global $OUTPUT, $USER; + global $OUTPUT, $PAGE, $USER; url_print_header($url, $cm, $course); - url_print_heading($url, $cm, $course, true); + + if (!$PAGE->has_secondary_navigation()) { + url_print_heading($url, $cm, $course, true); + } // Display any activity information (eg completion requirements / dates). $cminfo = cm_info::create($cm); @@ -344,7 +347,9 @@ function url_display_embed($url, $cm, $course) { } url_print_header($url, $cm, $course); - url_print_heading($url, $cm, $course); + if (!$PAGE->has_secondary_navigation()) { + url_print_heading($url, $cm, $course); + } // Display any activity information (eg completion requirements / dates). $cminfo = cm_info::create($cm); diff --git a/mod/url/view.php b/mod/url/view.php index cc5c12fb94f..1068a6e5545 100644 --- a/mod/url/view.php +++ b/mod/url/view.php @@ -58,7 +58,9 @@ $PAGE->set_url('/mod/url/view.php', array('id' => $cm->id)); $exturl = trim($url->externalurl); if (empty($exturl) or $exturl === 'http://') { url_print_header($url, $cm, $course); - url_print_heading($url, $cm, $course); + if (!$PAGE->has_secondary_navigation()) { + url_print_heading($url, $cm, $course); + } url_print_intro($url, $cm, $course); notice(get_string('invalidstoredurl', 'url'), new moodle_url('/course/view.php', array('id'=>$cm->course))); die; diff --git a/mod/workshop/allocation.php b/mod/workshop/allocation.php index ebc5abaff02..b6e727bc6a8 100644 --- a/mod/workshop/allocation.php +++ b/mod/workshop/allocation.php @@ -38,7 +38,8 @@ $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EX $workshop = $DB->get_record('workshop', array('id' => $cm->instance), '*', MUST_EXIST); $workshop = new workshop($workshop, $cm, $course); -$PAGE->set_url($workshop->allocation_url($method)); +$url = $workshop->allocation_url($method); +$PAGE->set_url($url); require_login($course, false, $cm); $context = $PAGE->context; @@ -54,25 +55,15 @@ $initresult = $allocator->init(); // // Output starts here // +$actionbar = new \mod_workshop\output\actionbar($url, $workshop); + $output = $PAGE->get_renderer('mod_workshop'); echo $output->header(); -echo $OUTPUT->heading(format_string($workshop->name)); - -$allocators = workshop::installed_allocators(); -if (!empty($allocators)) { - $tabs = array(); - $row = array(); - $inactive = array(); - $activated = array(); - foreach ($allocators as $methodid => $methodname) { - $row[] = new tabobject($methodid, $workshop->allocation_url($methodid)->out(), $methodname); - if ($methodid == $method) { - $currenttab = $methodid; - } - } +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($workshop->name)); } -$tabs[] = $row; -print_tabs($tabs, $currenttab, $inactive, $activated); + +echo $actionbar->get_allocation_menu(); if (is_null($initresult->get_status()) or $initresult->get_status() == workshop_allocation_result::STATUS_VOID) { echo $output->container_start('allocator-ui'); diff --git a/mod/workshop/allocation/random/settings_form.php b/mod/workshop/allocation/random/settings_form.php index 50fa1a2ec24..81aefed2b7d 100644 --- a/mod/workshop/allocation/random/settings_form.php +++ b/mod/workshop/allocation/random/settings_form.php @@ -96,7 +96,7 @@ class workshop_random_allocator_form extends moodleform { $mform->addElement('checkbox', 'addselfassessment', get_string('addselfassessment', 'workshopallocation_random')); } - $this->add_action_buttons(); + $this->add_action_buttons(false); } /** diff --git a/mod/workshop/assessment.php b/mod/workshop/assessment.php index 2bf0639f6b9..dbe56ed4d7b 100644 --- a/mod/workshop/assessment.php +++ b/mod/workshop/assessment.php @@ -54,6 +54,7 @@ $PAGE->set_url($workshop->assess_url($assessment->id)); $PAGE->set_title($workshop->name); $PAGE->set_heading($course->fullname); $PAGE->navbar->add(get_string('assessingsubmission', 'workshop')); +$PAGE->set_secondary_active_tab('modulepage'); $cansetassessmentweight = has_capability('mod/workshop:allocate', $workshop->context); $canoverridegrades = has_capability('mod/workshop:overridegrades', $workshop->context); @@ -74,7 +75,9 @@ if ($assessmenteditable) { list($assessed, $notice) = $workshop->check_examples_assessed_before_assessment($assessment->reviewerid); if (!$assessed) { echo $output->header(); - echo $output->heading(format_string($workshop->name)); + if (!$PAGE->has_secondary_navigation()) { + echo $output->heading(format_string($workshop->name)); + } notice(get_string($notice, 'workshop'), new moodle_url('/mod/workshop/view.php', array('id' => $cm->id))); echo $output->footer(); exit; @@ -155,7 +158,9 @@ if ($canoverridegrades or $cansetassessmentweight) { // output starts here $output = $PAGE->get_renderer('mod_workshop'); // workshop renderer echo $output->header(); -echo $output->heading(format_string($workshop->name)); +if (!$PAGE->has_secondary_navigation()) { + echo $output->heading(format_string($workshop->name)); +} echo $output->heading(get_string('assessedsubmission', 'workshop'), 3); $submission = $workshop->get_submission_by_id($submission->id); // reload so can be passed to the renderer diff --git a/mod/workshop/classes/output/actionbar.php b/mod/workshop/classes/output/actionbar.php new file mode 100644 index 00000000000..af3738f76f5 --- /dev/null +++ b/mod/workshop/classes/output/actionbar.php @@ -0,0 +1,82 @@ +. + +namespace mod_workshop\output; + +use moodle_url; +use url_select; + +/** + * Output the rendered elements for the tertiary nav for page action. + * + * @package mod_workshop + * @copyright 2021 Sujith Haridasan + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class actionbar { + /** + * The current url. + * + * @var moodle_url $currenturl + */ + private $currenturl; + + /** + * The workshop object. + * @var \workshop $workshop + */ + private $workshop; + + /** + * actionbar constructor. + * + * @param moodle_url $currenturl The current URL. + * @param \workshop $workshop The workshop object. + */ + public function __construct(moodle_url $currenturl, \workshop $workshop) { + $this->currenturl = $currenturl; + $this->workshop = $workshop; + } + + /** + * Creates the select menu for allocation page. + * + * @return url_select url_select object. + */ + private function create_select_menu(): url_select { + $allocators = \workshop::installed_allocators(); + $menu = []; + + foreach (array_keys($allocators) as $methodid) { + $selectorname = get_string('pluginname', 'workshopallocation_' . $methodid); + $menu[$this->workshop->allocation_url($methodid)->out(false)] = $selectorname; + } + + return new url_select($menu, $this->currenturl->out(false), null, 'allocationsetting'); + } + + /** + * Rendered HTML for the allocation action. + * + * @return string rendered HTML string + */ + public function get_allocation_menu(): string { + global $OUTPUT; + + $urlselect = $this->create_select_menu(); + return $OUTPUT->render($urlselect); + } +} diff --git a/mod/workshop/editform.php b/mod/workshop/editform.php index 6e77865c237..b799b9adb68 100644 --- a/mod/workshop/editform.php +++ b/mod/workshop/editform.php @@ -73,7 +73,9 @@ if ($mform->is_cancelled()) { // Output starts here echo $OUTPUT->header(); -echo $OUTPUT->heading(format_string($workshop->name)); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($workshop->name)); +} echo $OUTPUT->heading(get_string('pluginname', 'workshopform_' . $workshop->strategy), 3); $mform->display(); diff --git a/mod/workshop/editformpreview.php b/mod/workshop/editformpreview.php index 4f2941d6111..77c50ed3a0b 100644 --- a/mod/workshop/editformpreview.php +++ b/mod/workshop/editformpreview.php @@ -43,6 +43,7 @@ $PAGE->set_title($workshop->name); $PAGE->set_heading($course->fullname); $PAGE->navbar->add(get_string('editingassessmentform', 'workshop'), $workshop->editform_url(), navigation_node::TYPE_CUSTOM); $PAGE->navbar->add(get_string('previewassessmentform', 'workshop')); +$PAGE->set_secondary_active_tab('workshopassessement'); $currenttab = 'editform'; // load the grading strategy logic @@ -53,7 +54,9 @@ $mform = $strategy->get_assessment_form($workshop->editform_url(), 'preview'); // output starts here echo $OUTPUT->header(); -echo $OUTPUT->heading(format_string($workshop->name)); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($workshop->name)); +} echo $OUTPUT->heading(get_string('assessmentform', 'workshop'), 3); $mform->display(); echo $OUTPUT->footer(); diff --git a/mod/workshop/exassessment.php b/mod/workshop/exassessment.php index 5d47e45e3d9..a890ca6901f 100644 --- a/mod/workshop/exassessment.php +++ b/mod/workshop/exassessment.php @@ -43,6 +43,7 @@ $PAGE->set_url($workshop->exassess_url($assessment->id)); $PAGE->set_title($workshop->name); $PAGE->set_heading($course->fullname); $PAGE->navbar->add(get_string('assessingexample', 'workshop')); +$PAGE->set_secondary_active_tab('modulepage'); $currenttab = 'assessment'; $canmanage = has_capability('mod/workshop:manageexamples', $workshop->context); @@ -133,7 +134,9 @@ if ($mform->is_cancelled()) { // output starts here $output = $PAGE->get_renderer('mod_workshop'); // workshop renderer echo $output->header(); -echo $output->heading(format_string($workshop->name)); +if (!$PAGE->has_secondary_navigation()) { + echo $output->heading(format_string($workshop->name)); +} echo $output->heading(get_string('assessedexample', 'workshop'), 3); $example = $workshop->get_example_by_id($example->id); // reload so can be passed to the renderer diff --git a/mod/workshop/excompare.php b/mod/workshop/excompare.php index 481f7cffe09..73545af1e59 100644 --- a/mod/workshop/excompare.php +++ b/mod/workshop/excompare.php @@ -72,7 +72,11 @@ $PAGE->navbar->add(get_string('examplecomparing', 'workshop')); // Output starts here $output = $PAGE->get_renderer('mod_workshop'); echo $output->header(); -echo $output->heading(format_string($workshop->name)); +// Output the back button. +echo $output->single_button($workshop->view_url(), get_string('back'), 'get', ['class' => 'mb-3']); +if (!$PAGE->has_secondary_navigation()) { + echo $output->heading(format_string($workshop->name)); +} echo $output->heading(get_string('assessedexample', 'workshop'), 3); echo $output->render($workshop->prepare_example_submission($example)); diff --git a/mod/workshop/exsubmission.php b/mod/workshop/exsubmission.php index f8f3be05864..dcac64dd4b3 100644 --- a/mod/workshop/exsubmission.php +++ b/mod/workshop/exsubmission.php @@ -47,6 +47,7 @@ $workshop = new workshop($workshop, $cm, $course); $PAGE->set_url($workshop->exsubmission_url($id), array('edit' => $edit)); $PAGE->set_title($workshop->name); $PAGE->set_heading($course->fullname); +$PAGE->set_secondary_active_tab('modulepage'); if ($edit) { $PAGE->navbar->add(get_string('exampleediting', 'workshop')); } else { @@ -173,7 +174,9 @@ if ($edit and $canmanage) { // Output starts here echo $output->header(); -echo $output->heading(format_string($workshop->name), 2); +if (!$PAGE->has_secondary_navigation()) { + echo $output->heading(format_string($workshop->name), 2); +} // show instructions for submitting as they may contain some list of questions and we need to know them // while reading the submitted answer diff --git a/mod/workshop/lib.php b/mod/workshop/lib.php index 4bfa6ea2d77..d2ae8829711 100644 --- a/mod/workshop/lib.php +++ b/mod/workshop/lib.php @@ -1633,7 +1633,8 @@ function workshop_extend_settings_navigation(settings_navigation $settingsnav, n if (has_capability('mod/workshop:editdimensions', $PAGE->cm->context)) { $url = new moodle_url('/mod/workshop/editform.php', array('cmid' => $PAGE->cm->id)); - $workshopnode->add(get_string('assessmentform', 'workshop'), $url, settings_navigation::TYPE_SETTING); + $workshopnode->add(get_string('assessmentform', 'workshop'), $url, + settings_navigation::TYPE_SETTING, null, 'workshopassessement'); } if (has_capability('mod/workshop:allocate', $PAGE->cm->context)) { $url = new moodle_url('/mod/workshop/allocation.php', array('cmid' => $PAGE->cm->id)); diff --git a/mod/workshop/submission.php b/mod/workshop/submission.php index a9d2072ea3f..a179a01cc31 100644 --- a/mod/workshop/submission.php +++ b/mod/workshop/submission.php @@ -45,6 +45,8 @@ $workshop = new workshop($workshoprecord, $cm, $course); $PAGE->set_url($workshop->submission_url(), array('cmid' => $cmid, 'id' => $id)); +$PAGE->set_secondary_active_tab("modulepage"); + if ($edit) { $PAGE->url->param('edit', $edit); } @@ -185,7 +187,9 @@ if ($edit) { // Output starts here $output = $PAGE->get_renderer('mod_workshop'); echo $output->header(); -echo $output->heading(format_string($workshop->name), 2); +if (!$PAGE->has_secondary_navigation()) { + echo $output->heading(format_string($workshop->name), 2); +} echo $output->heading(get_string('mysubmission', 'workshop'), 3); // show instructions for submitting as thay may contain some list of questions and we need to know them diff --git a/mod/workshop/switchphase.php b/mod/workshop/switchphase.php index 3e1b7062a66..d30d46cf572 100644 --- a/mod/workshop/switchphase.php +++ b/mod/workshop/switchphase.php @@ -54,11 +54,19 @@ $PAGE->set_title($workshop->name); $PAGE->set_heading($course->fullname); $PAGE->navbar->add(get_string('switchingphase', 'workshop')); +$PAGE->set_secondary_active_tab("modulepage"); + // // Output starts here // echo $OUTPUT->header(); -echo $OUTPUT->heading(format_string($workshop->name)); +if (!$PAGE->has_secondary_navigation()) { + echo $OUTPUT->heading(format_string($workshop->name)); +} + +$continuebtn = new single_button( + new moodle_url($PAGE->url, array('confirm' => 1)), get_string('continue'), 'post', true); +$continuebtn->class .= ' mr-3'; echo $OUTPUT->confirm(get_string('switchphase' . $phase . 'info', 'workshop'), - new moodle_url($PAGE->url, array('confirm' => 1)), $workshop->view_url()); + $continuebtn, $workshop->view_url()); echo $OUTPUT->footer(); diff --git a/mod/workshop/tests/behat/behat_mod_workshop.php b/mod/workshop/tests/behat/behat_mod_workshop.php index 881cac9d012..60209b9329e 100644 --- a/mod/workshop/tests/behat/behat_mod_workshop.php +++ b/mod/workshop/tests/behat/behat_mod_workshop.php @@ -71,7 +71,7 @@ class behat_mod_workshop extends behat_base { public function i_add_a_submission_in_workshop_as($workshopname, $table) { $workshopname = $this->escape($workshopname); $savechanges = $this->escape(get_string('savechanges')); - $xpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' ownsubmission ')]/descendant::*[@type='submit']"; + $xpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' singlebutton ')]/descendant::*[@type='submit']"; $this->execute("behat_navigation::i_am_on_page_instance", [$workshopname, 'workshop activity']); diff --git a/mod/workshop/version.php b/mod/workshop/version.php index 8c9266949e8..61011514eb3 100644 --- a/mod/workshop/version.php +++ b/mod/workshop/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2021052501; // The current module version (YYYYMMDDXX). +$plugin->version = 2021052502; // The current module version (YYYYMMDDXX). $plugin->requires = 2021052500; // Requires this Moodle version. $plugin->component = 'mod_workshop'; diff --git a/mod/workshop/view.php b/mod/workshop/view.php index 7465481641f..638581b0e85 100644 --- a/mod/workshop/view.php +++ b/mod/workshop/view.php @@ -102,7 +102,9 @@ $output = $PAGE->get_renderer('mod_workshop'); /// Output starts here echo $output->header(); -echo $output->heading_with_help(format_string($workshop->name), 'userplan', 'workshop'); +if (!$PAGE->has_secondary_navigation()) { + echo $output->heading_with_help(format_string($workshop->name), 'userplan', 'workshop'); +} // Display any activity information (eg completion requirements / dates). $cminfo = cm_info::create($cm); @@ -110,6 +112,54 @@ $completiondetails = \core_completion\cm_completion_details::get_instance($cminf $activitydates = \core\activity_dates::get_dates_for_module($cminfo, $USER->id); echo $output->activity_information($cminfo, $completiondetails, $activitydates); +// Output action buttons here. +switch ($workshop->phase) { + case workshop::PHASE_SUBMISSION: + // Does the user have to assess examples before submitting their own work? + $examplesmust = ($workshop->useexamples and $workshop->examplesmode == workshop::EXAMPLES_BEFORE_SUBMISSION); + + // Is the assessment of example submissions considered finished? + $examplesdone = has_capability('mod/workshop:manageexamples', $workshop->context); + + if ($workshop->assessing_examples_allowed() && has_capability('mod/workshop:submit', $workshop->context) && + !has_capability('mod/workshop:manageexamples', $workshop->context)) { + $examples = $userplan->get_examples(); + $left = 0; + // Make sure the current user has all examples allocated. + foreach ($examples as $exampleid => $example) { + if (is_null($example->grade)) { + $left++; + break; + } + } + if ($left > 0 and $workshop->examplesmode != workshop::EXAMPLES_VOLUNTARY) { + $examplesdone = false; + } else { + $examplesdone = true; + } + } + + if (has_capability('mod/workshop:submit', $PAGE->context) and (!$examplesmust or $examplesdone)) { + if (!$workshop->get_submission_by_author($USER->id)) { + $btnurl = new moodle_url($workshop->submission_url(), ['edit' => 'on']); + $btntxt = get_string('createsubmission', 'workshop'); + echo $output->single_button($btnurl, $btntxt, 'get', ['primary' => true]); + } + } + break; + + case workshop::PHASE_ASSESSMENT: + if (has_capability('mod/workshop:submit', $PAGE->context)) { + if (!$workshop->get_submission_by_author($USER->id)) { + if ($workshop->creating_submission_allowed($USER->id)) { + $btnurl = new moodle_url($workshop->submission_url(), array('edit' => 'on')); + $btntxt = get_string('createsubmission', 'workshop'); + echo $output->single_button($btnurl, $btntxt, 'get', ['primary' => true]); + } + } + } +} + echo $output->heading(format_string($currentphasetitle), 3, null, 'mod_workshop-userplanheading'); echo $output->render($userplan); @@ -153,31 +203,11 @@ case workshop::PHASE_SUBMISSION: print_collapsible_region_end(); } - // does the user have to assess examples before submitting their own work? - $examplesmust = ($workshop->useexamples and $workshop->examplesmode == workshop::EXAMPLES_BEFORE_SUBMISSION); - - // is the assessment of example submissions considered finished? - $examplesdone = has_capability('mod/workshop:manageexamples', $workshop->context); if ($workshop->assessing_examples_allowed() and has_capability('mod/workshop:submit', $workshop->context) and ! has_capability('mod/workshop:manageexamples', $workshop->context)) { $examples = $userplan->get_examples(); $total = count($examples); - $left = 0; - // make sure the current user has all examples allocated - foreach ($examples as $exampleid => $example) { - if (is_null($example->assessmentid)) { - $examples[$exampleid]->assessmentid = $workshop->add_allocation($example, $USER->id, 0); - } - if (is_null($example->grade)) { - $left++; - } - } - if ($left > 0 and $workshop->examplesmode != workshop::EXAMPLES_VOLUNTARY) { - $examplesdone = false; - } else { - $examplesdone = true; - } print_collapsible_region_start('', 'workshop-viewlet-examples', get_string('exampleassessments', 'workshop'), 'workshop-viewlet-examples-collapsed', $examplesdone); echo $output->box_start('generalbox exampleassessments'); @@ -199,20 +229,10 @@ case workshop::PHASE_SUBMISSION: echo $output->box_start('generalbox ownsubmission'); if ($submission = $workshop->get_submission_by_author($USER->id)) { echo $output->render($workshop->prepare_submission_summary($submission, true)); - if ($workshop->modifying_submission_allowed($USER->id)) { - $btnurl = new moodle_url($workshop->submission_url(), array('edit' => 'on')); - $btntxt = get_string('editsubmission', 'workshop'); - } } else { echo $output->container(get_string('noyoursubmission', 'workshop')); - if ($workshop->creating_submission_allowed($USER->id)) { - $btnurl = new moodle_url($workshop->submission_url(), array('edit' => 'on')); - $btntxt = get_string('createsubmission', 'workshop'); - } - } - if (!empty($btnurl)) { - echo $output->single_button($btnurl, $btntxt, 'get'); } + echo $output->box_end(); print_collapsible_region_end(); } @@ -290,14 +310,8 @@ case workshop::PHASE_ASSESSMENT: echo $output->box_start('generalbox ownsubmission'); echo $output->container(get_string('noyoursubmission', 'workshop')); $ownsubmissionexists = false; - if ($workshop->creating_submission_allowed($USER->id)) { - $btnurl = new moodle_url($workshop->submission_url(), array('edit' => 'on')); - $btntxt = get_string('createsubmission', 'workshop'); - } - } - if (!empty($btnurl)) { - echo $output->single_button($btnurl, $btntxt, 'get'); } + echo $output->box_end(); print_collapsible_region_end(); } diff --git a/question/bank/exportquestions/export.php b/question/bank/exportquestions/export.php index d12b0479e4e..7bc3ae2b7f7 100644 --- a/question/bank/exportquestions/export.php +++ b/question/bank/exportquestions/export.php @@ -46,11 +46,14 @@ $category = $DB->get_record('question_categories', ["id" => $catid, 'contextid' $PAGE->set_url($thispageurl); $PAGE->set_title($strexportquestions); $PAGE->set_heading($COURSE->fullname); -echo $OUTPUT->header(); // Print horizontal nav if needed. $renderer = $PAGE->get_renderer('core_question', 'bank'); -echo $renderer->extra_horizontal_navigation(); + +echo $OUTPUT->header(); + +$qbankaction = new \core_question\output\qbank_actionbar($thispageurl); +echo $renderer->qbank_action_menu($qbankaction); $exportform = new export_form($thispageurl, ['contexts' => $contexts->having_one_edit_tab_cap('export'), 'defaultcategory' => $pagevars['cat']]); diff --git a/question/bank/importquestions/import.php b/question/bank/importquestions/import.php index 91eab596d0e..62e3c8a1865 100644 --- a/question/bank/importquestions/import.php +++ b/question/bank/importquestions/import.php @@ -73,11 +73,14 @@ if ($importform->is_cancelled()) { // Page header. $PAGE->set_title($txt->importquestions); $PAGE->set_heading($COURSE->fullname); -echo $OUTPUT->header(); // Print horizontal nav if needed. $renderer = $PAGE->get_renderer('core_question', 'bank'); -echo $renderer->extra_horizontal_navigation(); + +echo $OUTPUT->header(); + +$qbankaction = new \core_question\output\qbank_actionbar($thispageurl); +echo $renderer->qbank_action_menu($qbankaction); // File upload form submitted. if ($form = $importform->get_data()) { diff --git a/question/bank/managecategories/category.php b/question/bank/managecategories/category.php index c558ee1686b..96b55591d6b 100644 --- a/question/bank/managecategories/category.php +++ b/question/bank/managecategories/category.php @@ -147,11 +147,14 @@ if ($param->edit) { $PAGE->set_title(get_string('editcategories', 'question')); $PAGE->set_heading($COURSE->fullname); -echo $OUTPUT->header(); // Print horizontal nav if needed. $renderer = $PAGE->get_renderer('core_question', 'bank'); -echo $renderer->extra_horizontal_navigation(); + +echo $OUTPUT->header(); + +$qbankaction = new \core_question\output\qbank_actionbar($url); +echo $renderer->qbank_action_menu($qbankaction); // Display the UI. if (!empty($param->edit)) { diff --git a/question/bank/managecategories/tests/behat/question_categories.feature b/question/bank/managecategories/tests/behat/question_categories.feature index 70b4b936457..9e4263cecb5 100644 --- a/question/bank/managecategories/tests/behat/question_categories.feature +++ b/question/bank/managecategories/tests/behat/question_categories.feature @@ -27,7 +27,8 @@ Feature: A teacher can put questions in categories in the question bank And I am on "Course 1" course homepage Scenario: A new question category can be created - When I navigate to "Question bank > Categories" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Categories" from the "questionbankactionselect" singleselect And I set the following fields to these values: | Name | New Category 1 | | Parent category | Top | @@ -42,7 +43,8 @@ Feature: A teacher can put questions in categories in the question bank And "New Category 1 [newcatidnumber]" "option" should exist in the "Parent category" "select" Scenario: A question category can be edited - When I navigate to "Question bank > Categories" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Categories" from the "questionbankactionselect" singleselect And I click on "Edit this category" "link" in the "Subcategory" "list_item" And the field "parent" matches value "   Default for C1" And I set the following fields to these values: @@ -53,12 +55,14 @@ Feature: A teacher can put questions in categories in the question bank And I should see "I was edited" in the "New name" "list_item" Scenario: An empty question category can be deleted - When I navigate to "Question bank > Categories" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Categories" from the "questionbankactionselect" singleselect And I click on "Delete" "link" in the "Subcategory" "list_item" Then I should not see "Subcategory" Scenario: An non-empty question category can be deleted if you move the contents elsewhere - When I navigate to "Question bank > Categories" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Categories" from the "questionbankactionselect" singleselect And I click on "Delete" "link" in the "Used category" "list_item" And I should see "The category 'Used category' contains 1 questions" And I press "Save in category" diff --git a/question/bank/managecategories/tests/behat/question_categories_idnumber.feature b/question/bank/managecategories/tests/behat/question_categories_idnumber.feature index 95226aa5046..c81e95d0f1b 100644 --- a/question/bank/managecategories/tests/behat/question_categories_idnumber.feature +++ b/question/bank/managecategories/tests/behat/question_categories_idnumber.feature @@ -23,7 +23,8 @@ Feature: A teacher can put questions with idnumbers in categories with idnumbers | contextlevel | reference | questioncategory | name | idnumber | | Course | C1 | Top | top | | | Course | C1 | top | Used category | c1used | - And I navigate to "Question bank > Categories" in current page administration + And I navigate to "Question bank" in current page administration + And I select "Categories" from the "questionbankactionselect" singleselect And I set the following fields to these values: | Name | Sub used category | | Parent category | Used category | @@ -46,7 +47,8 @@ Feature: A teacher can put questions with idnumbers in categories with idnumbers | contextlevel | reference | questioncategory | name | idnumber | | Course | C1 | Top | top | | | Course | C1 | top | Used category | c1used | - And I navigate to "Question bank > Categories" in current page administration + And I navigate to "Question bank" in current page administration + And I select "Categories" from the "questionbankactionselect" singleselect And I click on "Edit this category" "link" in the "Used category" "list_item" And I press "Save changes" Then I should not see "This ID number is already in use" diff --git a/question/bank/managecategories/tests/behat/view_manage_categories_plugin.feature b/question/bank/managecategories/tests/behat/view_manage_categories_plugin.feature index b74387bdc53..18a1150bb35 100644 --- a/question/bank/managecategories/tests/behat/view_manage_categories_plugin.feature +++ b/question/bank/managecategories/tests/behat/view_manage_categories_plugin.feature @@ -22,13 +22,11 @@ Feature: Use the qbank plugin manager page for managecategories And I should see "Manage categories" And I click on "Disable" "link" in the "Manage categories" "table_row" And I am on the "Test quiz" "quiz activity" page - And I navigate to "Question bank" in current page administration - Then I should not see "Categories" + Then "Categories" "link" should not exist in current page administration And I navigate to "Plugins > Question bank plugins > Manage question bank plugins" in site administration And I click on "Enable" "link" in the "Manage categories" "table_row" And I am on the "Test quiz" "quiz activity" page - And I navigate to "Question bank" in current page administration - And I should see "Categories" + And "Categories" "link" should exist in current page administration Scenario: Enable/disable the tab New category when tyring to add a random question to a quiz Given I log in as "admin" diff --git a/question/bank/statistics/tests/behat/statistics_values.feature b/question/bank/statistics/tests/behat/statistics_values.feature index 26015d44e48..ca2fb1f83a0 100644 --- a/question/bank/statistics/tests/behat/statistics_values.feature +++ b/question/bank/statistics/tests/behat/statistics_values.feature @@ -73,7 +73,8 @@ Feature: Show statistics in question bank | 1 | True | | 2 | True | When I am on the "Course 1" course page logged in as admin - And I navigate to "Question bank > Questions" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Questions" from the "questionbankactionselect" singleselect And I should see "50.00%" in the "TF1" "table_row" And I should see "75.00%" in the "TF2" "table_row" And I should see "75.00%" in the "TF3" "table_row" @@ -89,7 +90,8 @@ Feature: Show statistics in question bank | 1 | True | | 2 | True | When I am on the "Course 1" course page logged in as admin - And I navigate to "Question bank > Questions" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Questions" from the "questionbankactionselect" singleselect And I should see "50.00%" in the "TF1" "table_row" And I should see "75.00%" in the "TF2" "table_row" And I should see "75.00%" in the "TF3" "table_row" @@ -105,7 +107,10 @@ Feature: Show statistics in question bank | 1 | True | | 2 | True | When I am on the "Course 1" course page logged in as admin - And I navigate to "Question bank > Questions" in current page administration + And I navigate to "Question bank" in current page administration + And I select "Questions" from the "questionbankactionselect" singleselect + When I navigate to "Question bank" in current page administration + And I select "Questions" from the "questionbankactionselect" singleselect And I should see "likely" in the "TF1" "table_row" And I should see "unlikely" in the "TF2" "table_row" And I should see "unlikely" in the "TF3" "table_row" @@ -127,7 +132,8 @@ Feature: Show statistics in question bank | 1 | True | | 2 | False | When I am on the "Course 1" course page logged in as admin - And I navigate to "Question bank > Questions" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Questions" from the "questionbankactionselect" singleselect And I should see "likely" in the "TF1" "table_row" And I should see "very likely" in the "TF2" "table_row" And I should see "very likely" in the "TF3" "table_row" diff --git a/question/classes/output/qbank_actionbar.php b/question/classes/output/qbank_actionbar.php new file mode 100644 index 00000000000..7933b562fdb --- /dev/null +++ b/question/classes/output/qbank_actionbar.php @@ -0,0 +1,74 @@ +. + +namespace core_question\output; + +use moodle_url; +use renderer_base; +use templatable; +use renderable; +use url_select; + +/** + * Rendered HTML elements for tertiary nav for Question bank. + * + * @package core_question + * @copyright 2021 Sujith Haridasan + * @package core_question + */ +class qbank_actionbar implements templatable, renderable { + /** @var moodle_url */ + private $currenturl; + + /** + * qbank_actionbar constructor. + * + * @param moodle_url $currenturl The current URL. + */ + public function __construct(moodle_url $currenturl) { + $this->currenturl = $currenturl; + } + + /** + * Provides the data for the template. + * + * @param renderer_base $output renderer_base object. + * @return array data for the template + */ + public function export_for_template(renderer_base $output): array { + $questionslink = new moodle_url('/question/edit.php', $this->currenturl->params()); + if (\core\plugininfo\qbank::is_plugin_enabled("qbank_managecategories")) { + $categorylink = new moodle_url('/question/bank/managecategories/category.php', $this->currenturl->params()); + } + $importlink = new moodle_url('/question/bank/importquestions/import.php', $this->currenturl->params()); + $exportlink = new moodle_url('/question/bank/exportquestions/export.php', $this->currenturl->params()); + + $menu = [ + $questionslink->out(false) => get_string('questions', 'question'), + ]; + + if (\core\plugininfo\qbank::is_plugin_enabled("qbank_managecategories")) { + $menu[$categorylink->out(false)] = get_string('categories', 'question'); + } + $menu[$importlink->out(false)] = get_string('import', 'question'); + $menu[$exportlink->out(false)] = get_string('export', 'question'); + + $urlselect = new url_select($menu, $this->currenturl, null, 'questionbankaction'); + $urlselect->set_label('questionbankactionselect', ['class' => 'accesshide']); + + return ['questionbankselect' => $urlselect->export_for_template($output)]; + } +} diff --git a/question/edit.php b/question/edit.php index b0d5ade4ae0..2c7138a6340 100644 --- a/question/edit.php +++ b/question/edit.php @@ -42,11 +42,14 @@ $context = $contexts->lowest(); $streditingquestions = get_string('editquestions', 'question'); $PAGE->set_title($streditingquestions); $PAGE->set_heading($COURSE->fullname); -echo $OUTPUT->header(); // Print horizontal nav if needed. $renderer = $PAGE->get_renderer('core_question', 'bank'); -echo $renderer->extra_horizontal_navigation(); + +echo $OUTPUT->header(); +// Render the selection action. +$qbankaction = new \core_question\output\qbank_actionbar($url); +echo $renderer->qbank_action_menu($qbankaction); // Print the question area. $questionbank->display($pagevars, 'questions'); diff --git a/question/format/aiken/tests/behat/aiken_export.feature b/question/format/aiken/tests/behat/aiken_export.feature index 13bddf67dea..9f937a7c22d 100644 --- a/question/format/aiken/tests/behat/aiken_export.feature +++ b/question/format/aiken/tests/behat/aiken_export.feature @@ -25,7 +25,8 @@ Feature: Test exporting questions using Aiken format. And I am on "Course 1" course homepage Scenario: Aiken export - When I navigate to "Question bank > Export" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_aiken" to "1" When I press "Export questions to file" Then following "click here" should download between "68" and "70" bytes diff --git a/question/format/aiken/tests/behat/aiken_import.feature b/question/format/aiken/tests/behat/aiken_import.feature index 520b2ef2259..807e7f80f02 100644 --- a/question/format/aiken/tests/behat/aiken_import.feature +++ b/question/format/aiken/tests/behat/aiken_import.feature @@ -19,7 +19,8 @@ Feature: Test importing questions from Aiken format. @javascript @_file_upload Scenario: import some Aiken questions - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_aiken" to "1" And I upload "question/format/aiken/tests/fixtures/questions.aiken.txt" file to "Import" filemanager And I press "id_submitbutton" diff --git a/question/format/gift/tests/behat/import_export.feature b/question/format/gift/tests/behat/import_export.feature index 48f0227321f..e398594c95f 100644 --- a/question/format/gift/tests/behat/import_export.feature +++ b/question/format/gift/tests/behat/import_export.feature @@ -19,7 +19,8 @@ Feature: Test importing questions from GIFT format. @javascript @_file_upload Scenario: import some GIFT questions - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_gift" to "1" And I upload "question/format/gift/tests/fixtures/questions.gift.txt" file to "Import" filemanager And I press "id_submitbutton" @@ -30,14 +31,17 @@ Feature: Test importing questions from GIFT format. Then I should see "colours" # Now export again. - And I follow "Export" + And I am on "Course 1" course homepage + And I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_gift" to "1" And I press "Export questions to file" And following "click here" should download between "1500" and "1800" bytes @javascript @_file_upload Scenario: import a GIFT file which specifies the category - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_gift" to "1" And I upload "question/format/gift/tests/fixtures/questions_in_category.gift.txt" file to "Import" filemanager And I press "id_submitbutton" diff --git a/question/format/xml/tests/behat/import_export.feature b/question/format/xml/tests/behat/import_export.feature index 0be26d71ddc..48e2cca5e77 100644 --- a/question/format/xml/tests/behat/import_export.feature +++ b/question/format/xml/tests/behat/import_export.feature @@ -19,7 +19,8 @@ Feature: Test importing questions from Moodle XML format. @javascript @_file_upload Scenario: import some true/false questions from Moodle XML format - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/format/xml/tests/fixtures/truefalse.xml" file to "Import" filemanager And I press "id_submitbutton" @@ -32,7 +33,9 @@ Feature: Test importing questions from Moodle XML format. Then I should see "Moodle acronym (True)" # Now export again. - And I follow "Export" + And I am on "Course 1" course homepage + When I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I set the field "Export category" to "TrueFalse" And I press "Export questions to file" @@ -40,7 +43,8 @@ Feature: Test importing questions from Moodle XML format. @javascript @_file_upload Scenario: import some multiple choice questions from Moodle XML format - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/format/xml/tests/fixtures/multichoice.xml" file to "Import" filemanager And I press "id_submitbutton" @@ -52,7 +56,8 @@ Feature: Test importing questions from Moodle XML format. @javascript @_file_upload Scenario: import some multi-answer questions from Moodle XML format - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/format/xml/tests/fixtures/multianswer.xml" file to "Import" filemanager And I press "id_submitbutton" @@ -64,7 +69,8 @@ Feature: Test importing questions from Moodle XML format. @javascript @_file_upload Scenario: import some questions with legacy-style images from Moodle XML format - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/format/xml/tests/fixtures/sample_questions_with_old_image_tag.xml" file to "Import" filemanager And I press "id_submitbutton" diff --git a/question/renderer.php b/question/renderer.php index 83cfc413e52..c4687e2b44b 100644 --- a/question/renderer.php +++ b/question/renderer.php @@ -182,6 +182,17 @@ class core_question_bank_renderer extends plugin_renderer_base { return ''; } + /** + * Get the rendered HTML for the action area in Question bank. + * + * @param \core_question\output\qbank_actionbar $qbankactionbar qbankactionbar object. + * @return string rendered HTML string from template. + */ + public function qbank_action_menu(\core_question\output\qbank_actionbar $qbankactionbar): string { + return $this->render_from_template('core_question/qbank_action_menu', + $qbankactionbar->export_for_template($this)); + } + /** * Build the HTML for a specified set of question types. * diff --git a/question/templates/qbank_action_menu.mustache b/question/templates/qbank_action_menu.mustache new file mode 100644 index 00000000000..87d9ed33d97 --- /dev/null +++ b/question/templates/qbank_action_menu.mustache @@ -0,0 +1,63 @@ +{{! + 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 core_question/qbank_action_menu + Add selector in the question bank tab. + Classes required for JS: + * none + Data attributes required for JS: + * data-region + Context variables required for this template: + * see question/classes/output/qbank_actionbar.php + Example context (json): + { + "action" : "http://localhost/moodle/course/jumpto.php", + "classes" : "urlselect", + "formid" : "questionbankaction", + "id" : "url_select61a85bc543dca7", + "label" : "questionbankactionselect", + "options" : [ + { + "name" : "Questions", + "selected" : true, + "value" : "/question/edit.php?courseid=7" + }, + { + "name" : "Categories", + "selected" : false, + "value" : "/question/bank/managecategories/category.php?courseid=7" + }, + { + "name" : "Import", + "selected" : false, + "value" : "/question/bank/importquestions/import.php?courseid=7" + }, + { + "name" : "Export", + "selected" : false, + "value" : "/question/bank/exportquestions/export.php?courseid=7" + } + ] + } +}} +
+
+ {{#questionbankselect}} + {{>core/url_select}} + {{/questionbankselect}} +
+
diff --git a/question/tests/behat/delete_questions.feature b/question/tests/behat/delete_questions.feature index 428ee233493..d61054c90c3 100644 --- a/question/tests/behat/delete_questions.feature +++ b/question/tests/behat/delete_questions.feature @@ -60,7 +60,7 @@ Feature: A teacher can delete questions in the question bank And I click on "Also show old questions" "checkbox" And I should see "Test used question to be deleted" And I am on the "Test quiz" "quiz activity" page - And I click on "Preview quiz now" "button" + And I follow "Preview quiz" And I should see "Write about whatever you want" @javascript diff --git a/question/type/ddimageortext/tests/behat/export.feature b/question/type/ddimageortext/tests/behat/export.feature index 61f582f1a5e..62265d391ab 100644 --- a/question/type/ddimageortext/tests/behat/export.feature +++ b/question/type/ddimageortext/tests/behat/export.feature @@ -26,7 +26,8 @@ Feature: Test exporting drag and drop onto image questions @javascript Scenario: Export a drag and drop onto image question # Import sample file. - When I navigate to "Question bank > Export" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I press "Export questions to file" And following "click here" should download between "18600" and "19150" bytes diff --git a/question/type/ddimageortext/tests/behat/import.feature b/question/type/ddimageortext/tests/behat/import.feature index 65c64db824f..d10b432d9a9 100644 --- a/question/type/ddimageortext/tests/behat/import.feature +++ b/question/type/ddimageortext/tests/behat/import.feature @@ -19,7 +19,8 @@ Feature: Test importing drag and drop onto image questions @javascript @_file_upload Scenario: import drag and drop onto image question. - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/type/ddimageortext/tests/fixtures/testquestion.moodle.xml" file to "Import" filemanager And I press "id_submitbutton" diff --git a/question/type/ddmarker/tests/behat/export.feature b/question/type/ddmarker/tests/behat/export.feature index 80928780368..8b196229822 100644 --- a/question/type/ddmarker/tests/behat/export.feature +++ b/question/type/ddmarker/tests/behat/export.feature @@ -26,7 +26,8 @@ Feature: Test exporting drag and drop markers questions @javascript Scenario: Export a drag and drop markers question # Import sample file. - When I navigate to "Question bank > Export" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I press "Export questions to file" And following "click here" should download between "233700" and "233950" bytes diff --git a/question/type/ddmarker/tests/behat/import.feature b/question/type/ddmarker/tests/behat/import.feature index 38ddf880fa4..ba32882d9d0 100644 --- a/question/type/ddmarker/tests/behat/import.feature +++ b/question/type/ddmarker/tests/behat/import.feature @@ -19,7 +19,8 @@ Feature: Test importing drag and drop markers questions @javascript @_file_upload Scenario: import drag and drop markers question. - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/type/ddmarker/tests/fixtures/testquestion.moodle.xml" file to "Import" filemanager And I press "id_submitbutton" diff --git a/question/type/ddwtos/tests/behat/export.feature b/question/type/ddwtos/tests/behat/export.feature index 03729a1c9eb..ae6151892db 100644 --- a/question/type/ddwtos/tests/behat/export.feature +++ b/question/type/ddwtos/tests/behat/export.feature @@ -26,7 +26,8 @@ Feature: Test exporting drag and drop into text questions @javascript Scenario: Export a drag and drop into text question # Import sample file. - When I navigate to "Question bank > Export" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I press "Export questions to file" And following "click here" should download between "1550" and "1700" bytes diff --git a/question/type/ddwtos/tests/behat/import.feature b/question/type/ddwtos/tests/behat/import.feature index 9785350456d..2659d869cf9 100644 --- a/question/type/ddwtos/tests/behat/import.feature +++ b/question/type/ddwtos/tests/behat/import.feature @@ -19,7 +19,8 @@ Feature: Test importing drag and drop into text questions @javascript @_file_upload Scenario: import drag and drop into text question. - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/type/ddwtos/tests/fixtures/testquestion.moodle.xml" file to "Import" filemanager And I press "id_submitbutton" diff --git a/question/type/description/tests/behat/export.feature b/question/type/description/tests/behat/export.feature index a630926060c..91c300fda38 100644 --- a/question/type/description/tests/behat/export.feature +++ b/question/type/description/tests/behat/export.feature @@ -24,7 +24,8 @@ Feature: Test exporting Description questions And I am on "Course 1" course homepage Scenario: Export a Description question - When I navigate to "Question bank > Export" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I press "Export questions to file" Then following "click here" should download between "650" and "900" bytes diff --git a/question/type/description/tests/behat/import.feature b/question/type/description/tests/behat/import.feature index 53bdb1964ea..3b7cf52f85d 100644 --- a/question/type/description/tests/behat/import.feature +++ b/question/type/description/tests/behat/import.feature @@ -19,7 +19,8 @@ Feature: Test importing Description questions @javascript @_file_upload Scenario: import a Description question. - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/type/description/tests/fixtures/testquestion.moodle.xml" file to "Import" filemanager And I press "id_submitbutton" diff --git a/question/type/essay/tests/behat/export.feature b/question/type/essay/tests/behat/export.feature index deef3d77558..a3b7aa59188 100644 --- a/question/type/essay/tests/behat/export.feature +++ b/question/type/essay/tests/behat/export.feature @@ -26,7 +26,8 @@ Feature: Test exporting Essay questions And I am on "Course 1" course homepage Scenario: Export 3 Essay questions - When I navigate to "Question bank > Export" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I press "Export questions to file" Then following "click here" should download between "3000" and "3500" bytes diff --git a/question/type/essay/tests/behat/file_type_restriction.feature b/question/type/essay/tests/behat/file_type_restriction.feature index de5e78912b7..82f164af7c9 100644 --- a/question/type/essay/tests/behat/file_type_restriction.feature +++ b/question/type/essay/tests/behat/file_type_restriction.feature @@ -44,7 +44,7 @@ I need to limit the submittable file types And I upload "lib/tests/fixtures/empty.txt" file to "Files" filemanager And I press "Save changes" And I am on the "Quiz 1" "quiz activity" page - And I press "Attempt quiz now" + And I follow "Attempt quiz" And I should see "First question" And I should see "You can drag and drop files here to add them." And I click on "Add..." "button" @@ -62,7 +62,7 @@ I need to limit the submittable file types And I upload "lib/tests/fixtures/upload_users.csv" file to "Files" filemanager And I press "Save changes" And I am on the "Quiz 1" "quiz activity" page - And I press "Attempt quiz now" + And I follow "Attempt quiz" And I should see "First question" And I should see "You can drag and drop files here to add them." And I click on "Add..." "button" diff --git a/question/type/essay/tests/behat/import.feature b/question/type/essay/tests/behat/import.feature index e365569e370..e756b8f6eb1 100644 --- a/question/type/essay/tests/behat/import.feature +++ b/question/type/essay/tests/behat/import.feature @@ -19,7 +19,8 @@ Feature: Test importing Essay questions @javascript @_file_upload Scenario: import Essay question. - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/type/essay/tests/fixtures/testquestion.moodle.xml" file to "Import" filemanager And I press "id_submitbutton" diff --git a/question/type/gapselect/tests/behat/import_test.feature b/question/type/gapselect/tests/behat/import_test.feature index a7d5018de8e..24cb258f747 100644 --- a/question/type/gapselect/tests/behat/import_test.feature +++ b/question/type/gapselect/tests/behat/import_test.feature @@ -20,7 +20,8 @@ Feature: Import and export select missing words questions @javascript @_file_upload Scenario: Import and export select missing words questions # Import sample file. - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/type/gapselect/tests/fixtures/testquestion.moodle.xml" file to "Import" filemanager And I press "id_submitbutton" @@ -31,7 +32,9 @@ Feature: Import and export select missing words questions And I should see "Imported Select missing words 001" # Now export again. - When I follow "Export" + And I am on "Course 1" course homepage + When I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I press "Export questions to file" Then following "click here" should download between "1650" and "1800" bytes diff --git a/question/type/match/tests/behat/export.feature b/question/type/match/tests/behat/export.feature index 4b1b08db9ae..0df927c1ca2 100644 --- a/question/type/match/tests/behat/export.feature +++ b/question/type/match/tests/behat/export.feature @@ -24,7 +24,8 @@ Feature: Test exporting Matching questions And I am on "Course 1" course homepage Scenario: Export a Matching question - When I navigate to "Question bank > Export" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I press "Export questions to file" Then following "click here" should download between "1600" and "1750" bytes diff --git a/question/type/match/tests/behat/import.feature b/question/type/match/tests/behat/import.feature index 99308528b2e..a7511298eec 100644 --- a/question/type/match/tests/behat/import.feature +++ b/question/type/match/tests/behat/import.feature @@ -19,7 +19,8 @@ Feature: Test importing Matching questions @javascript @_file_upload Scenario: import Matching question. - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/type/match/tests/fixtures/testquestion.moodle.xml" file to "Import" filemanager And I press "id_submitbutton" diff --git a/question/type/multichoice/tests/behat/clearanswers.feature b/question/type/multichoice/tests/behat/clearanswers.feature index 95c7c5d27df..fe9548a259b 100644 --- a/question/type/multichoice/tests/behat/clearanswers.feature +++ b/question/type/multichoice/tests/behat/clearanswers.feature @@ -40,7 +40,7 @@ Feature: Clear my answers @javascript Scenario: Attempt a quiz and reset my chosen answer. Given I am on the "Quiz 1" "quiz activity" page logged in as student1 - When I press "Attempt quiz now" + When I follow "Attempt quiz" And I should see "Question One" And I click on "Four" "qtype_multichoice > Answer" in the "Question One" "question" And I should see "Clear my choice" @@ -52,7 +52,7 @@ Feature: Clear my answers @javascript Scenario: Attempt a quiz and revisit a cleared answer. Given I am on the "Quiz 1" "quiz activity" page logged in as student1 - When I press "Attempt quiz now" + When I follow "Attempt quiz" And I should see "Question One" And I click on "Four" "qtype_multichoice > Answer" in the "Question One" "question" And I follow "Finish attempt ..." diff --git a/question/type/multichoice/tests/behat/export.feature b/question/type/multichoice/tests/behat/export.feature index 27fd30eb613..1d4c8a22763 100644 --- a/question/type/multichoice/tests/behat/export.feature +++ b/question/type/multichoice/tests/behat/export.feature @@ -25,7 +25,8 @@ Feature: Test exporting Multiple choice questions And I am on "Course 1" course homepage Scenario: Export a Multiple choice question - When I navigate to "Question bank > Export" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I press "Export questions to file" Then following "click here" should download between "3900" and "4100" bytes diff --git a/question/type/multichoice/tests/behat/import.feature b/question/type/multichoice/tests/behat/import.feature index 53744321b2e..79e7dc9abc7 100644 --- a/question/type/multichoice/tests/behat/import.feature +++ b/question/type/multichoice/tests/behat/import.feature @@ -19,7 +19,8 @@ Feature: Test importing Multiple choice questions @javascript @_file_upload Scenario: import Multiple choice question. - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/type/multichoice/tests/fixtures/testquestion.moodle.xml" file to "Import" filemanager And I press "id_submitbutton" diff --git a/question/type/numerical/tests/behat/export.feature b/question/type/numerical/tests/behat/export.feature index 7d3f920819c..d77074457da 100644 --- a/question/type/numerical/tests/behat/export.feature +++ b/question/type/numerical/tests/behat/export.feature @@ -25,7 +25,8 @@ Feature: Test exporting Numerical questions And I am on "Course 1" course homepage Scenario: Export a Numerical question - When I navigate to "Question bank > Export" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I press "Export questions to file" Then following "click here" should download between "3650" and "3750" bytes diff --git a/question/type/numerical/tests/behat/import.feature b/question/type/numerical/tests/behat/import.feature index 6995a63dc0f..b7026ea5748 100644 --- a/question/type/numerical/tests/behat/import.feature +++ b/question/type/numerical/tests/behat/import.feature @@ -19,7 +19,8 @@ Feature: Test importing Numerical questions @javascript @_file_upload Scenario: import Numerical question. - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/type/numerical/tests/fixtures/testquestion.moodle.xml" file to "Import" filemanager And I press "id_submitbutton" diff --git a/question/type/shortanswer/tests/behat/export.feature b/question/type/shortanswer/tests/behat/export.feature index e80449a994c..d83243fecb1 100644 --- a/question/type/shortanswer/tests/behat/export.feature +++ b/question/type/shortanswer/tests/behat/export.feature @@ -24,7 +24,8 @@ Feature: Test exporting Short answer questions And I am on "Course 1" course homepage Scenario: Export a Short answer question - When I navigate to "Question bank > Export" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I press "Export questions to file" Then following "click here" should download between "1200" and "1450" bytes diff --git a/question/type/shortanswer/tests/behat/import.feature b/question/type/shortanswer/tests/behat/import.feature index 48908094429..a8df6faea91 100644 --- a/question/type/shortanswer/tests/behat/import.feature +++ b/question/type/shortanswer/tests/behat/import.feature @@ -19,7 +19,8 @@ Feature: Test importing Short answer questions @javascript @_file_upload Scenario: import Matching question. - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/type/shortanswer/tests/fixtures/testquestion.moodle.xml" file to "Import" filemanager And I press "id_submitbutton" diff --git a/question/type/truefalse/tests/behat/export.feature b/question/type/truefalse/tests/behat/export.feature index 1f0f4ad9c66..81b9de39ade 100644 --- a/question/type/truefalse/tests/behat/export.feature +++ b/question/type/truefalse/tests/behat/export.feature @@ -24,7 +24,8 @@ Feature: Test exporting True/False questions And I am on "Course 1" course homepage Scenario: Export a True/False question - When I navigate to "Question bank > Export" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Export" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I press "Export questions to file" Then following "click here" should download between "1000" and "1200" bytes diff --git a/question/type/truefalse/tests/behat/import.feature b/question/type/truefalse/tests/behat/import.feature index 7a3bd4c1174..4bf13dceb86 100644 --- a/question/type/truefalse/tests/behat/import.feature +++ b/question/type/truefalse/tests/behat/import.feature @@ -19,7 +19,8 @@ Feature: Test importing True/False questions @javascript @_file_upload Scenario: import a True/False question. - When I navigate to "Question bank > Import" in current page administration + When I navigate to "Question bank" in current page administration + And I select "Import" from the "questionbankactionselect" singleselect And I set the field "id_format_xml" to "1" And I upload "question/type/truefalse/tests/fixtures/testquestion.moodle.xml" file to "Import" filemanager And I press "id_submitbutton" diff --git a/repository/contentbank/tests/behat/select_content.feature b/repository/contentbank/tests/behat/select_content.feature index 9a2d29980d6..dd322015d16 100644 --- a/repository/contentbank/tests/behat/select_content.feature +++ b/repository/contentbank/tests/behat/select_content.feature @@ -130,14 +130,14 @@ Feature: Select content bank files using the content bank files repository Scenario: Non-editing teacher can not see the content bank repository Given I am on the Forum "Forum activity" page logged in as teacher2 - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I click on "Link" "button" When I click on "Browse repositories..." "button" Then I should not see "Content bank" in the ".fp-repo-area" "css_element" Scenario: Student can not see the content bank repository Given I am on the Forum "Forum activity" page logged in as student - And I click on "Add a new discussion topic" "link" + And I click on "Add discussion topic" "link" And I click on "Link" "button" When I click on "Browse repositories..." "button" Then I should not see "Content bank" in the ".fp-repo-area" "css_element" diff --git a/theme/classic/tests/behat/behat_theme_classic_behat_mod_forum.php b/theme/classic/tests/behat/behat_theme_classic_behat_mod_forum.php deleted file mode 100644 index 193e7de3e9c..00000000000 --- a/theme/classic/tests/behat/behat_theme_classic_behat_mod_forum.php +++ /dev/null @@ -1,67 +0,0 @@ -. - -/** - * Step definitions related to mod_forum overrides for the Classic theme. - * - * @package theme_classic - * @category test - * @copyright 2019 Ryan Wyllie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. - -require_once(__DIR__ . '/../../../../mod/forum/tests/behat/behat_mod_forum.php'); - -/** - * Step definitions related to mod_forum overrides for the Classic theme. - * - * @package theme_classic - * @category test - * @copyright 2019 Ryan Wyllie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class behat_theme_classic_behat_mod_forum extends behat_mod_forum { - - /** - * Checks if the user can subscribe to the forum. - */ - public function i_can_subscribe_to_this_forum() { - $this->execute('behat_general::assert_page_contains_text', [get_string('subscribe', 'mod_forum')]); - } - - /** - * Checks if the user can unsubscribe from the forum. - */ - public function i_can_unsubscribe_from_this_forum() { - $this->execute('behat_general::assert_page_contains_text', [get_string('unsubscribe', 'mod_forum')]); - } - - /** - * Subscribes to the forum. - */ - public function i_subscribe_to_this_forum() { - $this->execute('behat_general::click_link', [get_string('subscribe', 'mod_forum')]); - } - - /** - * Unsubscribes from the forum. - */ - public function i_unsubscribe_from_this_forum() { - $this->execute('behat_general::click_link', [get_string('unsubscribe', 'mod_forum')]); - } -} diff --git a/theme/classic/tests/behat/behat_theme_classic_behat_navigation.php b/theme/classic/tests/behat/behat_theme_classic_behat_navigation.php index a0e23d1e324..791274e6c7d 100644 --- a/theme/classic/tests/behat/behat_theme_classic_behat_navigation.php +++ b/theme/classic/tests/behat/behat_theme_classic_behat_navigation.php @@ -154,7 +154,16 @@ class behat_theme_classic_behat_navigation extends behat_navigation { } $exception = new ElementNotFoundException($this->getSession(), "\"{$element}\" \"{$selectortype}\""); - $this->find('xpath', $menuxpath, $exception); + try { + $this->find('xpath', $menuxpath, $exception); + } catch (Exception $e) { + // For question bank a different approach. + $menuxpath = $rootxpath . "//div[contains(@class, 'dropdown-menu')]"; + if ($selectortype === 'link') { + $menuxpath .= "//a[contains(text(), 'Categories')]"; + } + $this->find('xpath', $menuxpath, $e); + } } /**