MDL-78885 comboboxsearch: Points from review

This commit is contained in:
Mathew May
2024-03-22 05:50:06 +11:00
committed by Shamim Rezaie
parent 2ac9dc9108
commit 68bf0f5b77
44 changed files with 120 additions and 131 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3
View File
@@ -40,6 +40,7 @@ export default class GradeItemSearch extends search_combobox {
};
const component = document.querySelector(this.componentSelector());
this.courseID = component.querySelector(this.selectors.courseid).dataset.courseid;
this.instance = this.component.querySelector(this.selectors.instance).dataset.instance;
const searchValueElement = this.component.querySelector(`#${this.searchInput.dataset.inputElement}`);
searchValueElement.addEventListener('change', () => {
@@ -102,6 +103,7 @@ export default class GradeItemSearch extends search_combobox {
*/
async renderDropdown() {
const {html, js} = await renderForPromise('core/local/comboboxsearch/resultset', {
instance: this.instance,
results: this.getMatchedResults(),
hasresults: this.getMatchedResults().length > 0,
searchterm: this.getSearchTerm(),
@@ -233,6 +235,7 @@ export default class GradeItemSearch extends search_combobox {
/**
* Build up the view all link that is dedicated to a particular result.
* We will call this function when a user interacts with the combobox to redirect them to show their results in the page.
*
* @param {Number} gradeID The ID of the grade item selected.
*/
+1
View File
@@ -65,6 +65,7 @@ class core_grades_renderer extends plugin_renderer_base {
$sbody = $this->render_from_template('core_group/comboboxsearch/searchbody', [
'courseid' => $course->id,
'currentvalue' => optional_param('groupsearchvalue', '', PARAM_NOTAGS),
'instance' => rand(),
]);
$label = $groupmode == VISIBLEGROUPS ? get_string('selectgroupsvisible') : get_string('selectgroupsseparate');
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +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 grader report.\n *\n * @module gradereport_grader/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/grader/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":"2WAyBqBA,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,iCAAkC,CACrDC,GAAIZ,KAAKM,SACTO,iBAAkBb,KAAKc,gBACvBC,MAAON,UACR"}
{"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 grader report.\n *\n * @module gradereport_grader/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 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/grader/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":"2WAyBqBA,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,iCAAkC,CACrDC,GAAIZ,KAAKM,SACTO,iBAAkBb,KAAKc,gBACvBC,MAAON,UACR"}
@@ -1 +1 @@
{"version":3,"file":"user.min.js","sources":["../src/user.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 learners within the grader report.\n *\n * @module gradereport_grader/user\n * @copyright 2023 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport UserSearch from 'core_user/comboboxsearch/user';\nimport Url from 'core/url';\nimport * as Repository from 'gradereport_grader/local/user/repository';\n\n// Define our standard lookups.\nconst selectors = {\n component: '.user-search',\n courseid: '[data-region=\"courseid\"]',\n};\nconst component = document.querySelector(selectors.component);\nconst courseID = component.querySelector(selectors.courseid).dataset.courseid;\n\nexport default class User extends UserSearch {\n\n constructor() {\n super();\n }\n\n static init() {\n return new User();\n }\n\n /**\n * Get the data we will be searching against in this component.\n *\n * @returns {Promise<*>}\n */\n fetchDataset() {\n return Repository.userFetch(courseID).then((r) => r.users);\n }\n\n /**\n * Build up the view all link.\n *\n * @returns {string|*}\n */\n selectAllResultsLink() {\n return Url.relativeUrl('/grade/report/grader/index.php', {\n id: courseID,\n gpr_search: this.getSearchTerm()\n }, false);\n }\n\n /**\n * Build up the view all link that is dedicated to a particular result.\n *\n * @param {Number} userID The ID of the user selected.\n * @returns {string|*}\n */\n selectOneLink(userID) {\n return Url.relativeUrl('/grade/report/grader/index.php', {\n id: courseID,\n gpr_search: this.getSearchTerm(),\n gpr_userid: userID,\n }, false);\n }\n}\n"],"names":["selectors","courseID","document","querySelector","dataset","courseid","User","UserSearch","constructor","fetchDataset","Repository","userFetch","then","r","users","selectAllResultsLink","Url","relativeUrl","id","gpr_search","this","getSearchTerm","selectOneLink","userID","gpr_userid"],"mappings":";;;;;;;q0BA2BMA,oBACS,eADTA,mBAEQ,2BAGRC,SADYC,SAASC,cAAcH,qBACdG,cAAcH,oBAAoBI,QAAQC,eAEhDC,aAAaC,cAE9BC,2CAKW,IAAIF,KAQfG,sBACWC,WAAWC,UAAUV,UAAUW,MAAMC,GAAMA,EAAEC,QAQxDC,8BACWC,aAAIC,YAAY,iCAAkC,CACrDC,GAAIjB,SACJkB,WAAYC,KAAKC,kBAClB,GASPC,cAAcC,eACHP,aAAIC,YAAY,iCAAkC,CACrDC,GAAIjB,SACJkB,WAAYC,KAAKC,gBACjBG,WAAYD,SACb"}
{"version":3,"file":"user.min.js","sources":["../src/user.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 learners within the grader report.\n *\n * @module gradereport_grader/user\n * @copyright 2023 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport UserSearch from 'core_user/comboboxsearch/user';\nimport Url from 'core/url';\nimport * as Repository from 'gradereport_grader/local/user/repository';\n\n// Define our standard lookups.\nconst selectors = {\n component: '.user-search',\n courseid: '[data-region=\"courseid\"]',\n};\nconst component = document.querySelector(selectors.component);\nconst courseID = component.querySelector(selectors.courseid).dataset.courseid;\n\nexport default class User extends UserSearch {\n\n constructor() {\n super();\n }\n\n static init() {\n return new User();\n }\n\n /**\n * Get the data we will be searching against in this component.\n *\n * @returns {Promise<*>}\n */\n fetchDataset() {\n return Repository.userFetch(courseID).then((r) => r.users);\n }\n\n /**\n * Build up the view all link.\n *\n * @returns {string|*}\n */\n selectAllResultsLink() {\n return Url.relativeUrl('/grade/report/grader/index.php', {\n id: courseID,\n gpr_search: this.getSearchTerm()\n }, false);\n }\n\n /**\n * Build up the link that is dedicated to a particular result.\n *\n * @param {Number} userID The ID of the user selected.\n * @returns {string|*}\n */\n selectOneLink(userID) {\n return Url.relativeUrl('/grade/report/grader/index.php', {\n id: courseID,\n gpr_search: this.getSearchTerm(),\n gpr_userid: userID,\n }, false);\n }\n}\n"],"names":["selectors","courseID","document","querySelector","dataset","courseid","User","UserSearch","constructor","fetchDataset","Repository","userFetch","then","r","users","selectAllResultsLink","Url","relativeUrl","id","gpr_search","this","getSearchTerm","selectOneLink","userID","gpr_userid"],"mappings":";;;;;;;q0BA2BMA,oBACS,eADTA,mBAEQ,2BAGRC,SADYC,SAASC,cAAcH,qBACdG,cAAcH,oBAAoBI,QAAQC,eAEhDC,aAAaC,cAE9BC,2CAKW,IAAIF,KAQfG,sBACWC,WAAWC,UAAUV,UAAUW,MAAMC,GAAMA,EAAEC,QAQxDC,8BACWC,aAAIC,YAAY,iCAAkC,CACrDC,GAAIjB,SACJkB,WAAYC,KAAKC,kBAClB,GASPC,cAAcC,eACHP,aAAIC,YAAY,iCAAkC,CACrDC,GAAIjB,SACJkB,WAAYC,KAAKC,gBACjBG,WAAYD,SACb"}
+2
View File
@@ -478,6 +478,7 @@ export default class ColumnSearch extends search_combobox {
// Update the collapsed button pill.
this.countUpdate();
const {html, js} = await renderForPromise('gradereport_grader/collapse/collapsebody', {
'instance': this.instance,
'results': this.getMatchedResults(),
'userid': this.userID,
});
@@ -500,6 +501,7 @@ export default class ColumnSearch extends search_combobox {
*/
async renderDropdown() {
const {html, js} = await renderForPromise('gradereport_grader/collapse/collapseresults', {
instance: this.instance,
'results': this.getMatchedResults(),
'searchTerm': this.getSearchTerm(),
});
+1 -1
View File
@@ -43,7 +43,7 @@ export default class Group extends GroupSearch {
}
/**
* Build up the view all link that is dedicated to a particular result.
* Build up the link that is dedicated to a particular result.
*
* @param {Number} groupID The ID of the group selected.
* @returns {string|*}
+1 -1
View File
@@ -64,7 +64,7 @@ export default class User extends UserSearch {
}
/**
* Build up the view all link that is dedicated to a particular result.
* Build up the link that is dedicated to a particular result.
*
* @param {Number} userID The ID of the user selected.
* @returns {string|*}
@@ -116,6 +116,7 @@ class action_bar extends \core_grades\output\action_bar {
$searchinput = $OUTPUT->render_from_template('core_user/comboboxsearch/user_selector', [
'currentvalue' => $this->usersearch,
'courseid' => $courseid,
'instance' => rand(),
'resetlink' => $resetlink->out(false),
'group' => 0,
'name' => 'usersearch',
@@ -18,6 +18,7 @@
Example context (json):
{
"instance": 25,
"results": [
{
"name": "42",
@@ -43,7 +44,7 @@
<form class="columnsdropdownform flex-column h-100">
<fieldset>
<legend class="sr-only">{{#str}} aria:dropdowncolumns, gradereport_grader {{/str}}</legend>
<ul id="collapse-listbox" class="searchresultitemscontainer overflow-auto py-2 px-1 list-group mx-0 text-truncate" data-region="search-result-items-container">
<ul id="collapse-{{instance}}-listbox" class="searchresultitemscontainer overflow-auto py-2 px-1 list-group mx-0 text-truncate" data-region="search-result-items-container">
{{>gradereport_grader/collapse/collapseresults}}
</ul>
</fieldset>
@@ -1 +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 singleview report.\n *\n * @module gradereport_singleview/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 item = null;\n\n /**\n * Construct the class.\n *\n * @param {string} item The page type we are currently on.\n */\n constructor(item) {\n super();\n this.item = item;\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 /**\n * Allow the class to be invoked via PHP.\n *\n * @param {string} item The page type we are currently on.\n * @returns {Group}\n */\n static init(item) {\n return new Group(item);\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/singleview/index.php', {\n id: this.courseID,\n groupsearchvalue: this.getSearchTerm(),\n group: groupID,\n item: this.item\n }, false);\n }\n}\n"],"names":["Group","GroupSearch","constructor","item","selectors","this","courseid","component","document","querySelector","componentSelector","courseID","dataset","selectOneLink","groupID","Url","relativeUrl","id","groupsearchvalue","getSearchTerm","group"],"mappings":"mhBAyBqBA,cAAcC,eAW/BC,YAAYC,kFAPL,WASEA,KAAOA,UAGPC,UAAY,IAAIC,KAAKD,UACtBE,SAAU,kCAERC,UAAYC,SAASC,cAAcJ,KAAKK,0BACzCC,SAAWJ,UAAUE,cAAcJ,KAAKD,UAAUE,UAAUM,QAAQN,qBASjEH,aACD,IAAIH,MAAMG,MASrBU,cAAcC,gBACHC,aAAIC,YAAY,qCAAsC,CACzDC,GAAIZ,KAAKM,SACTO,iBAAkBb,KAAKc,gBACvBC,MAAON,QACPX,KAAME,KAAKF,OACZ"}
{"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 singleview report.\n *\n * @module gradereport_singleview/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 item = null;\n\n /**\n * Construct the class.\n *\n * @param {string} item The page type we are currently on.\n */\n constructor(item) {\n super();\n this.item = item;\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 /**\n * Allow the class to be invoked via PHP.\n *\n * @param {string} item The page type we are currently on.\n * @returns {Group}\n */\n static init(item) {\n return new Group(item);\n }\n\n /**\n * Build up the 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/singleview/index.php', {\n id: this.courseID,\n groupsearchvalue: this.getSearchTerm(),\n group: groupID,\n item: this.item\n }, false);\n }\n}\n"],"names":["Group","GroupSearch","constructor","item","selectors","this","courseid","component","document","querySelector","componentSelector","courseID","dataset","selectOneLink","groupID","Url","relativeUrl","id","groupsearchvalue","getSearchTerm","group"],"mappings":"mhBAyBqBA,cAAcC,eAW/BC,YAAYC,kFAPL,WASEA,KAAOA,UAGPC,UAAY,IAAIC,KAAKD,UACtBE,SAAU,kCAERC,UAAYC,SAASC,cAAcJ,KAAKK,0BACzCC,SAAWJ,UAAUE,cAAcJ,KAAKD,UAAUE,UAAUM,QAAQN,qBASjEH,aACD,IAAIH,MAAMG,MASrBU,cAAcC,gBACHC,aAAIC,YAAY,qCAAsC,CACzDC,GAAIZ,KAAKM,SACTO,iBAAkBb,KAAKc,gBACvBC,MAAON,QACPX,KAAME,KAAKF,OACZ"}
+1 -1
View File
@@ -5,6 +5,6 @@ define("gradereport_singleview/user",["exports","core_user/comboboxsearch/user",
* @module gradereport_singleview/user
* @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.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,searchterm:this.getSearchTerm()});(0,_templates.replaceNodeContents)(this.getHTMLElements().searchDropdown,html,js),this.searchInput.removeAttribute("aria-activedescendant")}selectAllResultsLink(){return null}selectOneLink(userID){return _url.default.relativeUrl("/grade/report/singleview/index.php",{id:this.courseID,searchvalue:this.getSearchTerm(),item:"user",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}));
*/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",{instance:this.instance,users:this.getMatchedResults().slice(0,5),hasresults:this.getMatchedResults().length>0,searchterm:this.getSearchTerm()});(0,_templates.replaceNodeContents)(this.getHTMLElements().searchDropdown,html,js),this.searchInput.removeAttribute("aria-activedescendant")}selectAllResultsLink(){return null}selectOneLink(userID){return _url.default.relativeUrl("/grade/report/singleview/index.php",{id:this.courseID,searchvalue:this.getSearchTerm(),item:"user",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
@@ -1 +1 @@
{"version":3,"file":"user.min.js","sources":["../src/user.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 learners within the singleview report.\n *\n * @module gradereport_singleview/user\n * @copyright 2023 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport UserSearch from 'core_user/comboboxsearch/user';\nimport Url from 'core/url';\nimport {renderForPromise, replaceNodeContents} from 'core/templates';\nimport * as Repository from 'core_grades/searchwidget/repository';\n\nexport default class User extends UserSearch {\n\n constructor() {\n super();\n }\n\n static init() {\n return new User();\n }\n\n /**\n * Build the content then replace the node.\n */\n async renderDropdown() {\n const {html, js} = await renderForPromise('core_user/comboboxsearch/resultset', {\n users: this.getMatchedResults().slice(0, 5),\n hasresults: this.getMatchedResults().length > 0,\n searchterm: this.getSearchTerm(),\n });\n replaceNodeContents(this.getHTMLElements().searchDropdown, html, js);\n // Remove aria-activedescendant when the available options change.\n this.searchInput.removeAttribute('aria-activedescendant');\n }\n\n /**\n * Stub out default required function unused here.\n * @returns {null}\n */\n selectAllResultsLink() {\n return null;\n }\n\n /**\n * Build up the view all link that is dedicated to a particular result.\n *\n * @param {Number} userID The ID of the user selected.\n * @returns {string|*}\n */\n selectOneLink(userID) {\n return Url.relativeUrl('/grade/report/singleview/index.php', {\n id: this.courseID,\n searchvalue: this.getSearchTerm(),\n item: 'user',\n userid: userID,\n }, false);\n }\n\n /**\n * Get the data we will be searching against in this component.\n *\n * @returns {Promise<*>}\n */\n fetchDataset() {\n // Small typing checks as sometimes groups don't exist therefore the element returns a empty string.\n const gts = typeof (this.groupID) === \"string\" && this.groupID === '' ? 0 : this.groupID;\n return Repository.userFetch(this.courseID, gts).then((r) => r.users);\n }\n}\n"],"names":["User","UserSearch","constructor","html","js","users","this","getMatchedResults","slice","hasresults","length","searchterm","getSearchTerm","getHTMLElements","searchDropdown","searchInput","removeAttribute","selectAllResultsLink","selectOneLink","userID","Url","relativeUrl","id","courseID","searchvalue","item","userid","fetchDataset","gts","groupID","Repository","userFetch","then","r"],"mappings":";;;;;;;q0BA2BqBA,aAAaC,cAE9BC,2CAKW,IAAIF,kCAOLG,KAACA,KAADC,GAAOA,UAAY,+BAAiB,qCAAsC,CAC5EC,MAAOC,KAAKC,oBAAoBC,MAAM,EAAG,GACzCC,WAAYH,KAAKC,oBAAoBG,OAAS,EAC9CC,WAAYL,KAAKM,qDAEDN,KAAKO,kBAAkBC,eAAgBX,KAAMC,SAE5DW,YAAYC,gBAAgB,yBAOrCC,8BACW,KASXC,cAAcC,eACHC,aAAIC,YAAY,qCAAsC,CACzDC,GAAIhB,KAAKiB,SACTC,YAAalB,KAAKM,gBAClBa,KAAM,OACNC,OAAQP,SACT,GAQPQ,qBAEUC,IAAgC,iBAAlBtB,KAAKuB,SAA0C,KAAjBvB,KAAKuB,QAAiB,EAAIvB,KAAKuB,eAC1EC,WAAWC,UAAUzB,KAAKiB,SAAUK,KAAKI,MAAMC,GAAMA,EAAE5B"}
{"version":3,"file":"user.min.js","sources":["../src/user.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 learners within the singleview report.\n *\n * @module gradereport_singleview/user\n * @copyright 2023 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport UserSearch from 'core_user/comboboxsearch/user';\nimport Url from 'core/url';\nimport {renderForPromise, replaceNodeContents} from 'core/templates';\nimport * as Repository from 'core_grades/searchwidget/repository';\n\nexport default class User extends UserSearch {\n\n constructor() {\n super();\n }\n\n static init() {\n return new User();\n }\n\n /**\n * Build the content then replace the node.\n */\n async renderDropdown() {\n const {html, js} = await renderForPromise('core_user/comboboxsearch/resultset', {\n instance: this.instance,\n users: this.getMatchedResults().slice(0, 5),\n hasresults: this.getMatchedResults().length > 0,\n searchterm: this.getSearchTerm(),\n });\n replaceNodeContents(this.getHTMLElements().searchDropdown, html, js);\n // Remove aria-activedescendant when the available options change.\n this.searchInput.removeAttribute('aria-activedescendant');\n }\n\n /**\n * Stub out default required function unused here.\n * @returns {null}\n */\n selectAllResultsLink() {\n return null;\n }\n\n /**\n * Build up the view all link that is dedicated to a particular result.\n *\n * @param {Number} userID The ID of the user selected.\n * @returns {string|*}\n */\n selectOneLink(userID) {\n return Url.relativeUrl('/grade/report/singleview/index.php', {\n id: this.courseID,\n searchvalue: this.getSearchTerm(),\n item: 'user',\n userid: userID,\n }, false);\n }\n\n /**\n * Get the data we will be searching against in this component.\n *\n * @returns {Promise<*>}\n */\n fetchDataset() {\n // Small typing checks as sometimes groups don't exist therefore the element returns a empty string.\n const gts = typeof (this.groupID) === \"string\" && this.groupID === '' ? 0 : this.groupID;\n return Repository.userFetch(this.courseID, gts).then((r) => r.users);\n }\n}\n"],"names":["User","UserSearch","constructor","html","js","instance","this","users","getMatchedResults","slice","hasresults","length","searchterm","getSearchTerm","getHTMLElements","searchDropdown","searchInput","removeAttribute","selectAllResultsLink","selectOneLink","userID","Url","relativeUrl","id","courseID","searchvalue","item","userid","fetchDataset","gts","groupID","Repository","userFetch","then","r"],"mappings":";;;;;;;q0BA2BqBA,aAAaC,cAE9BC,2CAKW,IAAIF,kCAOLG,KAACA,KAADC,GAAOA,UAAY,+BAAiB,qCAAsC,CAC5EC,SAAUC,KAAKD,SACfE,MAAOD,KAAKE,oBAAoBC,MAAM,EAAG,GACzCC,WAAYJ,KAAKE,oBAAoBG,OAAS,EAC9CC,WAAYN,KAAKO,qDAEDP,KAAKQ,kBAAkBC,eAAgBZ,KAAMC,SAE5DY,YAAYC,gBAAgB,yBAOrCC,8BACW,KASXC,cAAcC,eACHC,aAAIC,YAAY,qCAAsC,CACzDC,GAAIjB,KAAKkB,SACTC,YAAanB,KAAKO,gBAClBa,KAAM,OACNC,OAAQP,SACT,GAQPQ,qBAEUC,IAAgC,iBAAlBvB,KAAKwB,SAA0C,KAAjBxB,KAAKwB,QAAiB,EAAIxB,KAAKwB,eAC1EC,WAAWC,UAAU1B,KAAKkB,SAAUK,KAAKI,MAAMC,GAAMA,EAAE3B"}
+1 -1
View File
@@ -57,7 +57,7 @@ export default class Group extends GroupSearch {
}
/**
* Build up the view all link that is dedicated to a particular result.
* Build up the link that is dedicated to a particular result.
*
* @param {Number} groupID The ID of the group selected.
* @returns {string|*}
+1
View File
@@ -40,6 +40,7 @@ export default class User extends UserSearch {
*/
async renderDropdown() {
const {html, js} = await renderForPromise('core_user/comboboxsearch/resultset', {
instance: this.instance,
users: this.getMatchedResults().slice(0, 5),
hasresults: this.getMatchedResults().length > 0,
searchterm: this.getSearchTerm(),
+3
View File
@@ -58,6 +58,7 @@ class gradereport_singleview_renderer extends plugin_renderer_base {
$data = [
'currentvalue' => $currentvalue,
'courseid' => $course->id,
'instance' => rand(),
'group' => $groupid ?? 0,
'resetlink' => $resetlink->out(false),
'name' => 'userid',
@@ -88,6 +89,7 @@ class gradereport_singleview_renderer extends plugin_renderer_base {
$data = [
'name' => 'itemid',
'courseid' => $course->id,
'instance' => rand(),
];
// If a particular grade item option is selected (not in zero state).
@@ -102,6 +104,7 @@ class gradereport_singleview_renderer extends plugin_renderer_base {
$sbody = $this->render_from_template('core/local/comboboxsearch/searchbody', [
'courseid' => $course->id,
'currentvalue' => optional_param('gradesearchvalue', '', PARAM_NOTAGS),
'instance' => $data['instance'],
]);
$dropdown = new comboboxsearch(
false,
@@ -18,6 +18,7 @@
Context variables required for this template:
* itemid - The value of the grade item selector element (id of the preselected grade item)
* instance - The instance ID of the combo box.
* courseid - The course ID.
* selectedoption - (optional) Object containing information about the selected option.
* text - The text of the selected option.
@@ -25,6 +26,7 @@
Example context (json):
{
"itemid": "21",
"instance": "25",
"courseid": "2",
"selectedoption": {
"text": "Grade item 1"
@@ -50,3 +52,4 @@
</div>
<span class="d-none" data-region="courseid" data-courseid="{{courseid}}"></span>
<span class="d-none" data-region="itemid" data-itemid="{{itemid}}"></span>
<span class="d-none" data-region="instance" data-instance="{{instance}}"></span>
+1 -1
View File
@@ -1 +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"}
{"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 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"}
+1 -1
View File
@@ -5,6 +5,6 @@ define("gradereport_user/user",["exports","core_user/comboboxsearch/user","core/
* @module gradereport_user/user
* @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.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),this.searchInput.removeAttribute("aria-activedescendant")}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}));
*/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,instance:this.instance,matches:this.getDatasetSize(),searchterm:this.getSearchTerm(),selectall:this.selectAllResultsLink()});(0,_templates.replaceNodeContents)(this.getHTMLElements().searchDropdown,html,js),this.searchInput.removeAttribute("aria-activedescendant")}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
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"user.min.js","sources":["../src/user.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 learners within the user report.\n *\n * @module gradereport_user/user\n * @copyright 2023 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport UserSearch from 'core_user/comboboxsearch/user';\nimport Url from 'core/url';\nimport {renderForPromise, replaceNodeContents} from 'core/templates';\nimport * as Repository from 'core_grades/searchwidget/repository';\n\nexport default class User extends UserSearch {\n\n constructor() {\n super();\n }\n\n static init() {\n return new User();\n }\n\n /**\n * Build the content then replace the node.\n */\n async renderDropdown() {\n const {html, js} = await renderForPromise('core_user/comboboxsearch/resultset', {\n users: this.getMatchedResults().slice(0, 5),\n hasresults: this.getMatchedResults().length > 0,\n matches: this.getDatasetSize(),\n searchterm: this.getSearchTerm(),\n selectall: this.selectAllResultsLink(),\n });\n replaceNodeContents(this.getHTMLElements().searchDropdown, html, js);\n // Remove aria-activedescendant when the available options change.\n this.searchInput.removeAttribute('aria-activedescendant');\n }\n\n /**\n * Build up the view all link.\n *\n * @returns {string|*}\n */\n selectAllResultsLink() {\n return Url.relativeUrl('/grade/report/user/index.php', {\n id: this.courseID,\n userid: 0,\n searchvalue: this.getSearchTerm()\n }, false);\n }\n\n /**\n * Build up the view all link that is dedicated to a particular result.\n *\n * @param {Number} userID The ID of the user selected.\n * @returns {string|*}\n */\n selectOneLink(userID) {\n return Url.relativeUrl('/grade/report/user/index.php', {\n id: this.courseID,\n searchvalue: this.getSearchTerm(),\n userid: userID,\n }, false);\n }\n\n /**\n * Get the data we will be searching against in this component.\n *\n * @returns {Promise<*>}\n */\n fetchDataset() {\n // Small typing checks as sometimes groups don't exist therefore the element returns a empty string.\n const gts = typeof (this.groupID) === \"string\" && this.groupID === '' ? 0 : this.groupID;\n return Repository.userFetch(this.courseID, gts).then((r) => r.users);\n }\n}\n"],"names":["User","UserSearch","constructor","html","js","users","this","getMatchedResults","slice","hasresults","length","matches","getDatasetSize","searchterm","getSearchTerm","selectall","selectAllResultsLink","getHTMLElements","searchDropdown","searchInput","removeAttribute","Url","relativeUrl","id","courseID","userid","searchvalue","selectOneLink","userID","fetchDataset","gts","groupID","Repository","userFetch","then","r"],"mappings":";;;;;;;q0BA2BqBA,aAAaC,cAE9BC,2CAKW,IAAIF,kCAOLG,KAACA,KAADC,GAAOA,UAAY,+BAAiB,qCAAsC,CAC5EC,MAAOC,KAAKC,oBAAoBC,MAAM,EAAG,GACzCC,WAAYH,KAAKC,oBAAoBG,OAAS,EAC9CC,QAASL,KAAKM,iBACdC,WAAYP,KAAKQ,gBACjBC,UAAWT,KAAKU,4DAEAV,KAAKW,kBAAkBC,eAAgBf,KAAMC,SAE5De,YAAYC,gBAAgB,yBAQrCJ,8BACWK,aAAIC,YAAY,+BAAgC,CACnDC,GAAIjB,KAAKkB,SACTC,OAAQ,EACRC,YAAapB,KAAKQ,kBACnB,GASPa,cAAcC,eACHP,aAAIC,YAAY,+BAAgC,CACnDC,GAAIjB,KAAKkB,SACTE,YAAapB,KAAKQ,gBAClBW,OAAQG,SACT,GAQPC,qBAEUC,IAAgC,iBAAlBxB,KAAKyB,SAA0C,KAAjBzB,KAAKyB,QAAiB,EAAIzB,KAAKyB,eAC1EC,WAAWC,UAAU3B,KAAKkB,SAAUM,KAAKI,MAAMC,GAAMA,EAAE9B"}
{"version":3,"file":"user.min.js","sources":["../src/user.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 learners within the user report.\n *\n * @module gradereport_user/user\n * @copyright 2023 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport UserSearch from 'core_user/comboboxsearch/user';\nimport Url from 'core/url';\nimport {renderForPromise, replaceNodeContents} from 'core/templates';\nimport * as Repository from 'core_grades/searchwidget/repository';\n\nexport default class User extends UserSearch {\n\n constructor() {\n super();\n }\n\n static init() {\n return new User();\n }\n\n /**\n * Build the content then replace the node.\n */\n async renderDropdown() {\n const {html, js} = await renderForPromise('core_user/comboboxsearch/resultset', {\n users: this.getMatchedResults().slice(0, 5),\n hasresults: this.getMatchedResults().length > 0,\n instance: this.instance,\n matches: this.getDatasetSize(),\n searchterm: this.getSearchTerm(),\n selectall: this.selectAllResultsLink(),\n });\n replaceNodeContents(this.getHTMLElements().searchDropdown, html, js);\n // Remove aria-activedescendant when the available options change.\n this.searchInput.removeAttribute('aria-activedescendant');\n }\n\n /**\n * Build up the view all link.\n *\n * @returns {string|*}\n */\n selectAllResultsLink() {\n return Url.relativeUrl('/grade/report/user/index.php', {\n id: this.courseID,\n userid: 0,\n searchvalue: this.getSearchTerm()\n }, false);\n }\n\n /**\n * Build up the link that is dedicated to a particular result.\n *\n * @param {Number} userID The ID of the user selected.\n * @returns {string|*}\n */\n selectOneLink(userID) {\n return Url.relativeUrl('/grade/report/user/index.php', {\n id: this.courseID,\n searchvalue: this.getSearchTerm(),\n userid: userID,\n }, false);\n }\n\n /**\n * Get the data we will be searching against in this component.\n *\n * @returns {Promise<*>}\n */\n fetchDataset() {\n // Small typing checks as sometimes groups don't exist therefore the element returns a empty string.\n const gts = typeof (this.groupID) === \"string\" && this.groupID === '' ? 0 : this.groupID;\n return Repository.userFetch(this.courseID, gts).then((r) => r.users);\n }\n}\n"],"names":["User","UserSearch","constructor","html","js","users","this","getMatchedResults","slice","hasresults","length","instance","matches","getDatasetSize","searchterm","getSearchTerm","selectall","selectAllResultsLink","getHTMLElements","searchDropdown","searchInput","removeAttribute","Url","relativeUrl","id","courseID","userid","searchvalue","selectOneLink","userID","fetchDataset","gts","groupID","Repository","userFetch","then","r"],"mappings":";;;;;;;q0BA2BqBA,aAAaC,cAE9BC,2CAKW,IAAIF,kCAOLG,KAACA,KAADC,GAAOA,UAAY,+BAAiB,qCAAsC,CAC5EC,MAAOC,KAAKC,oBAAoBC,MAAM,EAAG,GACzCC,WAAYH,KAAKC,oBAAoBG,OAAS,EAC9CC,SAAUL,KAAKK,SACfC,QAASN,KAAKO,iBACdC,WAAYR,KAAKS,gBACjBC,UAAWV,KAAKW,4DAEAX,KAAKY,kBAAkBC,eAAgBhB,KAAMC,SAE5DgB,YAAYC,gBAAgB,yBAQrCJ,8BACWK,aAAIC,YAAY,+BAAgC,CACnDC,GAAIlB,KAAKmB,SACTC,OAAQ,EACRC,YAAarB,KAAKS,kBACnB,GASPa,cAAcC,eACHP,aAAIC,YAAY,+BAAgC,CACnDC,GAAIlB,KAAKmB,SACTE,YAAarB,KAAKS,gBAClBW,OAAQG,SACT,GAQPC,qBAEUC,IAAgC,iBAAlBzB,KAAK0B,SAA0C,KAAjB1B,KAAK0B,QAAiB,EAAI1B,KAAK0B,eAC1EC,WAAWC,UAAU5B,KAAKmB,SAAUM,KAAKI,MAAMC,GAAMA,EAAE/B"}
+1 -1
View File
@@ -43,7 +43,7 @@ export default class Group extends GroupSearch {
}
/**
* Build up the view all link that is dedicated to a particular result.
* Build up the link that is dedicated to a particular result.
*
* @param {Number} groupID The ID of the group selected.
* @returns {string|*}
+2 -1
View File
@@ -42,6 +42,7 @@ export default class User extends UserSearch {
const {html, js} = await renderForPromise('core_user/comboboxsearch/resultset', {
users: this.getMatchedResults().slice(0, 5),
hasresults: this.getMatchedResults().length > 0,
instance: this.instance,
matches: this.getDatasetSize(),
searchterm: this.getSearchTerm(),
selectall: this.selectAllResultsLink(),
@@ -65,7 +66,7 @@ export default class User extends UserSearch {
}
/**
* Build up the view all link that is dedicated to a particular result.
* Build up the link that is dedicated to a particular result.
*
* @param {Number} userID The ID of the user selected.
* @returns {string|*}
+1
View File
@@ -104,6 +104,7 @@ class gradereport_user_renderer extends plugin_renderer_base {
$data = [
'currentvalue' => $currentvalue,
'instance' => rand(),
'resetlink' => $resetlink->out(false),
'name' => 'userid',
'value' => $submitteduserid ?? '',
+1 -1
View File
@@ -1,3 +1,3 @@
define("core_group/comboboxsearch/group",["exports","core/comboboxsearch/search_combobox","core_group/comboboxsearch/repository","core/templates","core/utils","core/notification"],(function(_exports,_search_combobox,_repository,_templates,_utils,_notification){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_search_combobox=_interopRequireDefault(_search_combobox),_notification=_interopRequireDefault(_notification);class GroupSearch extends _search_combobox.default{constructor(){super(),_defineProperty(this,"courseID",void 0),_defineProperty(this,"bannedFilterFields",["id","link","groupimageurl"]),this.selectors={...this.selectors,courseid:'[data-region="courseid"]',placeholder:'.groupsearchdropdown [data-region="searchplaceholder"]'};const component=document.querySelector(this.componentSelector());this.courseID=component.querySelector(this.selectors.courseid).dataset.courseid;const searchValueElement=this.component.querySelector("#".concat(this.searchInput.dataset.inputElement));searchValueElement.addEventListener("change",(()=>{this.toggleDropdown();const valueElement=this.component.querySelector("#".concat(this.combobox.dataset.inputElement));valueElement.value!==searchValueElement.value&&(valueElement.value=searchValueElement.value,valueElement.dispatchEvent(new Event("change",{bubbles:!0}))),searchValueElement.value=""})),this.$component.on("hide.bs.dropdown",(()=>{this.searchInput.removeAttribute("aria-activedescendant");const listbox=document.querySelector("#".concat(this.searchInput.getAttribute("aria-controls"),'[role="listbox"]'));listbox.querySelectorAll('.active[role="option"]').forEach((option=>{option.classList.remove("active")})),listbox.scrollTop=0,setTimeout((()=>{""!==this.searchInput.value&&(this.searchInput.value="",this.searchInput.dispatchEvent(new Event("input",{bubbles:!0})))}))})),this.renderDefault().catch(_notification.default.exception)}static init(){return new GroupSearch}componentSelector(){return".group-search"}dropdownSelector(){return".groupsearchdropdown"}async renderDropdown(){const{html:html,js:js}=await(0,_templates.renderForPromise)("core_group/comboboxsearch/resultset",{groups:this.getMatchedResults(),hasresults:this.getMatchedResults().length>0,searchterm:this.getSearchTerm()});(0,_templates.replaceNodeContents)(this.selectors.placeholder,html,js),this.searchInput.removeAttribute("aria-activedescendant")}async renderDefault(){this.setMatchedResults(await this.filterDataset(await this.getDataset())),this.filterMatchDataset(),await this.renderDropdown(),this.updateNodes(),this.registerInputEvents()}async fetchDataset(){return await(0,_repository.groupFetch)(this.courseID).then((r=>r.groups))}async filterDataset(filterableData){return""===this.getPreppedSearchTerm()?filterableData:filterableData.filter((group=>Object.keys(group).some((key=>""!==group[key]&&!this.bannedFilterFields.includes(key)&&group[key].toString().toLowerCase().includes(this.getPreppedSearchTerm())))))}filterMatchDataset(){this.setMatchedResults(this.getMatchedResults().map((group=>({id:group.id,name:group.name,groupimageurl:group.groupimageurl}))))}registerInputEvents(){this.searchInput.addEventListener("input",(0,_utils.debounce)((async()=>{this.setSearchTerms(this.searchInput.value),""===this.searchInput.value?this.clearSearchButton.classList.add("d-none"):this.clearSearchButton.classList.remove("d-none"),await this.filterrenderpipe()}),300))}async clickHandler(e){e.target.closest(this.selectors.clearSearch)&&(e.stopPropagation(),this.searchInput.value="",this.setSearchTerms(this.searchInput.value),this.searchInput.focus(),this.clearSearchButton.classList.add("d-none"),await this.filterrenderpipe())}changeHandler(e){window.location=this.selectOneLink(e.target.value)}registerInputHandlers(){this.searchInput.addEventListener("input",(0,_utils.debounce)((()=>{this.setSearchTerms(this.searchInput.value),""===this.getSearchTerm()?this.clearSearchButton.classList.add("d-none"):this.clearSearchButton.classList.remove("d-none")}),300))}selectOneLink(groupID){throw new Error("selectOneLink(".concat(groupID,") must be implemented in ").concat(this.constructor.name))}}return _exports.default=GroupSearch,_exports.default}));
define("core_group/comboboxsearch/group",["exports","core/comboboxsearch/search_combobox","core_group/comboboxsearch/repository","core/templates","core/utils","core/notification"],(function(_exports,_search_combobox,_repository,_templates,_utils,_notification){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_search_combobox=_interopRequireDefault(_search_combobox),_notification=_interopRequireDefault(_notification);class GroupSearch extends _search_combobox.default{constructor(){super(),_defineProperty(this,"courseID",void 0),_defineProperty(this,"bannedFilterFields",["id","link","groupimageurl"]),this.selectors={...this.selectors,courseid:'[data-region="courseid"]',placeholder:'.groupsearchdropdown [data-region="searchplaceholder"]'};const component=document.querySelector(this.componentSelector());this.courseID=component.querySelector(this.selectors.courseid).dataset.courseid,this.instance=component.querySelector(this.selectors.instance).dataset.instance;const searchValueElement=this.component.querySelector("#".concat(this.searchInput.dataset.inputElement));searchValueElement.addEventListener("change",(()=>{this.toggleDropdown();const valueElement=this.component.querySelector("#".concat(this.combobox.dataset.inputElement));valueElement.value!==searchValueElement.value&&(valueElement.value=searchValueElement.value,valueElement.dispatchEvent(new Event("change",{bubbles:!0}))),searchValueElement.value=""})),this.$component.on("hide.bs.dropdown",(()=>{this.searchInput.removeAttribute("aria-activedescendant");const listbox=document.querySelector("#".concat(this.searchInput.getAttribute("aria-controls"),'[role="listbox"]'));listbox.querySelectorAll('.active[role="option"]').forEach((option=>{option.classList.remove("active")})),listbox.scrollTop=0,setTimeout((()=>{""!==this.searchInput.value&&(this.searchInput.value="",this.searchInput.dispatchEvent(new Event("input",{bubbles:!0})))}))})),this.renderDefault().catch(_notification.default.exception)}static init(){return new GroupSearch}componentSelector(){return".group-search"}dropdownSelector(){return".groupsearchdropdown"}async renderDropdown(){const{html:html,js:js}=await(0,_templates.renderForPromise)("core_group/comboboxsearch/resultset",{groups:this.getMatchedResults(),hasresults:this.getMatchedResults().length>0,instance:this.instance,searchterm:this.getSearchTerm()});(0,_templates.replaceNodeContents)(this.selectors.placeholder,html,js),this.searchInput.removeAttribute("aria-activedescendant")}async renderDefault(){this.setMatchedResults(await this.filterDataset(await this.getDataset())),this.filterMatchDataset(),await this.renderDropdown(),this.updateNodes()}async fetchDataset(){return await(0,_repository.groupFetch)(this.courseID).then((r=>r.groups))}async filterDataset(filterableData){return""===this.getPreppedSearchTerm()?filterableData:filterableData.filter((group=>Object.keys(group).some((key=>""!==group[key]&&!this.bannedFilterFields.includes(key)&&group[key].toString().toLowerCase().includes(this.getPreppedSearchTerm())))))}filterMatchDataset(){this.setMatchedResults(this.getMatchedResults().map((group=>({id:group.id,name:group.name,groupimageurl:group.groupimageurl}))))}async clickHandler(e){e.target.closest(this.selectors.clearSearch)&&(e.stopPropagation(),this.searchInput.value="",this.setSearchTerms(this.searchInput.value),this.searchInput.focus(),this.clearSearchButton.classList.add("d-none"),await this.filterrenderpipe())}changeHandler(e){window.location=this.selectOneLink(e.target.value)}registerInputHandlers(){this.searchInput.addEventListener("input",(0,_utils.debounce)((async()=>{this.setSearchTerms(this.searchInput.value),""===this.getSearchTerm()?this.clearSearchButton.classList.add("d-none"):this.clearSearchButton.classList.remove("d-none"),await this.filterrenderpipe()}),300))}selectOneLink(groupID){throw new Error("selectOneLink(".concat(groupID,") must be implemented in ").concat(this.constructor.name))}}return _exports.default=GroupSearch,_exports.default}));
//# sourceMappingURL=group.min.js.map
File diff suppressed because one or more lines are too long
+7 -22
View File
@@ -39,6 +39,8 @@ export default class GroupSearch extends search_combobox {
};
const component = document.querySelector(this.componentSelector());
this.courseID = component.querySelector(this.selectors.courseid).dataset.courseid;
// Override the instance since the body is built outside the constructor for the combobox.
this.instance = component.querySelector(this.selectors.instance).dataset.instance;
const searchValueElement = this.component.querySelector(`#${this.searchInput.dataset.inputElement}`);
searchValueElement.addEventListener('change', () => {
@@ -103,6 +105,7 @@ export default class GroupSearch extends search_combobox {
const {html, js} = await renderForPromise('core_group/comboboxsearch/resultset', {
groups: this.getMatchedResults(),
hasresults: this.getMatchedResults().length > 0,
instance: this.instance,
searchterm: this.getSearchTerm(),
});
replaceNodeContents(this.selectors.placeholder, html, js);
@@ -120,7 +123,6 @@ export default class GroupSearch extends search_combobox {
await this.renderDropdown();
this.updateNodes();
this.registerInputEvents();
}
/**
@@ -166,26 +168,6 @@ export default class GroupSearch extends search_combobox {
);
}
/**
* Handle any keyboard inputs.
*/
registerInputEvents() {
// Register & handle the text input.
this.searchInput.addEventListener('input', debounce(async() => {
this.setSearchTerms(this.searchInput.value);
// We can also require a set amount of input before search.
if (this.searchInput.value === '') {
// Hide the "clear" search button in the search bar.
this.clearSearchButton.classList.add('d-none');
} else {
// Display the "clear" search button in the search bar.
this.clearSearchButton.classList.remove('d-none');
}
// User has given something for us to filter against.
await this.filterrenderpipe();
}, 300));
}
/**
* The handler for when a user interacts with the component.
*
@@ -218,7 +200,7 @@ export default class GroupSearch extends search_combobox {
*/
registerInputHandlers() {
// Register & handle the text input.
this.searchInput.addEventListener('input', debounce(() => {
this.searchInput.addEventListener('input', debounce(async() => {
this.setSearchTerms(this.searchInput.value);
// We can also require a set amount of input before search.
if (this.getSearchTerm() === '') {
@@ -228,11 +210,14 @@ export default class GroupSearch extends search_combobox {
// Display the "clear" search button in the search bar.
this.clearSearchButton.classList.remove('d-none');
}
// User has given something for us to filter against.
await this.filterrenderpipe();
}, 300));
}
/**
* Build up the view all link that is dedicated to a particular result.
* We will call this function when a user interacts with the combobox to redirect them to show their results in the page.
*
* @param {Number} groupID The ID of the group selected.
*/
@@ -18,6 +18,7 @@
Context variables required for this template:
* groups - Our returned groups to render.
* instance - The instance ID of the combo box.
* searchterm - The entered text to find these results.
* hasgroups - Allow the handling where no users exist for the returned search term.
@@ -35,6 +36,7 @@
"link": "http://foo.bar/grade/report/grader/index.php?id=42&userid=3"
}
],
"instance": 25,
"searchterm": "Foo",
"hasresults": true
}
@@ -29,42 +29,27 @@
}
}}
<div class="flex-column h-100 w-100">
<span class="d-none" data-region="courseid" data-courseid="{{courseid}}" aria-hidden="true"></span>
<span class="d-none" data-region="groupid" data-groupid="{{groupid}}" aria-hidden="true"></span>
<span class="d-none" data-region="courseid" data-courseid="{{courseid}}"></span>
<span class="d-none" data-region="groupid" data-groupid="{{groupid}}"></span>
<span class="d-none" data-region="instance" data-instance="{{instance}}"></span>
{{#currentvalue}}
{{< core/search_input_auto }}
{{$label}}{{#str}}
searchgroups, core
{{/str}}{{/label}}
{{$value}}{{currentvalue}}{{/value}}
{{$additionalattributes}}
role="combobox"
aria-expanded="true"
aria-controls="groups-result-listbox"
aria-autocomplete="list"
data-input-element="input-{{uniqid}}"
{{/additionalattributes}}
{{/ core/search_input_auto }}
{{/currentvalue}}
{{^currentvalue}}
{{< core/search_input_auto }}
{{$label}}{{#str}}
searchgroups, core
{{/str}}{{/label}}
{{$placeholder}}{{#str}}
searchgroups, core
{{/str}}{{/placeholder}}
{{$additionalattributes}}
role="combobox"
aria-expanded="true"
aria-controls="groups-result-listbox"
aria-autocomplete="list"
data-input-element="input-{{uniqid}}"
{{/additionalattributes}}
{{/ core/search_input_auto }}
{{/currentvalue}}
<input type="hidden" name="search" id="input-{{uniqid}}"/>
{{< core/search_input_auto }}
{{$label}}{{#str}}
searchgroups, core
{{/str}}{{/label}}
{{$placeholder}}{{#str}}
searchgroups, core
{{/str}}{{/placeholder}}
{{$value}}{{currentvalue}}{{/value}}
{{$additionalattributes}}
role="combobox"
aria-expanded="true"
aria-controls="groups-{{instance}}-result-listbox"
aria-autocomplete="list"
data-input-element="input-{{uniqid}}-{{instance}}"
{{/additionalattributes}}
{{/ core/search_input_auto }}
<input type="hidden" name="search" id="input-{{uniqid}}-{{instance}}"/>
<div data-region="searchplaceholder"></div>
</div>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -30,6 +30,7 @@ export default class {
selectors = {
component: this.componentSelector(),
toggle: '[data-toggle="dropdown"]',
instance: '[data-region="instance"]',
input: '[data-action="search"]',
clearSearch: '[data-action="clearsearch"]',
dropdown: this.dropdownSelector(),
@@ -62,6 +63,7 @@ export default class {
// DOM nodes that persist.
component = document.querySelector(this.selectors.component);
instance = this.component.dataset.instance;
toggle = this.component.querySelector(this.selectors.toggle);
searchInput = this.component.querySelector(this.selectors.input);
searchDropdown = this.component.querySelector(this.selectors.dropdown);
@@ -74,7 +76,10 @@ export default class {
this.setSearchTerms(this.searchInput?.value ?? '');
// Begin handling the base search component.
this.registerClickHandlers();
// Conditionally set up the input handler since we don't know exactly how we were called.
// If the combobox is rendered later, then you'll need to call this.registerInputHandlers() manually.
// An example of this is the collapse columns in the gradebook.
if (this.searchInput !== null) {
this.registerInputHandlers();
this.registerChangeHandlers();
+6 -4
View File
@@ -30,7 +30,9 @@ use templatable;
*/
class comboboxsearch implements renderable, templatable {
/** @var bool $renderlater Should the dropdown render straightaway? */
/** @var bool $renderlater Should the dropdown render straightaway? We sometimes need to output the component without all of the
* data and leave the rendering of any defaults and actual data to the caller. We will give you a basic placeholder that can
* then be easily replaced.*/
protected $renderlater;
/** @var string $buttoncontent What is the content of the "Button" that users will always see. */
@@ -68,16 +70,16 @@ class comboboxsearch implements renderable, templatable {
*
* @param bool $renderlater How we figure out if we should render the template instantly.
* @param string $buttoncontent What gets placed in the button.
* @param ?string $dropdowncontent What can be placed in the dropdown if we are rendering now.
* @param ?string $dropdowncontent What will be placed in the dropdown if we are rendering now.
* @param ?string $parentclasses The classes that can be added that the bootstrap events are attached to.
* @param ?string $buttonclasses Any special classes that may be needed.
* @param ?string $dropdownclasses Any special classes that may be needed.
* @param ?string $buttonheader If the button item in the tertiary nav needs an extra top header for context.
* @param ?string $buttonheader Sometimes we want extra context for a button before it is shown, basically a pseudo header.
* @param ?bool $usebutton If we want the mustache to add the button roles for us or do we have another aria role node?
* @param ?string $label The label of the combobox.
* @param ?string $name The name of the input element representing the combobox.
* @param ?string $value The value of the input element representing the combobox.
* @throws moodle_exception If the implementor incorrectly call this module.
* @throws moodle_exception If the implementor incorrectly calls this module.
*/
public function __construct(
bool $renderlater,
+5 -3
View File
@@ -21,6 +21,7 @@
* name - The name of the input element representing the combobox.
* value - The value of the input element representing the combobox.
* renderlater - This determines if we show a placeholder whilst fetching content to replace within the placeholder region
* buttonheader - The header to be shown above the button
* buttoncontent - The string to be shown to users to trigger the dropdown
* usebutton - If we want to use a button to trigger the dropdown, or just the dropdown itself
* dropdowncontent - If rendering now, The content within the dropdown
@@ -35,8 +36,9 @@
"name": "input-1",
"value": "0",
"renderlater": false,
"buttonheader": "Example:",
"usebutton": true,
"buttoncontent": "Example dropdown button",
"buttoncontent": "Dropdown button",
"dropdowncontent": "Some body content to render right now",
"parentclasses": "my-dropdown",
"buttonclasses": "my-button",
@@ -47,7 +49,7 @@
{{#buttonheader}}
<small>{{.}}</small>
{{/buttonheader}}
<div class="{{#parentclasses}}{{.}}{{/parentclasses}} dropdown">
<div class="{{#parentclasses}}{{.}}{{/parentclasses}} dropdown" data-instance="{{instance}}">
{{#usebutton}}
<div tabindex="0"
@@ -56,7 +58,7 @@
role="combobox"
aria-haspopup="dialog"
aria-controls="dialog-{{instance}}-{{uniqid}}"
class="{{#buttonclasses}}{{.}}{{/buttonclasses}} btn dropdown-toggle keep-open d-flex text-left align-items-center p-0 font-weight-bold"
class="{{#buttonclasses}}{{.}}{{/buttonclasses}} btn dropdown-toggle d-flex text-left align-items-center p-0 font-weight-bold"
aria-label="{{label}}"
data-input-element="input-{{instance}}-{{uniqid}}">
{{{buttoncontent}}}
@@ -18,8 +18,8 @@
Context variables required for this template:
* id - Result item system ID.
* instance - The instance ID of the combo box.
* name - Result item human readable name.
* link - The link used to redirect upon self to show only this specific result item.
The shorttext pragma can be used to provide a short text for the result item.
This is especially useful when the result item content contains html tags.
@@ -27,11 +27,12 @@
Example context (json):
{
"id": 2,
"instance": 25,
"name": "Foo bar"
}
}}
<li
id="result-{{id}}"
id="result-{{instance}}-{{id}}"
class="w-100 dropdown-item d-flex px-0 align-items-center"
role="option"
{{! aria.js would use the data-short-text attribute if it is provided. }}
@@ -17,12 +17,14 @@
Wrapping template for returned result items.
Context variables required for this template:
* instance - The instance ID of the combo box.
* results - Our returned results to render.
* searchterm - The entered text to find these results.
* hasresult - Allow the handling where no results exist for the returned search term.
Example context (json):
{
"instance": 25,
"results": [
{
"id": 2,
@@ -39,7 +41,7 @@
}}
<div class="d-flex flex-column mh-100 h-100">
<ul
id="{{$listid}}list{{/listid}}-result-listbox"
id="{{$listid}}list{{/listid}}-{{instance}}-result-listbox"
class="searchresultitemscontainer d-flex flex-column mw-100 position-relative py-2 list-group h-100 mx-0 {{$listclasses}}{{/listclasses}}"
role="listbox"
data-region="search-result-items-container"
@@ -28,39 +28,22 @@
}}
<div class="flex-column h-100 w-100">
<span class="d-none" data-region="courseid" data-courseid="{{courseid}}" aria-hidden="true"></span>
{{#currentvalue}}
{{< core/search_input_auto }}
{{$label}}{{#str}}
searchitems, core
{{/str}}{{/label}}
{{$value}}{{currentvalue}}{{/value}}
{{$additionalattributes}}
role="combobox"
aria-expanded="true"
aria-controls="list-result-listbox"
aria-autocomplete="list"
data-input-element="result-input-{{uniqid}}"
{{/additionalattributes}}
{{/ core/search_input_auto }}
{{/currentvalue}}
{{^currentvalue}}
{{< core/search_input_auto }}
{{$label}}{{#str}}
searchitems, core
{{/str}}{{/label}}
{{$placeholder}}{{#str}}
searchitems, core
{{/str}}{{/placeholder}}
{{$additionalattributes}}
role="combobox"
aria-expanded="true"
aria-controls="list-result-listbox"
aria-autocomplete="list"
data-input-element="result-input-{{uniqid}}"
{{/additionalattributes}}
{{/ core/search_input_auto }}
{{/currentvalue}}
<input type="hidden" name="search" id="result-input-{{uniqid}}"/>
{{< core/search_input_auto }}
{{$label}}{{#str}}
searchitems, core
{{/str}}{{/label}}
{{$placeholder}}{{#str}}
searchitems, core
{{/str}}{{/placeholder}}
{{$value}}{{currentvalue}}{{/value}}
{{$additionalattributes}}
role="combobox"
aria-expanded="true"
aria-controls="list-{{instance}}-result-listbox"
aria-autocomplete="list"
data-input-element="result-input-{{uniqid}}-{{instance}}"
{{/additionalattributes}}
{{/ core/search_input_auto }}
<input type="hidden" name="search" id="result-input-{{uniqid}}-{{instance}}"/>
<div data-region="searchplaceholder"></div>
</div>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4 -2
View File
@@ -55,9 +55,9 @@ export default class UserSearch extends search_combobox {
resetPageButton: '[data-action="resetpage"]',
};
const component = document.querySelector(this.componentSelector());
this.courseID = component.querySelector(this.selectors.courseid).dataset.courseid;
this.courseID = this.component.querySelector(this.selectors.courseid).dataset.courseid;
this.groupID = document.querySelector(this.selectors.groupid)?.dataset?.groupid;
this.instance = this.component.querySelector(this.selectors.instance).dataset.instance;
// We need to render some content by default for ARIA purposes.
this.renderDefault();
@@ -92,6 +92,7 @@ export default class UserSearch extends search_combobox {
const {html, js} = await renderForPromise('core_user/comboboxsearch/resultset', {
users: this.getMatchedResults().slice(0, 5),
hasresults: this.getMatchedResults().length > 0,
instance: this.instance,
matches: this.getMatchedResults().length,
searchterm: this.getSearchTerm(),
selectall: this.selectAllResultsLink(),
@@ -261,6 +262,7 @@ export default class UserSearch extends search_combobox {
/**
* Build up the view all link that is dedicated to a particular result.
* We will call this function when a user interacts with the combobox to redirect them to show their results in the page.
*
* @param {Number} userID The ID of the user selected.
*/
@@ -17,6 +17,7 @@
Wrapping template for returned result items.
Context variables required for this template:
* instance - The instance ID of the combo box.
* users - Our returned users to render.
* found - Count of the found users.
* total - Total count of users within this report.
@@ -26,6 +27,7 @@
Example context (json):
{
"instance": 25,
"users": [
{
"id": 2,
@@ -58,7 +60,7 @@
{{$selectall}}
{{#selectall}}
<li
id="result-row-0"
id="result-row-{{instance}}-0"
class="w-100 p-1 border-top bottom-0 position-sticky dropdown-item d-flex small p-3"
role="option"
{{! The data-short-text attribute is provided so that aria.js would use it rather than the whole content. }}
@@ -39,6 +39,7 @@
}}
<span class="d-none" data-region="courseid" data-courseid="{{courseid}}"></span>
<span class="d-none" data-region="groupid" data-groupid="{{group}}"></span>
<span class="d-none" data-region="instance" data-instance="{{instance}}"></span>
{{< core/search_input_auto }}
{{$label}}{{#str}}searchusers, core{{/str}}{{/label}}
{{$placeholder}}{{#str}}searchusers, core{{/str}}{{/placeholder}}
@@ -46,10 +47,10 @@
{{$additionalattributes}}
role="combobox"
aria-expanded="false"
aria-controls="user-result-listbox"
aria-controls="user-{{instance}}-result-listbox"
aria-autocomplete="list"
aria-haspopup="listbox"
data-input-element="user-input-{{uniqid}}"
data-input-element="user-input-{{uniqid}}-{{instance}}"
{{/additionalattributes}}
{{/ core/search_input_auto }}
{{#currentvalue}}
@@ -57,4 +58,4 @@
{{#str}}clear{{/str}}
</a>
{{/currentvalue}}
<input type="hidden" name="{{name}}" value="{{value}}" id="user-input-{{uniqid}}"/>
<input type="hidden" name="{{name}}" value="{{value}}" id="user-input-{{uniqid}}-{{instance}}"/>