MDL-77991 gradereport_user: Migrate to core search dropdown
This commit is contained in:
+3
@@ -0,0 +1,3 @@
|
||||
define("gradereport_user/group",["exports","core_group/comboboxsearch/group","core/url"],(function(_exports,_group,_url){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_group=_interopRequireDefault(_group),_url=_interopRequireDefault(_url);class Group extends _group.default{constructor(){var obj,key,value;super(),value=void 0,(key="courseID")in(obj=this)?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,this.selectors={...this.selectors,courseid:'[data-region="courseid"]'};const component=document.querySelector(this.componentSelector());this.courseID=component.querySelector(this.selectors.courseid).dataset.courseid}static init(){return new Group}selectOneLink(groupID){return _url.default.relativeUrl("/grade/report/user/index.php",{id:this.courseID,groupsearchvalue:this.getSearchTerm(),group:groupID},!1)}}return _exports.default=Group,_exports.default}));
|
||||
|
||||
//# sourceMappingURL=group.min.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"group.min.js","sources":["../src/group.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Allow the user to search for groups within the user report.\n *\n * @module gradereport_user/group\n * @copyright 2023 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport GroupSearch from 'core_group/comboboxsearch/group';\nimport Url from 'core/url';\n\nexport default class Group extends GroupSearch {\n\n courseID;\n\n constructor() {\n super();\n\n // Define our standard lookups.\n this.selectors = {...this.selectors,\n courseid: '[data-region=\"courseid\"]',\n };\n const component = document.querySelector(this.componentSelector());\n this.courseID = component.querySelector(this.selectors.courseid).dataset.courseid;\n }\n\n static init() {\n return new Group();\n }\n\n /**\n * Build up the view all link that is dedicated to a particular result.\n *\n * @param {Number} groupID The ID of the group selected.\n * @returns {string|*}\n */\n selectOneLink(groupID) {\n return Url.relativeUrl('/grade/report/user/index.php', {\n id: this.courseID,\n groupsearchvalue: this.getSearchTerm(),\n group: groupID,\n }, false);\n }\n}\n"],"names":["Group","GroupSearch","constructor","selectors","this","courseid","component","document","querySelector","componentSelector","courseID","dataset","selectOneLink","groupID","Url","relativeUrl","id","groupsearchvalue","getSearchTerm","group"],"mappings":"yWAyBqBA,cAAcC,eAI/BC,6LAISC,UAAY,IAAIC,KAAKD,UACtBE,SAAU,kCAERC,UAAYC,SAASC,cAAcJ,KAAKK,0BACzCC,SAAWJ,UAAUE,cAAcJ,KAAKD,UAAUE,UAAUM,QAAQN,8BAIlE,IAAIL,MASfY,cAAcC,gBACHC,aAAIC,YAAY,+BAAgC,CACnDC,GAAIZ,KAAKM,SACTO,iBAAkBb,KAAKc,gBACvBC,MAAON,UACR"}
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
define("gradereport_user/user",["exports","core/local/aria/focuslock","core/pending","core/templates","core_grades/searchwidget/repository","core_grades/searchwidget/basewidget","core/str","core/url","jquery","core_grades/searchwidget/selectors"],(function(_exports,FocusLockManager,_pending,Templates,Repository,WidgetBase,_str,_url,_jquery,Selectors){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}
|
||||
define("gradereport_user/user",["exports","core_user/comboboxsearch/user","core/url","core/templates","core_grades/searchwidget/repository"],(function(_exports,_user,_url,_templates,Repository){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
|
||||
/**
|
||||
* A widget to search users within the gradebook.
|
||||
* Allow the user to search for learners within the user report.
|
||||
*
|
||||
* @module gradereport_user/user
|
||||
* @copyright 2022 Mathew May <mathew.solutions>
|
||||
* @copyright 2023 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,FocusLockManager=_interopRequireWildcard(FocusLockManager),_pending=_interopRequireDefault(_pending),Templates=_interopRequireWildcard(Templates),Repository=_interopRequireWildcard(Repository),WidgetBase=_interopRequireWildcard(WidgetBase),_url=_interopRequireDefault(_url),_jquery=_interopRequireDefault(_jquery),Selectors=_interopRequireWildcard(Selectors);_exports.init=()=>{const pendingPromise=new _pending.default;registerListenerEvents(),pendingPromise.resolve()};const registerListenerEvents=()=>{let{bodyPromiseResolver:bodyPromiseResolver,bodyPromise:bodyPromise}=WidgetBase.promisesAndResolvers();const dropdownMenuContainer=document.querySelector(Selectors.elements.getSearchWidgetDropdownSelector("user")),menuContainer=document.querySelector(Selectors.elements.getSearchWidgetSelector("user")),inputElement=menuContainer.querySelector('input[name="userid"]');(0,_jquery.default)(menuContainer).on("show.bs.dropdown",(async e=>{const courseID=e.relatedTarget.dataset.courseid,groupId=e.relatedTarget.dataset.groupid;await WidgetBase.showLoader(dropdownMenuContainer);const data=await Repository.userFetch(courseID,groupId).catch((async e=>{const errorTemplateData={errormessage:e.message};bodyPromiseResolver(await Templates.render("core_grades/searchwidget/error",errorTemplateData))}));if(data===[])return;const allUsersOptionName=await(0,_str.get_string)("allusersnum","gradereport_user",data.users.length),allUsersOption=await Templates.render("gradereport_user/all_users_item",{id:0,name:allUsersOptionName,url:_url.default.relativeUrl("/grade/report/user/index.php",{id:courseID,userid:0},!1)});await WidgetBase.init(dropdownMenuContainer,bodyPromise,data.users,searchUsers(),allUsersOption,afterSelect),bodyPromiseResolver(Templates.render("core_grades/searchwidget/user/usersearch_body",{displayunsearchablecontent:!0})),FocusLockManager.trapFocus(dropdownMenuContainer)})),(0,_jquery.default)(menuContainer).on("hide.bs.dropdown",(()=>{FocusLockManager.untrapFocus()})),inputElement.addEventListener("change",(e=>{const courseID=menuContainer.querySelector(".dropdown-toggle").dataset.courseid,actionUrl=_url.default.relativeUrl("/grade/report/user/index.php",{id:courseID,userid:e.target.value},!1);location.href=actionUrl,e.stopPropagation()}))},searchUsers=()=>()=>(users,searchTerm)=>{if(""===searchTerm)return users;searchTerm=searchTerm.toLowerCase();const searchResults=[];return users.forEach((user=>{user.fullname.toLowerCase().includes(searchTerm)&&searchResults.push(user)})),searchResults},afterSelect=selected=>{const menuContainer=document.querySelector(Selectors.elements.getSearchWidgetSelector("user")),inputElement=menuContainer.querySelector('input[name="userid"]');(0,_jquery.default)(menuContainer).dropdown("hide"),inputElement.value!=selected&&(inputElement.value=selected,inputElement.dispatchEvent(new Event("change",{bubbles:!0})))}}));
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_user=_interopRequireDefault(_user),_url=_interopRequireDefault(_url),Repository=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(Repository);class User extends _user.default{constructor(){super()}static init(){return new User}async renderDropdown(){const{html:html,js:js}=await(0,_templates.renderForPromise)("core_user/comboboxsearch/resultset",{users:this.getMatchedResults().slice(0,5),hasresults:this.getMatchedResults().length>0,matches:this.getDatasetSize(),searchterm:this.getSearchTerm(),selectall:this.selectAllResultsLink()});(0,_templates.replaceNodeContents)(this.getHTMLElements().searchDropdown,html,js)}selectAllResultsLink(){return _url.default.relativeUrl("/grade/report/user/index.php",{id:this.courseID,userid:0,searchvalue:this.getSearchTerm()},!1)}selectOneLink(userID){return _url.default.relativeUrl("/grade/report/user/index.php",{id:this.courseID,searchvalue:this.getSearchTerm(),userid:userID},!1)}fetchDataset(){const gts="string"==typeof this.groupID&&""===this.groupID?0:this.groupID;return Repository.userFetch(this.courseID,gts).then((r=>r.users))}}return _exports.default=User,_exports.default}));
|
||||
|
||||
//# sourceMappingURL=user.min.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Allow the user to search for groups within the user report.
|
||||
*
|
||||
* @module gradereport_user/group
|
||||
* @copyright 2023 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
import GroupSearch from 'core_group/comboboxsearch/group';
|
||||
import Url from 'core/url';
|
||||
|
||||
export default class Group extends GroupSearch {
|
||||
|
||||
courseID;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// Define our standard lookups.
|
||||
this.selectors = {...this.selectors,
|
||||
courseid: '[data-region="courseid"]',
|
||||
};
|
||||
const component = document.querySelector(this.componentSelector());
|
||||
this.courseID = component.querySelector(this.selectors.courseid).dataset.courseid;
|
||||
}
|
||||
|
||||
static init() {
|
||||
return new Group();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build up the view all link that is dedicated to a particular result.
|
||||
*
|
||||
* @param {Number} groupID The ID of the group selected.
|
||||
* @returns {string|*}
|
||||
*/
|
||||
selectOneLink(groupID) {
|
||||
return Url.relativeUrl('/grade/report/user/index.php', {
|
||||
id: this.courseID,
|
||||
groupsearchvalue: this.getSearchTerm(),
|
||||
group: groupID,
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
@@ -14,147 +14,76 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* A widget to search users within the gradebook.
|
||||
* Allow the user to search for learners within the user report.
|
||||
*
|
||||
* @module gradereport_user/user
|
||||
* @copyright 2022 Mathew May <mathew.solutions>
|
||||
* @copyright 2023 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import * as FocusLockManager from 'core/local/aria/focuslock';
|
||||
import Pending from 'core/pending';
|
||||
import * as Templates from 'core/templates';
|
||||
import * as Repository from 'core_grades/searchwidget/repository';
|
||||
import * as WidgetBase from 'core_grades/searchwidget/basewidget';
|
||||
import {get_string as getString} from 'core/str';
|
||||
import UserSearch from 'core_user/comboboxsearch/user';
|
||||
import Url from 'core/url';
|
||||
import $ from 'jquery';
|
||||
import * as Selectors from 'core_grades/searchwidget/selectors';
|
||||
import {renderForPromise, replaceNodeContents} from 'core/templates';
|
||||
import * as Repository from 'core_grades/searchwidget/repository';
|
||||
|
||||
/**
|
||||
* Our entry point into starting to build the search widget.
|
||||
* It'll eventually, based upon the listeners, open the search widget and allow filtering.
|
||||
*
|
||||
* @method init
|
||||
*/
|
||||
export const init = () => {
|
||||
const pendingPromise = new Pending();
|
||||
registerListenerEvents();
|
||||
pendingPromise.resolve();
|
||||
};
|
||||
export default class User extends UserSearch {
|
||||
|
||||
/**
|
||||
* Register user search widget related event listeners.
|
||||
*
|
||||
* @method registerListenerEvents
|
||||
*/
|
||||
const registerListenerEvents = () => {
|
||||
let {bodyPromiseResolver, bodyPromise} = WidgetBase.promisesAndResolvers();
|
||||
const dropdownMenuContainer = document.querySelector(Selectors.elements.getSearchWidgetDropdownSelector('user'));
|
||||
const menuContainer = document.querySelector(Selectors.elements.getSearchWidgetSelector('user'));
|
||||
const inputElement = menuContainer.querySelector('input[name="userid"]');
|
||||
|
||||
// Handle the 'shown.bs.dropdown' event (Fired when the dropdown menu is fully displayed).
|
||||
$(menuContainer).on('show.bs.dropdown', async(e) => {
|
||||
const courseID = e.relatedTarget.dataset.courseid;
|
||||
const groupId = e.relatedTarget.dataset.groupid;
|
||||
// Display a loading icon in the dropdown menu container until the body promise is resolved.
|
||||
await WidgetBase.showLoader(dropdownMenuContainer);
|
||||
|
||||
// If an error occurs while fetching the data, display the error within the dropdown menu.
|
||||
const data = await Repository.userFetch(courseID, groupId).catch(async(e) => {
|
||||
const errorTemplateData = {
|
||||
'errormessage': e.message
|
||||
};
|
||||
bodyPromiseResolver(
|
||||
await Templates.render('core_grades/searchwidget/error', errorTemplateData)
|
||||
);
|
||||
});
|
||||
|
||||
// Early return if there is no module data.
|
||||
if (data === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The HTML for the 'All users' option which will be rendered in the non-searchable content are of the widget.
|
||||
const allUsersOptionName = await getString('allusersnum', 'gradereport_user', data.users.length);
|
||||
const allUsersOption = await Templates.render('gradereport_user/all_users_item', {
|
||||
id: 0,
|
||||
name: allUsersOptionName,
|
||||
url: Url.relativeUrl('/grade/report/user/index.php', {id: courseID, userid: 0}, false),
|
||||
});
|
||||
|
||||
await WidgetBase.init(
|
||||
dropdownMenuContainer,
|
||||
bodyPromise,
|
||||
data.users,
|
||||
searchUsers(),
|
||||
allUsersOption,
|
||||
afterSelect
|
||||
);
|
||||
|
||||
// Resolvers for passed functions in the dropdown menu creation.
|
||||
bodyPromiseResolver(Templates.render(
|
||||
'core_grades/searchwidget/user/usersearch_body', {displayunsearchablecontent: true}
|
||||
));
|
||||
|
||||
// Lock tab control. It has to be locked because the dropdown's role is dialog.
|
||||
FocusLockManager.trapFocus(dropdownMenuContainer);
|
||||
});
|
||||
|
||||
// Handle the 'hide.bs.dropdown' event (Fired when the dropdown menu is being closed).
|
||||
$(menuContainer).on('hide.bs.dropdown', () => {
|
||||
FocusLockManager.untrapFocus();
|
||||
});
|
||||
|
||||
inputElement.addEventListener('change', e => {
|
||||
const toggle = menuContainer.querySelector('.dropdown-toggle');
|
||||
const courseID = toggle.dataset.courseid;
|
||||
const actionUrl = Url.relativeUrl('/grade/report/user/index.php', {id: courseID, userid: e.target.value}, false);
|
||||
location.href = actionUrl;
|
||||
|
||||
e.stopPropagation();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Define how we want to search and filter users when the user decides to input a search value.
|
||||
*
|
||||
* @method searchUsers
|
||||
* @returns {function(): function(*, *): (*)}
|
||||
*/
|
||||
const searchUsers = () => {
|
||||
return () => {
|
||||
return (users, searchTerm) => {
|
||||
if (searchTerm === '') {
|
||||
return users;
|
||||
}
|
||||
searchTerm = searchTerm.toLowerCase();
|
||||
const searchResults = [];
|
||||
users.forEach((user) => {
|
||||
const userName = user.fullname.toLowerCase();
|
||||
if (userName.includes(searchTerm)) {
|
||||
searchResults.push(user);
|
||||
}
|
||||
});
|
||||
return searchResults;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Define the action to be performed when an item is selected by the search widget.
|
||||
*
|
||||
* @param {String} selected The selected item's value.
|
||||
*/
|
||||
const afterSelect = (selected) => {
|
||||
const menuContainer = document.querySelector(Selectors.elements.getSearchWidgetSelector('user'));
|
||||
const inputElement = menuContainer.querySelector('input[name="userid"]');
|
||||
|
||||
$(menuContainer).dropdown('hide'); // Otherwise the dropdown stays open when user choose an option using keyboard.
|
||||
|
||||
if (inputElement.value != selected) {
|
||||
inputElement.value = selected;
|
||||
inputElement.dispatchEvent(new Event('change', {bubbles: true}));
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
};
|
||||
|
||||
static init() {
|
||||
return new User();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the content then replace the node.
|
||||
*/
|
||||
async renderDropdown() {
|
||||
const {html, js} = await renderForPromise('core_user/comboboxsearch/resultset', {
|
||||
users: this.getMatchedResults().slice(0, 5),
|
||||
hasresults: this.getMatchedResults().length > 0,
|
||||
matches: this.getDatasetSize(),
|
||||
searchterm: this.getSearchTerm(),
|
||||
selectall: this.selectAllResultsLink(),
|
||||
});
|
||||
replaceNodeContents(this.getHTMLElements().searchDropdown, html, js);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build up the view all link.
|
||||
*
|
||||
* @returns {string|*}
|
||||
*/
|
||||
selectAllResultsLink() {
|
||||
return Url.relativeUrl('/grade/report/user/index.php', {
|
||||
id: this.courseID,
|
||||
userid: 0,
|
||||
searchvalue: this.getSearchTerm()
|
||||
}, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build up the view all link that is dedicated to a particular result.
|
||||
*
|
||||
* @param {Number} userID The ID of the user selected.
|
||||
* @returns {string|*}
|
||||
*/
|
||||
selectOneLink(userID) {
|
||||
return Url.relativeUrl('/grade/report/user/index.php', {
|
||||
id: this.courseID,
|
||||
searchvalue: this.getSearchTerm(),
|
||||
userid: userID,
|
||||
}, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data we will be searching against in this component.
|
||||
*
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
fetchDataset() {
|
||||
// Small typing checks as sometimes groups don't exist therefore the element returns a empty string.
|
||||
const gts = typeof (this.groupID) === "string" && this.groupID === '' ? 0 : this.groupID;
|
||||
return Repository.userFetch(this.courseID, gts).then((r) => r.users);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,12 +80,12 @@ class action_bar extends \core_grades\output\action_bar {
|
||||
// If the user has the capability to view all grades, display the group selector (if applicable), the user selector
|
||||
// and the view mode selector (if applicable).
|
||||
if (has_capability('moodle/grade:viewall', $this->context)) {
|
||||
$course = get_course($courseid);
|
||||
$gradesrenderer = $PAGE->get_renderer('core_grades');
|
||||
$userreportrenderer = $PAGE->get_renderer('gradereport_user');
|
||||
|
||||
$data['groupselector'] = $gradesrenderer->group_selector($course);
|
||||
$data['userselector'] = $userreportrenderer->users_selector($course, $this->userid, $this->currentgroupid);
|
||||
$data['groupselector'] = $PAGE->get_renderer('core_grades')->group_selector(get_course($courseid));
|
||||
$data['userselector'] = [
|
||||
'courseid' => $courseid,
|
||||
'content' => $userreportrenderer->users_selector(get_course($courseid), $this->userid, $this->currentgroupid)
|
||||
];
|
||||
|
||||
// Do not output the 'view mode' selector when in zero state or when the current user is viewing its own report.
|
||||
if (!is_null($this->userid) && $USER->id != $this->userid) {
|
||||
|
||||
@@ -93,6 +93,10 @@ if (has_capability('moodle/grade:viewall', $context)) {
|
||||
// Verify if we are using groups or not.
|
||||
$groupmode = groups_get_course_groupmode($course);
|
||||
$currentgroup = $gpr->groupid;
|
||||
// Conditionally add the group JS if we have groups enabled.
|
||||
if ($groupmode) {
|
||||
$PAGE->requires->js_call_amd('gradereport_user/group', 'init');
|
||||
}
|
||||
|
||||
// To make some other functions work better later.
|
||||
if (!$currentgroup) {
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use core\output\comboboxsearch;
|
||||
|
||||
/**
|
||||
* Custom renderer for the user grade report
|
||||
*
|
||||
@@ -90,47 +92,27 @@ class gradereport_user_renderer extends plugin_renderer_base {
|
||||
* @throws coding_exception
|
||||
*/
|
||||
public function users_selector(object $course, ?int $userid = null, ?int $groupid = null): string {
|
||||
|
||||
$resetlink = new moodle_url('/grade/report/user/index.php', ['id' => $course->id, 'group' => 0]);
|
||||
$data = [
|
||||
'currentvalue' => optional_param('searchvalue', '', PARAM_NOTAGS),
|
||||
'resetlink' => $resetlink->out(false),
|
||||
'name' => 'userid',
|
||||
'courseid' => $course->id,
|
||||
'groupid' => $groupid ?? 0,
|
||||
];
|
||||
|
||||
// If a particular option is selected (not in zero state).
|
||||
if (!is_null($userid)) {
|
||||
if ($userid) { // A single user selected.
|
||||
$user = core_user::get_user($userid);
|
||||
$data['selectedoption'] = [
|
||||
'image' => $this->user_picture($user, ['size' => 40, 'link' => false]),
|
||||
'text' => fullname($user),
|
||||
'additionaltext' => $user->email,
|
||||
];
|
||||
} else { // All users selected.
|
||||
// Get the total number of users.
|
||||
$defaultgradeshowactiveenrol = !empty($CFG->grade_report_showonlyactiveenrol);
|
||||
$showonlyactiveenrol = get_user_preferences('grade_report_showonlyactiveenrol', $defaultgradeshowactiveenrol);
|
||||
$showonlyactiveenrol = $showonlyactiveenrol ||
|
||||
!has_capability('moodle/course:viewsuspendedusers', context_course::instance($course->id));
|
||||
$gui = new graded_users_iterator($course, null, $groupid);
|
||||
$gui->require_active_enrolment($showonlyactiveenrol);
|
||||
$gui->init();
|
||||
$totalusersnum = 0;
|
||||
while ($userdata = $gui->next_user()) {
|
||||
$totalusersnum++;
|
||||
}
|
||||
$gui->close();
|
||||
|
||||
$data['selectedoption'] = [
|
||||
'text' => get_string('allusersnum', 'gradereport_user', $totalusersnum),
|
||||
];
|
||||
}
|
||||
|
||||
$data['userid'] = $userid;
|
||||
}
|
||||
|
||||
$searchdropdown = new comboboxsearch(
|
||||
true,
|
||||
$this->render_from_template('core_user/comboboxsearch/user_selector', $data),
|
||||
null,
|
||||
'user-search dropdown d-flex',
|
||||
null,
|
||||
'usersearchdropdown overflow-auto',
|
||||
null,
|
||||
false,
|
||||
);
|
||||
$this->page->requires->js_call_amd('gradereport_user/user', 'init');
|
||||
return $this->render_from_template('core_grades/user_selector', $data);
|
||||
return $this->render_from_template($searchdropdown->get_template(), $searchdropdown->export_for_template($this));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
Context variables required for this template:
|
||||
* generalnavselector - The data object containing the required properties to render the general navigation selector.
|
||||
* groupselector - (optional) HTML that outputs the group selector
|
||||
* userselector - (optional) HTML that outputs the user selector
|
||||
* userselector - (optional) The data object containing the required properties to render the user selector
|
||||
* viewasselector - (optional) HTML that outputs the 'view report as' selector
|
||||
|
||||
Example context (json):
|
||||
@@ -63,7 +63,10 @@
|
||||
]
|
||||
},
|
||||
"groupselector": "<div class='group-selector'></div>",
|
||||
"userselector": "<div class='user-selector'></div>",
|
||||
"userselector": {
|
||||
"content": "<div class='user-selector'></div>",
|
||||
"courseid": 25
|
||||
},
|
||||
"viewasselector": "<div class='view-user-selector'></div>"
|
||||
}
|
||||
}}
|
||||
@@ -82,8 +85,11 @@
|
||||
<div class="navitem-divider"></div>
|
||||
{{/groupselector}}
|
||||
{{#userselector}}
|
||||
<div class="navitem">
|
||||
{{{userselector}}}
|
||||
<span class="d-none" data-region="courseid" data-courseid="{{courseid}}" aria-hidden="true"></span>
|
||||
<div class="navitem flex-column">
|
||||
{{#content}}
|
||||
{{{.}}}
|
||||
{{/content}}
|
||||
</div>
|
||||
<div class="navitem-divider"></div>
|
||||
{{/userselector}}
|
||||
|
||||
@@ -27,41 +27,91 @@ Feature: Group searching functionality within the user report.
|
||||
And the "multilang" filter applies to "content and headings"
|
||||
And I am on the "C1" "Course" page logged in as "teacher1"
|
||||
And I change window size to "large"
|
||||
And I navigate to "View > User report" in the course gradebook
|
||||
|
||||
Scenario: A teacher can see the 'group' search widget only when group mode is enabled in the course
|
||||
Given I navigate to "View > User report" in the course gradebook
|
||||
And ".search-widget[data-searchtype='group']" "css_element" should exist
|
||||
Given ".groupsearchwidget" "css_element" should exist
|
||||
And I am on "Course 1" course homepage
|
||||
And I navigate to "Settings" in current page administration
|
||||
And I set the following fields to these values:
|
||||
| id_groupmode | No groups |
|
||||
And I press "Save and display"
|
||||
When I navigate to "View > User report" in the course gradebook
|
||||
Then ".search-widget[data-searchtype='group']" "css_element" should not exist
|
||||
Then ".groupsearchwidget" "css_element" should not exist
|
||||
|
||||
Scenario: A teacher can search for and find a group to find a user in
|
||||
Given I navigate to "View > User report" in the course gradebook
|
||||
And I click on ".search-widget[data-searchtype='group']" "css_element"
|
||||
And I confirm "Tutor group" in "group" search within the gradebook widget exists
|
||||
Given I confirm "Tutor group" in "group" search within the gradebook widget exists
|
||||
And I confirm "Marker group" in "group" search within the gradebook widget exists
|
||||
When I set the field "Search groups" to "tutor"
|
||||
And I wait "1" seconds
|
||||
Then I confirm "Tutor group" in "group" search within the gradebook widget exists
|
||||
And I confirm "Marker group" in "group" search within the gradebook widget does not exist
|
||||
And I click on "Tutor group" in the "group" search widget
|
||||
# The search input remains in the field on reload this is in keeping with other search implementations.
|
||||
And I click on ".groupsearchwidget" "css_element"
|
||||
And the field "Search groups" matches value "tutor"
|
||||
Then I set the field "Search groups" to "Turtle"
|
||||
And I should see "No results for \"Turtle\""
|
||||
|
||||
Scenario: A teacher can only see the group members in the 'user' search widget after selecting a group option
|
||||
Given I navigate to "View > User report" in the course gradebook
|
||||
# Confirm that all users are initially displayed in the 'user' search widget.
|
||||
Given I set the field "Search users" to "Student"
|
||||
And I confirm "Student 1" in "user" search within the gradebook widget exists
|
||||
And I confirm "Student 2" in "user" search within the gradebook widget exists
|
||||
# Select a particular group from the 'group' search widget.
|
||||
When I click on "Default group" in the "group" search widget
|
||||
# Confirm that only users which are members of the selected group are displayed in the 'user' search widget.
|
||||
And I confirm "Student 1" in "user" search within the gradebook widget exists
|
||||
And I set the field "Search users" to "Student"
|
||||
Then I confirm "Student 1" in "user" search within the gradebook widget exists
|
||||
And I confirm "Student 2" in "user" search within the gradebook widget does not exist
|
||||
And I click on "Tutor group" in the "group" search widget
|
||||
And I set the field "Search users" to "Student"
|
||||
And I confirm "Student 1" in "user" search within the gradebook widget does not exist
|
||||
And I confirm "Student 2" in "user" search within the gradebook widget does not exist
|
||||
And I click on "All participants" in the "group" search widget
|
||||
And I set the field "Search users" to "Student"
|
||||
And I confirm "Student 1" in "user" search within the gradebook widget exists
|
||||
And I confirm "Student 2" in "user" search within the gradebook widget exists
|
||||
|
||||
@accessibility
|
||||
Scenario: A teacher can set focus and search using the input with a keyboard
|
||||
# Basic tests for the page.
|
||||
Given I click on ".groupsearchwidget" "css_element"
|
||||
And the page should meet accessibility standards
|
||||
And the page should meet "wcag131, wcag141, wcag412" accessibility standards
|
||||
And the page should meet accessibility standards with "wcag131, wcag141, wcag412" extra tests
|
||||
# Move onto general keyboard navigation testing.
|
||||
And I click on "Search groups" "field"
|
||||
And I wait until "Default group" "option_role" exists
|
||||
And I press the down key
|
||||
And the focused element is "All participants" "option_role"
|
||||
And I press the end key
|
||||
And the focused element is "Tutor group" "option_role"
|
||||
And I press the home key
|
||||
And the focused element is "All participants" "option_role"
|
||||
And I press the up key
|
||||
And the focused element is "Tutor group" "option_role"
|
||||
And I press the down key
|
||||
And the focused element is "All participants" "option_role"
|
||||
And I press the escape key
|
||||
And the focused element is "Search groups" "field"
|
||||
Then I set the field "Search groups" to "Goodmeme"
|
||||
And I wait until "Tutor group" "option_role" does not exist
|
||||
And I press the down key
|
||||
And the focused element is "Search groups" "field"
|
||||
|
||||
And I navigate to "View > User report" in the course gradebook
|
||||
And I click on ".groupsearchwidget" "css_element"
|
||||
And I set the field "Search groups" to "Tutor"
|
||||
And I wait until "All participants" "option_role" does not exist
|
||||
And I press the down key
|
||||
And the focused element is "Tutor group" "option_role"
|
||||
|
||||
# Lets check the tabbing order.
|
||||
And I set the field "Search groups" to "Marker"
|
||||
And I wait until "Marker group" "option_role" exists
|
||||
And I press the tab key
|
||||
And the focused element is "Clear search input" "button"
|
||||
And I press the enter key
|
||||
And I wait until the page is ready
|
||||
And ".groupsearchwidget" "css_element" should exist
|
||||
|
||||
@@ -4,29 +4,296 @@ Feature: Within the User report, a teacher can search for users.
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | category | groupmode |
|
||||
| Course 1 | C1 | 0 | 1 |
|
||||
| Course 2 | C2 | 0 | 0 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email | idnumber |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com | t1 |
|
||||
| student1 | Student | 1 | student1@example.com | s1 |
|
||||
| student2 | Student | 2 | student2@example.com | s2 |
|
||||
| student32 | Student | 32 | student32@example.com | s32 |
|
||||
| username | firstname | lastname | email | idnumber | phone1 | phone2 | department | institution | city | country |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com | t1 | 1234567892 | 1234567893 | ABC1 | ABCD | Perth | AU |
|
||||
| student1 | Student | 1 | student1@example.com | s1 | 3213078612 | 8974325612 | ABC1 | ABCD | Hanoi | VN |
|
||||
| student2 | Dummy | User | student2@example.com | s2 | 4365899871 | 7654789012 | ABC2 | ABCD | Tokyo | JP |
|
||||
| student3 | User | Example | student3@example.com | s3 | 3243249087 | 0875421745 | ABC2 | ABCD | Olney | GB |
|
||||
| student4 | User | Test | student4@example.com | s4 | 0987532523 | 2149871323 | ABC3 | ABCD | Tokyo | JP |
|
||||
| student5 | Turtle | Manatee | student5@example.com | s5 | 1239087780 | 9873623589 | ABC3 | ABCD | Perth | AU |
|
||||
# Note: Add groups etc so we can test that the search ignores those filters as well if we go down the filter dataset path.
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
| student2 | C1 | student |
|
||||
| student32 | C1 | student |
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| teacher1 | C2 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
| student2 | C1 | student |
|
||||
| student3 | C1 | student |
|
||||
| student4 | C1 | student |
|
||||
| student5 | C1 | student |
|
||||
And the following "activities" exist:
|
||||
| activity | course | idnumber | name |
|
||||
| assign | C1 | a1 | Test assignment one |
|
||||
And the following config values are set as admin:
|
||||
| showuseridentity | idnumber,email,city,country,phone1,phone2,department,institution |
|
||||
And I am on the "Course 1" "Course" page logged in as "teacher1"
|
||||
And I change window size to "large"
|
||||
And I navigate to "View > User report" in the course gradebook
|
||||
|
||||
Scenario: A teacher can search for and find a user to view
|
||||
Given I navigate to "View > User report" in the course gradebook
|
||||
When I click on ".search-widget[data-searchtype='user']" "css_element"
|
||||
Scenario: A teacher can view and trigger the user search
|
||||
# Check the placeholder text
|
||||
Given I should see "Search users"
|
||||
# Confirm the search is currently inactive and results are unfiltered.
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Turtle Manatee |
|
||||
| Student 1 |
|
||||
| User Example |
|
||||
| User Test |
|
||||
| Dummy User |
|
||||
And the following should not exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Teacher 1 |
|
||||
When I set the field "Search users" to "Turtle"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And I confirm "Turtle Manatee" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Example" in "user" search within the gradebook widget does not exist
|
||||
And I click on "Turtle Manatee" "list_item"
|
||||
# Business case: This will trigger a page reload and can not dynamically update the table.
|
||||
And I wait until the page is ready
|
||||
Then the following should exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Turtle Manatee |
|
||||
And the following should not exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Teacher 1 |
|
||||
| Student 1 |
|
||||
| User Example |
|
||||
| User Test |
|
||||
| Dummy User |
|
||||
And I set the field "Search users" to "Turt"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And I click on "Clear search input" "button" in the ".user-search" "css_element"
|
||||
And "View all results (5)" "option_role" should not be visible
|
||||
|
||||
Scenario: A teacher can search the user report to find specified users
|
||||
# Case: Standard search.
|
||||
Given I click on "Dummy" in the "user" search widget
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Turtle Manatee |
|
||||
And the following should not exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Teacher 1 |
|
||||
| Student 1 |
|
||||
| User Example |
|
||||
| User Test |
|
||||
| Dummy User |
|
||||
|
||||
# Case: No users found.
|
||||
When I set the field "Search users" to "Plagiarism"
|
||||
And I should see "No results for \"Plagiarism\""
|
||||
# Table remains unchanged as the user had no results to select from the dropdown.
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Turtle Manatee |
|
||||
And the following should not exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Teacher 1 |
|
||||
| Student 1 |
|
||||
| User Example |
|
||||
| User Test |
|
||||
| Dummy User |
|
||||
|
||||
# Case: Multiple users found and select only one result.
|
||||
Then I set the field "Search users" to "User"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And I confirm "Dummy User" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Example" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Test" in "user" search within the gradebook widget exists
|
||||
And I confirm "Turtle Manatee" in "user" search within the gradebook widget does not exist
|
||||
# Check if the matched field names (by lines) includes some identifiable info to help differentiate similar users.
|
||||
And I confirm "User (student2@example.com)" in "user" search within the gradebook widget exists
|
||||
And I confirm "User (student3@example.com)" in "user" search within the gradebook widget exists
|
||||
And I confirm "User (student4@example.com)" in "user" search within the gradebook widget exists
|
||||
And I click on "Dummy User" "list_item"
|
||||
And I wait until the page is ready
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Dummy User |
|
||||
And the following should not exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Teacher 1 |
|
||||
| Student 1 |
|
||||
| User Example |
|
||||
| User Test |
|
||||
| Turtle Manatee |
|
||||
|
||||
# Business case: When searching with multiple partial matches, show the matches in the dropdown + a "View all results for (Bob)"
|
||||
# Business case cont. When pressing enter with multiple partial matches, behave like when you select the "View all results for (Bob)"
|
||||
# Case: Multiple users found and select all partial matches.
|
||||
And I set the field "Search users" to "User"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And I click on "View all results (5)" "option_role"
|
||||
And I wait until the page is ready
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Dummy User |
|
||||
| User Example |
|
||||
| User Test |
|
||||
And the following should not exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Teacher 1 |
|
||||
| Student 1 |
|
||||
| Turtle Manatee |
|
||||
And I click on "Clear" "link" in the ".user-search" "css_element"
|
||||
And I wait until the page is ready
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Turtle Manatee |
|
||||
| Student 1 |
|
||||
| User Example |
|
||||
| User Test |
|
||||
| Dummy User |
|
||||
|
||||
# Case: No users enrolled.
|
||||
And I am on the "Course 2" "Course" page
|
||||
And I navigate to "View > User report" in the course gradebook
|
||||
And I set the field "Search users" to "a"
|
||||
And I should see "No results for \"a\""
|
||||
|
||||
Scenario: A teacher can quickly tell that a search is active on the current table
|
||||
Given I click on "Turtle" in the "user" search widget
|
||||
# The search input remains in the field on reload this is in keeping with other search implementations.
|
||||
When the field "Search users" matches value "Turtle"
|
||||
And I wait until "View all results (5)" "link" does not exist
|
||||
# Test if we can then further retain the turtle result set and further filter from there.
|
||||
Then I set the field "Search users" to "Turtle plagiarism"
|
||||
And "Turtle Manatee" "list_item" should not exist
|
||||
And I should see "No results for \"Turtle plagiarism\""
|
||||
|
||||
Scenario: A teacher can search for values besides the users' name
|
||||
Given I set the field "Search users" to "student5@example.com"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And "Turtle Manatee" "list_item" should exist
|
||||
And I set the field "Search users" to "@example.com"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
# Note: All learners match this email & showing emails is current default.
|
||||
And I confirm "Dummy User" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Example" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Test" in "user" search within the gradebook widget exists
|
||||
And I confirm "Student 1" in "user" search within the gradebook widget exists
|
||||
And I confirm "Turtle Manatee" in "user" search within the gradebook widget exists
|
||||
|
||||
# Search on the country field.
|
||||
When I set the field "Search users" to "JP"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And I wait until "Turtle Manatee" "list_item" does not exist
|
||||
And I confirm "Dummy User" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Test" in "user" search within the gradebook widget exists
|
||||
|
||||
# Search on the city field.
|
||||
And I set the field "Search users" to "Hanoi"
|
||||
And I wait until "User Test" "list_item" does not exist
|
||||
Then I confirm "Student 1" in "user" search within the gradebook widget exists
|
||||
And I confirm "Student 2" in "user" search within the gradebook widget exists
|
||||
And I confirm "Student 32" in "user" search within the gradebook widget exists
|
||||
And I set the field "Search users" to "2"
|
||||
|
||||
# Search on the institution field.
|
||||
And I set the field "Search users" to "ABCD"
|
||||
And I wait until "Dummy User" "list_item" exists
|
||||
And I confirm "User Example" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Test" in "user" search within the gradebook widget exists
|
||||
And I confirm "Student 1" in "user" search within the gradebook widget exists
|
||||
And I confirm "Turtle Manatee" in "user" search within the gradebook widget exists
|
||||
|
||||
# Search on the department field.
|
||||
And I set the field "Search users" to "ABC3"
|
||||
And I wait until "User Example" "list_item" does not exist
|
||||
And I confirm "User Test" in "user" search within the gradebook widget exists
|
||||
And I confirm "Turtle Manatee" in "user" search within the gradebook widget exists
|
||||
|
||||
# Search on the phone1 field.
|
||||
And I set the field "Search users" to "4365899871"
|
||||
And I wait until "User Test" "list_item" does not exist
|
||||
And I confirm "Dummy User" in "user" search within the gradebook widget exists
|
||||
|
||||
# Search on the phone2 field.
|
||||
And I set the field "Search users" to "2149871323"
|
||||
And I wait until "Dummy User" "list_item" does not exist
|
||||
And I confirm "User Test" in "user" search within the gradebook widget exists
|
||||
|
||||
# Search on the institution field then press enter to show the record set.
|
||||
And I set the field "Search users" to "ABC"
|
||||
And I wait until "Turtle Manatee" "list_item" exists
|
||||
And I confirm "Dummy User" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Example" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Test" in "user" search within the gradebook widget exists
|
||||
And I confirm "Student 1" in "user" search within the gradebook widget exists
|
||||
And I press the enter key
|
||||
And I wait until the page is ready
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Student 1 |
|
||||
| User Example |
|
||||
| User Test |
|
||||
| Dummy User |
|
||||
| Turtle Manatee |
|
||||
And the following should not exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Teacher 1 |
|
||||
|
||||
@accessibility
|
||||
Scenario: A teacher can set focus and search using the input are with a keyboard
|
||||
Given I set the field "Search users" to "ABC"
|
||||
# Basic tests for the page.
|
||||
And the page should meet accessibility standards
|
||||
And the page should meet "wcag131, wcag141, wcag412" accessibility standards
|
||||
And the page should meet accessibility standards with "wcag131, wcag141, wcag412" extra tests
|
||||
# Move onto general keyboard navigation testing.
|
||||
When I wait until "Turtle Manatee" "option_role" exists
|
||||
And I press the down key
|
||||
And the focused element is "Student 1" "option_role"
|
||||
And I press the end key
|
||||
And the focused element is "View all results (5)" "option_role"
|
||||
And I press the home key
|
||||
And the focused element is "Student 1" "option_role"
|
||||
And I press the up key
|
||||
And the focused element is "View all results (5)" "option_role"
|
||||
And I press the down key
|
||||
And the focused element is "Student 1" "option_role"
|
||||
And I press the escape key
|
||||
And the focused element is "Search users" "field"
|
||||
Then I set the field "Search users" to "Goodmeme"
|
||||
And I press the down key
|
||||
And the focused element is "Search users" "field"
|
||||
|
||||
And I navigate to "View > User report" in the course gradebook
|
||||
And I set the field "Search users" to "ABC"
|
||||
And I wait until "Turtle Manatee" "option_role" exists
|
||||
And I press the down key
|
||||
And the focused element is "Student 1" "option_role"
|
||||
|
||||
# Lets check the tabbing order.
|
||||
And I set the field "Search users" to "ABC"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And I press the tab key
|
||||
And the focused element is "Clear search input" "button" in the ".user-search" "css_element"
|
||||
And I press the tab key
|
||||
And the focused element is "View all results (5)" "option_role"
|
||||
And I press the tab key
|
||||
And ".groupsearchwidget" "css_element" should exist
|
||||
# Ensure we can interact with the input & clear search options with the keyboard.
|
||||
# Space & Enter have the same handling for triggering the two functionalities.
|
||||
And I set the field "Search users" to "User"
|
||||
And I press the enter key
|
||||
And I wait to be redirected
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Dummy User |
|
||||
| User Example |
|
||||
| User Test |
|
||||
And the following should not exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Teacher 1 |
|
||||
| Student 1 |
|
||||
| Turtle Manatee |
|
||||
# Sometimes with behat we get unattached nodes causing spurious failures.
|
||||
And I wait "1" seconds
|
||||
And I confirm "Student 2" in "user" search within the gradebook widget exists
|
||||
And I confirm "Student 32" in "user" search within the gradebook widget exists
|
||||
And I confirm "Student 1" in "user" search within the gradebook widget does not exist
|
||||
And I set the field "Search users" to "ABC"
|
||||
And I wait until "Turtle Manatee" "option_role" exists
|
||||
And I press the tab key
|
||||
And the focused element is "Clear search input" "button" in the ".user-search" "css_element"
|
||||
And I press the enter key
|
||||
And I wait until the page is ready
|
||||
And I confirm "Turtle Manatee" in "user" search within the gradebook widget does not exist
|
||||
|
||||
@@ -11,13 +11,12 @@ Feature: We can use the user report
|
||||
Scenario: Verify we can view a user grade report with no users enrolled.
|
||||
Given I log in as "admin"
|
||||
And I am on "Course 1" course homepage
|
||||
And I navigate to "View > User report" in the course gradebook
|
||||
And I click on "All users (0)" in the "user" search widget
|
||||
When I navigate to "View > User report" in the course gradebook
|
||||
Then I should see "There are no students enrolled in this course."
|
||||
|
||||
Scenario: Teacher sees his last viewed user report when navigating back to the gradebook user report.
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
| teacher2 | Teacher | 2 | teacher2@example.com |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
|
||||
Reference in New Issue
Block a user