From b389393dc58e99df3bb7b4c8ddc1bc2e1c424c5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mudr=C3=A1k?= Date: Wed, 22 Jan 2020 23:18:11 +0100 Subject: [PATCH] MDL-67748 user: Add new core_user/form_user_selector JS module The module provides AJAX support for the autocomplete form element. --- user/amd/build/form_user_selector.min.js | 2 + user/amd/build/form_user_selector.min.js.map | 1 + user/amd/src/form_user_selector.js | 87 +++++++++++++++++++ .../form_user_selector_suggestion.mustache | 54 ++++++++++++ user/upgrade.txt | 2 + 5 files changed, 146 insertions(+) create mode 100644 user/amd/build/form_user_selector.min.js create mode 100644 user/amd/build/form_user_selector.min.js.map create mode 100644 user/amd/src/form_user_selector.js create mode 100644 user/templates/form_user_selector_suggestion.mustache diff --git a/user/amd/build/form_user_selector.min.js b/user/amd/build/form_user_selector.min.js new file mode 100644 index 00000000000..41c53a6abc6 --- /dev/null +++ b/user/amd/build/form_user_selector.min.js @@ -0,0 +1,2 @@ +define ("core_user/form_user_selector",["exports","core/ajax","core/templates","core/str"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.transport=g;a.processResults=function(a,b){if(!Array.isArray(b)){return b}else{return b.map(function(a){return{value:a.id,label:a.label}})}};b=function(a){return a&&a.__esModule?a:{default:a}}(b);function e(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function f(a){return function(){var b=this,c=arguments;return new Promise(function(d,f){var i=a.apply(b,c);function g(a){e(i,d,f,g,h,"next",a)}function h(a){e(i,d,f,g,h,"throw",a)}g(void 0)})}}function g(){return h.apply(this,arguments)}function h(){h=f(regeneratorRuntime.mark(function a(e,f,g,h){var i,j,k,l;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:i={methodname:"core_user_search_identity",args:{query:f}};a.prev=1;a.next=4;return b.default.call([i])[0];case 4:j=a.sent;if(!j.overflow){a.next=12;break}a.next=8;return(0,d.get_string)("toomanyuserstoshow","core",">"+j.maxusersperpage);case 8:k=a.sent;g(k);a.next=19;break;case 12:l=[];j.list.forEach(function(a){l.push((0,c.render)("core_user/form_user_selector_suggestion",a))});a.next=16;return Promise.all(l);case 16:l=a.sent;j.list.forEach(function(a,b){a.label=l[b]});g(j.list);case 19:a.next=24;break;case 21:a.prev=21;a.t0=a["catch"](1);h(a.t0);case 24:case"end":return a.stop();}}},a,null,[[1,21]])}));return h.apply(this,arguments)}}); +//# sourceMappingURL=form_user_selector.min.js.map diff --git a/user/amd/build/form_user_selector.min.js.map b/user/amd/build/form_user_selector.min.js.map new file mode 100644 index 00000000000..0b7ebcb9a1a --- /dev/null +++ b/user/amd/build/form_user_selector.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/form_user_selector.js"],"names":["selector","results","Array","isArray","map","result","value","id","label","transport","query","callback","failure","request","methodname","args","Ajax","call","response","overflow","maxusersperpage","msg","labels","list","forEach","user","push","Promise","all","index"],"mappings":"0MA8EO,SAAwBA,CAAxB,CAAkCC,CAAlC,CAA2C,CAE9C,GAAI,CAACC,KAAK,CAACC,OAAN,CAAcF,CAAd,CAAL,CAA6B,CACzB,MAAOA,CAAAA,CAEV,CAHD,IAGO,CACH,MAAOA,CAAAA,CAAO,CAACG,GAAR,CAAY,SAAAC,CAAM,QAAK,CAACC,KAAK,CAAED,CAAM,CAACE,EAAf,CAAmBC,KAAK,CAAEH,CAAM,CAACG,KAAjC,CAAL,CAAlB,CACV,CACJ,C,CA9DD,uD,uUAYsBC,CAAAA,C,2EAAf,WAAyBT,CAAzB,CAAmCU,CAAnC,CAA0CC,CAA1C,CAAoDC,CAApD,+FAEGC,CAFH,CAEa,CACZC,UAAU,CAAE,2BADA,CAEZC,IAAI,CAAE,CACFL,KAAK,CAAEA,CADL,CAFM,CAFb,yBAUwBM,WAAKC,IAAL,CAAU,CAACJ,CAAD,CAAV,EAAqB,CAArB,CAVxB,QAUOK,CAVP,YAYKA,CAAQ,CAACC,QAZd,iCAauB,iBAAU,oBAAV,CAAgC,MAAhC,CAAwC,IAAMD,CAAQ,CAACE,eAAvD,CAbvB,QAaWC,CAbX,QAcKV,CAAQ,CAACU,CAAD,CAAR,CAdL,wBAiBSC,CAjBT,CAiBkB,EAjBlB,CAkBKJ,CAAQ,CAACK,IAAT,CAAcC,OAAd,CAAsB,SAAAC,CAAI,CAAI,CAC1BH,CAAM,CAACI,IAAP,CAAY,aAAe,yCAAf,CAA0DD,CAA1D,CAAZ,CACH,CAFD,EAlBL,gBAqBoBE,CAAAA,OAAO,CAACC,GAAR,CAAYN,CAAZ,CArBpB,SAqBKA,CArBL,QAuBKJ,CAAQ,CAACK,IAAT,CAAcC,OAAd,CAAsB,SAACC,CAAD,CAAOI,CAAP,CAAiB,CACnCJ,CAAI,CAACjB,KAAL,CAAac,CAAM,CAACO,CAAD,CACtB,CAFD,EAIAlB,CAAQ,CAACO,CAAQ,CAACK,IAAV,CAAR,CA3BL,6DA+BCX,CAAO,MAAP,CA/BD,uD","sourcesContent":["// This file is part of Moodle - https://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 .\n\n/**\n * Provides the required functionality for an autocomplete element to select a user.\n *\n * @module core_user/form_user_selector\n * @package core_webservice\n * @copyright 2020 David Mudrák \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\nimport {render as renderTemplate} from 'core/templates';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Load the list of users matching the query and render the selector labels for them.\n *\n * @param {String} selector The selector of the auto complete element.\n * @param {String} query The query string.\n * @param {Function} callback A callback function receiving an array of results.\n * @param {Function} failure A function to call in case of failure, receiving the error message.\n */\nexport async function transport(selector, query, callback, failure) {\n\n const request = {\n methodname: 'core_user_search_identity',\n args: {\n query: query\n }\n };\n\n try {\n const response = await Ajax.call([request])[0];\n\n if (response.overflow) {\n const msg = await getString('toomanyuserstoshow', 'core', '>' + response.maxusersperpage);\n callback(msg);\n\n } else {\n let labels = [];\n response.list.forEach(user => {\n labels.push(renderTemplate('core_user/form_user_selector_suggestion', user));\n });\n labels = await Promise.all(labels);\n\n response.list.forEach((user, index) => {\n user.label = labels[index];\n });\n\n callback(response.list);\n }\n\n } catch (e) {\n failure(e);\n }\n}\n\n/**\n * Process the results for auto complete elements.\n *\n * @param {String} selector The selector of the auto complete element.\n * @param {Array} results An array or results returned by {@see transport()}.\n * @return {Array} New array of the selector options.\n */\nexport function processResults(selector, results) {\n\n if (!Array.isArray(results)) {\n return results;\n\n } else {\n return results.map(result => ({value: result.id, label: result.label}));\n }\n}\n"],"file":"form_user_selector.min.js"} \ No newline at end of file diff --git a/user/amd/src/form_user_selector.js b/user/amd/src/form_user_selector.js new file mode 100644 index 00000000000..07df01c03be --- /dev/null +++ b/user/amd/src/form_user_selector.js @@ -0,0 +1,87 @@ +// This file is part of Moodle - https://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 . + +/** + * Provides the required functionality for an autocomplete element to select a user. + * + * @module core_user/form_user_selector + * @package core_webservice + * @copyright 2020 David Mudrák + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import Ajax from 'core/ajax'; +import {render as renderTemplate} from 'core/templates'; +import {get_string as getString} from 'core/str'; + +/** + * Load the list of users matching the query and render the selector labels for them. + * + * @param {String} selector The selector of the auto complete element. + * @param {String} query The query string. + * @param {Function} callback A callback function receiving an array of results. + * @param {Function} failure A function to call in case of failure, receiving the error message. + */ +export async function transport(selector, query, callback, failure) { + + const request = { + methodname: 'core_user_search_identity', + args: { + query: query + } + }; + + try { + const response = await Ajax.call([request])[0]; + + if (response.overflow) { + const msg = await getString('toomanyuserstoshow', 'core', '>' + response.maxusersperpage); + callback(msg); + + } else { + let labels = []; + response.list.forEach(user => { + labels.push(renderTemplate('core_user/form_user_selector_suggestion', user)); + }); + labels = await Promise.all(labels); + + response.list.forEach((user, index) => { + user.label = labels[index]; + }); + + callback(response.list); + } + + } catch (e) { + failure(e); + } +} + +/** + * Process the results for auto complete elements. + * + * @param {String} selector The selector of the auto complete element. + * @param {Array} results An array or results returned by {@see transport()}. + * @return {Array} New array of the selector options. + */ +export function processResults(selector, results) { + + if (!Array.isArray(results)) { + return results; + + } else { + return results.map(result => ({value: result.id, label: result.label})); + } +} diff --git a/user/templates/form_user_selector_suggestion.mustache b/user/templates/form_user_selector_suggestion.mustache new file mode 100644 index 00000000000..abec063a0a7 --- /dev/null +++ b/user/templates/form_user_selector_suggestion.mustache @@ -0,0 +1,54 @@ +{{! + This file is part of Moodle - https://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core_user/form_user_selector_suggestion + + Moodle template for the list of valid options in an user selector autocomplate form element. + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Context variables required for this template: + * fullname - string Users full name + * extrafields - list + + Example context (json): + { + "fullname": "Admin User", + "extrafields": [ + { + "name": "email", + "value": "admin@example.com" + }, + { + "name": "phone1", + "value": "0123456789" + } + ] + } +}} + + {{fullname}} + + {{#extrafields}} + {{{value}}} + {{/extrafields}} + + diff --git a/user/upgrade.txt b/user/upgrade.txt index 3d4c3624782..d20af1afffd 100644 --- a/user/upgrade.txt +++ b/user/upgrade.txt @@ -2,6 +2,8 @@ This files describes API changes for code that uses the user API. === 3.11 === +* Added new core_user/form_user_selector JS module that can be used as the 'ajax' handler for the autocomplete form + element implementing the user selector. * Added new external function core_user_external::search_identity(). The main purpose of this external function is to provide data for asynchronous user selectors and similar widgets. It allows to search users matching the given query in their name or other available identity fields.