diff --git a/.eslintrc b/.eslintrc
index a388f57560c..0493181083f 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -227,7 +227,7 @@
},
// We're using babel transpiling so use their parser
// for linting.
- parser: 'babel-eslint',
+ parser: '@babel/eslint-parser',
// Check AMD with some slightly stricter rules.
rules: {
'no-unused-vars': 'error',
@@ -300,7 +300,8 @@
},
parserOptions: {
'ecmaVersion': 9,
- 'sourceType': 'module'
+ 'sourceType': 'module',
+ 'requireConfigFile': false,
}
}
]
diff --git a/.gitignore b/.gitignore
index 0a44a94ce68..780bcc878fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,3 +53,4 @@ moodle-plugin-ci.phar
/jsdoc
/admin/tool/componentlibrary/docs
/admin/tool/componentlibrary/hugo/site/data/my-index.json
+.hugo_build.lock
diff --git a/.grunt/tasks/javascript.js b/.grunt/tasks/javascript.js
index 5761f9206fd..9533f18db64 100644
--- a/.grunt/tasks/javascript.js
+++ b/.grunt/tasks/javascript.js
@@ -30,6 +30,7 @@
* @param {String} srcPath the matched src path
* @return {String} The rewritten destination path.
*/
+
const babelRename = function(destPath, srcPath) {
destPath = srcPath.replace('src', 'build');
destPath = destPath.replace('.js', '.min.js');
@@ -53,65 +54,139 @@ module.exports = grunt => {
// Register JS tasks.
grunt.registerTask('yui', ['eslint:yui', 'shifter']);
- grunt.registerTask('amd', ['ignorefiles', 'eslint:amd', 'babel']);
+ grunt.registerTask('amd', ['ignorefiles', 'eslint:amd', 'rollup']);
grunt.registerTask('js', ['amd', 'yui']);
// Register NPM tasks.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
+ grunt.loadNpmTasks('grunt-rollup');
- // Load the Babel tasks and config.
- grunt.loadNpmTasks('grunt-babel');
+ const babelTransform = require('@babel/core').transform;
+ const babel = (options = {}) => {
+ return {
+ name: 'babel',
+
+ transform: (code, id) => {
+ grunt.log.debug(`Transforming ${id}`);
+ options.filename = id;
+ const transformed = babelTransform(code, options);
+
+ return {
+ code: transformed.code,
+ map: transformed.map
+ };
+ }
+ };
+ };
+
+ // Note: We have to use a rate limit plugin here because rollup runs all tasks asynchronously and in parallel.
+ // When we kick off a full run, if we kick off a rollup of every file this will fork-bomb the machine.
+ // To work around this we use a concurrent Promise queue based on the number of available processors.
+ const rateLimit = () => {
+ const queue = [];
+ let queueRunner;
+
+ const startQueue = () => {
+ if (queueRunner) {
+ return;
+ }
+
+ queueRunner = setTimeout(() => {
+ const limit = Math.max(1, require('os').cpus().length / 2);
+ grunt.log.debug(`Starting rollup with queue size of ${limit}`);
+ runQueue(limit);
+ }, 100);
+ };
+
+ // The queue runner will run the next `size` items in the queue.
+ const runQueue = (size = 1) => {
+ queue.splice(0, size).forEach(resolve => {
+ resolve();
+ });
+ };
+
+ return {
+ name: 'ratelimit',
+
+ // The options hook is run in parallel.
+ // We can return an unresolved Promise which is queued for later resolution.
+ options: async() => {
+ return new Promise(resolve => {
+ queue.push(resolve);
+ startQueue();
+ });
+ },
+
+ // When an item in the queue completes, start the next item in the queue.
+ buildEnd: () => {
+ runQueue();
+ },
+ };
+ };
+
+ const terser = require('rollup-plugin-terser').terser;
grunt.config.merge({
- babel: {
+ rollup: {
options: {
- sourceMaps: true,
- comments: false,
+ format: 'esm',
+ dir: 'output',
+ sourcemap: true,
+ treeshake: false,
+ context: 'window',
plugins: [
- 'transform-es2015-modules-amd-lazy',
- 'system-import-transformer',
- // This plugin modifies the Babel transpiling for "export default"
- // so that if it's used then only the exported value is returned
- // by the generated AMD module.
- //
- // It also adds the Moodle plugin name to the AMD module definition
- // so that it can be imported as expected in other modules.
- path.resolve('.grunt/babel-plugin-add-module-to-define.js'),
- '@babel/plugin-syntax-dynamic-import',
- '@babel/plugin-syntax-import-meta',
- ['@babel/plugin-proposal-class-properties', {'loose': false}],
- '@babel/plugin-proposal-json-strings'
+ rateLimit(),
+ babel({
+ sourceMaps: true,
+ comments: false,
+ compact: false,
+ plugins: [
+ 'transform-es2015-modules-amd-lazy',
+ 'system-import-transformer',
+ // This plugin modifies the Babel transpiling for "export default"
+ // so that if it's used then only the exported value is returned
+ // by the generated AMD module.
+ //
+ // It also adds the Moodle plugin name to the AMD module definition
+ // so that it can be imported as expected in other modules.
+ path.resolve('.grunt/babel-plugin-add-module-to-define.js'),
+ '@babel/plugin-syntax-dynamic-import',
+ '@babel/plugin-syntax-import-meta',
+ ['@babel/plugin-proposal-class-properties', {'loose': false}],
+ '@babel/plugin-proposal-json-strings'
+ ],
+ presets: [
+ ['@babel/preset-env', {
+ targets: {
+ browsers: [
+ ">0.3%",
+ "last 2 versions",
+ "not ie >= 0",
+ "not op_mini all",
+ "not Opera > 0",
+ "not dead"
+ ]
+ },
+ modules: false,
+ useBuiltIns: false
+ }]
+ ]
+ }),
+
+ terser({
+ // Do not mangle variables.
+ // Makes debugging easier.
+ mangle: false,
+ }),
],
- presets: [
- ['minify', {
- // This minification plugin needs to be disabled because it breaks the
- // source map generation and causes invalid source maps to be output.
- simplify: false,
- builtIns: false
- }],
- ['@babel/preset-env', {
- targets: {
- browsers: [
- ">0.25%",
- "last 2 versions",
- "not ie <= 10",
- "not op_mini all",
- "not Opera > 0",
- "not dead"
- ]
- },
- modules: false,
- useBuiltIns: false
- }]
- ]
},
dist: {
files: [{
expand: true,
src: grunt.moodleEnv.files ? grunt.moodleEnv.files : grunt.moodleEnv.amdSrc,
rename: babelRename
- }]
- }
+ }],
+ },
},
});
@@ -135,7 +210,7 @@ module.exports = grunt => {
let changedFiles = Object.create(null);
const onChange = grunt.util._.debounce(function() {
const files = Object.keys(changedFiles);
- grunt.config('babel.dist.files', [{expand: true, src: files, rename: babelRename}]);
+ grunt.config('rollup.dist.files', [{expand: true, src: files, rename: babelRename}]);
changedFiles = Object.create(null);
}, 200);
diff --git a/.nvmrc b/.nvmrc
index b2d264b67df..53d838af215 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-v14.18.0
+lts/gallium
diff --git a/admin/tool/analytics/amd/build/log_info.min.js b/admin/tool/analytics/amd/build/log_info.min.js
index 9b48cc9f4e7..71c8acc96cf 100644
--- a/admin/tool/analytics/amd/build/log_info.min.js
+++ b/admin/tool/analytics/amd/build/log_info.min.js
@@ -1,2 +1,10 @@
-define ("tool_analytics/log_info",["jquery","core/str","core/modal_factory","core/notification"],function(a,b,c,d){return{loadInfo:function loadInfo(e,f){var g=a("[data-model-log-id=\""+e+"\"]");b.get_string("loginfo","tool_analytics").then(function(b){var d=a("
");f.forEach(function(a){d.append("
"+a+"
")});d.append("
");return c.create({title:b,body:d.html(),large:!0},g)}).catch(d.exception)}}});
-//# sourceMappingURL=log_info.min.js.map
+/**
+ * Shows a dialogue with info about this logs.
+ *
+ * @module tool_analytics/log_info
+ * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_analytics/log_info",["jquery","core/str","core/modal_factory","core/notification"],(function($,str,ModalFactory,Notification){return{loadInfo:function(id,info){var link=$('[data-model-log-id="'+id+'"]');str.get_string("loginfo","tool_analytics").then((function(langString){var bodyInfo=$("
"),ModalFactory.create({title:langString,body:bodyInfo.html(),large:!0},link)})).catch(Notification.exception)}}}));
+
+//# sourceMappingURL=log_info.min.js.map
\ No newline at end of file
diff --git a/admin/tool/analytics/amd/build/log_info.min.js.map b/admin/tool/analytics/amd/build/log_info.min.js.map
index c3243b8a2f8..38c60d0eedc 100644
--- a/admin/tool/analytics/amd/build/log_info.min.js.map
+++ b/admin/tool/analytics/amd/build/log_info.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/log_info.js"],"names":["define","$","str","ModalFactory","Notification","loadInfo","id","info","link","get_string","then","langString","bodyInfo","forEach","item","append","create","title","body","html","large","catch","exception"],"mappings":"AAsBAA,OAAM,2BAAC,CAAC,QAAD,CAAW,UAAX,CAAuB,oBAAvB,CAA6C,mBAA7C,CAAD,CAAoE,SAASC,CAAT,CAAYC,CAAZ,CAAiBC,CAAjB,CAA+BC,CAA/B,CAA6C,CAEnH,MAAoD,CAShDC,QAAQ,CAAE,kBAASC,CAAT,CAAaC,CAAb,CAAmB,CAEzB,GAAIC,CAAAA,CAAI,CAAGP,CAAC,CAAC,wBAAyBK,CAAzB,CAA8B,KAA/B,CAAZ,CACAJ,CAAG,CAACO,UAAJ,CAAe,SAAf,CAA0B,gBAA1B,EAA4CC,IAA5C,CAAiD,SAASC,CAAT,CAAqB,CAElE,GAAIC,CAAAA,CAAQ,CAAGX,CAAC,CAAC,MAAD,CAAhB,CACAM,CAAI,CAACM,OAAL,CAAa,SAASC,CAAT,CAAe,CACxBF,CAAQ,CAACG,MAAT,CAAgB,OAASD,CAAT,CAAgB,OAAhC,CACH,CAFD,EAGAF,CAAQ,CAACG,MAAT,CAAgB,OAAhB,EAEA,MAAOZ,CAAAA,CAAY,CAACa,MAAb,CAAoB,CACvBC,KAAK,CAAEN,CADgB,CAEvBO,IAAI,CAAEN,CAAQ,CAACO,IAAT,EAFiB,CAGvBC,KAAK,GAHkB,CAApB,CAIJZ,CAJI,CAMV,CAdD,EAcGa,KAdH,CAcSjB,CAAY,CAACkB,SAdtB,CAeH,CA3B+C,CA6BvD,CA/BK,CAAN","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 .\n\n/**\n * Shows a dialogue with info about this logs.\n *\n * @module tool_analytics/log_info\n * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/str', 'core/modal_factory', 'core/notification'], function($, str, ModalFactory, Notification) {\n\n return /** @alias module:tool_analytics/log_info */ {\n\n /**\n * Prepares a modal info for a log's results.\n *\n * @method loadInfo\n * @param {int} id\n * @param {string[]} info\n */\n loadInfo: function(id, info) {\n\n var link = $('[data-model-log-id=\"' + id + '\"]');\n str.get_string('loginfo', 'tool_analytics').then(function(langString) {\n\n var bodyInfo = $(\"
\");\n\n return ModalFactory.create({\n title: langString,\n body: bodyInfo.html(),\n large: true,\n }, link);\n\n }).catch(Notification.exception);\n }\n };\n});\n"],"file":"log_info.min.js"}
\ No newline at end of file
+{"version":3,"file":"log_info.min.js","sources":["../src/log_info.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 .\n\n/**\n * Shows a dialogue with info about this logs.\n *\n * @module tool_analytics/log_info\n * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/str', 'core/modal_factory', 'core/notification'], function($, str, ModalFactory, Notification) {\n\n return /** @alias module:tool_analytics/log_info */ {\n\n /**\n * Prepares a modal info for a log's results.\n *\n * @method loadInfo\n * @param {int} id\n * @param {string[]} info\n */\n loadInfo: function(id, info) {\n\n var link = $('[data-model-log-id=\"' + id + '\"]');\n str.get_string('loginfo', 'tool_analytics').then(function(langString) {\n\n var bodyInfo = $(\"
\");\n\n return ModalFactory.create({\n title: langString,\n body: bodyInfo.html(),\n large: true,\n }, link);\n\n }).catch(Notification.exception);\n }\n };\n});\n"],"names":["define","$","str","ModalFactory","Notification","loadInfo","id","info","link","get_string","then","langString","bodyInfo","forEach","item","append","create","title","body","html","large","catch","exception"],"mappings":";;;;;;;AAsBAA,iCAAO,CAAC,SAAU,WAAY,qBAAsB,sBAAsB,SAASC,EAAGC,IAAKC,aAAcC,oBAEjD,CAShDC,SAAU,SAASC,GAAIC,UAEfC,KAAOP,EAAE,uBAAyBK,GAAK,MAC3CJ,IAAIO,WAAW,UAAW,kBAAkBC,MAAK,SAASC,gBAElDC,SAAWX,EAAE,eACjBM,KAAKM,SAAQ,SAASC,MAClBF,SAASG,OAAO,OAASD,KAAO,YAEpCF,SAASG,OAAO,SAETZ,aAAaa,OAAO,CACvBC,MAAON,WACPO,KAAMN,SAASO,OACfC,OAAO,GACRZ,SAEJa,MAAMjB,aAAakB"}
\ No newline at end of file
diff --git a/admin/tool/analytics/amd/build/model.min.js b/admin/tool/analytics/amd/build/model.min.js
index 05c30735ae0..6c8812c6022 100644
--- a/admin/tool/analytics/amd/build/model.min.js
+++ b/admin/tool/analytics/amd/build/model.min.js
@@ -1,2 +1,10 @@
-define ("tool_analytics/model",["jquery","core/str","core/log","core/notification","core/modal_factory","core/modal_events","core/templates"],function(b,c,d,e,f,g,h){var i={clear:{title:{key:"clearpredictions",component:"tool_analytics"},body:{key:"clearmodelpredictions",component:"tool_analytics"}},delete:{title:{key:"delete",component:"tool_analytics"},body:{key:"deletemodelconfirmation",component:"tool_analytics"}}},j=function(a){var c=b(a).closest("[data-model-name]");if(c.length){return c.attr("data-model-name")}else{d.error("Unexpected DOM error - unable to obtain the model name");return""}};return{confirmAction:function confirmAction(a,h){b("[data-action-id=\""+a+"\"]").on("click",function(k){k.preventDefault();var l=b(k.currentTarget);if("undefined"==typeof i[h]){d.error("Action \""+h+"\" is not allowed.");return}var a=[i[h].title,i[h].body];a[1].param=j(l);var m=c.get_strings(a),n=f.create({type:f.types.SAVE_CANCEL});b.when(m,n).then(function(a,b){b.setTitle(a[0]);b.setBody(a[1]);b.setSaveButtonText(a[0]);b.getRoot().on(g.save,function(){window.location.href=l.attr("href")});b.show();return b}).fail(e.exception)})},selectEvaluationOptions:function selectEvaluationOptions(a,d){b("[data-action-id=\""+a+"\"]").on("click",function(i){i.preventDefault();var j=b(i.currentTarget),a=b(this).attr("data-timesplitting-methods"),k=c.get_strings([{key:"evaluatemodel",component:"tool_analytics"},{key:"evaluate",component:"tool_analytics"}]),l=f.create({type:f.types.SAVE_CANCEL}),m=h.render("tool_analytics/evaluation_options",{trainedexternally:d,timesplittingmethods:JSON.parse(a)});b.when(k,l).then(function(a,c){c.getRoot().on(g.hidden,c.destroy.bind(c));c.setTitle(a[0]);c.setSaveButtonText(a[1]);c.setBody(m);c.getRoot().on(g.save,function(){var a=b("input[name='evaluationmode']:checked").val();if("trainedmodel"==a){j.attr("href",j.attr("href")+"&mode=trainedmodel")}var c=b("#id-evaluation-timesplitting").val();j.attr("href",j.attr("href")+"×plitting="+c);window.location.href=j.attr("href")});c.show();return c}).fail(e.exception)})},selectExportOptions:function selectExportOptions(a,d){b("[data-action-id=\""+a+"\"]").on("click",function(i){i.preventDefault();var j=b(i.currentTarget);if(!d){j.attr("href",j.attr("href")+"&action=exportmodel&includeweights=0");window.location.href=j.attr("href");return}var a=c.get_strings([{key:"export",component:"tool_analytics"}]),k=f.create({type:f.types.SAVE_CANCEL}),l=h.render("tool_analytics/export_options",{});b.when(a,k).then(function(a,c){c.getRoot().on(g.hidden,c.destroy.bind(c));c.setTitle(a[0]);c.setSaveButtonText(a[0]);c.setBody(l);c.getRoot().on(g.save,function(){var a=b("input[name='exportoption']:checked").val();if("exportdata"==a){j.attr("href",j.attr("href")+"&action=exportdata")}else{j.attr("href",j.attr("href")+"&action=exportmodel");if(b("#id-includeweights").is(":checked")){j.attr("href",j.attr("href")+"&includeweights=1")}else{j.attr("href",j.attr("href")+"&includeweights=0")}}window.location.href=j.attr("href")});c.show();return c}).fail(e.exception)})}}});
-//# sourceMappingURL=model.min.js.map
+/**
+ * AMD module for model actions confirmation.
+ *
+ * @module tool_analytics/model
+ * @copyright 2017 David Monllao
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_analytics/model",["jquery","core/str","core/log","core/notification","core/modal_factory","core/modal_events","core/templates"],(function($,Str,log,Notification,ModalFactory,ModalEvents,Templates){var actionsList={clear:{title:{key:"clearpredictions",component:"tool_analytics"},body:{key:"clearmodelpredictions",component:"tool_analytics"}},delete:{title:{key:"delete",component:"tool_analytics"},body:{key:"deletemodelconfirmation",component:"tool_analytics"}}};return{confirmAction:function(actionId,actionType){$('[data-action-id="'+actionId+'"]').on("click",(function(ev){ev.preventDefault();var a=$(ev.currentTarget);if(void 0!==actionsList[actionType]){var wrap,reqStrings=[actionsList[actionType].title,actionsList[actionType].body];reqStrings[1].param=(wrap=$(a).closest("[data-model-name]")).length?wrap.attr("data-model-name"):(log.error("Unexpected DOM error - unable to obtain the model name"),"");var stringsPromise=Str.get_strings(reqStrings),modalPromise=ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL});$.when(stringsPromise,modalPromise).then((function(strings,modal){return modal.setTitle(strings[0]),modal.setBody(strings[1]),modal.setSaveButtonText(strings[0]),modal.getRoot().on(ModalEvents.save,(function(){window.location.href=a.attr("href")})),modal.show(),modal})).fail(Notification.exception)}else log.error('Action "'+actionType+'" is not allowed.')}))},selectEvaluationOptions:function(actionId,trainedOnlyExternally){$('[data-action-id="'+actionId+'"]').on("click",(function(ev){ev.preventDefault();var a=$(ev.currentTarget),timeSplittingMethods=$(this).attr("data-timesplitting-methods"),stringsPromise=Str.get_strings([{key:"evaluatemodel",component:"tool_analytics"},{key:"evaluate",component:"tool_analytics"}]),modalPromise=ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL}),bodyPromise=Templates.render("tool_analytics/evaluation_options",{trainedexternally:trainedOnlyExternally,timesplittingmethods:JSON.parse(timeSplittingMethods)});$.when(stringsPromise,modalPromise).then((function(strings,modal){return modal.getRoot().on(ModalEvents.hidden,modal.destroy.bind(modal)),modal.setTitle(strings[0]),modal.setSaveButtonText(strings[1]),modal.setBody(bodyPromise),modal.getRoot().on(ModalEvents.save,(function(){"trainedmodel"==$("input[name='evaluationmode']:checked").val()&&a.attr("href",a.attr("href")+"&mode=trainedmodel");var timeSplittingMethod=$("#id-evaluation-timesplitting").val();a.attr("href",a.attr("href")+"×plitting="+timeSplittingMethod),window.location.href=a.attr("href")})),modal.show(),modal})).fail(Notification.exception)}))},selectExportOptions:function(actionId,isTrained){$('[data-action-id="'+actionId+'"]').on("click",(function(ev){ev.preventDefault();var a=$(ev.currentTarget);if(!isTrained)return a.attr("href",a.attr("href")+"&action=exportmodel&includeweights=0"),void(window.location.href=a.attr("href"));var stringsPromise=Str.get_strings([{key:"export",component:"tool_analytics"}]),modalPromise=ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL}),bodyPromise=Templates.render("tool_analytics/export_options",{});$.when(stringsPromise,modalPromise).then((function(strings,modal){return modal.getRoot().on(ModalEvents.hidden,modal.destroy.bind(modal)),modal.setTitle(strings[0]),modal.setSaveButtonText(strings[0]),modal.setBody(bodyPromise),modal.getRoot().on(ModalEvents.save,(function(){"exportdata"==$("input[name='exportoption']:checked").val()?a.attr("href",a.attr("href")+"&action=exportdata"):(a.attr("href",a.attr("href")+"&action=exportmodel"),$("#id-includeweights").is(":checked")?a.attr("href",a.attr("href")+"&includeweights=1"):a.attr("href",a.attr("href")+"&includeweights=0")),window.location.href=a.attr("href")})),modal.show(),modal})).fail(Notification.exception)}))}}}));
+
+//# sourceMappingURL=model.min.js.map
\ No newline at end of file
diff --git a/admin/tool/analytics/amd/build/model.min.js.map b/admin/tool/analytics/amd/build/model.min.js.map
index 1ea039bdf3b..f50f1c0f05a 100644
--- a/admin/tool/analytics/amd/build/model.min.js.map
+++ b/admin/tool/analytics/amd/build/model.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/model.js"],"names":["define","$","Str","log","Notification","ModalFactory","ModalEvents","Templates","actionsList","clear","title","key","component","body","getModelName","actionItem","wrap","closest","length","attr","error","confirmAction","actionId","actionType","on","ev","preventDefault","a","currentTarget","reqStrings","param","stringsPromise","get_strings","modalPromise","create","type","types","SAVE_CANCEL","when","then","strings","modal","setTitle","setBody","setSaveButtonText","getRoot","save","window","location","href","show","fail","exception","selectEvaluationOptions","trainedOnlyExternally","timeSplittingMethods","bodyPromise","render","trainedexternally","timesplittingmethods","JSON","parse","hidden","destroy","bind","evaluationMode","val","timeSplittingMethod","selectExportOptions","isTrained","exportOption","is"],"mappings":"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","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 .\n\n/**\n * AMD module for model actions confirmation.\n *\n * @module tool_analytics/model\n * @copyright 2017 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/str', 'core/log', 'core/notification', 'core/modal_factory', 'core/modal_events', 'core/templates'],\n function($, Str, log, Notification, ModalFactory, ModalEvents, Templates) {\n\n /**\n * List of actions that require confirmation and confirmation message.\n */\n var actionsList = {\n clear: {\n title: {\n key: 'clearpredictions',\n component: 'tool_analytics'\n }, body: {\n key: 'clearmodelpredictions',\n component: 'tool_analytics'\n }\n\n },\n 'delete': {\n title: {\n key: 'delete',\n component: 'tool_analytics'\n }, body: {\n key: 'deletemodelconfirmation',\n component: 'tool_analytics'\n }\n }\n };\n\n /**\n * Returns the model name.\n *\n * @param {Object} actionItem The action item DOM node.\n * @return {String}\n */\n var getModelName = function(actionItem) {\n var wrap = $(actionItem).closest('[data-model-name]');\n\n if (wrap.length) {\n return wrap.attr('data-model-name');\n\n } else {\n log.error('Unexpected DOM error - unable to obtain the model name');\n return '';\n }\n };\n\n /** @alias module:tool_analytics/model */\n return {\n\n /**\n * Displays a confirm modal window before executing the action.\n *\n * @param {String} actionId\n * @param {String} actionType\n */\n confirmAction: function(actionId, actionType) {\n $('[data-action-id=\"' + actionId + '\"]').on('click', function(ev) {\n ev.preventDefault();\n\n var a = $(ev.currentTarget);\n\n if (typeof actionsList[actionType] === \"undefined\") {\n log.error('Action \"' + actionType + '\" is not allowed.');\n return;\n }\n\n var reqStrings = [\n actionsList[actionType].title,\n actionsList[actionType].body\n ];\n reqStrings[1].param = getModelName(a);\n\n var stringsPromise = Str.get_strings(reqStrings);\n var modalPromise = ModalFactory.create({type: ModalFactory.types.SAVE_CANCEL});\n\n $.when(stringsPromise, modalPromise).then(function(strings, modal) {\n modal.setTitle(strings[0]);\n modal.setBody(strings[1]);\n modal.setSaveButtonText(strings[0]);\n modal.getRoot().on(ModalEvents.save, function() {\n window.location.href = a.attr('href');\n });\n modal.show();\n return modal;\n }).fail(Notification.exception);\n });\n },\n\n /**\n * Displays evaluation mode and time-splitting method choices.\n *\n * @param {String} actionId\n * @param {Boolean} trainedOnlyExternally\n */\n selectEvaluationOptions: function(actionId, trainedOnlyExternally) {\n $('[data-action-id=\"' + actionId + '\"]').on('click', function(ev) {\n ev.preventDefault();\n\n var a = $(ev.currentTarget);\n\n var timeSplittingMethods = $(this).attr('data-timesplitting-methods');\n\n var stringsPromise = Str.get_strings([\n {\n key: 'evaluatemodel',\n component: 'tool_analytics'\n }, {\n key: 'evaluate',\n component: 'tool_analytics'\n }\n ]);\n var modalPromise = ModalFactory.create({type: ModalFactory.types.SAVE_CANCEL});\n var bodyPromise = Templates.render('tool_analytics/evaluation_options', {\n trainedexternally: trainedOnlyExternally,\n timesplittingmethods: JSON.parse(timeSplittingMethods)\n });\n\n $.when(stringsPromise, modalPromise).then(function(strings, modal) {\n\n\n modal.getRoot().on(ModalEvents.hidden, modal.destroy.bind(modal));\n\n modal.setTitle(strings[0]);\n modal.setSaveButtonText(strings[1]);\n modal.setBody(bodyPromise);\n\n modal.getRoot().on(ModalEvents.save, function() {\n\n // Evaluation mode.\n var evaluationMode = $(\"input[name='evaluationmode']:checked\").val();\n if (evaluationMode == 'trainedmodel') {\n a.attr('href', a.attr('href') + '&mode=trainedmodel');\n }\n\n // Selected time-splitting id.\n var timeSplittingMethod = $(\"#id-evaluation-timesplitting\").val();\n a.attr('href', a.attr('href') + '×plitting=' + timeSplittingMethod);\n\n window.location.href = a.attr('href');\n return;\n });\n\n modal.show();\n return modal;\n }).fail(Notification.exception);\n });\n },\n\n /**\n * Displays export options.\n *\n * We have two main options: export training data and export configuration.\n * The 2nd option has an extra option: include the trained algorithm weights.\n *\n * @param {String} actionId\n * @param {Boolean} isTrained\n */\n selectExportOptions: function(actionId, isTrained) {\n $('[data-action-id=\"' + actionId + '\"]').on('click', function(ev) {\n ev.preventDefault();\n\n var a = $(ev.currentTarget);\n\n if (!isTrained) {\n // Export the model configuration if the model is not trained. We can't export anything else.\n a.attr('href', a.attr('href') + '&action=exportmodel&includeweights=0');\n window.location.href = a.attr('href');\n return;\n }\n\n var stringsPromise = Str.get_strings([\n {\n key: 'export',\n component: 'tool_analytics'\n }\n ]);\n var modalPromise = ModalFactory.create({type: ModalFactory.types.SAVE_CANCEL});\n var bodyPromise = Templates.render('tool_analytics/export_options', {});\n\n $.when(stringsPromise, modalPromise).then(function(strings, modal) {\n\n modal.getRoot().on(ModalEvents.hidden, modal.destroy.bind(modal));\n\n modal.setTitle(strings[0]);\n modal.setSaveButtonText(strings[0]);\n modal.setBody(bodyPromise);\n\n modal.getRoot().on(ModalEvents.save, function() {\n\n var exportOption = $(\"input[name='exportoption']:checked\").val();\n\n if (exportOption == 'exportdata') {\n a.attr('href', a.attr('href') + '&action=exportdata');\n\n } else {\n a.attr('href', a.attr('href') + '&action=exportmodel');\n if ($(\"#id-includeweights\").is(':checked')) {\n a.attr('href', a.attr('href') + '&includeweights=1');\n } else {\n a.attr('href', a.attr('href') + '&includeweights=0');\n }\n }\n\n window.location.href = a.attr('href');\n return;\n });\n\n modal.show();\n return modal;\n }).fail(Notification.exception);\n });\n }\n };\n});\n"],"file":"model.min.js"}
\ No newline at end of file
+{"version":3,"file":"model.min.js","sources":["../src/model.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 .\n\n/**\n * AMD module for model actions confirmation.\n *\n * @module tool_analytics/model\n * @copyright 2017 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/str', 'core/log', 'core/notification', 'core/modal_factory', 'core/modal_events', 'core/templates'],\n function($, Str, log, Notification, ModalFactory, ModalEvents, Templates) {\n\n /**\n * List of actions that require confirmation and confirmation message.\n */\n var actionsList = {\n clear: {\n title: {\n key: 'clearpredictions',\n component: 'tool_analytics'\n }, body: {\n key: 'clearmodelpredictions',\n component: 'tool_analytics'\n }\n\n },\n 'delete': {\n title: {\n key: 'delete',\n component: 'tool_analytics'\n }, body: {\n key: 'deletemodelconfirmation',\n component: 'tool_analytics'\n }\n }\n };\n\n /**\n * Returns the model name.\n *\n * @param {Object} actionItem The action item DOM node.\n * @return {String}\n */\n var getModelName = function(actionItem) {\n var wrap = $(actionItem).closest('[data-model-name]');\n\n if (wrap.length) {\n return wrap.attr('data-model-name');\n\n } else {\n log.error('Unexpected DOM error - unable to obtain the model name');\n return '';\n }\n };\n\n /** @alias module:tool_analytics/model */\n return {\n\n /**\n * Displays a confirm modal window before executing the action.\n *\n * @param {String} actionId\n * @param {String} actionType\n */\n confirmAction: function(actionId, actionType) {\n $('[data-action-id=\"' + actionId + '\"]').on('click', function(ev) {\n ev.preventDefault();\n\n var a = $(ev.currentTarget);\n\n if (typeof actionsList[actionType] === \"undefined\") {\n log.error('Action \"' + actionType + '\" is not allowed.');\n return;\n }\n\n var reqStrings = [\n actionsList[actionType].title,\n actionsList[actionType].body\n ];\n reqStrings[1].param = getModelName(a);\n\n var stringsPromise = Str.get_strings(reqStrings);\n var modalPromise = ModalFactory.create({type: ModalFactory.types.SAVE_CANCEL});\n\n $.when(stringsPromise, modalPromise).then(function(strings, modal) {\n modal.setTitle(strings[0]);\n modal.setBody(strings[1]);\n modal.setSaveButtonText(strings[0]);\n modal.getRoot().on(ModalEvents.save, function() {\n window.location.href = a.attr('href');\n });\n modal.show();\n return modal;\n }).fail(Notification.exception);\n });\n },\n\n /**\n * Displays evaluation mode and time-splitting method choices.\n *\n * @param {String} actionId\n * @param {Boolean} trainedOnlyExternally\n */\n selectEvaluationOptions: function(actionId, trainedOnlyExternally) {\n $('[data-action-id=\"' + actionId + '\"]').on('click', function(ev) {\n ev.preventDefault();\n\n var a = $(ev.currentTarget);\n\n var timeSplittingMethods = $(this).attr('data-timesplitting-methods');\n\n var stringsPromise = Str.get_strings([\n {\n key: 'evaluatemodel',\n component: 'tool_analytics'\n }, {\n key: 'evaluate',\n component: 'tool_analytics'\n }\n ]);\n var modalPromise = ModalFactory.create({type: ModalFactory.types.SAVE_CANCEL});\n var bodyPromise = Templates.render('tool_analytics/evaluation_options', {\n trainedexternally: trainedOnlyExternally,\n timesplittingmethods: JSON.parse(timeSplittingMethods)\n });\n\n $.when(stringsPromise, modalPromise).then(function(strings, modal) {\n\n\n modal.getRoot().on(ModalEvents.hidden, modal.destroy.bind(modal));\n\n modal.setTitle(strings[0]);\n modal.setSaveButtonText(strings[1]);\n modal.setBody(bodyPromise);\n\n modal.getRoot().on(ModalEvents.save, function() {\n\n // Evaluation mode.\n var evaluationMode = $(\"input[name='evaluationmode']:checked\").val();\n if (evaluationMode == 'trainedmodel') {\n a.attr('href', a.attr('href') + '&mode=trainedmodel');\n }\n\n // Selected time-splitting id.\n var timeSplittingMethod = $(\"#id-evaluation-timesplitting\").val();\n a.attr('href', a.attr('href') + '×plitting=' + timeSplittingMethod);\n\n window.location.href = a.attr('href');\n return;\n });\n\n modal.show();\n return modal;\n }).fail(Notification.exception);\n });\n },\n\n /**\n * Displays export options.\n *\n * We have two main options: export training data and export configuration.\n * The 2nd option has an extra option: include the trained algorithm weights.\n *\n * @param {String} actionId\n * @param {Boolean} isTrained\n */\n selectExportOptions: function(actionId, isTrained) {\n $('[data-action-id=\"' + actionId + '\"]').on('click', function(ev) {\n ev.preventDefault();\n\n var a = $(ev.currentTarget);\n\n if (!isTrained) {\n // Export the model configuration if the model is not trained. We can't export anything else.\n a.attr('href', a.attr('href') + '&action=exportmodel&includeweights=0');\n window.location.href = a.attr('href');\n return;\n }\n\n var stringsPromise = Str.get_strings([\n {\n key: 'export',\n component: 'tool_analytics'\n }\n ]);\n var modalPromise = ModalFactory.create({type: ModalFactory.types.SAVE_CANCEL});\n var bodyPromise = Templates.render('tool_analytics/export_options', {});\n\n $.when(stringsPromise, modalPromise).then(function(strings, modal) {\n\n modal.getRoot().on(ModalEvents.hidden, modal.destroy.bind(modal));\n\n modal.setTitle(strings[0]);\n modal.setSaveButtonText(strings[0]);\n modal.setBody(bodyPromise);\n\n modal.getRoot().on(ModalEvents.save, function() {\n\n var exportOption = $(\"input[name='exportoption']:checked\").val();\n\n if (exportOption == 'exportdata') {\n a.attr('href', a.attr('href') + '&action=exportdata');\n\n } else {\n a.attr('href', a.attr('href') + '&action=exportmodel');\n if ($(\"#id-includeweights\").is(':checked')) {\n a.attr('href', a.attr('href') + '&includeweights=1');\n } else {\n a.attr('href', a.attr('href') + '&includeweights=0');\n }\n }\n\n window.location.href = a.attr('href');\n return;\n });\n\n modal.show();\n return modal;\n }).fail(Notification.exception);\n });\n }\n };\n});\n"],"names":["define","$","Str","log","Notification","ModalFactory","ModalEvents","Templates","actionsList","clear","title","key","component","body","confirmAction","actionId","actionType","on","ev","preventDefault","a","currentTarget","wrap","reqStrings","param","closest","length","attr","error","stringsPromise","get_strings","modalPromise","create","type","types","SAVE_CANCEL","when","then","strings","modal","setTitle","setBody","setSaveButtonText","getRoot","save","window","location","href","show","fail","exception","selectEvaluationOptions","trainedOnlyExternally","timeSplittingMethods","this","bodyPromise","render","trainedexternally","timesplittingmethods","JSON","parse","hidden","destroy","bind","val","timeSplittingMethod","selectExportOptions","isTrained","is"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/analytics/amd/build/potential-contexts.min.js b/admin/tool/analytics/amd/build/potential-contexts.min.js
index c93ee47896f..a6c87044eb6 100644
--- a/admin/tool/analytics/amd/build/potential-contexts.min.js
+++ b/admin/tool/analytics/amd/build/potential-contexts.min.js
@@ -1,2 +1,10 @@
-define ("tool_analytics/potential-contexts",["jquery","core/ajax"],function(a,b){return{processResults:function processResults(b,c){var d=[];if(a.isArray(c)){a.each(c,function(a,b){d.push({value:b.id,label:b.name})});return d}else{return c}},transport:function transport(c,d,e,f){var g,h=a(c).attr("modelid")||null;g=b.call([{methodname:"tool_analytics_potential_contexts",args:{query:d,modelid:h}}]);g[0].then(e).fail(f)}}});
-//# sourceMappingURL=potential-contexts.min.js.map
+/**
+ * Potential contexts selector module.
+ *
+ * @module tool_analytics/potential-contexts
+ * @copyright 2019 David Monllao
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_analytics/potential-contexts",["jquery","core/ajax"],(function($,Ajax){return{processResults:function(selector,results){var contexts=[];return $.isArray(results)?($.each(results,(function(index,context){contexts.push({value:context.id,label:context.name})})),contexts):results},transport:function(selector,query,success,failure){let modelid=$(selector).attr("modelid")||null;Ajax.call([{methodname:"tool_analytics_potential_contexts",args:{query:query,modelid:modelid}}])[0].then(success).fail(failure)}}}));
+
+//# sourceMappingURL=potential-contexts.min.js.map
\ No newline at end of file
diff --git a/admin/tool/analytics/amd/build/potential-contexts.min.js.map b/admin/tool/analytics/amd/build/potential-contexts.min.js.map
index c4ca6a9fec5..82ec224e954 100644
--- a/admin/tool/analytics/amd/build/potential-contexts.min.js.map
+++ b/admin/tool/analytics/amd/build/potential-contexts.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/potential-contexts.js"],"names":["define","$","Ajax","processResults","selector","results","contexts","isArray","each","index","context","push","value","id","label","name","transport","query","success","failure","promise","modelid","attr","call","methodname","args","then","fail"],"mappings":"AAuBAA,OAAM,qCAAC,CAAC,QAAD,CAAW,WAAX,CAAD,CAA0B,SAASC,CAAT,CAAYC,CAAZ,CAAkB,CAE9C,MAA8D,CAE1DC,cAAc,CAAE,wBAASC,CAAT,CAAmBC,CAAnB,CAA4B,CACxC,GAAIC,CAAAA,CAAQ,CAAG,EAAf,CACA,GAAIL,CAAC,CAACM,OAAF,CAAUF,CAAV,CAAJ,CAAwB,CACpBJ,CAAC,CAACO,IAAF,CAAOH,CAAP,CAAgB,SAASI,CAAT,CAAgBC,CAAhB,CAAyB,CACrCJ,CAAQ,CAACK,IAAT,CAAc,CACVC,KAAK,CAAEF,CAAO,CAACG,EADL,CAEVC,KAAK,CAAEJ,CAAO,CAACK,IAFL,CAAd,CAIH,CALD,EAMA,MAAOT,CAAAA,CAEV,CATD,IASO,CACH,MAAOD,CAAAA,CACV,CACJ,CAhByD,CAkB1DW,SAAS,CAAE,mBAASZ,CAAT,CAAmBa,CAAnB,CAA0BC,CAA1B,CAAmCC,CAAnC,CAA4C,IAC/CC,CAAAA,CAD+C,CAG/CC,CAAO,CAAGpB,CAAC,CAACG,CAAD,CAAD,CAAYkB,IAAZ,CAAiB,SAAjB,GAA+B,IAHM,CAInDF,CAAO,CAAGlB,CAAI,CAACqB,IAAL,CAAU,CAAC,CACjBC,UAAU,CAAE,mCADK,CAEjBC,IAAI,CAAE,CACFR,KAAK,CAAEA,CADL,CAEFI,OAAO,CAAEA,CAFP,CAFW,CAAD,CAAV,CAAV,CAQAD,CAAO,CAAC,CAAD,CAAP,CAAWM,IAAX,CAAgBR,CAAhB,EAAyBS,IAAzB,CAA8BR,CAA9B,CACH,CA/ByD,CAmCjE,CArCK,CAAN","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 .\n\n/**\n * Potential contexts selector module.\n *\n * @module tool_analytics/potential-contexts\n * @copyright 2019 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax'], function($, Ajax) {\n\n return /** @alias module:tool_analytics/potential-contexts */ {\n\n processResults: function(selector, results) {\n var contexts = [];\n if ($.isArray(results)) {\n $.each(results, function(index, context) {\n contexts.push({\n value: context.id,\n label: context.name\n });\n });\n return contexts;\n\n } else {\n return results;\n }\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n\n let modelid = $(selector).attr('modelid') || null;\n promise = Ajax.call([{\n methodname: 'tool_analytics_potential_contexts',\n args: {\n query: query,\n modelid: modelid\n }\n }]);\n\n promise[0].then(success).fail(failure);\n }\n\n };\n\n});\n"],"file":"potential-contexts.min.js"}
\ No newline at end of file
+{"version":3,"file":"potential-contexts.min.js","sources":["../src/potential-contexts.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 .\n\n/**\n * Potential contexts selector module.\n *\n * @module tool_analytics/potential-contexts\n * @copyright 2019 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax'], function($, Ajax) {\n\n return /** @alias module:tool_analytics/potential-contexts */ {\n\n processResults: function(selector, results) {\n var contexts = [];\n if ($.isArray(results)) {\n $.each(results, function(index, context) {\n contexts.push({\n value: context.id,\n label: context.name\n });\n });\n return contexts;\n\n } else {\n return results;\n }\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n\n let modelid = $(selector).attr('modelid') || null;\n promise = Ajax.call([{\n methodname: 'tool_analytics_potential_contexts',\n args: {\n query: query,\n modelid: modelid\n }\n }]);\n\n promise[0].then(success).fail(failure);\n }\n\n };\n\n});\n"],"names":["define","$","Ajax","processResults","selector","results","contexts","isArray","each","index","context","push","value","id","label","name","transport","query","success","failure","modelid","attr","call","methodname","args","then","fail"],"mappings":";;;;;;;AAuBAA,2CAAO,CAAC,SAAU,cAAc,SAASC,EAAGC,YAEsB,CAE1DC,eAAgB,SAASC,SAAUC,aAC3BC,SAAW,UACXL,EAAEM,QAAQF,UACVJ,EAAEO,KAAKH,SAAS,SAASI,MAAOC,SAC5BJ,SAASK,KAAK,CACVC,MAAOF,QAAQG,GACfC,MAAOJ,QAAQK,UAGhBT,UAGAD,SAIfW,UAAW,SAASZ,SAAUa,MAAOC,QAASC,aAGtCC,QAAUnB,EAAEG,UAAUiB,KAAK,YAAc,KACnCnB,KAAKoB,KAAK,CAAC,CACjBC,WAAY,oCACZC,KAAM,CACFP,MAAOA,MACPG,QAASA,YAIT,GAAGK,KAAKP,SAASQ,KAAKP"}
\ No newline at end of file
diff --git a/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js
index 30e97fccc72..fee3a858e71 100644
--- a/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js
+++ b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js
@@ -1 +1 @@
-YUI.add("moodle-tool_capability-search",function(s,t){var e=function(){e.superclass.constructor.apply(this,arguments)};e.prototype={form:null,select:null,selectoptions:{},input:null,button:null,cancel:null,lastsearch:null,initializer:function(){this.form=s.one("#capability-overview-form"),this.select=this.form.one("select[data-search=capability]"),this.select.setStyle("minWidth",this.select.get("offsetWidth")),this.select.get("options").each(function(t){var e=t.get("value");this.selectoptions[e]=t},this),this.button=this.form.all("input[type=submit]"),this.lastsearch=this.form.one("input[name=search]");var t=s.Node.create(''),e=s.Node.create('");this.cancel=s.Node.create(''),this.input=s.Node.create(''),t.append(e).append(this.input).append(this.cancel),this.select.insert(t,"before"),this.input.on("keyup",this.typed,this),this.select.on("change",this.validate,this),this.cancel.on("click",function(){this.input.set("value",""),this.typed()},this),this.lastsearch&&(this.input.set("value",this.lastsearch.get("value")),this.typed(),this.select.one("option[selected]")&&this.select.set("scrollTop",this.select.one("option[selected]").get("getX"))),this.validate()},validate:function(){this.button.set("disabled",""===this.select.get("value"))},typed:function(){var t,e=this.input.get("value"),s=0,i=null;for(t in this.lastsearch&&this.lastsearch.set("value",e),this.select.all("option").remove(),this.selectoptions)0<=t.indexOf(e)&&(s++,i=this.selectoptions[t],this.select.append(this.selectoptions[t]));0===s?this.input.addClass("error"):(this.input.removeClass("error"),1===s&&i.set("selected",!0)),""!==e?this.cancel.removeClass("d-none"):this.cancel.addClass("d-none"),this.validate()}},s.extend(e,s.Base,e.prototype,{NAME:"tool_capability-search",ATTRS:{strsearch:{}}}),M.tool_capability=M.tool_capability||{},M.tool_capability.init_capability_search=function(t){new e(t)}},"@VERSION@",{requires:["base","node"]});
\ No newline at end of file
+YUI.add("moodle-tool_capability-search",function(s,t){var e=function(){e.superclass.constructor.apply(this,arguments)};s.extend(e,s.Base,e.prototype={form:null,select:null,selectoptions:{},input:null,button:null,cancel:null,lastsearch:null,initializer:function(){this.form=s.one("#capability-overview-form"),this.select=this.form.one("select[data-search=capability]"),this.select.setStyle("minWidth",this.select.get("offsetWidth")),this.select.get("options").each(function(t){var e=t.get("value");this.selectoptions[e]=t},this),this.button=this.form.all("input[type=submit]"),this.lastsearch=this.form.one("input[name=search]");var t=s.Node.create(''),e=s.Node.create('");this.cancel=s.Node.create(''),this.input=s.Node.create(''),t.append(e).append(this.input).append(this.cancel),this.select.insert(t,"before"),this.input.on("keyup",this.typed,this),this.select.on("change",this.validate,this),this.cancel.on("click",function(){this.input.set("value",""),this.typed()},this),this.lastsearch&&(this.input.set("value",this.lastsearch.get("value")),this.typed(),this.select.one("option[selected]")&&this.select.set("scrollTop",this.select.one("option[selected]").get("getX"))),this.validate()},validate:function(){this.button.set("disabled",""===this.select.get("value"))},typed:function(){var t,e=this.input.get("value"),s=0,i=null;for(t in this.lastsearch&&this.lastsearch.set("value",e),this.select.all("option").remove(),this.selectoptions)0<=t.indexOf(e)&&(s++,i=this.selectoptions[t],this.select.append(this.selectoptions[t]));0===s?this.input.addClass("error"):(this.input.removeClass("error"),1===s&&i.set("selected",!0)),""!==e?this.cancel.removeClass("d-none"):this.cancel.addClass("d-none"),this.validate()}},{NAME:"tool_capability-search",ATTRS:{strsearch:{}}}),M.tool_capability=M.tool_capability||{},M.tool_capability.init_capability_search=function(t){new e(t)}},"@VERSION@",{requires:["base","node"]});
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/clipboardwrapper.min.js b/admin/tool/componentlibrary/amd/build/clipboardwrapper.min.js
index 37db2479ca3..a8faa5acf56 100644
--- a/admin/tool/componentlibrary/amd/build/clipboardwrapper.min.js
+++ b/admin/tool/componentlibrary/amd/build/clipboardwrapper.min.js
@@ -1,2 +1,10 @@
-define ("tool_componentlibrary/clipboardwrapper",["exports","core/copy_to_clipboard","tool_componentlibrary/selectors","core/templates"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.clipboardWrapper=void 0;c=e(c);d=e(d);function e(a){return a&&a.__esModule?a:{default:a}}function f(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 g(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var i=a.apply(b,c);function g(a){f(i,d,e,g,h,"next",a)}function h(a){f(i,d,e,g,h,"throw",a)}g(void 0)})}}var h=0,i=function(){var a=g(regeneratorRuntime.mark(function a(){return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:document.querySelectorAll(c.default.clipboardcontent).forEach(function(a){if(!a.id){a.id="tool_componentlibrary_content-".concat(h++)}d.default.renderForPromise("tool_componentlibrary/clipboardbutton",{clipboardtarget:"#".concat(a.id," code")}).then(function(b){var c=b.html,e=b.js;d.default.prependNodeContents(a,c,e);return}).catch()});case 1:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}();a.clipboardWrapper=i});
-//# sourceMappingURL=clipboardwrapper.min.js.map
+define("tool_componentlibrary/clipboardwrapper",["exports","core/copy_to_clipboard","tool_componentlibrary/selectors","core/templates"],(function(_exports,_copy_to_clipboard,_selectors,_templates){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
+/**
+ * Wrapper to ensure that all Hugo example snippets have a "Copy to clipboard" button.
+ *
+ * @module tool_componentlibrary/clipboardwrapper
+ * @copyright 2021 Bas Brands
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.clipboardWrapper=void 0,_selectors=_interopRequireDefault(_selectors),_templates=_interopRequireDefault(_templates);let idCounter=0;_exports.clipboardWrapper=async()=>{document.querySelectorAll(_selectors.default.clipboardcontent).forEach((element=>{element.id||(element.id="tool_componentlibrary_content-".concat(idCounter++)),_templates.default.renderForPromise("tool_componentlibrary/clipboardbutton",{clipboardtarget:"#".concat(element.id," code")}).then((_ref=>{let{html:html,js:js}=_ref;_templates.default.prependNodeContents(element,html,js)})).catch()}))}}));
+
+//# sourceMappingURL=clipboardwrapper.min.js.map
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/clipboardwrapper.min.js.map b/admin/tool/componentlibrary/amd/build/clipboardwrapper.min.js.map
index 080df4a7164..0c6e79f2a59 100644
--- a/admin/tool/componentlibrary/amd/build/clipboardwrapper.min.js.map
+++ b/admin/tool/componentlibrary/amd/build/clipboardwrapper.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/clipboardwrapper.js"],"names":["idCounter","clipboardWrapper","document","querySelectorAll","selectors","clipboardcontent","forEach","element","id","Templates","renderForPromise","clipboardtarget","then","html","js","prependNodeContents","catch"],"mappings":"mPAuBA,OACA,O,qXAEIA,CAAAA,CAAS,CAAG,C,CAOHC,CAAgB,4CAAG,8FAC5BC,QAAQ,CAACC,gBAAT,CAA0BC,UAAUC,gBAApC,EAAsDC,OAAtD,CAA8D,SAAAC,CAAO,CAAI,CACrE,GAAI,CAACA,CAAO,CAACC,EAAb,CAAiB,CACbD,CAAO,CAACC,EAAR,yCAA8CR,CAAS,EAAvD,CACH,CACDS,UAAUC,gBAAV,CAA2B,uCAA3B,CAAoE,CAACC,eAAe,YAAMJ,CAAO,CAACC,EAAd,SAAhB,CAApE,EACCI,IADD,CACM,WAAgB,IAAdC,CAAAA,CAAc,GAAdA,IAAc,CAARC,CAAQ,GAARA,EAAQ,CAClBL,UAAUM,mBAAV,CAA8BR,CAA9B,CAAuCM,CAAvC,CAA6CC,CAA7C,EACA,MACH,CAJD,EAKCE,KALD,EAMH,CAVD,EAD4B,wCAAH,uD","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 .\n\n/**\n * Wrapper to ensure that all Hugo example snippets have a \"Copy to clipboard\" button.\n *\n * @module tool_componentlibrary/clipboardwrapper\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport 'core/copy_to_clipboard';\nimport selectors from 'tool_componentlibrary/selectors';\nimport Templates from 'core/templates';\n\nlet idCounter = 0;\n\n/**\n * Initialise the clipboard button on all reusable code.\n *\n * @method\n */\nexport const clipboardWrapper = async() => {\n document.querySelectorAll(selectors.clipboardcontent).forEach(element => {\n if (!element.id) {\n element.id = `tool_componentlibrary_content-${idCounter++}`;\n }\n Templates.renderForPromise('tool_componentlibrary/clipboardbutton', {clipboardtarget: `#${element.id} code`})\n .then(({html, js}) => {\n Templates.prependNodeContents(element, html, js);\n return;\n })\n .catch();\n });\n};\n"],"file":"clipboardwrapper.min.js"}
\ No newline at end of file
+{"version":3,"file":"clipboardwrapper.min.js","sources":["../src/clipboardwrapper.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 .\n\n/**\n * Wrapper to ensure that all Hugo example snippets have a \"Copy to clipboard\" button.\n *\n * @module tool_componentlibrary/clipboardwrapper\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport 'core/copy_to_clipboard';\nimport selectors from 'tool_componentlibrary/selectors';\nimport Templates from 'core/templates';\n\nlet idCounter = 0;\n\n/**\n * Initialise the clipboard button on all reusable code.\n *\n * @method\n */\nexport const clipboardWrapper = async() => {\n document.querySelectorAll(selectors.clipboardcontent).forEach(element => {\n if (!element.id) {\n element.id = `tool_componentlibrary_content-${idCounter++}`;\n }\n Templates.renderForPromise('tool_componentlibrary/clipboardbutton', {clipboardtarget: `#${element.id} code`})\n .then(({html, js}) => {\n Templates.prependNodeContents(element, html, js);\n return;\n })\n .catch();\n });\n};\n"],"names":["idCounter","async","document","querySelectorAll","selectors","clipboardcontent","forEach","element","id","renderForPromise","clipboardtarget","then","_ref","html","js","prependNodeContents","catch"],"mappings":";;;;;;;8LA0BIA,UAAY,4BAOgBC,UAC5BC,SAASC,iBAAiBC,mBAAUC,kBAAkBC,SAAQC,UACrDA,QAAQC,KACTD,QAAQC,2CAAsCR,iCAExCS,iBAAiB,wCAAyC,CAACC,2BAAqBH,QAAQC,cACjGG,MAAKC,WAACC,KAACA,KAADC,GAAOA,4BACAC,oBAAoBR,QAASM,KAAMC,OAGhDE"}
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/jsrunner.min.js b/admin/tool/componentlibrary/amd/build/jsrunner.min.js
index 727d94d0ff2..df5fb710e61 100644
--- a/admin/tool/componentlibrary/amd/build/jsrunner.min.js
+++ b/admin/tool/componentlibrary/amd/build/jsrunner.min.js
@@ -1,2 +1,10 @@
-define ("tool_componentlibrary/jsrunner",["exports","tool_componentlibrary/selectors"],function(_exports,_selectors){"use strict";Object.defineProperty(_exports,"__esModule",{value:!0});_exports.jsRunner=void 0;_selectors=_interopRequireDefault(_selectors);function _interopRequireDefault(a){return a&&a.__esModule?a:{default:a}}var jsRunner=function(){var compLib=document.querySelector(_selectors.default.componentlibrary);compLib.querySelectorAll(_selectors.default.jscode).forEach(function(runjs){eval(runjs.innerText)})};_exports.jsRunner=jsRunner});
-//# sourceMappingURL=jsrunner.min.js.map
+define("tool_componentlibrary/jsrunner",["exports","tool_componentlibrary/selectors"],(function(_exports,_selectors){var obj;
+/**
+ * Run the JS required for example code to work in the library.
+ *
+ * @module tool_componentlibrary/jsrunner
+ * @copyright 2021 Bas Brands
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.jsRunner=void 0,_selectors=(obj=_selectors)&&obj.__esModule?obj:{default:obj};_exports.jsRunner=()=>{document.querySelector(_selectors.default.componentlibrary).querySelectorAll(_selectors.default.jscode).forEach((runjs=>{const script=document.createElement("script");script.type="text/javascript",script.innerHTML=runjs.textContent,document.head.appendChild(script)}))}}));
+
+//# sourceMappingURL=jsrunner.min.js.map
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/jsrunner.min.js.map b/admin/tool/componentlibrary/amd/build/jsrunner.min.js.map
index fbad8f1fe76..cba5b132059 100644
--- a/admin/tool/componentlibrary/amd/build/jsrunner.min.js.map
+++ b/admin/tool/componentlibrary/amd/build/jsrunner.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/jsrunner.js"],"names":["jsRunner","compLib","document","querySelector","selectors","componentlibrary","querySelectorAll","jscode","forEach","runjs","eval","innerText"],"mappings":"mNAuBA,8C,wEAUO,GAAMA,CAAAA,QAAQ,CAAG,UAAM,CAC1B,GAAMC,CAAAA,OAAO,CAAGC,QAAQ,CAACC,aAAT,CAAuBC,mBAAUC,gBAAjC,CAAhB,CACAJ,OAAO,CAACK,gBAAR,CAAyBF,mBAAUG,MAAnC,EAA2CC,OAA3C,CAAmD,SAAAC,KAAK,CAAI,CACxDC,IAAI,CAACD,KAAK,CAACE,SAAP,CACP,CAFD,CAGH,CALM,C","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 .\n\n/**\n * Run the JS required for example code to work in the library.\n *\n * @module tool_componentlibrary/jsrunner\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport selectors from 'tool_componentlibrary/selectors';\n\n/**\n * The Hugo shortcodes changes the JavaScript in markdownfiles from\n * the Moodle mustache {{js}} code... {{/js}} syntax into a div with\n * attribute data-action='runjs'. See hugo/site/layouts/shortcodes/example.html.\n * This code fetches and runs the JavaScript content.\n *\n * @method\n */\nexport const jsRunner = () => {\n const compLib = document.querySelector(selectors.componentlibrary);\n compLib.querySelectorAll(selectors.jscode).forEach(runjs => {\n eval(runjs.innerText); // eslint-disable-line no-eval\n });\n};\n"],"file":"jsrunner.min.js"}
\ No newline at end of file
+{"version":3,"file":"jsrunner.min.js","sources":["../src/jsrunner.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 .\n\n/**\n * Run the JS required for example code to work in the library.\n *\n * @module tool_componentlibrary/jsrunner\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport selectors from 'tool_componentlibrary/selectors';\n\n/**\n * The Hugo shortcodes changes the JavaScript in markdownfiles from\n * the Moodle mustache {{js}} code... {{/js}} syntax into a div with\n * attribute data-action='runjs'. See hugo/site/layouts/shortcodes/example.html.\n * This code fetches and runs the JavaScript content.\n *\n * @method\n */\nexport const jsRunner = () => {\n const compLib = document.querySelector(selectors.componentlibrary);\n compLib.querySelectorAll(selectors.jscode).forEach(runjs => {\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.innerHTML = runjs.textContent;\n document.head.appendChild(script);\n });\n};\n"],"names":["document","querySelector","selectors","componentlibrary","querySelectorAll","jscode","forEach","runjs","script","createElement","type","innerHTML","textContent","head","appendChild"],"mappings":";;;;;;;sKAiCwB,KACJA,SAASC,cAAcC,mBAAUC,kBACzCC,iBAAiBF,mBAAUG,QAAQC,SAAQC,cACzCC,OAASR,SAASS,cAAc,UACtCD,OAAOE,KAAO,kBACdF,OAAOG,UAAYJ,MAAMK,YACzBZ,SAASa,KAAKC,YAAYN"}
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/loader.min.js b/admin/tool/componentlibrary/amd/build/loader.min.js
index 84f31de304b..e921903b5f5 100644
--- a/admin/tool/componentlibrary/amd/build/loader.min.js
+++ b/admin/tool/componentlibrary/amd/build/loader.min.js
@@ -1,2 +1,3 @@
-define ("tool_componentlibrary/loader",["exports","./mustache","./jsrunner","./clipboardwrapper","./search"],function(a,b,c,d,e){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;a.init=function init(a){(0,b.mustache)();(0,c.jsRunner)();(0,d.clipboardWrapper)();(0,e.search)(a)}});
-//# sourceMappingURL=loader.min.js.map
+define("tool_componentlibrary/loader",["exports","./mustache","./jsrunner","./clipboardwrapper","./search"],(function(_exports,_mustache,_jsrunner,_clipboardwrapper,_search){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0;_exports.init=jsonFile=>{(0,_mustache.mustache)(),(0,_jsrunner.jsRunner)(),(0,_clipboardwrapper.clipboardWrapper)(),(0,_search.search)(jsonFile)}}));
+
+//# sourceMappingURL=loader.min.js.map
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/loader.min.js.map b/admin/tool/componentlibrary/amd/build/loader.min.js.map
index 44286dee310..cd8e5c606e5 100644
--- a/admin/tool/componentlibrary/amd/build/loader.min.js.map
+++ b/admin/tool/componentlibrary/amd/build/loader.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/loader.js"],"names":["init","jsonFile"],"mappings":"oNAiCoB,QAAPA,CAAAA,IAAO,CAAAC,CAAQ,CAAI,CAC5B,iBACA,iBACA,yBACA,aAAOA,CAAP,CACH,C","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 .\n\n/**\n * This initialises the component library JS\n *\n * @module tool_componentlibrary/loader\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {mustache} from './mustache';\nimport {jsRunner} from './jsrunner';\nimport {clipboardWrapper} from './clipboardwrapper';\nimport {search} from './search';\n\n/**\n * Load all the component library JavaScript.\n *\n * @param {string} jsonFile Full path to the JSON file with the search DB.\n */\nexport const init = jsonFile => {\n mustache();\n jsRunner();\n clipboardWrapper();\n search(jsonFile);\n};\n"],"file":"loader.min.js"}
\ No newline at end of file
+{"version":3,"file":"loader.min.js","sources":["../src/loader.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 .\n\n/**\n * This initialises the component library JS\n *\n * @module tool_componentlibrary/loader\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {mustache} from './mustache';\nimport {jsRunner} from './jsrunner';\nimport {clipboardWrapper} from './clipboardwrapper';\nimport {search} from './search';\n\n/**\n * Load all the component library JavaScript.\n *\n * @param {string} jsonFile Full path to the JSON file with the search DB.\n */\nexport const init = jsonFile => {\n mustache();\n jsRunner();\n clipboardWrapper();\n search(jsonFile);\n};\n"],"names":["jsonFile"],"mappings":"yQAiCoBA,yHAITA"}
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/lunr.min.js b/admin/tool/componentlibrary/amd/build/lunr.min.js
index ae085755e7e..9273bde7c14 100644
--- a/admin/tool/componentlibrary/amd/build/lunr.min.js
+++ b/admin/tool/componentlibrary/amd/build/lunr.min.js
@@ -1,2 +1,8 @@
-function _typeof(e){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(e){return typeof e}}else{_typeof=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e}}return _typeof(e)}(function(){var e=function(t){var r=new e.Builder;r.pipeline.add(e.trimmer,e.stopWordFilter,e.stemmer);r.searchPipeline.add(e.stemmer);t.call(r,r);return r.build()};e.version="2.3.9";e.utils={};e.utils.warn=function(e){return function(t){if(e.console&&console.warn){console.warn(t)}}}(this);e.utils.asString=function(e){if(void 0===e||null===e){return""}else{return e.toString()}};e.utils.clone=function(e){if(null===e||e===void 0){return e}for(var t=Object.create(null),r=Object.keys(e),n=0;ne){r=n}if(s==e){break}i=r-t;n=t+Math.floor(i/2);s=this.elements[2*n]}if(s==e){return 2*n}if(s>e){return 2*n}if(sa){u+=2}else if(o==a){t+=r[l+1]*n[u+1];l+=2;u+=2}}return t};e.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0};e.Vector.prototype.toArray=function(){for(var e=Array(this.elements.length/2),t=1,r=0;ts.length){return s}a=s.substr(0,1);if("y"==a){s=a.toUpperCase()+s.substr(1)}l=/^(.+?)(ss|i)es$/;u=/^(.+?)([^s])s$/;if(l.test(s)){s=s.replace(l,"$1$2")}else if(u.test(s)){s=s.replace(u,"$1$2")}l=/^(.+?)eed$/;u=/^(.+?)(ed|ing)$/;if(l.test(s)){var m=l.exec(s);l=r;if(l.test(m[1])){l=n;s=s.replace(l,"")}}else if(u.test(s)){var m=u.exec(s);d=m[1];u=/^([^aeiou][^aeiouy]*)?[aeiouy]/;if(u.test(d)){s=d;u=/(at|bl|iz)$/;p=/([^aeiouylsz])\1$/;c=/^[^aeiou][^aeiouy]*[aeiouy][^aeiouwxy]$/;if(u.test(s)){s=s+"e"}else if(p.test(s)){l=n;s=s.replace(l,"")}else if(c.test(s)){s=s+"e"}}}l=/^(.+?[^aeiou])y$/;if(l.test(s)){var m=l.exec(s);d=m[1];s=d+"i"}l=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;if(l.test(s)){var m=l.exec(s);d=m[1];o=m[2];l=r;if(l.test(d)){s=d+e[o]}}l=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;if(l.test(s)){var m=l.exec(s);d=m[1];o=m[2];l=r;if(l.test(d)){s=d+t[o]}}l=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;u=/^(.+?)(s|t)(ion)$/;if(l.test(s)){var m=l.exec(s);d=m[1];l=i;if(l.test(d)){s=d}}else if(u.test(s)){var m=u.exec(s);d=m[1]+m[2];u=i;if(u.test(d)){s=d}}l=/^(.+?)e$/;if(l.test(s)){var m=l.exec(s);d=m[1];l=i;u=/^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*([aeiouy][aeiou]*)?$/;p=/^[^aeiou][^aeiouy]*[aeiouy][^aeiouwxy]$/;if(l.test(d)||u.test(d)&&!p.test(d)){s=d}}l=/ll$/;u=i;if(l.test(s)&&u.test(s)){l=n;s=s.replace(l,"")}if("y"==a){s=a.toLowerCase()+s.substr(1)}return s};return function(e){return e.update(s)}}();e.Pipeline.registerFunction(e.stemmer,"stemmer");e.generateStopWordFilter=function(e){var t=e.reduce(function(e,t){e[t]=t;return e},{});return function(e){if(e&&t[e.toString()]!==e.toString())return e}};e.stopWordFilter=e.generateStopWordFilter(["a","able","about","across","after","all","almost","also","am","among","an","and","any","are","as","at","be","because","been","but","by","can","cannot","could","dear","did","do","does","either","else","ever","every","for","from","get","got","had","has","have","he","her","hers","him","his","how","however","i","if","in","into","is","it","its","just","least","let","like","likely","may","me","might","most","must","my","neither","no","nor","not","of","off","often","on","only","or","other","our","own","rather","said","say","says","she","should","since","so","some","than","that","the","their","them","then","there","these","they","this","tis","to","too","twas","us","wants","was","we","were","what","when","where","which","while","who","whom","why","will","with","would","yet","you","your"]);e.Pipeline.registerFunction(e.stopWordFilter,"stopWordFilter");e.trimmer=function(e){return e.update(function(e){return e.replace(/^\W+/,"").replace(/\W+$/,"")})};e.Pipeline.registerFunction(e.trimmer,"trimmer");e.TokenSet=function(){this.final=!1;this.edges={};this.id=e.TokenSet._nextId;e.TokenSet._nextId+=1};e.TokenSet._nextId=1;e.TokenSet.fromArray=function(t){for(var r=new e.TokenSet.Builder,n=0,s=t.length;n=e;t--){var r=this.uncheckedNodes[t],n=r.child.toString();if(n in this.minimizedNodes){r.parent.edges[r.char]=this.minimizedNodes[n]}else{r.child._str=n;this.minimizedNodes[n]=r.child}this.uncheckedNodes.pop()}};e.Index=function(e){this.invertedIndex=e.invertedIndex;this.fieldVectors=e.fieldVectors;this.tokenSet=e.tokenSet;this.fields=e.fields;this.pipeline=e.pipeline};e.Index.prototype.search=function(t){return this.query(function(r){var i=new e.QueryParser(t,r);i.parse()})};e.Index.prototype.query=function(t){for(var r=new e.Query(this.fields),n=Object.create(null),s=Object.create(null),d=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;ue){this._b=0}else if(1=this.length){return e.QueryLexer.EOS}var t=this.str.charAt(this.pos);this.pos+=1;return t};e.QueryLexer.prototype.width=function(){return this.pos-this.start};e.QueryLexer.prototype.ignore=function(){if(this.start==this.pos){this.pos+=1}this.start=this.pos};e.QueryLexer.prototype.backup=function(){this.pos-=1};e.QueryLexer.prototype.acceptDigitRun=function(){var t,r;do{t=this.next();r=t.charCodeAt(0)}while(47r);if(t!=e.QueryLexer.EOS){this.backup()}};e.QueryLexer.prototype.more=function(){return this.pos0){var tokenMetadata=lunr.utils.clone(metadata)||{};tokenMetadata.position=[sliceStart,sliceLength],tokenMetadata.index=tokens.length,tokens.push(new lunr.Token(str.slice(sliceStart,sliceEnd),tokenMetadata))}sliceStart=sliceEnd+1}}return tokens},lunr.tokenizer.separator=/[\s\-]+/,lunr.Pipeline=function(){this._stack=[]},lunr.Pipeline.registeredFunctions=Object.create(null),lunr.Pipeline.registerFunction=function(fn,label){label in this.registeredFunctions&&lunr.utils.warn("Overwriting existing registered function: "+label),fn.label=label,lunr.Pipeline.registeredFunctions[fn.label]=fn},lunr.Pipeline.warnIfFunctionNotRegistered=function(fn){fn.label&&fn.label in this.registeredFunctions||lunr.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",fn)},lunr.Pipeline.load=function(serialised){var pipeline=new lunr.Pipeline;return serialised.forEach((function(fnName){var fn=lunr.Pipeline.registeredFunctions[fnName];if(!fn)throw new Error("Cannot load unregistered function: "+fnName);pipeline.add(fn)})),pipeline},lunr.Pipeline.prototype.add=function(){var fns=Array.prototype.slice.call(arguments);fns.forEach((function(fn){lunr.Pipeline.warnIfFunctionNotRegistered(fn),this._stack.push(fn)}),this)},lunr.Pipeline.prototype.after=function(existingFn,newFn){lunr.Pipeline.warnIfFunctionNotRegistered(newFn);var pos=this._stack.indexOf(existingFn);if(-1==pos)throw new Error("Cannot find existingFn");pos+=1,this._stack.splice(pos,0,newFn)},lunr.Pipeline.prototype.before=function(existingFn,newFn){lunr.Pipeline.warnIfFunctionNotRegistered(newFn);var pos=this._stack.indexOf(existingFn);if(-1==pos)throw new Error("Cannot find existingFn");this._stack.splice(pos,0,newFn)},lunr.Pipeline.prototype.remove=function(fn){var pos=this._stack.indexOf(fn);-1!=pos&&this._stack.splice(pos,1)},lunr.Pipeline.prototype.run=function(tokens){for(var stackLength=this._stack.length,i=0;i1&&(pivotIndexindex&&(end=pivotPoint),pivotIndex!=index);)sliceLength=end-start,pivotPoint=start+Math.floor(sliceLength/2),pivotIndex=this.elements[2*pivotPoint];return pivotIndex==index||pivotIndex>index?2*pivotPoint:pivotIndexbVal?j+=2:aVal==bVal&&(dotProduct+=a[i+1]*b[j+1],i+=2,j+=2);return dotProduct},lunr.Vector.prototype.similarity=function(otherVector){return this.dot(otherVector)/this.magnitude()||0},lunr.Vector.prototype.toArray=function(){for(var output=new Array(this.elements.length/2),i=1,j=0;i0){var noEditNode,char=frame.str.charAt(0);char in frame.node.edges?noEditNode=frame.node.edges[char]:(noEditNode=new lunr.TokenSet,frame.node.edges[char]=noEditNode),1==frame.str.length&&(noEditNode.final=!0),stack.push({node:noEditNode,editsRemaining:frame.editsRemaining,str:frame.str.slice(1)})}if(0!=frame.editsRemaining){if("*"in frame.node.edges)var insertionNode=frame.node.edges["*"];else{insertionNode=new lunr.TokenSet;frame.node.edges["*"]=insertionNode}if(0==frame.str.length&&(insertionNode.final=!0),stack.push({node:insertionNode,editsRemaining:frame.editsRemaining-1,str:frame.str}),frame.str.length>1&&stack.push({node:frame.node,editsRemaining:frame.editsRemaining-1,str:frame.str.slice(1)}),1==frame.str.length&&(frame.node.final=!0),frame.str.length>=1){if("*"in frame.node.edges)var substitutionNode=frame.node.edges["*"];else{substitutionNode=new lunr.TokenSet;frame.node.edges["*"]=substitutionNode}1==frame.str.length&&(substitutionNode.final=!0),stack.push({node:substitutionNode,editsRemaining:frame.editsRemaining-1,str:frame.str.slice(1)})}if(frame.str.length>1){var transposeNode,charA=frame.str.charAt(0),charB=frame.str.charAt(1);charB in frame.node.edges?transposeNode=frame.node.edges[charB]:(transposeNode=new lunr.TokenSet,frame.node.edges[charB]=transposeNode),1==frame.str.length&&(transposeNode.final=!0),stack.push({node:transposeNode,editsRemaining:frame.editsRemaining-1,str:charA+frame.str.slice(2)})}}}return root},lunr.TokenSet.fromString=function(str){for(var node=new lunr.TokenSet,root=node,i=0,len=str.length;i=downTo;i--){var node=this.uncheckedNodes[i],childKey=node.child.toString();childKey in this.minimizedNodes?node.parent.edges[node.char]=this.minimizedNodes[childKey]:(node.child._str=childKey,this.minimizedNodes[childKey]=node.child),this.uncheckedNodes.pop()}},lunr.Index=function(attrs){this.invertedIndex=attrs.invertedIndex,this.fieldVectors=attrs.fieldVectors,this.tokenSet=attrs.tokenSet,this.fields=attrs.fields,this.pipeline=attrs.pipeline},lunr.Index.prototype.search=function(queryString){return this.query((function(query){new lunr.QueryParser(queryString,query).parse()}))},lunr.Index.prototype.query=function(fn){for(var query=new lunr.Query(this.fields),matchingFields=Object.create(null),queryVectors=Object.create(null),termFieldCache=Object.create(null),requiredMatches=Object.create(null),prohibitedMatches=Object.create(null),i=0;i1?1:number},lunr.Builder.prototype.k1=function(number){this._k1=number},lunr.Builder.prototype.add=function(doc,attributes){var docRef=doc[this._ref],fields=Object.keys(this._fields);this._documents[docRef]=attributes||{},this.documentCount+=1;for(var i=0;i=this.length)return lunr.QueryLexer.EOS;var char=this.str.charAt(this.pos);return this.pos+=1,char},lunr.QueryLexer.prototype.width=function(){return this.pos-this.start},lunr.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},lunr.QueryLexer.prototype.backup=function(){this.pos-=1},lunr.QueryLexer.prototype.acceptDigitRun=function(){var char,charCode;do{charCode=(char=this.next()).charCodeAt(0)}while(charCode>47&&charCode<58);char!=lunr.QueryLexer.EOS&&this.backup()},lunr.QueryLexer.prototype.more=function(){return this.pos1&&(lexer.backup(),lexer.emit(lunr.QueryLexer.TERM)),lexer.ignore(),lexer.more())return lunr.QueryLexer.lexText},lunr.QueryLexer.lexEditDistance=function(lexer){return lexer.ignore(),lexer.acceptDigitRun(),lexer.emit(lunr.QueryLexer.EDIT_DISTANCE),lunr.QueryLexer.lexText},lunr.QueryLexer.lexBoost=function(lexer){return lexer.ignore(),lexer.acceptDigitRun(),lexer.emit(lunr.QueryLexer.BOOST),lunr.QueryLexer.lexText},lunr.QueryLexer.lexEOS=function(lexer){lexer.width()>0&&lexer.emit(lunr.QueryLexer.TERM)},lunr.QueryLexer.termSeparator=lunr.tokenizer.separator,lunr.QueryLexer.lexText=function(lexer){for(;;){var char=lexer.next();if(char==lunr.QueryLexer.EOS)return lunr.QueryLexer.lexEOS;if(92!=char.charCodeAt(0)){if(":"==char)return lunr.QueryLexer.lexField;if("~"==char)return lexer.backup(),lexer.width()>0&&lexer.emit(lunr.QueryLexer.TERM),lunr.QueryLexer.lexEditDistance;if("^"==char)return lexer.backup(),lexer.width()>0&&lexer.emit(lunr.QueryLexer.TERM),lunr.QueryLexer.lexBoost;if("+"==char&&1===lexer.width())return lexer.emit(lunr.QueryLexer.PRESENCE),lunr.QueryLexer.lexText;if("-"==char&&1===lexer.width())return lexer.emit(lunr.QueryLexer.PRESENCE),lunr.QueryLexer.lexText;if(char.match(lunr.QueryLexer.termSeparator))return lunr.QueryLexer.lexTerm}else lexer.escapeCharacter()}},lunr.QueryParser=function(str,query){this.lexer=new lunr.QueryLexer(str),this.query=query,this.currentClause={},this.lexemeIdx=0},lunr.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var state=lunr.QueryParser.parseClause;state;)state=state(this);return this.query},lunr.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},lunr.QueryParser.prototype.consumeLexeme=function(){var lexeme=this.peekLexeme();return this.lexemeIdx+=1,lexeme},lunr.QueryParser.prototype.nextClause=function(){var completedClause=this.currentClause;this.query.clause(completedClause),this.currentClause={}},lunr.QueryParser.parseClause=function(parser){var lexeme=parser.peekLexeme();if(null!=lexeme)switch(lexeme.type){case lunr.QueryLexer.PRESENCE:return lunr.QueryParser.parsePresence;case lunr.QueryLexer.FIELD:return lunr.QueryParser.parseField;case lunr.QueryLexer.TERM:return lunr.QueryParser.parseTerm;default:var errorMessage="expected either a field or a term, found "+lexeme.type;throw lexeme.str.length>=1&&(errorMessage+=" with value '"+lexeme.str+"'"),new lunr.QueryParseError(errorMessage,lexeme.start,lexeme.end)}},lunr.QueryParser.parsePresence=function(parser){var lexeme=parser.consumeLexeme();if(null!=lexeme){switch(lexeme.str){case"-":parser.currentClause.presence=lunr.Query.presence.PROHIBITED;break;case"+":parser.currentClause.presence=lunr.Query.presence.REQUIRED;break;default:var errorMessage="unrecognised presence operator'"+lexeme.str+"'";throw new lunr.QueryParseError(errorMessage,lexeme.start,lexeme.end)}var nextLexeme=parser.peekLexeme();if(null==nextLexeme){errorMessage="expecting term or field, found nothing";throw new lunr.QueryParseError(errorMessage,lexeme.start,lexeme.end)}switch(nextLexeme.type){case lunr.QueryLexer.FIELD:return lunr.QueryParser.parseField;case lunr.QueryLexer.TERM:return lunr.QueryParser.parseTerm;default:errorMessage="expecting term or field, found '"+nextLexeme.type+"'";throw new lunr.QueryParseError(errorMessage,nextLexeme.start,nextLexeme.end)}}},lunr.QueryParser.parseField=function(parser){var lexeme=parser.consumeLexeme();if(null!=lexeme){if(-1==parser.query.allFields.indexOf(lexeme.str)){var possibleFields=parser.query.allFields.map((function(f){return"'"+f+"'"})).join(", "),errorMessage="unrecognised field '"+lexeme.str+"', possible fields: "+possibleFields;throw new lunr.QueryParseError(errorMessage,lexeme.start,lexeme.end)}parser.currentClause.fields=[lexeme.str];var nextLexeme=parser.peekLexeme();if(null==nextLexeme){errorMessage="expecting term, found nothing";throw new lunr.QueryParseError(errorMessage,lexeme.start,lexeme.end)}if(nextLexeme.type===lunr.QueryLexer.TERM)return lunr.QueryParser.parseTerm;errorMessage="expecting term, found '"+nextLexeme.type+"'";throw new lunr.QueryParseError(errorMessage,nextLexeme.start,nextLexeme.end)}},lunr.QueryParser.parseTerm=function(parser){var lexeme=parser.consumeLexeme();if(null!=lexeme){parser.currentClause.term=lexeme.str.toLowerCase(),-1!=lexeme.str.indexOf("*")&&(parser.currentClause.usePipeline=!1);var nextLexeme=parser.peekLexeme();if(null!=nextLexeme)switch(nextLexeme.type){case lunr.QueryLexer.TERM:return parser.nextClause(),lunr.QueryParser.parseTerm;case lunr.QueryLexer.FIELD:return parser.nextClause(),lunr.QueryParser.parseField;case lunr.QueryLexer.EDIT_DISTANCE:return lunr.QueryParser.parseEditDistance;case lunr.QueryLexer.BOOST:return lunr.QueryParser.parseBoost;case lunr.QueryLexer.PRESENCE:return parser.nextClause(),lunr.QueryParser.parsePresence;default:var errorMessage="Unexpected lexeme type '"+nextLexeme.type+"'";throw new lunr.QueryParseError(errorMessage,nextLexeme.start,nextLexeme.end)}else parser.nextClause()}},lunr.QueryParser.parseEditDistance=function(parser){var lexeme=parser.consumeLexeme();if(null!=lexeme){var editDistance=parseInt(lexeme.str,10);if(isNaN(editDistance)){var errorMessage="edit distance must be numeric";throw new lunr.QueryParseError(errorMessage,lexeme.start,lexeme.end)}parser.currentClause.editDistance=editDistance;var nextLexeme=parser.peekLexeme();if(null!=nextLexeme)switch(nextLexeme.type){case lunr.QueryLexer.TERM:return parser.nextClause(),lunr.QueryParser.parseTerm;case lunr.QueryLexer.FIELD:return parser.nextClause(),lunr.QueryParser.parseField;case lunr.QueryLexer.EDIT_DISTANCE:return lunr.QueryParser.parseEditDistance;case lunr.QueryLexer.BOOST:return lunr.QueryParser.parseBoost;case lunr.QueryLexer.PRESENCE:return parser.nextClause(),lunr.QueryParser.parsePresence;default:errorMessage="Unexpected lexeme type '"+nextLexeme.type+"'";throw new lunr.QueryParseError(errorMessage,nextLexeme.start,nextLexeme.end)}else parser.nextClause()}},lunr.QueryParser.parseBoost=function(parser){var lexeme=parser.consumeLexeme();if(null!=lexeme){var boost=parseInt(lexeme.str,10);if(isNaN(boost)){var errorMessage="boost must be numeric";throw new lunr.QueryParseError(errorMessage,lexeme.start,lexeme.end)}parser.currentClause.boost=boost;var nextLexeme=parser.peekLexeme();if(null!=nextLexeme)switch(nextLexeme.type){case lunr.QueryLexer.TERM:return parser.nextClause(),lunr.QueryParser.parseTerm;case lunr.QueryLexer.FIELD:return parser.nextClause(),lunr.QueryParser.parseField;case lunr.QueryLexer.EDIT_DISTANCE:return lunr.QueryParser.parseEditDistance;case lunr.QueryLexer.BOOST:return lunr.QueryParser.parseBoost;case lunr.QueryLexer.PRESENCE:return parser.nextClause(),lunr.QueryParser.parsePresence;default:errorMessage="Unexpected lexeme type '"+nextLexeme.type+"'";throw new lunr.QueryParseError(errorMessage,nextLexeme.start,nextLexeme.end)}else parser.nextClause()}},root=this,factory=function(){return lunr},"function"==typeof define&&define.amd?define("tool_componentlibrary/lunr",factory):"object"==typeof exports?module.exports=factory():root.lunr=factory()}();
+
+//# sourceMappingURL=lunr.min.js.map
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/lunr.min.js.map b/admin/tool/componentlibrary/amd/build/lunr.min.js.map
index 5b8ba3e9cef..fb888b2a655 100644
--- a/admin/tool/componentlibrary/amd/build/lunr.min.js.map
+++ b/admin/tool/componentlibrary/amd/build/lunr.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/lunr.js"],"names":["lunr","config","builder","Builder","pipeline","add","trimmer","stopWordFilter","stemmer","searchPipeline","call","build","version","utils","warn","global","message","console","asString","obj","toString","clone","Object","create","keys","i","length","key","val","Array","isArray","slice","TypeError","FieldRef","docRef","fieldName","stringValue","_stringValue","joiner","fromString","s","n","indexOf","fieldRef","prototype","Set","elements","complete","intersect","other","union","contains","empty","object","a","b","intersection","element","push","concat","idf","posting","documentCount","documentsWithTerm","x","Math","log","abs","Token","str","metadata","update","fn","tokenizer","map","t","toLowerCase","len","tokens","sliceEnd","sliceStart","char","charAt","sliceLength","match","separator","tokenMetadata","Pipeline","_stack","registeredFunctions","registerFunction","label","warnIfFunctionNotRegistered","isRegistered","load","serialised","forEach","fnName","Error","fns","arguments","after","existingFn","newFn","pos","splice","before","remove","run","stackLength","memo","j","result","k","runString","token","reset","toJSON","Vector","_magnitude","positionForIndex","index","start","end","pivotPoint","floor","pivotIndex","insert","insertIdx","upsert","position","magnitude","sumOfSquares","elementsLength","sqrt","dot","otherVector","dotProduct","aLen","bLen","aVal","bVal","similarity","toArray","output","step2list","step3list","re_mgr0","re_mgr1","re_1b_2","porterStemmer","w","stem","suffix","firstch","re","re2","re3","re4","substr","toUpperCase","test","replace","fp","exec","generateStopWordFilter","stopWords","words","reduce","stopWord","TokenSet","final","edges","id","_nextId","fromArray","arr","finish","root","fromClause","clause","fromFuzzyString","term","editDistance","stack","node","editsRemaining","frame","pop","noEditNode","insertionNode","substitutionNode","charA","charB","transposeNode","next","prefix","edge","_str","labels","sort","qNode","qEdges","qLen","nEdges","nLen","q","qEdge","nEdge","previousWord","uncheckedNodes","minimizedNodes","word","commonPrefix","minimize","child","nextNode","parent","downTo","childKey","Index","attrs","invertedIndex","fieldVectors","tokenSet","fields","search","queryString","query","parser","QueryParser","parse","Query","matchingFields","queryVectors","termFieldCache","requiredMatches","prohibitedMatches","clauses","terms","clauseMatches","usePipeline","m","termTokenSet","expandedTerms","presence","REQUIRED","field","expandedTerm","termIndex","_index","fieldPosting","matchingDocumentRefs","termField","matchingDocumentsSet","PROHIBITED","boost","l","matchingDocumentRef","matchingFieldRef","fieldMatch","MatchData","allRequiredMatches","allProhibitedMatches","matchingFieldRefs","results","matches","isNegated","fieldVector","score","docMatch","matchData","combine","ref","serializedIndex","serializedVectors","serializedInvertedIndex","tokenSetBuilder","tuple","_ref","_fields","_documents","fieldTermFrequencies","fieldLengths","_b","_k1","metadataWhitelist","attributes","RangeError","number","k1","doc","extractor","fieldTerms","metadataKey","calculateAverageFieldLengths","fieldRefs","numberOfFields","accumulator","documentsWithField","averageFieldLength","createFieldVectors","fieldRefsLength","termIdfCache","fieldLength","termFrequencies","termsLength","fieldBoost","docBoost","tf","scoreWithPrecision","round","createTokenSet","use","args","unshift","apply","clonedMetadata","metadataKeys","otherMatchData","allFields","wildcard","String","NONE","LEADING","TRAILING","OPTIONAL","options","QueryParseError","name","QueryLexer","lexemes","escapeCharPositions","state","lexText","sliceString","subSlices","join","emit","type","escapeCharacter","EOS","width","ignore","backup","acceptDigitRun","charCode","charCodeAt","more","FIELD","TERM","EDIT_DISTANCE","BOOST","PRESENCE","lexField","lexer","lexTerm","lexEditDistance","lexBoost","lexEOS","termSeparator","currentClause","lexemeIdx","parseClause","peekLexeme","consumeLexeme","lexeme","nextClause","completedClause","parsePresence","parseField","parseTerm","errorMessage","nextLexeme","possibleFields","f","parseEditDistance","parseBoost","parseInt","isNaN","factory","define","amd","exports","module"],"mappings":"mSAaC,CAAC,UAAU,CAiCZ,GAAIA,CAAAA,CAAI,CAAG,SAAUC,CAAV,CAAkB,CAC3B,GAAIC,CAAAA,CAAO,CAAG,GAAIF,CAAAA,CAAI,CAACG,OAAvB,CAEAD,CAAO,CAACE,QAAR,CAAiBC,GAAjB,CACEL,CAAI,CAACM,OADP,CAEEN,CAAI,CAACO,cAFP,CAGEP,CAAI,CAACQ,OAHP,EAMAN,CAAO,CAACO,cAAR,CAAuBJ,GAAvB,CACEL,CAAI,CAACQ,OADP,EAIAP,CAAM,CAACS,IAAP,CAAYR,CAAZ,CAAqBA,CAArB,EACA,MAAOA,CAAAA,CAAO,CAACS,KAAR,EACR,CAfD,CAiBAX,CAAI,CAACY,OAAL,CAAe,OAAf,CAUAZ,CAAI,CAACa,KAAL,CAAa,EAAb,CASAb,CAAI,CAACa,KAAL,CAAWC,IAAX,CAAmB,SAAUC,CAAV,CAAkB,CAEnC,MAAO,UAAUC,CAAV,CAAmB,CACxB,GAAID,CAAM,CAACE,OAAP,EAAkBA,OAAO,CAACH,IAA9B,CAAoC,CAClCG,OAAO,CAACH,IAAR,CAAaE,CAAb,CACD,CACF,CAEF,CARiB,CAQf,IARe,CAAlB,CAqBAhB,CAAI,CAACa,KAAL,CAAWK,QAAX,CAAsB,SAAUC,CAAV,CAAe,CACnC,GAAY,IAAK,EAAb,GAAAA,CAAG,EAAuB,IAAR,GAAAA,CAAtB,CAAoC,CAClC,MAAO,EACR,CAFD,IAEO,CACL,MAAOA,CAAAA,CAAG,CAACC,QAAJ,EACR,CACF,CAND,CAwBApB,CAAI,CAACa,KAAL,CAAWQ,KAAX,CAAmB,SAAUF,CAAV,CAAe,CAChC,GAAY,IAAR,GAAAA,CAAG,EAAaA,CAAG,SAAvB,CAAuC,CACrC,MAAOA,CAAAA,CACR,CAKD,OAHIE,CAAAA,CAAK,CAAGC,MAAM,CAACC,MAAP,CAAc,IAAd,CAGZ,CAFIC,CAAI,CAAGF,MAAM,CAACE,IAAP,CAAYL,CAAZ,CAEX,CAASM,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGD,CAAI,CAACE,MAAzB,CAAiCD,CAAC,EAAlC,CAAsC,CACpC,GAAIE,CAAAA,CAAG,CAAGH,CAAI,CAACC,CAAD,CAAd,CACIG,CAAG,CAAGT,CAAG,CAACQ,CAAD,CADb,CAGA,GAAIE,KAAK,CAACC,OAAN,CAAcF,CAAd,CAAJ,CAAwB,CACtBP,CAAK,CAACM,CAAD,CAAL,CAAaC,CAAG,CAACG,KAAJ,EAAb,CACA,QACD,CAED,GAAmB,QAAf,QAAOH,CAAAA,CAAP,EACe,QAAf,QAAOA,CAAAA,CADP,EAEe,SAAf,QAAOA,CAAAA,CAFX,CAE8B,CAC5BP,CAAK,CAACM,CAAD,CAAL,CAAaC,CAAb,CACA,QACD,CAED,KAAM,IAAII,CAAAA,SAAJ,CAAc,uDAAd,CACP,CAED,MAAOX,CAAAA,CACR,CA5BD,CA6BArB,CAAI,CAACiC,QAAL,CAAgB,SAAUC,CAAV,CAAkBC,CAAlB,CAA6BC,CAA7B,CAA0C,CACxD,KAAKF,MAAL,CAAcA,CAAd,CACA,KAAKC,SAAL,CAAiBA,CAAjB,CACA,KAAKE,YAAL,CAAoBD,CACrB,CAJD,CAMApC,CAAI,CAACiC,QAAL,CAAcK,MAAd,CAAuB,GAAvB,CAEAtC,CAAI,CAACiC,QAAL,CAAcM,UAAd,CAA2B,SAAUC,CAAV,CAAa,CACtC,GAAIC,CAAAA,CAAC,CAAGD,CAAC,CAACE,OAAF,CAAU1C,CAAI,CAACiC,QAAL,CAAcK,MAAxB,CAAR,CAEA,GAAU,CAAC,CAAP,GAAAG,CAAJ,CAAc,CACZ,KAAM,4BACP,CAED,GAAIE,CAAAA,CAAQ,CAAGH,CAAC,CAACT,KAAF,CAAQ,CAAR,CAAWU,CAAX,CAAf,CACIP,CAAM,CAAGM,CAAC,CAACT,KAAF,CAAQU,CAAC,CAAG,CAAZ,CADb,CAGA,MAAO,IAAIzC,CAAAA,CAAI,CAACiC,QAAT,CAAmBC,CAAnB,CAA2BS,CAA3B,CAAqCH,CAArC,CACR,CAXD,CAaAxC,CAAI,CAACiC,QAAL,CAAcW,SAAd,CAAwBxB,QAAxB,CAAmC,UAAY,CAC7C,GAAI,KAAKiB,YAAL,QAAJ,CAAoC,CAClC,KAAKA,YAAL,CAAoB,KAAKF,SAAL,CAAiBnC,CAAI,CAACiC,QAAL,CAAcK,MAA/B,CAAwC,KAAKJ,MAClE,CAED,MAAO,MAAKG,YACb,CAND,CAiBArC,CAAI,CAAC6C,GAAL,CAAW,SAAUC,CAAV,CAAoB,CAC7B,KAAKA,QAAL,CAAgBxB,MAAM,CAACC,MAAP,CAAc,IAAd,CAAhB,CAEA,GAAIuB,CAAJ,CAAc,CACZ,KAAKpB,MAAL,CAAcoB,CAAQ,CAACpB,MAAvB,CAEA,IAAK,GAAID,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAG,KAAKC,MAAzB,CAAiCD,CAAC,EAAlC,CAAsC,CACpC,KAAKqB,QAAL,CAAcA,CAAQ,CAACrB,CAAD,CAAtB,IACD,CACF,CAND,IAMO,CACL,KAAKC,MAAL,CAAc,CACf,CACF,CAZD,CAqBA1B,CAAI,CAAC6C,GAAL,CAASE,QAAT,CAAoB,CAClBC,SAAS,CAAE,mBAAUC,CAAV,CAAiB,CAC1B,MAAOA,CAAAA,CACR,CAHiB,CAKlBC,KAAK,CAAE,gBAAY,CACjB,MAAO,KACR,CAPiB,CASlBC,QAAQ,CAAE,mBAAY,CACpB,QACD,CAXiB,CAApB,CAqBAnD,CAAI,CAAC6C,GAAL,CAASO,KAAT,CAAiB,CACfJ,SAAS,CAAE,oBAAY,CACrB,MAAO,KACR,CAHc,CAKfE,KAAK,CAAE,eAAUD,CAAV,CAAiB,CACtB,MAAOA,CAAAA,CACR,CAPc,CASfE,QAAQ,CAAE,mBAAY,CACpB,QACD,CAXc,CAAjB,CAoBAnD,CAAI,CAAC6C,GAAL,CAASD,SAAT,CAAmBO,QAAnB,CAA8B,SAAUE,CAAV,CAAkB,CAC9C,MAAO,CAAC,CAAC,KAAKP,QAAL,CAAcO,CAAd,CACV,CAFD,CAYArD,CAAI,CAAC6C,GAAL,CAASD,SAAT,CAAmBI,SAAnB,CAA+B,SAAUC,CAAV,CAAiB,CAC9C,GAAIK,CAAAA,CAAJ,CAAOC,CAAP,CAAUT,CAAV,CAAoBU,CAAY,CAAG,EAAnC,CAEA,GAAIP,CAAK,GAAKjD,CAAI,CAAC6C,GAAL,CAASE,QAAvB,CAAiC,CAC/B,MAAO,KACR,CAED,GAAIE,CAAK,GAAKjD,CAAI,CAAC6C,GAAL,CAASO,KAAvB,CAA8B,CAC5B,MAAOH,CAAAA,CACR,CAED,GAAI,KAAKvB,MAAL,CAAcuB,CAAK,CAACvB,MAAxB,CAAgC,CAC9B4B,CAAC,CAAG,IAAJ,CACAC,CAAC,CAAGN,CACL,CAHD,IAGO,CACLK,CAAC,CAAGL,CAAJ,CACAM,CAAC,CAAG,IACL,CAEDT,CAAQ,CAAGxB,MAAM,CAACE,IAAP,CAAY8B,CAAC,CAACR,QAAd,CAAX,CAEA,IAAK,GAAIrB,CAAAA,CAAC,CAAG,CAAR,CACCgC,CADN,CAAgBhC,CAAC,CAAGqB,CAAQ,CAACpB,MAA7B,CAAqCD,CAAC,EAAtC,CAA0C,CACpCgC,CADoC,CAC1BX,CAAQ,CAACrB,CAAD,CADkB,CAExC,GAAIgC,CAAO,GAAIF,CAAAA,CAAC,CAACT,QAAjB,CAA2B,CACzBU,CAAY,CAACE,IAAb,CAAkBD,CAAlB,CACD,CACF,CAED,MAAO,IAAIzD,CAAAA,CAAI,CAAC6C,GAAT,CAAcW,CAAd,CACR,CA7BD,CAsCAxD,CAAI,CAAC6C,GAAL,CAASD,SAAT,CAAmBM,KAAnB,CAA2B,SAAUD,CAAV,CAAiB,CAC1C,GAAIA,CAAK,GAAKjD,CAAI,CAAC6C,GAAL,CAASE,QAAvB,CAAiC,CAC/B,MAAO/C,CAAAA,CAAI,CAAC6C,GAAL,CAASE,QACjB,CAED,GAAIE,CAAK,GAAKjD,CAAI,CAAC6C,GAAL,CAASO,KAAvB,CAA8B,CAC5B,MAAO,KACR,CAED,MAAO,IAAIpD,CAAAA,CAAI,CAAC6C,GAAT,CAAavB,MAAM,CAACE,IAAP,CAAY,KAAKsB,QAAjB,EAA2Ba,MAA3B,CAAkCrC,MAAM,CAACE,IAAP,CAAYyB,CAAK,CAACH,QAAlB,CAAlC,CAAb,CACR,CAVD,CAmBA9C,CAAI,CAAC4D,GAAL,CAAW,SAAUC,CAAV,CAAmBC,CAAnB,CAAkC,CAC3C,GAAIC,CAAAA,CAAiB,CAAG,CAAxB,CAEA,IAAK,GAAI5B,CAAAA,CAAT,GAAsB0B,CAAAA,CAAtB,CAA+B,CAC7B,GAAiB,QAAb,EAAA1B,CAAJ,CAA2B,SAC3B4B,CAAiB,EAAIzC,MAAM,CAACE,IAAP,CAAYqC,CAAO,CAAC1B,CAAD,CAAnB,EAAgCT,MACtD,CAED,GAAIsC,CAAAA,CAAC,CAAG,CAACF,CAAa,CAAGC,CAAhB,CAAoC,EAArC,GAA6CA,CAAiB,CAAG,EAAjE,CAAR,CAEA,MAAOE,CAAAA,IAAI,CAACC,GAAL,CAAS,EAAID,IAAI,CAACE,GAAL,CAASH,CAAT,CAAb,CACR,CAXD,CAqBAhE,CAAI,CAACoE,KAAL,CAAa,SAAUC,CAAV,CAAeC,CAAf,CAAyB,CACpC,KAAKD,GAAL,CAAWA,CAAG,EAAI,EAAlB,CACA,KAAKC,QAAL,CAAgBA,CAAQ,EAAI,EAC7B,CAHD,CAUAtE,CAAI,CAACoE,KAAL,CAAWxB,SAAX,CAAqBxB,QAArB,CAAgC,UAAY,CAC1C,MAAO,MAAKiD,GACb,CAFD,CAwBArE,CAAI,CAACoE,KAAL,CAAWxB,SAAX,CAAqB2B,MAArB,CAA8B,SAAUC,CAAV,CAAc,CAC1C,KAAKH,GAAL,CAAWG,CAAE,CAAC,KAAKH,GAAN,CAAW,KAAKC,QAAhB,CAAb,CACA,MAAO,KACR,CAHD,CAYAtE,CAAI,CAACoE,KAAL,CAAWxB,SAAX,CAAqBvB,KAArB,CAA6B,SAAUmD,CAAV,CAAc,CACzCA,CAAE,CAAGA,CAAE,EAAI,SAAUhC,CAAV,CAAa,CAAE,MAAOA,CAAAA,CAAG,CAApC,CACA,MAAO,IAAIxC,CAAAA,CAAI,CAACoE,KAAT,CAAgBI,CAAE,CAAC,KAAKH,GAAN,CAAW,KAAKC,QAAhB,CAAlB,CAA6C,KAAKA,QAAlD,CACR,CAHD,CA2BAtE,CAAI,CAACyE,SAAL,CAAiB,SAAUtD,CAAV,CAAemD,CAAf,CAAyB,CACxC,GAAW,IAAP,EAAAnD,CAAG,EAAYA,CAAG,QAAtB,CAAqC,CACnC,MAAO,EACR,CAED,GAAIU,KAAK,CAACC,OAAN,CAAcX,CAAd,CAAJ,CAAwB,CACtB,MAAOA,CAAAA,CAAG,CAACuD,GAAJ,CAAQ,SAAUC,CAAV,CAAa,CAC1B,MAAO,IAAI3E,CAAAA,CAAI,CAACoE,KAAT,CACLpE,CAAI,CAACa,KAAL,CAAWK,QAAX,CAAoByD,CAApB,EAAuBC,WAAvB,EADK,CAEL5E,CAAI,CAACa,KAAL,CAAWQ,KAAX,CAAiBiD,CAAjB,CAFK,CAIR,CALM,CAMR,CAMD,OAJID,CAAAA,CAAG,CAAGlD,CAAG,CAACC,QAAJ,GAAewD,WAAf,EAIV,CAHIC,CAAG,CAAGR,CAAG,CAAC3C,MAGd,CAFIoD,CAAM,CAAG,EAEb,CAASC,CAAQ,CAAG,CAApB,CAAuBC,CAAU,CAAG,CAApC,CAAuCD,CAAQ,EAAIF,CAAnD,CAAwDE,CAAQ,EAAhE,CAAoE,CAClE,GAAIE,CAAAA,CAAI,CAAGZ,CAAG,CAACa,MAAJ,CAAWH,CAAX,CAAX,CACII,CAAW,CAAGJ,CAAQ,CAAGC,CAD7B,CAGA,GAAKC,CAAI,CAACG,KAAL,CAAWpF,CAAI,CAACyE,SAAL,CAAeY,SAA1B,GAAwCN,CAAQ,EAAIF,CAAzD,CAA+D,CAE7D,GAAkB,CAAd,CAAAM,CAAJ,CAAqB,CACnB,GAAIG,CAAAA,CAAa,CAAGtF,CAAI,CAACa,KAAL,CAAWQ,KAAX,CAAiBiD,CAAjB,GAA8B,EAAlD,CACAgB,CAAa,SAAb,CAA4B,CAACN,CAAD,CAAaG,CAAb,CAA5B,CACAG,CAAa,MAAb,CAAyBR,CAAM,CAACpD,MAAhC,CAEAoD,CAAM,CAACpB,IAAP,CACE,GAAI1D,CAAAA,CAAI,CAACoE,KAAT,CACEC,CAAG,CAACtC,KAAJ,CAAUiD,CAAV,CAAsBD,CAAtB,CADF,CAEEO,CAFF,CADF,CAMD,CAEDN,CAAU,CAAGD,CAAQ,CAAG,CACzB,CAEF,CAED,MAAOD,CAAAA,CACR,CA3CD,CAoDA9E,CAAI,CAACyE,SAAL,CAAeY,SAAf,CAA2B,SAA3B,CAmCArF,CAAI,CAACuF,QAAL,CAAgB,UAAY,CAC1B,KAAKC,MAAL,CAAc,EACf,CAFD,CAIAxF,CAAI,CAACuF,QAAL,CAAcE,mBAAd,CAAoCnE,MAAM,CAACC,MAAP,CAAc,IAAd,CAApC,CAmCAvB,CAAI,CAACuF,QAAL,CAAcG,gBAAd,CAAiC,SAAUlB,CAAV,CAAcmB,CAAd,CAAqB,CACpD,GAAIA,CAAK,GAAI,MAAKF,mBAAlB,CAAuC,CACrCzF,CAAI,CAACa,KAAL,CAAWC,IAAX,CAAgB,6CAA+C6E,CAA/D,CACD,CAEDnB,CAAE,CAACmB,KAAH,CAAWA,CAAX,CACA3F,CAAI,CAACuF,QAAL,CAAcE,mBAAd,CAAkCjB,CAAE,CAACmB,KAArC,EAA8CnB,CAC/C,CAPD,CAeAxE,CAAI,CAACuF,QAAL,CAAcK,2BAAd,CAA4C,SAAUpB,CAAV,CAAc,CACxD,GAAIqB,CAAAA,CAAY,CAAGrB,CAAE,CAACmB,KAAH,EAAanB,CAAE,CAACmB,KAAH,GAAY,MAAKF,mBAAjD,CAEA,GAAI,CAACI,CAAL,CAAmB,CACjB7F,CAAI,CAACa,KAAL,CAAWC,IAAX,CAAgB,iGAAhB,CAAmH0D,CAAnH,CACD,CACF,CAND,CAkBAxE,CAAI,CAACuF,QAAL,CAAcO,IAAd,CAAqB,SAAUC,CAAV,CAAsB,CACzC,GAAI3F,CAAAA,CAAQ,CAAG,GAAIJ,CAAAA,CAAI,CAACuF,QAAxB,CAEAQ,CAAU,CAACC,OAAX,CAAmB,SAAUC,CAAV,CAAkB,CACnC,GAAIzB,CAAAA,CAAE,CAAGxE,CAAI,CAACuF,QAAL,CAAcE,mBAAd,CAAkCQ,CAAlC,CAAT,CAEA,GAAIzB,CAAJ,CAAQ,CACNpE,CAAQ,CAACC,GAAT,CAAamE,CAAb,CACD,CAFD,IAEO,CACL,KAAM,IAAI0B,CAAAA,KAAJ,CAAU,sCAAwCD,CAAlD,CACP,CACF,CARD,EAUA,MAAO7F,CAAAA,CACR,CAdD,CAuBAJ,CAAI,CAACuF,QAAL,CAAc3C,SAAd,CAAwBvC,GAAxB,CAA8B,UAAY,CACxC,GAAI8F,CAAAA,CAAG,CAAGtE,KAAK,CAACe,SAAN,CAAgBb,KAAhB,CAAsBrB,IAAtB,CAA2B0F,SAA3B,CAAV,CAEAD,CAAG,CAACH,OAAJ,CAAY,SAAUxB,CAAV,CAAc,CACxBxE,CAAI,CAACuF,QAAL,CAAcK,2BAAd,CAA0CpB,CAA1C,EACA,KAAKgB,MAAL,CAAY9B,IAAZ,CAAiBc,CAAjB,CACD,CAHD,CAGG,IAHH,CAID,CAPD,CAkBAxE,CAAI,CAACuF,QAAL,CAAc3C,SAAd,CAAwByD,KAAxB,CAAgC,SAAUC,CAAV,CAAsBC,CAAtB,CAA6B,CAC3DvG,CAAI,CAACuF,QAAL,CAAcK,2BAAd,CAA0CW,CAA1C,EAEA,GAAIC,CAAAA,CAAG,CAAG,KAAKhB,MAAL,CAAY9C,OAAZ,CAAoB4D,CAApB,CAAV,CACA,GAAW,CAAC,CAAR,EAAAE,CAAJ,CAAe,CACb,KAAM,IAAIN,CAAAA,KAAJ,CAAU,wBAAV,CACP,CAEDM,CAAG,CAAGA,CAAG,CAAG,CAAZ,CACA,KAAKhB,MAAL,CAAYiB,MAAZ,CAAmBD,CAAnB,CAAwB,CAAxB,CAA2BD,CAA3B,CACD,CAVD,CAqBAvG,CAAI,CAACuF,QAAL,CAAc3C,SAAd,CAAwB8D,MAAxB,CAAiC,SAAUJ,CAAV,CAAsBC,CAAtB,CAA6B,CAC5DvG,CAAI,CAACuF,QAAL,CAAcK,2BAAd,CAA0CW,CAA1C,EAEA,GAAIC,CAAAA,CAAG,CAAG,KAAKhB,MAAL,CAAY9C,OAAZ,CAAoB4D,CAApB,CAAV,CACA,GAAW,CAAC,CAAR,EAAAE,CAAJ,CAAe,CACb,KAAM,IAAIN,CAAAA,KAAJ,CAAU,wBAAV,CACP,CAED,KAAKV,MAAL,CAAYiB,MAAZ,CAAmBD,CAAnB,CAAwB,CAAxB,CAA2BD,CAA3B,CACD,CATD,CAgBAvG,CAAI,CAACuF,QAAL,CAAc3C,SAAd,CAAwB+D,MAAxB,CAAiC,SAAUnC,CAAV,CAAc,CAC7C,GAAIgC,CAAAA,CAAG,CAAG,KAAKhB,MAAL,CAAY9C,OAAZ,CAAoB8B,CAApB,CAAV,CACA,GAAW,CAAC,CAAR,EAAAgC,CAAJ,CAAe,CACb,MACD,CAED,KAAKhB,MAAL,CAAYiB,MAAZ,CAAmBD,CAAnB,CAAwB,CAAxB,CACD,CAPD,CAgBAxG,CAAI,CAACuF,QAAL,CAAc3C,SAAd,CAAwBgE,GAAxB,CAA8B,SAAU9B,CAAV,CAAkB,CAG9C,OAFI+B,CAAAA,CAAW,CAAG,KAAKrB,MAAL,CAAY9D,MAE9B,CAASD,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGoF,CAApB,CAAiCpF,CAAC,EAAlC,CAAsC,CAIpC,OAHI+C,CAAAA,CAAE,CAAG,KAAKgB,MAAL,CAAY/D,CAAZ,CAGT,CAFIqF,CAAI,CAAG,EAEX,CAASC,CAAC,CAAG,CAAb,CACMC,CADN,CAAgBD,CAAC,CAAGjC,CAAM,CAACpD,MAA3B,CAAmCqF,CAAC,EAApC,CAAwC,CAClCC,CADkC,CACzBxC,CAAE,CAACM,CAAM,CAACiC,CAAD,CAAP,CAAYA,CAAZ,CAAejC,CAAf,CADuB,CAGtC,GAAe,IAAX,GAAAkC,CAAM,EAAwB,IAAK,EAAhB,GAAAA,CAAnB,EAAmD,EAAX,GAAAA,CAA5C,CAA2D,SAE3D,GAAInF,KAAK,CAACC,OAAN,CAAckF,CAAd,CAAJ,CAA2B,CACzB,IAAK,GAAIC,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGD,CAAM,CAACtF,MAA3B,CAAmCuF,CAAC,EAApC,CAAwC,CACtCH,CAAI,CAACpD,IAAL,CAAUsD,CAAM,CAACC,CAAD,CAAhB,CACD,CACF,CAJD,IAIO,CACLH,CAAI,CAACpD,IAAL,CAAUsD,CAAV,CACD,CACF,CAEDlC,CAAM,CAAGgC,CACV,CAED,MAAOhC,CAAAA,CACR,CAzBD,CAqCA9E,CAAI,CAACuF,QAAL,CAAc3C,SAAd,CAAwBsE,SAAxB,CAAoC,SAAU7C,CAAV,CAAeC,CAAf,CAAyB,CAC3D,GAAI6C,CAAAA,CAAK,CAAG,GAAInH,CAAAA,CAAI,CAACoE,KAAT,CAAgBC,CAAhB,CAAqBC,CAArB,CAAZ,CAEA,MAAO,MAAKsC,GAAL,CAAS,CAACO,CAAD,CAAT,EAAkBzC,GAAlB,CAAsB,SAAUC,CAAV,CAAa,CACxC,MAAOA,CAAAA,CAAC,CAACvD,QAAF,EACR,CAFM,CAGR,CAND,CAYApB,CAAI,CAACuF,QAAL,CAAc3C,SAAd,CAAwBwE,KAAxB,CAAgC,UAAY,CAC1C,KAAK5B,MAAL,CAAc,EACf,CAFD,CAWAxF,CAAI,CAACuF,QAAL,CAAc3C,SAAd,CAAwByE,MAAxB,CAAiC,UAAY,CAC3C,MAAO,MAAK7B,MAAL,CAAYd,GAAZ,CAAgB,SAAUF,CAAV,CAAc,CACnCxE,CAAI,CAACuF,QAAL,CAAcK,2BAAd,CAA0CpB,CAA1C,EAEA,MAAOA,CAAAA,CAAE,CAACmB,KACX,CAJM,CAKR,CAND,CA4BA3F,CAAI,CAACsH,MAAL,CAAc,SAAUxE,CAAV,CAAoB,CAChC,KAAKyE,UAAL,CAAkB,CAAlB,CACA,KAAKzE,QAAL,CAAgBA,CAAQ,EAAI,EAC7B,CAHD,CAgBA9C,CAAI,CAACsH,MAAL,CAAY1E,SAAZ,CAAsB4E,gBAAtB,CAAyC,SAAUC,CAAV,CAAiB,CAExD,GAA4B,CAAxB,OAAK3E,QAAL,CAAcpB,MAAlB,CAA+B,CAC7B,MAAO,EACR,CAED,GAAIgG,CAAAA,CAAK,CAAG,CAAZ,CACIC,CAAG,CAAG,KAAK7E,QAAL,CAAcpB,MAAd,CAAuB,CADjC,CAEIyD,CAAW,CAAGwC,CAAG,CAAGD,CAFxB,CAGIE,CAAU,CAAG3D,IAAI,CAAC4D,KAAL,CAAW1C,CAAW,CAAG,CAAzB,CAHjB,CAII2C,CAAU,CAAG,KAAKhF,QAAL,CAA2B,CAAb,CAAA8E,CAAd,CAJjB,CAMA,MAAqB,CAAd,CAAAzC,CAAP,CAAwB,CACtB,GAAI2C,CAAU,CAAGL,CAAjB,CAAwB,CACtBC,CAAK,CAAGE,CACT,CAED,GAAIE,CAAU,CAAGL,CAAjB,CAAwB,CACtBE,CAAG,CAAGC,CACP,CAED,GAAIE,CAAU,EAAIL,CAAlB,CAAyB,CACvB,KACD,CAEDtC,CAAW,CAAGwC,CAAG,CAAGD,CAApB,CACAE,CAAU,CAAGF,CAAK,CAAGzD,IAAI,CAAC4D,KAAL,CAAW1C,CAAW,CAAG,CAAzB,CAArB,CACA2C,CAAU,CAAG,KAAKhF,QAAL,CAA2B,CAAb,CAAA8E,CAAd,CACd,CAED,GAAIE,CAAU,EAAIL,CAAlB,CAAyB,CACvB,MAAoB,EAAb,CAAAG,CACR,CAED,GAAIE,CAAU,CAAGL,CAAjB,CAAwB,CACtB,MAAoB,EAAb,CAAAG,CACR,CAED,GAAIE,CAAU,CAAGL,CAAjB,CAAwB,CACtB,MAA0B,EAAnB,EAACG,CAAU,CAAG,CAAd,CACR,CACF,CAzCD,CAoDA5H,CAAI,CAACsH,MAAL,CAAY1E,SAAZ,CAAsBmF,MAAtB,CAA+B,SAAUC,CAAV,CAAqBpG,CAArB,CAA0B,CACvD,KAAKqG,MAAL,CAAYD,CAAZ,CAAuBpG,CAAvB,CAA4B,UAAY,CACtC,KAAM,iBACP,CAFD,CAGD,CAJD,CAcA5B,CAAI,CAACsH,MAAL,CAAY1E,SAAZ,CAAsBqF,MAAtB,CAA+B,SAAUD,CAAV,CAAqBpG,CAArB,CAA0B4C,CAA1B,CAA8B,CAC3D,KAAK+C,UAAL,CAAkB,CAAlB,CACA,GAAIW,CAAAA,CAAQ,CAAG,KAAKV,gBAAL,CAAsBQ,CAAtB,CAAf,CAEA,GAAI,KAAKlF,QAAL,CAAcoF,CAAd,GAA2BF,CAA/B,CAA0C,CACxC,KAAKlF,QAAL,CAAcoF,CAAQ,CAAG,CAAzB,EAA8B1D,CAAE,CAAC,KAAK1B,QAAL,CAAcoF,CAAQ,CAAG,CAAzB,CAAD,CAA8BtG,CAA9B,CACjC,CAFD,IAEO,CACL,KAAKkB,QAAL,CAAc2D,MAAd,CAAqByB,CAArB,CAA+B,CAA/B,CAAkCF,CAAlC,CAA6CpG,CAA7C,CACD,CACF,CATD,CAgBA5B,CAAI,CAACsH,MAAL,CAAY1E,SAAZ,CAAsBuF,SAAtB,CAAkC,UAAY,CAC5C,GAAI,KAAKZ,UAAT,CAAqB,MAAO,MAAKA,UAAZ,CAKrB,OAHIa,CAAAA,CAAY,CAAG,CAGnB,CAFIC,CAAc,CAAG,KAAKvF,QAAL,CAAcpB,MAEnC,CAASD,CAAC,CAAG,CAAb,CACMG,CADN,CAAgBH,CAAC,CAAG4G,CAApB,CAAoC5G,CAAC,EAAI,CAAzC,CAA4C,CACtCG,CADsC,CAChC,KAAKkB,QAAL,CAAcrB,CAAd,CADgC,CAE1C2G,CAAY,EAAIxG,CAAG,CAAGA,CACvB,CAED,MAAO,MAAK2F,UAAL,CAAkBtD,IAAI,CAACqE,IAAL,CAAUF,CAAV,CAC1B,CAZD,CAoBApI,CAAI,CAACsH,MAAL,CAAY1E,SAAZ,CAAsB2F,GAAtB,CAA4B,SAAUC,CAAV,CAAuB,CACjD,GAAIC,CAAAA,CAAU,CAAG,CAAjB,CACInF,CAAC,CAAG,KAAKR,QADb,CACuBS,CAAC,CAAGiF,CAAW,CAAC1F,QADvC,CAEI4F,CAAI,CAAGpF,CAAC,CAAC5B,MAFb,CAEqBiH,CAAI,CAAGpF,CAAC,CAAC7B,MAF9B,CAGIkH,CAAI,CAAG,CAHX,CAGcC,CAAI,CAAG,CAHrB,CAIIpH,CAAC,CAAG,CAJR,CAIWsF,CAAC,CAAG,CAJf,CAMA,MAAOtF,CAAC,CAAGiH,CAAJ,EAAY3B,CAAC,CAAG4B,CAAvB,CAA6B,CAC3BC,CAAI,CAAGtF,CAAC,CAAC7B,CAAD,CAAR,CAAaoH,CAAI,CAAGtF,CAAC,CAACwD,CAAD,CAArB,CACA,GAAI6B,CAAI,CAAGC,CAAX,CAAiB,CACfpH,CAAC,EAAI,CACN,CAFD,IAEO,IAAImH,CAAI,CAAGC,CAAX,CAAiB,CACtB9B,CAAC,EAAI,CACN,CAFM,IAEA,IAAI6B,CAAI,EAAIC,CAAZ,CAAkB,CACvBJ,CAAU,EAAInF,CAAC,CAAC7B,CAAC,CAAG,CAAL,CAAD,CAAW8B,CAAC,CAACwD,CAAC,CAAG,CAAL,CAA1B,CACAtF,CAAC,EAAI,CAAL,CACAsF,CAAC,EAAI,CACN,CACF,CAED,MAAO0B,CAAAA,CACR,CArBD,CA8BAzI,CAAI,CAACsH,MAAL,CAAY1E,SAAZ,CAAsBkG,UAAtB,CAAmC,SAAUN,CAAV,CAAuB,CACxD,MAAO,MAAKD,GAAL,CAASC,CAAT,EAAwB,KAAKL,SAAL,EAAxB,EAA4C,CACpD,CAFD,CASAnI,CAAI,CAACsH,MAAL,CAAY1E,SAAZ,CAAsBmG,OAAtB,CAAgC,UAAY,CAG1C,OAFIC,CAAAA,CAAM,CAAOnH,KAAP,CAAc,KAAKiB,QAAL,CAAcpB,MAAd,CAAuB,CAArC,CAEV,CAASD,CAAC,CAAG,CAAb,CAAgBsF,CAAC,CAAG,CAApB,CAAuBtF,CAAC,CAAG,KAAKqB,QAAL,CAAcpB,MAAzC,CAAiDD,CAAC,EAAI,CAAL,CAAQsF,CAAC,EAA1D,CAA8D,CAC5DiC,CAAM,CAACjC,CAAD,CAAN,CAAY,KAAKjE,QAAL,CAAcrB,CAAd,CACb,CAED,MAAOuH,CAAAA,CACR,CARD,CAeAhJ,CAAI,CAACsH,MAAL,CAAY1E,SAAZ,CAAsByE,MAAtB,CAA+B,UAAY,CACzC,MAAO,MAAKvE,QACb,CAFD,CAqBA9C,CAAI,CAACQ,OAAL,CAAgB,UAAU,IACpByI,CAAAA,CAAS,CAAG,CACZ,QAAY,KADA,CAEZ,OAAW,MAFC,CAGZ,KAAS,MAHG,CAIZ,KAAS,MAJG,CAKZ,KAAS,KALG,CAMZ,IAAQ,KANI,CAOZ,KAAS,IAPG,CAQZ,MAAU,KARE,CASZ,IAAQ,GATI,CAUZ,MAAU,KAVE,CAWZ,QAAY,KAXA,CAYZ,MAAU,KAZE,CAaZ,KAAS,KAbG,CAcZ,MAAU,IAdE,CAeZ,QAAY,KAfA,CAgBZ,QAAY,KAhBA,CAiBZ,QAAY,KAjBA,CAkBZ,MAAU,IAlBE,CAmBZ,MAAU,KAnBE,CAoBZ,OAAW,KApBC,CAqBZ,KAAS,KArBG,CADQ,CAyBtBC,CAAS,CAAG,CACV,MAAU,IADA,CAEV,MAAU,EAFA,CAGV,MAAU,IAHA,CAIV,MAAU,IAJA,CAKV,KAAS,IALC,CAMV,IAAQ,EANE,CAOV,KAAS,EAPC,CAzBU,CA6CpBC,CAAO,2DA7Ca,CA8CpBC,CAAO,6FA9Ca,CAsDpBC,CAAO,CAAG,IAtDU,CAuEpBC,CAAa,CAAG,SAAuBC,CAAvB,CAA0B,CAC5C,GAAIC,CAAAA,CAAJ,CACEC,CADF,CAEEC,CAFF,CAGEC,CAHF,CAIEC,CAJF,CAKEC,CALF,CAMEC,CANF,CAQA,GAAe,CAAX,CAAAP,CAAC,CAAC7H,MAAN,CAAkB,CAAE,MAAO6H,CAAAA,CAAI,CAE/BG,CAAO,CAAGH,CAAC,CAACQ,MAAF,CAAS,CAAT,CAAW,CAAX,CAAV,CACA,GAAe,GAAX,EAAAL,CAAJ,CAAoB,CAClBH,CAAC,CAAGG,CAAO,CAACM,WAAR,GAAwBT,CAAC,CAACQ,MAAF,CAAS,CAAT,CAC7B,CAGDJ,CAAE,CAtCQ,iBAsCV,CACAC,CAAG,CAtCQ,gBAsCX,CAEA,GAAID,CAAE,CAACM,IAAH,CAAQV,CAAR,CAAJ,CAAgB,CAAEA,CAAC,CAAGA,CAAC,CAACW,OAAF,CAAUP,CAAV,CAAa,MAAb,CAAuB,CAA7C,IACK,IAAIC,CAAG,CAACK,IAAJ,CAASV,CAAT,CAAJ,CAAiB,CAAEA,CAAC,CAAGA,CAAC,CAACW,OAAF,CAAUN,CAAV,CAAc,MAAd,CAAwB,CAGpDD,CAAE,CA3CQ,YA2CV,CACAC,CAAG,CA3CQ,iBA2CX,CACA,GAAID,CAAE,CAACM,IAAH,CAAQV,CAAR,CAAJ,CAAgB,CACd,GAAIY,CAAAA,CAAE,CAAGR,CAAE,CAACS,IAAH,CAAQb,CAAR,CAAT,CACAI,CAAE,CAAGR,CAAL,CACA,GAAIQ,CAAE,CAACM,IAAH,CAAQE,CAAE,CAAC,CAAD,CAAV,CAAJ,CAAoB,CAClBR,CAAE,CAAGN,CAAL,CACAE,CAAC,CAAGA,CAAC,CAACW,OAAF,CAAUP,CAAV,CAAa,EAAb,CACL,CACF,CAPD,IAOO,IAAIC,CAAG,CAACK,IAAJ,CAASV,CAAT,CAAJ,CAAiB,CACtB,GAAIY,CAAAA,CAAE,CAAGP,CAAG,CAACQ,IAAJ,CAASb,CAAT,CAAT,CACAC,CAAI,CAAGW,CAAE,CAAC,CAAD,CAAT,CACAP,CAAG,iCAAH,CACA,GAAIA,CAAG,CAACK,IAAJ,CAAST,CAAT,CAAJ,CAAoB,CAClBD,CAAC,CAAGC,CAAJ,CACAI,CAAG,CAvDM,aAuDT,CACAC,CAAG,oBAAH,CACAC,CAAG,0CAAH,CACA,GAAIF,CAAG,CAACK,IAAJ,CAASV,CAAT,CAAJ,CAAiB,CAAEA,CAAC,CAAGA,CAAC,CAAG,GAAM,CAAjC,IACK,IAAIM,CAAG,CAACI,IAAJ,CAASV,CAAT,CAAJ,CAAiB,CAAEI,CAAE,CAAGN,CAAL,CAAcE,CAAC,CAAGA,CAAC,CAACW,OAAF,CAAUP,CAAV,CAAa,EAAb,CAAmB,CAAxD,IACA,IAAIG,CAAG,CAACG,IAAJ,CAASV,CAAT,CAAJ,CAAiB,CAAEA,CAAC,CAAGA,CAAC,CAAG,GAAM,CACvC,CACF,CAGDI,CAAE,CA7DQ,kBA6DV,CACA,GAAIA,CAAE,CAACM,IAAH,CAAQV,CAAR,CAAJ,CAAgB,CACd,GAAIY,CAAAA,CAAE,CAAGR,CAAE,CAACS,IAAH,CAAQb,CAAR,CAAT,CACAC,CAAI,CAAGW,CAAE,CAAC,CAAD,CAAT,CACAZ,CAAC,CAAGC,CAAI,CAAG,GACZ,CAGDG,CAAE,CApEO,0IAoET,CACA,GAAIA,CAAE,CAACM,IAAH,CAAQV,CAAR,CAAJ,CAAgB,CACd,GAAIY,CAAAA,CAAE,CAAGR,CAAE,CAACS,IAAH,CAAQb,CAAR,CAAT,CACAC,CAAI,CAAGW,CAAE,CAAC,CAAD,CAAT,CACAV,CAAM,CAAGU,CAAE,CAAC,CAAD,CAAX,CACAR,CAAE,CAAGR,CAAL,CACA,GAAIQ,CAAE,CAACM,IAAH,CAAQT,CAAR,CAAJ,CAAmB,CACjBD,CAAC,CAAGC,CAAI,CAAGP,CAAS,CAACQ,CAAD,CACrB,CACF,CAGDE,CAAE,CA9EO,gDA8ET,CACA,GAAIA,CAAE,CAACM,IAAH,CAAQV,CAAR,CAAJ,CAAgB,CACd,GAAIY,CAAAA,CAAE,CAAGR,CAAE,CAACS,IAAH,CAAQb,CAAR,CAAT,CACAC,CAAI,CAAGW,CAAE,CAAC,CAAD,CAAT,CACAV,CAAM,CAAGU,CAAE,CAAC,CAAD,CAAX,CACAR,CAAE,CAAGR,CAAL,CACA,GAAIQ,CAAE,CAACM,IAAH,CAAQT,CAAR,CAAJ,CAAmB,CACjBD,CAAC,CAAGC,CAAI,CAAGN,CAAS,CAACO,CAAD,CACrB,CACF,CAGDE,CAAE,CAxFO,qFAwFT,CACAC,CAAG,CAxFO,mBAwFV,CACA,GAAID,CAAE,CAACM,IAAH,CAAQV,CAAR,CAAJ,CAAgB,CACd,GAAIY,CAAAA,CAAE,CAAGR,CAAE,CAACS,IAAH,CAAQb,CAAR,CAAT,CACAC,CAAI,CAAGW,CAAE,CAAC,CAAD,CAAT,CACAR,CAAE,CAAGP,CAAL,CACA,GAAIO,CAAE,CAACM,IAAH,CAAQT,CAAR,CAAJ,CAAmB,CACjBD,CAAC,CAAGC,CACL,CACF,CAPD,IAOO,IAAII,CAAG,CAACK,IAAJ,CAASV,CAAT,CAAJ,CAAiB,CACtB,GAAIY,CAAAA,CAAE,CAAGP,CAAG,CAACQ,IAAJ,CAASb,CAAT,CAAT,CACAC,CAAI,CAAGW,CAAE,CAAC,CAAD,CAAF,CAAQA,CAAE,CAAC,CAAD,CAAjB,CACAP,CAAG,CAAGR,CAAN,CACA,GAAIQ,CAAG,CAACK,IAAJ,CAAST,CAAT,CAAJ,CAAoB,CAClBD,CAAC,CAAGC,CACL,CACF,CAGDG,CAAE,CAxGO,UAwGT,CACA,GAAIA,CAAE,CAACM,IAAH,CAAQV,CAAR,CAAJ,CAAgB,CACd,GAAIY,CAAAA,CAAE,CAAGR,CAAE,CAACS,IAAH,CAAQb,CAAR,CAAT,CACAC,CAAI,CAAGW,CAAE,CAAC,CAAD,CAAT,CACAR,CAAE,CAAGP,CAAL,CACAQ,CAAG,+EAAH,CACAC,CAAG,0CAAH,CACA,GAAIF,CAAE,CAACM,IAAH,CAAQT,CAAR,GAAkBI,CAAG,CAACK,IAAJ,CAAST,CAAT,GAAkB,CAAEK,CAAG,CAACI,IAAJ,CAAST,CAAT,CAA1C,CAA4D,CAC1DD,CAAC,CAAGC,CACL,CACF,CAEDG,CAAE,CAnHS,KAmHX,CACAC,CAAG,CAAGR,CAAN,CACA,GAAIO,CAAE,CAACM,IAAH,CAAQV,CAAR,GAAcK,CAAG,CAACK,IAAJ,CAASV,CAAT,CAAlB,CAA+B,CAC7BI,CAAE,CAAGN,CAAL,CACAE,CAAC,CAAGA,CAAC,CAACW,OAAF,CAAUP,CAAV,CAAa,EAAb,CACL,CAID,GAAe,GAAX,EAAAD,CAAJ,CAAoB,CAClBH,CAAC,CAAGG,CAAO,CAAC9E,WAAR,GAAwB2E,CAAC,CAACQ,MAAF,CAAS,CAAT,CAC7B,CAED,MAAOR,CAAAA,CACR,CArMuB,CAuMxB,MAAO,UAAUpC,CAAV,CAAiB,CACtB,MAAOA,CAAAA,CAAK,CAAC5C,MAAN,CAAa+E,CAAb,CACR,CACF,CA1Mc,EAAf,CA4MAtJ,CAAI,CAACuF,QAAL,CAAcG,gBAAd,CAA+B1F,CAAI,CAACQ,OAApC,CAA6C,SAA7C,EAmBAR,CAAI,CAACqK,sBAAL,CAA8B,SAAUC,CAAV,CAAqB,CACjD,GAAIC,CAAAA,CAAK,CAAGD,CAAS,CAACE,MAAV,CAAiB,SAAU1D,CAAV,CAAgB2D,CAAhB,CAA0B,CACrD3D,CAAI,CAAC2D,CAAD,CAAJ,CAAiBA,CAAjB,CACA,MAAO3D,CAAAA,CACR,CAHW,CAGT,EAHS,CAAZ,CAKA,MAAO,UAAUK,CAAV,CAAiB,CACtB,GAAIA,CAAK,EAAIoD,CAAK,CAACpD,CAAK,CAAC/F,QAAN,EAAD,CAAL,GAA4B+F,CAAK,CAAC/F,QAAN,EAAzC,CAA2D,MAAO+F,CAAAA,CACnE,CACF,CATD,CAwBAnH,CAAI,CAACO,cAAL,CAAsBP,CAAI,CAACqK,sBAAL,CAA4B,CAChD,GADgD,CAEhD,MAFgD,CAGhD,OAHgD,CAIhD,QAJgD,CAKhD,OALgD,CAMhD,KANgD,CAOhD,QAPgD,CAQhD,MARgD,CAShD,IATgD,CAUhD,OAVgD,CAWhD,IAXgD,CAYhD,KAZgD,CAahD,KAbgD,CAchD,KAdgD,CAehD,IAfgD,CAgBhD,IAhBgD,CAiBhD,IAjBgD,CAkBhD,SAlBgD,CAmBhD,MAnBgD,CAoBhD,KApBgD,CAqBhD,IArBgD,CAsBhD,KAtBgD,CAuBhD,QAvBgD,CAwBhD,OAxBgD,CAyBhD,MAzBgD,CA0BhD,KA1BgD,CA2BhD,IA3BgD,CA4BhD,MA5BgD,CA6BhD,QA7BgD,CA8BhD,MA9BgD,CA+BhD,MA/BgD,CAgChD,OAhCgD,CAiChD,KAjCgD,CAkChD,MAlCgD,CAmChD,KAnCgD,CAoChD,KApCgD,CAqChD,KArCgD,CAsChD,KAtCgD,CAuChD,MAvCgD,CAwChD,IAxCgD,CAyChD,KAzCgD,CA0ChD,MA1CgD,CA2ChD,KA3CgD,CA4ChD,KA5CgD,CA6ChD,KA7CgD,CA8ChD,SA9CgD,CA+ChD,GA/CgD,CAgDhD,IAhDgD,CAiDhD,IAjDgD,CAkDhD,MAlDgD,CAmDhD,IAnDgD,CAoDhD,IApDgD,CAqDhD,KArDgD,CAsDhD,MAtDgD,CAuDhD,OAvDgD,CAwDhD,KAxDgD,CAyDhD,MAzDgD,CA0DhD,QA1DgD,CA2DhD,KA3DgD,CA4DhD,IA5DgD,CA6DhD,OA7DgD,CA8DhD,MA9DgD,CA+DhD,MA/DgD,CAgEhD,IAhEgD,CAiEhD,SAjEgD,CAkEhD,IAlEgD,CAmEhD,KAnEgD,CAoEhD,KApEgD,CAqEhD,IArEgD,CAsEhD,KAtEgD,CAuEhD,OAvEgD,CAwEhD,IAxEgD,CAyEhD,MAzEgD,CA0EhD,IA1EgD,CA2EhD,OA3EgD,CA4EhD,KA5EgD,CA6EhD,KA7EgD,CA8EhD,QA9EgD,CA+EhD,MA/EgD,CAgFhD,KAhFgD,CAiFhD,MAjFgD,CAkFhD,KAlFgD,CAmFhD,QAnFgD,CAoFhD,OApFgD,CAqFhD,IArFgD,CAsFhD,MAtFgD,CAuFhD,MAvFgD,CAwFhD,MAxFgD,CAyFhD,KAzFgD,CA0FhD,OA1FgD,CA2FhD,MA3FgD,CA4FhD,MA5FgD,CA6FhD,OA7FgD,CA8FhD,OA9FgD,CA+FhD,MA/FgD,CAgGhD,MAhGgD,CAiGhD,KAjGgD,CAkGhD,IAlGgD,CAmGhD,KAnGgD,CAoGhD,MApGgD,CAqGhD,IArGgD,CAsGhD,OAtGgD,CAuGhD,KAvGgD,CAwGhD,IAxGgD,CAyGhD,MAzGgD,CA0GhD,MA1GgD,CA2GhD,MA3GgD,CA4GhD,OA5GgD,CA6GhD,OA7GgD,CA8GhD,OA9GgD,CA+GhD,KA/GgD,CAgHhD,MAhHgD,CAiHhD,KAjHgD,CAkHhD,MAlHgD,CAmHhD,MAnHgD,CAoHhD,OApHgD,CAqHhD,KArHgD,CAsHhD,KAtHgD,CAuHhD,MAvHgD,CAA5B,CAAtB,CA0HArK,CAAI,CAACuF,QAAL,CAAcG,gBAAd,CAA+B1F,CAAI,CAACO,cAApC,CAAoD,gBAApD,EAqBAP,CAAI,CAACM,OAAL,CAAe,SAAU6G,CAAV,CAAiB,CAC9B,MAAOA,CAAAA,CAAK,CAAC5C,MAAN,CAAa,SAAU/B,CAAV,CAAa,CAC/B,MAAOA,CAAAA,CAAC,CAAC0H,OAAF,CAAU,MAAV,CAAkB,EAAlB,EAAsBA,OAAtB,CAA8B,MAA9B,CAAsC,EAAtC,CACR,CAFM,CAGR,CAJD,CAMAlK,CAAI,CAACuF,QAAL,CAAcG,gBAAd,CAA+B1F,CAAI,CAACM,OAApC,CAA6C,SAA7C,EA2BAN,CAAI,CAAC0K,QAAL,CAAgB,UAAY,CAC1B,KAAKC,KAAL,IACA,KAAKC,KAAL,CAAa,EAAb,CACA,KAAKC,EAAL,CAAU7K,CAAI,CAAC0K,QAAL,CAAcI,OAAxB,CACA9K,CAAI,CAAC0K,QAAL,CAAcI,OAAd,EAAyB,CAC1B,CALD,CAeA9K,CAAI,CAAC0K,QAAL,CAAcI,OAAd,CAAwB,CAAxB,CASA9K,CAAI,CAAC0K,QAAL,CAAcK,SAAd,CAA0B,SAAUC,CAAV,CAAe,CAGvC,OAFI9K,CAAAA,CAAO,CAAG,GAAIF,CAAAA,CAAI,CAAC0K,QAAL,CAAcvK,OAEhC,CAASsB,CAAC,CAAG,CAAb,CAAgBoD,CAAG,CAAGmG,CAAG,CAACtJ,MAA1B,CAAkCD,CAAC,CAAGoD,CAAtC,CAA2CpD,CAAC,EAA5C,CAAgD,CAC9CvB,CAAO,CAAC6H,MAAR,CAAeiD,CAAG,CAACvJ,CAAD,CAAlB,CACD,CAEDvB,CAAO,CAAC+K,MAAR,GACA,MAAO/K,CAAAA,CAAO,CAACgL,IAChB,CATD,CAoBAlL,CAAI,CAAC0K,QAAL,CAAcS,UAAd,CAA2B,SAAUC,CAAV,CAAkB,CAC3C,GAAI,gBAAkBA,CAAAA,CAAtB,CAA8B,CAC5B,MAAOpL,CAAAA,CAAI,CAAC0K,QAAL,CAAcW,eAAd,CAA8BD,CAAM,CAACE,IAArC,CAA2CF,CAAM,CAACG,YAAlD,CACR,CAFD,IAEO,CACL,MAAOvL,CAAAA,CAAI,CAAC0K,QAAL,CAAcnI,UAAd,CAAyB6I,CAAM,CAACE,IAAhC,CACR,CACF,CAND,CAuBAtL,CAAI,CAAC0K,QAAL,CAAcW,eAAd,CAAgC,SAAUhH,CAAV,CAAekH,CAAf,CAA6B,IACvDL,CAAAA,CAAI,CAAG,GAAIlL,CAAAA,CAAI,CAAC0K,QADuC,CAGvDc,CAAK,CAAG,CAAC,CACXC,IAAI,CAAEP,CADK,CAEXQ,cAAc,CAAEH,CAFL,CAGXlH,GAAG,CAAEA,CAHM,CAAD,CAH+C,CAS3D,MAAOmH,CAAK,CAAC9J,MAAb,CAAqB,CACnB,GAAIiK,CAAAA,CAAK,CAAGH,CAAK,CAACI,GAAN,EAAZ,CAGA,GAAuB,CAAnB,CAAAD,CAAK,CAACtH,GAAN,CAAU3C,MAAd,CAA0B,CACxB,GAAIuD,CAAAA,CAAI,CAAG0G,CAAK,CAACtH,GAAN,CAAUa,MAAV,CAAiB,CAAjB,CAAX,CACI2G,CADJ,CAGA,GAAI5G,CAAI,GAAI0G,CAAAA,CAAK,CAACF,IAAN,CAAWb,KAAvB,CAA8B,CAC5BiB,CAAU,CAAGF,CAAK,CAACF,IAAN,CAAWb,KAAX,CAAiB3F,CAAjB,CACd,CAFD,IAEO,CACL4G,CAAU,CAAG,GAAI7L,CAAAA,CAAI,CAAC0K,QAAtB,CACAiB,CAAK,CAACF,IAAN,CAAWb,KAAX,CAAiB3F,CAAjB,EAAyB4G,CAC1B,CAED,GAAwB,CAApB,EAAAF,CAAK,CAACtH,GAAN,CAAU3C,MAAd,CAA2B,CACzBmK,CAAU,CAAClB,KAAX,GACD,CAEDa,CAAK,CAAC9H,IAAN,CAAW,CACT+H,IAAI,CAAEI,CADG,CAETH,cAAc,CAAEC,CAAK,CAACD,cAFb,CAGTrH,GAAG,CAAEsH,CAAK,CAACtH,GAAN,CAAUtC,KAAV,CAAgB,CAAhB,CAHI,CAAX,CAKD,CAED,GAA4B,CAAxB,EAAA4J,CAAK,CAACD,cAAV,CAA+B,CAC7B,QACD,CAGD,GAAI,KAAOC,CAAAA,CAAK,CAACF,IAAN,CAAWb,KAAtB,CAA6B,CAC3B,GAAIkB,CAAAA,CAAa,CAAGH,CAAK,CAACF,IAAN,CAAWb,KAAX,CAAiB,GAAjB,CACrB,CAFD,IAEO,CACL,GAAIkB,CAAAA,CAAa,CAAG,GAAI9L,CAAAA,CAAI,CAAC0K,QAA7B,CACAiB,CAAK,CAACF,IAAN,CAAWb,KAAX,CAAiB,GAAjB,EAAwBkB,CACzB,CAED,GAAwB,CAApB,EAAAH,CAAK,CAACtH,GAAN,CAAU3C,MAAd,CAA2B,CACzBoK,CAAa,CAACnB,KAAd,GACD,CAEDa,CAAK,CAAC9H,IAAN,CAAW,CACT+H,IAAI,CAAEK,CADG,CAETJ,cAAc,CAAEC,CAAK,CAACD,cAAN,CAAuB,CAF9B,CAGTrH,GAAG,CAAEsH,CAAK,CAACtH,GAHF,CAAX,EASA,GAAuB,CAAnB,CAAAsH,CAAK,CAACtH,GAAN,CAAU3C,MAAd,CAA0B,CACxB8J,CAAK,CAAC9H,IAAN,CAAW,CACT+H,IAAI,CAAEE,CAAK,CAACF,IADH,CAETC,cAAc,CAAEC,CAAK,CAACD,cAAN,CAAuB,CAF9B,CAGTrH,GAAG,CAAEsH,CAAK,CAACtH,GAAN,CAAUtC,KAAV,CAAgB,CAAhB,CAHI,CAAX,CAKD,CAID,GAAwB,CAApB,EAAA4J,CAAK,CAACtH,GAAN,CAAU3C,MAAd,CAA2B,CACzBiK,CAAK,CAACF,IAAN,CAAWd,KAAX,GACD,CAKD,GAAwB,CAApB,EAAAgB,CAAK,CAACtH,GAAN,CAAU3C,MAAd,CAA2B,CACzB,GAAI,KAAOiK,CAAAA,CAAK,CAACF,IAAN,CAAWb,KAAtB,CAA6B,CAC3B,GAAImB,CAAAA,CAAgB,CAAGJ,CAAK,CAACF,IAAN,CAAWb,KAAX,CAAiB,GAAjB,CACxB,CAFD,IAEO,CACL,GAAImB,CAAAA,CAAgB,CAAG,GAAI/L,CAAAA,CAAI,CAAC0K,QAAhC,CACAiB,CAAK,CAACF,IAAN,CAAWb,KAAX,CAAiB,GAAjB,EAAwBmB,CACzB,CAED,GAAwB,CAApB,EAAAJ,CAAK,CAACtH,GAAN,CAAU3C,MAAd,CAA2B,CACzBqK,CAAgB,CAACpB,KAAjB,GACD,CAEDa,CAAK,CAAC9H,IAAN,CAAW,CACT+H,IAAI,CAAEM,CADG,CAETL,cAAc,CAAEC,CAAK,CAACD,cAAN,CAAuB,CAF9B,CAGTrH,GAAG,CAAEsH,CAAK,CAACtH,GAAN,CAAUtC,KAAV,CAAgB,CAAhB,CAHI,CAAX,CAKD,CAKD,GAAuB,CAAnB,CAAA4J,CAAK,CAACtH,GAAN,CAAU3C,MAAd,CAA0B,CACxB,GAAIsK,CAAAA,CAAK,CAAGL,CAAK,CAACtH,GAAN,CAAUa,MAAV,CAAiB,CAAjB,CAAZ,CACI+G,CAAK,CAAGN,CAAK,CAACtH,GAAN,CAAUa,MAAV,CAAiB,CAAjB,CADZ,CAEIgH,CAFJ,CAIA,GAAID,CAAK,GAAIN,CAAAA,CAAK,CAACF,IAAN,CAAWb,KAAxB,CAA+B,CAC7BsB,CAAa,CAAGP,CAAK,CAACF,IAAN,CAAWb,KAAX,CAAiBqB,CAAjB,CACjB,CAFD,IAEO,CACLC,CAAa,CAAG,GAAIlM,CAAAA,CAAI,CAAC0K,QAAzB,CACAiB,CAAK,CAACF,IAAN,CAAWb,KAAX,CAAiBqB,CAAjB,EAA0BC,CAC3B,CAED,GAAwB,CAApB,EAAAP,CAAK,CAACtH,GAAN,CAAU3C,MAAd,CAA2B,CACzBwK,CAAa,CAACvB,KAAd,GACD,CAEDa,CAAK,CAAC9H,IAAN,CAAW,CACT+H,IAAI,CAAES,CADG,CAETR,cAAc,CAAEC,CAAK,CAACD,cAAN,CAAuB,CAF9B,CAGTrH,GAAG,CAAE2H,CAAK,CAAGL,CAAK,CAACtH,GAAN,CAAUtC,KAAV,CAAgB,CAAhB,CAHJ,CAAX,CAKD,CACF,CAED,MAAOmJ,CAAAA,CACR,CA5HD,CAwIAlL,CAAI,CAAC0K,QAAL,CAAcnI,UAAd,CAA2B,SAAU8B,CAAV,CAAe,CAYxC,OAXIoH,CAAAA,CAAI,CAAG,GAAIzL,CAAAA,CAAI,CAAC0K,QAWpB,CAVIQ,CAAI,CAAGO,CAUX,CAAShK,CAAC,CAAG,CAAb,CAAgBoD,CAAG,CAAGR,CAAG,CAAC3C,MAA1B,CAAkCD,CAAC,CAAGoD,CAAtC,CAA2CpD,CAAC,EAA5C,CAAgD,CAC9C,GAAIwD,CAAAA,CAAI,CAAGZ,CAAG,CAAC5C,CAAD,CAAd,CACIkJ,CAAK,CAAIlJ,CAAC,EAAIoD,CAAG,CAAG,CADxB,CAGA,GAAY,GAAR,EAAAI,CAAJ,CAAiB,CACfwG,CAAI,CAACb,KAAL,CAAW3F,CAAX,EAAmBwG,CAAnB,CACAA,CAAI,CAACd,KAAL,CAAaA,CAEd,CAJD,IAIO,CACL,GAAIwB,CAAAA,CAAI,CAAG,GAAInM,CAAAA,CAAI,CAAC0K,QAApB,CACAyB,CAAI,CAACxB,KAAL,CAAaA,CAAb,CAEAc,CAAI,CAACb,KAAL,CAAW3F,CAAX,EAAmBkH,CAAnB,CACAV,CAAI,CAAGU,CACR,CACF,CAED,MAAOjB,CAAAA,CACR,CA9BD,CA0CAlL,CAAI,CAAC0K,QAAL,CAAc9H,SAAd,CAAwBmG,OAAxB,CAAkC,UAAY,IACxCwB,CAAAA,CAAK,CAAG,EADgC,CAGxCiB,CAAK,CAAG,CAAC,CACXY,MAAM,CAAE,EADG,CAEXX,IAAI,CAAE,IAFK,CAAD,CAHgC,CAQ5C,MAAOD,CAAK,CAAC9J,MAAb,CAAqB,CACnB,GAAIiK,CAAAA,CAAK,CAAGH,CAAK,CAACI,GAAN,EAAZ,CACIhB,CAAK,CAAGtJ,MAAM,CAACE,IAAP,CAAYmK,CAAK,CAACF,IAAN,CAAWb,KAAvB,CADZ,CAEI/F,CAAG,CAAG+F,CAAK,CAAClJ,MAFhB,CAIA,GAAIiK,CAAK,CAACF,IAAN,CAAWd,KAAf,CAAsB,CAKpBgB,CAAK,CAACS,MAAN,CAAalH,MAAb,CAAoB,CAApB,EACAqF,CAAK,CAAC7G,IAAN,CAAWiI,CAAK,CAACS,MAAjB,CACD,CAED,IAAK,GAAI3K,CAAAA,CAAC,CAAG,CAAR,CACC4K,CADN,CAAgB5K,CAAC,CAAGoD,CAApB,CAAyBpD,CAAC,EAA1B,CAA8B,CACxB4K,CADwB,CACjBzB,CAAK,CAACnJ,CAAD,CADY,CAG5B+J,CAAK,CAAC9H,IAAN,CAAW,CACT0I,MAAM,CAAET,CAAK,CAACS,MAAN,CAAazI,MAAb,CAAoB0I,CAApB,CADC,CAETZ,IAAI,CAAEE,CAAK,CAACF,IAAN,CAAWb,KAAX,CAAiByB,CAAjB,CAFG,CAAX,CAID,CACF,CAED,MAAO9B,CAAAA,CACR,CAjCD,CA6CAvK,CAAI,CAAC0K,QAAL,CAAc9H,SAAd,CAAwBxB,QAAxB,CAAmC,UAAY,CAS7C,GAAI,KAAKkL,IAAT,CAAe,CACb,MAAO,MAAKA,IACb,CAMD,OAJIjI,CAAAA,CAAG,CAAG,KAAKsG,KAAL,CAAa,GAAb,CAAmB,GAI7B,CAHI4B,CAAM,CAAGjL,MAAM,CAACE,IAAP,CAAY,KAAKoJ,KAAjB,EAAwB4B,IAAxB,EAGb,CAFI3H,CAAG,CAAG0H,CAAM,CAAC7K,MAEjB,CAASD,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGoD,CAApB,CAAyBpD,CAAC,EAA1B,CAA8B,CAC5B,GAAIkE,CAAAA,CAAK,CAAG4G,CAAM,CAAC9K,CAAD,CAAlB,CACIgK,CAAI,CAAG,KAAKb,KAAL,CAAWjF,CAAX,CADX,CAGAtB,CAAG,CAAGA,CAAG,CAAGsB,CAAN,CAAc8F,CAAI,CAACZ,EAC1B,CAED,MAAOxG,CAAAA,CACR,CAzBD,CAqCArE,CAAI,CAAC0K,QAAL,CAAc9H,SAAd,CAAwBI,SAAxB,CAAoC,SAAUO,CAAV,CAAa,IAC3CyF,CAAAA,CAAM,CAAG,GAAIhJ,CAAAA,CAAI,CAAC0K,QADyB,CAE3CiB,CAAK,OAFsC,CAI3CH,CAAK,CAAG,CAAC,CACXiB,KAAK,CAAElJ,CADI,CAEXyF,MAAM,CAAEA,CAFG,CAGXyC,IAAI,CAAE,IAHK,CAAD,CAJmC,CAU/C,MAAOD,CAAK,CAAC9J,MAAb,CAAqB,CACnBiK,CAAK,CAAGH,CAAK,CAACI,GAAN,EAAR,CAWA,OALIc,CAAAA,CAAM,CAAGpL,MAAM,CAACE,IAAP,CAAYmK,CAAK,CAACc,KAAN,CAAY7B,KAAxB,CAKb,CAJI+B,CAAI,CAAGD,CAAM,CAAChL,MAIlB,CAHIkL,CAAM,CAAGtL,MAAM,CAACE,IAAP,CAAYmK,CAAK,CAACF,IAAN,CAAWb,KAAvB,CAGb,CAFIiC,CAAI,CAAGD,CAAM,CAAClL,MAElB,CAASoL,CAAC,CAAG,CAAb,CACMC,CADN,CAAgBD,CAAC,CAAGH,CAApB,CAA0BG,CAAC,EAA3B,CAA+B,CACzBC,CADyB,CACjBL,CAAM,CAACI,CAAD,CADW,CAG7B,IAAK,GAAIrK,CAAAA,CAAC,CAAG,CAAR,CACCuK,CADN,CAAgBvK,CAAC,CAAGoK,CAApB,CAA0BpK,CAAC,EAA3B,CAA+B,CACzBuK,CADyB,CACjBJ,CAAM,CAACnK,CAAD,CADW,CAG7B,GAAIuK,CAAK,EAAID,CAAT,EAA2B,GAAT,EAAAA,CAAtB,CAAoC,CAClC,GAAItB,CAAAA,CAAI,CAAGE,CAAK,CAACF,IAAN,CAAWb,KAAX,CAAiBoC,CAAjB,CAAX,CACIP,CAAK,CAAGd,CAAK,CAACc,KAAN,CAAY7B,KAAZ,CAAkBmC,CAAlB,CADZ,CAEIpC,CAAK,CAAGc,CAAI,CAACd,KAAL,EAAc8B,CAAK,CAAC9B,KAFhC,CAGIwB,CAAI,OAHR,CAKA,GAAIa,CAAK,GAAIrB,CAAAA,CAAK,CAAC3C,MAAN,CAAa4B,KAA1B,CAAiC,CAI/BuB,CAAI,CAAGR,CAAK,CAAC3C,MAAN,CAAa4B,KAAb,CAAmBoC,CAAnB,CAAP,CACAb,CAAI,CAACxB,KAAL,CAAawB,CAAI,CAACxB,KAAL,EAAcA,CAE5B,CAPD,IAOO,CAILwB,CAAI,CAAG,GAAInM,CAAAA,CAAI,CAAC0K,QAAhB,CACAyB,CAAI,CAACxB,KAAL,CAAaA,CAAb,CACAgB,CAAK,CAAC3C,MAAN,CAAa4B,KAAb,CAAmBoC,CAAnB,EAA4Bb,CAC7B,CAEDX,CAAK,CAAC9H,IAAN,CAAW,CACT+I,KAAK,CAAEA,CADE,CAETzD,MAAM,CAAEmD,CAFC,CAGTV,IAAI,CAAEA,CAHG,CAAX,CAKD,CACF,CACF,CACF,CAED,MAAOzC,CAAAA,CACR,CA7DD,CA8DAhJ,CAAI,CAAC0K,QAAL,CAAcvK,OAAd,CAAwB,UAAY,CAClC,KAAK8M,YAAL,CAAoB,EAApB,CACA,KAAK/B,IAAL,CAAY,GAAIlL,CAAAA,CAAI,CAAC0K,QAArB,CACA,KAAKwC,cAAL,CAAsB,EAAtB,CACA,KAAKC,cAAL,CAAsB,EACvB,CALD,CAOAnN,CAAI,CAAC0K,QAAL,CAAcvK,OAAd,CAAsByC,SAAtB,CAAgCmF,MAAhC,CAAyC,SAAUqF,CAAV,CAAgB,CACvD,GAAI3B,CAAAA,CAAJ,CACI4B,CAAY,CAAG,CADnB,CAGA,GAAID,CAAI,CAAG,KAAKH,YAAhB,CAA8B,CAC5B,KAAM,IAAI/G,CAAAA,KAAJ,CAAW,6BAAX,CACP,CAED,IAAK,GAAIzE,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAG2L,CAAI,CAAC1L,MAAT,EAAmBD,CAAC,CAAG,KAAKwL,YAAL,CAAkBvL,MAAzD,CAAiED,CAAC,EAAlE,CAAsE,CACpE,GAAI2L,CAAI,CAAC3L,CAAD,CAAJ,EAAW,KAAKwL,YAAL,CAAkBxL,CAAlB,CAAf,CAAqC,MACrC4L,CAAY,EACb,CAED,KAAKC,QAAL,CAAcD,CAAd,EAEA,GAAkC,CAA9B,OAAKH,cAAL,CAAoBxL,MAAxB,CAAqC,CACnC+J,CAAI,CAAG,KAAKP,IACb,CAFD,IAEO,CACLO,CAAI,CAAG,KAAKyB,cAAL,CAAoB,KAAKA,cAAL,CAAoBxL,MAApB,CAA6B,CAAjD,EAAoD6L,KAC5D,CAED,IAAK,GAAI9L,CAAAA,CAAC,CAAG4L,CAAb,CAA2B5L,CAAC,CAAG2L,CAAI,CAAC1L,MAApC,CAA4CD,CAAC,EAA7C,CAAiD,CAC/C,GAAI+L,CAAAA,CAAQ,CAAG,GAAIxN,CAAAA,CAAI,CAAC0K,QAAxB,CACIzF,CAAI,CAAGmI,CAAI,CAAC3L,CAAD,CADf,CAGAgK,CAAI,CAACb,KAAL,CAAW3F,CAAX,EAAmBuI,CAAnB,CAEA,KAAKN,cAAL,CAAoBxJ,IAApB,CAAyB,CACvB+J,MAAM,CAAEhC,CADe,CAEvBxG,IAAI,CAAEA,CAFiB,CAGvBsI,KAAK,CAAEC,CAHgB,CAAzB,EAMA/B,CAAI,CAAG+B,CACR,CAED/B,CAAI,CAACd,KAAL,IACA,KAAKsC,YAAL,CAAoBG,CACrB,CAtCD,CAwCApN,CAAI,CAAC0K,QAAL,CAAcvK,OAAd,CAAsByC,SAAtB,CAAgCqI,MAAhC,CAAyC,UAAY,CACnD,KAAKqC,QAAL,CAAc,CAAd,CACD,CAFD,CAIAtN,CAAI,CAAC0K,QAAL,CAAcvK,OAAd,CAAsByC,SAAtB,CAAgC0K,QAAhC,CAA2C,SAAUI,CAAV,CAAkB,CAC3D,IAAK,GAAIjM,CAAAA,CAAC,CAAG,KAAKyL,cAAL,CAAoBxL,MAApB,CAA6B,CAA1C,CAA6CD,CAAC,EAAIiM,CAAlD,CAA0DjM,CAAC,EAA3D,CAA+D,CAC7D,GAAIgK,CAAAA,CAAI,CAAG,KAAKyB,cAAL,CAAoBzL,CAApB,CAAX,CACIkM,CAAQ,CAAGlC,CAAI,CAAC8B,KAAL,CAAWnM,QAAX,EADf,CAGA,GAAIuM,CAAQ,GAAI,MAAKR,cAArB,CAAqC,CACnC1B,CAAI,CAACgC,MAAL,CAAY7C,KAAZ,CAAkBa,CAAI,CAACxG,IAAvB,EAA+B,KAAKkI,cAAL,CAAoBQ,CAApB,CAChC,CAFD,IAEO,CAGLlC,CAAI,CAAC8B,KAAL,CAAWjB,IAAX,CAAkBqB,CAAlB,CAEA,KAAKR,cAAL,CAAoBQ,CAApB,EAAgClC,CAAI,CAAC8B,KACtC,CAED,KAAKL,cAAL,CAAoBtB,GAApB,EACD,CACF,CAjBD,CAuCA5L,CAAI,CAAC4N,KAAL,CAAa,SAAUC,CAAV,CAAiB,CAC5B,KAAKC,aAAL,CAAqBD,CAAK,CAACC,aAA3B,CACA,KAAKC,YAAL,CAAoBF,CAAK,CAACE,YAA1B,CACA,KAAKC,QAAL,CAAgBH,CAAK,CAACG,QAAtB,CACA,KAAKC,MAAL,CAAcJ,CAAK,CAACI,MAApB,CACA,KAAK7N,QAAL,CAAgByN,CAAK,CAACzN,QACvB,CAND,CA+EAJ,CAAI,CAAC4N,KAAL,CAAWhL,SAAX,CAAqBsL,MAArB,CAA8B,SAAUC,CAAV,CAAuB,CACnD,MAAO,MAAKC,KAAL,CAAW,SAAUA,CAAV,CAAiB,CACjC,GAAIC,CAAAA,CAAM,CAAG,GAAIrO,CAAAA,CAAI,CAACsO,WAAT,CAAqBH,CAArB,CAAkCC,CAAlC,CAAb,CACAC,CAAM,CAACE,KAAP,EACD,CAHM,CAIR,CALD,CAgCAvO,CAAI,CAAC4N,KAAL,CAAWhL,SAAX,CAAqBwL,KAArB,CAA6B,SAAU5J,CAAV,CAAc,CAoBzC,OAZI4J,CAAAA,CAAK,CAAG,GAAIpO,CAAAA,CAAI,CAACwO,KAAT,CAAe,KAAKP,MAApB,CAYZ,CAXIQ,CAAc,CAAGnN,MAAM,CAACC,MAAP,CAAc,IAAd,CAWrB,CAVImN,CAAY,CAAGpN,MAAM,CAACC,MAAP,CAAc,IAAd,CAUnB,CATIoN,CAAc,CAAGrN,MAAM,CAACC,MAAP,CAAc,IAAd,CASrB,CARIqN,CAAe,CAAGtN,MAAM,CAACC,MAAP,CAAc,IAAd,CAQtB,CAPIsN,CAAiB,CAAGvN,MAAM,CAACC,MAAP,CAAc,IAAd,CAOxB,CAASE,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAG,KAAKwM,MAAL,CAAYvM,MAAhC,CAAwCD,CAAC,EAAzC,CAA6C,CAC3CiN,CAAY,CAAC,KAAKT,MAAL,CAAYxM,CAAZ,CAAD,CAAZ,CAA+B,GAAIzB,CAAAA,CAAI,CAACsH,MACzC,CAED9C,CAAE,CAAC9D,IAAH,CAAQ0N,CAAR,CAAeA,CAAf,EAEA,IAAK,GAAI3M,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAG2M,CAAK,CAACU,OAAN,CAAcpN,MAAlC,CAA0CD,CAAC,EAA3C,CAA+C,CAS7C,GAAI2J,CAAAA,CAAM,CAAGgD,CAAK,CAACU,OAAN,CAAcrN,CAAd,CAAb,CACIsN,CAAK,CAAG,IADZ,CAEIC,CAAa,CAAGhP,CAAI,CAAC6C,GAAL,CAASO,KAF7B,CAIA,GAAIgI,CAAM,CAAC6D,WAAX,CAAwB,CACtBF,CAAK,CAAG,KAAK3O,QAAL,CAAc8G,SAAd,CAAwBkE,CAAM,CAACE,IAA/B,CAAqC,CAC3C2C,MAAM,CAAE7C,CAAM,CAAC6C,MAD4B,CAArC,CAGT,CAJD,IAIO,CACLc,CAAK,CAAG,CAAC3D,CAAM,CAACE,IAAR,CACT,CAED,IAAK,GAAI4D,CAAAA,CAAC,CAAG,CAAR,CACC5D,CADN,CAAgB4D,CAAC,CAAGH,CAAK,CAACrN,MAA1B,CAAkCwN,CAAC,EAAnC,CAAuC,CACjC5D,CADiC,CAC1ByD,CAAK,CAACG,CAAD,CADqB,CASrC9D,CAAM,CAACE,IAAP,CAAcA,CAAd,CAOA,GAAI6D,CAAAA,CAAY,CAAGnP,CAAI,CAAC0K,QAAL,CAAcS,UAAd,CAAyBC,CAAzB,CAAnB,CACIgE,CAAa,CAAG,KAAKpB,QAAL,CAAchL,SAAd,CAAwBmM,CAAxB,EAAsCpG,OAAtC,EADpB,CASA,GAA6B,CAAzB,GAAAqG,CAAa,CAAC1N,MAAd,EAA8B0J,CAAM,CAACiE,QAAP,GAAoBrP,CAAI,CAACwO,KAAL,CAAWa,QAAX,CAAoBC,QAA1E,CAAoF,CAClF,IAAK,GAAIrI,CAAAA,CAAC,CAAG,CAAR,CACCsI,CADN,CAAgBtI,CAAC,CAAGmE,CAAM,CAAC6C,MAAP,CAAcvM,MAAlC,CAA0CuF,CAAC,EAA3C,CAA+C,CACzCsI,CADyC,CACjCnE,CAAM,CAAC6C,MAAP,CAAchH,CAAd,CADiC,CAE7C2H,CAAe,CAACW,CAAD,CAAf,CAAyBvP,CAAI,CAAC6C,GAAL,CAASO,KACnC,CAED,KACD,CAED,IAAK,GAAI2D,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGqI,CAAa,CAAC1N,MAAlC,CAA0CqF,CAAC,EAA3C,CAA+C,CAS7C,OAJIyI,CAAAA,CAAY,CAAGJ,CAAa,CAACrI,CAAD,CAIhC,CAHIlD,CAAO,CAAG,KAAKiK,aAAL,CAAmB0B,CAAnB,CAGd,CAFIC,CAAS,CAAG5L,CAAO,CAAC6L,MAExB,CAASzI,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGmE,CAAM,CAAC6C,MAAP,CAAcvM,MAAlC,CAA0CuF,CAAC,EAA3C,CAA+C,CAS7C,GAAIsI,CAAAA,CAAK,CAAGnE,CAAM,CAAC6C,MAAP,CAAchH,CAAd,CAAZ,CACI0I,CAAY,CAAG9L,CAAO,CAAC0L,CAAD,CAD1B,CAEIK,CAAoB,CAAGtO,MAAM,CAACE,IAAP,CAAYmO,CAAZ,CAF3B,CAGIE,CAAS,CAAGL,CAAY,CAAG,GAAf,CAAqBD,CAHrC,CAIIO,CAAoB,CAAG,GAAI9P,CAAAA,CAAI,CAAC6C,GAAT,CAAa+M,CAAb,CAJ3B,CAWA,GAAIxE,CAAM,CAACiE,QAAP,EAAmBrP,CAAI,CAACwO,KAAL,CAAWa,QAAX,CAAoBC,QAA3C,CAAqD,CACnDN,CAAa,CAAGA,CAAa,CAAC9L,KAAd,CAAoB4M,CAApB,CAAhB,CAEA,GAAIlB,CAAe,CAACW,CAAD,CAAf,SAAJ,CAA0C,CACxCX,CAAe,CAACW,CAAD,CAAf,CAAyBvP,CAAI,CAAC6C,GAAL,CAASE,QACnC,CACF,CAOD,GAAIqI,CAAM,CAACiE,QAAP,EAAmBrP,CAAI,CAACwO,KAAL,CAAWa,QAAX,CAAoBU,UAA3C,CAAuD,CACrD,GAAIlB,CAAiB,CAACU,CAAD,CAAjB,SAAJ,CAA4C,CAC1CV,CAAiB,CAACU,CAAD,CAAjB,CAA2BvP,CAAI,CAAC6C,GAAL,CAASO,KACrC,CAEDyL,CAAiB,CAACU,CAAD,CAAjB,CAA2BV,CAAiB,CAACU,CAAD,CAAjB,CAAyBrM,KAAzB,CAA+B4M,CAA/B,CAA3B,CAOA,QACD,CASDpB,CAAY,CAACa,CAAD,CAAZ,CAAoBtH,MAApB,CAA2BwH,CAA3B,CAAsCrE,CAAM,CAAC4E,KAA7C,CAAoD,SAAU1M,CAAV,CAAaC,CAAb,CAAgB,CAAE,MAAOD,CAAAA,CAAC,CAAGC,CAAG,CAApF,EAMA,GAAIoL,CAAc,CAACkB,CAAD,CAAlB,CAA+B,CAC7B,QACD,CAED,IAAK,GAAII,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGL,CAAoB,CAAClO,MAAzC,CAAiDuO,CAAC,EAAlD,CAAsD,CAOpD,GAAIC,CAAAA,CAAmB,CAAGN,CAAoB,CAACK,CAAD,CAA9C,CACIE,CAAgB,CAAG,GAAInQ,CAAAA,CAAI,CAACiC,QAAT,CAAmBiO,CAAnB,CAAwCX,CAAxC,CADvB,CAEIjL,CAAQ,CAAGqL,CAAY,CAACO,CAAD,CAF3B,CAGIE,CAHJ,CAKA,GAAI,CAACA,CAAU,CAAG3B,CAAc,CAAC0B,CAAD,CAA5B,UAAJ,CAAmE,CACjE1B,CAAc,CAAC0B,CAAD,CAAd,CAAmC,GAAInQ,CAAAA,CAAI,CAACqQ,SAAT,CAAoBb,CAApB,CAAkCD,CAAlC,CAAyCjL,CAAzC,CACpC,CAFD,IAEO,CACL8L,CAAU,CAAC/P,GAAX,CAAemP,CAAf,CAA6BD,CAA7B,CAAoCjL,CAApC,CACD,CAEF,CAEDqK,CAAc,CAACkB,CAAD,CAAd,GACD,CACF,CACF,CAQD,GAAIzE,CAAM,CAACiE,QAAP,GAAoBrP,CAAI,CAACwO,KAAL,CAAWa,QAAX,CAAoBC,QAA5C,CAAsD,CACpD,IAAK,GAAIrI,CAAAA,CAAC,CAAG,CAAR,CACCsI,CADN,CAAgBtI,CAAC,CAAGmE,CAAM,CAAC6C,MAAP,CAAcvM,MAAlC,CAA0CuF,CAAC,EAA3C,CAA+C,CACzCsI,CADyC,CACjCnE,CAAM,CAAC6C,MAAP,CAAchH,CAAd,CADiC,CAE7C2H,CAAe,CAACW,CAAD,CAAf,CAAyBX,CAAe,CAACW,CAAD,CAAf,CAAuBvM,SAAvB,CAAiCgM,CAAjC,CAC1B,CACF,CACF,CAUD,OAHIsB,CAAAA,CAAkB,CAAGtQ,CAAI,CAAC6C,GAAL,CAASE,QAGlC,CAFIwN,CAAoB,CAAGvQ,CAAI,CAAC6C,GAAL,CAASO,KAEpC,CAAS3B,CAAC,CAAG,CAAb,CACM8N,CADN,CAAgB9N,CAAC,CAAG,KAAKwM,MAAL,CAAYvM,MAAhC,CAAwCD,CAAC,EAAzC,CAA6C,CACvC8N,CADuC,CAC/B,KAAKtB,MAAL,CAAYxM,CAAZ,CAD+B,CAG3C,GAAImN,CAAe,CAACW,CAAD,CAAnB,CAA4B,CAC1Be,CAAkB,CAAGA,CAAkB,CAACtN,SAAnB,CAA6B4L,CAAe,CAACW,CAAD,CAA5C,CACtB,CAED,GAAIV,CAAiB,CAACU,CAAD,CAArB,CAA8B,CAC5BgB,CAAoB,CAAGA,CAAoB,CAACrN,KAArB,CAA2B2L,CAAiB,CAACU,CAAD,CAA5C,CACxB,CACF,CAED,GAAIiB,CAAAA,CAAiB,CAAGlP,MAAM,CAACE,IAAP,CAAYiN,CAAZ,CAAxB,CACIgC,CAAO,CAAG,EADd,CAEIC,CAAO,CAAGpP,MAAM,CAACC,MAAP,CAAc,IAAd,CAFd,CAcA,GAAI6M,CAAK,CAACuC,SAAN,EAAJ,CAAuB,CACrBH,CAAiB,CAAGlP,MAAM,CAACE,IAAP,CAAY,KAAKuM,YAAjB,CAApB,CAEA,IAAK,GAAItM,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAG+O,CAAiB,CAAC9O,MAAtC,CAA8CD,CAAC,EAA/C,CAAmD,IAC7C0O,CAAAA,CAAgB,CAAGK,CAAiB,CAAC/O,CAAD,CADS,CAE7CkB,CAAQ,CAAG3C,CAAI,CAACiC,QAAL,CAAcM,UAAd,CAAyB4N,CAAzB,CAFkC,CAGjD1B,CAAc,CAAC0B,CAAD,CAAd,CAAmC,GAAInQ,CAAAA,CAAI,CAACqQ,SAC7C,CACF,CAED,IAAK,GAAI5O,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAG+O,CAAiB,CAAC9O,MAAtC,CAA8CD,CAAC,EAA/C,CAAmD,CASjD,GAAIkB,CAAAA,CAAQ,CAAG3C,CAAI,CAACiC,QAAL,CAAcM,UAAd,CAAyBiO,CAAiB,CAAC/O,CAAD,CAA1C,CAAf,CACIS,CAAM,CAAGS,CAAQ,CAACT,MADtB,CAGA,GAAI,CAACoO,CAAkB,CAACnN,QAAnB,CAA4BjB,CAA5B,CAAL,CAA0C,CACxC,QACD,CAED,GAAIqO,CAAoB,CAACpN,QAArB,CAA8BjB,CAA9B,CAAJ,CAA2C,CACzC,QACD,CAED,GAAI0O,CAAAA,CAAW,CAAG,KAAK7C,YAAL,CAAkBpL,CAAlB,CAAlB,CACIkO,CAAK,CAAGnC,CAAY,CAAC/L,CAAQ,CAACR,SAAV,CAAZ,CAAiC2G,UAAjC,CAA4C8H,CAA5C,CADZ,CAEIE,CAFJ,CAIA,GAAI,CAACA,CAAQ,CAAGJ,CAAO,CAACxO,CAAD,CAAnB,UAAJ,CAAgD,CAC9C4O,CAAQ,CAACD,KAAT,EAAkBA,CAAlB,CACAC,CAAQ,CAACC,SAAT,CAAmBC,OAAnB,CAA2BvC,CAAc,CAAC9L,CAAD,CAAzC,CACD,CAHD,IAGO,CACL,GAAIyC,CAAAA,CAAK,CAAG,CACV6L,GAAG,CAAE/O,CADK,CAEV2O,KAAK,CAAEA,CAFG,CAGVE,SAAS,CAAEtC,CAAc,CAAC9L,CAAD,CAHf,CAAZ,CAKA+N,CAAO,CAACxO,CAAD,CAAP,CAAkBkD,CAAlB,CACAqL,CAAO,CAAC/M,IAAR,CAAa0B,CAAb,CACD,CACF,CAKD,MAAOqL,CAAAA,CAAO,CAACjE,IAAR,CAAa,SAAUlJ,CAAV,CAAaC,CAAb,CAAgB,CAClC,MAAOA,CAAAA,CAAC,CAACsN,KAAF,CAAUvN,CAAC,CAACuN,KACpB,CAFM,CAGR,CA1RD,CAoSA7Q,CAAI,CAAC4N,KAAL,CAAWhL,SAAX,CAAqByE,MAArB,CAA8B,UAAY,IACpCyG,CAAAA,CAAa,CAAGxM,MAAM,CAACE,IAAP,CAAY,KAAKsM,aAAjB,EACjBtB,IADiB,GAEjB9H,GAFiB,CAEb,SAAU4G,CAAV,CAAgB,CACnB,MAAO,CAACA,CAAD,CAAO,KAAKwC,aAAL,CAAmBxC,CAAnB,CAAP,CACR,CAJiB,CAIf,IAJe,CADoB,CAOpCyC,CAAY,CAAGzM,MAAM,CAACE,IAAP,CAAY,KAAKuM,YAAjB,EAChBrJ,GADgB,CACZ,SAAUuM,CAAV,CAAe,CAClB,MAAO,CAACA,CAAD,CAAM,KAAKlD,YAAL,CAAkBkD,CAAlB,EAAuB5J,MAAvB,EAAN,CACR,CAHgB,CAGd,IAHc,CAPqB,CAYxC,MAAO,CACLzG,OAAO,CAAEZ,CAAI,CAACY,OADT,CAELqN,MAAM,CAAE,KAAKA,MAFR,CAGLF,YAAY,CAAEA,CAHT,CAILD,aAAa,CAAEA,CAJV,CAKL1N,QAAQ,CAAE,KAAKA,QAAL,CAAciH,MAAd,EALL,CAOR,CAnBD,CA2BArH,CAAI,CAAC4N,KAAL,CAAW9H,IAAX,CAAkB,SAAUoL,CAAV,CAA2B,CAC3C,GAAIrD,CAAAA,CAAK,CAAG,EAAZ,CACIE,CAAY,CAAG,EADnB,CAEIoD,CAAiB,CAAGD,CAAe,CAACnD,YAFxC,CAGID,CAAa,CAAGxM,MAAM,CAACC,MAAP,CAAc,IAAd,CAHpB,CAII6P,CAAuB,CAAGF,CAAe,CAACpD,aAJ9C,CAKIuD,CAAe,CAAG,GAAIrR,CAAAA,CAAI,CAAC0K,QAAL,CAAcvK,OALxC,CAMIC,CAAQ,CAAGJ,CAAI,CAACuF,QAAL,CAAcO,IAAd,CAAmBoL,CAAe,CAAC9Q,QAAnC,CANf,CAQA,GAAI8Q,CAAe,CAACtQ,OAAhB,EAA2BZ,CAAI,CAACY,OAApC,CAA6C,CAC3CZ,CAAI,CAACa,KAAL,CAAWC,IAAX,CAAgB,4EAA8Ed,CAAI,CAACY,OAAnF,CAA6F,qCAA7F,CAAqIsQ,CAAe,CAACtQ,OAArJ,CAA+J,GAA/K,CACD,CAED,IAAK,GAAIa,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAG0P,CAAiB,CAACzP,MAAtC,CAA8CD,CAAC,EAA/C,CAAmD,CACjD,GAAI6P,CAAAA,CAAK,CAAGH,CAAiB,CAAC1P,CAAD,CAA7B,CACIwP,CAAG,CAAGK,CAAK,CAAC,CAAD,CADf,CAEIxO,CAAQ,CAAGwO,CAAK,CAAC,CAAD,CAFpB,CAIAvD,CAAY,CAACkD,CAAD,CAAZ,CAAoB,GAAIjR,CAAAA,CAAI,CAACsH,MAAT,CAAgBxE,CAAhB,CACrB,CAED,IAAK,GAAIrB,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAG2P,CAAuB,CAAC1P,MAA5C,CAAoDD,CAAC,EAArD,CAAyD,CACvD,GAAI6P,CAAAA,CAAK,CAAGF,CAAuB,CAAC3P,CAAD,CAAnC,CACI6J,CAAI,CAAGgG,CAAK,CAAC,CAAD,CADhB,CAEIzN,CAAO,CAAGyN,CAAK,CAAC,CAAD,CAFnB,CAIAD,CAAe,CAACtJ,MAAhB,CAAuBuD,CAAvB,EACAwC,CAAa,CAACxC,CAAD,CAAb,CAAsBzH,CACvB,CAEDwN,CAAe,CAACpG,MAAhB,GAEA4C,CAAK,CAACI,MAAN,CAAeiD,CAAe,CAACjD,MAA/B,CAEAJ,CAAK,CAACE,YAAN,CAAqBA,CAArB,CACAF,CAAK,CAACC,aAAN,CAAsBA,CAAtB,CACAD,CAAK,CAACG,QAAN,CAAiBqD,CAAe,CAACnG,IAAjC,CACA2C,CAAK,CAACzN,QAAN,CAAiBA,CAAjB,CAEA,MAAO,IAAIJ,CAAAA,CAAI,CAAC4N,KAAT,CAAeC,CAAf,CACR,CAxCD,CAsEA7N,CAAI,CAACG,OAAL,CAAe,UAAY,CACzB,KAAKoR,IAAL,CAAY,IAAZ,CACA,KAAKC,OAAL,CAAelQ,MAAM,CAACC,MAAP,CAAc,IAAd,CAAf,CACA,KAAKkQ,UAAL,CAAkBnQ,MAAM,CAACC,MAAP,CAAc,IAAd,CAAlB,CACA,KAAKuM,aAAL,CAAqBxM,MAAM,CAACC,MAAP,CAAc,IAAd,CAArB,CACA,KAAKmQ,oBAAL,CAA4B,EAA5B,CACA,KAAKC,YAAL,CAAoB,EAApB,CACA,KAAKlN,SAAL,CAAiBzE,CAAI,CAACyE,SAAtB,CACA,KAAKrE,QAAL,CAAgB,GAAIJ,CAAAA,CAAI,CAACuF,QAAzB,CACA,KAAK9E,cAAL,CAAsB,GAAIT,CAAAA,CAAI,CAACuF,QAA/B,CACA,KAAKzB,aAAL,CAAqB,CAArB,CACA,KAAK8N,EAAL,CAAU,GAAV,CACA,KAAKC,GAAL,CAAW,GAAX,CACA,KAAKpC,SAAL,CAAiB,CAAjB,CACA,KAAKqC,iBAAL,CAAyB,EAC1B,CAfD,CA6BA9R,CAAI,CAACG,OAAL,CAAayC,SAAb,CAAuBqO,GAAvB,CAA6B,SAAUA,CAAV,CAAe,CAC1C,KAAKM,IAAL,CAAYN,CACb,CAFD,CAoCAjR,CAAI,CAACG,OAAL,CAAayC,SAAb,CAAuB2M,KAAvB,CAA+B,SAAUpN,CAAV,CAAqB4P,CAArB,CAAiC,CAC9D,GAAI,KAAK9H,IAAL,CAAU9H,CAAV,CAAJ,CAA0B,CACxB,KAAM,IAAI6P,CAAAA,UAAJ,CAAgB,UAAY7P,CAAZ,CAAwB,kCAAxC,CACP,CAED,KAAKqP,OAAL,CAAarP,CAAb,EAA0B4P,CAAU,EAAI,EACzC,CAND,CAgBA/R,CAAI,CAACG,OAAL,CAAayC,SAAb,CAAuBW,CAAvB,CAA2B,SAAU0O,CAAV,CAAkB,CAC3C,GAAa,CAAT,CAAAA,CAAJ,CAAgB,CACd,KAAKL,EAAL,CAAU,CACX,CAFD,IAEO,IAAa,CAAT,CAAAK,CAAJ,CAAgB,CACrB,KAAKL,EAAL,CAAU,CACX,CAFM,IAEA,CACL,KAAKA,EAAL,CAAUK,CACX,CACF,CARD,CAiBAjS,CAAI,CAACG,OAAL,CAAayC,SAAb,CAAuBsP,EAAvB,CAA4B,SAAUD,CAAV,CAAkB,CAC5C,KAAKJ,GAAL,CAAWI,CACZ,CAFD,CAqBAjS,CAAI,CAACG,OAAL,CAAayC,SAAb,CAAuBvC,GAAvB,CAA6B,SAAU8R,CAAV,CAAeJ,CAAf,CAA2B,CACtD,GAAI7P,CAAAA,CAAM,CAAGiQ,CAAG,CAAC,KAAKZ,IAAN,CAAhB,CACItD,CAAM,CAAG3M,MAAM,CAACE,IAAP,CAAY,KAAKgQ,OAAjB,CADb,CAGA,KAAKC,UAAL,CAAgBvP,CAAhB,EAA0B6P,CAAU,EAAI,EAAxC,CACA,KAAKjO,aAAL,EAAsB,CAAtB,CAEA,IAAK,GAAIrC,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGwM,CAAM,CAACvM,MAA3B,CAAmCD,CAAC,EAApC,CAAwC,CACtC,GAAIU,CAAAA,CAAS,CAAG8L,CAAM,CAACxM,CAAD,CAAtB,CACI2Q,CAAS,CAAG,KAAKZ,OAAL,CAAarP,CAAb,EAAwBiQ,SADxC,CAEI7C,CAAK,CAAG6C,CAAS,CAAGA,CAAS,CAACD,CAAD,CAAZ,CAAoBA,CAAG,CAAChQ,CAAD,CAF5C,CAGI2C,CAAM,CAAG,KAAKL,SAAL,CAAe8K,CAAf,CAAsB,CAC7BtB,MAAM,CAAE,CAAC9L,CAAD,CADqB,CAAtB,CAHb,CAMI4M,CAAK,CAAG,KAAK3O,QAAL,CAAcwG,GAAd,CAAkB9B,CAAlB,CANZ,CAOInC,CAAQ,CAAG,GAAI3C,CAAAA,CAAI,CAACiC,QAAT,CAAmBC,CAAnB,CAA2BC,CAA3B,CAPf,CAQIkQ,CAAU,CAAG/Q,MAAM,CAACC,MAAP,CAAc,IAAd,CARjB,CAUA,KAAKmQ,oBAAL,CAA0B/O,CAA1B,EAAsC0P,CAAtC,CACA,KAAKV,YAAL,CAAkBhP,CAAlB,EAA8B,CAA9B,CAGA,KAAKgP,YAAL,CAAkBhP,CAAlB,GAA+BoM,CAAK,CAACrN,MAArC,CAGA,IAAK,GAAIqF,CAAAA,CAAC,CAAG,CAAR,CACCuE,CADN,CAAgBvE,CAAC,CAAGgI,CAAK,CAACrN,MAA1B,CAAkCqF,CAAC,EAAnC,CAAuC,CACjCuE,CADiC,CAC1ByD,CAAK,CAAChI,CAAD,CADqB,CAGrC,GAAIsL,CAAU,CAAC/G,CAAD,CAAV,QAAJ,CAAmC,CACjC+G,CAAU,CAAC/G,CAAD,CAAV,CAAmB,CACpB,CAED+G,CAAU,CAAC/G,CAAD,CAAV,EAAoB,CAApB,CAIA,GAAI,KAAKwC,aAAL,CAAmBxC,CAAnB,SAAJ,CAA2C,CACzC,GAAIzH,CAAAA,CAAO,CAAGvC,MAAM,CAACC,MAAP,CAAc,IAAd,CAAd,CACAsC,CAAO,OAAP,CAAoB,KAAK4L,SAAzB,CACA,KAAKA,SAAL,EAAkB,CAAlB,CAEA,IAAK,GAAIxI,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGgH,CAAM,CAACvM,MAA3B,CAAmCuF,CAAC,EAApC,CAAwC,CACtCpD,CAAO,CAACoK,CAAM,CAAChH,CAAD,CAAP,CAAP,CAAqB3F,MAAM,CAACC,MAAP,CAAc,IAAd,CACtB,CAED,KAAKuM,aAAL,CAAmBxC,CAAnB,EAA2BzH,CAC5B,CAGD,GAAI,KAAKiK,aAAL,CAAmBxC,CAAnB,EAAyBnJ,CAAzB,EAAoCD,CAApC,SAAJ,CAA8D,CAC5D,KAAK4L,aAAL,CAAmBxC,CAAnB,EAAyBnJ,CAAzB,EAAoCD,CAApC,EAA8CZ,MAAM,CAACC,MAAP,CAAc,IAAd,CAC/C,CAID,IAAK,GAAI0O,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAG,KAAK6B,iBAAL,CAAuBpQ,MAA3C,CAAmDuO,CAAC,EAApD,CAAwD,CACtD,GAAIqC,CAAAA,CAAW,CAAG,KAAKR,iBAAL,CAAuB7B,CAAvB,CAAlB,CACI3L,CAAQ,CAAGgH,CAAI,CAAChH,QAAL,CAAcgO,CAAd,CADf,CAGA,GAAI,KAAKxE,aAAL,CAAmBxC,CAAnB,EAAyBnJ,CAAzB,EAAoCD,CAApC,EAA4CoQ,CAA5C,SAAJ,CAA2E,CACzE,KAAKxE,aAAL,CAAmBxC,CAAnB,EAAyBnJ,CAAzB,EAAoCD,CAApC,EAA4CoQ,CAA5C,EAA2D,EAC5D,CAED,KAAKxE,aAAL,CAAmBxC,CAAnB,EAAyBnJ,CAAzB,EAAoCD,CAApC,EAA4CoQ,CAA5C,EAAyD5O,IAAzD,CAA8DY,CAA9D,CACD,CACF,CAEF,CACF,CApED,CA2EAtE,CAAI,CAACG,OAAL,CAAayC,SAAb,CAAuB2P,4BAAvB,CAAsD,UAAY,CAOhE,OALIC,CAAAA,CAAS,CAAGlR,MAAM,CAACE,IAAP,CAAY,KAAKmQ,YAAjB,CAKhB,CAJIc,CAAc,CAAGD,CAAS,CAAC9Q,MAI/B,CAHIgR,CAAW,CAAG,EAGlB,CAFIC,CAAkB,CAAG,EAEzB,CAASlR,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGgR,CAApB,CAAoChR,CAAC,EAArC,CAAyC,CACvC,GAAIkB,CAAAA,CAAQ,CAAG3C,CAAI,CAACiC,QAAL,CAAcM,UAAd,CAAyBiQ,CAAS,CAAC/Q,CAAD,CAAlC,CAAf,CACI8N,CAAK,CAAG5M,CAAQ,CAACR,SADrB,CAGAwQ,CAAkB,CAACpD,CAAD,CAAlB,GAA8BoD,CAAkB,CAACpD,CAAD,CAAlB,CAA4B,CAA1D,EACAoD,CAAkB,CAACpD,CAAD,CAAlB,EAA6B,CAA7B,CAEAmD,CAAW,CAACnD,CAAD,CAAX,GAAuBmD,CAAW,CAACnD,CAAD,CAAX,CAAqB,CAA5C,EACAmD,CAAW,CAACnD,CAAD,CAAX,EAAsB,KAAKoC,YAAL,CAAkBhP,CAAlB,CACvB,CAID,OAFIsL,CAAAA,CAAM,CAAG3M,MAAM,CAACE,IAAP,CAAY,KAAKgQ,OAAjB,CAEb,CAAS/P,CAAC,CAAG,CAAb,CACMU,CADN,CAAgBV,CAAC,CAAGwM,CAAM,CAACvM,MAA3B,CAAmCD,CAAC,EAApC,CAAwC,CAClCU,CADkC,CACtB8L,CAAM,CAACxM,CAAD,CADgB,CAEtCiR,CAAW,CAACvQ,CAAD,CAAX,CAAyBuQ,CAAW,CAACvQ,CAAD,CAAX,CAAyBwQ,CAAkB,CAACxQ,CAAD,CACrE,CAED,KAAKyQ,kBAAL,CAA0BF,CAC3B,CA1BD,CAiCA1S,CAAI,CAACG,OAAL,CAAayC,SAAb,CAAuBiQ,kBAAvB,CAA4C,UAAY,CAMtD,OALI9E,CAAAA,CAAY,CAAG,EAKnB,CAJIyE,CAAS,CAAGlR,MAAM,CAACE,IAAP,CAAY,KAAKkQ,oBAAjB,CAIhB,CAHIoB,CAAe,CAAGN,CAAS,CAAC9Q,MAGhC,CAFIqR,CAAY,CAAGzR,MAAM,CAACC,MAAP,CAAc,IAAd,CAEnB,CAASE,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGqR,CAApB,CAAqCrR,CAAC,EAAtC,CAA0C,CAaxC,OAZIkB,CAAAA,CAAQ,CAAG3C,CAAI,CAACiC,QAAL,CAAcM,UAAd,CAAyBiQ,CAAS,CAAC/Q,CAAD,CAAlC,CAYf,CAXIU,CAAS,CAAGQ,CAAQ,CAACR,SAWzB,CAVI6Q,CAAW,CAAG,KAAKrB,YAAL,CAAkBhP,CAAlB,CAUlB,CATIiO,CAAW,CAAG,GAAI5Q,CAAAA,CAAI,CAACsH,MAS3B,CARI2L,CAAe,CAAG,KAAKvB,oBAAL,CAA0B/O,CAA1B,CAQtB,CAPIoM,CAAK,CAAGzN,MAAM,CAACE,IAAP,CAAYyR,CAAZ,CAOZ,CANIC,CAAW,CAAGnE,CAAK,CAACrN,MAMxB,CAHIyR,CAAU,CAAG,KAAK3B,OAAL,CAAarP,CAAb,EAAwB6N,KAAxB,EAAiC,CAGlD,CAFIoD,CAAQ,CAAG,KAAK3B,UAAL,CAAgB9O,CAAQ,CAACT,MAAzB,EAAiC8N,KAAjC,EAA0C,CAEzD,CAASjJ,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGmM,CAApB,CAAiCnM,CAAC,EAAlC,CAAsC,CACpC,GAAIuE,CAAAA,CAAI,CAAGyD,CAAK,CAAChI,CAAD,CAAhB,CACIsM,CAAE,CAAGJ,CAAe,CAAC3H,CAAD,CADxB,CAEImE,CAAS,CAAG,KAAK3B,aAAL,CAAmBxC,CAAnB,EAAyBoE,MAFzC,CAGI9L,CAHJ,CAGSiN,CAHT,CAGgByC,CAHhB,CAKA,GAAIP,CAAY,CAACzH,CAAD,CAAZ,SAAJ,CAAsC,CACpC1H,CAAG,CAAG5D,CAAI,CAAC4D,GAAL,CAAS,KAAKkK,aAAL,CAAmBxC,CAAnB,CAAT,CAAmC,KAAKxH,aAAxC,CAAN,CACAiP,CAAY,CAACzH,CAAD,CAAZ,CAAqB1H,CACtB,CAHD,IAGO,CACLA,CAAG,CAAGmP,CAAY,CAACzH,CAAD,CACnB,CAEDuF,CAAK,CAAGjN,CAAG,EAAI,CAAC,KAAKiO,GAAL,CAAW,CAAZ,EAAiBwB,CAArB,CAAH,EAA+B,KAAKxB,GAAL,EAAY,EAAI,KAAKD,EAAT,CAAc,KAAKA,EAAL,EAAWoB,CAAW,CAAG,KAAKJ,kBAAL,CAAwBzQ,CAAxB,CAAzB,CAA1B,EAA0FkR,CAAzH,CAAR,CACAxC,CAAK,EAAIsC,CAAT,CACAtC,CAAK,EAAIuC,CAAT,CACAE,CAAkB,CAAGrP,IAAI,CAACsP,KAAL,CAAmB,GAAR,CAAA1C,CAAX,EAA2B,GAAhD,CAQAD,CAAW,CAAC7I,MAAZ,CAAmB0H,CAAnB,CAA8B6D,CAA9B,CACD,CAEDvF,CAAY,CAACpL,CAAD,CAAZ,CAAyBiO,CAC1B,CAED,KAAK7C,YAAL,CAAoBA,CACrB,CAlDD,CAyDA/N,CAAI,CAACG,OAAL,CAAayC,SAAb,CAAuB4Q,cAAvB,CAAwC,UAAY,CAClD,KAAKxF,QAAL,CAAgBhO,CAAI,CAAC0K,QAAL,CAAcK,SAAd,CACdzJ,MAAM,CAACE,IAAP,CAAY,KAAKsM,aAAjB,EAAgCtB,IAAhC,EADc,CAGjB,CAJD,CAcAxM,CAAI,CAACG,OAAL,CAAayC,SAAb,CAAuBjC,KAAvB,CAA+B,UAAY,CACzC,KAAK4R,4BAAL,GACA,KAAKM,kBAAL,GACA,KAAKW,cAAL,GAEA,MAAO,IAAIxT,CAAAA,CAAI,CAAC4N,KAAT,CAAe,CACpBE,aAAa,CAAE,KAAKA,aADA,CAEpBC,YAAY,CAAE,KAAKA,YAFC,CAGpBC,QAAQ,CAAE,KAAKA,QAHK,CAIpBC,MAAM,CAAE3M,MAAM,CAACE,IAAP,CAAY,KAAKgQ,OAAjB,CAJY,CAKpBpR,QAAQ,CAAE,KAAKK,cALK,CAAf,CAOR,CAZD,CA4BAT,CAAI,CAACG,OAAL,CAAayC,SAAb,CAAuB6Q,GAAvB,CAA6B,SAAUjP,CAAV,CAAc,CACzC,GAAIkP,CAAAA,CAAI,CAAG7R,KAAK,CAACe,SAAN,CAAgBb,KAAhB,CAAsBrB,IAAtB,CAA2B0F,SAA3B,CAAsC,CAAtC,CAAX,CACAsN,CAAI,CAACC,OAAL,CAAa,IAAb,EACAnP,CAAE,CAACoP,KAAH,CAAS,IAAT,CAAeF,CAAf,CACD,CAJD,CAiBA1T,CAAI,CAACqQ,SAAL,CAAiB,SAAU/E,CAAV,CAAgBiE,CAAhB,CAAuBjL,CAAvB,CAAiC,CAShD,OARIuP,CAAAA,CAAc,CAAGvS,MAAM,CAACC,MAAP,CAAc,IAAd,CAQrB,CAPIuS,CAAY,CAAGxS,MAAM,CAACE,IAAP,CAAY8C,CAAQ,EAAI,EAAxB,CAOnB,CAAS7C,CAAC,CAAG,CAAb,CACME,CADN,CAAgBF,CAAC,CAAGqS,CAAY,CAACpS,MAAjC,CAAyCD,CAAC,EAA1C,CAA8C,CACxCE,CADwC,CAClCmS,CAAY,CAACrS,CAAD,CADsB,CAE5CoS,CAAc,CAAClS,CAAD,CAAd,CAAsB2C,CAAQ,CAAC3C,CAAD,CAAR,CAAcI,KAAd,EACvB,CAED,KAAKuC,QAAL,CAAgBhD,MAAM,CAACC,MAAP,CAAc,IAAd,CAAhB,CAEA,GAAI+J,CAAI,SAAR,CAAwB,CACtB,KAAKhH,QAAL,CAAcgH,CAAd,EAAsBhK,MAAM,CAACC,MAAP,CAAc,IAAd,CAAtB,CACA,KAAK+C,QAAL,CAAcgH,CAAd,EAAoBiE,CAApB,EAA6BsE,CAC9B,CACF,CApBD,CA+BA7T,CAAI,CAACqQ,SAAL,CAAezN,SAAf,CAAyBoO,OAAzB,CAAmC,SAAU+C,CAAV,CAA0B,CAG3D,OAFIhF,CAAAA,CAAK,CAAGzN,MAAM,CAACE,IAAP,CAAYuS,CAAc,CAACzP,QAA3B,CAEZ,CAAS7C,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGsN,CAAK,CAACrN,MAA1B,CAAkCD,CAAC,EAAnC,CAAuC,CACrC,GAAI6J,CAAAA,CAAI,CAAGyD,CAAK,CAACtN,CAAD,CAAhB,CACIwM,CAAM,CAAG3M,MAAM,CAACE,IAAP,CAAYuS,CAAc,CAACzP,QAAf,CAAwBgH,CAAxB,CAAZ,CADb,CAGA,GAAI,KAAKhH,QAAL,CAAcgH,CAAd,SAAJ,CAAsC,CACpC,KAAKhH,QAAL,CAAcgH,CAAd,EAAsBhK,MAAM,CAACC,MAAP,CAAc,IAAd,CACvB,CAED,IAAK,GAAIwF,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAGkH,CAAM,CAACvM,MAA3B,CAAmCqF,CAAC,EAApC,CAAwC,CACtC,GAAIwI,CAAAA,CAAK,CAAGtB,CAAM,CAAClH,CAAD,CAAlB,CACIvF,CAAI,CAAGF,MAAM,CAACE,IAAP,CAAYuS,CAAc,CAACzP,QAAf,CAAwBgH,CAAxB,EAA8BiE,CAA9B,CAAZ,CADX,CAGA,GAAI,KAAKjL,QAAL,CAAcgH,CAAd,EAAoBiE,CAApB,SAAJ,CAA6C,CAC3C,KAAKjL,QAAL,CAAcgH,CAAd,EAAoBiE,CAApB,EAA6BjO,MAAM,CAACC,MAAP,CAAc,IAAd,CAC9B,CAED,IAAK,GAAI0F,CAAAA,CAAC,CAAG,CAAR,CACCtF,CADN,CAAgBsF,CAAC,CAAGzF,CAAI,CAACE,MAAzB,CAAiCuF,CAAC,EAAlC,CAAsC,CAChCtF,CADgC,CAC1BH,CAAI,CAACyF,CAAD,CADsB,CAGpC,GAAI,KAAK3C,QAAL,CAAcgH,CAAd,EAAoBiE,CAApB,EAA2B5N,CAA3B,SAAJ,CAAkD,CAChD,KAAK2C,QAAL,CAAcgH,CAAd,EAAoBiE,CAApB,EAA2B5N,CAA3B,EAAkCoS,CAAc,CAACzP,QAAf,CAAwBgH,CAAxB,EAA8BiE,CAA9B,EAAqC5N,CAArC,CACnC,CAFD,IAEO,CACL,KAAK2C,QAAL,CAAcgH,CAAd,EAAoBiE,CAApB,EAA2B5N,CAA3B,EAAkC,KAAK2C,QAAL,CAAcgH,CAAd,EAAoBiE,CAApB,EAA2B5N,CAA3B,EAAgCgC,MAAhC,CAAuCoQ,CAAc,CAACzP,QAAf,CAAwBgH,CAAxB,EAA8BiE,CAA9B,EAAqC5N,CAArC,CAAvC,CACnC,CAEF,CACF,CACF,CACF,CA/BD,CAwCA3B,CAAI,CAACqQ,SAAL,CAAezN,SAAf,CAAyBvC,GAAzB,CAA+B,SAAUiL,CAAV,CAAgBiE,CAAhB,CAAuBjL,CAAvB,CAAiC,CAC9D,GAAI,EAAEgH,CAAI,GAAI,MAAKhH,QAAf,CAAJ,CAA8B,CAC5B,KAAKA,QAAL,CAAcgH,CAAd,EAAsBhK,MAAM,CAACC,MAAP,CAAc,IAAd,CAAtB,CACA,KAAK+C,QAAL,CAAcgH,CAAd,EAAoBiE,CAApB,EAA6BjL,CAA7B,CACA,MACD,CAED,GAAI,EAAEiL,CAAK,GAAI,MAAKjL,QAAL,CAAcgH,CAAd,CAAX,CAAJ,CAAqC,CACnC,KAAKhH,QAAL,CAAcgH,CAAd,EAAoBiE,CAApB,EAA6BjL,CAA7B,CACA,MACD,CAID,OAFIwP,CAAAA,CAAY,CAAGxS,MAAM,CAACE,IAAP,CAAY8C,CAAZ,CAEnB,CAAS7C,CAAC,CAAG,CAAb,CACME,CADN,CAAgBF,CAAC,CAAGqS,CAAY,CAACpS,MAAjC,CAAyCD,CAAC,EAA1C,CAA8C,CACxCE,CADwC,CAClCmS,CAAY,CAACrS,CAAD,CADsB,CAG5C,GAAIE,CAAG,GAAI,MAAK2C,QAAL,CAAcgH,CAAd,EAAoBiE,CAApB,CAAX,CAAuC,CACrC,KAAKjL,QAAL,CAAcgH,CAAd,EAAoBiE,CAApB,EAA2B5N,CAA3B,EAAkC,KAAK2C,QAAL,CAAcgH,CAAd,EAAoBiE,CAApB,EAA2B5N,CAA3B,EAAgCgC,MAAhC,CAAuCW,CAAQ,CAAC3C,CAAD,CAA/C,CACnC,CAFD,IAEO,CACL,KAAK2C,QAAL,CAAcgH,CAAd,EAAoBiE,CAApB,EAA2B5N,CAA3B,EAAkC2C,CAAQ,CAAC3C,CAAD,CAC3C,CACF,CACF,CAvBD,CAmCA3B,CAAI,CAACwO,KAAL,CAAa,SAAUwF,CAAV,CAAqB,CAChC,KAAKlF,OAAL,CAAe,EAAf,CACA,KAAKkF,SAAL,CAAiBA,CAClB,CAHD,CA6BAhU,CAAI,CAACwO,KAAL,CAAWyF,QAAX,CAAsB,GAAIC,CAAAA,MAAJ,CAAY,GAAZ,CAAtB,CACAlU,CAAI,CAACwO,KAAL,CAAWyF,QAAX,CAAoBE,IAApB,CAA2B,CAA3B,CACAnU,CAAI,CAACwO,KAAL,CAAWyF,QAAX,CAAoBG,OAApB,CAA8B,CAA9B,CACApU,CAAI,CAACwO,KAAL,CAAWyF,QAAX,CAAoBI,QAApB,CAA+B,CAA/B,CAaArU,CAAI,CAACwO,KAAL,CAAWa,QAAX,CAAsB,CAIpBiF,QAAQ,CAAE,CAJU,CAUpBhF,QAAQ,CAAE,CAVU,CAgBpBS,UAAU,CAAE,CAhBQ,CAAtB,CA0CA/P,CAAI,CAACwO,KAAL,CAAW5L,SAAX,CAAqBwI,MAArB,CAA8B,SAAUA,CAAV,CAAkB,CAC9C,GAAI,EAAE,UAAYA,CAAAA,CAAd,CAAJ,CAA2B,CACzBA,CAAM,CAAC6C,MAAP,CAAgB,KAAK+F,SACtB,CAED,GAAI,EAAE,SAAW5I,CAAAA,CAAb,CAAJ,CAA0B,CACxBA,CAAM,CAAC4E,KAAP,CAAe,CAChB,CAED,GAAI,EAAE,eAAiB5E,CAAAA,CAAnB,CAAJ,CAAgC,CAC9BA,CAAM,CAAC6D,WAAP,GACD,CAED,GAAI,EAAE,YAAc7D,CAAAA,CAAhB,CAAJ,CAA6B,CAC3BA,CAAM,CAAC6I,QAAP,CAAkBjU,CAAI,CAACwO,KAAL,CAAWyF,QAAX,CAAoBE,IACvC,CAED,GAAK/I,CAAM,CAAC6I,QAAP,CAAkBjU,CAAI,CAACwO,KAAL,CAAWyF,QAAX,CAAoBG,OAAvC,EAAoDhJ,CAAM,CAACE,IAAP,CAAYpG,MAAZ,CAAmB,CAAnB,GAAyBlF,CAAI,CAACwO,KAAL,CAAWyF,QAA5F,CAAuG,CACrG7I,CAAM,CAACE,IAAP,CAAc,IAAMF,CAAM,CAACE,IAC5B,CAED,GAAKF,CAAM,CAAC6I,QAAP,CAAkBjU,CAAI,CAACwO,KAAL,CAAWyF,QAAX,CAAoBI,QAAvC,EAAqDjJ,CAAM,CAACE,IAAP,CAAYvJ,KAAZ,CAAkB,CAAC,CAAnB,GAAyB/B,CAAI,CAACwO,KAAL,CAAWyF,QAA7F,CAAwG,CACtG7I,CAAM,CAACE,IAAP,CAAc,GAAKF,CAAM,CAACE,IAAZ,CAAmB,GAClC,CAED,GAAI,EAAE,YAAcF,CAAAA,CAAhB,CAAJ,CAA6B,CAC3BA,CAAM,CAACiE,QAAP,CAAkBrP,CAAI,CAACwO,KAAL,CAAWa,QAAX,CAAoBiF,QACvC,CAED,KAAKxF,OAAL,CAAapL,IAAb,CAAkB0H,CAAlB,EAEA,MAAO,KACR,CAhCD,CAyCApL,CAAI,CAACwO,KAAL,CAAW5L,SAAX,CAAqB+N,SAArB,CAAiC,UAAY,CAC3C,IAAK,GAAIlP,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAG,KAAKqN,OAAL,CAAapN,MAAjC,CAAyCD,CAAC,EAA1C,CAA8C,CAC5C,GAAI,KAAKqN,OAAL,CAAarN,CAAb,EAAgB4N,QAAhB,EAA4BrP,CAAI,CAACwO,KAAL,CAAWa,QAAX,CAAoBU,UAApD,CAAgE,CAC9D,QACD,CACF,CAED,QACD,CARD,CAoCA/P,CAAI,CAACwO,KAAL,CAAW5L,SAAX,CAAqB0I,IAArB,CAA4B,SAAUA,CAAV,CAAgBiJ,CAAhB,CAAyB,CACnD,GAAI1S,KAAK,CAACC,OAAN,CAAcwJ,CAAd,CAAJ,CAAyB,CACvBA,CAAI,CAACtF,OAAL,CAAa,SAAUrB,CAAV,CAAa,CAAE,KAAK2G,IAAL,CAAU3G,CAAV,CAAa3E,CAAI,CAACa,KAAL,CAAWQ,KAAX,CAAiBkT,CAAjB,CAAb,CAAyC,CAArE,CAAuE,IAAvE,EACA,MAAO,KACR,CAED,GAAInJ,CAAAA,CAAM,CAAGmJ,CAAO,EAAI,EAAxB,CACAnJ,CAAM,CAACE,IAAP,CAAcA,CAAI,CAAClK,QAAL,EAAd,CAEA,KAAKgK,MAAL,CAAYA,CAAZ,EAEA,MAAO,KACR,CAZD,CAaApL,CAAI,CAACwU,eAAL,CAAuB,SAAUxT,CAAV,CAAmB0G,CAAnB,CAA0BC,CAA1B,CAA+B,CACpD,KAAK8M,IAAL,CAAY,iBAAZ,CACA,KAAKzT,OAAL,CAAeA,CAAf,CACA,KAAK0G,KAAL,CAAaA,CAAb,CACA,KAAKC,GAAL,CAAWA,CACZ,CALD,CAOA3H,CAAI,CAACwU,eAAL,CAAqB5R,SAArB,CAAiC,GAAIsD,CAAAA,KAArC,CACAlG,CAAI,CAAC0U,UAAL,CAAkB,SAAUrQ,CAAV,CAAe,CAC/B,KAAKsQ,OAAL,CAAe,EAAf,CACA,KAAKtQ,GAAL,CAAWA,CAAX,CACA,KAAK3C,MAAL,CAAc2C,CAAG,CAAC3C,MAAlB,CACA,KAAK8E,GAAL,CAAW,CAAX,CACA,KAAKkB,KAAL,CAAa,CAAb,CACA,KAAKkN,mBAAL,CAA2B,EAC5B,CAPD,CASA5U,CAAI,CAAC0U,UAAL,CAAgB9R,SAAhB,CAA0BgE,GAA1B,CAAgC,UAAY,CAC1C,GAAIiO,CAAAA,CAAK,CAAG7U,CAAI,CAAC0U,UAAL,CAAgBI,OAA5B,CAEA,MAAOD,CAAP,CAAc,CACZA,CAAK,CAAGA,CAAK,CAAC,IAAD,CACd,CACF,CAND,CAQA7U,CAAI,CAAC0U,UAAL,CAAgB9R,SAAhB,CAA0BmS,WAA1B,CAAwC,UAAY,CAKlD,OAJIC,CAAAA,CAAS,CAAG,EAIhB,CAHIhQ,CAAU,CAAG,KAAK0C,KAGtB,CAFI3C,CAAQ,CAAG,KAAKyB,GAEpB,CAAS/E,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAG,KAAKmT,mBAAL,CAAyBlT,MAA7C,CAAqDD,CAAC,EAAtD,CAA0D,CACxDsD,CAAQ,CAAG,KAAK6P,mBAAL,CAAyBnT,CAAzB,CAAX,CACAuT,CAAS,CAACtR,IAAV,CAAe,KAAKW,GAAL,CAAStC,KAAT,CAAeiD,CAAf,CAA2BD,CAA3B,CAAf,EACAC,CAAU,CAAGD,CAAQ,CAAG,CACzB,CAEDiQ,CAAS,CAACtR,IAAV,CAAe,KAAKW,GAAL,CAAStC,KAAT,CAAeiD,CAAf,CAA2B,KAAKwB,GAAhC,CAAf,EACA,KAAKoO,mBAAL,CAAyBlT,MAAzB,CAAkC,CAAlC,CAEA,MAAOsT,CAAAA,CAAS,CAACC,IAAV,CAAe,EAAf,CACR,CAfD,CAiBAjV,CAAI,CAAC0U,UAAL,CAAgB9R,SAAhB,CAA0BsS,IAA1B,CAAiC,SAAUC,CAAV,CAAgB,CAC/C,KAAKR,OAAL,CAAajR,IAAb,CAAkB,CAChByR,IAAI,CAAEA,CADU,CAEhB9Q,GAAG,CAAE,KAAK0Q,WAAL,EAFW,CAGhBrN,KAAK,CAAE,KAAKA,KAHI,CAIhBC,GAAG,CAAE,KAAKnB,GAJM,CAAlB,EAOA,KAAKkB,KAAL,CAAa,KAAKlB,GACnB,CATD,CAWAxG,CAAI,CAAC0U,UAAL,CAAgB9R,SAAhB,CAA0BwS,eAA1B,CAA4C,UAAY,CACtD,KAAKR,mBAAL,CAAyBlR,IAAzB,CAA8B,KAAK8C,GAAL,CAAW,CAAzC,EACA,KAAKA,GAAL,EAAY,CACb,CAHD,CAKAxG,CAAI,CAAC0U,UAAL,CAAgB9R,SAAhB,CAA0BuJ,IAA1B,CAAiC,UAAY,CAC3C,GAAI,KAAK3F,GAAL,EAAY,KAAK9E,MAArB,CAA6B,CAC3B,MAAO1B,CAAAA,CAAI,CAAC0U,UAAL,CAAgBW,GACxB,CAED,GAAIpQ,CAAAA,CAAI,CAAG,KAAKZ,GAAL,CAASa,MAAT,CAAgB,KAAKsB,GAArB,CAAX,CACA,KAAKA,GAAL,EAAY,CAAZ,CACA,MAAOvB,CAAAA,CACR,CARD,CAUAjF,CAAI,CAAC0U,UAAL,CAAgB9R,SAAhB,CAA0B0S,KAA1B,CAAkC,UAAY,CAC5C,MAAO,MAAK9O,GAAL,CAAW,KAAKkB,KACxB,CAFD,CAIA1H,CAAI,CAAC0U,UAAL,CAAgB9R,SAAhB,CAA0B2S,MAA1B,CAAmC,UAAY,CAC7C,GAAI,KAAK7N,KAAL,EAAc,KAAKlB,GAAvB,CAA4B,CAC1B,KAAKA,GAAL,EAAY,CACb,CAED,KAAKkB,KAAL,CAAa,KAAKlB,GACnB,CAND,CAQAxG,CAAI,CAAC0U,UAAL,CAAgB9R,SAAhB,CAA0B4S,MAA1B,CAAmC,UAAY,CAC7C,KAAKhP,GAAL,EAAY,CACb,CAFD,CAIAxG,CAAI,CAAC0U,UAAL,CAAgB9R,SAAhB,CAA0B6S,cAA1B,CAA2C,UAAY,CACrD,GAAIxQ,CAAAA,CAAJ,CAAUyQ,CAAV,CAEA,EAAG,CACDzQ,CAAI,CAAG,KAAKkH,IAAL,EAAP,CACAuJ,CAAQ,CAAGzQ,CAAI,CAAC0Q,UAAL,CAAgB,CAAhB,CACZ,CAHD,MAGoB,EAAX,CAAAD,CAAQ,EAAoB,EAAX,CAAAA,CAH1B,EAKA,GAAIzQ,CAAI,EAAIjF,CAAI,CAAC0U,UAAL,CAAgBW,GAA5B,CAAiC,CAC/B,KAAKG,MAAL,EACD,CACF,CAXD,CAaAxV,CAAI,CAAC0U,UAAL,CAAgB9R,SAAhB,CAA0BgT,IAA1B,CAAiC,UAAY,CAC3C,MAAO,MAAKpP,GAAL,CAAW,KAAK9E,MACxB,CAFD,CAIA1B,CAAI,CAAC0U,UAAL,CAAgBW,GAAhB,CAAsB,KAAtB,CACArV,CAAI,CAAC0U,UAAL,CAAgBmB,KAAhB,CAAwB,OAAxB,CACA7V,CAAI,CAAC0U,UAAL,CAAgBoB,IAAhB,CAAuB,MAAvB,CACA9V,CAAI,CAAC0U,UAAL,CAAgBqB,aAAhB,CAAgC,eAAhC,CACA/V,CAAI,CAAC0U,UAAL,CAAgBsB,KAAhB,CAAwB,OAAxB,CACAhW,CAAI,CAAC0U,UAAL,CAAgBuB,QAAhB,CAA2B,UAA3B,CAEAjW,CAAI,CAAC0U,UAAL,CAAgBwB,QAAhB,CAA2B,SAAUC,CAAV,CAAiB,CAC1CA,CAAK,CAACX,MAAN,GACAW,CAAK,CAACjB,IAAN,CAAWlV,CAAI,CAAC0U,UAAL,CAAgBmB,KAA3B,EACAM,CAAK,CAACZ,MAAN,GACA,MAAOvV,CAAAA,CAAI,CAAC0U,UAAL,CAAgBI,OACxB,CALD,CAOA9U,CAAI,CAAC0U,UAAL,CAAgB0B,OAAhB,CAA0B,SAAUD,CAAV,CAAiB,CACzC,GAAoB,CAAhB,CAAAA,CAAK,CAACb,KAAN,EAAJ,CAAuB,CACrBa,CAAK,CAACX,MAAN,GACAW,CAAK,CAACjB,IAAN,CAAWlV,CAAI,CAAC0U,UAAL,CAAgBoB,IAA3B,CACD,CAEDK,CAAK,CAACZ,MAAN,GAEA,GAAIY,CAAK,CAACP,IAAN,EAAJ,CAAkB,CAChB,MAAO5V,CAAAA,CAAI,CAAC0U,UAAL,CAAgBI,OACxB,CACF,CAXD,CAaA9U,CAAI,CAAC0U,UAAL,CAAgB2B,eAAhB,CAAkC,SAAUF,CAAV,CAAiB,CACjDA,CAAK,CAACZ,MAAN,GACAY,CAAK,CAACV,cAAN,GACAU,CAAK,CAACjB,IAAN,CAAWlV,CAAI,CAAC0U,UAAL,CAAgBqB,aAA3B,EACA,MAAO/V,CAAAA,CAAI,CAAC0U,UAAL,CAAgBI,OACxB,CALD,CAOA9U,CAAI,CAAC0U,UAAL,CAAgB4B,QAAhB,CAA2B,SAAUH,CAAV,CAAiB,CAC1CA,CAAK,CAACZ,MAAN,GACAY,CAAK,CAACV,cAAN,GACAU,CAAK,CAACjB,IAAN,CAAWlV,CAAI,CAAC0U,UAAL,CAAgBsB,KAA3B,EACA,MAAOhW,CAAAA,CAAI,CAAC0U,UAAL,CAAgBI,OACxB,CALD,CAOA9U,CAAI,CAAC0U,UAAL,CAAgB6B,MAAhB,CAAyB,SAAUJ,CAAV,CAAiB,CACxC,GAAoB,CAAhB,CAAAA,CAAK,CAACb,KAAN,EAAJ,CAAuB,CACrBa,CAAK,CAACjB,IAAN,CAAWlV,CAAI,CAAC0U,UAAL,CAAgBoB,IAA3B,CACD,CACF,CAJD,CAiBA9V,CAAI,CAAC0U,UAAL,CAAgB8B,aAAhB,CAAgCxW,CAAI,CAACyE,SAAL,CAAeY,SAA/C,CAEArF,CAAI,CAAC0U,UAAL,CAAgBI,OAAhB,CAA0B,SAAUqB,CAAV,CAAiB,CACzC,SAAa,CACX,GAAIlR,CAAAA,CAAI,CAAGkR,CAAK,CAAChK,IAAN,EAAX,CAEA,GAAIlH,CAAI,EAAIjF,CAAI,CAAC0U,UAAL,CAAgBW,GAA5B,CAAiC,CAC/B,MAAOrV,CAAAA,CAAI,CAAC0U,UAAL,CAAgB6B,MACxB,CAGD,GAA0B,EAAtB,EAAAtR,CAAI,CAAC0Q,UAAL,CAAgB,CAAhB,CAAJ,CAA8B,CAC5BQ,CAAK,CAACf,eAAN,GACA,QACD,CAED,GAAY,GAAR,EAAAnQ,CAAJ,CAAiB,CACf,MAAOjF,CAAAA,CAAI,CAAC0U,UAAL,CAAgBwB,QACxB,CAED,GAAY,GAAR,EAAAjR,CAAJ,CAAiB,CACfkR,CAAK,CAACX,MAAN,GACA,GAAoB,CAAhB,CAAAW,CAAK,CAACb,KAAN,EAAJ,CAAuB,CACrBa,CAAK,CAACjB,IAAN,CAAWlV,CAAI,CAAC0U,UAAL,CAAgBoB,IAA3B,CACD,CACD,MAAO9V,CAAAA,CAAI,CAAC0U,UAAL,CAAgB2B,eACxB,CAED,GAAY,GAAR,EAAApR,CAAJ,CAAiB,CACfkR,CAAK,CAACX,MAAN,GACA,GAAoB,CAAhB,CAAAW,CAAK,CAACb,KAAN,EAAJ,CAAuB,CACrBa,CAAK,CAACjB,IAAN,CAAWlV,CAAI,CAAC0U,UAAL,CAAgBoB,IAA3B,CACD,CACD,MAAO9V,CAAAA,CAAI,CAAC0U,UAAL,CAAgB4B,QACxB,CAKD,GAAY,GAAR,EAAArR,CAAI,EAA6B,CAAlB,GAAAkR,CAAK,CAACb,KAAN,EAAnB,CAAwC,CACtCa,CAAK,CAACjB,IAAN,CAAWlV,CAAI,CAAC0U,UAAL,CAAgBuB,QAA3B,EACA,MAAOjW,CAAAA,CAAI,CAAC0U,UAAL,CAAgBI,OACxB,CAKD,GAAY,GAAR,EAAA7P,CAAI,EAA6B,CAAlB,GAAAkR,CAAK,CAACb,KAAN,EAAnB,CAAwC,CACtCa,CAAK,CAACjB,IAAN,CAAWlV,CAAI,CAAC0U,UAAL,CAAgBuB,QAA3B,EACA,MAAOjW,CAAAA,CAAI,CAAC0U,UAAL,CAAgBI,OACxB,CAED,GAAI7P,CAAI,CAACG,KAAL,CAAWpF,CAAI,CAAC0U,UAAL,CAAgB8B,aAA3B,CAAJ,CAA+C,CAC7C,MAAOxW,CAAAA,CAAI,CAAC0U,UAAL,CAAgB0B,OACxB,CACF,CACF,CAtDD,CAwDApW,CAAI,CAACsO,WAAL,CAAmB,SAAUjK,CAAV,CAAe+J,CAAf,CAAsB,CACvC,KAAK+H,KAAL,CAAa,GAAInW,CAAAA,CAAI,CAAC0U,UAAT,CAAqBrQ,CAArB,CAAb,CACA,KAAK+J,KAAL,CAAaA,CAAb,CACA,KAAKqI,aAAL,CAAqB,EAArB,CACA,KAAKC,SAAL,CAAiB,CAClB,CALD,CAOA1W,CAAI,CAACsO,WAAL,CAAiB1L,SAAjB,CAA2B2L,KAA3B,CAAmC,UAAY,CAC7C,KAAK4H,KAAL,CAAWvP,GAAX,GACA,KAAK+N,OAAL,CAAe,KAAKwB,KAAL,CAAWxB,OAA1B,CAEA,GAAIE,CAAAA,CAAK,CAAG7U,CAAI,CAACsO,WAAL,CAAiBqI,WAA7B,CAEA,MAAO9B,CAAP,CAAc,CACZA,CAAK,CAAGA,CAAK,CAAC,IAAD,CACd,CAED,MAAO,MAAKzG,KACb,CAXD,CAaApO,CAAI,CAACsO,WAAL,CAAiB1L,SAAjB,CAA2BgU,UAA3B,CAAwC,UAAY,CAClD,MAAO,MAAKjC,OAAL,CAAa,KAAK+B,SAAlB,CACR,CAFD,CAIA1W,CAAI,CAACsO,WAAL,CAAiB1L,SAAjB,CAA2BiU,aAA3B,CAA2C,UAAY,CACrD,GAAIC,CAAAA,CAAM,CAAG,KAAKF,UAAL,EAAb,CACA,KAAKF,SAAL,EAAkB,CAAlB,CACA,MAAOI,CAAAA,CACR,CAJD,CAMA9W,CAAI,CAACsO,WAAL,CAAiB1L,SAAjB,CAA2BmU,UAA3B,CAAwC,UAAY,CAClD,GAAIC,CAAAA,CAAe,CAAG,KAAKP,aAA3B,CACA,KAAKrI,KAAL,CAAWhD,MAAX,CAAkB4L,CAAlB,EACA,KAAKP,aAAL,CAAqB,EACtB,CAJD,CAMAzW,CAAI,CAACsO,WAAL,CAAiBqI,WAAjB,CAA+B,SAAUtI,CAAV,CAAkB,CAC/C,GAAIyI,CAAAA,CAAM,CAAGzI,CAAM,CAACuI,UAAP,EAAb,CAEA,GAAIE,CAAM,QAAV,CAAyB,CACvB,MACD,CAED,OAAQA,CAAM,CAAC3B,IAAf,EACE,IAAKnV,CAAAA,CAAI,CAAC0U,UAAL,CAAgBuB,QAArB,CACE,MAAOjW,CAAAA,CAAI,CAACsO,WAAL,CAAiB2I,aAAxB,CACF,IAAKjX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBmB,KAArB,CACE,MAAO7V,CAAAA,CAAI,CAACsO,WAAL,CAAiB4I,UAAxB,CACF,IAAKlX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBoB,IAArB,CACE,MAAO9V,CAAAA,CAAI,CAACsO,WAAL,CAAiB6I,SAAxB,CACF,QACE,GAAIC,CAAAA,CAAY,CAAG,4CAA8CN,CAAM,CAAC3B,IAAxE,CAEA,GAAyB,CAArB,EAAA2B,CAAM,CAACzS,GAAP,CAAW3C,MAAf,CAA4B,CAC1B0V,CAAY,EAAI,gBAAkBN,CAAM,CAACzS,GAAzB,CAA+B,GAChD,CAED,KAAM,IAAIrE,CAAAA,CAAI,CAACwU,eAAT,CAA0B4C,CAA1B,CAAwCN,CAAM,CAACpP,KAA/C,CAAsDoP,CAAM,CAACnP,GAA7D,CAAN,CAdJ,CAgBD,CAvBD,CAyBA3H,CAAI,CAACsO,WAAL,CAAiB2I,aAAjB,CAAiC,SAAU5I,CAAV,CAAkB,CACjD,GAAIyI,CAAAA,CAAM,CAAGzI,CAAM,CAACwI,aAAP,EAAb,CAEA,GAAIC,CAAM,QAAV,CAAyB,CACvB,MACD,CAED,OAAQA,CAAM,CAACzS,GAAf,EACE,IAAK,GAAL,CACEgK,CAAM,CAACoI,aAAP,CAAqBpH,QAArB,CAAgCrP,CAAI,CAACwO,KAAL,CAAWa,QAAX,CAAoBU,UAApD,CACA,MACF,IAAK,GAAL,CACE1B,CAAM,CAACoI,aAAP,CAAqBpH,QAArB,CAAgCrP,CAAI,CAACwO,KAAL,CAAWa,QAAX,CAAoBC,QAApD,CACA,MACF,QACE,GAAI8H,CAAAA,CAAY,CAAG,kCAAoCN,CAAM,CAACzS,GAA3C,CAAiD,GAApE,CACA,KAAM,IAAIrE,CAAAA,CAAI,CAACwU,eAAT,CAA0B4C,CAA1B,CAAwCN,CAAM,CAACpP,KAA/C,CAAsDoP,CAAM,CAACnP,GAA7D,CAAN,CATJ,CAYA,GAAI0P,CAAAA,CAAU,CAAGhJ,CAAM,CAACuI,UAAP,EAAjB,CAEA,GAAIS,CAAU,QAAd,CAA6B,CAC3B,GAAID,CAAAA,CAAY,CAAG,wCAAnB,CACA,KAAM,IAAIpX,CAAAA,CAAI,CAACwU,eAAT,CAA0B4C,CAA1B,CAAwCN,CAAM,CAACpP,KAA/C,CAAsDoP,CAAM,CAACnP,GAA7D,CACP,CAED,OAAQ0P,CAAU,CAAClC,IAAnB,EACE,IAAKnV,CAAAA,CAAI,CAAC0U,UAAL,CAAgBmB,KAArB,CACE,MAAO7V,CAAAA,CAAI,CAACsO,WAAL,CAAiB4I,UAAxB,CACF,IAAKlX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBoB,IAArB,CACE,MAAO9V,CAAAA,CAAI,CAACsO,WAAL,CAAiB6I,SAAxB,CACF,QACE,GAAIC,CAAAA,CAAY,CAAG,mCAAqCC,CAAU,CAAClC,IAAhD,CAAuD,GAA1E,CACA,KAAM,IAAInV,CAAAA,CAAI,CAACwU,eAAT,CAA0B4C,CAA1B,CAAwCC,CAAU,CAAC3P,KAAnD,CAA0D2P,CAAU,CAAC1P,GAArE,CAAN,CAPJ,CASD,CAnCD,CAqCA3H,CAAI,CAACsO,WAAL,CAAiB4I,UAAjB,CAA8B,SAAU7I,CAAV,CAAkB,CAC9C,GAAIyI,CAAAA,CAAM,CAAGzI,CAAM,CAACwI,aAAP,EAAb,CAEA,GAAIC,CAAM,QAAV,CAAyB,CACvB,MACD,CAED,GAAkD,CAAC,CAA/C,EAAAzI,CAAM,CAACD,KAAP,CAAa4F,SAAb,CAAuBtR,OAAvB,CAA+BoU,CAAM,CAACzS,GAAtC,CAAJ,CAAsD,CACpD,GAAIiT,CAAAA,CAAc,CAAGjJ,CAAM,CAACD,KAAP,CAAa4F,SAAb,CAAuBtP,GAAvB,CAA2B,SAAU6S,CAAV,CAAa,CAAE,MAAO,IAAMA,CAAN,CAAU,GAAK,CAAhE,EAAkEtC,IAAlE,CAAuE,IAAvE,CAArB,CACImC,CAAY,CAAG,uBAAyBN,CAAM,CAACzS,GAAhC,CAAsC,sBAAtC,CAA+DiT,CADlF,CAGA,KAAM,IAAItX,CAAAA,CAAI,CAACwU,eAAT,CAA0B4C,CAA1B,CAAwCN,CAAM,CAACpP,KAA/C,CAAsDoP,CAAM,CAACnP,GAA7D,CACP,CAED0G,CAAM,CAACoI,aAAP,CAAqBxI,MAArB,CAA8B,CAAC6I,CAAM,CAACzS,GAAR,CAA9B,CAEA,GAAIgT,CAAAA,CAAU,CAAGhJ,CAAM,CAACuI,UAAP,EAAjB,CAEA,GAAIS,CAAU,QAAd,CAA6B,CAC3B,GAAID,CAAAA,CAAY,CAAG,+BAAnB,CACA,KAAM,IAAIpX,CAAAA,CAAI,CAACwU,eAAT,CAA0B4C,CAA1B,CAAwCN,CAAM,CAACpP,KAA/C,CAAsDoP,CAAM,CAACnP,GAA7D,CACP,CAED,OAAQ0P,CAAU,CAAClC,IAAnB,EACE,IAAKnV,CAAAA,CAAI,CAAC0U,UAAL,CAAgBoB,IAArB,CACE,MAAO9V,CAAAA,CAAI,CAACsO,WAAL,CAAiB6I,SAAxB,CACF,QACE,GAAIC,CAAAA,CAAY,CAAG,0BAA4BC,CAAU,CAAClC,IAAvC,CAA8C,GAAjE,CACA,KAAM,IAAInV,CAAAA,CAAI,CAACwU,eAAT,CAA0B4C,CAA1B,CAAwCC,CAAU,CAAC3P,KAAnD,CAA0D2P,CAAU,CAAC1P,GAArE,CAAN,CALJ,CAOD,CA9BD,CAgCA3H,CAAI,CAACsO,WAAL,CAAiB6I,SAAjB,CAA6B,SAAU9I,CAAV,CAAkB,CAC7C,GAAIyI,CAAAA,CAAM,CAAGzI,CAAM,CAACwI,aAAP,EAAb,CAEA,GAAIC,CAAM,QAAV,CAAyB,CACvB,MACD,CAEDzI,CAAM,CAACoI,aAAP,CAAqBnL,IAArB,CAA4BwL,CAAM,CAACzS,GAAP,CAAWO,WAAX,EAA5B,CAEA,GAA+B,CAAC,CAA5B,EAAAkS,CAAM,CAACzS,GAAP,CAAW3B,OAAX,CAAmB,GAAnB,CAAJ,CAAmC,CACjC2L,CAAM,CAACoI,aAAP,CAAqBxH,WAArB,GACD,CAED,GAAIoI,CAAAA,CAAU,CAAGhJ,CAAM,CAACuI,UAAP,EAAjB,CAEA,GAAIS,CAAU,QAAd,CAA6B,CAC3BhJ,CAAM,CAAC0I,UAAP,GACA,MACD,CAED,OAAQM,CAAU,CAAClC,IAAnB,EACE,IAAKnV,CAAAA,CAAI,CAAC0U,UAAL,CAAgBoB,IAArB,CACEzH,CAAM,CAAC0I,UAAP,GACA,MAAO/W,CAAAA,CAAI,CAACsO,WAAL,CAAiB6I,SAAxB,CACF,IAAKnX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBmB,KAArB,CACExH,CAAM,CAAC0I,UAAP,GACA,MAAO/W,CAAAA,CAAI,CAACsO,WAAL,CAAiB4I,UAAxB,CACF,IAAKlX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBqB,aAArB,CACE,MAAO/V,CAAAA,CAAI,CAACsO,WAAL,CAAiBkJ,iBAAxB,CACF,IAAKxX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBsB,KAArB,CACE,MAAOhW,CAAAA,CAAI,CAACsO,WAAL,CAAiBmJ,UAAxB,CACF,IAAKzX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBuB,QAArB,CACE5H,CAAM,CAAC0I,UAAP,GACA,MAAO/W,CAAAA,CAAI,CAACsO,WAAL,CAAiB2I,aAAxB,CACF,QACE,GAAIG,CAAAA,CAAY,CAAG,2BAA6BC,CAAU,CAAClC,IAAxC,CAA+C,GAAlE,CACA,KAAM,IAAInV,CAAAA,CAAI,CAACwU,eAAT,CAA0B4C,CAA1B,CAAwCC,CAAU,CAAC3P,KAAnD,CAA0D2P,CAAU,CAAC1P,GAArE,CAAN,CAhBJ,CAkBD,CAtCD,CAwCA3H,CAAI,CAACsO,WAAL,CAAiBkJ,iBAAjB,CAAqC,SAAUnJ,CAAV,CAAkB,CACrD,GAAIyI,CAAAA,CAAM,CAAGzI,CAAM,CAACwI,aAAP,EAAb,CAEA,GAAIC,CAAM,QAAV,CAAyB,CACvB,MACD,CAED,GAAIvL,CAAAA,CAAY,CAAGmM,QAAQ,CAACZ,CAAM,CAACzS,GAAR,CAAa,EAAb,CAA3B,CAEA,GAAIsT,KAAK,CAACpM,CAAD,CAAT,CAAyB,CACvB,GAAI6L,CAAAA,CAAY,CAAG,+BAAnB,CACA,KAAM,IAAIpX,CAAAA,CAAI,CAACwU,eAAT,CAA0B4C,CAA1B,CAAwCN,CAAM,CAACpP,KAA/C,CAAsDoP,CAAM,CAACnP,GAA7D,CACP,CAED0G,CAAM,CAACoI,aAAP,CAAqBlL,YAArB,CAAoCA,CAApC,CAEA,GAAI8L,CAAAA,CAAU,CAAGhJ,CAAM,CAACuI,UAAP,EAAjB,CAEA,GAAIS,CAAU,QAAd,CAA6B,CAC3BhJ,CAAM,CAAC0I,UAAP,GACA,MACD,CAED,OAAQM,CAAU,CAAClC,IAAnB,EACE,IAAKnV,CAAAA,CAAI,CAAC0U,UAAL,CAAgBoB,IAArB,CACEzH,CAAM,CAAC0I,UAAP,GACA,MAAO/W,CAAAA,CAAI,CAACsO,WAAL,CAAiB6I,SAAxB,CACF,IAAKnX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBmB,KAArB,CACExH,CAAM,CAAC0I,UAAP,GACA,MAAO/W,CAAAA,CAAI,CAACsO,WAAL,CAAiB4I,UAAxB,CACF,IAAKlX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBqB,aAArB,CACE,MAAO/V,CAAAA,CAAI,CAACsO,WAAL,CAAiBkJ,iBAAxB,CACF,IAAKxX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBsB,KAArB,CACE,MAAOhW,CAAAA,CAAI,CAACsO,WAAL,CAAiBmJ,UAAxB,CACF,IAAKzX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBuB,QAArB,CACE5H,CAAM,CAAC0I,UAAP,GACA,MAAO/W,CAAAA,CAAI,CAACsO,WAAL,CAAiB2I,aAAxB,CACF,QACE,GAAIG,CAAAA,CAAY,CAAG,2BAA6BC,CAAU,CAAClC,IAAxC,CAA+C,GAAlE,CACA,KAAM,IAAInV,CAAAA,CAAI,CAACwU,eAAT,CAA0B4C,CAA1B,CAAwCC,CAAU,CAAC3P,KAAnD,CAA0D2P,CAAU,CAAC1P,GAArE,CAAN,CAhBJ,CAkBD,CAzCD,CA2CA3H,CAAI,CAACsO,WAAL,CAAiBmJ,UAAjB,CAA8B,SAAUpJ,CAAV,CAAkB,CAC9C,GAAIyI,CAAAA,CAAM,CAAGzI,CAAM,CAACwI,aAAP,EAAb,CAEA,GAAIC,CAAM,QAAV,CAAyB,CACvB,MACD,CAED,GAAI9G,CAAAA,CAAK,CAAG0H,QAAQ,CAACZ,CAAM,CAACzS,GAAR,CAAa,EAAb,CAApB,CAEA,GAAIsT,KAAK,CAAC3H,CAAD,CAAT,CAAkB,CAChB,GAAIoH,CAAAA,CAAY,CAAG,uBAAnB,CACA,KAAM,IAAIpX,CAAAA,CAAI,CAACwU,eAAT,CAA0B4C,CAA1B,CAAwCN,CAAM,CAACpP,KAA/C,CAAsDoP,CAAM,CAACnP,GAA7D,CACP,CAED0G,CAAM,CAACoI,aAAP,CAAqBzG,KAArB,CAA6BA,CAA7B,CAEA,GAAIqH,CAAAA,CAAU,CAAGhJ,CAAM,CAACuI,UAAP,EAAjB,CAEA,GAAIS,CAAU,QAAd,CAA6B,CAC3BhJ,CAAM,CAAC0I,UAAP,GACA,MACD,CAED,OAAQM,CAAU,CAAClC,IAAnB,EACE,IAAKnV,CAAAA,CAAI,CAAC0U,UAAL,CAAgBoB,IAArB,CACEzH,CAAM,CAAC0I,UAAP,GACA,MAAO/W,CAAAA,CAAI,CAACsO,WAAL,CAAiB6I,SAAxB,CACF,IAAKnX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBmB,KAArB,CACExH,CAAM,CAAC0I,UAAP,GACA,MAAO/W,CAAAA,CAAI,CAACsO,WAAL,CAAiB4I,UAAxB,CACF,IAAKlX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBqB,aAArB,CACE,MAAO/V,CAAAA,CAAI,CAACsO,WAAL,CAAiBkJ,iBAAxB,CACF,IAAKxX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBsB,KAArB,CACE,MAAOhW,CAAAA,CAAI,CAACsO,WAAL,CAAiBmJ,UAAxB,CACF,IAAKzX,CAAAA,CAAI,CAAC0U,UAAL,CAAgBuB,QAArB,CACE5H,CAAM,CAAC0I,UAAP,GACA,MAAO/W,CAAAA,CAAI,CAACsO,WAAL,CAAiB2I,aAAxB,CACF,QACE,GAAIG,CAAAA,CAAY,CAAG,2BAA6BC,CAAU,CAAClC,IAAxC,CAA+C,GAAlE,CACA,KAAM,IAAInV,CAAAA,CAAI,CAACwU,eAAT,CAA0B4C,CAA1B,CAAwCC,CAAU,CAAC3P,KAAnD,CAA0D2P,CAAU,CAAC1P,GAArE,CAAN,CAhBJ,CAkBD,CAzCD,CA+CI,UAAUuD,CAAV,CAAgB0M,CAAhB,CAAyB,CACzB,GAAsB,UAAlB,QAAOC,CAAAA,MAAP,EAAgCA,MAAM,CAACC,GAA3C,CAAgD,CAE9CD,OAAM,8BAACD,CAAD,CACP,CAHD,IAGO,IAAuB,QAAnB,uBAAOG,CAAAA,OAAP,qBAAOA,OAAP,EAAJ,CAAiC,CAMtCC,MAAM,CAACD,OAAP,CAAiBH,CAAO,EACzB,CAPM,IAOA,CAEL1M,CAAI,CAAClL,IAAL,CAAY4X,CAAO,EACpB,CACF,CAfC,EAeA,IAfA,CAeM,UAAY,CAMlB,MAAO5X,CAAAA,CACR,CAtBC,CAuBH,CA54GA","sourcesContent":["/**\n * moodle readme\n *\n * Lunrjs can be downloaded from https://github.com/olivernn/lunr.js. To update this library get the lunr.js file\n * from this project and replace the content below with the new content.\n */\n\n/**\n * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9\n * Copyright (C) 2020 Oliver Nightingale\n * @license MIT\n */\n\n;(function(){\n\n/**\n * A convenience function for configuring and constructing\n * a new lunr Index.\n *\n * A lunr.Builder instance is created and the pipeline setup\n * with a trimmer, stop word filter and stemmer.\n *\n * This builder object is yielded to the configuration function\n * that is passed as a parameter, allowing the list of fields\n * and other builder parameters to be customised.\n *\n * All documents _must_ be added within the passed config function.\n *\n * @example\n * var idx = lunr(function () {\n * this.field('title')\n * this.field('body')\n * this.ref('id')\n *\n * documents.forEach(function (doc) {\n * this.add(doc)\n * }, this)\n * })\n *\n * @see {@link lunr.Builder}\n * @see {@link lunr.Pipeline}\n * @see {@link lunr.trimmer}\n * @see {@link lunr.stopWordFilter}\n * @see {@link lunr.stemmer}\n * @namespace {function} lunr\n */\nvar lunr = function (config) {\n var builder = new lunr.Builder\n\n builder.pipeline.add(\n lunr.trimmer,\n lunr.stopWordFilter,\n lunr.stemmer\n )\n\n builder.searchPipeline.add(\n lunr.stemmer\n )\n\n config.call(builder, builder)\n return builder.build()\n}\n\nlunr.version = \"2.3.9\"\n/*!\n * lunr.utils\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A namespace containing utils for the rest of the lunr library\n * @namespace lunr.utils\n */\nlunr.utils = {}\n\n/**\n * Print a warning message to the console.\n *\n * @param {String} message The message to be printed.\n * @memberOf lunr.utils\n * @function\n */\nlunr.utils.warn = (function (global) {\n /* eslint-disable no-console */\n return function (message) {\n if (global.console && console.warn) {\n console.warn(message)\n }\n }\n /* eslint-enable no-console */\n})(this)\n\n/**\n * Convert an object to a string.\n *\n * In the case of `null` and `undefined` the function returns\n * the empty string, in all other cases the result of calling\n * `toString` on the passed object is returned.\n *\n * @param {Any} obj The object to convert to a string.\n * @return {String} string representation of the passed object.\n * @memberOf lunr.utils\n */\nlunr.utils.asString = function (obj) {\n if (obj === void 0 || obj === null) {\n return \"\"\n } else {\n return obj.toString()\n }\n}\n\n/**\n * Clones an object.\n *\n * Will create a copy of an existing object such that any mutations\n * on the copy cannot affect the original.\n *\n * Only shallow objects are supported, passing a nested object to this\n * function will cause a TypeError.\n *\n * Objects with primitives, and arrays of primitives are supported.\n *\n * @param {Object} obj The object to clone.\n * @return {Object} a clone of the passed object.\n * @throws {TypeError} when a nested object is passed.\n * @memberOf Utils\n */\nlunr.utils.clone = function (obj) {\n if (obj === null || obj === undefined) {\n return obj\n }\n\n var clone = Object.create(null),\n keys = Object.keys(obj)\n\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i],\n val = obj[key]\n\n if (Array.isArray(val)) {\n clone[key] = val.slice()\n continue\n }\n\n if (typeof val === 'string' ||\n typeof val === 'number' ||\n typeof val === 'boolean') {\n clone[key] = val\n continue\n }\n\n throw new TypeError(\"clone is not deep and does not support nested objects\")\n }\n\n return clone\n}\nlunr.FieldRef = function (docRef, fieldName, stringValue) {\n this.docRef = docRef\n this.fieldName = fieldName\n this._stringValue = stringValue\n}\n\nlunr.FieldRef.joiner = \"/\"\n\nlunr.FieldRef.fromString = function (s) {\n var n = s.indexOf(lunr.FieldRef.joiner)\n\n if (n === -1) {\n throw \"malformed field ref string\"\n }\n\n var fieldRef = s.slice(0, n),\n docRef = s.slice(n + 1)\n\n return new lunr.FieldRef (docRef, fieldRef, s)\n}\n\nlunr.FieldRef.prototype.toString = function () {\n if (this._stringValue == undefined) {\n this._stringValue = this.fieldName + lunr.FieldRef.joiner + this.docRef\n }\n\n return this._stringValue\n}\n/*!\n * lunr.Set\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A lunr set.\n *\n * @constructor\n */\nlunr.Set = function (elements) {\n this.elements = Object.create(null)\n\n if (elements) {\n this.length = elements.length\n\n for (var i = 0; i < this.length; i++) {\n this.elements[elements[i]] = true\n }\n } else {\n this.length = 0\n }\n}\n\n/**\n * A complete set that contains all elements.\n *\n * @static\n * @readonly\n * @type {lunr.Set}\n */\nlunr.Set.complete = {\n intersect: function (other) {\n return other\n },\n\n union: function () {\n return this\n },\n\n contains: function () {\n return true\n }\n}\n\n/**\n * An empty set that contains no elements.\n *\n * @static\n * @readonly\n * @type {lunr.Set}\n */\nlunr.Set.empty = {\n intersect: function () {\n return this\n },\n\n union: function (other) {\n return other\n },\n\n contains: function () {\n return false\n }\n}\n\n/**\n * Returns true if this set contains the specified object.\n *\n * @param {object} object - Object whose presence in this set is to be tested.\n * @returns {boolean} - True if this set contains the specified object.\n */\nlunr.Set.prototype.contains = function (object) {\n return !!this.elements[object]\n}\n\n/**\n * Returns a new set containing only the elements that are present in both\n * this set and the specified set.\n *\n * @param {lunr.Set} other - set to intersect with this set.\n * @returns {lunr.Set} a new set that is the intersection of this and the specified set.\n */\n\nlunr.Set.prototype.intersect = function (other) {\n var a, b, elements, intersection = []\n\n if (other === lunr.Set.complete) {\n return this\n }\n\n if (other === lunr.Set.empty) {\n return other\n }\n\n if (this.length < other.length) {\n a = this\n b = other\n } else {\n a = other\n b = this\n }\n\n elements = Object.keys(a.elements)\n\n for (var i = 0; i < elements.length; i++) {\n var element = elements[i]\n if (element in b.elements) {\n intersection.push(element)\n }\n }\n\n return new lunr.Set (intersection)\n}\n\n/**\n * Returns a new set combining the elements of this and the specified set.\n *\n * @param {lunr.Set} other - set to union with this set.\n * @return {lunr.Set} a new set that is the union of this and the specified set.\n */\n\nlunr.Set.prototype.union = function (other) {\n if (other === lunr.Set.complete) {\n return lunr.Set.complete\n }\n\n if (other === lunr.Set.empty) {\n return this\n }\n\n return new lunr.Set(Object.keys(this.elements).concat(Object.keys(other.elements)))\n}\n/**\n * A function to calculate the inverse document frequency for\n * a posting. This is shared between the builder and the index\n *\n * @private\n * @param {object} posting - The posting for a given term\n * @param {number} documentCount - The total number of documents.\n */\nlunr.idf = function (posting, documentCount) {\n var documentsWithTerm = 0\n\n for (var fieldName in posting) {\n if (fieldName == '_index') continue // Ignore the term index, its not a field\n documentsWithTerm += Object.keys(posting[fieldName]).length\n }\n\n var x = (documentCount - documentsWithTerm + 0.5) / (documentsWithTerm + 0.5)\n\n return Math.log(1 + Math.abs(x))\n}\n\n/**\n * A token wraps a string representation of a token\n * as it is passed through the text processing pipeline.\n *\n * @constructor\n * @param {string} [str=''] - The string token being wrapped.\n * @param {object} [metadata={}] - Metadata associated with this token.\n */\nlunr.Token = function (str, metadata) {\n this.str = str || \"\"\n this.metadata = metadata || {}\n}\n\n/**\n * Returns the token string that is being wrapped by this object.\n *\n * @returns {string}\n */\nlunr.Token.prototype.toString = function () {\n return this.str\n}\n\n/**\n * A token update function is used when updating or optionally\n * when cloning a token.\n *\n * @callback lunr.Token~updateFunction\n * @param {string} str - The string representation of the token.\n * @param {Object} metadata - All metadata associated with this token.\n */\n\n/**\n * Applies the given function to the wrapped string token.\n *\n * @example\n * token.update(function (str, metadata) {\n * return str.toUpperCase()\n * })\n *\n * @param {lunr.Token~updateFunction} fn - A function to apply to the token string.\n * @returns {lunr.Token}\n */\nlunr.Token.prototype.update = function (fn) {\n this.str = fn(this.str, this.metadata)\n return this\n}\n\n/**\n * Creates a clone of this token. Optionally a function can be\n * applied to the cloned token.\n *\n * @param {lunr.Token~updateFunction} [fn] - An optional function to apply to the cloned token.\n * @returns {lunr.Token}\n */\nlunr.Token.prototype.clone = function (fn) {\n fn = fn || function (s) { return s }\n return new lunr.Token (fn(this.str, this.metadata), this.metadata)\n}\n/*!\n * lunr.tokenizer\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A function for splitting a string into tokens ready to be inserted into\n * the search index. Uses `lunr.tokenizer.separator` to split strings, change\n * the value of this property to change how strings are split into tokens.\n *\n * This tokenizer will convert its parameter to a string by calling `toString` and\n * then will split this string on the character in `lunr.tokenizer.separator`.\n * Arrays will have their elements converted to strings and wrapped in a lunr.Token.\n *\n * Optional metadata can be passed to the tokenizer, this metadata will be cloned and\n * added as metadata to every token that is created from the object to be tokenized.\n *\n * @static\n * @param {?(string|object|object[])} obj - The object to convert into tokens\n * @param {?object} metadata - Optional metadata to associate with every token\n * @returns {lunr.Token[]}\n * @see {@link lunr.Pipeline}\n */\nlunr.tokenizer = function (obj, metadata) {\n if (obj == null || obj == undefined) {\n return []\n }\n\n if (Array.isArray(obj)) {\n return obj.map(function (t) {\n return new lunr.Token(\n lunr.utils.asString(t).toLowerCase(),\n lunr.utils.clone(metadata)\n )\n })\n }\n\n var str = obj.toString().toLowerCase(),\n len = str.length,\n tokens = []\n\n for (var sliceEnd = 0, sliceStart = 0; sliceEnd <= len; sliceEnd++) {\n var char = str.charAt(sliceEnd),\n sliceLength = sliceEnd - sliceStart\n\n if ((char.match(lunr.tokenizer.separator) || sliceEnd == len)) {\n\n if (sliceLength > 0) {\n var tokenMetadata = lunr.utils.clone(metadata) || {}\n tokenMetadata[\"position\"] = [sliceStart, sliceLength]\n tokenMetadata[\"index\"] = tokens.length\n\n tokens.push(\n new lunr.Token (\n str.slice(sliceStart, sliceEnd),\n tokenMetadata\n )\n )\n }\n\n sliceStart = sliceEnd + 1\n }\n\n }\n\n return tokens\n}\n\n/**\n * The separator used to split a string into tokens. Override this property to change the behaviour of\n * `lunr.tokenizer` behaviour when tokenizing strings. By default this splits on whitespace and hyphens.\n *\n * @static\n * @see lunr.tokenizer\n */\nlunr.tokenizer.separator = /[\\s\\-]+/\n/*!\n * lunr.Pipeline\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.Pipelines maintain an ordered list of functions to be applied to all\n * tokens in documents entering the search index and queries being ran against\n * the index.\n *\n * An instance of lunr.Index created with the lunr shortcut will contain a\n * pipeline with a stop word filter and an English language stemmer. Extra\n * functions can be added before or after either of these functions or these\n * default functions can be removed.\n *\n * When run the pipeline will call each function in turn, passing a token, the\n * index of that token in the original list of all tokens and finally a list of\n * all the original tokens.\n *\n * The output of functions in the pipeline will be passed to the next function\n * in the pipeline. To exclude a token from entering the index the function\n * should return undefined, the rest of the pipeline will not be called with\n * this token.\n *\n * For serialisation of pipelines to work, all functions used in an instance of\n * a pipeline should be registered with lunr.Pipeline. Registered functions can\n * then be loaded. If trying to load a serialised pipeline that uses functions\n * that are not registered an error will be thrown.\n *\n * If not planning on serialising the pipeline then registering pipeline functions\n * is not necessary.\n *\n * @constructor\n */\nlunr.Pipeline = function () {\n this._stack = []\n}\n\nlunr.Pipeline.registeredFunctions = Object.create(null)\n\n/**\n * A pipeline function maps lunr.Token to lunr.Token. A lunr.Token contains the token\n * string as well as all known metadata. A pipeline function can mutate the token string\n * or mutate (or add) metadata for a given token.\n *\n * A pipeline function can indicate that the passed token should be discarded by returning\n * null, undefined or an empty string. This token will not be passed to any downstream pipeline\n * functions and will not be added to the index.\n *\n * Multiple tokens can be returned by returning an array of tokens. Each token will be passed\n * to any downstream pipeline functions and all will returned tokens will be added to the index.\n *\n * Any number of pipeline functions may be chained together using a lunr.Pipeline.\n *\n * @interface lunr.PipelineFunction\n * @param {lunr.Token} token - A token from the document being processed.\n * @param {number} i - The index of this token in the complete list of tokens for this document/field.\n * @param {lunr.Token[]} tokens - All tokens for this document/field.\n * @returns {(?lunr.Token|lunr.Token[])}\n */\n\n/**\n * Register a function with the pipeline.\n *\n * Functions that are used in the pipeline should be registered if the pipeline\n * needs to be serialised, or a serialised pipeline needs to be loaded.\n *\n * Registering a function does not add it to a pipeline, functions must still be\n * added to instances of the pipeline for them to be used when running a pipeline.\n *\n * @param {lunr.PipelineFunction} fn - The function to check for.\n * @param {String} label - The label to register this function with\n */\nlunr.Pipeline.registerFunction = function (fn, label) {\n if (label in this.registeredFunctions) {\n lunr.utils.warn('Overwriting existing registered function: ' + label)\n }\n\n fn.label = label\n lunr.Pipeline.registeredFunctions[fn.label] = fn\n}\n\n/**\n * Warns if the function is not registered as a Pipeline function.\n *\n * @param {lunr.PipelineFunction} fn - The function to check for.\n * @private\n */\nlunr.Pipeline.warnIfFunctionNotRegistered = function (fn) {\n var isRegistered = fn.label && (fn.label in this.registeredFunctions)\n\n if (!isRegistered) {\n lunr.utils.warn('Function is not registered with pipeline. This may cause problems when serialising the index.\\n', fn)\n }\n}\n\n/**\n * Loads a previously serialised pipeline.\n *\n * All functions to be loaded must already be registered with lunr.Pipeline.\n * If any function from the serialised data has not been registered then an\n * error will be thrown.\n *\n * @param {Object} serialised - The serialised pipeline to load.\n * @returns {lunr.Pipeline}\n */\nlunr.Pipeline.load = function (serialised) {\n var pipeline = new lunr.Pipeline\n\n serialised.forEach(function (fnName) {\n var fn = lunr.Pipeline.registeredFunctions[fnName]\n\n if (fn) {\n pipeline.add(fn)\n } else {\n throw new Error('Cannot load unregistered function: ' + fnName)\n }\n })\n\n return pipeline\n}\n\n/**\n * Adds new functions to the end of the pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction[]} functions - Any number of functions to add to the pipeline.\n */\nlunr.Pipeline.prototype.add = function () {\n var fns = Array.prototype.slice.call(arguments)\n\n fns.forEach(function (fn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(fn)\n this._stack.push(fn)\n }, this)\n}\n\n/**\n * Adds a single function after a function that already exists in the\n * pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline.\n * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline.\n */\nlunr.Pipeline.prototype.after = function (existingFn, newFn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(newFn)\n\n var pos = this._stack.indexOf(existingFn)\n if (pos == -1) {\n throw new Error('Cannot find existingFn')\n }\n\n pos = pos + 1\n this._stack.splice(pos, 0, newFn)\n}\n\n/**\n * Adds a single function before a function that already exists in the\n * pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline.\n * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline.\n */\nlunr.Pipeline.prototype.before = function (existingFn, newFn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(newFn)\n\n var pos = this._stack.indexOf(existingFn)\n if (pos == -1) {\n throw new Error('Cannot find existingFn')\n }\n\n this._stack.splice(pos, 0, newFn)\n}\n\n/**\n * Removes a function from the pipeline.\n *\n * @param {lunr.PipelineFunction} fn The function to remove from the pipeline.\n */\nlunr.Pipeline.prototype.remove = function (fn) {\n var pos = this._stack.indexOf(fn)\n if (pos == -1) {\n return\n }\n\n this._stack.splice(pos, 1)\n}\n\n/**\n * Runs the current list of functions that make up the pipeline against the\n * passed tokens.\n *\n * @param {Array} tokens The tokens to run through the pipeline.\n * @returns {Array}\n */\nlunr.Pipeline.prototype.run = function (tokens) {\n var stackLength = this._stack.length\n\n for (var i = 0; i < stackLength; i++) {\n var fn = this._stack[i]\n var memo = []\n\n for (var j = 0; j < tokens.length; j++) {\n var result = fn(tokens[j], j, tokens)\n\n if (result === null || result === void 0 || result === '') continue\n\n if (Array.isArray(result)) {\n for (var k = 0; k < result.length; k++) {\n memo.push(result[k])\n }\n } else {\n memo.push(result)\n }\n }\n\n tokens = memo\n }\n\n return tokens\n}\n\n/**\n * Convenience method for passing a string through a pipeline and getting\n * strings out. This method takes care of wrapping the passed string in a\n * token and mapping the resulting tokens back to strings.\n *\n * @param {string} str - The string to pass through the pipeline.\n * @param {?object} metadata - Optional metadata to associate with the token\n * passed to the pipeline.\n * @returns {string[]}\n */\nlunr.Pipeline.prototype.runString = function (str, metadata) {\n var token = new lunr.Token (str, metadata)\n\n return this.run([token]).map(function (t) {\n return t.toString()\n })\n}\n\n/**\n * Resets the pipeline by removing any existing processors.\n *\n */\nlunr.Pipeline.prototype.reset = function () {\n this._stack = []\n}\n\n/**\n * Returns a representation of the pipeline ready for serialisation.\n *\n * Logs a warning if the function has not been registered.\n *\n * @returns {Array}\n */\nlunr.Pipeline.prototype.toJSON = function () {\n return this._stack.map(function (fn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(fn)\n\n return fn.label\n })\n}\n/*!\n * lunr.Vector\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A vector is used to construct the vector space of documents and queries. These\n * vectors support operations to determine the similarity between two documents or\n * a document and a query.\n *\n * Normally no parameters are required for initializing a vector, but in the case of\n * loading a previously dumped vector the raw elements can be provided to the constructor.\n *\n * For performance reasons vectors are implemented with a flat array, where an elements\n * index is immediately followed by its value. E.g. [index, value, index, value]. This\n * allows the underlying array to be as sparse as possible and still offer decent\n * performance when being used for vector calculations.\n *\n * @constructor\n * @param {Number[]} [elements] - The flat list of element index and element value pairs.\n */\nlunr.Vector = function (elements) {\n this._magnitude = 0\n this.elements = elements || []\n}\n\n\n/**\n * Calculates the position within the vector to insert a given index.\n *\n * This is used internally by insert and upsert. If there are duplicate indexes then\n * the position is returned as if the value for that index were to be updated, but it\n * is the callers responsibility to check whether there is a duplicate at that index\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @returns {Number}\n */\nlunr.Vector.prototype.positionForIndex = function (index) {\n // For an empty vector the tuple can be inserted at the beginning\n if (this.elements.length == 0) {\n return 0\n }\n\n var start = 0,\n end = this.elements.length / 2,\n sliceLength = end - start,\n pivotPoint = Math.floor(sliceLength / 2),\n pivotIndex = this.elements[pivotPoint * 2]\n\n while (sliceLength > 1) {\n if (pivotIndex < index) {\n start = pivotPoint\n }\n\n if (pivotIndex > index) {\n end = pivotPoint\n }\n\n if (pivotIndex == index) {\n break\n }\n\n sliceLength = end - start\n pivotPoint = start + Math.floor(sliceLength / 2)\n pivotIndex = this.elements[pivotPoint * 2]\n }\n\n if (pivotIndex == index) {\n return pivotPoint * 2\n }\n\n if (pivotIndex > index) {\n return pivotPoint * 2\n }\n\n if (pivotIndex < index) {\n return (pivotPoint + 1) * 2\n }\n}\n\n/**\n * Inserts an element at an index within the vector.\n *\n * Does not allow duplicates, will throw an error if there is already an entry\n * for this index.\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @param {Number} val - The value to be inserted into the vector.\n */\nlunr.Vector.prototype.insert = function (insertIdx, val) {\n this.upsert(insertIdx, val, function () {\n throw \"duplicate index\"\n })\n}\n\n/**\n * Inserts or updates an existing index within the vector.\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @param {Number} val - The value to be inserted into the vector.\n * @param {function} fn - A function that is called for updates, the existing value and the\n * requested value are passed as arguments\n */\nlunr.Vector.prototype.upsert = function (insertIdx, val, fn) {\n this._magnitude = 0\n var position = this.positionForIndex(insertIdx)\n\n if (this.elements[position] == insertIdx) {\n this.elements[position + 1] = fn(this.elements[position + 1], val)\n } else {\n this.elements.splice(position, 0, insertIdx, val)\n }\n}\n\n/**\n * Calculates the magnitude of this vector.\n *\n * @returns {Number}\n */\nlunr.Vector.prototype.magnitude = function () {\n if (this._magnitude) return this._magnitude\n\n var sumOfSquares = 0,\n elementsLength = this.elements.length\n\n for (var i = 1; i < elementsLength; i += 2) {\n var val = this.elements[i]\n sumOfSquares += val * val\n }\n\n return this._magnitude = Math.sqrt(sumOfSquares)\n}\n\n/**\n * Calculates the dot product of this vector and another vector.\n *\n * @param {lunr.Vector} otherVector - The vector to compute the dot product with.\n * @returns {Number}\n */\nlunr.Vector.prototype.dot = function (otherVector) {\n var dotProduct = 0,\n a = this.elements, b = otherVector.elements,\n aLen = a.length, bLen = b.length,\n aVal = 0, bVal = 0,\n i = 0, j = 0\n\n while (i < aLen && j < bLen) {\n aVal = a[i], bVal = b[j]\n if (aVal < bVal) {\n i += 2\n } else if (aVal > bVal) {\n j += 2\n } else if (aVal == bVal) {\n dotProduct += a[i + 1] * b[j + 1]\n i += 2\n j += 2\n }\n }\n\n return dotProduct\n}\n\n/**\n * Calculates the similarity between this vector and another vector.\n *\n * @param {lunr.Vector} otherVector - The other vector to calculate the\n * similarity with.\n * @returns {Number}\n */\nlunr.Vector.prototype.similarity = function (otherVector) {\n return this.dot(otherVector) / this.magnitude() || 0\n}\n\n/**\n * Converts the vector to an array of the elements within the vector.\n *\n * @returns {Number[]}\n */\nlunr.Vector.prototype.toArray = function () {\n var output = new Array (this.elements.length / 2)\n\n for (var i = 1, j = 0; i < this.elements.length; i += 2, j++) {\n output[j] = this.elements[i]\n }\n\n return output\n}\n\n/**\n * A JSON serializable representation of the vector.\n *\n * @returns {Number[]}\n */\nlunr.Vector.prototype.toJSON = function () {\n return this.elements\n}\n/* eslint-disable */\n/*!\n * lunr.stemmer\n * Copyright (C) 2020 Oliver Nightingale\n * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt\n */\n\n/**\n * lunr.stemmer is an english language stemmer, this is a JavaScript\n * implementation of the PorterStemmer taken from http://tartarus.org/~martin\n *\n * @static\n * @implements {lunr.PipelineFunction}\n * @param {lunr.Token} token - The string to stem\n * @returns {lunr.Token}\n * @see {@link lunr.Pipeline}\n * @function\n */\nlunr.stemmer = (function(){\n var step2list = {\n \"ational\" : \"ate\",\n \"tional\" : \"tion\",\n \"enci\" : \"ence\",\n \"anci\" : \"ance\",\n \"izer\" : \"ize\",\n \"bli\" : \"ble\",\n \"alli\" : \"al\",\n \"entli\" : \"ent\",\n \"eli\" : \"e\",\n \"ousli\" : \"ous\",\n \"ization\" : \"ize\",\n \"ation\" : \"ate\",\n \"ator\" : \"ate\",\n \"alism\" : \"al\",\n \"iveness\" : \"ive\",\n \"fulness\" : \"ful\",\n \"ousness\" : \"ous\",\n \"aliti\" : \"al\",\n \"iviti\" : \"ive\",\n \"biliti\" : \"ble\",\n \"logi\" : \"log\"\n },\n\n step3list = {\n \"icate\" : \"ic\",\n \"ative\" : \"\",\n \"alize\" : \"al\",\n \"iciti\" : \"ic\",\n \"ical\" : \"ic\",\n \"ful\" : \"\",\n \"ness\" : \"\"\n },\n\n c = \"[^aeiou]\", // consonant\n v = \"[aeiouy]\", // vowel\n C = c + \"[^aeiouy]*\", // consonant sequence\n V = v + \"[aeiou]*\", // vowel sequence\n\n mgr0 = \"^(\" + C + \")?\" + V + C, // [C]VC... is m>0\n meq1 = \"^(\" + C + \")?\" + V + C + \"(\" + V + \")?$\", // [C]VC[V] is m=1\n mgr1 = \"^(\" + C + \")?\" + V + C + V + C, // [C]VCVC... is m>1\n s_v = \"^(\" + C + \")?\" + v; // vowel in stem\n\n var re_mgr0 = new RegExp(mgr0);\n var re_mgr1 = new RegExp(mgr1);\n var re_meq1 = new RegExp(meq1);\n var re_s_v = new RegExp(s_v);\n\n var re_1a = /^(.+?)(ss|i)es$/;\n var re2_1a = /^(.+?)([^s])s$/;\n var re_1b = /^(.+?)eed$/;\n var re2_1b = /^(.+?)(ed|ing)$/;\n var re_1b_2 = /.$/;\n var re2_1b_2 = /(at|bl|iz)$/;\n var re3_1b_2 = new RegExp(\"([^aeiouylsz])\\\\1$\");\n var re4_1b_2 = new RegExp(\"^\" + C + v + \"[^aeiouwxy]$\");\n\n var re_1c = /^(.+?[^aeiou])y$/;\n var re_2 = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;\n\n var re_3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;\n\n var re_4 = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;\n var re2_4 = /^(.+?)(s|t)(ion)$/;\n\n var re_5 = /^(.+?)e$/;\n var re_5_1 = /ll$/;\n var re3_5 = new RegExp(\"^\" + C + v + \"[^aeiouwxy]$\");\n\n var porterStemmer = function porterStemmer(w) {\n var stem,\n suffix,\n firstch,\n re,\n re2,\n re3,\n re4;\n\n if (w.length < 3) { return w; }\n\n firstch = w.substr(0,1);\n if (firstch == \"y\") {\n w = firstch.toUpperCase() + w.substr(1);\n }\n\n // Step 1a\n re = re_1a\n re2 = re2_1a;\n\n if (re.test(w)) { w = w.replace(re,\"$1$2\"); }\n else if (re2.test(w)) { w = w.replace(re2,\"$1$2\"); }\n\n // Step 1b\n re = re_1b;\n re2 = re2_1b;\n if (re.test(w)) {\n var fp = re.exec(w);\n re = re_mgr0;\n if (re.test(fp[1])) {\n re = re_1b_2;\n w = w.replace(re,\"\");\n }\n } else if (re2.test(w)) {\n var fp = re2.exec(w);\n stem = fp[1];\n re2 = re_s_v;\n if (re2.test(stem)) {\n w = stem;\n re2 = re2_1b_2;\n re3 = re3_1b_2;\n re4 = re4_1b_2;\n if (re2.test(w)) { w = w + \"e\"; }\n else if (re3.test(w)) { re = re_1b_2; w = w.replace(re,\"\"); }\n else if (re4.test(w)) { w = w + \"e\"; }\n }\n }\n\n // Step 1c - replace suffix y or Y by i if preceded by a non-vowel which is not the first letter of the word (so cry -> cri, by -> by, say -> say)\n re = re_1c;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n w = stem + \"i\";\n }\n\n // Step 2\n re = re_2;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n suffix = fp[2];\n re = re_mgr0;\n if (re.test(stem)) {\n w = stem + step2list[suffix];\n }\n }\n\n // Step 3\n re = re_3;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n suffix = fp[2];\n re = re_mgr0;\n if (re.test(stem)) {\n w = stem + step3list[suffix];\n }\n }\n\n // Step 4\n re = re_4;\n re2 = re2_4;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n re = re_mgr1;\n if (re.test(stem)) {\n w = stem;\n }\n } else if (re2.test(w)) {\n var fp = re2.exec(w);\n stem = fp[1] + fp[2];\n re2 = re_mgr1;\n if (re2.test(stem)) {\n w = stem;\n }\n }\n\n // Step 5\n re = re_5;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n re = re_mgr1;\n re2 = re_meq1;\n re3 = re3_5;\n if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) {\n w = stem;\n }\n }\n\n re = re_5_1;\n re2 = re_mgr1;\n if (re.test(w) && re2.test(w)) {\n re = re_1b_2;\n w = w.replace(re,\"\");\n }\n\n // and turn initial Y back to y\n\n if (firstch == \"y\") {\n w = firstch.toLowerCase() + w.substr(1);\n }\n\n return w;\n };\n\n return function (token) {\n return token.update(porterStemmer);\n }\n})();\n\nlunr.Pipeline.registerFunction(lunr.stemmer, 'stemmer')\n/*!\n * lunr.stopWordFilter\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.generateStopWordFilter builds a stopWordFilter function from the provided\n * list of stop words.\n *\n * The built in lunr.stopWordFilter is built using this generator and can be used\n * to generate custom stopWordFilters for applications or non English languages.\n *\n * @function\n * @param {Array} token The token to pass through the filter\n * @returns {lunr.PipelineFunction}\n * @see lunr.Pipeline\n * @see lunr.stopWordFilter\n */\nlunr.generateStopWordFilter = function (stopWords) {\n var words = stopWords.reduce(function (memo, stopWord) {\n memo[stopWord] = stopWord\n return memo\n }, {})\n\n return function (token) {\n if (token && words[token.toString()] !== token.toString()) return token\n }\n}\n\n/**\n * lunr.stopWordFilter is an English language stop word list filter, any words\n * contained in the list will not be passed through the filter.\n *\n * This is intended to be used in the Pipeline. If the token does not pass the\n * filter then undefined will be returned.\n *\n * @function\n * @implements {lunr.PipelineFunction}\n * @params {lunr.Token} token - A token to check for being a stop word.\n * @returns {lunr.Token}\n * @see {@link lunr.Pipeline}\n */\nlunr.stopWordFilter = lunr.generateStopWordFilter([\n 'a',\n 'able',\n 'about',\n 'across',\n 'after',\n 'all',\n 'almost',\n 'also',\n 'am',\n 'among',\n 'an',\n 'and',\n 'any',\n 'are',\n 'as',\n 'at',\n 'be',\n 'because',\n 'been',\n 'but',\n 'by',\n 'can',\n 'cannot',\n 'could',\n 'dear',\n 'did',\n 'do',\n 'does',\n 'either',\n 'else',\n 'ever',\n 'every',\n 'for',\n 'from',\n 'get',\n 'got',\n 'had',\n 'has',\n 'have',\n 'he',\n 'her',\n 'hers',\n 'him',\n 'his',\n 'how',\n 'however',\n 'i',\n 'if',\n 'in',\n 'into',\n 'is',\n 'it',\n 'its',\n 'just',\n 'least',\n 'let',\n 'like',\n 'likely',\n 'may',\n 'me',\n 'might',\n 'most',\n 'must',\n 'my',\n 'neither',\n 'no',\n 'nor',\n 'not',\n 'of',\n 'off',\n 'often',\n 'on',\n 'only',\n 'or',\n 'other',\n 'our',\n 'own',\n 'rather',\n 'said',\n 'say',\n 'says',\n 'she',\n 'should',\n 'since',\n 'so',\n 'some',\n 'than',\n 'that',\n 'the',\n 'their',\n 'them',\n 'then',\n 'there',\n 'these',\n 'they',\n 'this',\n 'tis',\n 'to',\n 'too',\n 'twas',\n 'us',\n 'wants',\n 'was',\n 'we',\n 'were',\n 'what',\n 'when',\n 'where',\n 'which',\n 'while',\n 'who',\n 'whom',\n 'why',\n 'will',\n 'with',\n 'would',\n 'yet',\n 'you',\n 'your'\n])\n\nlunr.Pipeline.registerFunction(lunr.stopWordFilter, 'stopWordFilter')\n/*!\n * lunr.trimmer\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.trimmer is a pipeline function for trimming non word\n * characters from the beginning and end of tokens before they\n * enter the index.\n *\n * This implementation may not work correctly for non latin\n * characters and should either be removed or adapted for use\n * with languages with non-latin characters.\n *\n * @static\n * @implements {lunr.PipelineFunction}\n * @param {lunr.Token} token The token to pass through the filter\n * @returns {lunr.Token}\n * @see lunr.Pipeline\n */\nlunr.trimmer = function (token) {\n return token.update(function (s) {\n return s.replace(/^\\W+/, '').replace(/\\W+$/, '')\n })\n}\n\nlunr.Pipeline.registerFunction(lunr.trimmer, 'trimmer')\n/*!\n * lunr.TokenSet\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A token set is used to store the unique list of all tokens\n * within an index. Token sets are also used to represent an\n * incoming query to the index, this query token set and index\n * token set are then intersected to find which tokens to look\n * up in the inverted index.\n *\n * A token set can hold multiple tokens, as in the case of the\n * index token set, or it can hold a single token as in the\n * case of a simple query token set.\n *\n * Additionally token sets are used to perform wildcard matching.\n * Leading, contained and trailing wildcards are supported, and\n * from this edit distance matching can also be provided.\n *\n * Token sets are implemented as a minimal finite state automata,\n * where both common prefixes and suffixes are shared between tokens.\n * This helps to reduce the space used for storing the token set.\n *\n * @constructor\n */\nlunr.TokenSet = function () {\n this.final = false\n this.edges = {}\n this.id = lunr.TokenSet._nextId\n lunr.TokenSet._nextId += 1\n}\n\n/**\n * Keeps track of the next, auto increment, identifier to assign\n * to a new tokenSet.\n *\n * TokenSets require a unique identifier to be correctly minimised.\n *\n * @private\n */\nlunr.TokenSet._nextId = 1\n\n/**\n * Creates a TokenSet instance from the given sorted array of words.\n *\n * @param {String[]} arr - A sorted array of strings to create the set from.\n * @returns {lunr.TokenSet}\n * @throws Will throw an error if the input array is not sorted.\n */\nlunr.TokenSet.fromArray = function (arr) {\n var builder = new lunr.TokenSet.Builder\n\n for (var i = 0, len = arr.length; i < len; i++) {\n builder.insert(arr[i])\n }\n\n builder.finish()\n return builder.root\n}\n\n/**\n * Creates a token set from a query clause.\n *\n * @private\n * @param {Object} clause - A single clause from lunr.Query.\n * @param {string} clause.term - The query clause term.\n * @param {number} [clause.editDistance] - The optional edit distance for the term.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.fromClause = function (clause) {\n if ('editDistance' in clause) {\n return lunr.TokenSet.fromFuzzyString(clause.term, clause.editDistance)\n } else {\n return lunr.TokenSet.fromString(clause.term)\n }\n}\n\n/**\n * Creates a token set representing a single string with a specified\n * edit distance.\n *\n * Insertions, deletions, substitutions and transpositions are each\n * treated as an edit distance of 1.\n *\n * Increasing the allowed edit distance will have a dramatic impact\n * on the performance of both creating and intersecting these TokenSets.\n * It is advised to keep the edit distance less than 3.\n *\n * @param {string} str - The string to create the token set from.\n * @param {number} editDistance - The allowed edit distance to match.\n * @returns {lunr.Vector}\n */\nlunr.TokenSet.fromFuzzyString = function (str, editDistance) {\n var root = new lunr.TokenSet\n\n var stack = [{\n node: root,\n editsRemaining: editDistance,\n str: str\n }]\n\n while (stack.length) {\n var frame = stack.pop()\n\n // no edit\n if (frame.str.length > 0) {\n var char = frame.str.charAt(0),\n noEditNode\n\n if (char in frame.node.edges) {\n noEditNode = frame.node.edges[char]\n } else {\n noEditNode = new lunr.TokenSet\n frame.node.edges[char] = noEditNode\n }\n\n if (frame.str.length == 1) {\n noEditNode.final = true\n }\n\n stack.push({\n node: noEditNode,\n editsRemaining: frame.editsRemaining,\n str: frame.str.slice(1)\n })\n }\n\n if (frame.editsRemaining == 0) {\n continue\n }\n\n // insertion\n if (\"*\" in frame.node.edges) {\n var insertionNode = frame.node.edges[\"*\"]\n } else {\n var insertionNode = new lunr.TokenSet\n frame.node.edges[\"*\"] = insertionNode\n }\n\n if (frame.str.length == 0) {\n insertionNode.final = true\n }\n\n stack.push({\n node: insertionNode,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str\n })\n\n // deletion\n // can only do a deletion if we have enough edits remaining\n // and if there are characters left to delete in the string\n if (frame.str.length > 1) {\n stack.push({\n node: frame.node,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str.slice(1)\n })\n }\n\n // deletion\n // just removing the last character from the str\n if (frame.str.length == 1) {\n frame.node.final = true\n }\n\n // substitution\n // can only do a substitution if we have enough edits remaining\n // and if there are characters left to substitute\n if (frame.str.length >= 1) {\n if (\"*\" in frame.node.edges) {\n var substitutionNode = frame.node.edges[\"*\"]\n } else {\n var substitutionNode = new lunr.TokenSet\n frame.node.edges[\"*\"] = substitutionNode\n }\n\n if (frame.str.length == 1) {\n substitutionNode.final = true\n }\n\n stack.push({\n node: substitutionNode,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str.slice(1)\n })\n }\n\n // transposition\n // can only do a transposition if there are edits remaining\n // and there are enough characters to transpose\n if (frame.str.length > 1) {\n var charA = frame.str.charAt(0),\n charB = frame.str.charAt(1),\n transposeNode\n\n if (charB in frame.node.edges) {\n transposeNode = frame.node.edges[charB]\n } else {\n transposeNode = new lunr.TokenSet\n frame.node.edges[charB] = transposeNode\n }\n\n if (frame.str.length == 1) {\n transposeNode.final = true\n }\n\n stack.push({\n node: transposeNode,\n editsRemaining: frame.editsRemaining - 1,\n str: charA + frame.str.slice(2)\n })\n }\n }\n\n return root\n}\n\n/**\n * Creates a TokenSet from a string.\n *\n * The string may contain one or more wildcard characters (*)\n * that will allow wildcard matching when intersecting with\n * another TokenSet.\n *\n * @param {string} str - The string to create a TokenSet from.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.fromString = function (str) {\n var node = new lunr.TokenSet,\n root = node\n\n /*\n * Iterates through all characters within the passed string\n * appending a node for each character.\n *\n * When a wildcard character is found then a self\n * referencing edge is introduced to continually match\n * any number of any characters.\n */\n for (var i = 0, len = str.length; i < len; i++) {\n var char = str[i],\n final = (i == len - 1)\n\n if (char == \"*\") {\n node.edges[char] = node\n node.final = final\n\n } else {\n var next = new lunr.TokenSet\n next.final = final\n\n node.edges[char] = next\n node = next\n }\n }\n\n return root\n}\n\n/**\n * Converts this TokenSet into an array of strings\n * contained within the TokenSet.\n *\n * This is not intended to be used on a TokenSet that\n * contains wildcards, in these cases the results are\n * undefined and are likely to cause an infinite loop.\n *\n * @returns {string[]}\n */\nlunr.TokenSet.prototype.toArray = function () {\n var words = []\n\n var stack = [{\n prefix: \"\",\n node: this\n }]\n\n while (stack.length) {\n var frame = stack.pop(),\n edges = Object.keys(frame.node.edges),\n len = edges.length\n\n if (frame.node.final) {\n /* In Safari, at this point the prefix is sometimes corrupted, see:\n * https://github.com/olivernn/lunr.js/issues/279 Calling any\n * String.prototype method forces Safari to \"cast\" this string to what\n * it's supposed to be, fixing the bug. */\n frame.prefix.charAt(0)\n words.push(frame.prefix)\n }\n\n for (var i = 0; i < len; i++) {\n var edge = edges[i]\n\n stack.push({\n prefix: frame.prefix.concat(edge),\n node: frame.node.edges[edge]\n })\n }\n }\n\n return words\n}\n\n/**\n * Generates a string representation of a TokenSet.\n *\n * This is intended to allow TokenSets to be used as keys\n * in objects, largely to aid the construction and minimisation\n * of a TokenSet. As such it is not designed to be a human\n * friendly representation of the TokenSet.\n *\n * @returns {string}\n */\nlunr.TokenSet.prototype.toString = function () {\n // NOTE: Using Object.keys here as this.edges is very likely\n // to enter 'hash-mode' with many keys being added\n //\n // avoiding a for-in loop here as it leads to the function\n // being de-optimised (at least in V8). From some simple\n // benchmarks the performance is comparable, but allowing\n // V8 to optimize may mean easy performance wins in the future.\n\n if (this._str) {\n return this._str\n }\n\n var str = this.final ? '1' : '0',\n labels = Object.keys(this.edges).sort(),\n len = labels.length\n\n for (var i = 0; i < len; i++) {\n var label = labels[i],\n node = this.edges[label]\n\n str = str + label + node.id\n }\n\n return str\n}\n\n/**\n * Returns a new TokenSet that is the intersection of\n * this TokenSet and the passed TokenSet.\n *\n * This intersection will take into account any wildcards\n * contained within the TokenSet.\n *\n * @param {lunr.TokenSet} b - An other TokenSet to intersect with.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.prototype.intersect = function (b) {\n var output = new lunr.TokenSet,\n frame = undefined\n\n var stack = [{\n qNode: b,\n output: output,\n node: this\n }]\n\n while (stack.length) {\n frame = stack.pop()\n\n // NOTE: As with the #toString method, we are using\n // Object.keys and a for loop instead of a for-in loop\n // as both of these objects enter 'hash' mode, causing\n // the function to be de-optimised in V8\n var qEdges = Object.keys(frame.qNode.edges),\n qLen = qEdges.length,\n nEdges = Object.keys(frame.node.edges),\n nLen = nEdges.length\n\n for (var q = 0; q < qLen; q++) {\n var qEdge = qEdges[q]\n\n for (var n = 0; n < nLen; n++) {\n var nEdge = nEdges[n]\n\n if (nEdge == qEdge || qEdge == '*') {\n var node = frame.node.edges[nEdge],\n qNode = frame.qNode.edges[qEdge],\n final = node.final && qNode.final,\n next = undefined\n\n if (nEdge in frame.output.edges) {\n // an edge already exists for this character\n // no need to create a new node, just set the finality\n // bit unless this node is already final\n next = frame.output.edges[nEdge]\n next.final = next.final || final\n\n } else {\n // no edge exists yet, must create one\n // set the finality bit and insert it\n // into the output\n next = new lunr.TokenSet\n next.final = final\n frame.output.edges[nEdge] = next\n }\n\n stack.push({\n qNode: qNode,\n output: next,\n node: node\n })\n }\n }\n }\n }\n\n return output\n}\nlunr.TokenSet.Builder = function () {\n this.previousWord = \"\"\n this.root = new lunr.TokenSet\n this.uncheckedNodes = []\n this.minimizedNodes = {}\n}\n\nlunr.TokenSet.Builder.prototype.insert = function (word) {\n var node,\n commonPrefix = 0\n\n if (word < this.previousWord) {\n throw new Error (\"Out of order word insertion\")\n }\n\n for (var i = 0; i < word.length && i < this.previousWord.length; i++) {\n if (word[i] != this.previousWord[i]) break\n commonPrefix++\n }\n\n this.minimize(commonPrefix)\n\n if (this.uncheckedNodes.length == 0) {\n node = this.root\n } else {\n node = this.uncheckedNodes[this.uncheckedNodes.length - 1].child\n }\n\n for (var i = commonPrefix; i < word.length; i++) {\n var nextNode = new lunr.TokenSet,\n char = word[i]\n\n node.edges[char] = nextNode\n\n this.uncheckedNodes.push({\n parent: node,\n char: char,\n child: nextNode\n })\n\n node = nextNode\n }\n\n node.final = true\n this.previousWord = word\n}\n\nlunr.TokenSet.Builder.prototype.finish = function () {\n this.minimize(0)\n}\n\nlunr.TokenSet.Builder.prototype.minimize = function (downTo) {\n for (var i = this.uncheckedNodes.length - 1; i >= downTo; i--) {\n var node = this.uncheckedNodes[i],\n childKey = node.child.toString()\n\n if (childKey in this.minimizedNodes) {\n node.parent.edges[node.char] = this.minimizedNodes[childKey]\n } else {\n // Cache the key for this node since\n // we know it can't change anymore\n node.child._str = childKey\n\n this.minimizedNodes[childKey] = node.child\n }\n\n this.uncheckedNodes.pop()\n }\n}\n/*!\n * lunr.Index\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * An index contains the built index of all documents and provides a query interface\n * to the index.\n *\n * Usually instances of lunr.Index will not be created using this constructor, instead\n * lunr.Builder should be used to construct new indexes, or lunr.Index.load should be\n * used to load previously built and serialized indexes.\n *\n * @constructor\n * @param {Object} attrs - The attributes of the built search index.\n * @param {Object} attrs.invertedIndex - An index of term/field to document reference.\n * @param {Object} attrs.fieldVectors - Field vectors\n * @param {lunr.TokenSet} attrs.tokenSet - An set of all corpus tokens.\n * @param {string[]} attrs.fields - The names of indexed document fields.\n * @param {lunr.Pipeline} attrs.pipeline - The pipeline to use for search terms.\n */\nlunr.Index = function (attrs) {\n this.invertedIndex = attrs.invertedIndex\n this.fieldVectors = attrs.fieldVectors\n this.tokenSet = attrs.tokenSet\n this.fields = attrs.fields\n this.pipeline = attrs.pipeline\n}\n\n/**\n * A result contains details of a document matching a search query.\n * @typedef {Object} lunr.Index~Result\n * @property {string} ref - The reference of the document this result represents.\n * @property {number} score - A number between 0 and 1 representing how similar this document is to the query.\n * @property {lunr.MatchData} matchData - Contains metadata about this match including which term(s) caused the match.\n */\n\n/**\n * Although lunr provides the ability to create queries using lunr.Query, it also provides a simple\n * query language which itself is parsed into an instance of lunr.Query.\n *\n * For programmatically building queries it is advised to directly use lunr.Query, the query language\n * is best used for human entered text rather than program generated text.\n *\n * At its simplest queries can just be a single term, e.g. `hello`, multiple terms are also supported\n * and will be combined with OR, e.g `hello world` will match documents that contain either 'hello'\n * or 'world', though those that contain both will rank higher in the results.\n *\n * Wildcards can be included in terms to match one or more unspecified characters, these wildcards can\n * be inserted anywhere within the term, and more than one wildcard can exist in a single term. Adding\n * wildcards will increase the number of documents that will be found but can also have a negative\n * impact on query performance, especially with wildcards at the beginning of a term.\n *\n * Terms can be restricted to specific fields, e.g. `title:hello`, only documents with the term\n * hello in the title field will match this query. Using a field not present in the index will lead\n * to an error being thrown.\n *\n * Modifiers can also be added to terms, lunr supports edit distance and boost modifiers on terms. A term\n * boost will make documents matching that term score higher, e.g. `foo^5`. Edit distance is also supported\n * to provide fuzzy matching, e.g. 'hello~2' will match documents with hello with an edit distance of 2.\n * Avoid large values for edit distance to improve query performance.\n *\n * Each term also supports a presence modifier. By default a term's presence in document is optional, however\n * this can be changed to either required or prohibited. For a term's presence to be required in a document the\n * term should be prefixed with a '+', e.g. `+foo bar` is a search for documents that must contain 'foo' and\n * optionally contain 'bar'. Conversely a leading '-' sets the terms presence to prohibited, i.e. it must not\n * appear in a document, e.g. `-foo bar` is a search for documents that do not contain 'foo' but may contain 'bar'.\n *\n * To escape special characters the backslash character '\\' can be used, this allows searches to include\n * characters that would normally be considered modifiers, e.g. `foo\\~2` will search for a term \"foo~2\" instead\n * of attempting to apply a boost of 2 to the search term \"foo\".\n *\n * @typedef {string} lunr.Index~QueryString\n * @example
Simple single term query
\n * hello\n * @example
Multiple term query
\n * hello world\n * @example
term scoped to a field
\n * title:hello\n * @example
term with a boost of 10
\n * hello^10\n * @example
term with an edit distance of 2
\n * hello~2\n * @example
terms with presence modifiers
\n * -foo +bar baz\n */\n\n/**\n * Performs a search against the index using lunr query syntax.\n *\n * Results will be returned sorted by their score, the most relevant results\n * will be returned first. For details on how the score is calculated, please see\n * the {@link https://lunrjs.com/guides/searching.html#scoring|guide}.\n *\n * For more programmatic querying use lunr.Index#query.\n *\n * @param {lunr.Index~QueryString} queryString - A string containing a lunr query.\n * @throws {lunr.QueryParseError} If the passed query string cannot be parsed.\n * @returns {lunr.Index~Result[]}\n */\nlunr.Index.prototype.search = function (queryString) {\n return this.query(function (query) {\n var parser = new lunr.QueryParser(queryString, query)\n parser.parse()\n })\n}\n\n/**\n * A query builder callback provides a query object to be used to express\n * the query to perform on the index.\n *\n * @callback lunr.Index~queryBuilder\n * @param {lunr.Query} query - The query object to build up.\n * @this lunr.Query\n */\n\n/**\n * Performs a query against the index using the yielded lunr.Query object.\n *\n * If performing programmatic queries against the index, this method is preferred\n * over lunr.Index#search so as to avoid the additional query parsing overhead.\n *\n * A query object is yielded to the supplied function which should be used to\n * express the query to be run against the index.\n *\n * Note that although this function takes a callback parameter it is _not_ an\n * asynchronous operation, the callback is just yielded a query object to be\n * customized.\n *\n * @param {lunr.Index~queryBuilder} fn - A function that is used to build the query.\n * @returns {lunr.Index~Result[]}\n */\nlunr.Index.prototype.query = function (fn) {\n // for each query clause\n // * process terms\n // * expand terms from token set\n // * find matching documents and metadata\n // * get document vectors\n // * score documents\n\n var query = new lunr.Query(this.fields),\n matchingFields = Object.create(null),\n queryVectors = Object.create(null),\n termFieldCache = Object.create(null),\n requiredMatches = Object.create(null),\n prohibitedMatches = Object.create(null)\n\n /*\n * To support field level boosts a query vector is created per\n * field. An empty vector is eagerly created to support negated\n * queries.\n */\n for (var i = 0; i < this.fields.length; i++) {\n queryVectors[this.fields[i]] = new lunr.Vector\n }\n\n fn.call(query, query)\n\n for (var i = 0; i < query.clauses.length; i++) {\n /*\n * Unless the pipeline has been disabled for this term, which is\n * the case for terms with wildcards, we need to pass the clause\n * term through the search pipeline. A pipeline returns an array\n * of processed terms. Pipeline functions may expand the passed\n * term, which means we may end up performing multiple index lookups\n * for a single query term.\n */\n var clause = query.clauses[i],\n terms = null,\n clauseMatches = lunr.Set.empty\n\n if (clause.usePipeline) {\n terms = this.pipeline.runString(clause.term, {\n fields: clause.fields\n })\n } else {\n terms = [clause.term]\n }\n\n for (var m = 0; m < terms.length; m++) {\n var term = terms[m]\n\n /*\n * Each term returned from the pipeline needs to use the same query\n * clause object, e.g. the same boost and or edit distance. The\n * simplest way to do this is to re-use the clause object but mutate\n * its term property.\n */\n clause.term = term\n\n /*\n * From the term in the clause we create a token set which will then\n * be used to intersect the indexes token set to get a list of terms\n * to lookup in the inverted index\n */\n var termTokenSet = lunr.TokenSet.fromClause(clause),\n expandedTerms = this.tokenSet.intersect(termTokenSet).toArray()\n\n /*\n * If a term marked as required does not exist in the tokenSet it is\n * impossible for the search to return any matches. We set all the field\n * scoped required matches set to empty and stop examining any further\n * clauses.\n */\n if (expandedTerms.length === 0 && clause.presence === lunr.Query.presence.REQUIRED) {\n for (var k = 0; k < clause.fields.length; k++) {\n var field = clause.fields[k]\n requiredMatches[field] = lunr.Set.empty\n }\n\n break\n }\n\n for (var j = 0; j < expandedTerms.length; j++) {\n /*\n * For each term get the posting and termIndex, this is required for\n * building the query vector.\n */\n var expandedTerm = expandedTerms[j],\n posting = this.invertedIndex[expandedTerm],\n termIndex = posting._index\n\n for (var k = 0; k < clause.fields.length; k++) {\n /*\n * For each field that this query term is scoped by (by default\n * all fields are in scope) we need to get all the document refs\n * that have this term in that field.\n *\n * The posting is the entry in the invertedIndex for the matching\n * term from above.\n */\n var field = clause.fields[k],\n fieldPosting = posting[field],\n matchingDocumentRefs = Object.keys(fieldPosting),\n termField = expandedTerm + \"/\" + field,\n matchingDocumentsSet = new lunr.Set(matchingDocumentRefs)\n\n /*\n * if the presence of this term is required ensure that the matching\n * documents are added to the set of required matches for this clause.\n *\n */\n if (clause.presence == lunr.Query.presence.REQUIRED) {\n clauseMatches = clauseMatches.union(matchingDocumentsSet)\n\n if (requiredMatches[field] === undefined) {\n requiredMatches[field] = lunr.Set.complete\n }\n }\n\n /*\n * if the presence of this term is prohibited ensure that the matching\n * documents are added to the set of prohibited matches for this field,\n * creating that set if it does not yet exist.\n */\n if (clause.presence == lunr.Query.presence.PROHIBITED) {\n if (prohibitedMatches[field] === undefined) {\n prohibitedMatches[field] = lunr.Set.empty\n }\n\n prohibitedMatches[field] = prohibitedMatches[field].union(matchingDocumentsSet)\n\n /*\n * Prohibited matches should not be part of the query vector used for\n * similarity scoring and no metadata should be extracted so we continue\n * to the next field\n */\n continue\n }\n\n /*\n * The query field vector is populated using the termIndex found for\n * the term and a unit value with the appropriate boost applied.\n * Using upsert because there could already be an entry in the vector\n * for the term we are working with. In that case we just add the scores\n * together.\n */\n queryVectors[field].upsert(termIndex, clause.boost, function (a, b) { return a + b })\n\n /**\n * If we've already seen this term, field combo then we've already collected\n * the matching documents and metadata, no need to go through all that again\n */\n if (termFieldCache[termField]) {\n continue\n }\n\n for (var l = 0; l < matchingDocumentRefs.length; l++) {\n /*\n * All metadata for this term/field/document triple\n * are then extracted and collected into an instance\n * of lunr.MatchData ready to be returned in the query\n * results\n */\n var matchingDocumentRef = matchingDocumentRefs[l],\n matchingFieldRef = new lunr.FieldRef (matchingDocumentRef, field),\n metadata = fieldPosting[matchingDocumentRef],\n fieldMatch\n\n if ((fieldMatch = matchingFields[matchingFieldRef]) === undefined) {\n matchingFields[matchingFieldRef] = new lunr.MatchData (expandedTerm, field, metadata)\n } else {\n fieldMatch.add(expandedTerm, field, metadata)\n }\n\n }\n\n termFieldCache[termField] = true\n }\n }\n }\n\n /**\n * If the presence was required we need to update the requiredMatches field sets.\n * We do this after all fields for the term have collected their matches because\n * the clause terms presence is required in _any_ of the fields not _all_ of the\n * fields.\n */\n if (clause.presence === lunr.Query.presence.REQUIRED) {\n for (var k = 0; k < clause.fields.length; k++) {\n var field = clause.fields[k]\n requiredMatches[field] = requiredMatches[field].intersect(clauseMatches)\n }\n }\n }\n\n /**\n * Need to combine the field scoped required and prohibited\n * matching documents into a global set of required and prohibited\n * matches\n */\n var allRequiredMatches = lunr.Set.complete,\n allProhibitedMatches = lunr.Set.empty\n\n for (var i = 0; i < this.fields.length; i++) {\n var field = this.fields[i]\n\n if (requiredMatches[field]) {\n allRequiredMatches = allRequiredMatches.intersect(requiredMatches[field])\n }\n\n if (prohibitedMatches[field]) {\n allProhibitedMatches = allProhibitedMatches.union(prohibitedMatches[field])\n }\n }\n\n var matchingFieldRefs = Object.keys(matchingFields),\n results = [],\n matches = Object.create(null)\n\n /*\n * If the query is negated (contains only prohibited terms)\n * we need to get _all_ fieldRefs currently existing in the\n * index. This is only done when we know that the query is\n * entirely prohibited terms to avoid any cost of getting all\n * fieldRefs unnecessarily.\n *\n * Additionally, blank MatchData must be created to correctly\n * populate the results.\n */\n if (query.isNegated()) {\n matchingFieldRefs = Object.keys(this.fieldVectors)\n\n for (var i = 0; i < matchingFieldRefs.length; i++) {\n var matchingFieldRef = matchingFieldRefs[i]\n var fieldRef = lunr.FieldRef.fromString(matchingFieldRef)\n matchingFields[matchingFieldRef] = new lunr.MatchData\n }\n }\n\n for (var i = 0; i < matchingFieldRefs.length; i++) {\n /*\n * Currently we have document fields that match the query, but we\n * need to return documents. The matchData and scores are combined\n * from multiple fields belonging to the same document.\n *\n * Scores are calculated by field, using the query vectors created\n * above, and combined into a final document score using addition.\n */\n var fieldRef = lunr.FieldRef.fromString(matchingFieldRefs[i]),\n docRef = fieldRef.docRef\n\n if (!allRequiredMatches.contains(docRef)) {\n continue\n }\n\n if (allProhibitedMatches.contains(docRef)) {\n continue\n }\n\n var fieldVector = this.fieldVectors[fieldRef],\n score = queryVectors[fieldRef.fieldName].similarity(fieldVector),\n docMatch\n\n if ((docMatch = matches[docRef]) !== undefined) {\n docMatch.score += score\n docMatch.matchData.combine(matchingFields[fieldRef])\n } else {\n var match = {\n ref: docRef,\n score: score,\n matchData: matchingFields[fieldRef]\n }\n matches[docRef] = match\n results.push(match)\n }\n }\n\n /*\n * Sort the results objects by score, highest first.\n */\n return results.sort(function (a, b) {\n return b.score - a.score\n })\n}\n\n/**\n * Prepares the index for JSON serialization.\n *\n * The schema for this JSON blob will be described in a\n * separate JSON schema file.\n *\n * @returns {Object}\n */\nlunr.Index.prototype.toJSON = function () {\n var invertedIndex = Object.keys(this.invertedIndex)\n .sort()\n .map(function (term) {\n return [term, this.invertedIndex[term]]\n }, this)\n\n var fieldVectors = Object.keys(this.fieldVectors)\n .map(function (ref) {\n return [ref, this.fieldVectors[ref].toJSON()]\n }, this)\n\n return {\n version: lunr.version,\n fields: this.fields,\n fieldVectors: fieldVectors,\n invertedIndex: invertedIndex,\n pipeline: this.pipeline.toJSON()\n }\n}\n\n/**\n * Loads a previously serialized lunr.Index\n *\n * @param {Object} serializedIndex - A previously serialized lunr.Index\n * @returns {lunr.Index}\n */\nlunr.Index.load = function (serializedIndex) {\n var attrs = {},\n fieldVectors = {},\n serializedVectors = serializedIndex.fieldVectors,\n invertedIndex = Object.create(null),\n serializedInvertedIndex = serializedIndex.invertedIndex,\n tokenSetBuilder = new lunr.TokenSet.Builder,\n pipeline = lunr.Pipeline.load(serializedIndex.pipeline)\n\n if (serializedIndex.version != lunr.version) {\n lunr.utils.warn(\"Version mismatch when loading serialised index. Current version of lunr '\" + lunr.version + \"' does not match serialized index '\" + serializedIndex.version + \"'\")\n }\n\n for (var i = 0; i < serializedVectors.length; i++) {\n var tuple = serializedVectors[i],\n ref = tuple[0],\n elements = tuple[1]\n\n fieldVectors[ref] = new lunr.Vector(elements)\n }\n\n for (var i = 0; i < serializedInvertedIndex.length; i++) {\n var tuple = serializedInvertedIndex[i],\n term = tuple[0],\n posting = tuple[1]\n\n tokenSetBuilder.insert(term)\n invertedIndex[term] = posting\n }\n\n tokenSetBuilder.finish()\n\n attrs.fields = serializedIndex.fields\n\n attrs.fieldVectors = fieldVectors\n attrs.invertedIndex = invertedIndex\n attrs.tokenSet = tokenSetBuilder.root\n attrs.pipeline = pipeline\n\n return new lunr.Index(attrs)\n}\n/*!\n * lunr.Builder\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.Builder performs indexing on a set of documents and\n * returns instances of lunr.Index ready for querying.\n *\n * All configuration of the index is done via the builder, the\n * fields to index, the document reference, the text processing\n * pipeline and document scoring parameters are all set on the\n * builder before indexing.\n *\n * @constructor\n * @property {string} _ref - Internal reference to the document reference field.\n * @property {string[]} _fields - Internal reference to the document fields to index.\n * @property {object} invertedIndex - The inverted index maps terms to document fields.\n * @property {object} documentTermFrequencies - Keeps track of document term frequencies.\n * @property {object} documentLengths - Keeps track of the length of documents added to the index.\n * @property {lunr.tokenizer} tokenizer - Function for splitting strings into tokens for indexing.\n * @property {lunr.Pipeline} pipeline - The pipeline performs text processing on tokens before indexing.\n * @property {lunr.Pipeline} searchPipeline - A pipeline for processing search terms before querying the index.\n * @property {number} documentCount - Keeps track of the total number of documents indexed.\n * @property {number} _b - A parameter to control field length normalization, setting this to 0 disabled normalization, 1 fully normalizes field lengths, the default value is 0.75.\n * @property {number} _k1 - A parameter to control how quickly an increase in term frequency results in term frequency saturation, the default value is 1.2.\n * @property {number} termIndex - A counter incremented for each unique term, used to identify a terms position in the vector space.\n * @property {array} metadataWhitelist - A list of metadata keys that have been whitelisted for entry in the index.\n */\nlunr.Builder = function () {\n this._ref = \"id\"\n this._fields = Object.create(null)\n this._documents = Object.create(null)\n this.invertedIndex = Object.create(null)\n this.fieldTermFrequencies = {}\n this.fieldLengths = {}\n this.tokenizer = lunr.tokenizer\n this.pipeline = new lunr.Pipeline\n this.searchPipeline = new lunr.Pipeline\n this.documentCount = 0\n this._b = 0.75\n this._k1 = 1.2\n this.termIndex = 0\n this.metadataWhitelist = []\n}\n\n/**\n * Sets the document field used as the document reference. Every document must have this field.\n * The type of this field in the document should be a string, if it is not a string it will be\n * coerced into a string by calling toString.\n *\n * The default ref is 'id'.\n *\n * The ref should _not_ be changed during indexing, it should be set before any documents are\n * added to the index. Changing it during indexing can lead to inconsistent results.\n *\n * @param {string} ref - The name of the reference field in the document.\n */\nlunr.Builder.prototype.ref = function (ref) {\n this._ref = ref\n}\n\n/**\n * A function that is used to extract a field from a document.\n *\n * Lunr expects a field to be at the top level of a document, if however the field\n * is deeply nested within a document an extractor function can be used to extract\n * the right field for indexing.\n *\n * @callback fieldExtractor\n * @param {object} doc - The document being added to the index.\n * @returns {?(string|object|object[])} obj - The object that will be indexed for this field.\n * @example
Extracting a nested field
\n * function (doc) { return doc.nested.field }\n */\n\n/**\n * Adds a field to the list of document fields that will be indexed. Every document being\n * indexed should have this field. Null values for this field in indexed documents will\n * not cause errors but will limit the chance of that document being retrieved by searches.\n *\n * All fields should be added before adding documents to the index. Adding fields after\n * a document has been indexed will have no effect on already indexed documents.\n *\n * Fields can be boosted at build time. This allows terms within that field to have more\n * importance when ranking search results. Use a field boost to specify that matches within\n * one field are more important than other fields.\n *\n * @param {string} fieldName - The name of a field to index in all documents.\n * @param {object} attributes - Optional attributes associated with this field.\n * @param {number} [attributes.boost=1] - Boost applied to all terms within this field.\n * @param {fieldExtractor} [attributes.extractor] - Function to extract a field from a document.\n * @throws {RangeError} fieldName cannot contain unsupported characters '/'\n */\nlunr.Builder.prototype.field = function (fieldName, attributes) {\n if (/\\//.test(fieldName)) {\n throw new RangeError (\"Field '\" + fieldName + \"' contains illegal character '/'\")\n }\n\n this._fields[fieldName] = attributes || {}\n}\n\n/**\n * A parameter to tune the amount of field length normalisation that is applied when\n * calculating relevance scores. A value of 0 will completely disable any normalisation\n * and a value of 1 will fully normalise field lengths. The default is 0.75. Values of b\n * will be clamped to the range 0 - 1.\n *\n * @param {number} number - The value to set for this tuning parameter.\n */\nlunr.Builder.prototype.b = function (number) {\n if (number < 0) {\n this._b = 0\n } else if (number > 1) {\n this._b = 1\n } else {\n this._b = number\n }\n}\n\n/**\n * A parameter that controls the speed at which a rise in term frequency results in term\n * frequency saturation. The default value is 1.2. Setting this to a higher value will give\n * slower saturation levels, a lower value will result in quicker saturation.\n *\n * @param {number} number - The value to set for this tuning parameter.\n */\nlunr.Builder.prototype.k1 = function (number) {\n this._k1 = number\n}\n\n/**\n * Adds a document to the index.\n *\n * Before adding fields to the index the index should have been fully setup, with the document\n * ref and all fields to index already having been specified.\n *\n * The document must have a field name as specified by the ref (by default this is 'id') and\n * it should have all fields defined for indexing, though null or undefined values will not\n * cause errors.\n *\n * Entire documents can be boosted at build time. Applying a boost to a document indicates that\n * this document should rank higher in search results than other documents.\n *\n * @param {object} doc - The document to add to the index.\n * @param {object} attributes - Optional attributes associated with this document.\n * @param {number} [attributes.boost=1] - Boost applied to all terms within this document.\n */\nlunr.Builder.prototype.add = function (doc, attributes) {\n var docRef = doc[this._ref],\n fields = Object.keys(this._fields)\n\n this._documents[docRef] = attributes || {}\n this.documentCount += 1\n\n for (var i = 0; i < fields.length; i++) {\n var fieldName = fields[i],\n extractor = this._fields[fieldName].extractor,\n field = extractor ? extractor(doc) : doc[fieldName],\n tokens = this.tokenizer(field, {\n fields: [fieldName]\n }),\n terms = this.pipeline.run(tokens),\n fieldRef = new lunr.FieldRef (docRef, fieldName),\n fieldTerms = Object.create(null)\n\n this.fieldTermFrequencies[fieldRef] = fieldTerms\n this.fieldLengths[fieldRef] = 0\n\n // store the length of this field for this document\n this.fieldLengths[fieldRef] += terms.length\n\n // calculate term frequencies for this field\n for (var j = 0; j < terms.length; j++) {\n var term = terms[j]\n\n if (fieldTerms[term] == undefined) {\n fieldTerms[term] = 0\n }\n\n fieldTerms[term] += 1\n\n // add to inverted index\n // create an initial posting if one doesn't exist\n if (this.invertedIndex[term] == undefined) {\n var posting = Object.create(null)\n posting[\"_index\"] = this.termIndex\n this.termIndex += 1\n\n for (var k = 0; k < fields.length; k++) {\n posting[fields[k]] = Object.create(null)\n }\n\n this.invertedIndex[term] = posting\n }\n\n // add an entry for this term/fieldName/docRef to the invertedIndex\n if (this.invertedIndex[term][fieldName][docRef] == undefined) {\n this.invertedIndex[term][fieldName][docRef] = Object.create(null)\n }\n\n // store all whitelisted metadata about this token in the\n // inverted index\n for (var l = 0; l < this.metadataWhitelist.length; l++) {\n var metadataKey = this.metadataWhitelist[l],\n metadata = term.metadata[metadataKey]\n\n if (this.invertedIndex[term][fieldName][docRef][metadataKey] == undefined) {\n this.invertedIndex[term][fieldName][docRef][metadataKey] = []\n }\n\n this.invertedIndex[term][fieldName][docRef][metadataKey].push(metadata)\n }\n }\n\n }\n}\n\n/**\n * Calculates the average document length for this index\n *\n * @private\n */\nlunr.Builder.prototype.calculateAverageFieldLengths = function () {\n\n var fieldRefs = Object.keys(this.fieldLengths),\n numberOfFields = fieldRefs.length,\n accumulator = {},\n documentsWithField = {}\n\n for (var i = 0; i < numberOfFields; i++) {\n var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]),\n field = fieldRef.fieldName\n\n documentsWithField[field] || (documentsWithField[field] = 0)\n documentsWithField[field] += 1\n\n accumulator[field] || (accumulator[field] = 0)\n accumulator[field] += this.fieldLengths[fieldRef]\n }\n\n var fields = Object.keys(this._fields)\n\n for (var i = 0; i < fields.length; i++) {\n var fieldName = fields[i]\n accumulator[fieldName] = accumulator[fieldName] / documentsWithField[fieldName]\n }\n\n this.averageFieldLength = accumulator\n}\n\n/**\n * Builds a vector space model of every document using lunr.Vector\n *\n * @private\n */\nlunr.Builder.prototype.createFieldVectors = function () {\n var fieldVectors = {},\n fieldRefs = Object.keys(this.fieldTermFrequencies),\n fieldRefsLength = fieldRefs.length,\n termIdfCache = Object.create(null)\n\n for (var i = 0; i < fieldRefsLength; i++) {\n var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]),\n fieldName = fieldRef.fieldName,\n fieldLength = this.fieldLengths[fieldRef],\n fieldVector = new lunr.Vector,\n termFrequencies = this.fieldTermFrequencies[fieldRef],\n terms = Object.keys(termFrequencies),\n termsLength = terms.length\n\n\n var fieldBoost = this._fields[fieldName].boost || 1,\n docBoost = this._documents[fieldRef.docRef].boost || 1\n\n for (var j = 0; j < termsLength; j++) {\n var term = terms[j],\n tf = termFrequencies[term],\n termIndex = this.invertedIndex[term]._index,\n idf, score, scoreWithPrecision\n\n if (termIdfCache[term] === undefined) {\n idf = lunr.idf(this.invertedIndex[term], this.documentCount)\n termIdfCache[term] = idf\n } else {\n idf = termIdfCache[term]\n }\n\n score = idf * ((this._k1 + 1) * tf) / (this._k1 * (1 - this._b + this._b * (fieldLength / this.averageFieldLength[fieldName])) + tf)\n score *= fieldBoost\n score *= docBoost\n scoreWithPrecision = Math.round(score * 1000) / 1000\n // Converts 1.23456789 to 1.234.\n // Reducing the precision so that the vectors take up less\n // space when serialised. Doing it now so that they behave\n // the same before and after serialisation. Also, this is\n // the fastest approach to reducing a number's precision in\n // JavaScript.\n\n fieldVector.insert(termIndex, scoreWithPrecision)\n }\n\n fieldVectors[fieldRef] = fieldVector\n }\n\n this.fieldVectors = fieldVectors\n}\n\n/**\n * Creates a token set of all tokens in the index using lunr.TokenSet\n *\n * @private\n */\nlunr.Builder.prototype.createTokenSet = function () {\n this.tokenSet = lunr.TokenSet.fromArray(\n Object.keys(this.invertedIndex).sort()\n )\n}\n\n/**\n * Builds the index, creating an instance of lunr.Index.\n *\n * This completes the indexing process and should only be called\n * once all documents have been added to the index.\n *\n * @returns {lunr.Index}\n */\nlunr.Builder.prototype.build = function () {\n this.calculateAverageFieldLengths()\n this.createFieldVectors()\n this.createTokenSet()\n\n return new lunr.Index({\n invertedIndex: this.invertedIndex,\n fieldVectors: this.fieldVectors,\n tokenSet: this.tokenSet,\n fields: Object.keys(this._fields),\n pipeline: this.searchPipeline\n })\n}\n\n/**\n * Applies a plugin to the index builder.\n *\n * A plugin is a function that is called with the index builder as its context.\n * Plugins can be used to customise or extend the behaviour of the index\n * in some way. A plugin is just a function, that encapsulated the custom\n * behaviour that should be applied when building the index.\n *\n * The plugin function will be called with the index builder as its argument, additional\n * arguments can also be passed when calling use. The function will be called\n * with the index builder as its context.\n *\n * @param {Function} plugin The plugin to apply.\n */\nlunr.Builder.prototype.use = function (fn) {\n var args = Array.prototype.slice.call(arguments, 1)\n args.unshift(this)\n fn.apply(this, args)\n}\n/**\n * Contains and collects metadata about a matching document.\n * A single instance of lunr.MatchData is returned as part of every\n * lunr.Index~Result.\n *\n * @constructor\n * @param {string} term - The term this match data is associated with\n * @param {string} field - The field in which the term was found\n * @param {object} metadata - The metadata recorded about this term in this field\n * @property {object} metadata - A cloned collection of metadata associated with this document.\n * @see {@link lunr.Index~Result}\n */\nlunr.MatchData = function (term, field, metadata) {\n var clonedMetadata = Object.create(null),\n metadataKeys = Object.keys(metadata || {})\n\n // Cloning the metadata to prevent the original\n // being mutated during match data combination.\n // Metadata is kept in an array within the inverted\n // index so cloning the data can be done with\n // Array#slice\n for (var i = 0; i < metadataKeys.length; i++) {\n var key = metadataKeys[i]\n clonedMetadata[key] = metadata[key].slice()\n }\n\n this.metadata = Object.create(null)\n\n if (term !== undefined) {\n this.metadata[term] = Object.create(null)\n this.metadata[term][field] = clonedMetadata\n }\n}\n\n/**\n * An instance of lunr.MatchData will be created for every term that matches a\n * document. However only one instance is required in a lunr.Index~Result. This\n * method combines metadata from another instance of lunr.MatchData with this\n * objects metadata.\n *\n * @param {lunr.MatchData} otherMatchData - Another instance of match data to merge with this one.\n * @see {@link lunr.Index~Result}\n */\nlunr.MatchData.prototype.combine = function (otherMatchData) {\n var terms = Object.keys(otherMatchData.metadata)\n\n for (var i = 0; i < terms.length; i++) {\n var term = terms[i],\n fields = Object.keys(otherMatchData.metadata[term])\n\n if (this.metadata[term] == undefined) {\n this.metadata[term] = Object.create(null)\n }\n\n for (var j = 0; j < fields.length; j++) {\n var field = fields[j],\n keys = Object.keys(otherMatchData.metadata[term][field])\n\n if (this.metadata[term][field] == undefined) {\n this.metadata[term][field] = Object.create(null)\n }\n\n for (var k = 0; k < keys.length; k++) {\n var key = keys[k]\n\n if (this.metadata[term][field][key] == undefined) {\n this.metadata[term][field][key] = otherMatchData.metadata[term][field][key]\n } else {\n this.metadata[term][field][key] = this.metadata[term][field][key].concat(otherMatchData.metadata[term][field][key])\n }\n\n }\n }\n }\n}\n\n/**\n * Add metadata for a term/field pair to this instance of match data.\n *\n * @param {string} term - The term this match data is associated with\n * @param {string} field - The field in which the term was found\n * @param {object} metadata - The metadata recorded about this term in this field\n */\nlunr.MatchData.prototype.add = function (term, field, metadata) {\n if (!(term in this.metadata)) {\n this.metadata[term] = Object.create(null)\n this.metadata[term][field] = metadata\n return\n }\n\n if (!(field in this.metadata[term])) {\n this.metadata[term][field] = metadata\n return\n }\n\n var metadataKeys = Object.keys(metadata)\n\n for (var i = 0; i < metadataKeys.length; i++) {\n var key = metadataKeys[i]\n\n if (key in this.metadata[term][field]) {\n this.metadata[term][field][key] = this.metadata[term][field][key].concat(metadata[key])\n } else {\n this.metadata[term][field][key] = metadata[key]\n }\n }\n}\n/**\n * A lunr.Query provides a programmatic way of defining queries to be performed\n * against a {@link lunr.Index}.\n *\n * Prefer constructing a lunr.Query using the {@link lunr.Index#query} method\n * so the query object is pre-initialized with the right index fields.\n *\n * @constructor\n * @property {lunr.Query~Clause[]} clauses - An array of query clauses.\n * @property {string[]} allFields - An array of all available fields in a lunr.Index.\n */\nlunr.Query = function (allFields) {\n this.clauses = []\n this.allFields = allFields\n}\n\n/**\n * Constants for indicating what kind of automatic wildcard insertion will be used when constructing a query clause.\n *\n * This allows wildcards to be added to the beginning and end of a term without having to manually do any string\n * concatenation.\n *\n * The wildcard constants can be bitwise combined to select both leading and trailing wildcards.\n *\n * @constant\n * @default\n * @property {number} wildcard.NONE - The term will have no wildcards inserted, this is the default behaviour\n * @property {number} wildcard.LEADING - Prepend the term with a wildcard, unless a leading wildcard already exists\n * @property {number} wildcard.TRAILING - Append a wildcard to the term, unless a trailing wildcard already exists\n * @see lunr.Query~Clause\n * @see lunr.Query#clause\n * @see lunr.Query#term\n * @example
\n * query.term('foo', {\n * wildcard: lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING\n * })\n */\n\nlunr.Query.wildcard = new String (\"*\")\nlunr.Query.wildcard.NONE = 0\nlunr.Query.wildcard.LEADING = 1\nlunr.Query.wildcard.TRAILING = 2\n\n/**\n * Constants for indicating what kind of presence a term must have in matching documents.\n *\n * @constant\n * @enum {number}\n * @see lunr.Query~Clause\n * @see lunr.Query#clause\n * @see lunr.Query#term\n * @example
query term with required presence
\n * query.term('foo', { presence: lunr.Query.presence.REQUIRED })\n */\nlunr.Query.presence = {\n /**\n * Term's presence in a document is optional, this is the default value.\n */\n OPTIONAL: 1,\n\n /**\n * Term's presence in a document is required, documents that do not contain\n * this term will not be returned.\n */\n REQUIRED: 2,\n\n /**\n * Term's presence in a document is prohibited, documents that do contain\n * this term will not be returned.\n */\n PROHIBITED: 3\n}\n\n/**\n * A single clause in a {@link lunr.Query} contains a term and details on how to\n * match that term against a {@link lunr.Index}.\n *\n * @typedef {Object} lunr.Query~Clause\n * @property {string[]} fields - The fields in an index this clause should be matched against.\n * @property {number} [boost=1] - Any boost that should be applied when matching this clause.\n * @property {number} [editDistance] - Whether the term should have fuzzy matching applied, and how fuzzy the match should be.\n * @property {boolean} [usePipeline] - Whether the term should be passed through the search pipeline.\n * @property {number} [wildcard=lunr.Query.wildcard.NONE] - Whether the term should have wildcards appended or prepended.\n * @property {number} [presence=lunr.Query.presence.OPTIONAL] - The terms presence in any matching documents.\n */\n\n/**\n * Adds a {@link lunr.Query~Clause} to this query.\n *\n * Unless the clause contains the fields to be matched all fields will be matched. In addition\n * a default boost of 1 is applied to the clause.\n *\n * @param {lunr.Query~Clause} clause - The clause to add to this query.\n * @see lunr.Query~Clause\n * @returns {lunr.Query}\n */\nlunr.Query.prototype.clause = function (clause) {\n if (!('fields' in clause)) {\n clause.fields = this.allFields\n }\n\n if (!('boost' in clause)) {\n clause.boost = 1\n }\n\n if (!('usePipeline' in clause)) {\n clause.usePipeline = true\n }\n\n if (!('wildcard' in clause)) {\n clause.wildcard = lunr.Query.wildcard.NONE\n }\n\n if ((clause.wildcard & lunr.Query.wildcard.LEADING) && (clause.term.charAt(0) != lunr.Query.wildcard)) {\n clause.term = \"*\" + clause.term\n }\n\n if ((clause.wildcard & lunr.Query.wildcard.TRAILING) && (clause.term.slice(-1) != lunr.Query.wildcard)) {\n clause.term = \"\" + clause.term + \"*\"\n }\n\n if (!('presence' in clause)) {\n clause.presence = lunr.Query.presence.OPTIONAL\n }\n\n this.clauses.push(clause)\n\n return this\n}\n\n/**\n * A negated query is one in which every clause has a presence of\n * prohibited. These queries require some special processing to return\n * the expected results.\n *\n * @returns boolean\n */\nlunr.Query.prototype.isNegated = function () {\n for (var i = 0; i < this.clauses.length; i++) {\n if (this.clauses[i].presence != lunr.Query.presence.PROHIBITED) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Adds a term to the current query, under the covers this will create a {@link lunr.Query~Clause}\n * to the list of clauses that make up this query.\n *\n * The term is used as is, i.e. no tokenization will be performed by this method. Instead conversion\n * to a token or token-like string should be done before calling this method.\n *\n * The term will be converted to a string by calling `toString`. Multiple terms can be passed as an\n * array, each term in the array will share the same options.\n *\n * @param {object|object[]} term - The term(s) to add to the query.\n * @param {object} [options] - Any additional properties to add to the query clause.\n * @returns {lunr.Query}\n * @see lunr.Query#clause\n * @see lunr.Query~Clause\n * @example
adding a single term to a query
\n * query.term(\"foo\")\n * @example
adding a single term to a query and specifying search fields, term boost and automatic trailing wildcard
using lunr.tokenizer to convert a string to tokens before using them as terms
\n * query.term(lunr.tokenizer(\"foo bar\"))\n */\nlunr.Query.prototype.term = function (term, options) {\n if (Array.isArray(term)) {\n term.forEach(function (t) { this.term(t, lunr.utils.clone(options)) }, this)\n return this\n }\n\n var clause = options || {}\n clause.term = term.toString()\n\n this.clause(clause)\n\n return this\n}\nlunr.QueryParseError = function (message, start, end) {\n this.name = \"QueryParseError\"\n this.message = message\n this.start = start\n this.end = end\n}\n\nlunr.QueryParseError.prototype = new Error\nlunr.QueryLexer = function (str) {\n this.lexemes = []\n this.str = str\n this.length = str.length\n this.pos = 0\n this.start = 0\n this.escapeCharPositions = []\n}\n\nlunr.QueryLexer.prototype.run = function () {\n var state = lunr.QueryLexer.lexText\n\n while (state) {\n state = state(this)\n }\n}\n\nlunr.QueryLexer.prototype.sliceString = function () {\n var subSlices = [],\n sliceStart = this.start,\n sliceEnd = this.pos\n\n for (var i = 0; i < this.escapeCharPositions.length; i++) {\n sliceEnd = this.escapeCharPositions[i]\n subSlices.push(this.str.slice(sliceStart, sliceEnd))\n sliceStart = sliceEnd + 1\n }\n\n subSlices.push(this.str.slice(sliceStart, this.pos))\n this.escapeCharPositions.length = 0\n\n return subSlices.join('')\n}\n\nlunr.QueryLexer.prototype.emit = function (type) {\n this.lexemes.push({\n type: type,\n str: this.sliceString(),\n start: this.start,\n end: this.pos\n })\n\n this.start = this.pos\n}\n\nlunr.QueryLexer.prototype.escapeCharacter = function () {\n this.escapeCharPositions.push(this.pos - 1)\n this.pos += 1\n}\n\nlunr.QueryLexer.prototype.next = function () {\n if (this.pos >= this.length) {\n return lunr.QueryLexer.EOS\n }\n\n var char = this.str.charAt(this.pos)\n this.pos += 1\n return char\n}\n\nlunr.QueryLexer.prototype.width = function () {\n return this.pos - this.start\n}\n\nlunr.QueryLexer.prototype.ignore = function () {\n if (this.start == this.pos) {\n this.pos += 1\n }\n\n this.start = this.pos\n}\n\nlunr.QueryLexer.prototype.backup = function () {\n this.pos -= 1\n}\n\nlunr.QueryLexer.prototype.acceptDigitRun = function () {\n var char, charCode\n\n do {\n char = this.next()\n charCode = char.charCodeAt(0)\n } while (charCode > 47 && charCode < 58)\n\n if (char != lunr.QueryLexer.EOS) {\n this.backup()\n }\n}\n\nlunr.QueryLexer.prototype.more = function () {\n return this.pos < this.length\n}\n\nlunr.QueryLexer.EOS = 'EOS'\nlunr.QueryLexer.FIELD = 'FIELD'\nlunr.QueryLexer.TERM = 'TERM'\nlunr.QueryLexer.EDIT_DISTANCE = 'EDIT_DISTANCE'\nlunr.QueryLexer.BOOST = 'BOOST'\nlunr.QueryLexer.PRESENCE = 'PRESENCE'\n\nlunr.QueryLexer.lexField = function (lexer) {\n lexer.backup()\n lexer.emit(lunr.QueryLexer.FIELD)\n lexer.ignore()\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexTerm = function (lexer) {\n if (lexer.width() > 1) {\n lexer.backup()\n lexer.emit(lunr.QueryLexer.TERM)\n }\n\n lexer.ignore()\n\n if (lexer.more()) {\n return lunr.QueryLexer.lexText\n }\n}\n\nlunr.QueryLexer.lexEditDistance = function (lexer) {\n lexer.ignore()\n lexer.acceptDigitRun()\n lexer.emit(lunr.QueryLexer.EDIT_DISTANCE)\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexBoost = function (lexer) {\n lexer.ignore()\n lexer.acceptDigitRun()\n lexer.emit(lunr.QueryLexer.BOOST)\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexEOS = function (lexer) {\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n}\n\n// This matches the separator used when tokenising fields\n// within a document. These should match otherwise it is\n// not possible to search for some tokens within a document.\n//\n// It is possible for the user to change the separator on the\n// tokenizer so it _might_ clash with any other of the special\n// characters already used within the search string, e.g. :.\n//\n// This means that it is possible to change the separator in\n// such a way that makes some words unsearchable using a search\n// string.\nlunr.QueryLexer.termSeparator = lunr.tokenizer.separator\n\nlunr.QueryLexer.lexText = function (lexer) {\n while (true) {\n var char = lexer.next()\n\n if (char == lunr.QueryLexer.EOS) {\n return lunr.QueryLexer.lexEOS\n }\n\n // Escape character is '\\'\n if (char.charCodeAt(0) == 92) {\n lexer.escapeCharacter()\n continue\n }\n\n if (char == \":\") {\n return lunr.QueryLexer.lexField\n }\n\n if (char == \"~\") {\n lexer.backup()\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n return lunr.QueryLexer.lexEditDistance\n }\n\n if (char == \"^\") {\n lexer.backup()\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n return lunr.QueryLexer.lexBoost\n }\n\n // \"+\" indicates term presence is required\n // checking for length to ensure that only\n // leading \"+\" are considered\n if (char == \"+\" && lexer.width() === 1) {\n lexer.emit(lunr.QueryLexer.PRESENCE)\n return lunr.QueryLexer.lexText\n }\n\n // \"-\" indicates term presence is prohibited\n // checking for length to ensure that only\n // leading \"-\" are considered\n if (char == \"-\" && lexer.width() === 1) {\n lexer.emit(lunr.QueryLexer.PRESENCE)\n return lunr.QueryLexer.lexText\n }\n\n if (char.match(lunr.QueryLexer.termSeparator)) {\n return lunr.QueryLexer.lexTerm\n }\n }\n}\n\nlunr.QueryParser = function (str, query) {\n this.lexer = new lunr.QueryLexer (str)\n this.query = query\n this.currentClause = {}\n this.lexemeIdx = 0\n}\n\nlunr.QueryParser.prototype.parse = function () {\n this.lexer.run()\n this.lexemes = this.lexer.lexemes\n\n var state = lunr.QueryParser.parseClause\n\n while (state) {\n state = state(this)\n }\n\n return this.query\n}\n\nlunr.QueryParser.prototype.peekLexeme = function () {\n return this.lexemes[this.lexemeIdx]\n}\n\nlunr.QueryParser.prototype.consumeLexeme = function () {\n var lexeme = this.peekLexeme()\n this.lexemeIdx += 1\n return lexeme\n}\n\nlunr.QueryParser.prototype.nextClause = function () {\n var completedClause = this.currentClause\n this.query.clause(completedClause)\n this.currentClause = {}\n}\n\nlunr.QueryParser.parseClause = function (parser) {\n var lexeme = parser.peekLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n switch (lexeme.type) {\n case lunr.QueryLexer.PRESENCE:\n return lunr.QueryParser.parsePresence\n case lunr.QueryLexer.FIELD:\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expected either a field or a term, found \" + lexeme.type\n\n if (lexeme.str.length >= 1) {\n errorMessage += \" with value '\" + lexeme.str + \"'\"\n }\n\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n}\n\nlunr.QueryParser.parsePresence = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n switch (lexeme.str) {\n case \"-\":\n parser.currentClause.presence = lunr.Query.presence.PROHIBITED\n break\n case \"+\":\n parser.currentClause.presence = lunr.Query.presence.REQUIRED\n break\n default:\n var errorMessage = \"unrecognised presence operator'\" + lexeme.str + \"'\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n var errorMessage = \"expecting term or field, found nothing\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.FIELD:\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expecting term or field, found '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseField = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n if (parser.query.allFields.indexOf(lexeme.str) == -1) {\n var possibleFields = parser.query.allFields.map(function (f) { return \"'\" + f + \"'\" }).join(', '),\n errorMessage = \"unrecognised field '\" + lexeme.str + \"', possible fields: \" + possibleFields\n\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.fields = [lexeme.str]\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n var errorMessage = \"expecting term, found nothing\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expecting term, found '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseTerm = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n parser.currentClause.term = lexeme.str.toLowerCase()\n\n if (lexeme.str.indexOf(\"*\") != -1) {\n parser.currentClause.usePipeline = false\n }\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseEditDistance = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n var editDistance = parseInt(lexeme.str, 10)\n\n if (isNaN(editDistance)) {\n var errorMessage = \"edit distance must be numeric\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.editDistance = editDistance\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseBoost = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n var boost = parseInt(lexeme.str, 10)\n\n if (isNaN(boost)) {\n var errorMessage = \"boost must be numeric\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.boost = boost\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\n /**\n * export the module via AMD, CommonJS or as a browser global\n * Export code from https://github.com/umdjs/umd/blob/master/returnExports.js\n */\n ;(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(factory)\n } else if (typeof exports === 'object') {\n /**\n * Node. Does not work with strict CommonJS, but\n * only CommonJS-like enviroments that support module.exports,\n * like Node.\n */\n module.exports = factory()\n } else {\n // Browser globals (root is window)\n root.lunr = factory()\n }\n }(this, function () {\n /**\n * Just return a value to define the module export.\n * This example returns an object, but the module\n * can return a function as the exported value.\n */\n return lunr\n }))\n})();\n"],"file":"lunr.min.js"}
\ No newline at end of file
+{"version":3,"file":"lunr.min.js","sources":["../src/lunr.js"],"sourcesContent":["/**\n * moodle readme\n *\n * Lunrjs can be downloaded from https://github.com/olivernn/lunr.js. To update this library get the lunr.js file\n * from this project and replace the content below with the new content.\n */\n\n/**\n * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9\n * Copyright (C) 2020 Oliver Nightingale\n * @license MIT\n */\n\n;(function(){\n\n/**\n * A convenience function for configuring and constructing\n * a new lunr Index.\n *\n * A lunr.Builder instance is created and the pipeline setup\n * with a trimmer, stop word filter and stemmer.\n *\n * This builder object is yielded to the configuration function\n * that is passed as a parameter, allowing the list of fields\n * and other builder parameters to be customised.\n *\n * All documents _must_ be added within the passed config function.\n *\n * @example\n * var idx = lunr(function () {\n * this.field('title')\n * this.field('body')\n * this.ref('id')\n *\n * documents.forEach(function (doc) {\n * this.add(doc)\n * }, this)\n * })\n *\n * @see {@link lunr.Builder}\n * @see {@link lunr.Pipeline}\n * @see {@link lunr.trimmer}\n * @see {@link lunr.stopWordFilter}\n * @see {@link lunr.stemmer}\n * @namespace {function} lunr\n */\nvar lunr = function (config) {\n var builder = new lunr.Builder\n\n builder.pipeline.add(\n lunr.trimmer,\n lunr.stopWordFilter,\n lunr.stemmer\n )\n\n builder.searchPipeline.add(\n lunr.stemmer\n )\n\n config.call(builder, builder)\n return builder.build()\n}\n\nlunr.version = \"2.3.9\"\n/*!\n * lunr.utils\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A namespace containing utils for the rest of the lunr library\n * @namespace lunr.utils\n */\nlunr.utils = {}\n\n/**\n * Print a warning message to the console.\n *\n * @param {String} message The message to be printed.\n * @memberOf lunr.utils\n * @function\n */\nlunr.utils.warn = (function (global) {\n /* eslint-disable no-console */\n return function (message) {\n if (global.console && console.warn) {\n console.warn(message)\n }\n }\n /* eslint-enable no-console */\n})(this)\n\n/**\n * Convert an object to a string.\n *\n * In the case of `null` and `undefined` the function returns\n * the empty string, in all other cases the result of calling\n * `toString` on the passed object is returned.\n *\n * @param {Any} obj The object to convert to a string.\n * @return {String} string representation of the passed object.\n * @memberOf lunr.utils\n */\nlunr.utils.asString = function (obj) {\n if (obj === void 0 || obj === null) {\n return \"\"\n } else {\n return obj.toString()\n }\n}\n\n/**\n * Clones an object.\n *\n * Will create a copy of an existing object such that any mutations\n * on the copy cannot affect the original.\n *\n * Only shallow objects are supported, passing a nested object to this\n * function will cause a TypeError.\n *\n * Objects with primitives, and arrays of primitives are supported.\n *\n * @param {Object} obj The object to clone.\n * @return {Object} a clone of the passed object.\n * @throws {TypeError} when a nested object is passed.\n * @memberOf Utils\n */\nlunr.utils.clone = function (obj) {\n if (obj === null || obj === undefined) {\n return obj\n }\n\n var clone = Object.create(null),\n keys = Object.keys(obj)\n\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i],\n val = obj[key]\n\n if (Array.isArray(val)) {\n clone[key] = val.slice()\n continue\n }\n\n if (typeof val === 'string' ||\n typeof val === 'number' ||\n typeof val === 'boolean') {\n clone[key] = val\n continue\n }\n\n throw new TypeError(\"clone is not deep and does not support nested objects\")\n }\n\n return clone\n}\nlunr.FieldRef = function (docRef, fieldName, stringValue) {\n this.docRef = docRef\n this.fieldName = fieldName\n this._stringValue = stringValue\n}\n\nlunr.FieldRef.joiner = \"/\"\n\nlunr.FieldRef.fromString = function (s) {\n var n = s.indexOf(lunr.FieldRef.joiner)\n\n if (n === -1) {\n throw \"malformed field ref string\"\n }\n\n var fieldRef = s.slice(0, n),\n docRef = s.slice(n + 1)\n\n return new lunr.FieldRef (docRef, fieldRef, s)\n}\n\nlunr.FieldRef.prototype.toString = function () {\n if (this._stringValue == undefined) {\n this._stringValue = this.fieldName + lunr.FieldRef.joiner + this.docRef\n }\n\n return this._stringValue\n}\n/*!\n * lunr.Set\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A lunr set.\n *\n * @constructor\n */\nlunr.Set = function (elements) {\n this.elements = Object.create(null)\n\n if (elements) {\n this.length = elements.length\n\n for (var i = 0; i < this.length; i++) {\n this.elements[elements[i]] = true\n }\n } else {\n this.length = 0\n }\n}\n\n/**\n * A complete set that contains all elements.\n *\n * @static\n * @readonly\n * @type {lunr.Set}\n */\nlunr.Set.complete = {\n intersect: function (other) {\n return other\n },\n\n union: function () {\n return this\n },\n\n contains: function () {\n return true\n }\n}\n\n/**\n * An empty set that contains no elements.\n *\n * @static\n * @readonly\n * @type {lunr.Set}\n */\nlunr.Set.empty = {\n intersect: function () {\n return this\n },\n\n union: function (other) {\n return other\n },\n\n contains: function () {\n return false\n }\n}\n\n/**\n * Returns true if this set contains the specified object.\n *\n * @param {object} object - Object whose presence in this set is to be tested.\n * @returns {boolean} - True if this set contains the specified object.\n */\nlunr.Set.prototype.contains = function (object) {\n return !!this.elements[object]\n}\n\n/**\n * Returns a new set containing only the elements that are present in both\n * this set and the specified set.\n *\n * @param {lunr.Set} other - set to intersect with this set.\n * @returns {lunr.Set} a new set that is the intersection of this and the specified set.\n */\n\nlunr.Set.prototype.intersect = function (other) {\n var a, b, elements, intersection = []\n\n if (other === lunr.Set.complete) {\n return this\n }\n\n if (other === lunr.Set.empty) {\n return other\n }\n\n if (this.length < other.length) {\n a = this\n b = other\n } else {\n a = other\n b = this\n }\n\n elements = Object.keys(a.elements)\n\n for (var i = 0; i < elements.length; i++) {\n var element = elements[i]\n if (element in b.elements) {\n intersection.push(element)\n }\n }\n\n return new lunr.Set (intersection)\n}\n\n/**\n * Returns a new set combining the elements of this and the specified set.\n *\n * @param {lunr.Set} other - set to union with this set.\n * @return {lunr.Set} a new set that is the union of this and the specified set.\n */\n\nlunr.Set.prototype.union = function (other) {\n if (other === lunr.Set.complete) {\n return lunr.Set.complete\n }\n\n if (other === lunr.Set.empty) {\n return this\n }\n\n return new lunr.Set(Object.keys(this.elements).concat(Object.keys(other.elements)))\n}\n/**\n * A function to calculate the inverse document frequency for\n * a posting. This is shared between the builder and the index\n *\n * @private\n * @param {object} posting - The posting for a given term\n * @param {number} documentCount - The total number of documents.\n */\nlunr.idf = function (posting, documentCount) {\n var documentsWithTerm = 0\n\n for (var fieldName in posting) {\n if (fieldName == '_index') continue // Ignore the term index, its not a field\n documentsWithTerm += Object.keys(posting[fieldName]).length\n }\n\n var x = (documentCount - documentsWithTerm + 0.5) / (documentsWithTerm + 0.5)\n\n return Math.log(1 + Math.abs(x))\n}\n\n/**\n * A token wraps a string representation of a token\n * as it is passed through the text processing pipeline.\n *\n * @constructor\n * @param {string} [str=''] - The string token being wrapped.\n * @param {object} [metadata={}] - Metadata associated with this token.\n */\nlunr.Token = function (str, metadata) {\n this.str = str || \"\"\n this.metadata = metadata || {}\n}\n\n/**\n * Returns the token string that is being wrapped by this object.\n *\n * @returns {string}\n */\nlunr.Token.prototype.toString = function () {\n return this.str\n}\n\n/**\n * A token update function is used when updating or optionally\n * when cloning a token.\n *\n * @callback lunr.Token~updateFunction\n * @param {string} str - The string representation of the token.\n * @param {Object} metadata - All metadata associated with this token.\n */\n\n/**\n * Applies the given function to the wrapped string token.\n *\n * @example\n * token.update(function (str, metadata) {\n * return str.toUpperCase()\n * })\n *\n * @param {lunr.Token~updateFunction} fn - A function to apply to the token string.\n * @returns {lunr.Token}\n */\nlunr.Token.prototype.update = function (fn) {\n this.str = fn(this.str, this.metadata)\n return this\n}\n\n/**\n * Creates a clone of this token. Optionally a function can be\n * applied to the cloned token.\n *\n * @param {lunr.Token~updateFunction} [fn] - An optional function to apply to the cloned token.\n * @returns {lunr.Token}\n */\nlunr.Token.prototype.clone = function (fn) {\n fn = fn || function (s) { return s }\n return new lunr.Token (fn(this.str, this.metadata), this.metadata)\n}\n/*!\n * lunr.tokenizer\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A function for splitting a string into tokens ready to be inserted into\n * the search index. Uses `lunr.tokenizer.separator` to split strings, change\n * the value of this property to change how strings are split into tokens.\n *\n * This tokenizer will convert its parameter to a string by calling `toString` and\n * then will split this string on the character in `lunr.tokenizer.separator`.\n * Arrays will have their elements converted to strings and wrapped in a lunr.Token.\n *\n * Optional metadata can be passed to the tokenizer, this metadata will be cloned and\n * added as metadata to every token that is created from the object to be tokenized.\n *\n * @static\n * @param {?(string|object|object[])} obj - The object to convert into tokens\n * @param {?object} metadata - Optional metadata to associate with every token\n * @returns {lunr.Token[]}\n * @see {@link lunr.Pipeline}\n */\nlunr.tokenizer = function (obj, metadata) {\n if (obj == null || obj == undefined) {\n return []\n }\n\n if (Array.isArray(obj)) {\n return obj.map(function (t) {\n return new lunr.Token(\n lunr.utils.asString(t).toLowerCase(),\n lunr.utils.clone(metadata)\n )\n })\n }\n\n var str = obj.toString().toLowerCase(),\n len = str.length,\n tokens = []\n\n for (var sliceEnd = 0, sliceStart = 0; sliceEnd <= len; sliceEnd++) {\n var char = str.charAt(sliceEnd),\n sliceLength = sliceEnd - sliceStart\n\n if ((char.match(lunr.tokenizer.separator) || sliceEnd == len)) {\n\n if (sliceLength > 0) {\n var tokenMetadata = lunr.utils.clone(metadata) || {}\n tokenMetadata[\"position\"] = [sliceStart, sliceLength]\n tokenMetadata[\"index\"] = tokens.length\n\n tokens.push(\n new lunr.Token (\n str.slice(sliceStart, sliceEnd),\n tokenMetadata\n )\n )\n }\n\n sliceStart = sliceEnd + 1\n }\n\n }\n\n return tokens\n}\n\n/**\n * The separator used to split a string into tokens. Override this property to change the behaviour of\n * `lunr.tokenizer` behaviour when tokenizing strings. By default this splits on whitespace and hyphens.\n *\n * @static\n * @see lunr.tokenizer\n */\nlunr.tokenizer.separator = /[\\s\\-]+/\n/*!\n * lunr.Pipeline\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.Pipelines maintain an ordered list of functions to be applied to all\n * tokens in documents entering the search index and queries being ran against\n * the index.\n *\n * An instance of lunr.Index created with the lunr shortcut will contain a\n * pipeline with a stop word filter and an English language stemmer. Extra\n * functions can be added before or after either of these functions or these\n * default functions can be removed.\n *\n * When run the pipeline will call each function in turn, passing a token, the\n * index of that token in the original list of all tokens and finally a list of\n * all the original tokens.\n *\n * The output of functions in the pipeline will be passed to the next function\n * in the pipeline. To exclude a token from entering the index the function\n * should return undefined, the rest of the pipeline will not be called with\n * this token.\n *\n * For serialisation of pipelines to work, all functions used in an instance of\n * a pipeline should be registered with lunr.Pipeline. Registered functions can\n * then be loaded. If trying to load a serialised pipeline that uses functions\n * that are not registered an error will be thrown.\n *\n * If not planning on serialising the pipeline then registering pipeline functions\n * is not necessary.\n *\n * @constructor\n */\nlunr.Pipeline = function () {\n this._stack = []\n}\n\nlunr.Pipeline.registeredFunctions = Object.create(null)\n\n/**\n * A pipeline function maps lunr.Token to lunr.Token. A lunr.Token contains the token\n * string as well as all known metadata. A pipeline function can mutate the token string\n * or mutate (or add) metadata for a given token.\n *\n * A pipeline function can indicate that the passed token should be discarded by returning\n * null, undefined or an empty string. This token will not be passed to any downstream pipeline\n * functions and will not be added to the index.\n *\n * Multiple tokens can be returned by returning an array of tokens. Each token will be passed\n * to any downstream pipeline functions and all will returned tokens will be added to the index.\n *\n * Any number of pipeline functions may be chained together using a lunr.Pipeline.\n *\n * @interface lunr.PipelineFunction\n * @param {lunr.Token} token - A token from the document being processed.\n * @param {number} i - The index of this token in the complete list of tokens for this document/field.\n * @param {lunr.Token[]} tokens - All tokens for this document/field.\n * @returns {(?lunr.Token|lunr.Token[])}\n */\n\n/**\n * Register a function with the pipeline.\n *\n * Functions that are used in the pipeline should be registered if the pipeline\n * needs to be serialised, or a serialised pipeline needs to be loaded.\n *\n * Registering a function does not add it to a pipeline, functions must still be\n * added to instances of the pipeline for them to be used when running a pipeline.\n *\n * @param {lunr.PipelineFunction} fn - The function to check for.\n * @param {String} label - The label to register this function with\n */\nlunr.Pipeline.registerFunction = function (fn, label) {\n if (label in this.registeredFunctions) {\n lunr.utils.warn('Overwriting existing registered function: ' + label)\n }\n\n fn.label = label\n lunr.Pipeline.registeredFunctions[fn.label] = fn\n}\n\n/**\n * Warns if the function is not registered as a Pipeline function.\n *\n * @param {lunr.PipelineFunction} fn - The function to check for.\n * @private\n */\nlunr.Pipeline.warnIfFunctionNotRegistered = function (fn) {\n var isRegistered = fn.label && (fn.label in this.registeredFunctions)\n\n if (!isRegistered) {\n lunr.utils.warn('Function is not registered with pipeline. This may cause problems when serialising the index.\\n', fn)\n }\n}\n\n/**\n * Loads a previously serialised pipeline.\n *\n * All functions to be loaded must already be registered with lunr.Pipeline.\n * If any function from the serialised data has not been registered then an\n * error will be thrown.\n *\n * @param {Object} serialised - The serialised pipeline to load.\n * @returns {lunr.Pipeline}\n */\nlunr.Pipeline.load = function (serialised) {\n var pipeline = new lunr.Pipeline\n\n serialised.forEach(function (fnName) {\n var fn = lunr.Pipeline.registeredFunctions[fnName]\n\n if (fn) {\n pipeline.add(fn)\n } else {\n throw new Error('Cannot load unregistered function: ' + fnName)\n }\n })\n\n return pipeline\n}\n\n/**\n * Adds new functions to the end of the pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction[]} functions - Any number of functions to add to the pipeline.\n */\nlunr.Pipeline.prototype.add = function () {\n var fns = Array.prototype.slice.call(arguments)\n\n fns.forEach(function (fn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(fn)\n this._stack.push(fn)\n }, this)\n}\n\n/**\n * Adds a single function after a function that already exists in the\n * pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline.\n * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline.\n */\nlunr.Pipeline.prototype.after = function (existingFn, newFn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(newFn)\n\n var pos = this._stack.indexOf(existingFn)\n if (pos == -1) {\n throw new Error('Cannot find existingFn')\n }\n\n pos = pos + 1\n this._stack.splice(pos, 0, newFn)\n}\n\n/**\n * Adds a single function before a function that already exists in the\n * pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline.\n * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline.\n */\nlunr.Pipeline.prototype.before = function (existingFn, newFn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(newFn)\n\n var pos = this._stack.indexOf(existingFn)\n if (pos == -1) {\n throw new Error('Cannot find existingFn')\n }\n\n this._stack.splice(pos, 0, newFn)\n}\n\n/**\n * Removes a function from the pipeline.\n *\n * @param {lunr.PipelineFunction} fn The function to remove from the pipeline.\n */\nlunr.Pipeline.prototype.remove = function (fn) {\n var pos = this._stack.indexOf(fn)\n if (pos == -1) {\n return\n }\n\n this._stack.splice(pos, 1)\n}\n\n/**\n * Runs the current list of functions that make up the pipeline against the\n * passed tokens.\n *\n * @param {Array} tokens The tokens to run through the pipeline.\n * @returns {Array}\n */\nlunr.Pipeline.prototype.run = function (tokens) {\n var stackLength = this._stack.length\n\n for (var i = 0; i < stackLength; i++) {\n var fn = this._stack[i]\n var memo = []\n\n for (var j = 0; j < tokens.length; j++) {\n var result = fn(tokens[j], j, tokens)\n\n if (result === null || result === void 0 || result === '') continue\n\n if (Array.isArray(result)) {\n for (var k = 0; k < result.length; k++) {\n memo.push(result[k])\n }\n } else {\n memo.push(result)\n }\n }\n\n tokens = memo\n }\n\n return tokens\n}\n\n/**\n * Convenience method for passing a string through a pipeline and getting\n * strings out. This method takes care of wrapping the passed string in a\n * token and mapping the resulting tokens back to strings.\n *\n * @param {string} str - The string to pass through the pipeline.\n * @param {?object} metadata - Optional metadata to associate with the token\n * passed to the pipeline.\n * @returns {string[]}\n */\nlunr.Pipeline.prototype.runString = function (str, metadata) {\n var token = new lunr.Token (str, metadata)\n\n return this.run([token]).map(function (t) {\n return t.toString()\n })\n}\n\n/**\n * Resets the pipeline by removing any existing processors.\n *\n */\nlunr.Pipeline.prototype.reset = function () {\n this._stack = []\n}\n\n/**\n * Returns a representation of the pipeline ready for serialisation.\n *\n * Logs a warning if the function has not been registered.\n *\n * @returns {Array}\n */\nlunr.Pipeline.prototype.toJSON = function () {\n return this._stack.map(function (fn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(fn)\n\n return fn.label\n })\n}\n/*!\n * lunr.Vector\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A vector is used to construct the vector space of documents and queries. These\n * vectors support operations to determine the similarity between two documents or\n * a document and a query.\n *\n * Normally no parameters are required for initializing a vector, but in the case of\n * loading a previously dumped vector the raw elements can be provided to the constructor.\n *\n * For performance reasons vectors are implemented with a flat array, where an elements\n * index is immediately followed by its value. E.g. [index, value, index, value]. This\n * allows the underlying array to be as sparse as possible and still offer decent\n * performance when being used for vector calculations.\n *\n * @constructor\n * @param {Number[]} [elements] - The flat list of element index and element value pairs.\n */\nlunr.Vector = function (elements) {\n this._magnitude = 0\n this.elements = elements || []\n}\n\n\n/**\n * Calculates the position within the vector to insert a given index.\n *\n * This is used internally by insert and upsert. If there are duplicate indexes then\n * the position is returned as if the value for that index were to be updated, but it\n * is the callers responsibility to check whether there is a duplicate at that index\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @returns {Number}\n */\nlunr.Vector.prototype.positionForIndex = function (index) {\n // For an empty vector the tuple can be inserted at the beginning\n if (this.elements.length == 0) {\n return 0\n }\n\n var start = 0,\n end = this.elements.length / 2,\n sliceLength = end - start,\n pivotPoint = Math.floor(sliceLength / 2),\n pivotIndex = this.elements[pivotPoint * 2]\n\n while (sliceLength > 1) {\n if (pivotIndex < index) {\n start = pivotPoint\n }\n\n if (pivotIndex > index) {\n end = pivotPoint\n }\n\n if (pivotIndex == index) {\n break\n }\n\n sliceLength = end - start\n pivotPoint = start + Math.floor(sliceLength / 2)\n pivotIndex = this.elements[pivotPoint * 2]\n }\n\n if (pivotIndex == index) {\n return pivotPoint * 2\n }\n\n if (pivotIndex > index) {\n return pivotPoint * 2\n }\n\n if (pivotIndex < index) {\n return (pivotPoint + 1) * 2\n }\n}\n\n/**\n * Inserts an element at an index within the vector.\n *\n * Does not allow duplicates, will throw an error if there is already an entry\n * for this index.\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @param {Number} val - The value to be inserted into the vector.\n */\nlunr.Vector.prototype.insert = function (insertIdx, val) {\n this.upsert(insertIdx, val, function () {\n throw \"duplicate index\"\n })\n}\n\n/**\n * Inserts or updates an existing index within the vector.\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @param {Number} val - The value to be inserted into the vector.\n * @param {function} fn - A function that is called for updates, the existing value and the\n * requested value are passed as arguments\n */\nlunr.Vector.prototype.upsert = function (insertIdx, val, fn) {\n this._magnitude = 0\n var position = this.positionForIndex(insertIdx)\n\n if (this.elements[position] == insertIdx) {\n this.elements[position + 1] = fn(this.elements[position + 1], val)\n } else {\n this.elements.splice(position, 0, insertIdx, val)\n }\n}\n\n/**\n * Calculates the magnitude of this vector.\n *\n * @returns {Number}\n */\nlunr.Vector.prototype.magnitude = function () {\n if (this._magnitude) return this._magnitude\n\n var sumOfSquares = 0,\n elementsLength = this.elements.length\n\n for (var i = 1; i < elementsLength; i += 2) {\n var val = this.elements[i]\n sumOfSquares += val * val\n }\n\n return this._magnitude = Math.sqrt(sumOfSquares)\n}\n\n/**\n * Calculates the dot product of this vector and another vector.\n *\n * @param {lunr.Vector} otherVector - The vector to compute the dot product with.\n * @returns {Number}\n */\nlunr.Vector.prototype.dot = function (otherVector) {\n var dotProduct = 0,\n a = this.elements, b = otherVector.elements,\n aLen = a.length, bLen = b.length,\n aVal = 0, bVal = 0,\n i = 0, j = 0\n\n while (i < aLen && j < bLen) {\n aVal = a[i], bVal = b[j]\n if (aVal < bVal) {\n i += 2\n } else if (aVal > bVal) {\n j += 2\n } else if (aVal == bVal) {\n dotProduct += a[i + 1] * b[j + 1]\n i += 2\n j += 2\n }\n }\n\n return dotProduct\n}\n\n/**\n * Calculates the similarity between this vector and another vector.\n *\n * @param {lunr.Vector} otherVector - The other vector to calculate the\n * similarity with.\n * @returns {Number}\n */\nlunr.Vector.prototype.similarity = function (otherVector) {\n return this.dot(otherVector) / this.magnitude() || 0\n}\n\n/**\n * Converts the vector to an array of the elements within the vector.\n *\n * @returns {Number[]}\n */\nlunr.Vector.prototype.toArray = function () {\n var output = new Array (this.elements.length / 2)\n\n for (var i = 1, j = 0; i < this.elements.length; i += 2, j++) {\n output[j] = this.elements[i]\n }\n\n return output\n}\n\n/**\n * A JSON serializable representation of the vector.\n *\n * @returns {Number[]}\n */\nlunr.Vector.prototype.toJSON = function () {\n return this.elements\n}\n/* eslint-disable */\n/*!\n * lunr.stemmer\n * Copyright (C) 2020 Oliver Nightingale\n * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt\n */\n\n/**\n * lunr.stemmer is an english language stemmer, this is a JavaScript\n * implementation of the PorterStemmer taken from http://tartarus.org/~martin\n *\n * @static\n * @implements {lunr.PipelineFunction}\n * @param {lunr.Token} token - The string to stem\n * @returns {lunr.Token}\n * @see {@link lunr.Pipeline}\n * @function\n */\nlunr.stemmer = (function(){\n var step2list = {\n \"ational\" : \"ate\",\n \"tional\" : \"tion\",\n \"enci\" : \"ence\",\n \"anci\" : \"ance\",\n \"izer\" : \"ize\",\n \"bli\" : \"ble\",\n \"alli\" : \"al\",\n \"entli\" : \"ent\",\n \"eli\" : \"e\",\n \"ousli\" : \"ous\",\n \"ization\" : \"ize\",\n \"ation\" : \"ate\",\n \"ator\" : \"ate\",\n \"alism\" : \"al\",\n \"iveness\" : \"ive\",\n \"fulness\" : \"ful\",\n \"ousness\" : \"ous\",\n \"aliti\" : \"al\",\n \"iviti\" : \"ive\",\n \"biliti\" : \"ble\",\n \"logi\" : \"log\"\n },\n\n step3list = {\n \"icate\" : \"ic\",\n \"ative\" : \"\",\n \"alize\" : \"al\",\n \"iciti\" : \"ic\",\n \"ical\" : \"ic\",\n \"ful\" : \"\",\n \"ness\" : \"\"\n },\n\n c = \"[^aeiou]\", // consonant\n v = \"[aeiouy]\", // vowel\n C = c + \"[^aeiouy]*\", // consonant sequence\n V = v + \"[aeiou]*\", // vowel sequence\n\n mgr0 = \"^(\" + C + \")?\" + V + C, // [C]VC... is m>0\n meq1 = \"^(\" + C + \")?\" + V + C + \"(\" + V + \")?$\", // [C]VC[V] is m=1\n mgr1 = \"^(\" + C + \")?\" + V + C + V + C, // [C]VCVC... is m>1\n s_v = \"^(\" + C + \")?\" + v; // vowel in stem\n\n var re_mgr0 = new RegExp(mgr0);\n var re_mgr1 = new RegExp(mgr1);\n var re_meq1 = new RegExp(meq1);\n var re_s_v = new RegExp(s_v);\n\n var re_1a = /^(.+?)(ss|i)es$/;\n var re2_1a = /^(.+?)([^s])s$/;\n var re_1b = /^(.+?)eed$/;\n var re2_1b = /^(.+?)(ed|ing)$/;\n var re_1b_2 = /.$/;\n var re2_1b_2 = /(at|bl|iz)$/;\n var re3_1b_2 = new RegExp(\"([^aeiouylsz])\\\\1$\");\n var re4_1b_2 = new RegExp(\"^\" + C + v + \"[^aeiouwxy]$\");\n\n var re_1c = /^(.+?[^aeiou])y$/;\n var re_2 = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;\n\n var re_3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;\n\n var re_4 = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;\n var re2_4 = /^(.+?)(s|t)(ion)$/;\n\n var re_5 = /^(.+?)e$/;\n var re_5_1 = /ll$/;\n var re3_5 = new RegExp(\"^\" + C + v + \"[^aeiouwxy]$\");\n\n var porterStemmer = function porterStemmer(w) {\n var stem,\n suffix,\n firstch,\n re,\n re2,\n re3,\n re4;\n\n if (w.length < 3) { return w; }\n\n firstch = w.substr(0,1);\n if (firstch == \"y\") {\n w = firstch.toUpperCase() + w.substr(1);\n }\n\n // Step 1a\n re = re_1a\n re2 = re2_1a;\n\n if (re.test(w)) { w = w.replace(re,\"$1$2\"); }\n else if (re2.test(w)) { w = w.replace(re2,\"$1$2\"); }\n\n // Step 1b\n re = re_1b;\n re2 = re2_1b;\n if (re.test(w)) {\n var fp = re.exec(w);\n re = re_mgr0;\n if (re.test(fp[1])) {\n re = re_1b_2;\n w = w.replace(re,\"\");\n }\n } else if (re2.test(w)) {\n var fp = re2.exec(w);\n stem = fp[1];\n re2 = re_s_v;\n if (re2.test(stem)) {\n w = stem;\n re2 = re2_1b_2;\n re3 = re3_1b_2;\n re4 = re4_1b_2;\n if (re2.test(w)) { w = w + \"e\"; }\n else if (re3.test(w)) { re = re_1b_2; w = w.replace(re,\"\"); }\n else if (re4.test(w)) { w = w + \"e\"; }\n }\n }\n\n // Step 1c - replace suffix y or Y by i if preceded by a non-vowel which is not the first letter of the word (so cry -> cri, by -> by, say -> say)\n re = re_1c;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n w = stem + \"i\";\n }\n\n // Step 2\n re = re_2;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n suffix = fp[2];\n re = re_mgr0;\n if (re.test(stem)) {\n w = stem + step2list[suffix];\n }\n }\n\n // Step 3\n re = re_3;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n suffix = fp[2];\n re = re_mgr0;\n if (re.test(stem)) {\n w = stem + step3list[suffix];\n }\n }\n\n // Step 4\n re = re_4;\n re2 = re2_4;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n re = re_mgr1;\n if (re.test(stem)) {\n w = stem;\n }\n } else if (re2.test(w)) {\n var fp = re2.exec(w);\n stem = fp[1] + fp[2];\n re2 = re_mgr1;\n if (re2.test(stem)) {\n w = stem;\n }\n }\n\n // Step 5\n re = re_5;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n re = re_mgr1;\n re2 = re_meq1;\n re3 = re3_5;\n if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) {\n w = stem;\n }\n }\n\n re = re_5_1;\n re2 = re_mgr1;\n if (re.test(w) && re2.test(w)) {\n re = re_1b_2;\n w = w.replace(re,\"\");\n }\n\n // and turn initial Y back to y\n\n if (firstch == \"y\") {\n w = firstch.toLowerCase() + w.substr(1);\n }\n\n return w;\n };\n\n return function (token) {\n return token.update(porterStemmer);\n }\n})();\n\nlunr.Pipeline.registerFunction(lunr.stemmer, 'stemmer')\n/*!\n * lunr.stopWordFilter\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.generateStopWordFilter builds a stopWordFilter function from the provided\n * list of stop words.\n *\n * The built in lunr.stopWordFilter is built using this generator and can be used\n * to generate custom stopWordFilters for applications or non English languages.\n *\n * @function\n * @param {Array} token The token to pass through the filter\n * @returns {lunr.PipelineFunction}\n * @see lunr.Pipeline\n * @see lunr.stopWordFilter\n */\nlunr.generateStopWordFilter = function (stopWords) {\n var words = stopWords.reduce(function (memo, stopWord) {\n memo[stopWord] = stopWord\n return memo\n }, {})\n\n return function (token) {\n if (token && words[token.toString()] !== token.toString()) return token\n }\n}\n\n/**\n * lunr.stopWordFilter is an English language stop word list filter, any words\n * contained in the list will not be passed through the filter.\n *\n * This is intended to be used in the Pipeline. If the token does not pass the\n * filter then undefined will be returned.\n *\n * @function\n * @implements {lunr.PipelineFunction}\n * @params {lunr.Token} token - A token to check for being a stop word.\n * @returns {lunr.Token}\n * @see {@link lunr.Pipeline}\n */\nlunr.stopWordFilter = lunr.generateStopWordFilter([\n 'a',\n 'able',\n 'about',\n 'across',\n 'after',\n 'all',\n 'almost',\n 'also',\n 'am',\n 'among',\n 'an',\n 'and',\n 'any',\n 'are',\n 'as',\n 'at',\n 'be',\n 'because',\n 'been',\n 'but',\n 'by',\n 'can',\n 'cannot',\n 'could',\n 'dear',\n 'did',\n 'do',\n 'does',\n 'either',\n 'else',\n 'ever',\n 'every',\n 'for',\n 'from',\n 'get',\n 'got',\n 'had',\n 'has',\n 'have',\n 'he',\n 'her',\n 'hers',\n 'him',\n 'his',\n 'how',\n 'however',\n 'i',\n 'if',\n 'in',\n 'into',\n 'is',\n 'it',\n 'its',\n 'just',\n 'least',\n 'let',\n 'like',\n 'likely',\n 'may',\n 'me',\n 'might',\n 'most',\n 'must',\n 'my',\n 'neither',\n 'no',\n 'nor',\n 'not',\n 'of',\n 'off',\n 'often',\n 'on',\n 'only',\n 'or',\n 'other',\n 'our',\n 'own',\n 'rather',\n 'said',\n 'say',\n 'says',\n 'she',\n 'should',\n 'since',\n 'so',\n 'some',\n 'than',\n 'that',\n 'the',\n 'their',\n 'them',\n 'then',\n 'there',\n 'these',\n 'they',\n 'this',\n 'tis',\n 'to',\n 'too',\n 'twas',\n 'us',\n 'wants',\n 'was',\n 'we',\n 'were',\n 'what',\n 'when',\n 'where',\n 'which',\n 'while',\n 'who',\n 'whom',\n 'why',\n 'will',\n 'with',\n 'would',\n 'yet',\n 'you',\n 'your'\n])\n\nlunr.Pipeline.registerFunction(lunr.stopWordFilter, 'stopWordFilter')\n/*!\n * lunr.trimmer\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.trimmer is a pipeline function for trimming non word\n * characters from the beginning and end of tokens before they\n * enter the index.\n *\n * This implementation may not work correctly for non latin\n * characters and should either be removed or adapted for use\n * with languages with non-latin characters.\n *\n * @static\n * @implements {lunr.PipelineFunction}\n * @param {lunr.Token} token The token to pass through the filter\n * @returns {lunr.Token}\n * @see lunr.Pipeline\n */\nlunr.trimmer = function (token) {\n return token.update(function (s) {\n return s.replace(/^\\W+/, '').replace(/\\W+$/, '')\n })\n}\n\nlunr.Pipeline.registerFunction(lunr.trimmer, 'trimmer')\n/*!\n * lunr.TokenSet\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A token set is used to store the unique list of all tokens\n * within an index. Token sets are also used to represent an\n * incoming query to the index, this query token set and index\n * token set are then intersected to find which tokens to look\n * up in the inverted index.\n *\n * A token set can hold multiple tokens, as in the case of the\n * index token set, or it can hold a single token as in the\n * case of a simple query token set.\n *\n * Additionally token sets are used to perform wildcard matching.\n * Leading, contained and trailing wildcards are supported, and\n * from this edit distance matching can also be provided.\n *\n * Token sets are implemented as a minimal finite state automata,\n * where both common prefixes and suffixes are shared between tokens.\n * This helps to reduce the space used for storing the token set.\n *\n * @constructor\n */\nlunr.TokenSet = function () {\n this.final = false\n this.edges = {}\n this.id = lunr.TokenSet._nextId\n lunr.TokenSet._nextId += 1\n}\n\n/**\n * Keeps track of the next, auto increment, identifier to assign\n * to a new tokenSet.\n *\n * TokenSets require a unique identifier to be correctly minimised.\n *\n * @private\n */\nlunr.TokenSet._nextId = 1\n\n/**\n * Creates a TokenSet instance from the given sorted array of words.\n *\n * @param {String[]} arr - A sorted array of strings to create the set from.\n * @returns {lunr.TokenSet}\n * @throws Will throw an error if the input array is not sorted.\n */\nlunr.TokenSet.fromArray = function (arr) {\n var builder = new lunr.TokenSet.Builder\n\n for (var i = 0, len = arr.length; i < len; i++) {\n builder.insert(arr[i])\n }\n\n builder.finish()\n return builder.root\n}\n\n/**\n * Creates a token set from a query clause.\n *\n * @private\n * @param {Object} clause - A single clause from lunr.Query.\n * @param {string} clause.term - The query clause term.\n * @param {number} [clause.editDistance] - The optional edit distance for the term.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.fromClause = function (clause) {\n if ('editDistance' in clause) {\n return lunr.TokenSet.fromFuzzyString(clause.term, clause.editDistance)\n } else {\n return lunr.TokenSet.fromString(clause.term)\n }\n}\n\n/**\n * Creates a token set representing a single string with a specified\n * edit distance.\n *\n * Insertions, deletions, substitutions and transpositions are each\n * treated as an edit distance of 1.\n *\n * Increasing the allowed edit distance will have a dramatic impact\n * on the performance of both creating and intersecting these TokenSets.\n * It is advised to keep the edit distance less than 3.\n *\n * @param {string} str - The string to create the token set from.\n * @param {number} editDistance - The allowed edit distance to match.\n * @returns {lunr.Vector}\n */\nlunr.TokenSet.fromFuzzyString = function (str, editDistance) {\n var root = new lunr.TokenSet\n\n var stack = [{\n node: root,\n editsRemaining: editDistance,\n str: str\n }]\n\n while (stack.length) {\n var frame = stack.pop()\n\n // no edit\n if (frame.str.length > 0) {\n var char = frame.str.charAt(0),\n noEditNode\n\n if (char in frame.node.edges) {\n noEditNode = frame.node.edges[char]\n } else {\n noEditNode = new lunr.TokenSet\n frame.node.edges[char] = noEditNode\n }\n\n if (frame.str.length == 1) {\n noEditNode.final = true\n }\n\n stack.push({\n node: noEditNode,\n editsRemaining: frame.editsRemaining,\n str: frame.str.slice(1)\n })\n }\n\n if (frame.editsRemaining == 0) {\n continue\n }\n\n // insertion\n if (\"*\" in frame.node.edges) {\n var insertionNode = frame.node.edges[\"*\"]\n } else {\n var insertionNode = new lunr.TokenSet\n frame.node.edges[\"*\"] = insertionNode\n }\n\n if (frame.str.length == 0) {\n insertionNode.final = true\n }\n\n stack.push({\n node: insertionNode,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str\n })\n\n // deletion\n // can only do a deletion if we have enough edits remaining\n // and if there are characters left to delete in the string\n if (frame.str.length > 1) {\n stack.push({\n node: frame.node,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str.slice(1)\n })\n }\n\n // deletion\n // just removing the last character from the str\n if (frame.str.length == 1) {\n frame.node.final = true\n }\n\n // substitution\n // can only do a substitution if we have enough edits remaining\n // and if there are characters left to substitute\n if (frame.str.length >= 1) {\n if (\"*\" in frame.node.edges) {\n var substitutionNode = frame.node.edges[\"*\"]\n } else {\n var substitutionNode = new lunr.TokenSet\n frame.node.edges[\"*\"] = substitutionNode\n }\n\n if (frame.str.length == 1) {\n substitutionNode.final = true\n }\n\n stack.push({\n node: substitutionNode,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str.slice(1)\n })\n }\n\n // transposition\n // can only do a transposition if there are edits remaining\n // and there are enough characters to transpose\n if (frame.str.length > 1) {\n var charA = frame.str.charAt(0),\n charB = frame.str.charAt(1),\n transposeNode\n\n if (charB in frame.node.edges) {\n transposeNode = frame.node.edges[charB]\n } else {\n transposeNode = new lunr.TokenSet\n frame.node.edges[charB] = transposeNode\n }\n\n if (frame.str.length == 1) {\n transposeNode.final = true\n }\n\n stack.push({\n node: transposeNode,\n editsRemaining: frame.editsRemaining - 1,\n str: charA + frame.str.slice(2)\n })\n }\n }\n\n return root\n}\n\n/**\n * Creates a TokenSet from a string.\n *\n * The string may contain one or more wildcard characters (*)\n * that will allow wildcard matching when intersecting with\n * another TokenSet.\n *\n * @param {string} str - The string to create a TokenSet from.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.fromString = function (str) {\n var node = new lunr.TokenSet,\n root = node\n\n /*\n * Iterates through all characters within the passed string\n * appending a node for each character.\n *\n * When a wildcard character is found then a self\n * referencing edge is introduced to continually match\n * any number of any characters.\n */\n for (var i = 0, len = str.length; i < len; i++) {\n var char = str[i],\n final = (i == len - 1)\n\n if (char == \"*\") {\n node.edges[char] = node\n node.final = final\n\n } else {\n var next = new lunr.TokenSet\n next.final = final\n\n node.edges[char] = next\n node = next\n }\n }\n\n return root\n}\n\n/**\n * Converts this TokenSet into an array of strings\n * contained within the TokenSet.\n *\n * This is not intended to be used on a TokenSet that\n * contains wildcards, in these cases the results are\n * undefined and are likely to cause an infinite loop.\n *\n * @returns {string[]}\n */\nlunr.TokenSet.prototype.toArray = function () {\n var words = []\n\n var stack = [{\n prefix: \"\",\n node: this\n }]\n\n while (stack.length) {\n var frame = stack.pop(),\n edges = Object.keys(frame.node.edges),\n len = edges.length\n\n if (frame.node.final) {\n /* In Safari, at this point the prefix is sometimes corrupted, see:\n * https://github.com/olivernn/lunr.js/issues/279 Calling any\n * String.prototype method forces Safari to \"cast\" this string to what\n * it's supposed to be, fixing the bug. */\n frame.prefix.charAt(0)\n words.push(frame.prefix)\n }\n\n for (var i = 0; i < len; i++) {\n var edge = edges[i]\n\n stack.push({\n prefix: frame.prefix.concat(edge),\n node: frame.node.edges[edge]\n })\n }\n }\n\n return words\n}\n\n/**\n * Generates a string representation of a TokenSet.\n *\n * This is intended to allow TokenSets to be used as keys\n * in objects, largely to aid the construction and minimisation\n * of a TokenSet. As such it is not designed to be a human\n * friendly representation of the TokenSet.\n *\n * @returns {string}\n */\nlunr.TokenSet.prototype.toString = function () {\n // NOTE: Using Object.keys here as this.edges is very likely\n // to enter 'hash-mode' with many keys being added\n //\n // avoiding a for-in loop here as it leads to the function\n // being de-optimised (at least in V8). From some simple\n // benchmarks the performance is comparable, but allowing\n // V8 to optimize may mean easy performance wins in the future.\n\n if (this._str) {\n return this._str\n }\n\n var str = this.final ? '1' : '0',\n labels = Object.keys(this.edges).sort(),\n len = labels.length\n\n for (var i = 0; i < len; i++) {\n var label = labels[i],\n node = this.edges[label]\n\n str = str + label + node.id\n }\n\n return str\n}\n\n/**\n * Returns a new TokenSet that is the intersection of\n * this TokenSet and the passed TokenSet.\n *\n * This intersection will take into account any wildcards\n * contained within the TokenSet.\n *\n * @param {lunr.TokenSet} b - An other TokenSet to intersect with.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.prototype.intersect = function (b) {\n var output = new lunr.TokenSet,\n frame = undefined\n\n var stack = [{\n qNode: b,\n output: output,\n node: this\n }]\n\n while (stack.length) {\n frame = stack.pop()\n\n // NOTE: As with the #toString method, we are using\n // Object.keys and a for loop instead of a for-in loop\n // as both of these objects enter 'hash' mode, causing\n // the function to be de-optimised in V8\n var qEdges = Object.keys(frame.qNode.edges),\n qLen = qEdges.length,\n nEdges = Object.keys(frame.node.edges),\n nLen = nEdges.length\n\n for (var q = 0; q < qLen; q++) {\n var qEdge = qEdges[q]\n\n for (var n = 0; n < nLen; n++) {\n var nEdge = nEdges[n]\n\n if (nEdge == qEdge || qEdge == '*') {\n var node = frame.node.edges[nEdge],\n qNode = frame.qNode.edges[qEdge],\n final = node.final && qNode.final,\n next = undefined\n\n if (nEdge in frame.output.edges) {\n // an edge already exists for this character\n // no need to create a new node, just set the finality\n // bit unless this node is already final\n next = frame.output.edges[nEdge]\n next.final = next.final || final\n\n } else {\n // no edge exists yet, must create one\n // set the finality bit and insert it\n // into the output\n next = new lunr.TokenSet\n next.final = final\n frame.output.edges[nEdge] = next\n }\n\n stack.push({\n qNode: qNode,\n output: next,\n node: node\n })\n }\n }\n }\n }\n\n return output\n}\nlunr.TokenSet.Builder = function () {\n this.previousWord = \"\"\n this.root = new lunr.TokenSet\n this.uncheckedNodes = []\n this.minimizedNodes = {}\n}\n\nlunr.TokenSet.Builder.prototype.insert = function (word) {\n var node,\n commonPrefix = 0\n\n if (word < this.previousWord) {\n throw new Error (\"Out of order word insertion\")\n }\n\n for (var i = 0; i < word.length && i < this.previousWord.length; i++) {\n if (word[i] != this.previousWord[i]) break\n commonPrefix++\n }\n\n this.minimize(commonPrefix)\n\n if (this.uncheckedNodes.length == 0) {\n node = this.root\n } else {\n node = this.uncheckedNodes[this.uncheckedNodes.length - 1].child\n }\n\n for (var i = commonPrefix; i < word.length; i++) {\n var nextNode = new lunr.TokenSet,\n char = word[i]\n\n node.edges[char] = nextNode\n\n this.uncheckedNodes.push({\n parent: node,\n char: char,\n child: nextNode\n })\n\n node = nextNode\n }\n\n node.final = true\n this.previousWord = word\n}\n\nlunr.TokenSet.Builder.prototype.finish = function () {\n this.minimize(0)\n}\n\nlunr.TokenSet.Builder.prototype.minimize = function (downTo) {\n for (var i = this.uncheckedNodes.length - 1; i >= downTo; i--) {\n var node = this.uncheckedNodes[i],\n childKey = node.child.toString()\n\n if (childKey in this.minimizedNodes) {\n node.parent.edges[node.char] = this.minimizedNodes[childKey]\n } else {\n // Cache the key for this node since\n // we know it can't change anymore\n node.child._str = childKey\n\n this.minimizedNodes[childKey] = node.child\n }\n\n this.uncheckedNodes.pop()\n }\n}\n/*!\n * lunr.Index\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * An index contains the built index of all documents and provides a query interface\n * to the index.\n *\n * Usually instances of lunr.Index will not be created using this constructor, instead\n * lunr.Builder should be used to construct new indexes, or lunr.Index.load should be\n * used to load previously built and serialized indexes.\n *\n * @constructor\n * @param {Object} attrs - The attributes of the built search index.\n * @param {Object} attrs.invertedIndex - An index of term/field to document reference.\n * @param {Object} attrs.fieldVectors - Field vectors\n * @param {lunr.TokenSet} attrs.tokenSet - An set of all corpus tokens.\n * @param {string[]} attrs.fields - The names of indexed document fields.\n * @param {lunr.Pipeline} attrs.pipeline - The pipeline to use for search terms.\n */\nlunr.Index = function (attrs) {\n this.invertedIndex = attrs.invertedIndex\n this.fieldVectors = attrs.fieldVectors\n this.tokenSet = attrs.tokenSet\n this.fields = attrs.fields\n this.pipeline = attrs.pipeline\n}\n\n/**\n * A result contains details of a document matching a search query.\n * @typedef {Object} lunr.Index~Result\n * @property {string} ref - The reference of the document this result represents.\n * @property {number} score - A number between 0 and 1 representing how similar this document is to the query.\n * @property {lunr.MatchData} matchData - Contains metadata about this match including which term(s) caused the match.\n */\n\n/**\n * Although lunr provides the ability to create queries using lunr.Query, it also provides a simple\n * query language which itself is parsed into an instance of lunr.Query.\n *\n * For programmatically building queries it is advised to directly use lunr.Query, the query language\n * is best used for human entered text rather than program generated text.\n *\n * At its simplest queries can just be a single term, e.g. `hello`, multiple terms are also supported\n * and will be combined with OR, e.g `hello world` will match documents that contain either 'hello'\n * or 'world', though those that contain both will rank higher in the results.\n *\n * Wildcards can be included in terms to match one or more unspecified characters, these wildcards can\n * be inserted anywhere within the term, and more than one wildcard can exist in a single term. Adding\n * wildcards will increase the number of documents that will be found but can also have a negative\n * impact on query performance, especially with wildcards at the beginning of a term.\n *\n * Terms can be restricted to specific fields, e.g. `title:hello`, only documents with the term\n * hello in the title field will match this query. Using a field not present in the index will lead\n * to an error being thrown.\n *\n * Modifiers can also be added to terms, lunr supports edit distance and boost modifiers on terms. A term\n * boost will make documents matching that term score higher, e.g. `foo^5`. Edit distance is also supported\n * to provide fuzzy matching, e.g. 'hello~2' will match documents with hello with an edit distance of 2.\n * Avoid large values for edit distance to improve query performance.\n *\n * Each term also supports a presence modifier. By default a term's presence in document is optional, however\n * this can be changed to either required or prohibited. For a term's presence to be required in a document the\n * term should be prefixed with a '+', e.g. `+foo bar` is a search for documents that must contain 'foo' and\n * optionally contain 'bar'. Conversely a leading '-' sets the terms presence to prohibited, i.e. it must not\n * appear in a document, e.g. `-foo bar` is a search for documents that do not contain 'foo' but may contain 'bar'.\n *\n * To escape special characters the backslash character '\\' can be used, this allows searches to include\n * characters that would normally be considered modifiers, e.g. `foo\\~2` will search for a term \"foo~2\" instead\n * of attempting to apply a boost of 2 to the search term \"foo\".\n *\n * @typedef {string} lunr.Index~QueryString\n * @example
Simple single term query
\n * hello\n * @example
Multiple term query
\n * hello world\n * @example
term scoped to a field
\n * title:hello\n * @example
term with a boost of 10
\n * hello^10\n * @example
term with an edit distance of 2
\n * hello~2\n * @example
terms with presence modifiers
\n * -foo +bar baz\n */\n\n/**\n * Performs a search against the index using lunr query syntax.\n *\n * Results will be returned sorted by their score, the most relevant results\n * will be returned first. For details on how the score is calculated, please see\n * the {@link https://lunrjs.com/guides/searching.html#scoring|guide}.\n *\n * For more programmatic querying use lunr.Index#query.\n *\n * @param {lunr.Index~QueryString} queryString - A string containing a lunr query.\n * @throws {lunr.QueryParseError} If the passed query string cannot be parsed.\n * @returns {lunr.Index~Result[]}\n */\nlunr.Index.prototype.search = function (queryString) {\n return this.query(function (query) {\n var parser = new lunr.QueryParser(queryString, query)\n parser.parse()\n })\n}\n\n/**\n * A query builder callback provides a query object to be used to express\n * the query to perform on the index.\n *\n * @callback lunr.Index~queryBuilder\n * @param {lunr.Query} query - The query object to build up.\n * @this lunr.Query\n */\n\n/**\n * Performs a query against the index using the yielded lunr.Query object.\n *\n * If performing programmatic queries against the index, this method is preferred\n * over lunr.Index#search so as to avoid the additional query parsing overhead.\n *\n * A query object is yielded to the supplied function which should be used to\n * express the query to be run against the index.\n *\n * Note that although this function takes a callback parameter it is _not_ an\n * asynchronous operation, the callback is just yielded a query object to be\n * customized.\n *\n * @param {lunr.Index~queryBuilder} fn - A function that is used to build the query.\n * @returns {lunr.Index~Result[]}\n */\nlunr.Index.prototype.query = function (fn) {\n // for each query clause\n // * process terms\n // * expand terms from token set\n // * find matching documents and metadata\n // * get document vectors\n // * score documents\n\n var query = new lunr.Query(this.fields),\n matchingFields = Object.create(null),\n queryVectors = Object.create(null),\n termFieldCache = Object.create(null),\n requiredMatches = Object.create(null),\n prohibitedMatches = Object.create(null)\n\n /*\n * To support field level boosts a query vector is created per\n * field. An empty vector is eagerly created to support negated\n * queries.\n */\n for (var i = 0; i < this.fields.length; i++) {\n queryVectors[this.fields[i]] = new lunr.Vector\n }\n\n fn.call(query, query)\n\n for (var i = 0; i < query.clauses.length; i++) {\n /*\n * Unless the pipeline has been disabled for this term, which is\n * the case for terms with wildcards, we need to pass the clause\n * term through the search pipeline. A pipeline returns an array\n * of processed terms. Pipeline functions may expand the passed\n * term, which means we may end up performing multiple index lookups\n * for a single query term.\n */\n var clause = query.clauses[i],\n terms = null,\n clauseMatches = lunr.Set.empty\n\n if (clause.usePipeline) {\n terms = this.pipeline.runString(clause.term, {\n fields: clause.fields\n })\n } else {\n terms = [clause.term]\n }\n\n for (var m = 0; m < terms.length; m++) {\n var term = terms[m]\n\n /*\n * Each term returned from the pipeline needs to use the same query\n * clause object, e.g. the same boost and or edit distance. The\n * simplest way to do this is to re-use the clause object but mutate\n * its term property.\n */\n clause.term = term\n\n /*\n * From the term in the clause we create a token set which will then\n * be used to intersect the indexes token set to get a list of terms\n * to lookup in the inverted index\n */\n var termTokenSet = lunr.TokenSet.fromClause(clause),\n expandedTerms = this.tokenSet.intersect(termTokenSet).toArray()\n\n /*\n * If a term marked as required does not exist in the tokenSet it is\n * impossible for the search to return any matches. We set all the field\n * scoped required matches set to empty and stop examining any further\n * clauses.\n */\n if (expandedTerms.length === 0 && clause.presence === lunr.Query.presence.REQUIRED) {\n for (var k = 0; k < clause.fields.length; k++) {\n var field = clause.fields[k]\n requiredMatches[field] = lunr.Set.empty\n }\n\n break\n }\n\n for (var j = 0; j < expandedTerms.length; j++) {\n /*\n * For each term get the posting and termIndex, this is required for\n * building the query vector.\n */\n var expandedTerm = expandedTerms[j],\n posting = this.invertedIndex[expandedTerm],\n termIndex = posting._index\n\n for (var k = 0; k < clause.fields.length; k++) {\n /*\n * For each field that this query term is scoped by (by default\n * all fields are in scope) we need to get all the document refs\n * that have this term in that field.\n *\n * The posting is the entry in the invertedIndex for the matching\n * term from above.\n */\n var field = clause.fields[k],\n fieldPosting = posting[field],\n matchingDocumentRefs = Object.keys(fieldPosting),\n termField = expandedTerm + \"/\" + field,\n matchingDocumentsSet = new lunr.Set(matchingDocumentRefs)\n\n /*\n * if the presence of this term is required ensure that the matching\n * documents are added to the set of required matches for this clause.\n *\n */\n if (clause.presence == lunr.Query.presence.REQUIRED) {\n clauseMatches = clauseMatches.union(matchingDocumentsSet)\n\n if (requiredMatches[field] === undefined) {\n requiredMatches[field] = lunr.Set.complete\n }\n }\n\n /*\n * if the presence of this term is prohibited ensure that the matching\n * documents are added to the set of prohibited matches for this field,\n * creating that set if it does not yet exist.\n */\n if (clause.presence == lunr.Query.presence.PROHIBITED) {\n if (prohibitedMatches[field] === undefined) {\n prohibitedMatches[field] = lunr.Set.empty\n }\n\n prohibitedMatches[field] = prohibitedMatches[field].union(matchingDocumentsSet)\n\n /*\n * Prohibited matches should not be part of the query vector used for\n * similarity scoring and no metadata should be extracted so we continue\n * to the next field\n */\n continue\n }\n\n /*\n * The query field vector is populated using the termIndex found for\n * the term and a unit value with the appropriate boost applied.\n * Using upsert because there could already be an entry in the vector\n * for the term we are working with. In that case we just add the scores\n * together.\n */\n queryVectors[field].upsert(termIndex, clause.boost, function (a, b) { return a + b })\n\n /**\n * If we've already seen this term, field combo then we've already collected\n * the matching documents and metadata, no need to go through all that again\n */\n if (termFieldCache[termField]) {\n continue\n }\n\n for (var l = 0; l < matchingDocumentRefs.length; l++) {\n /*\n * All metadata for this term/field/document triple\n * are then extracted and collected into an instance\n * of lunr.MatchData ready to be returned in the query\n * results\n */\n var matchingDocumentRef = matchingDocumentRefs[l],\n matchingFieldRef = new lunr.FieldRef (matchingDocumentRef, field),\n metadata = fieldPosting[matchingDocumentRef],\n fieldMatch\n\n if ((fieldMatch = matchingFields[matchingFieldRef]) === undefined) {\n matchingFields[matchingFieldRef] = new lunr.MatchData (expandedTerm, field, metadata)\n } else {\n fieldMatch.add(expandedTerm, field, metadata)\n }\n\n }\n\n termFieldCache[termField] = true\n }\n }\n }\n\n /**\n * If the presence was required we need to update the requiredMatches field sets.\n * We do this after all fields for the term have collected their matches because\n * the clause terms presence is required in _any_ of the fields not _all_ of the\n * fields.\n */\n if (clause.presence === lunr.Query.presence.REQUIRED) {\n for (var k = 0; k < clause.fields.length; k++) {\n var field = clause.fields[k]\n requiredMatches[field] = requiredMatches[field].intersect(clauseMatches)\n }\n }\n }\n\n /**\n * Need to combine the field scoped required and prohibited\n * matching documents into a global set of required and prohibited\n * matches\n */\n var allRequiredMatches = lunr.Set.complete,\n allProhibitedMatches = lunr.Set.empty\n\n for (var i = 0; i < this.fields.length; i++) {\n var field = this.fields[i]\n\n if (requiredMatches[field]) {\n allRequiredMatches = allRequiredMatches.intersect(requiredMatches[field])\n }\n\n if (prohibitedMatches[field]) {\n allProhibitedMatches = allProhibitedMatches.union(prohibitedMatches[field])\n }\n }\n\n var matchingFieldRefs = Object.keys(matchingFields),\n results = [],\n matches = Object.create(null)\n\n /*\n * If the query is negated (contains only prohibited terms)\n * we need to get _all_ fieldRefs currently existing in the\n * index. This is only done when we know that the query is\n * entirely prohibited terms to avoid any cost of getting all\n * fieldRefs unnecessarily.\n *\n * Additionally, blank MatchData must be created to correctly\n * populate the results.\n */\n if (query.isNegated()) {\n matchingFieldRefs = Object.keys(this.fieldVectors)\n\n for (var i = 0; i < matchingFieldRefs.length; i++) {\n var matchingFieldRef = matchingFieldRefs[i]\n var fieldRef = lunr.FieldRef.fromString(matchingFieldRef)\n matchingFields[matchingFieldRef] = new lunr.MatchData\n }\n }\n\n for (var i = 0; i < matchingFieldRefs.length; i++) {\n /*\n * Currently we have document fields that match the query, but we\n * need to return documents. The matchData and scores are combined\n * from multiple fields belonging to the same document.\n *\n * Scores are calculated by field, using the query vectors created\n * above, and combined into a final document score using addition.\n */\n var fieldRef = lunr.FieldRef.fromString(matchingFieldRefs[i]),\n docRef = fieldRef.docRef\n\n if (!allRequiredMatches.contains(docRef)) {\n continue\n }\n\n if (allProhibitedMatches.contains(docRef)) {\n continue\n }\n\n var fieldVector = this.fieldVectors[fieldRef],\n score = queryVectors[fieldRef.fieldName].similarity(fieldVector),\n docMatch\n\n if ((docMatch = matches[docRef]) !== undefined) {\n docMatch.score += score\n docMatch.matchData.combine(matchingFields[fieldRef])\n } else {\n var match = {\n ref: docRef,\n score: score,\n matchData: matchingFields[fieldRef]\n }\n matches[docRef] = match\n results.push(match)\n }\n }\n\n /*\n * Sort the results objects by score, highest first.\n */\n return results.sort(function (a, b) {\n return b.score - a.score\n })\n}\n\n/**\n * Prepares the index for JSON serialization.\n *\n * The schema for this JSON blob will be described in a\n * separate JSON schema file.\n *\n * @returns {Object}\n */\nlunr.Index.prototype.toJSON = function () {\n var invertedIndex = Object.keys(this.invertedIndex)\n .sort()\n .map(function (term) {\n return [term, this.invertedIndex[term]]\n }, this)\n\n var fieldVectors = Object.keys(this.fieldVectors)\n .map(function (ref) {\n return [ref, this.fieldVectors[ref].toJSON()]\n }, this)\n\n return {\n version: lunr.version,\n fields: this.fields,\n fieldVectors: fieldVectors,\n invertedIndex: invertedIndex,\n pipeline: this.pipeline.toJSON()\n }\n}\n\n/**\n * Loads a previously serialized lunr.Index\n *\n * @param {Object} serializedIndex - A previously serialized lunr.Index\n * @returns {lunr.Index}\n */\nlunr.Index.load = function (serializedIndex) {\n var attrs = {},\n fieldVectors = {},\n serializedVectors = serializedIndex.fieldVectors,\n invertedIndex = Object.create(null),\n serializedInvertedIndex = serializedIndex.invertedIndex,\n tokenSetBuilder = new lunr.TokenSet.Builder,\n pipeline = lunr.Pipeline.load(serializedIndex.pipeline)\n\n if (serializedIndex.version != lunr.version) {\n lunr.utils.warn(\"Version mismatch when loading serialised index. Current version of lunr '\" + lunr.version + \"' does not match serialized index '\" + serializedIndex.version + \"'\")\n }\n\n for (var i = 0; i < serializedVectors.length; i++) {\n var tuple = serializedVectors[i],\n ref = tuple[0],\n elements = tuple[1]\n\n fieldVectors[ref] = new lunr.Vector(elements)\n }\n\n for (var i = 0; i < serializedInvertedIndex.length; i++) {\n var tuple = serializedInvertedIndex[i],\n term = tuple[0],\n posting = tuple[1]\n\n tokenSetBuilder.insert(term)\n invertedIndex[term] = posting\n }\n\n tokenSetBuilder.finish()\n\n attrs.fields = serializedIndex.fields\n\n attrs.fieldVectors = fieldVectors\n attrs.invertedIndex = invertedIndex\n attrs.tokenSet = tokenSetBuilder.root\n attrs.pipeline = pipeline\n\n return new lunr.Index(attrs)\n}\n/*!\n * lunr.Builder\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.Builder performs indexing on a set of documents and\n * returns instances of lunr.Index ready for querying.\n *\n * All configuration of the index is done via the builder, the\n * fields to index, the document reference, the text processing\n * pipeline and document scoring parameters are all set on the\n * builder before indexing.\n *\n * @constructor\n * @property {string} _ref - Internal reference to the document reference field.\n * @property {string[]} _fields - Internal reference to the document fields to index.\n * @property {object} invertedIndex - The inverted index maps terms to document fields.\n * @property {object} documentTermFrequencies - Keeps track of document term frequencies.\n * @property {object} documentLengths - Keeps track of the length of documents added to the index.\n * @property {lunr.tokenizer} tokenizer - Function for splitting strings into tokens for indexing.\n * @property {lunr.Pipeline} pipeline - The pipeline performs text processing on tokens before indexing.\n * @property {lunr.Pipeline} searchPipeline - A pipeline for processing search terms before querying the index.\n * @property {number} documentCount - Keeps track of the total number of documents indexed.\n * @property {number} _b - A parameter to control field length normalization, setting this to 0 disabled normalization, 1 fully normalizes field lengths, the default value is 0.75.\n * @property {number} _k1 - A parameter to control how quickly an increase in term frequency results in term frequency saturation, the default value is 1.2.\n * @property {number} termIndex - A counter incremented for each unique term, used to identify a terms position in the vector space.\n * @property {array} metadataWhitelist - A list of metadata keys that have been whitelisted for entry in the index.\n */\nlunr.Builder = function () {\n this._ref = \"id\"\n this._fields = Object.create(null)\n this._documents = Object.create(null)\n this.invertedIndex = Object.create(null)\n this.fieldTermFrequencies = {}\n this.fieldLengths = {}\n this.tokenizer = lunr.tokenizer\n this.pipeline = new lunr.Pipeline\n this.searchPipeline = new lunr.Pipeline\n this.documentCount = 0\n this._b = 0.75\n this._k1 = 1.2\n this.termIndex = 0\n this.metadataWhitelist = []\n}\n\n/**\n * Sets the document field used as the document reference. Every document must have this field.\n * The type of this field in the document should be a string, if it is not a string it will be\n * coerced into a string by calling toString.\n *\n * The default ref is 'id'.\n *\n * The ref should _not_ be changed during indexing, it should be set before any documents are\n * added to the index. Changing it during indexing can lead to inconsistent results.\n *\n * @param {string} ref - The name of the reference field in the document.\n */\nlunr.Builder.prototype.ref = function (ref) {\n this._ref = ref\n}\n\n/**\n * A function that is used to extract a field from a document.\n *\n * Lunr expects a field to be at the top level of a document, if however the field\n * is deeply nested within a document an extractor function can be used to extract\n * the right field for indexing.\n *\n * @callback fieldExtractor\n * @param {object} doc - The document being added to the index.\n * @returns {?(string|object|object[])} obj - The object that will be indexed for this field.\n * @example
Extracting a nested field
\n * function (doc) { return doc.nested.field }\n */\n\n/**\n * Adds a field to the list of document fields that will be indexed. Every document being\n * indexed should have this field. Null values for this field in indexed documents will\n * not cause errors but will limit the chance of that document being retrieved by searches.\n *\n * All fields should be added before adding documents to the index. Adding fields after\n * a document has been indexed will have no effect on already indexed documents.\n *\n * Fields can be boosted at build time. This allows terms within that field to have more\n * importance when ranking search results. Use a field boost to specify that matches within\n * one field are more important than other fields.\n *\n * @param {string} fieldName - The name of a field to index in all documents.\n * @param {object} attributes - Optional attributes associated with this field.\n * @param {number} [attributes.boost=1] - Boost applied to all terms within this field.\n * @param {fieldExtractor} [attributes.extractor] - Function to extract a field from a document.\n * @throws {RangeError} fieldName cannot contain unsupported characters '/'\n */\nlunr.Builder.prototype.field = function (fieldName, attributes) {\n if (/\\//.test(fieldName)) {\n throw new RangeError (\"Field '\" + fieldName + \"' contains illegal character '/'\")\n }\n\n this._fields[fieldName] = attributes || {}\n}\n\n/**\n * A parameter to tune the amount of field length normalisation that is applied when\n * calculating relevance scores. A value of 0 will completely disable any normalisation\n * and a value of 1 will fully normalise field lengths. The default is 0.75. Values of b\n * will be clamped to the range 0 - 1.\n *\n * @param {number} number - The value to set for this tuning parameter.\n */\nlunr.Builder.prototype.b = function (number) {\n if (number < 0) {\n this._b = 0\n } else if (number > 1) {\n this._b = 1\n } else {\n this._b = number\n }\n}\n\n/**\n * A parameter that controls the speed at which a rise in term frequency results in term\n * frequency saturation. The default value is 1.2. Setting this to a higher value will give\n * slower saturation levels, a lower value will result in quicker saturation.\n *\n * @param {number} number - The value to set for this tuning parameter.\n */\nlunr.Builder.prototype.k1 = function (number) {\n this._k1 = number\n}\n\n/**\n * Adds a document to the index.\n *\n * Before adding fields to the index the index should have been fully setup, with the document\n * ref and all fields to index already having been specified.\n *\n * The document must have a field name as specified by the ref (by default this is 'id') and\n * it should have all fields defined for indexing, though null or undefined values will not\n * cause errors.\n *\n * Entire documents can be boosted at build time. Applying a boost to a document indicates that\n * this document should rank higher in search results than other documents.\n *\n * @param {object} doc - The document to add to the index.\n * @param {object} attributes - Optional attributes associated with this document.\n * @param {number} [attributes.boost=1] - Boost applied to all terms within this document.\n */\nlunr.Builder.prototype.add = function (doc, attributes) {\n var docRef = doc[this._ref],\n fields = Object.keys(this._fields)\n\n this._documents[docRef] = attributes || {}\n this.documentCount += 1\n\n for (var i = 0; i < fields.length; i++) {\n var fieldName = fields[i],\n extractor = this._fields[fieldName].extractor,\n field = extractor ? extractor(doc) : doc[fieldName],\n tokens = this.tokenizer(field, {\n fields: [fieldName]\n }),\n terms = this.pipeline.run(tokens),\n fieldRef = new lunr.FieldRef (docRef, fieldName),\n fieldTerms = Object.create(null)\n\n this.fieldTermFrequencies[fieldRef] = fieldTerms\n this.fieldLengths[fieldRef] = 0\n\n // store the length of this field for this document\n this.fieldLengths[fieldRef] += terms.length\n\n // calculate term frequencies for this field\n for (var j = 0; j < terms.length; j++) {\n var term = terms[j]\n\n if (fieldTerms[term] == undefined) {\n fieldTerms[term] = 0\n }\n\n fieldTerms[term] += 1\n\n // add to inverted index\n // create an initial posting if one doesn't exist\n if (this.invertedIndex[term] == undefined) {\n var posting = Object.create(null)\n posting[\"_index\"] = this.termIndex\n this.termIndex += 1\n\n for (var k = 0; k < fields.length; k++) {\n posting[fields[k]] = Object.create(null)\n }\n\n this.invertedIndex[term] = posting\n }\n\n // add an entry for this term/fieldName/docRef to the invertedIndex\n if (this.invertedIndex[term][fieldName][docRef] == undefined) {\n this.invertedIndex[term][fieldName][docRef] = Object.create(null)\n }\n\n // store all whitelisted metadata about this token in the\n // inverted index\n for (var l = 0; l < this.metadataWhitelist.length; l++) {\n var metadataKey = this.metadataWhitelist[l],\n metadata = term.metadata[metadataKey]\n\n if (this.invertedIndex[term][fieldName][docRef][metadataKey] == undefined) {\n this.invertedIndex[term][fieldName][docRef][metadataKey] = []\n }\n\n this.invertedIndex[term][fieldName][docRef][metadataKey].push(metadata)\n }\n }\n\n }\n}\n\n/**\n * Calculates the average document length for this index\n *\n * @private\n */\nlunr.Builder.prototype.calculateAverageFieldLengths = function () {\n\n var fieldRefs = Object.keys(this.fieldLengths),\n numberOfFields = fieldRefs.length,\n accumulator = {},\n documentsWithField = {}\n\n for (var i = 0; i < numberOfFields; i++) {\n var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]),\n field = fieldRef.fieldName\n\n documentsWithField[field] || (documentsWithField[field] = 0)\n documentsWithField[field] += 1\n\n accumulator[field] || (accumulator[field] = 0)\n accumulator[field] += this.fieldLengths[fieldRef]\n }\n\n var fields = Object.keys(this._fields)\n\n for (var i = 0; i < fields.length; i++) {\n var fieldName = fields[i]\n accumulator[fieldName] = accumulator[fieldName] / documentsWithField[fieldName]\n }\n\n this.averageFieldLength = accumulator\n}\n\n/**\n * Builds a vector space model of every document using lunr.Vector\n *\n * @private\n */\nlunr.Builder.prototype.createFieldVectors = function () {\n var fieldVectors = {},\n fieldRefs = Object.keys(this.fieldTermFrequencies),\n fieldRefsLength = fieldRefs.length,\n termIdfCache = Object.create(null)\n\n for (var i = 0; i < fieldRefsLength; i++) {\n var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]),\n fieldName = fieldRef.fieldName,\n fieldLength = this.fieldLengths[fieldRef],\n fieldVector = new lunr.Vector,\n termFrequencies = this.fieldTermFrequencies[fieldRef],\n terms = Object.keys(termFrequencies),\n termsLength = terms.length\n\n\n var fieldBoost = this._fields[fieldName].boost || 1,\n docBoost = this._documents[fieldRef.docRef].boost || 1\n\n for (var j = 0; j < termsLength; j++) {\n var term = terms[j],\n tf = termFrequencies[term],\n termIndex = this.invertedIndex[term]._index,\n idf, score, scoreWithPrecision\n\n if (termIdfCache[term] === undefined) {\n idf = lunr.idf(this.invertedIndex[term], this.documentCount)\n termIdfCache[term] = idf\n } else {\n idf = termIdfCache[term]\n }\n\n score = idf * ((this._k1 + 1) * tf) / (this._k1 * (1 - this._b + this._b * (fieldLength / this.averageFieldLength[fieldName])) + tf)\n score *= fieldBoost\n score *= docBoost\n scoreWithPrecision = Math.round(score * 1000) / 1000\n // Converts 1.23456789 to 1.234.\n // Reducing the precision so that the vectors take up less\n // space when serialised. Doing it now so that they behave\n // the same before and after serialisation. Also, this is\n // the fastest approach to reducing a number's precision in\n // JavaScript.\n\n fieldVector.insert(termIndex, scoreWithPrecision)\n }\n\n fieldVectors[fieldRef] = fieldVector\n }\n\n this.fieldVectors = fieldVectors\n}\n\n/**\n * Creates a token set of all tokens in the index using lunr.TokenSet\n *\n * @private\n */\nlunr.Builder.prototype.createTokenSet = function () {\n this.tokenSet = lunr.TokenSet.fromArray(\n Object.keys(this.invertedIndex).sort()\n )\n}\n\n/**\n * Builds the index, creating an instance of lunr.Index.\n *\n * This completes the indexing process and should only be called\n * once all documents have been added to the index.\n *\n * @returns {lunr.Index}\n */\nlunr.Builder.prototype.build = function () {\n this.calculateAverageFieldLengths()\n this.createFieldVectors()\n this.createTokenSet()\n\n return new lunr.Index({\n invertedIndex: this.invertedIndex,\n fieldVectors: this.fieldVectors,\n tokenSet: this.tokenSet,\n fields: Object.keys(this._fields),\n pipeline: this.searchPipeline\n })\n}\n\n/**\n * Applies a plugin to the index builder.\n *\n * A plugin is a function that is called with the index builder as its context.\n * Plugins can be used to customise or extend the behaviour of the index\n * in some way. A plugin is just a function, that encapsulated the custom\n * behaviour that should be applied when building the index.\n *\n * The plugin function will be called with the index builder as its argument, additional\n * arguments can also be passed when calling use. The function will be called\n * with the index builder as its context.\n *\n * @param {Function} plugin The plugin to apply.\n */\nlunr.Builder.prototype.use = function (fn) {\n var args = Array.prototype.slice.call(arguments, 1)\n args.unshift(this)\n fn.apply(this, args)\n}\n/**\n * Contains and collects metadata about a matching document.\n * A single instance of lunr.MatchData is returned as part of every\n * lunr.Index~Result.\n *\n * @constructor\n * @param {string} term - The term this match data is associated with\n * @param {string} field - The field in which the term was found\n * @param {object} metadata - The metadata recorded about this term in this field\n * @property {object} metadata - A cloned collection of metadata associated with this document.\n * @see {@link lunr.Index~Result}\n */\nlunr.MatchData = function (term, field, metadata) {\n var clonedMetadata = Object.create(null),\n metadataKeys = Object.keys(metadata || {})\n\n // Cloning the metadata to prevent the original\n // being mutated during match data combination.\n // Metadata is kept in an array within the inverted\n // index so cloning the data can be done with\n // Array#slice\n for (var i = 0; i < metadataKeys.length; i++) {\n var key = metadataKeys[i]\n clonedMetadata[key] = metadata[key].slice()\n }\n\n this.metadata = Object.create(null)\n\n if (term !== undefined) {\n this.metadata[term] = Object.create(null)\n this.metadata[term][field] = clonedMetadata\n }\n}\n\n/**\n * An instance of lunr.MatchData will be created for every term that matches a\n * document. However only one instance is required in a lunr.Index~Result. This\n * method combines metadata from another instance of lunr.MatchData with this\n * objects metadata.\n *\n * @param {lunr.MatchData} otherMatchData - Another instance of match data to merge with this one.\n * @see {@link lunr.Index~Result}\n */\nlunr.MatchData.prototype.combine = function (otherMatchData) {\n var terms = Object.keys(otherMatchData.metadata)\n\n for (var i = 0; i < terms.length; i++) {\n var term = terms[i],\n fields = Object.keys(otherMatchData.metadata[term])\n\n if (this.metadata[term] == undefined) {\n this.metadata[term] = Object.create(null)\n }\n\n for (var j = 0; j < fields.length; j++) {\n var field = fields[j],\n keys = Object.keys(otherMatchData.metadata[term][field])\n\n if (this.metadata[term][field] == undefined) {\n this.metadata[term][field] = Object.create(null)\n }\n\n for (var k = 0; k < keys.length; k++) {\n var key = keys[k]\n\n if (this.metadata[term][field][key] == undefined) {\n this.metadata[term][field][key] = otherMatchData.metadata[term][field][key]\n } else {\n this.metadata[term][field][key] = this.metadata[term][field][key].concat(otherMatchData.metadata[term][field][key])\n }\n\n }\n }\n }\n}\n\n/**\n * Add metadata for a term/field pair to this instance of match data.\n *\n * @param {string} term - The term this match data is associated with\n * @param {string} field - The field in which the term was found\n * @param {object} metadata - The metadata recorded about this term in this field\n */\nlunr.MatchData.prototype.add = function (term, field, metadata) {\n if (!(term in this.metadata)) {\n this.metadata[term] = Object.create(null)\n this.metadata[term][field] = metadata\n return\n }\n\n if (!(field in this.metadata[term])) {\n this.metadata[term][field] = metadata\n return\n }\n\n var metadataKeys = Object.keys(metadata)\n\n for (var i = 0; i < metadataKeys.length; i++) {\n var key = metadataKeys[i]\n\n if (key in this.metadata[term][field]) {\n this.metadata[term][field][key] = this.metadata[term][field][key].concat(metadata[key])\n } else {\n this.metadata[term][field][key] = metadata[key]\n }\n }\n}\n/**\n * A lunr.Query provides a programmatic way of defining queries to be performed\n * against a {@link lunr.Index}.\n *\n * Prefer constructing a lunr.Query using the {@link lunr.Index#query} method\n * so the query object is pre-initialized with the right index fields.\n *\n * @constructor\n * @property {lunr.Query~Clause[]} clauses - An array of query clauses.\n * @property {string[]} allFields - An array of all available fields in a lunr.Index.\n */\nlunr.Query = function (allFields) {\n this.clauses = []\n this.allFields = allFields\n}\n\n/**\n * Constants for indicating what kind of automatic wildcard insertion will be used when constructing a query clause.\n *\n * This allows wildcards to be added to the beginning and end of a term without having to manually do any string\n * concatenation.\n *\n * The wildcard constants can be bitwise combined to select both leading and trailing wildcards.\n *\n * @constant\n * @default\n * @property {number} wildcard.NONE - The term will have no wildcards inserted, this is the default behaviour\n * @property {number} wildcard.LEADING - Prepend the term with a wildcard, unless a leading wildcard already exists\n * @property {number} wildcard.TRAILING - Append a wildcard to the term, unless a trailing wildcard already exists\n * @see lunr.Query~Clause\n * @see lunr.Query#clause\n * @see lunr.Query#term\n * @example
\n * query.term('foo', {\n * wildcard: lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING\n * })\n */\n\nlunr.Query.wildcard = new String (\"*\")\nlunr.Query.wildcard.NONE = 0\nlunr.Query.wildcard.LEADING = 1\nlunr.Query.wildcard.TRAILING = 2\n\n/**\n * Constants for indicating what kind of presence a term must have in matching documents.\n *\n * @constant\n * @enum {number}\n * @see lunr.Query~Clause\n * @see lunr.Query#clause\n * @see lunr.Query#term\n * @example
query term with required presence
\n * query.term('foo', { presence: lunr.Query.presence.REQUIRED })\n */\nlunr.Query.presence = {\n /**\n * Term's presence in a document is optional, this is the default value.\n */\n OPTIONAL: 1,\n\n /**\n * Term's presence in a document is required, documents that do not contain\n * this term will not be returned.\n */\n REQUIRED: 2,\n\n /**\n * Term's presence in a document is prohibited, documents that do contain\n * this term will not be returned.\n */\n PROHIBITED: 3\n}\n\n/**\n * A single clause in a {@link lunr.Query} contains a term and details on how to\n * match that term against a {@link lunr.Index}.\n *\n * @typedef {Object} lunr.Query~Clause\n * @property {string[]} fields - The fields in an index this clause should be matched against.\n * @property {number} [boost=1] - Any boost that should be applied when matching this clause.\n * @property {number} [editDistance] - Whether the term should have fuzzy matching applied, and how fuzzy the match should be.\n * @property {boolean} [usePipeline] - Whether the term should be passed through the search pipeline.\n * @property {number} [wildcard=lunr.Query.wildcard.NONE] - Whether the term should have wildcards appended or prepended.\n * @property {number} [presence=lunr.Query.presence.OPTIONAL] - The terms presence in any matching documents.\n */\n\n/**\n * Adds a {@link lunr.Query~Clause} to this query.\n *\n * Unless the clause contains the fields to be matched all fields will be matched. In addition\n * a default boost of 1 is applied to the clause.\n *\n * @param {lunr.Query~Clause} clause - The clause to add to this query.\n * @see lunr.Query~Clause\n * @returns {lunr.Query}\n */\nlunr.Query.prototype.clause = function (clause) {\n if (!('fields' in clause)) {\n clause.fields = this.allFields\n }\n\n if (!('boost' in clause)) {\n clause.boost = 1\n }\n\n if (!('usePipeline' in clause)) {\n clause.usePipeline = true\n }\n\n if (!('wildcard' in clause)) {\n clause.wildcard = lunr.Query.wildcard.NONE\n }\n\n if ((clause.wildcard & lunr.Query.wildcard.LEADING) && (clause.term.charAt(0) != lunr.Query.wildcard)) {\n clause.term = \"*\" + clause.term\n }\n\n if ((clause.wildcard & lunr.Query.wildcard.TRAILING) && (clause.term.slice(-1) != lunr.Query.wildcard)) {\n clause.term = \"\" + clause.term + \"*\"\n }\n\n if (!('presence' in clause)) {\n clause.presence = lunr.Query.presence.OPTIONAL\n }\n\n this.clauses.push(clause)\n\n return this\n}\n\n/**\n * A negated query is one in which every clause has a presence of\n * prohibited. These queries require some special processing to return\n * the expected results.\n *\n * @returns boolean\n */\nlunr.Query.prototype.isNegated = function () {\n for (var i = 0; i < this.clauses.length; i++) {\n if (this.clauses[i].presence != lunr.Query.presence.PROHIBITED) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Adds a term to the current query, under the covers this will create a {@link lunr.Query~Clause}\n * to the list of clauses that make up this query.\n *\n * The term is used as is, i.e. no tokenization will be performed by this method. Instead conversion\n * to a token or token-like string should be done before calling this method.\n *\n * The term will be converted to a string by calling `toString`. Multiple terms can be passed as an\n * array, each term in the array will share the same options.\n *\n * @param {object|object[]} term - The term(s) to add to the query.\n * @param {object} [options] - Any additional properties to add to the query clause.\n * @returns {lunr.Query}\n * @see lunr.Query#clause\n * @see lunr.Query~Clause\n * @example
adding a single term to a query
\n * query.term(\"foo\")\n * @example
adding a single term to a query and specifying search fields, term boost and automatic trailing wildcard
using lunr.tokenizer to convert a string to tokens before using them as terms
\n * query.term(lunr.tokenizer(\"foo bar\"))\n */\nlunr.Query.prototype.term = function (term, options) {\n if (Array.isArray(term)) {\n term.forEach(function (t) { this.term(t, lunr.utils.clone(options)) }, this)\n return this\n }\n\n var clause = options || {}\n clause.term = term.toString()\n\n this.clause(clause)\n\n return this\n}\nlunr.QueryParseError = function (message, start, end) {\n this.name = \"QueryParseError\"\n this.message = message\n this.start = start\n this.end = end\n}\n\nlunr.QueryParseError.prototype = new Error\nlunr.QueryLexer = function (str) {\n this.lexemes = []\n this.str = str\n this.length = str.length\n this.pos = 0\n this.start = 0\n this.escapeCharPositions = []\n}\n\nlunr.QueryLexer.prototype.run = function () {\n var state = lunr.QueryLexer.lexText\n\n while (state) {\n state = state(this)\n }\n}\n\nlunr.QueryLexer.prototype.sliceString = function () {\n var subSlices = [],\n sliceStart = this.start,\n sliceEnd = this.pos\n\n for (var i = 0; i < this.escapeCharPositions.length; i++) {\n sliceEnd = this.escapeCharPositions[i]\n subSlices.push(this.str.slice(sliceStart, sliceEnd))\n sliceStart = sliceEnd + 1\n }\n\n subSlices.push(this.str.slice(sliceStart, this.pos))\n this.escapeCharPositions.length = 0\n\n return subSlices.join('')\n}\n\nlunr.QueryLexer.prototype.emit = function (type) {\n this.lexemes.push({\n type: type,\n str: this.sliceString(),\n start: this.start,\n end: this.pos\n })\n\n this.start = this.pos\n}\n\nlunr.QueryLexer.prototype.escapeCharacter = function () {\n this.escapeCharPositions.push(this.pos - 1)\n this.pos += 1\n}\n\nlunr.QueryLexer.prototype.next = function () {\n if (this.pos >= this.length) {\n return lunr.QueryLexer.EOS\n }\n\n var char = this.str.charAt(this.pos)\n this.pos += 1\n return char\n}\n\nlunr.QueryLexer.prototype.width = function () {\n return this.pos - this.start\n}\n\nlunr.QueryLexer.prototype.ignore = function () {\n if (this.start == this.pos) {\n this.pos += 1\n }\n\n this.start = this.pos\n}\n\nlunr.QueryLexer.prototype.backup = function () {\n this.pos -= 1\n}\n\nlunr.QueryLexer.prototype.acceptDigitRun = function () {\n var char, charCode\n\n do {\n char = this.next()\n charCode = char.charCodeAt(0)\n } while (charCode > 47 && charCode < 58)\n\n if (char != lunr.QueryLexer.EOS) {\n this.backup()\n }\n}\n\nlunr.QueryLexer.prototype.more = function () {\n return this.pos < this.length\n}\n\nlunr.QueryLexer.EOS = 'EOS'\nlunr.QueryLexer.FIELD = 'FIELD'\nlunr.QueryLexer.TERM = 'TERM'\nlunr.QueryLexer.EDIT_DISTANCE = 'EDIT_DISTANCE'\nlunr.QueryLexer.BOOST = 'BOOST'\nlunr.QueryLexer.PRESENCE = 'PRESENCE'\n\nlunr.QueryLexer.lexField = function (lexer) {\n lexer.backup()\n lexer.emit(lunr.QueryLexer.FIELD)\n lexer.ignore()\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexTerm = function (lexer) {\n if (lexer.width() > 1) {\n lexer.backup()\n lexer.emit(lunr.QueryLexer.TERM)\n }\n\n lexer.ignore()\n\n if (lexer.more()) {\n return lunr.QueryLexer.lexText\n }\n}\n\nlunr.QueryLexer.lexEditDistance = function (lexer) {\n lexer.ignore()\n lexer.acceptDigitRun()\n lexer.emit(lunr.QueryLexer.EDIT_DISTANCE)\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexBoost = function (lexer) {\n lexer.ignore()\n lexer.acceptDigitRun()\n lexer.emit(lunr.QueryLexer.BOOST)\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexEOS = function (lexer) {\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n}\n\n// This matches the separator used when tokenising fields\n// within a document. These should match otherwise it is\n// not possible to search for some tokens within a document.\n//\n// It is possible for the user to change the separator on the\n// tokenizer so it _might_ clash with any other of the special\n// characters already used within the search string, e.g. :.\n//\n// This means that it is possible to change the separator in\n// such a way that makes some words unsearchable using a search\n// string.\nlunr.QueryLexer.termSeparator = lunr.tokenizer.separator\n\nlunr.QueryLexer.lexText = function (lexer) {\n while (true) {\n var char = lexer.next()\n\n if (char == lunr.QueryLexer.EOS) {\n return lunr.QueryLexer.lexEOS\n }\n\n // Escape character is '\\'\n if (char.charCodeAt(0) == 92) {\n lexer.escapeCharacter()\n continue\n }\n\n if (char == \":\") {\n return lunr.QueryLexer.lexField\n }\n\n if (char == \"~\") {\n lexer.backup()\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n return lunr.QueryLexer.lexEditDistance\n }\n\n if (char == \"^\") {\n lexer.backup()\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n return lunr.QueryLexer.lexBoost\n }\n\n // \"+\" indicates term presence is required\n // checking for length to ensure that only\n // leading \"+\" are considered\n if (char == \"+\" && lexer.width() === 1) {\n lexer.emit(lunr.QueryLexer.PRESENCE)\n return lunr.QueryLexer.lexText\n }\n\n // \"-\" indicates term presence is prohibited\n // checking for length to ensure that only\n // leading \"-\" are considered\n if (char == \"-\" && lexer.width() === 1) {\n lexer.emit(lunr.QueryLexer.PRESENCE)\n return lunr.QueryLexer.lexText\n }\n\n if (char.match(lunr.QueryLexer.termSeparator)) {\n return lunr.QueryLexer.lexTerm\n }\n }\n}\n\nlunr.QueryParser = function (str, query) {\n this.lexer = new lunr.QueryLexer (str)\n this.query = query\n this.currentClause = {}\n this.lexemeIdx = 0\n}\n\nlunr.QueryParser.prototype.parse = function () {\n this.lexer.run()\n this.lexemes = this.lexer.lexemes\n\n var state = lunr.QueryParser.parseClause\n\n while (state) {\n state = state(this)\n }\n\n return this.query\n}\n\nlunr.QueryParser.prototype.peekLexeme = function () {\n return this.lexemes[this.lexemeIdx]\n}\n\nlunr.QueryParser.prototype.consumeLexeme = function () {\n var lexeme = this.peekLexeme()\n this.lexemeIdx += 1\n return lexeme\n}\n\nlunr.QueryParser.prototype.nextClause = function () {\n var completedClause = this.currentClause\n this.query.clause(completedClause)\n this.currentClause = {}\n}\n\nlunr.QueryParser.parseClause = function (parser) {\n var lexeme = parser.peekLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n switch (lexeme.type) {\n case lunr.QueryLexer.PRESENCE:\n return lunr.QueryParser.parsePresence\n case lunr.QueryLexer.FIELD:\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expected either a field or a term, found \" + lexeme.type\n\n if (lexeme.str.length >= 1) {\n errorMessage += \" with value '\" + lexeme.str + \"'\"\n }\n\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n}\n\nlunr.QueryParser.parsePresence = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n switch (lexeme.str) {\n case \"-\":\n parser.currentClause.presence = lunr.Query.presence.PROHIBITED\n break\n case \"+\":\n parser.currentClause.presence = lunr.Query.presence.REQUIRED\n break\n default:\n var errorMessage = \"unrecognised presence operator'\" + lexeme.str + \"'\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n var errorMessage = \"expecting term or field, found nothing\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.FIELD:\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expecting term or field, found '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseField = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n if (parser.query.allFields.indexOf(lexeme.str) == -1) {\n var possibleFields = parser.query.allFields.map(function (f) { return \"'\" + f + \"'\" }).join(', '),\n errorMessage = \"unrecognised field '\" + lexeme.str + \"', possible fields: \" + possibleFields\n\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.fields = [lexeme.str]\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n var errorMessage = \"expecting term, found nothing\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expecting term, found '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseTerm = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n parser.currentClause.term = lexeme.str.toLowerCase()\n\n if (lexeme.str.indexOf(\"*\") != -1) {\n parser.currentClause.usePipeline = false\n }\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseEditDistance = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n var editDistance = parseInt(lexeme.str, 10)\n\n if (isNaN(editDistance)) {\n var errorMessage = \"edit distance must be numeric\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.editDistance = editDistance\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseBoost = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n var boost = parseInt(lexeme.str, 10)\n\n if (isNaN(boost)) {\n var errorMessage = \"boost must be numeric\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.boost = boost\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\n /**\n * export the module via AMD, CommonJS or as a browser global\n * Export code from https://github.com/umdjs/umd/blob/master/returnExports.js\n */\n ;(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(factory)\n } else if (typeof exports === 'object') {\n /**\n * Node. Does not work with strict CommonJS, but\n * only CommonJS-like enviroments that support module.exports,\n * like Node.\n */\n module.exports = factory()\n } else {\n // Browser globals (root is window)\n root.lunr = factory()\n }\n }(this, function () {\n /**\n * Just return a value to define the module export.\n * This example returns an object, but the module\n * can return a function as the exported value.\n */\n return lunr\n }))\n})();\n"],"names":["global","step2list","step3list","v","C","re_mgr0","re_mgr1","re_meq1","re_s_v","re_1a","re2_1a","re_1b","re2_1b","re_1b_2","re2_1b_2","re3_1b_2","re4_1b_2","re_1c","re_2","re_3","re_4","re2_4","re_5","re_5_1","re3_5","porterStemmer","root","factory","lunr","config","builder","Builder","pipeline","add","trimmer","stopWordFilter","stemmer","searchPipeline","call","build","version","utils","warn","this","message","console","asString","obj","toString","clone","Object","create","keys","i","length","key","val","Array","isArray","slice","TypeError","FieldRef","docRef","fieldName","stringValue","_stringValue","joiner","fromString","s","n","indexOf","fieldRef","prototype","undefined","Set","elements","complete","intersect","other","union","contains","empty","object","a","b","intersection","element","push","concat","idf","posting","documentCount","documentsWithTerm","x","Math","log","abs","Token","str","metadata","update","fn","tokenizer","map","t","toLowerCase","len","tokens","sliceEnd","sliceStart","sliceLength","charAt","match","separator","tokenMetadata","Pipeline","_stack","registeredFunctions","registerFunction","label","warnIfFunctionNotRegistered","load","serialised","forEach","fnName","Error","fns","arguments","after","existingFn","newFn","pos","splice","before","remove","run","stackLength","memo","j","result","k","runString","token","reset","toJSON","Vector","_magnitude","positionForIndex","index","start","end","pivotPoint","floor","pivotIndex","insert","insertIdx","upsert","position","magnitude","sumOfSquares","elementsLength","sqrt","dot","otherVector","dotProduct","aLen","bLen","aVal","bVal","similarity","toArray","output","c","RegExp","w","stem","suffix","firstch","re","re2","re3","re4","substr","toUpperCase","test","replace","fp","exec","generateStopWordFilter","stopWords","words","reduce","stopWord","TokenSet","final","edges","id","_nextId","fromArray","arr","finish","fromClause","clause","fromFuzzyString","term","editDistance","stack","node","editsRemaining","frame","pop","noEditNode","char","insertionNode","substitutionNode","transposeNode","charA","charB","next","prefix","edge","_str","labels","sort","qNode","qEdges","qLen","nEdges","nLen","q","qEdge","nEdge","previousWord","uncheckedNodes","minimizedNodes","word","commonPrefix","minimize","child","nextNode","parent","downTo","childKey","Index","attrs","invertedIndex","fieldVectors","tokenSet","fields","search","queryString","query","QueryParser","parse","Query","matchingFields","queryVectors","termFieldCache","requiredMatches","prohibitedMatches","clauses","terms","clauseMatches","usePipeline","m","termTokenSet","expandedTerms","presence","REQUIRED","field","expandedTerm","termIndex","_index","fieldPosting","matchingDocumentRefs","termField","matchingDocumentsSet","PROHIBITED","boost","l","fieldMatch","matchingDocumentRef","matchingFieldRef","MatchData","allRequiredMatches","allProhibitedMatches","matchingFieldRefs","results","matches","isNegated","docMatch","fieldVector","score","matchData","combine","ref","serializedIndex","serializedVectors","serializedInvertedIndex","tokenSetBuilder","tuple","_ref","_fields","_documents","fieldTermFrequencies","fieldLengths","_b","_k1","metadataWhitelist","attributes","RangeError","number","k1","doc","extractor","fieldTerms","metadataKey","calculateAverageFieldLengths","fieldRefs","numberOfFields","accumulator","documentsWithField","averageFieldLength","createFieldVectors","fieldRefsLength","termIdfCache","fieldLength","termFrequencies","termsLength","fieldBoost","docBoost","scoreWithPrecision","tf","round","createTokenSet","use","args","unshift","apply","clonedMetadata","metadataKeys","otherMatchData","allFields","wildcard","String","NONE","LEADING","TRAILING","OPTIONAL","options","QueryParseError","name","QueryLexer","lexemes","escapeCharPositions","state","lexText","sliceString","subSlices","join","emit","type","escapeCharacter","EOS","width","ignore","backup","acceptDigitRun","charCode","charCodeAt","more","FIELD","TERM","EDIT_DISTANCE","BOOST","PRESENCE","lexField","lexer","lexTerm","lexEditDistance","lexBoost","lexEOS","termSeparator","currentClause","lexemeIdx","parseClause","peekLexeme","consumeLexeme","lexeme","nextClause","completedClause","parser","parsePresence","parseField","parseTerm","errorMessage","nextLexeme","possibleFields","f","parseEditDistance","parseBoost","parseInt","isNaN","define","amd","exports","module"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/mustache.min.js b/admin/tool/componentlibrary/amd/build/mustache.min.js
index 88e2e53d339..571732f1afc 100644
--- a/admin/tool/componentlibrary/amd/build/mustache.min.js
+++ b/admin/tool/componentlibrary/amd/build/mustache.min.js
@@ -1,2 +1,10 @@
-define ("tool_componentlibrary/mustache",["exports","tool_componentlibrary/selectors","core/ajax","core/config","core/templates","core/log","core/notification"],function(a,b,c,d,e,f,g){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.mustache=void 0;b=h(b);c=h(c);d=h(d);e=h(e);f=h(f);g=h(g);function h(a){return a&&a.__esModule?a:{default:a}}function i(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 j(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){i(h,d,e,f,g,"next",a)}function g(a){i(h,d,e,f,g,"throw",a)}f(void 0)})}}var k=function(){var a=j(regeneratorRuntime.mark(function a(c,d,g){var h,i,j,k;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:try{g=JSON.parse(g)}catch(a){f.default.debug("Could not parse json example context for template.");f.default.debug(a)}a.next=3;return e.default.renderForPromise(d,g);case 3:h=a.sent;i=h.html;j=h.js;k=c.querySelector(b.default.mustacherendered);a.next=9;return e.default.replaceNodeContents(k,i,j);case 9:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}(),l=function(a){var e=a.querySelector(b.default.mustachesource),f=a.querySelector(b.default.mustachecontext),h=a.dataset.template,i=a.querySelector(b.default.mustacherawcontext).textContent,j=h.split("/"),l=j.shift(),m=j.join("/"),n={methodname:"core_output_load_template",args:{component:l,template:m,themename:d.default.theme,includecomments:!0}};c.default.call([n])[0].done(function(b){e.textContent=b;if(!i){var c=b.match(/Example context \(json\):([\s\S]+?)(}})/);i=c[1];var d=document.createElement("pre");d.innerHTML=JSON.stringify(JSON.parse(i),null,4);f.parentNode.appendChild(d);f.classList.add("d-none")}k(a,h,i)}).fail(g.default.exception)},m=function(){document.querySelectorAll(b.default.mustachecode).forEach(function(a){l(a)})};a.mustache=m});
-//# sourceMappingURL=mustache.min.js.map
+define("tool_componentlibrary/mustache",["exports","tool_componentlibrary/selectors","core/ajax","core/config","core/templates","core/log","core/notification"],(function(_exports,_selectors,_ajax,_config,_templates,_log,_notification){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
+/**
+ * Render mustache template examples within the component library.
+ *
+ * @module tool_componentlibrary/mustache
+ * @copyright 2021 Bas Brands
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.mustache=void 0,_selectors=_interopRequireDefault(_selectors),_ajax=_interopRequireDefault(_ajax),_config=_interopRequireDefault(_config),_templates=_interopRequireDefault(_templates),_log=_interopRequireDefault(_log),_notification=_interopRequireDefault(_notification);const loadTemplate=container=>{const sourcecontainer=container.querySelector(_selectors.default.mustachesource),contextcontainer=container.querySelector(_selectors.default.mustachecontext),templateName=container.dataset.template;let context=container.querySelector(_selectors.default.mustacherawcontext).textContent;const parts=templateName.split("/"),request={methodname:"core_output_load_template",args:{component:parts.shift(),template:parts.join("/"),themename:_config.default.theme,includecomments:!0}};_ajax.default.call([request])[0].done((source=>{if(sourcecontainer.textContent=source,!context){const example=source.match(/Example context \(json\):([\s\S]+?)(}})/);context=example[1];const precontainer=document.createElement("pre");precontainer.innerHTML=JSON.stringify(JSON.parse(context),null,4),contextcontainer.parentNode.appendChild(precontainer),contextcontainer.classList.add("d-none")}(async(container,templateName,context)=>{try{context=JSON.parse(context)}catch(e){_log.default.debug("Could not parse json example context for template."),_log.default.debug(e)}const{html:html,js:js}=await _templates.default.renderForPromise(templateName,context),rendercontainer=container.querySelector(_selectors.default.mustacherendered);await _templates.default.replaceNodeContents(rendercontainer,html,js)})(container,templateName,context)})).fail(_notification.default.exception)};_exports.mustache=()=>{document.querySelectorAll(_selectors.default.mustachecode).forEach((container=>{loadTemplate(container)}))}}));
+
+//# sourceMappingURL=mustache.min.js.map
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/mustache.min.js.map b/admin/tool/componentlibrary/amd/build/mustache.min.js.map
index a7b69afaf6c..3e3fa85e215 100644
--- a/admin/tool/componentlibrary/amd/build/mustache.min.js.map
+++ b/admin/tool/componentlibrary/amd/build/mustache.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/mustache.js"],"names":["renderTemplate","container","templateName","context","JSON","parse","e","Log","debug","Templates","renderForPromise","html","js","rendercontainer","querySelector","selectors","mustacherendered","replaceNodeContents","loadTemplate","sourcecontainer","mustachesource","contextcontainer","mustachecontext","dataset","template","mustacherawcontext","textContent","parts","split","component","shift","name","join","request","methodname","args","themename","Config","theme","includecomments","Ajax","call","done","source","example","match","precontainer","document","createElement","innerHTML","stringify","parentNode","appendChild","classList","add","fail","Notification","exception","mustache","querySelectorAll","mustachecode","forEach"],"mappings":"yQAuBA,OACA,OACA,OACA,OACA,OACA,O,qXAWMA,CAAAA,CAAc,4CAAG,WAAMC,CAAN,CAAiBC,CAAjB,CAA+BC,CAA/B,+FACnB,GAAI,CACAA,CAAO,CAAGC,IAAI,CAACC,KAAL,CAAWF,CAAX,CACb,CAAC,MAAOG,CAAP,CAAU,CACRC,UAAIC,KAAJ,CAAU,oDAAV,EACAD,UAAIC,KAAJ,CAAUF,CAAV,CACH,CANkB,eAQMG,WAAUC,gBAAV,CAA2BR,CAA3B,CAAyCC,CAAzC,CARN,iBAQZQ,CARY,GAQZA,IARY,CAQNC,CARM,GAQNA,EARM,CAUbC,CAVa,CAUKZ,CAAS,CAACa,aAAV,CAAwBC,UAAUC,gBAAlC,CAVL,gBAabP,WAAUQ,mBAAV,CAA8BJ,CAA9B,CAA+CF,CAA/C,CAAqDC,CAArD,CAba,yCAAH,uD,CAuBdM,CAAY,CAAG,SAAAjB,CAAS,CAAI,IACpBkB,CAAAA,CAAe,CAAGlB,CAAS,CAACa,aAAV,CAAwBC,UAAUK,cAAlC,CADE,CAEpBC,CAAgB,CAAGpB,CAAS,CAACa,aAAV,CAAwBC,UAAUO,eAAlC,CAFC,CAGpBpB,CAAY,CAAGD,CAAS,CAACsB,OAAV,CAAkBC,QAHb,CAItBrB,CAAO,CAAGF,CAAS,CAACa,aAAV,CAAwBC,UAAUU,kBAAlC,EAAsDC,WAJ1C,CAMpBC,CAAK,CAAGzB,CAAY,CAAC0B,KAAb,CAAmB,GAAnB,CANY,CAOpBC,CAAS,CAAGF,CAAK,CAACG,KAAN,EAPQ,CAQpBC,CAAI,CAAGJ,CAAK,CAACK,IAAN,CAAW,GAAX,CARa,CAUpBC,CAAO,CAAG,CACZC,UAAU,CAAE,2BADA,CAEZC,IAAI,CAAE,CACFN,SAAS,CAAEA,CADT,CAEFL,QAAQ,CAAEO,CAFR,CAGFK,SAAS,CAAEC,UAAOC,KAHhB,CAIFC,eAAe,GAJb,CAFM,CAVU,CAoB1BC,UAAKC,IAAL,CAAU,CAACR,CAAD,CAAV,EAAqB,CAArB,EACKS,IADL,CACU,SAACC,CAAD,CAAY,CAEdxB,CAAe,CAACO,WAAhB,CAA8BiB,CAA9B,CACA,GAAI,CAACxC,CAAL,CAAc,CACV,GAAMyC,CAAAA,CAAO,CAAGD,CAAM,CAACE,KAAP,CAAa,yCAAb,CAAhB,CACA1C,CAAO,CAAGyC,CAAO,CAAC,CAAD,CAAjB,CAEA,GAAME,CAAAA,CAAY,CAAGC,QAAQ,CAACC,aAAT,CAAuB,KAAvB,CAArB,CACAF,CAAY,CAACG,SAAb,CAAyB7C,IAAI,CAAC8C,SAAL,CAAe9C,IAAI,CAACC,KAAL,CAAWF,CAAX,CAAf,CAAoC,IAApC,CAA0C,CAA1C,CAAzB,CACAkB,CAAgB,CAAC8B,UAAjB,CAA4BC,WAA5B,CAAwCN,CAAxC,EACAzB,CAAgB,CAACgC,SAAjB,CAA2BC,GAA3B,CAA+B,QAA/B,CACH,CACDtD,CAAc,CAACC,CAAD,CAAYC,CAAZ,CAA0BC,CAA1B,CACjB,CAdL,EAeKoD,IAfL,CAeUC,UAAaC,SAfvB,CAgBP,C,CAOYC,CAAQ,CAAG,UAAM,CAC1BX,QAAQ,CAACY,gBAAT,CAA0B5C,UAAU6C,YAApC,EAAkDC,OAAlD,CAA0D,SAAC5D,CAAD,CAAe,CACrEiB,CAAY,CAACjB,CAAD,CACf,CAFD,CAGH,C","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 .\n\n/**\n * Render mustache template examples within the component library.\n *\n * @module tool_componentlibrary/mustache\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport selectors from 'tool_componentlibrary/selectors';\nimport Ajax from 'core/ajax';\nimport Config from 'core/config';\nimport Templates from 'core/templates';\nimport Log from 'core/log';\nimport Notification from 'core/notification';\n\n/**\n * Handle a template loaded response.\n *\n * @method\n * @private\n * @param {String} container The template container\n * @param {String} templateName The template name\n * @param {String} context Data for the template.\n */\nconst renderTemplate = async(container, templateName, context) => {\n try {\n context = JSON.parse(context);\n } catch (e) {\n Log.debug('Could not parse json example context for template.');\n Log.debug(e);\n }\n\n const {html, js} = await Templates.renderForPromise(templateName, context);\n\n const rendercontainer = container.querySelector(selectors.mustacherendered);\n\n // Load the rendered content in the renderer tab.\n await Templates.replaceNodeContents(rendercontainer, html, js);\n};\n\n/**\n * Load the a template source from Moodle.\n *\n * @method\n * @private\n * @param {String} container The template container\n */\nconst loadTemplate = container => {\n const sourcecontainer = container.querySelector(selectors.mustachesource);\n const contextcontainer = container.querySelector(selectors.mustachecontext);\n const templateName = container.dataset.template;\n let context = container.querySelector(selectors.mustacherawcontext).textContent;\n\n const parts = templateName.split('/');\n const component = parts.shift();\n const name = parts.join('/');\n\n const request = {\n methodname: 'core_output_load_template',\n args: {\n component: component,\n template: name,\n themename: Config.theme,\n includecomments: true\n }\n };\n\n Ajax.call([request])[0]\n .done((source) => {\n // Load the source template in Template tab.\n sourcecontainer.textContent = source;\n if (!context) {\n const example = source.match(/Example context \\(json\\):([\\s\\S]+?)(}})/);\n context = example[1];\n // Load the variables in the Variables tab.\n const precontainer = document.createElement(\"pre\");\n precontainer.innerHTML = JSON.stringify(JSON.parse(context), null, 4);\n contextcontainer.parentNode.appendChild(precontainer);\n contextcontainer.classList.add('d-none');\n }\n renderTemplate(container, templateName, context);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Initialize the module.\n *\n * @method\n */\nexport const mustache = () => {\n document.querySelectorAll(selectors.mustachecode).forEach((container) => {\n loadTemplate(container);\n });\n};\n"],"file":"mustache.min.js"}
\ No newline at end of file
+{"version":3,"file":"mustache.min.js","sources":["../src/mustache.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 .\n\n/**\n * Render mustache template examples within the component library.\n *\n * @module tool_componentlibrary/mustache\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport selectors from 'tool_componentlibrary/selectors';\nimport Ajax from 'core/ajax';\nimport Config from 'core/config';\nimport Templates from 'core/templates';\nimport Log from 'core/log';\nimport Notification from 'core/notification';\n\n/**\n * Handle a template loaded response.\n *\n * @method\n * @private\n * @param {String} container The template container\n * @param {String} templateName The template name\n * @param {String} context Data for the template.\n */\nconst renderTemplate = async(container, templateName, context) => {\n try {\n context = JSON.parse(context);\n } catch (e) {\n Log.debug('Could not parse json example context for template.');\n Log.debug(e);\n }\n\n const {html, js} = await Templates.renderForPromise(templateName, context);\n\n const rendercontainer = container.querySelector(selectors.mustacherendered);\n\n // Load the rendered content in the renderer tab.\n await Templates.replaceNodeContents(rendercontainer, html, js);\n};\n\n/**\n * Load the a template source from Moodle.\n *\n * @method\n * @private\n * @param {String} container The template container\n */\nconst loadTemplate = container => {\n const sourcecontainer = container.querySelector(selectors.mustachesource);\n const contextcontainer = container.querySelector(selectors.mustachecontext);\n const templateName = container.dataset.template;\n let context = container.querySelector(selectors.mustacherawcontext).textContent;\n\n const parts = templateName.split('/');\n const component = parts.shift();\n const name = parts.join('/');\n\n const request = {\n methodname: 'core_output_load_template',\n args: {\n component: component,\n template: name,\n themename: Config.theme,\n includecomments: true\n }\n };\n\n Ajax.call([request])[0]\n .done((source) => {\n // Load the source template in Template tab.\n sourcecontainer.textContent = source;\n if (!context) {\n const example = source.match(/Example context \\(json\\):([\\s\\S]+?)(}})/);\n context = example[1];\n // Load the variables in the Variables tab.\n const precontainer = document.createElement(\"pre\");\n precontainer.innerHTML = JSON.stringify(JSON.parse(context), null, 4);\n contextcontainer.parentNode.appendChild(precontainer);\n contextcontainer.classList.add('d-none');\n }\n renderTemplate(container, templateName, context);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Initialize the module.\n *\n * @method\n */\nexport const mustache = () => {\n document.querySelectorAll(selectors.mustachecode).forEach((container) => {\n loadTemplate(container);\n });\n};\n"],"names":["loadTemplate","container","sourcecontainer","querySelector","selectors","mustachesource","contextcontainer","mustachecontext","templateName","dataset","template","context","mustacherawcontext","textContent","parts","split","request","methodname","args","component","shift","join","themename","Config","theme","includecomments","call","done","source","example","match","precontainer","document","createElement","innerHTML","JSON","stringify","parse","parentNode","appendChild","classList","add","async","e","debug","html","js","Templates","renderForPromise","rendercontainer","mustacherendered","replaceNodeContents","renderTemplate","fail","Notification","exception","querySelectorAll","mustachecode","forEach"],"mappings":";;;;;;;0VA8DMA,aAAeC,kBACPC,gBAAkBD,UAAUE,cAAcC,mBAAUC,gBACpDC,iBAAmBL,UAAUE,cAAcC,mBAAUG,iBACrDC,aAAeP,UAAUQ,QAAQC,aACnCC,QAAUV,UAAUE,cAAcC,mBAAUQ,oBAAoBC,kBAE9DC,MAAQN,aAAaO,MAAM,KAI3BC,QAAU,CACZC,WAAY,4BACZC,KAAM,CACFC,UANUL,MAAMM,QAOhBV,SANKI,MAAMO,KAAK,KAOhBC,UAAWC,gBAAOC,MAClBC,iBAAiB,kBAIpBC,KAAK,CAACV,UAAU,GAChBW,MAAMC,YAEH1B,gBAAgBW,YAAce,QACzBjB,QAAS,OACJkB,QAAUD,OAAOE,MAAM,2CAC7BnB,QAAUkB,QAAQ,SAEZE,aAAeC,SAASC,cAAc,OAC5CF,aAAaG,UAAYC,KAAKC,UAAUD,KAAKE,MAAM1B,SAAU,KAAM,GACnEL,iBAAiBgC,WAAWC,YAAYR,cACxCzB,iBAAiBkC,UAAUC,IAAI,UAtD5BC,OAAMzC,UAAWO,aAAcG,eAE9CA,QAAUwB,KAAKE,MAAM1B,SACvB,MAAOgC,gBACDC,MAAM,mEACNA,MAAMD,SAGRE,KAACA,KAADC,GAAOA,UAAYC,mBAAUC,iBAAiBxC,aAAcG,SAE5DsC,gBAAkBhD,UAAUE,cAAcC,mBAAU8C,wBAGpDH,mBAAUI,oBAAoBF,gBAAiBJ,KAAMC,KA2C/CM,CAAenD,UAAWO,aAAcG,YAE3C0C,KAAKC,sBAAaC,8BAQP,KACpBvB,SAASwB,iBAAiBpD,mBAAUqD,cAAcC,SAASzD,YACvDD,aAAaC"}
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/search.min.js b/admin/tool/componentlibrary/amd/build/search.min.js
index 19b9ac47361..94280efb0d9 100644
--- a/admin/tool/componentlibrary/amd/build/search.min.js
+++ b/admin/tool/componentlibrary/amd/build/search.min.js
@@ -1,2 +1,10 @@
-define ("tool_componentlibrary/search",["exports","tool_componentlibrary/lunr","tool_componentlibrary/selectors","core/log","core/notification","core/key_codes"],function(a,b,c,d,e,f){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.search=void 0;b=g(b);c=g(c);d=g(d);e=g(e);function g(a){return a&&a.__esModule?a:{default:a}}function h(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 i(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var i=a.apply(b,c);function f(a){h(i,d,e,f,g,"next",a)}function g(a){h(i,d,e,f,g,"throw",a)}f(void 0)})}}var j=null,k=null,l=function(){var a=i(regeneratorRuntime.mark(function a(b){var c;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:a.next=2;return fetch(b);case 2:c=a.sent;if(!c.ok){d.default.debug("Error getting Hugo index file: ".concat(c.status))}a.next=6;return c.json();case 6:return a.abrupt("return",a.sent);case 7:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}(),m=function(a){l(a).then(function(a){k=a;j=(0,b.default)(function(){var b=this;this.ref("uri");this.field("title",{boost:10});this.field("content");this.field("tags",{boost:5});a.forEach(function(a){b.add(a)})});return null}).catch(e.default.exception)},n=function(){var a=document.querySelector(c.default.searchinput);a.addEventListener("keyup",function(a){var b=a.currentTarget.value;if(2>b.length){document.querySelector(c.default.dropdownmenu).classList.remove("show");return}p(o(b))});a.addEventListener("keydown",function(b){if(b.keyCode===f.enter){b.preventDefault()}if(b.keyCode===f.escape){a.value=""}})},o=function(a){return j.search(a+" "+a+"*").map(function(a){return k.filter(function(b){return b.uri===a.ref})[0]})},p=function(a){var b=document.querySelector(c.default.dropdownmenu);if(!a.length){b.classList.remove("show");return}b.innerHTML="";var d=M.cfg.wwwroot+"/admin/tool/componentlibrary/docspage.php";a.slice(0,10).forEach(function(a){var c=document.createElement("a"),e=a.uri.split("/")[1];c.appendChild(document.createTextNode("".concat(e," > ").concat(a.title)));c.classList.add("dropdown-item");c.href=d+a.uri;b.appendChild(c)});b.classList.add("show")};a.search=function search(a){m(a);n()}});
-//# sourceMappingURL=search.min.js.map
+define("tool_componentlibrary/search",["exports","tool_componentlibrary/lunr","tool_componentlibrary/selectors","core/log","core/notification","core/key_codes"],(function(_exports,_lunr,_selectors,_log,_notification,_key_codes){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
+/**
+ * Interface to the Lunr search engines.
+ *
+ * @module tool_componentlibrary/search
+ * @copyright 2021 Bas Brands
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.search=void 0,_lunr=_interopRequireDefault(_lunr),_selectors=_interopRequireDefault(_selectors),_log=_interopRequireDefault(_log),_notification=_interopRequireDefault(_notification);let lunrIndex=null,pagesIndex=null;const initLunr=jsonFile=>{(async jsonFile=>{const response=await fetch(jsonFile);return response.ok||_log.default.debug("Error getting Hugo index file: ".concat(response.status)),await response.json()})(jsonFile).then((jsondata=>(pagesIndex=jsondata,lunrIndex=(0,_lunr.default)((function(){this.ref("uri"),this.field("title",{boost:10}),this.field("content"),this.field("tags",{boost:5}),jsondata.forEach((p=>{this.add(p)}))})),null))).catch(_notification.default.exception)},searchIndex=query=>lunrIndex.search(query+" "+query+"*").map((result=>pagesIndex.filter((page=>page.uri===result.ref))[0])),renderResults=results=>{const dropdownMenu=document.querySelector(_selectors.default.dropdownmenu);if(!results.length)return void dropdownMenu.classList.remove("show");dropdownMenu.innerHTML="";const baseUrl=M.cfg.wwwroot+"/admin/tool/componentlibrary/docspage.php";results.slice(0,10).forEach((function(result){const link=document.createElement("a"),chapter=result.uri.split("/")[1];link.appendChild(document.createTextNode("".concat(chapter," > ").concat(result.title))),link.classList.add("dropdown-item"),link.href=baseUrl+result.uri,dropdownMenu.appendChild(link)})),dropdownMenu.classList.add("show")};_exports.search=jsonFile=>{initLunr(jsonFile),(()=>{const searchInput=document.querySelector(_selectors.default.searchinput);searchInput.addEventListener("keyup",(e=>{const query=e.currentTarget.value;query.length<2?document.querySelector(_selectors.default.dropdownmenu).classList.remove("show"):renderResults(searchIndex(query))})),searchInput.addEventListener("keydown",(e=>{e.keyCode===_key_codes.enter&&e.preventDefault(),e.keyCode===_key_codes.escape&&(searchInput.value="")}))})()}}));
+
+//# sourceMappingURL=search.min.js.map
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/search.min.js.map b/admin/tool/componentlibrary/amd/build/search.min.js.map
index b3ff1293d90..82b9e5a4a44 100644
--- a/admin/tool/componentlibrary/amd/build/search.min.js.map
+++ b/admin/tool/componentlibrary/amd/build/search.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/search.js"],"names":["lunrIndex","pagesIndex","fetchJson","jsonFile","fetch","response","ok","Log","debug","status","json","initLunr","then","jsondata","ref","field","boost","forEach","p","add","catch","Notification","exception","initUI","searchInput","document","querySelector","selectors","searchinput","addEventListener","e","query","currentTarget","value","length","dropdownmenu","classList","remove","renderResults","searchIndex","keyCode","enter","preventDefault","escape","search","map","result","filter","page","uri","results","dropdownMenu","innerHTML","baseUrl","M","cfg","wwwroot","slice","link","createElement","chapter","split","appendChild","createTextNode","title","href"],"mappings":"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","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 .\n\n/**\n * Interface to the Lunr search engines.\n *\n * @module tool_componentlibrary/search\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport lunrJs from 'tool_componentlibrary/lunr';\nimport selectors from 'tool_componentlibrary/selectors';\nimport Log from 'core/log';\nimport Notification from 'core/notification';\nimport {enter, escape} from 'core/key_codes';\n\nlet lunrIndex = null;\nlet pagesIndex = null;\n\n/**\n * Get the jsonFile that is generated when the component library is build.\n *\n * @method\n * @private\n * @param {String} jsonFile the URL to the json file.\n * @return {Object}\n */\nconst fetchJson = async(jsonFile) => {\n const response = await fetch(jsonFile);\n\n if (!response.ok) {\n Log.debug(`Error getting Hugo index file: ${response.status}`);\n }\n\n return await response.json();\n};\n\n/**\n * Initiate lunr on the data in the jsonFile and add the jsondata to the pagesIndex\n *\n * @method\n * @private\n * @param {String} jsonFile the URL to the json file.\n */\nconst initLunr = jsonFile => {\n fetchJson(jsonFile).then(jsondata => {\n pagesIndex = jsondata;\n // Using an arrow function here will break lunr on compile.\n lunrIndex = lunrJs(function() {\n this.ref('uri');\n this.field('title', {boost: 10});\n this.field('content');\n this.field('tags', {boost: 5});\n jsondata.forEach(p => {\n this.add(p);\n });\n });\n return null;\n }).catch(Notification.exception);\n};\n\n/**\n * Setup the eventlistener to listen on user input on the search field.\n *\n * @method\n * @private\n */\nconst initUI = () => {\n const searchInput = document.querySelector(selectors.searchinput);\n searchInput.addEventListener('keyup', e => {\n const query = e.currentTarget.value;\n if (query.length < 2) {\n document.querySelector(selectors.dropdownmenu).classList.remove('show');\n return;\n }\n renderResults(searchIndex(query));\n });\n searchInput.addEventListener('keydown', e => {\n if (e.keyCode === enter) {\n e.preventDefault();\n }\n if (e.keyCode === escape) {\n searchInput.value = '';\n }\n });\n};\n\n/**\n * Trigger a search in lunr and transform the result.\n *\n * @method\n * @private\n * @param {String} query\n * @return {Array} results\n */\nconst searchIndex = query => {\n // Find the item in our index corresponding to the lunr one to have more info\n // Lunr result:\n // {ref: \"/section/page1\", score: 0.2725657778206127}\n // Our result:\n // {title:\"Page1\", href:\"/section/page1\", ...}\n\n return lunrIndex.search(query + ' ' + query + '*').map(result => {\n return pagesIndex.filter(page => {\n return page.uri === result.ref;\n })[0];\n });\n};\n\n/**\n * Display the 10 first results\n *\n * @method\n * @private\n * @param {Array} results to display\n */\nconst renderResults = results => {\n const dropdownMenu = document.querySelector(selectors.dropdownmenu);\n if (!results.length) {\n dropdownMenu.classList.remove('show');\n return;\n }\n\n // Clear out the results.\n dropdownMenu.innerHTML = '';\n\n const baseUrl = M.cfg.wwwroot + '/admin/tool/componentlibrary/docspage.php';\n\n // Only show the ten first results\n results.slice(0, 10).forEach(function(result) {\n const link = document.createElement(\"a\");\n const chapter = result.uri.split('/')[1];\n link.appendChild(document.createTextNode(`${chapter} > ${result.title}`));\n link.classList.add('dropdown-item');\n link.href = baseUrl + result.uri;\n\n dropdownMenu.appendChild(link);\n });\n\n dropdownMenu.classList.add('show');\n};\n\n/**\n * Initialize module.\n *\n * @method\n * @param {String} jsonFile Full path to the search DB json file.\n */\nexport const search = jsonFile => {\n initLunr(jsonFile);\n initUI();\n};\n"],"file":"search.min.js"}
\ No newline at end of file
+{"version":3,"file":"search.min.js","sources":["../src/search.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 .\n\n/**\n * Interface to the Lunr search engines.\n *\n * @module tool_componentlibrary/search\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport lunrJs from 'tool_componentlibrary/lunr';\nimport selectors from 'tool_componentlibrary/selectors';\nimport Log from 'core/log';\nimport Notification from 'core/notification';\nimport {enter, escape} from 'core/key_codes';\n\nlet lunrIndex = null;\nlet pagesIndex = null;\n\n/**\n * Get the jsonFile that is generated when the component library is build.\n *\n * @method\n * @private\n * @param {String} jsonFile the URL to the json file.\n * @return {Object}\n */\nconst fetchJson = async(jsonFile) => {\n const response = await fetch(jsonFile);\n\n if (!response.ok) {\n Log.debug(`Error getting Hugo index file: ${response.status}`);\n }\n\n return await response.json();\n};\n\n/**\n * Initiate lunr on the data in the jsonFile and add the jsondata to the pagesIndex\n *\n * @method\n * @private\n * @param {String} jsonFile the URL to the json file.\n */\nconst initLunr = jsonFile => {\n fetchJson(jsonFile).then(jsondata => {\n pagesIndex = jsondata;\n // Using an arrow function here will break lunr on compile.\n lunrIndex = lunrJs(function() {\n this.ref('uri');\n this.field('title', {boost: 10});\n this.field('content');\n this.field('tags', {boost: 5});\n jsondata.forEach(p => {\n this.add(p);\n });\n });\n return null;\n }).catch(Notification.exception);\n};\n\n/**\n * Setup the eventlistener to listen on user input on the search field.\n *\n * @method\n * @private\n */\nconst initUI = () => {\n const searchInput = document.querySelector(selectors.searchinput);\n searchInput.addEventListener('keyup', e => {\n const query = e.currentTarget.value;\n if (query.length < 2) {\n document.querySelector(selectors.dropdownmenu).classList.remove('show');\n return;\n }\n renderResults(searchIndex(query));\n });\n searchInput.addEventListener('keydown', e => {\n if (e.keyCode === enter) {\n e.preventDefault();\n }\n if (e.keyCode === escape) {\n searchInput.value = '';\n }\n });\n};\n\n/**\n * Trigger a search in lunr and transform the result.\n *\n * @method\n * @private\n * @param {String} query\n * @return {Array} results\n */\nconst searchIndex = query => {\n // Find the item in our index corresponding to the lunr one to have more info\n // Lunr result:\n // {ref: \"/section/page1\", score: 0.2725657778206127}\n // Our result:\n // {title:\"Page1\", href:\"/section/page1\", ...}\n\n return lunrIndex.search(query + ' ' + query + '*').map(result => {\n return pagesIndex.filter(page => {\n return page.uri === result.ref;\n })[0];\n });\n};\n\n/**\n * Display the 10 first results\n *\n * @method\n * @private\n * @param {Array} results to display\n */\nconst renderResults = results => {\n const dropdownMenu = document.querySelector(selectors.dropdownmenu);\n if (!results.length) {\n dropdownMenu.classList.remove('show');\n return;\n }\n\n // Clear out the results.\n dropdownMenu.innerHTML = '';\n\n const baseUrl = M.cfg.wwwroot + '/admin/tool/componentlibrary/docspage.php';\n\n // Only show the ten first results\n results.slice(0, 10).forEach(function(result) {\n const link = document.createElement(\"a\");\n const chapter = result.uri.split('/')[1];\n link.appendChild(document.createTextNode(`${chapter} > ${result.title}`));\n link.classList.add('dropdown-item');\n link.href = baseUrl + result.uri;\n\n dropdownMenu.appendChild(link);\n });\n\n dropdownMenu.classList.add('show');\n};\n\n/**\n * Initialize module.\n *\n * @method\n * @param {String} jsonFile Full path to the search DB json file.\n */\nexport const search = jsonFile => {\n initLunr(jsonFile);\n initUI();\n};\n"],"names":["lunrIndex","pagesIndex","initLunr","jsonFile","async","response","fetch","ok","debug","status","json","fetchJson","then","jsondata","ref","field","boost","forEach","p","add","catch","Notification","exception","searchIndex","query","search","map","result","filter","page","uri","renderResults","results","dropdownMenu","document","querySelector","selectors","dropdownmenu","length","classList","remove","innerHTML","baseUrl","M","cfg","wwwroot","slice","link","createElement","chapter","split","appendChild","createTextNode","title","href","searchInput","searchinput","addEventListener","e","currentTarget","value","keyCode","enter","preventDefault","escape","initUI"],"mappings":";;;;;;;gQA6BIA,UAAY,KACZC,WAAa,WA2BXC,SAAWC,WAjBCC,OAAAA,iBACRC,eAAiBC,MAAMH,iBAExBE,SAASE,iBACNC,+CAAwCH,SAASI,eAG5CJ,SAASK,QAWtBC,CAAUR,UAAUS,MAAKC,WACrBZ,WAAaY,SAEbb,WAAY,kBAAO,gBACVc,IAAI,YACJC,MAAM,QAAS,CAACC,MAAO,UACvBD,MAAM,gBACNA,MAAM,OAAQ,CAACC,MAAO,IAC3BH,SAASI,SAAQC,SACRC,IAAID,SAGV,QACRE,MAAMC,sBAAaC,YAqCpBC,YAAcC,OAOTxB,UAAUyB,OAAOD,MAAQ,IAAMA,MAAQ,KAAKE,KAAIC,QAC5C1B,WAAW2B,QAAOC,MACdA,KAAKC,MAAQH,OAAOb,MAC5B,KAWLiB,cAAgBC,gBACZC,aAAeC,SAASC,cAAcC,mBAAUC,kBACjDL,QAAQM,mBACTL,aAAaM,UAAUC,OAAO,QAKlCP,aAAaQ,UAAY,SAEnBC,QAAUC,EAAEC,IAAIC,QAAU,4CAGhCb,QAAQc,MAAM,EAAG,IAAI7B,SAAQ,SAASU,cAC5BoB,KAAOb,SAASc,cAAc,KAC9BC,QAAUtB,OAAOG,IAAIoB,MAAM,KAAK,GACtCH,KAAKI,YAAYjB,SAASkB,yBAAkBH,sBAAatB,OAAO0B,SAChEN,KAAKR,UAAUpB,IAAI,iBACnB4B,KAAKO,KAAOZ,QAAUf,OAAOG,IAE7BG,aAAakB,YAAYJ,SAG7Bd,aAAaM,UAAUpB,IAAI,yBASThB,WAClBD,SAASC,UAlFE,YACLoD,YAAcrB,SAASC,cAAcC,mBAAUoB,aACrDD,YAAYE,iBAAiB,SAASC,UAC5BlC,MAAQkC,EAAEC,cAAcC,MAC1BpC,MAAMc,OAAS,EACfJ,SAASC,cAAcC,mBAAUC,cAAcE,UAAUC,OAAO,QAGpET,cAAcR,YAAYC,WAE9B+B,YAAYE,iBAAiB,WAAWC,IAChCA,EAAEG,UAAYC,kBACdJ,EAAEK,iBAEFL,EAAEG,UAAYG,oBACdT,YAAYK,MAAQ,QAoE5BK"}
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/selectors.min.js b/admin/tool/componentlibrary/amd/build/selectors.min.js
index b7ad97c31ba..1f57da39fcb 100644
--- a/admin/tool/componentlibrary/amd/build/selectors.min.js
+++ b/admin/tool/componentlibrary/amd/build/selectors.min.js
@@ -1,2 +1,3 @@
-define ("tool_componentlibrary/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;a.default={clipboardbutton:".btn-clipboard",clipboardcontent:"figure.highlight, div.highlight",searchinput:"[data-region=\"docsearch\"] input",searchsubmit:"[data-region=\"docsearch\"] .btn-submit",dropdownmenu:"[data-region=\"docsearch\"] .dropdown-menu",componentlibrary:"[data-region=\"componentlibrary\"]",jscode:"[data-action=\"runjs\"]",mustachecode:"[data-region=\"mustachecode\"]",mustacherawcontext:"[data-region=\"rawcontext\"]",mustacherendered:"[data-region=\"mustacherendered\"]",mustachesource:"[data-region=\"mustachesource\"]",mustachecontext:"[data-region=\"mustachecontext\"]"};return a.default});
-//# sourceMappingURL=selectors.min.js.map
+define("tool_componentlibrary/selectors",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;return _exports.default={clipboardbutton:".btn-clipboard",clipboardcontent:"figure.highlight, div.highlight",searchinput:'[data-region="docsearch"] input',searchsubmit:'[data-region="docsearch"] .btn-submit',dropdownmenu:'[data-region="docsearch"] .dropdown-menu',componentlibrary:'[data-region="componentlibrary"]',jscode:'[data-action="runjs"]',mustachecode:'[data-region="mustachecode"]',mustacherawcontext:'[data-region="rawcontext"]',mustacherendered:'[data-region="mustacherendered"]',mustachesource:'[data-region="mustachesource"]',mustachecontext:'[data-region="mustachecontext"]'},_exports.default}));
+
+//# sourceMappingURL=selectors.min.js.map
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/build/selectors.min.js.map b/admin/tool/componentlibrary/amd/build/selectors.min.js.map
index 55c47bad35a..3f14335b2e2 100644
--- a/admin/tool/componentlibrary/amd/build/selectors.min.js.map
+++ b/admin/tool/componentlibrary/amd/build/selectors.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/selectors.js"],"names":["clipboardbutton","clipboardcontent","searchinput","searchsubmit","dropdownmenu","componentlibrary","jscode","mustachecode","mustacherawcontext","mustacherendered","mustachesource","mustachecontext"],"mappings":"2JAsBe,CAMXA,eAAe,CAAE,gBANN,CAaXC,gBAAgB,CAAE,iCAbP,CAoBXC,WAAW,CAAE,mCApBF,CA2BXC,YAAY,CAAE,yCA3BH,CAkCXC,YAAY,CAAE,4CAlCH,CAyCXC,gBAAgB,CAAE,oCAzCP,CAgDXC,MAAM,CAAE,yBAhDG,CAuDXC,YAAY,CAAE,gCAvDH,CA8DXC,kBAAkB,CAAE,8BA9DT,CAqEXC,gBAAgB,CAAE,oCArEP,CA4EXC,cAAc,CAAE,kCA5EL,CAmFXC,eAAe,CAAE,mCAnFN,C","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 .\n\n/**\n * Selectors for the component library\n *\n * @module tool_componentlibrary/selectors\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default {\n /**\n * A selector relating to the 'Copy to clipboard' button.\n *\n * @type {string}\n */\n clipboardbutton: '.btn-clipboard',\n\n /**\n * A selector relating to the content copied by the 'Copy to clipboard' button.\n *\n * @type {string}\n */\n clipboardcontent: 'figure.highlight, div.highlight',\n\n /**\n * A selector relating to the 'Search' text input.\n *\n * @type {string}\n */\n searchinput: '[data-region=\"docsearch\"] input',\n\n /**\n * A selector relating to the 'Search' submit btton.\n *\n * @type {string}\n */\n searchsubmit: '[data-region=\"docsearch\"] .btn-submit',\n\n /**\n * A selector relating to the search dropdown menu.\n *\n * @type {string}\n */\n dropdownmenu: '[data-region=\"docsearch\"] .dropdown-menu',\n\n /**\n * A selector relating to the entire Component Library content region.\n *\n * @type {string}\n */\n componentlibrary: '[data-region=\"componentlibrary\"]',\n\n /**\n * A selector relating to JS Code which is to be run for examples to function.\n *\n * @type {string}\n */\n jscode: '[data-action=\"runjs\"]',\n\n /**\n * A selector relating to Mustache Template code regions.\n *\n * @type {string}\n */\n mustachecode: '[data-region=\"mustachecode\"]',\n\n /**\n * A selector relating to raw Mustache content regions.\n *\n * @type {string}\n */\n mustacherawcontext: '[data-region=\"rawcontext\"]',\n\n /**\n * A selector relating to rendered Mustache content regions.\n *\n * @type {string}\n */\n mustacherendered: '[data-region=\"mustacherendered\"]',\n\n /**\n * A selector relating to Mustache source code regions.\n *\n * @type {string}\n */\n mustachesource: '[data-region=\"mustachesource\"]',\n\n /**\n * A selector relating to Mustache context regions.\n *\n * @type {string}\n */\n mustachecontext: '[data-region=\"mustachecontext\"]',\n};\n"],"file":"selectors.min.js"}
\ No newline at end of file
+{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 .\n\n/**\n * Selectors for the component library\n *\n * @module tool_componentlibrary/selectors\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default {\n /**\n * A selector relating to the 'Copy to clipboard' button.\n *\n * @type {string}\n */\n clipboardbutton: '.btn-clipboard',\n\n /**\n * A selector relating to the content copied by the 'Copy to clipboard' button.\n *\n * @type {string}\n */\n clipboardcontent: 'figure.highlight, div.highlight',\n\n /**\n * A selector relating to the 'Search' text input.\n *\n * @type {string}\n */\n searchinput: '[data-region=\"docsearch\"] input',\n\n /**\n * A selector relating to the 'Search' submit btton.\n *\n * @type {string}\n */\n searchsubmit: '[data-region=\"docsearch\"] .btn-submit',\n\n /**\n * A selector relating to the search dropdown menu.\n *\n * @type {string}\n */\n dropdownmenu: '[data-region=\"docsearch\"] .dropdown-menu',\n\n /**\n * A selector relating to the entire Component Library content region.\n *\n * @type {string}\n */\n componentlibrary: '[data-region=\"componentlibrary\"]',\n\n /**\n * A selector relating to JS Code which is to be run for examples to function.\n *\n * @type {string}\n */\n jscode: '[data-action=\"runjs\"]',\n\n /**\n * A selector relating to Mustache Template code regions.\n *\n * @type {string}\n */\n mustachecode: '[data-region=\"mustachecode\"]',\n\n /**\n * A selector relating to raw Mustache content regions.\n *\n * @type {string}\n */\n mustacherawcontext: '[data-region=\"rawcontext\"]',\n\n /**\n * A selector relating to rendered Mustache content regions.\n *\n * @type {string}\n */\n mustacherendered: '[data-region=\"mustacherendered\"]',\n\n /**\n * A selector relating to Mustache source code regions.\n *\n * @type {string}\n */\n mustachesource: '[data-region=\"mustachesource\"]',\n\n /**\n * A selector relating to Mustache context regions.\n *\n * @type {string}\n */\n mustachecontext: '[data-region=\"mustachecontext\"]',\n};\n"],"names":["clipboardbutton","clipboardcontent","searchinput","searchsubmit","dropdownmenu","componentlibrary","jscode","mustachecode","mustacherawcontext","mustacherendered","mustachesource","mustachecontext"],"mappings":"iLAsBe,CAMXA,gBAAiB,iBAOjBC,iBAAkB,kCAOlBC,YAAa,kCAObC,aAAc,wCAOdC,aAAc,2CAOdC,iBAAkB,mCAOlBC,OAAQ,wBAORC,aAAc,+BAOdC,mBAAoB,6BAOpBC,iBAAkB,mCAOlBC,eAAgB,iCAOhBC,gBAAiB"}
\ No newline at end of file
diff --git a/admin/tool/componentlibrary/amd/src/jsrunner.js b/admin/tool/componentlibrary/amd/src/jsrunner.js
index f36c7188414..dfe2678ef85 100644
--- a/admin/tool/componentlibrary/amd/src/jsrunner.js
+++ b/admin/tool/componentlibrary/amd/src/jsrunner.js
@@ -34,6 +34,9 @@ import selectors from 'tool_componentlibrary/selectors';
export const jsRunner = () => {
const compLib = document.querySelector(selectors.componentlibrary);
compLib.querySelectorAll(selectors.jscode).forEach(runjs => {
- eval(runjs.innerText); // eslint-disable-line no-eval
+ const script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.innerHTML = runjs.textContent;
+ document.head.appendChild(script);
});
};
diff --git a/admin/tool/dataprivacy/amd/build/add_category.min.js b/admin/tool/dataprivacy/amd/build/add_category.min.js
index 987f86b93c9..63a1d972b27 100644
--- a/admin/tool/dataprivacy/amd/build/add_category.min.js
+++ b/admin/tool/dataprivacy/amd/build/add_category.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/add_category",["jquery","core/str","core/ajax","core/notification","core/modal_factory","core/modal_events","core/fragment","core_form/changechecker"],function(a,b,c,d,e,f,g,h){var i={CATEGORY_LINK:"[data-add-element=\"category\"]"},j=function(a){this.contextId=a;this.strings=b.get_strings([{key:"addcategory",component:"tool_dataprivacy"},{key:"save",component:"admin"}]);this.registerEventListeners()};j.prototype.contextId=0;j.prototype.strings=0;j.prototype.registerEventListeners=function(){var b=a(i.CATEGORY_LINK);b.on("click",function(){return this.strings.then(function(a){e.create({type:e.types.SAVE_CANCEL,title:a[0],body:""},b).done(function(b){this.setupFormModal(b,a[1])}.bind(this))}.bind(this)).fail(d.exception)}.bind(this))};j.prototype.getBody=function(a){var b=null;if("undefined"!=typeof a){b={jsonformdata:JSON.stringify(a)}}return g.loadFragment("tool_dataprivacy","addcategory_form",this.contextId,b)};j.prototype.setupFormModal=function(a,b){a.setLarge();a.setSaveButtonText(b);a.getRoot().on(f.hidden,this.destroy.bind(this));a.setBody(this.getBody());a.getRoot().on(f.save,this.submitForm.bind(this));a.getRoot().on("submit","form",this.submitFormAjax.bind(this));this.modal=a;a.show()};j.prototype.submitForm=function(a){a.preventDefault();this.modal.getRoot().find("form").submit()};j.prototype.submitFormAjax=function(a){a.preventDefault();var b=this.modal.getRoot().find("form").serialize();c.call([{methodname:"tool_dataprivacy_create_category_form",args:{jsonformdata:JSON.stringify(b)},done:function(a){if(a.validationerrors){this.modal.setBody(this.getBody(b))}else{this.close()}}.bind(this),fail:d.exception}])};j.prototype.close=function(){this.destroy();document.location.reload()};j.prototype.destroy=function(){h.resetAllFormDirtyStates();this.modal.destroy()};j.prototype.removeListeners=function(){a(i.CATEGORY_LINK).off("click")};return{getInstance:function getInstance(a){return new j(a)}}});
-//# sourceMappingURL=add_category.min.js.map
+/**
+ * Module to add categories.
+ *
+ * @module tool_dataprivacy/add_category
+ * @copyright 2018 David Monllao
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/add_category",["jquery","core/str","core/ajax","core/notification","core/modal_factory","core/modal_events","core/fragment","core_form/changechecker"],(function($,Str,Ajax,Notification,ModalFactory,ModalEvents,Fragment,FormChangeChecker){var SELECTORS_CATEGORY_LINK='[data-add-element="category"]',AddCategory=function(contextId){this.contextId=contextId;this.strings=Str.get_strings([{key:"addcategory",component:"tool_dataprivacy"},{key:"save",component:"admin"}]),this.registerEventListeners()};return AddCategory.prototype.contextId=0,AddCategory.prototype.strings=0,AddCategory.prototype.registerEventListeners=function(){var trigger=$(SELECTORS_CATEGORY_LINK);trigger.on("click",function(){return this.strings.then(function(strings){ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL,title:strings[0],body:""},trigger).done(function(modal){this.setupFormModal(modal,strings[1])}.bind(this))}.bind(this)).fail(Notification.exception)}.bind(this))},AddCategory.prototype.getBody=function(formdata){var params=null;return void 0!==formdata&&(params={jsonformdata:JSON.stringify(formdata)}),Fragment.loadFragment("tool_dataprivacy","addcategory_form",this.contextId,params)},AddCategory.prototype.setupFormModal=function(modal,saveText){modal.setLarge(),modal.setSaveButtonText(saveText),modal.getRoot().on(ModalEvents.hidden,this.destroy.bind(this)),modal.setBody(this.getBody()),modal.getRoot().on(ModalEvents.save,this.submitForm.bind(this)),modal.getRoot().on("submit","form",this.submitFormAjax.bind(this)),this.modal=modal,modal.show()},AddCategory.prototype.submitForm=function(e){e.preventDefault(),this.modal.getRoot().find("form").submit()},AddCategory.prototype.submitFormAjax=function(e){e.preventDefault();var formData=this.modal.getRoot().find("form").serialize();Ajax.call([{methodname:"tool_dataprivacy_create_category_form",args:{jsonformdata:JSON.stringify(formData)},done:function(data){data.validationerrors?this.modal.setBody(this.getBody(formData)):this.close()}.bind(this),fail:Notification.exception}])},AddCategory.prototype.close=function(){this.destroy(),document.location.reload()},AddCategory.prototype.destroy=function(){FormChangeChecker.resetAllFormDirtyStates(),this.modal.destroy()},AddCategory.prototype.removeListeners=function(){$(SELECTORS_CATEGORY_LINK).off("click")},{getInstance:function(contextId){return new AddCategory(contextId)}}}));
+
+//# sourceMappingURL=add_category.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/add_category.min.js.map b/admin/tool/dataprivacy/amd/build/add_category.min.js.map
index f97e7286498..2ee9d89dc99 100644
--- a/admin/tool/dataprivacy/amd/build/add_category.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/add_category.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/add_category.js"],"names":["define","$","Str","Ajax","Notification","ModalFactory","ModalEvents","Fragment","FormChangeChecker","SELECTORS","CATEGORY_LINK","AddCategory","contextId","strings","get_strings","key","component","registerEventListeners","prototype","trigger","on","then","create","type","types","SAVE_CANCEL","title","body","done","modal","setupFormModal","bind","fail","exception","getBody","formdata","params","jsonformdata","JSON","stringify","loadFragment","saveText","setLarge","setSaveButtonText","getRoot","hidden","destroy","setBody","save","submitForm","submitFormAjax","show","e","preventDefault","find","submit","formData","serialize","call","methodname","args","data","validationerrors","close","document","location","reload","resetAllFormDirtyStates","removeListeners","off","getInstance"],"mappings":"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","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 .\n\n/**\n * Module to add categories.\n *\n * @module tool_dataprivacy/add_category\n * @copyright 2018 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/ajax',\n 'core/notification',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/fragment',\n 'core_form/changechecker',\n], function(\n $,\n Str,\n Ajax,\n Notification,\n ModalFactory,\n ModalEvents,\n Fragment,\n FormChangeChecker\n) {\n\n var SELECTORS = {\n CATEGORY_LINK: '[data-add-element=\"category\"]',\n };\n\n var AddCategory = function(contextId) {\n this.contextId = contextId;\n\n var stringKeys = [\n {\n key: 'addcategory',\n component: 'tool_dataprivacy'\n },\n {\n key: 'save',\n component: 'admin'\n }\n ];\n this.strings = Str.get_strings(stringKeys);\n\n this.registerEventListeners();\n };\n\n /**\n * @var {int} contextId\n * @private\n */\n AddCategory.prototype.contextId = 0;\n\n /**\n * @var {Promise}\n * @private\n */\n AddCategory.prototype.strings = 0;\n\n AddCategory.prototype.registerEventListeners = function() {\n\n var trigger = $(SELECTORS.CATEGORY_LINK);\n trigger.on('click', function() {\n return this.strings.then(function(strings) {\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: strings[0],\n body: '',\n }, trigger).done(function(modal) {\n this.setupFormModal(modal, strings[1]);\n }.bind(this));\n }.bind(this))\n .fail(Notification.exception);\n }.bind(this));\n\n };\n\n /**\n * @method getBody\n * @param {Object} formdata\n * @private\n * @return {Promise}\n */\n AddCategory.prototype.getBody = function(formdata) {\n\n var params = null;\n if (typeof formdata !== \"undefined\") {\n params = {jsonformdata: JSON.stringify(formdata)};\n }\n // Get the content of the modal.\n return Fragment.loadFragment('tool_dataprivacy', 'addcategory_form', this.contextId, params);\n };\n\n AddCategory.prototype.setupFormModal = function(modal, saveText) {\n modal.setLarge();\n\n modal.setSaveButtonText(saveText);\n\n // We want to reset the form every time it is opened.\n modal.getRoot().on(ModalEvents.hidden, this.destroy.bind(this));\n\n modal.setBody(this.getBody());\n\n // We catch the modal save event, and use it to submit the form inside the modal.\n // Triggering a form submission will give JS validation scripts a chance to check for errors.\n modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));\n // We also catch the form submit event and use it to submit the form with ajax.\n modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));\n\n this.modal = modal;\n\n modal.show();\n };\n\n /**\n * This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.\n *\n * @method submitForm\n * @param {Event} e Form submission event.\n * @private\n */\n AddCategory.prototype.submitForm = function(e) {\n e.preventDefault();\n this.modal.getRoot().find('form').submit();\n };\n\n AddCategory.prototype.submitFormAjax = function(e) {\n // We don't want to do a real form submission.\n e.preventDefault();\n\n // Convert all the form elements values to a serialised string.\n var formData = this.modal.getRoot().find('form').serialize();\n\n Ajax.call([{\n methodname: 'tool_dataprivacy_create_category_form',\n args: {jsonformdata: JSON.stringify(formData)},\n done: function(data) {\n if (data.validationerrors) {\n this.modal.setBody(this.getBody(formData));\n } else {\n this.close();\n }\n }.bind(this),\n fail: Notification.exception\n }]);\n };\n\n AddCategory.prototype.close = function() {\n this.destroy();\n document.location.reload();\n };\n\n AddCategory.prototype.destroy = function() {\n FormChangeChecker.resetAllFormDirtyStates();\n this.modal.destroy();\n };\n\n AddCategory.prototype.removeListeners = function() {\n $(SELECTORS.CATEGORY_LINK).off('click');\n };\n\n return /** @alias module:tool_dataprivacy/add_category */ {\n getInstance: function(contextId) {\n return new AddCategory(contextId);\n }\n };\n }\n);\n\n"],"file":"add_category.min.js"}
\ No newline at end of file
+{"version":3,"file":"add_category.min.js","sources":["../src/add_category.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 .\n\n/**\n * Module to add categories.\n *\n * @module tool_dataprivacy/add_category\n * @copyright 2018 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/ajax',\n 'core/notification',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/fragment',\n 'core_form/changechecker',\n], function(\n $,\n Str,\n Ajax,\n Notification,\n ModalFactory,\n ModalEvents,\n Fragment,\n FormChangeChecker\n) {\n\n var SELECTORS = {\n CATEGORY_LINK: '[data-add-element=\"category\"]',\n };\n\n var AddCategory = function(contextId) {\n this.contextId = contextId;\n\n var stringKeys = [\n {\n key: 'addcategory',\n component: 'tool_dataprivacy'\n },\n {\n key: 'save',\n component: 'admin'\n }\n ];\n this.strings = Str.get_strings(stringKeys);\n\n this.registerEventListeners();\n };\n\n /**\n * @var {int} contextId\n * @private\n */\n AddCategory.prototype.contextId = 0;\n\n /**\n * @var {Promise}\n * @private\n */\n AddCategory.prototype.strings = 0;\n\n AddCategory.prototype.registerEventListeners = function() {\n\n var trigger = $(SELECTORS.CATEGORY_LINK);\n trigger.on('click', function() {\n return this.strings.then(function(strings) {\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: strings[0],\n body: '',\n }, trigger).done(function(modal) {\n this.setupFormModal(modal, strings[1]);\n }.bind(this));\n }.bind(this))\n .fail(Notification.exception);\n }.bind(this));\n\n };\n\n /**\n * @method getBody\n * @param {Object} formdata\n * @private\n * @return {Promise}\n */\n AddCategory.prototype.getBody = function(formdata) {\n\n var params = null;\n if (typeof formdata !== \"undefined\") {\n params = {jsonformdata: JSON.stringify(formdata)};\n }\n // Get the content of the modal.\n return Fragment.loadFragment('tool_dataprivacy', 'addcategory_form', this.contextId, params);\n };\n\n AddCategory.prototype.setupFormModal = function(modal, saveText) {\n modal.setLarge();\n\n modal.setSaveButtonText(saveText);\n\n // We want to reset the form every time it is opened.\n modal.getRoot().on(ModalEvents.hidden, this.destroy.bind(this));\n\n modal.setBody(this.getBody());\n\n // We catch the modal save event, and use it to submit the form inside the modal.\n // Triggering a form submission will give JS validation scripts a chance to check for errors.\n modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));\n // We also catch the form submit event and use it to submit the form with ajax.\n modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));\n\n this.modal = modal;\n\n modal.show();\n };\n\n /**\n * This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.\n *\n * @method submitForm\n * @param {Event} e Form submission event.\n * @private\n */\n AddCategory.prototype.submitForm = function(e) {\n e.preventDefault();\n this.modal.getRoot().find('form').submit();\n };\n\n AddCategory.prototype.submitFormAjax = function(e) {\n // We don't want to do a real form submission.\n e.preventDefault();\n\n // Convert all the form elements values to a serialised string.\n var formData = this.modal.getRoot().find('form').serialize();\n\n Ajax.call([{\n methodname: 'tool_dataprivacy_create_category_form',\n args: {jsonformdata: JSON.stringify(formData)},\n done: function(data) {\n if (data.validationerrors) {\n this.modal.setBody(this.getBody(formData));\n } else {\n this.close();\n }\n }.bind(this),\n fail: Notification.exception\n }]);\n };\n\n AddCategory.prototype.close = function() {\n this.destroy();\n document.location.reload();\n };\n\n AddCategory.prototype.destroy = function() {\n FormChangeChecker.resetAllFormDirtyStates();\n this.modal.destroy();\n };\n\n AddCategory.prototype.removeListeners = function() {\n $(SELECTORS.CATEGORY_LINK).off('click');\n };\n\n return /** @alias module:tool_dataprivacy/add_category */ {\n getInstance: function(contextId) {\n return new AddCategory(contextId);\n }\n };\n }\n);\n\n"],"names":["define","$","Str","Ajax","Notification","ModalFactory","ModalEvents","Fragment","FormChangeChecker","SELECTORS","AddCategory","contextId","strings","get_strings","key","component","registerEventListeners","prototype","trigger","on","this","then","create","type","types","SAVE_CANCEL","title","body","done","modal","setupFormModal","bind","fail","exception","getBody","formdata","params","jsonformdata","JSON","stringify","loadFragment","saveText","setLarge","setSaveButtonText","getRoot","hidden","destroy","setBody","save","submitForm","submitFormAjax","show","e","preventDefault","find","submit","formData","serialize","call","methodname","args","data","validationerrors","close","document","location","reload","resetAllFormDirtyStates","removeListeners","off","getInstance"],"mappings":";;;;;;;AAsBAA,uCAAO,CACH,SACA,WACA,YACA,oBACA,qBACA,oBACA,gBACA,4BACD,SACCC,EACAC,IACAC,KACAC,aACAC,aACAC,YACAC,SACAC,uBAGQC,wBACe,gCAGfC,YAAc,SAASC,gBAClBA,UAAYA,eAYZC,QAAUV,IAAIW,YAVF,CACb,CACIC,IAAK,cACLC,UAAW,oBAEf,CACID,IAAK,OACLC,UAAW,gBAKdC,iCAOTN,YAAYO,UAAUN,UAAY,EAMlCD,YAAYO,UAAUL,QAAU,EAEhCF,YAAYO,UAAUD,uBAAyB,eAEvCE,QAAUjB,EAAEQ,yBAChBS,QAAQC,GAAG,QAAS,kBACTC,KAAKR,QAAQS,KAAK,SAAST,SAC9BP,aAAaiB,OAAO,CAChBC,KAAMlB,aAAamB,MAAMC,YACzBC,MAAOd,QAAQ,GACfe,KAAM,IACPT,SAASU,KAAK,SAASC,YACjBC,eAAeD,MAAOjB,QAAQ,KACrCmB,KAAKX,QACTW,KAAKX,OACNY,KAAK5B,aAAa6B,YACrBF,KAAKX,QAUXV,YAAYO,UAAUiB,QAAU,SAASC,cAEjCC,OAAS,iBACW,IAAbD,WACPC,OAAS,CAACC,aAAcC,KAAKC,UAAUJ,YAGpC5B,SAASiC,aAAa,mBAAoB,mBAAoBpB,KAAKT,UAAWyB,SAGzF1B,YAAYO,UAAUa,eAAiB,SAASD,MAAOY,UACnDZ,MAAMa,WAENb,MAAMc,kBAAkBF,UAGxBZ,MAAMe,UAAUzB,GAAGb,YAAYuC,OAAQzB,KAAK0B,QAAQf,KAAKX,OAEzDS,MAAMkB,QAAQ3B,KAAKc,WAInBL,MAAMe,UAAUzB,GAAGb,YAAY0C,KAAM5B,KAAK6B,WAAWlB,KAAKX,OAE1DS,MAAMe,UAAUzB,GAAG,SAAU,OAAQC,KAAK8B,eAAenB,KAAKX,YAEzDS,MAAQA,MAEbA,MAAMsB,QAUVzC,YAAYO,UAAUgC,WAAa,SAASG,GACxCA,EAAEC,sBACGxB,MAAMe,UAAUU,KAAK,QAAQC,UAGtC7C,YAAYO,UAAUiC,eAAiB,SAASE,GAE5CA,EAAEC,qBAGEG,SAAWpC,KAAKS,MAAMe,UAAUU,KAAK,QAAQG,YAEjDtD,KAAKuD,KAAK,CAAC,CACPC,WAAY,wCACZC,KAAM,CAACvB,aAAcC,KAAKC,UAAUiB,WACpC5B,KAAM,SAASiC,MACPA,KAAKC,sBACAjC,MAAMkB,QAAQ3B,KAAKc,QAAQsB,gBAE3BO,SAEXhC,KAAKX,MACPY,KAAM5B,aAAa6B,cAI3BvB,YAAYO,UAAU8C,MAAQ,gBACrBjB,UACLkB,SAASC,SAASC,UAGtBxD,YAAYO,UAAU6B,QAAU,WAC5BtC,kBAAkB2D,+BACbtC,MAAMiB,WAGfpC,YAAYO,UAAUmD,gBAAkB,WACpCnE,EAAEQ,yBAAyB4D,IAAI,UAGuB,CACtDC,YAAa,SAAS3D,kBACX,IAAID,YAAYC"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/add_purpose.min.js b/admin/tool/dataprivacy/amd/build/add_purpose.min.js
index 9e71843cdb6..1a949a9f722 100644
--- a/admin/tool/dataprivacy/amd/build/add_purpose.min.js
+++ b/admin/tool/dataprivacy/amd/build/add_purpose.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/add_purpose",["jquery","core/str","core/ajax","core/notification","core/modal_factory","core/modal_events","core/fragment","core_form/changechecker"],function(a,b,c,d,e,f,g,h){var i={PURPOSE_LINK:"[data-add-element=\"purpose\"]"},j=function(a){this.contextId=a;this.strings=b.get_strings([{key:"addpurpose",component:"tool_dataprivacy"},{key:"save",component:"admin"}]);this.registerEventListeners()};j.prototype.contextId=0;j.prototype.strings=0;j.prototype.registerEventListeners=function(){var b=a(i.PURPOSE_LINK);b.on("click",function(){return this.strings.then(function(a){e.create({type:e.types.SAVE_CANCEL,title:a[0],body:""},b).done(function(b){this.setupFormModal(b,a[1])}.bind(this))}.bind(this)).fail(d.exception)}.bind(this))};j.prototype.getBody=function(a){var b=null;if("undefined"!=typeof a){b={jsonformdata:JSON.stringify(a)}}return g.loadFragment("tool_dataprivacy","addpurpose_form",this.contextId,b)};j.prototype.setupFormModal=function(a,b){a.setLarge();a.setSaveButtonText(b);a.getRoot().on(f.hidden,this.destroy.bind(this));a.setBody(this.getBody());a.getRoot().on(f.save,this.submitForm.bind(this));a.getRoot().on("submit","form",this.submitFormAjax.bind(this));this.modal=a;a.show()};j.prototype.submitForm=function(a){a.preventDefault();this.modal.getRoot().find("form").submit()};j.prototype.submitFormAjax=function(a){a.preventDefault();var b=this.modal.getRoot().find("form").serialize();c.call([{methodname:"tool_dataprivacy_create_purpose_form",args:{jsonformdata:JSON.stringify(b)},done:function(a){if(a.validationerrors){this.modal.setBody(this.getBody(b))}else{this.close()}}.bind(this),fail:d.exception}])};j.prototype.close=function(){this.destroy();document.location.reload()};j.prototype.destroy=function(){h.resetAllFormDirtyStates();this.modal.destroy()};j.prototype.removeListeners=function(){a(i.PURPOSE_LINK).off("click")};return{getInstance:function getInstance(a){return new j(a)}}});
-//# sourceMappingURL=add_purpose.min.js.map
+/**
+ * Module to add purposes.
+ *
+ * @module tool_dataprivacy/add_purpose
+ * @copyright 2018 David Monllao
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/add_purpose",["jquery","core/str","core/ajax","core/notification","core/modal_factory","core/modal_events","core/fragment","core_form/changechecker"],(function($,Str,Ajax,Notification,ModalFactory,ModalEvents,Fragment,FormChangeChecker){var SELECTORS_PURPOSE_LINK='[data-add-element="purpose"]',AddPurpose=function(contextId){this.contextId=contextId;this.strings=Str.get_strings([{key:"addpurpose",component:"tool_dataprivacy"},{key:"save",component:"admin"}]),this.registerEventListeners()};return AddPurpose.prototype.contextId=0,AddPurpose.prototype.strings=0,AddPurpose.prototype.registerEventListeners=function(){var trigger=$(SELECTORS_PURPOSE_LINK);trigger.on("click",function(){return this.strings.then(function(strings){ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL,title:strings[0],body:""},trigger).done(function(modal){this.setupFormModal(modal,strings[1])}.bind(this))}.bind(this)).fail(Notification.exception)}.bind(this))},AddPurpose.prototype.getBody=function(formdata){var params=null;return void 0!==formdata&&(params={jsonformdata:JSON.stringify(formdata)}),Fragment.loadFragment("tool_dataprivacy","addpurpose_form",this.contextId,params)},AddPurpose.prototype.setupFormModal=function(modal,saveText){modal.setLarge(),modal.setSaveButtonText(saveText),modal.getRoot().on(ModalEvents.hidden,this.destroy.bind(this)),modal.setBody(this.getBody()),modal.getRoot().on(ModalEvents.save,this.submitForm.bind(this)),modal.getRoot().on("submit","form",this.submitFormAjax.bind(this)),this.modal=modal,modal.show()},AddPurpose.prototype.submitForm=function(e){e.preventDefault(),this.modal.getRoot().find("form").submit()},AddPurpose.prototype.submitFormAjax=function(e){e.preventDefault();var formData=this.modal.getRoot().find("form").serialize();Ajax.call([{methodname:"tool_dataprivacy_create_purpose_form",args:{jsonformdata:JSON.stringify(formData)},done:function(data){data.validationerrors?this.modal.setBody(this.getBody(formData)):this.close()}.bind(this),fail:Notification.exception}])},AddPurpose.prototype.close=function(){this.destroy(),document.location.reload()},AddPurpose.prototype.destroy=function(){FormChangeChecker.resetAllFormDirtyStates(),this.modal.destroy()},AddPurpose.prototype.removeListeners=function(){$(SELECTORS_PURPOSE_LINK).off("click")},{getInstance:function(contextId){return new AddPurpose(contextId)}}}));
+
+//# sourceMappingURL=add_purpose.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/add_purpose.min.js.map b/admin/tool/dataprivacy/amd/build/add_purpose.min.js.map
index 81d703e1eca..6b9b9f5b460 100644
--- a/admin/tool/dataprivacy/amd/build/add_purpose.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/add_purpose.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/add_purpose.js"],"names":["define","$","Str","Ajax","Notification","ModalFactory","ModalEvents","Fragment","FormChangeChecker","SELECTORS","PURPOSE_LINK","AddPurpose","contextId","strings","get_strings","key","component","registerEventListeners","prototype","trigger","on","then","create","type","types","SAVE_CANCEL","title","body","done","modal","setupFormModal","bind","fail","exception","getBody","formdata","params","jsonformdata","JSON","stringify","loadFragment","saveText","setLarge","setSaveButtonText","getRoot","hidden","destroy","setBody","save","submitForm","submitFormAjax","show","e","preventDefault","find","submit","formData","serialize","call","methodname","args","data","validationerrors","close","document","location","reload","resetAllFormDirtyStates","removeListeners","off","getInstance"],"mappings":"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","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 .\n\n/**\n * Module to add purposes.\n *\n * @module tool_dataprivacy/add_purpose\n * @copyright 2018 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/ajax',\n 'core/notification',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/fragment',\n 'core_form/changechecker',\n], function(\n $,\n Str,\n Ajax,\n Notification,\n ModalFactory,\n ModalEvents,\n Fragment,\n FormChangeChecker\n) {\n\n var SELECTORS = {\n PURPOSE_LINK: '[data-add-element=\"purpose\"]',\n };\n\n var AddPurpose = function(contextId) {\n this.contextId = contextId;\n\n var stringKeys = [\n {\n key: 'addpurpose',\n component: 'tool_dataprivacy'\n },\n {\n key: 'save',\n component: 'admin'\n }\n ];\n this.strings = Str.get_strings(stringKeys);\n\n this.registerEventListeners();\n };\n\n /**\n * @var {int} contextId\n * @private\n */\n AddPurpose.prototype.contextId = 0;\n\n /**\n * @var {Promise}\n * @private\n */\n AddPurpose.prototype.strings = 0;\n\n AddPurpose.prototype.registerEventListeners = function() {\n\n var trigger = $(SELECTORS.PURPOSE_LINK);\n trigger.on('click', function() {\n return this.strings.then(function(strings) {\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: strings[0],\n body: '',\n }, trigger).done(function(modal) {\n this.setupFormModal(modal, strings[1]);\n }.bind(this));\n }.bind(this))\n .fail(Notification.exception);\n }.bind(this));\n\n };\n\n /**\n * @method getBody\n * @param {Object} formdata\n * @private\n * @return {Promise}\n */\n AddPurpose.prototype.getBody = function(formdata) {\n\n var params = null;\n if (typeof formdata !== \"undefined\") {\n params = {jsonformdata: JSON.stringify(formdata)};\n }\n // Get the content of the modal.\n return Fragment.loadFragment('tool_dataprivacy', 'addpurpose_form', this.contextId, params);\n };\n\n AddPurpose.prototype.setupFormModal = function(modal, saveText) {\n modal.setLarge();\n\n modal.setSaveButtonText(saveText);\n\n // We want to reset the form every time it is opened.\n modal.getRoot().on(ModalEvents.hidden, this.destroy.bind(this));\n\n modal.setBody(this.getBody());\n\n // We catch the modal save event, and use it to submit the form inside the modal.\n // Triggering a form submission will give JS validation scripts a chance to check for errors.\n modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));\n // We also catch the form submit event and use it to submit the form with ajax.\n modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));\n\n this.modal = modal;\n\n modal.show();\n };\n\n /**\n * This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.\n *\n * @method submitForm\n * @param {Event} e Form submission event.\n * @private\n */\n AddPurpose.prototype.submitForm = function(e) {\n e.preventDefault();\n this.modal.getRoot().find('form').submit();\n };\n\n AddPurpose.prototype.submitFormAjax = function(e) {\n // We don't want to do a real form submission.\n e.preventDefault();\n\n // Convert all the form elements values to a serialised string.\n var formData = this.modal.getRoot().find('form').serialize();\n\n Ajax.call([{\n methodname: 'tool_dataprivacy_create_purpose_form',\n args: {jsonformdata: JSON.stringify(formData)},\n done: function(data) {\n if (data.validationerrors) {\n this.modal.setBody(this.getBody(formData));\n } else {\n this.close();\n }\n }.bind(this),\n\n fail: Notification.exception\n }]);\n };\n\n AddPurpose.prototype.close = function() {\n this.destroy();\n document.location.reload();\n };\n\n AddPurpose.prototype.destroy = function() {\n FormChangeChecker.resetAllFormDirtyStates();\n this.modal.destroy();\n };\n\n AddPurpose.prototype.removeListeners = function() {\n $(SELECTORS.PURPOSE_LINK).off('click');\n };\n\n return /** @alias module:tool_dataprivacy/add_purpose */ {\n getInstance: function(contextId) {\n return new AddPurpose(contextId);\n }\n };\n }\n);\n\n"],"file":"add_purpose.min.js"}
\ No newline at end of file
+{"version":3,"file":"add_purpose.min.js","sources":["../src/add_purpose.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 .\n\n/**\n * Module to add purposes.\n *\n * @module tool_dataprivacy/add_purpose\n * @copyright 2018 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/ajax',\n 'core/notification',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/fragment',\n 'core_form/changechecker',\n], function(\n $,\n Str,\n Ajax,\n Notification,\n ModalFactory,\n ModalEvents,\n Fragment,\n FormChangeChecker\n) {\n\n var SELECTORS = {\n PURPOSE_LINK: '[data-add-element=\"purpose\"]',\n };\n\n var AddPurpose = function(contextId) {\n this.contextId = contextId;\n\n var stringKeys = [\n {\n key: 'addpurpose',\n component: 'tool_dataprivacy'\n },\n {\n key: 'save',\n component: 'admin'\n }\n ];\n this.strings = Str.get_strings(stringKeys);\n\n this.registerEventListeners();\n };\n\n /**\n * @var {int} contextId\n * @private\n */\n AddPurpose.prototype.contextId = 0;\n\n /**\n * @var {Promise}\n * @private\n */\n AddPurpose.prototype.strings = 0;\n\n AddPurpose.prototype.registerEventListeners = function() {\n\n var trigger = $(SELECTORS.PURPOSE_LINK);\n trigger.on('click', function() {\n return this.strings.then(function(strings) {\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: strings[0],\n body: '',\n }, trigger).done(function(modal) {\n this.setupFormModal(modal, strings[1]);\n }.bind(this));\n }.bind(this))\n .fail(Notification.exception);\n }.bind(this));\n\n };\n\n /**\n * @method getBody\n * @param {Object} formdata\n * @private\n * @return {Promise}\n */\n AddPurpose.prototype.getBody = function(formdata) {\n\n var params = null;\n if (typeof formdata !== \"undefined\") {\n params = {jsonformdata: JSON.stringify(formdata)};\n }\n // Get the content of the modal.\n return Fragment.loadFragment('tool_dataprivacy', 'addpurpose_form', this.contextId, params);\n };\n\n AddPurpose.prototype.setupFormModal = function(modal, saveText) {\n modal.setLarge();\n\n modal.setSaveButtonText(saveText);\n\n // We want to reset the form every time it is opened.\n modal.getRoot().on(ModalEvents.hidden, this.destroy.bind(this));\n\n modal.setBody(this.getBody());\n\n // We catch the modal save event, and use it to submit the form inside the modal.\n // Triggering a form submission will give JS validation scripts a chance to check for errors.\n modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));\n // We also catch the form submit event and use it to submit the form with ajax.\n modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));\n\n this.modal = modal;\n\n modal.show();\n };\n\n /**\n * This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.\n *\n * @method submitForm\n * @param {Event} e Form submission event.\n * @private\n */\n AddPurpose.prototype.submitForm = function(e) {\n e.preventDefault();\n this.modal.getRoot().find('form').submit();\n };\n\n AddPurpose.prototype.submitFormAjax = function(e) {\n // We don't want to do a real form submission.\n e.preventDefault();\n\n // Convert all the form elements values to a serialised string.\n var formData = this.modal.getRoot().find('form').serialize();\n\n Ajax.call([{\n methodname: 'tool_dataprivacy_create_purpose_form',\n args: {jsonformdata: JSON.stringify(formData)},\n done: function(data) {\n if (data.validationerrors) {\n this.modal.setBody(this.getBody(formData));\n } else {\n this.close();\n }\n }.bind(this),\n\n fail: Notification.exception\n }]);\n };\n\n AddPurpose.prototype.close = function() {\n this.destroy();\n document.location.reload();\n };\n\n AddPurpose.prototype.destroy = function() {\n FormChangeChecker.resetAllFormDirtyStates();\n this.modal.destroy();\n };\n\n AddPurpose.prototype.removeListeners = function() {\n $(SELECTORS.PURPOSE_LINK).off('click');\n };\n\n return /** @alias module:tool_dataprivacy/add_purpose */ {\n getInstance: function(contextId) {\n return new AddPurpose(contextId);\n }\n };\n }\n);\n\n"],"names":["define","$","Str","Ajax","Notification","ModalFactory","ModalEvents","Fragment","FormChangeChecker","SELECTORS","AddPurpose","contextId","strings","get_strings","key","component","registerEventListeners","prototype","trigger","on","this","then","create","type","types","SAVE_CANCEL","title","body","done","modal","setupFormModal","bind","fail","exception","getBody","formdata","params","jsonformdata","JSON","stringify","loadFragment","saveText","setLarge","setSaveButtonText","getRoot","hidden","destroy","setBody","save","submitForm","submitFormAjax","show","e","preventDefault","find","submit","formData","serialize","call","methodname","args","data","validationerrors","close","document","location","reload","resetAllFormDirtyStates","removeListeners","off","getInstance"],"mappings":";;;;;;;AAsBAA,sCAAO,CACH,SACA,WACA,YACA,oBACA,qBACA,oBACA,gBACA,4BACD,SACCC,EACAC,IACAC,KACAC,aACAC,aACAC,YACAC,SACAC,uBAGQC,uBACc,+BAGdC,WAAa,SAASC,gBACjBA,UAAYA,eAYZC,QAAUV,IAAIW,YAVF,CACb,CACIC,IAAK,aACLC,UAAW,oBAEf,CACID,IAAK,OACLC,UAAW,gBAKdC,iCAOTN,WAAWO,UAAUN,UAAY,EAMjCD,WAAWO,UAAUL,QAAU,EAE/BF,WAAWO,UAAUD,uBAAyB,eAEtCE,QAAUjB,EAAEQ,wBAChBS,QAAQC,GAAG,QAAS,kBACTC,KAAKR,QAAQS,KAAK,SAAST,SAC9BP,aAAaiB,OAAO,CAChBC,KAAMlB,aAAamB,MAAMC,YACzBC,MAAOd,QAAQ,GACfe,KAAM,IACPT,SAASU,KAAK,SAASC,YACjBC,eAAeD,MAAOjB,QAAQ,KACrCmB,KAAKX,QACTW,KAAKX,OACNY,KAAK5B,aAAa6B,YACrBF,KAAKX,QAUXV,WAAWO,UAAUiB,QAAU,SAASC,cAEhCC,OAAS,iBACW,IAAbD,WACPC,OAAS,CAACC,aAAcC,KAAKC,UAAUJ,YAGpC5B,SAASiC,aAAa,mBAAoB,kBAAmBpB,KAAKT,UAAWyB,SAGxF1B,WAAWO,UAAUa,eAAiB,SAASD,MAAOY,UAClDZ,MAAMa,WAENb,MAAMc,kBAAkBF,UAGxBZ,MAAMe,UAAUzB,GAAGb,YAAYuC,OAAQzB,KAAK0B,QAAQf,KAAKX,OAEzDS,MAAMkB,QAAQ3B,KAAKc,WAInBL,MAAMe,UAAUzB,GAAGb,YAAY0C,KAAM5B,KAAK6B,WAAWlB,KAAKX,OAE1DS,MAAMe,UAAUzB,GAAG,SAAU,OAAQC,KAAK8B,eAAenB,KAAKX,YAEzDS,MAAQA,MAEbA,MAAMsB,QAUVzC,WAAWO,UAAUgC,WAAa,SAASG,GACvCA,EAAEC,sBACGxB,MAAMe,UAAUU,KAAK,QAAQC,UAGtC7C,WAAWO,UAAUiC,eAAiB,SAASE,GAE3CA,EAAEC,qBAGEG,SAAWpC,KAAKS,MAAMe,UAAUU,KAAK,QAAQG,YAEjDtD,KAAKuD,KAAK,CAAC,CACPC,WAAY,uCACZC,KAAM,CAACvB,aAAcC,KAAKC,UAAUiB,WACpC5B,KAAM,SAASiC,MACPA,KAAKC,sBACAjC,MAAMkB,QAAQ3B,KAAKc,QAAQsB,gBAE3BO,SAEXhC,KAAKX,MAEPY,KAAM5B,aAAa6B,cAI3BvB,WAAWO,UAAU8C,MAAQ,gBACpBjB,UACLkB,SAASC,SAASC,UAGtBxD,WAAWO,UAAU6B,QAAU,WAC3BtC,kBAAkB2D,+BACbtC,MAAMiB,WAGfpC,WAAWO,UAAUmD,gBAAkB,WACnCnE,EAAEQ,wBAAwB4D,IAAI,UAGuB,CACrDC,YAAa,SAAS3D,kBACX,IAAID,WAAWC"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/categoriesactions.min.js b/admin/tool/dataprivacy/amd/build/categoriesactions.min.js
index 0b47fca7d37..4fe615bab59 100644
--- a/admin/tool/dataprivacy/amd/build/categoriesactions.min.js
+++ b/admin/tool/dataprivacy/amd/build/categoriesactions.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/categoriesactions",["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events"],function(a,b,c,d,e,f){var g={DELETE:"[data-action=\"deletecategory\"]"},h=function(){this.registerEvents()};h.prototype.registerEvents=function(){a(g.DELETE).click(function(g){g.preventDefault();var h=a(this).data("id"),i=a(this).data("name");d.get_strings([{key:"deletecategory",component:"tool_dataprivacy"},{key:"deletecategorytext",component:"tool_dataprivacy",param:i},{key:"delete"}]).then(function(d){var g=d[0],i=d[1],j=d[2];return e.create({title:g,body:i,type:e.types.SAVE_CANCEL}).then(function(d){d.setSaveButtonText(j);d.getRoot().on(f.save,function(){b.call([{methodname:"tool_dataprivacy_delete_category",args:{id:h}}])[0].done(function(b){if(b.result){a("tr[data-categoryid=\""+h+"\"]").remove()}else{c.addNotification({message:b.warnings[0].message,type:"error"})}}).fail(c.exception)});d.getRoot().on(f.hidden,function(){d.destroy()});return d})}).done(function(a){a.show()}).fail(c.exception)})};return{init:function init(){return new h}}});
-//# sourceMappingURL=categoriesactions.min.js.map
+/**
+ * AMD module for categories actions.
+ *
+ * @module tool_dataprivacy/categoriesactions
+ * @copyright 2018 David Monllao
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/categoriesactions",["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events"],(function($,Ajax,Notification,Str,ModalFactory,ModalEvents){var ACTIONS_DELETE='[data-action="deletecategory"]',CategoriesActions=function(){this.registerEvents()};return CategoriesActions.prototype.registerEvents=function(){$(ACTIONS_DELETE).click((function(e){e.preventDefault();var id=$(this).data("id"),stringkeys=[{key:"deletecategory",component:"tool_dataprivacy"},{key:"deletecategorytext",component:"tool_dataprivacy",param:$(this).data("name")},{key:"delete"}];Str.get_strings(stringkeys).then((function(langStrings){var title=langStrings[0],confirmMessage=langStrings[1],buttonText=langStrings[2];return ModalFactory.create({title:title,body:confirmMessage,type:ModalFactory.types.SAVE_CANCEL}).then((function(modal){return modal.setSaveButtonText(buttonText),modal.getRoot().on(ModalEvents.save,(function(){var request={methodname:"tool_dataprivacy_delete_category",args:{id:id}};Ajax.call([request])[0].done((function(data){data.result?$('tr[data-categoryid="'+id+'"]').remove():Notification.addNotification({message:data.warnings[0].message,type:"error"})})).fail(Notification.exception)})),modal.getRoot().on(ModalEvents.hidden,(function(){modal.destroy()})),modal}))})).done((function(modal){modal.show()})).fail(Notification.exception)}))},{init:function(){return new CategoriesActions}}}));
+
+//# sourceMappingURL=categoriesactions.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/categoriesactions.min.js.map b/admin/tool/dataprivacy/amd/build/categoriesactions.min.js.map
index cb8801921da..683666ec3bb 100644
--- a/admin/tool/dataprivacy/amd/build/categoriesactions.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/categoriesactions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/categoriesactions.js"],"names":["define","$","Ajax","Notification","Str","ModalFactory","ModalEvents","ACTIONS","DELETE","CategoriesActions","registerEvents","prototype","click","e","preventDefault","id","data","categoryname","get_strings","key","component","param","then","langStrings","title","confirmMessage","buttonText","create","body","type","types","SAVE_CANCEL","modal","setSaveButtonText","getRoot","on","save","call","methodname","args","done","result","remove","addNotification","message","warnings","fail","exception","hidden","destroy","show"],"mappings":"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","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 .\n\n/**\n * AMD module for categories actions.\n *\n * @module tool_dataprivacy/categoriesactions\n * @copyright 2018 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events'],\nfunction($, Ajax, Notification, Str, ModalFactory, ModalEvents) {\n\n /**\n * List of action selectors.\n *\n * @type {{DELETE: string}}\n */\n var ACTIONS = {\n DELETE: '[data-action=\"deletecategory\"]',\n };\n\n /**\n * CategoriesActions class.\n */\n var CategoriesActions = function() {\n this.registerEvents();\n };\n\n /**\n * Register event listeners.\n */\n CategoriesActions.prototype.registerEvents = function() {\n $(ACTIONS.DELETE).click(function(e) {\n e.preventDefault();\n\n var id = $(this).data('id');\n var categoryname = $(this).data('name');\n var stringkeys = [\n {\n key: 'deletecategory',\n component: 'tool_dataprivacy'\n },\n {\n key: 'deletecategorytext',\n component: 'tool_dataprivacy',\n param: categoryname\n },\n {\n key: 'delete'\n }\n ];\n\n Str.get_strings(stringkeys).then(function(langStrings) {\n var title = langStrings[0];\n var confirmMessage = langStrings[1];\n var buttonText = langStrings[2];\n return ModalFactory.create({\n title: title,\n body: confirmMessage,\n type: ModalFactory.types.SAVE_CANCEL\n }).then(function(modal) {\n modal.setSaveButtonText(buttonText);\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function() {\n\n var request = {\n methodname: 'tool_dataprivacy_delete_category',\n args: {'id': id}\n };\n\n Ajax.call([request])[0].done(function(data) {\n if (data.result) {\n $('tr[data-categoryid=\"' + id + '\"]').remove();\n } else {\n Notification.addNotification({\n message: data.warnings[0].message,\n type: 'error'\n });\n }\n }).fail(Notification.exception);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n return modal;\n });\n }).done(function(modal) {\n modal.show();\n\n }).fail(Notification.exception);\n });\n };\n\n return /** @alias module:tool_dataprivacy/categoriesactions */ {\n // Public variables and functions.\n\n /**\n * Initialise the module.\n *\n * @method init\n * @return {CategoriesActions}\n */\n 'init': function() {\n return new CategoriesActions();\n }\n };\n});\n"],"file":"categoriesactions.min.js"}
\ No newline at end of file
+{"version":3,"file":"categoriesactions.min.js","sources":["../src/categoriesactions.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 .\n\n/**\n * AMD module for categories actions.\n *\n * @module tool_dataprivacy/categoriesactions\n * @copyright 2018 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events'],\nfunction($, Ajax, Notification, Str, ModalFactory, ModalEvents) {\n\n /**\n * List of action selectors.\n *\n * @type {{DELETE: string}}\n */\n var ACTIONS = {\n DELETE: '[data-action=\"deletecategory\"]',\n };\n\n /**\n * CategoriesActions class.\n */\n var CategoriesActions = function() {\n this.registerEvents();\n };\n\n /**\n * Register event listeners.\n */\n CategoriesActions.prototype.registerEvents = function() {\n $(ACTIONS.DELETE).click(function(e) {\n e.preventDefault();\n\n var id = $(this).data('id');\n var categoryname = $(this).data('name');\n var stringkeys = [\n {\n key: 'deletecategory',\n component: 'tool_dataprivacy'\n },\n {\n key: 'deletecategorytext',\n component: 'tool_dataprivacy',\n param: categoryname\n },\n {\n key: 'delete'\n }\n ];\n\n Str.get_strings(stringkeys).then(function(langStrings) {\n var title = langStrings[0];\n var confirmMessage = langStrings[1];\n var buttonText = langStrings[2];\n return ModalFactory.create({\n title: title,\n body: confirmMessage,\n type: ModalFactory.types.SAVE_CANCEL\n }).then(function(modal) {\n modal.setSaveButtonText(buttonText);\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function() {\n\n var request = {\n methodname: 'tool_dataprivacy_delete_category',\n args: {'id': id}\n };\n\n Ajax.call([request])[0].done(function(data) {\n if (data.result) {\n $('tr[data-categoryid=\"' + id + '\"]').remove();\n } else {\n Notification.addNotification({\n message: data.warnings[0].message,\n type: 'error'\n });\n }\n }).fail(Notification.exception);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n return modal;\n });\n }).done(function(modal) {\n modal.show();\n\n }).fail(Notification.exception);\n });\n };\n\n return /** @alias module:tool_dataprivacy/categoriesactions */ {\n // Public variables and functions.\n\n /**\n * Initialise the module.\n *\n * @method init\n * @return {CategoriesActions}\n */\n 'init': function() {\n return new CategoriesActions();\n }\n };\n});\n"],"names":["define","$","Ajax","Notification","Str","ModalFactory","ModalEvents","ACTIONS","CategoriesActions","registerEvents","prototype","click","e","preventDefault","id","this","data","stringkeys","key","component","param","get_strings","then","langStrings","title","confirmMessage","buttonText","create","body","type","types","SAVE_CANCEL","modal","setSaveButtonText","getRoot","on","save","request","methodname","args","call","done","result","remove","addNotification","message","warnings","fail","exception","hidden","destroy","show"],"mappings":";;;;;;;AAsBAA,4CAAO,CACH,SACA,YACA,oBACA,WACA,qBACA,sBACJ,SAASC,EAAGC,KAAMC,aAAcC,IAAKC,aAAcC,iBAO3CC,eACQ,iCAMRC,kBAAoB,gBACfC,yBAMTD,kBAAkBE,UAAUD,eAAiB,WACzCR,EAAEM,gBAAgBI,OAAM,SAASC,GAC7BA,EAAEC,qBAEEC,GAAKb,EAAEc,MAAMC,KAAK,MAElBC,WAAa,CACb,CACIC,IAAK,iBACLC,UAAW,oBAEf,CACID,IAAK,qBACLC,UAAW,mBACXC,MATWnB,EAAEc,MAAMC,KAAK,SAW5B,CACIE,IAAK,WAIbd,IAAIiB,YAAYJ,YAAYK,MAAK,SAASC,iBAClCC,MAAQD,YAAY,GACpBE,eAAiBF,YAAY,GAC7BG,WAAaH,YAAY,UACtBlB,aAAasB,OAAO,CACvBH,MAAOA,MACPI,KAAMH,eACNI,KAAMxB,aAAayB,MAAMC,cAC1BT,MAAK,SAASU,cACbA,MAAMC,kBAAkBP,YAGxBM,MAAME,UAAUC,GAAG7B,YAAY8B,MAAM,eAE7BC,QAAU,CACVC,WAAY,mCACZC,KAAM,IAAOzB,KAGjBZ,KAAKsC,KAAK,CAACH,UAAU,GAAGI,MAAK,SAASzB,MAC9BA,KAAK0B,OACLzC,EAAE,uBAAyBa,GAAK,MAAM6B,SAEtCxC,aAAayC,gBAAgB,CACzBC,QAAS7B,KAAK8B,SAAS,GAAGD,QAC1BhB,KAAM,aAGfkB,KAAK5C,aAAa6C,cAIzBhB,MAAME,UAAUC,GAAG7B,YAAY2C,QAAQ,WAEnCjB,MAAMkB,aAGHlB,YAEZS,MAAK,SAAST,OACbA,MAAMmB,UAEPJ,KAAK5C,aAAa6C,eAIkC,MASnD,kBACG,IAAIxC"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/contactdpo.min.js b/admin/tool/dataprivacy/amd/build/contactdpo.min.js
index 73514788d05..c13d9806449 100644
--- a/admin/tool/dataprivacy/amd/build/contactdpo.min.js
+++ b/admin/tool/dataprivacy/amd/build/contactdpo.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/contactdpo",["exports","core_form/modalform","core/notification","core/str","core/toast"],function(a,b,c,d,e){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=f(b);c=f(c);function f(a){return a&&a.__esModule?a:{default:a}}var g={CONTACT_DPO:"[data-action=\"contactdpo\"]"};a.init=function init(){var a=document.querySelector(g.CONTACT_DPO);a.addEventListener("click",function(f){f.preventDefault();var g=new b.default({modalConfig:{title:(0,d.get_string)("contactdataprotectionofficer","tool_dataprivacy")},formClass:"tool_dataprivacy\\form\\contactdpo",saveButtonText:(0,d.get_string)("send","tool_dataprivacy"),returnFocus:a});g.addEventListener(g.events.FORM_SUBMITTED,function(a){if(a.detail.result){(0,d.get_string)("requestsubmitted","tool_dataprivacy").then(e.add).catch()}else{var b=a.detail.warnings.map(function(a){return a.message});c.default.addNotification({type:"error",message:b.join(" ")})}});g.show()})}});
-//# sourceMappingURL=contactdpo.min.js.map
+define("tool_dataprivacy/contactdpo",["exports","core_form/modalform","core/notification","core/str","core/toast"],(function(_exports,_modalform,_notification,_str,_toast){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
+/**
+ * Javascript module for contacting the site DPO
+ *
+ * @module tool_dataprivacy/contactdpo
+ * @copyright 2021 Paul Holden
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modalform=_interopRequireDefault(_modalform),_notification=_interopRequireDefault(_notification);const SELECTORS_CONTACT_DPO='[data-action="contactdpo"]';_exports.init=()=>{const triggerElement=document.querySelector(SELECTORS_CONTACT_DPO);triggerElement.addEventListener("click",(event=>{event.preventDefault();const modalForm=new _modalform.default({modalConfig:{title:(0,_str.get_string)("contactdataprotectionofficer","tool_dataprivacy")},formClass:"tool_dataprivacy\\form\\contactdpo",saveButtonText:(0,_str.get_string)("send","tool_dataprivacy"),returnFocus:triggerElement});modalForm.addEventListener(modalForm.events.FORM_SUBMITTED,(event=>{if(event.detail.result)(0,_str.get_string)("requestsubmitted","tool_dataprivacy").then(_toast.add).catch();else{const warningMessages=event.detail.warnings.map((warning=>warning.message));_notification.default.addNotification({type:"error",message:warningMessages.join(" ")})}})),modalForm.show()}))}}));
+
+//# sourceMappingURL=contactdpo.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/contactdpo.min.js.map b/admin/tool/dataprivacy/amd/build/contactdpo.min.js.map
index efbac474315..680d7bb355d 100644
--- a/admin/tool/dataprivacy/amd/build/contactdpo.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/contactdpo.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/contactdpo.js"],"names":["SELECTORS","CONTACT_DPO","init","triggerElement","document","querySelector","addEventListener","event","preventDefault","modalForm","ModalForm","modalConfig","title","formClass","saveButtonText","returnFocus","events","FORM_SUBMITTED","detail","result","then","addToast","catch","warningMessages","warnings","map","warning","message","Notification","addNotification","type","join","show"],"mappings":"oNAuBA,OACA,O,sDAIMA,CAAAA,CAAS,CAAG,CACdC,WAAW,CAAE,8BADC,C,QAOE,QAAPC,CAAAA,IAAO,EAAM,CACtB,GAAMC,CAAAA,CAAc,CAAGC,QAAQ,CAACC,aAAT,CAAuBL,CAAS,CAACC,WAAjC,CAAvB,CAEAE,CAAc,CAACG,gBAAf,CAAgC,OAAhC,CAAyC,SAAAC,CAAK,CAAI,CAC9CA,CAAK,CAACC,cAAN,GAEA,GAAMC,CAAAA,CAAS,CAAG,GAAIC,UAAJ,CAAc,CAC5BC,WAAW,CAAE,CACTC,KAAK,CAAE,iBAAU,8BAAV,CAA0C,kBAA1C,CADE,CADe,CAI5BC,SAAS,CAAE,oCAJiB,CAK5BC,cAAc,CAAE,iBAAU,MAAV,CAAkB,kBAAlB,CALY,CAM5BC,WAAW,CAAEZ,CANe,CAAd,CAAlB,CAUAM,CAAS,CAACH,gBAAV,CAA2BG,CAAS,CAACO,MAAV,CAAiBC,cAA5C,CAA4D,SAAAV,CAAK,CAAI,CACjE,GAAIA,CAAK,CAACW,MAAN,CAAaC,MAAjB,CAAyB,CACrB,iBAAU,kBAAV,CAA8B,kBAA9B,EAAkDC,IAAlD,CAAuDC,KAAvD,EAAiEC,KAAjE,EACH,CAFD,IAEO,CACH,GAAMC,CAAAA,CAAe,CAAGhB,CAAK,CAACW,MAAN,CAAaM,QAAb,CAAsBC,GAAtB,CAA0B,SAAAC,CAAO,QAAIA,CAAAA,CAAO,CAACC,OAAZ,CAAjC,CAAxB,CACAC,UAAaC,eAAb,CAA6B,CACzBC,IAAI,CAAE,OADmB,CAEzBH,OAAO,CAAEJ,CAAe,CAACQ,IAAhB,CAAqB,MAArB,CAFgB,CAA7B,CAIH,CACJ,CAVD,EAYAtB,CAAS,CAACuB,IAAV,EACH,CA1BD,CA2BH,C","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 .\n\n/**\n * Javascript module for contacting the site DPO\n *\n * @module tool_dataprivacy/contactdpo\n * @copyright 2021 Paul Holden \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport Notification from 'core/notification';\nimport {get_string as getString} from 'core/str';\nimport {add as addToast} from 'core/toast';\n\nconst SELECTORS = {\n CONTACT_DPO: '[data-action=\"contactdpo\"]',\n};\n\n/**\n * Initialize module\n */\nexport const init = () => {\n const triggerElement = document.querySelector(SELECTORS.CONTACT_DPO);\n\n triggerElement.addEventListener('click', event => {\n event.preventDefault();\n\n const modalForm = new ModalForm({\n modalConfig: {\n title: getString('contactdataprotectionofficer', 'tool_dataprivacy'),\n },\n formClass: 'tool_dataprivacy\\\\form\\\\contactdpo',\n saveButtonText: getString('send', 'tool_dataprivacy'),\n returnFocus: triggerElement,\n });\n\n // Show a toast notification when the form is submitted.\n modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, event => {\n if (event.detail.result) {\n getString('requestsubmitted', 'tool_dataprivacy').then(addToast).catch();\n } else {\n const warningMessages = event.detail.warnings.map(warning => warning.message);\n Notification.addNotification({\n type: 'error',\n message: warningMessages.join(' ')\n });\n }\n });\n\n modalForm.show();\n });\n};\n"],"file":"contactdpo.min.js"}
\ No newline at end of file
+{"version":3,"file":"contactdpo.min.js","sources":["../src/contactdpo.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 .\n\n/**\n * Javascript module for contacting the site DPO\n *\n * @module tool_dataprivacy/contactdpo\n * @copyright 2021 Paul Holden \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport Notification from 'core/notification';\nimport {get_string as getString} from 'core/str';\nimport {add as addToast} from 'core/toast';\n\nconst SELECTORS = {\n CONTACT_DPO: '[data-action=\"contactdpo\"]',\n};\n\n/**\n * Initialize module\n */\nexport const init = () => {\n const triggerElement = document.querySelector(SELECTORS.CONTACT_DPO);\n\n triggerElement.addEventListener('click', event => {\n event.preventDefault();\n\n const modalForm = new ModalForm({\n modalConfig: {\n title: getString('contactdataprotectionofficer', 'tool_dataprivacy'),\n },\n formClass: 'tool_dataprivacy\\\\form\\\\contactdpo',\n saveButtonText: getString('send', 'tool_dataprivacy'),\n returnFocus: triggerElement,\n });\n\n // Show a toast notification when the form is submitted.\n modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, event => {\n if (event.detail.result) {\n getString('requestsubmitted', 'tool_dataprivacy').then(addToast).catch();\n } else {\n const warningMessages = event.detail.warnings.map(warning => warning.message);\n Notification.addNotification({\n type: 'error',\n message: warningMessages.join(' ')\n });\n }\n });\n\n modalForm.show();\n });\n};\n"],"names":["SELECTORS","triggerElement","document","querySelector","addEventListener","event","preventDefault","modalForm","ModalForm","modalConfig","title","formClass","saveButtonText","returnFocus","events","FORM_SUBMITTED","detail","result","then","addToast","catch","warningMessages","warnings","map","warning","message","addNotification","type","join","show"],"mappings":";;;;;;;0LA4BMA,sBACW,2CAMG,WACVC,eAAiBC,SAASC,cAAcH,uBAE9CC,eAAeG,iBAAiB,SAASC,QACrCA,MAAMC,uBAEAC,UAAY,IAAIC,mBAAU,CAC5BC,YAAa,CACTC,OAAO,mBAAU,+BAAgC,qBAErDC,UAAW,qCACXC,gBAAgB,mBAAU,OAAQ,oBAClCC,YAAaZ,iBAIjBM,UAAUH,iBAAiBG,UAAUO,OAAOC,gBAAgBV,WACpDA,MAAMW,OAAOC,2BACH,mBAAoB,oBAAoBC,KAAKC,YAAUC,YAC9D,OACGC,gBAAkBhB,MAAMW,OAAOM,SAASC,KAAIC,SAAWA,QAAQC,gCACxDC,gBAAgB,CACzBC,KAAM,QACNF,QAASJ,gBAAgBO,KAAK,cAK1CrB,UAAUsB"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/data_deletion.min.js b/admin/tool/dataprivacy/amd/build/data_deletion.min.js
index 88f9f42ce41..212a020c29a 100644
--- a/admin/tool/dataprivacy/amd/build/data_deletion.min.js
+++ b/admin/tool/dataprivacy/amd/build/data_deletion.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/data_deletion",["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events"],function(a,b,c,d,e,f){var h={MARK_FOR_DELETION:"[data-action=\"markfordeletion\"]",SELECT_ALL:"[data-action=\"selectall\"]"},i={SELECTCONTEXT:".selectcontext"},j=function(){this.registerEvents()};j.prototype.registerEvents=function(){a(h.MARK_FOR_DELETION).click(function(b){b.preventDefault();var c=[];a(i.SELECTCONTEXT).each(function(){var b=a(this);if(b.is(":checked")){c.push(b.val())}});g(c)});a(h.SELECT_ALL).change(function(b){b.preventDefault();var c=a(this);if(c.is(":checked")){a(i.SELECTCONTEXT).attr("checked","checked")}else{a(i.SELECTCONTEXT).removeAttr("checked")}})};function g(a){var g="";d.get_strings([{key:"confirm",component:"moodle"},{key:"confirmcontextdeletion",component:"tool_dataprivacy"}]).then(function(a){g=a[0];var b=a[1];return e.create({title:g,body:b,type:e.types.SAVE_CANCEL})}).then(function(d){d.setSaveButtonText(g);d.getRoot().on(f.save,function(){b.call([{methodname:"tool_dataprivacy_confirm_contexts_for_deletion",args:{ids:a}}])[0].done(function(a){if(a.result){window.location.reload()}else{c.addNotification({message:a.warnings[0].message,type:"error"})}}).fail(c.exception)});d.getRoot().on(f.hidden,function(){d.destroy()});return d}).done(function(a){a.show()}).fail(c.exception)}return j});
-//# sourceMappingURL=data_deletion.min.js.map
+/**
+ * Request actions.
+ *
+ * @module tool_dataprivacy/data_deletion
+ * @copyright 2018 Jun Pataleta
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/data_deletion",["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events"],(function($,Ajax,Notification,Str,ModalFactory,ModalEvents){var ACTIONS_MARK_FOR_DELETION='[data-action="markfordeletion"]',ACTIONS_SELECT_ALL='[data-action="selectall"]',SELECTORS_SELECTCONTEXT=".selectcontext",DataDeletionActions=function(){this.registerEvents()};return DataDeletionActions.prototype.registerEvents=function(){$(ACTIONS_MARK_FOR_DELETION).click((function(e){e.preventDefault();var ids,keys,wsfunction,modalTitle,selectedIds=[];$(SELECTORS_SELECTCONTEXT).each((function(){var checkbox=$(this);checkbox.is(":checked")&&selectedIds.push(checkbox.val())})),ids=selectedIds,keys=[{key:"confirm",component:"moodle"},{key:"confirmcontextdeletion",component:"tool_dataprivacy"}],wsfunction="tool_dataprivacy_confirm_contexts_for_deletion",modalTitle="",Str.get_strings(keys).then((function(langStrings){modalTitle=langStrings[0];var confirmMessage=langStrings[1];return ModalFactory.create({title:modalTitle,body:confirmMessage,type:ModalFactory.types.SAVE_CANCEL})})).then((function(modal){return modal.setSaveButtonText(modalTitle),modal.getRoot().on(ModalEvents.save,(function(){var request={methodname:wsfunction,args:{ids:ids}};Ajax.call([request])[0].done((function(data){data.result?window.location.reload():Notification.addNotification({message:data.warnings[0].message,type:"error"})})).fail(Notification.exception)})),modal.getRoot().on(ModalEvents.hidden,(function(){modal.destroy()})),modal})).done((function(modal){modal.show()})).fail(Notification.exception)})),$(ACTIONS_SELECT_ALL).change((function(e){e.preventDefault(),$(this).is(":checked")?$(SELECTORS_SELECTCONTEXT).attr("checked","checked"):$(SELECTORS_SELECTCONTEXT).removeAttr("checked")}))},DataDeletionActions}));
+
+//# sourceMappingURL=data_deletion.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/data_deletion.min.js.map b/admin/tool/dataprivacy/amd/build/data_deletion.min.js.map
index 70995ebd33a..79fec21d7e6 100644
--- a/admin/tool/dataprivacy/amd/build/data_deletion.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/data_deletion.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/data_deletion.js"],"names":["define","$","Ajax","Notification","Str","ModalFactory","ModalEvents","ACTIONS","MARK_FOR_DELETION","SELECT_ALL","SELECTORS","SELECTCONTEXT","DataDeletionActions","registerEvents","prototype","click","e","preventDefault","selectedIds","each","checkbox","is","push","val","showConfirmation","change","selectallnone","attr","removeAttr","ids","modalTitle","get_strings","key","component","then","langStrings","confirmMessage","create","title","body","type","types","SAVE_CANCEL","modal","setSaveButtonText","getRoot","on","save","call","methodname","args","done","data","result","window","location","reload","addNotification","message","warnings","fail","exception","hidden","destroy","show"],"mappings":"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","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 .\n\n/**\n * Request actions.\n *\n * @module tool_dataprivacy/data_deletion\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events'],\nfunction($, Ajax, Notification, Str, ModalFactory, ModalEvents) {\n\n /**\n * List of action selectors.\n *\n * @type {{MARK_FOR_DELETION: string}}\n * @type {{SELECT_ALL: string}}\n */\n var ACTIONS = {\n MARK_FOR_DELETION: '[data-action=\"markfordeletion\"]',\n SELECT_ALL: '[data-action=\"selectall\"]',\n };\n\n /**\n * List of selectors.\n *\n * @type {{SELECTCONTEXT: string}}\n */\n var SELECTORS = {\n SELECTCONTEXT: '.selectcontext',\n };\n\n /**\n * DataDeletionActions class.\n */\n var DataDeletionActions = function() {\n this.registerEvents();\n };\n\n /**\n * Register event listeners.\n */\n DataDeletionActions.prototype.registerEvents = function() {\n $(ACTIONS.MARK_FOR_DELETION).click(function(e) {\n e.preventDefault();\n\n var selectedIds = [];\n $(SELECTORS.SELECTCONTEXT).each(function() {\n var checkbox = $(this);\n if (checkbox.is(':checked')) {\n selectedIds.push(checkbox.val());\n }\n });\n showConfirmation(selectedIds);\n });\n\n $(ACTIONS.SELECT_ALL).change(function(e) {\n e.preventDefault();\n\n var selectallnone = $(this);\n if (selectallnone.is(':checked')) {\n $(SELECTORS.SELECTCONTEXT).attr('checked', 'checked');\n } else {\n $(SELECTORS.SELECTCONTEXT).removeAttr('checked');\n }\n });\n };\n\n /**\n * Show the confirmation dialogue.\n *\n * @param {Array} ids The array of expired context record IDs.\n */\n function showConfirmation(ids) {\n var keys = [\n {\n key: 'confirm',\n component: 'moodle'\n },\n {\n key: 'confirmcontextdeletion',\n component: 'tool_dataprivacy'\n }\n ];\n var wsfunction = 'tool_dataprivacy_confirm_contexts_for_deletion';\n\n var modalTitle = '';\n Str.get_strings(keys).then(function(langStrings) {\n modalTitle = langStrings[0];\n var confirmMessage = langStrings[1];\n return ModalFactory.create({\n title: modalTitle,\n body: confirmMessage,\n type: ModalFactory.types.SAVE_CANCEL\n });\n }).then(function(modal) {\n modal.setSaveButtonText(modalTitle);\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function() {\n // Confirm the request.\n var params = {\n 'ids': ids\n };\n\n var request = {\n methodname: wsfunction,\n args: params\n };\n\n Ajax.call([request])[0].done(function(data) {\n if (data.result) {\n window.location.reload();\n } else {\n Notification.addNotification({\n message: data.warnings[0].message,\n type: 'error'\n });\n }\n }).fail(Notification.exception);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n return modal;\n }).done(function(modal) {\n modal.show();\n }).fail(Notification.exception);\n }\n\n return DataDeletionActions;\n});\n"],"file":"data_deletion.min.js"}
\ No newline at end of file
+{"version":3,"file":"data_deletion.min.js","sources":["../src/data_deletion.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 .\n\n/**\n * Request actions.\n *\n * @module tool_dataprivacy/data_deletion\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events'],\nfunction($, Ajax, Notification, Str, ModalFactory, ModalEvents) {\n\n /**\n * List of action selectors.\n *\n * @type {{MARK_FOR_DELETION: string}}\n * @type {{SELECT_ALL: string}}\n */\n var ACTIONS = {\n MARK_FOR_DELETION: '[data-action=\"markfordeletion\"]',\n SELECT_ALL: '[data-action=\"selectall\"]',\n };\n\n /**\n * List of selectors.\n *\n * @type {{SELECTCONTEXT: string}}\n */\n var SELECTORS = {\n SELECTCONTEXT: '.selectcontext',\n };\n\n /**\n * DataDeletionActions class.\n */\n var DataDeletionActions = function() {\n this.registerEvents();\n };\n\n /**\n * Register event listeners.\n */\n DataDeletionActions.prototype.registerEvents = function() {\n $(ACTIONS.MARK_FOR_DELETION).click(function(e) {\n e.preventDefault();\n\n var selectedIds = [];\n $(SELECTORS.SELECTCONTEXT).each(function() {\n var checkbox = $(this);\n if (checkbox.is(':checked')) {\n selectedIds.push(checkbox.val());\n }\n });\n showConfirmation(selectedIds);\n });\n\n $(ACTIONS.SELECT_ALL).change(function(e) {\n e.preventDefault();\n\n var selectallnone = $(this);\n if (selectallnone.is(':checked')) {\n $(SELECTORS.SELECTCONTEXT).attr('checked', 'checked');\n } else {\n $(SELECTORS.SELECTCONTEXT).removeAttr('checked');\n }\n });\n };\n\n /**\n * Show the confirmation dialogue.\n *\n * @param {Array} ids The array of expired context record IDs.\n */\n function showConfirmation(ids) {\n var keys = [\n {\n key: 'confirm',\n component: 'moodle'\n },\n {\n key: 'confirmcontextdeletion',\n component: 'tool_dataprivacy'\n }\n ];\n var wsfunction = 'tool_dataprivacy_confirm_contexts_for_deletion';\n\n var modalTitle = '';\n Str.get_strings(keys).then(function(langStrings) {\n modalTitle = langStrings[0];\n var confirmMessage = langStrings[1];\n return ModalFactory.create({\n title: modalTitle,\n body: confirmMessage,\n type: ModalFactory.types.SAVE_CANCEL\n });\n }).then(function(modal) {\n modal.setSaveButtonText(modalTitle);\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function() {\n // Confirm the request.\n var params = {\n 'ids': ids\n };\n\n var request = {\n methodname: wsfunction,\n args: params\n };\n\n Ajax.call([request])[0].done(function(data) {\n if (data.result) {\n window.location.reload();\n } else {\n Notification.addNotification({\n message: data.warnings[0].message,\n type: 'error'\n });\n }\n }).fail(Notification.exception);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n return modal;\n }).done(function(modal) {\n modal.show();\n }).fail(Notification.exception);\n }\n\n return DataDeletionActions;\n});\n"],"names":["define","$","Ajax","Notification","Str","ModalFactory","ModalEvents","ACTIONS","SELECTORS","DataDeletionActions","registerEvents","prototype","click","e","preventDefault","ids","keys","wsfunction","modalTitle","selectedIds","each","checkbox","this","is","push","val","key","component","get_strings","then","langStrings","confirmMessage","create","title","body","type","types","SAVE_CANCEL","modal","setSaveButtonText","getRoot","on","save","request","methodname","args","call","done","data","result","window","location","reload","addNotification","message","warnings","fail","exception","hidden","destroy","show","change","attr","removeAttr"],"mappings":";;;;;;;AAsBAA,wCAAO,CACH,SACA,YACA,oBACA,WACA,qBACA,sBACJ,SAASC,EAAGC,KAAMC,aAAcC,IAAKC,aAAcC,iBAQ3CC,0BACmB,kCADnBA,mBAEY,4BAQZC,wBACe,iBAMfC,oBAAsB,gBACjBC,yBAMTD,oBAAoBE,UAAUD,eAAiB,WAC3CT,EAAEM,2BAA2BK,OAAM,SAASC,GACxCA,EAAEC,qBA6BgBC,IAClBC,KAUAC,WAEAC,WAxCIC,YAAc,GAClBlB,EAAEO,yBAAyBY,MAAK,eACxBC,SAAWpB,EAAEqB,MACbD,SAASE,GAAG,aACZJ,YAAYK,KAAKH,SAASI,UAuBhBV,IApBDI,YAqBjBH,KAAO,CACP,CACIU,IAAK,UACLC,UAAW,UAEf,CACID,IAAK,yBACLC,UAAW,qBAGfV,WAAa,iDAEbC,WAAa,GACjBd,IAAIwB,YAAYZ,MAAMa,MAAK,SAASC,aAChCZ,WAAaY,YAAY,OACrBC,eAAiBD,YAAY,UAC1BzB,aAAa2B,OAAO,CACvBC,MAAOf,WACPgB,KAAMH,eACNI,KAAM9B,aAAa+B,MAAMC,iBAE9BR,MAAK,SAASS,cACbA,MAAMC,kBAAkBrB,YAGxBoB,MAAME,UAAUC,GAAGnC,YAAYoC,MAAM,eAM7BC,QAAU,CACVC,WAAY3B,WACZ4B,KANS,KACF9B,MAQXb,KAAK4C,KAAK,CAACH,UAAU,GAAGI,MAAK,SAASC,MAC9BA,KAAKC,OACLC,OAAOC,SAASC,SAEhBjD,aAAakD,gBAAgB,CACzBC,QAASN,KAAKO,SAAS,GAAGD,QAC1BnB,KAAM,aAGfqB,KAAKrD,aAAasD,cAIzBnB,MAAME,UAAUC,GAAGnC,YAAYoD,QAAQ,WAEnCpB,MAAMqB,aAGHrB,SACRS,MAAK,SAAST,OACbA,MAAMsB,UACPJ,KAAKrD,aAAasD,cA3ErBxD,EAAEM,oBAAoBsD,QAAO,SAAShD,GAClCA,EAAEC,iBAEkBb,EAAEqB,MACJC,GAAG,YACjBtB,EAAEO,yBAAyBsD,KAAK,UAAW,WAE3C7D,EAAEO,yBAAyBuD,WAAW,eAuE3CtD"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/data_registry.min.js b/admin/tool/dataprivacy/amd/build/data_registry.min.js
index 44c2310075f..5dd4d5ed6eb 100644
--- a/admin/tool/dataprivacy/amd/build/data_registry.min.js
+++ b/admin/tool/dataprivacy/amd/build/data_registry.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/data_registry",["jquery","core/str","core/ajax","core/notification","core/templates","core/modal_factory","core/modal_events","core/fragment","tool_dataprivacy/add_purpose","tool_dataprivacy/add_category"],function(a,b,c,d,e,f,g,h,i,j){var k={TREE_NODES:"[data-context-tree-node=1]",FORM_CONTAINER:"#context-form-container"},l=function(a,b,c){this.systemContextId=a;this.currentContextLevel=b;this.currentContextId=c;this.init()};l.prototype.systemContextId=0;l.prototype.currentContextLevel=0;l.prototype.currentContextId=0;l.prototype.addpurpose=null;l.prototype.addcategory=null;l.prototype.init=function(){this.addpurpose=i.getInstance(this.systemContextId);this.addcategory=j.getInstance(this.systemContextId);this.strings=b.get_strings([{key:"changessaved",component:"moodle"},{key:"contextpurposecategorysaved",component:"tool_dataprivacy"},{key:"noblockstoload",component:"tool_dataprivacy"},{key:"noactivitiestoload",component:"tool_dataprivacy"},{key:"nocoursestoload",component:"tool_dataprivacy"}]);this.registerEventListeners();if(this.currentContextId){this.loadForm("context_form",[this.currentContextId],this.submitContextFormAjax.bind(this))}else{this.loadForm("contextlevel_form",[this.currentContextLevel],this.submitContextLevelFormAjax.bind(this))}};l.prototype.registerEventListeners=function(){a(k.TREE_NODES).on("click",function(b){b.preventDefault();var c=a(b.currentTarget);a(k.TREE_NODES).removeClass("active");c.addClass("active");var d=c.data("contextlevel"),e=c.data("contextid");if(d){window.history.pushState({},null,"?contextlevel="+d);this.addpurpose.removeListeners();this.addcategory.removeListeners();this.currentContextLevel=d;this.loadForm("contextlevel_form",[this.currentContextLevel],this.submitContextLevelFormAjax.bind(this))}else if(e){window.history.pushState({},null,"?contextid="+e);this.addpurpose.removeListeners();this.addcategory.removeListeners();this.currentContextId=e;this.loadForm("context_form",[this.currentContextId],this.submitContextFormAjax.bind(this))}else{var f=c.data("expandcontextid"),g=c.data("expandelement"),h=c.data("expanded");if(g){if(!h){if(c.data("loaded")||!f||!g){this.expand(c)}else{c.find("> i").removeClass("fa-plus");c.find("> i").addClass("fa-circle-o-notch fa-spin");this.loadExtra(c,f,g)}}else{this.collapse(c)}}}}.bind(this))};l.prototype.removeListeners=function(){a(k.TREE_NODES).off("click")};l.prototype.loadForm=function(b,c,f){this.clearForm();var g=h.loadFragment("tool_dataprivacy",b,this.systemContextId,c);g.done(function(b,c){a(k.FORM_CONTAINER).html(b);e.runTemplateJS(c);this.addpurpose.registerEventListeners();this.addcategory.registerEventListeners();a(k.FORM_CONTAINER).on("submit","form",f)}.bind(this)).fail(d.exception)};l.prototype.clearForm=function(){a(k.FORM_CONTAINER).off("submit","form")};l.prototype.submitForm=function(b){b.preventDefault();a(k.FORM_CONTAINER).find("form").submit()};l.prototype.submitContextLevelFormAjax=function(a){this.submitFormAjax(a,"tool_dataprivacy_set_contextlevel_form")};l.prototype.submitContextFormAjax=function(a){this.submitFormAjax(a,"tool_dataprivacy_set_context_form")};l.prototype.submitFormAjax=function(b,e){b.preventDefault();var f=a(k.FORM_CONTAINER).find("form").serialize();return this.strings.then(function(a){c.call([{methodname:e,args:{jsonformdata:JSON.stringify(f)},done:function done(){d.alert(a[0],a[1])},fail:d.exception}])}).catch(d.exception)};l.prototype.loadExtra=function(a,b,f){c.call([{methodname:"tool_dataprivacy_tree_extra_branches",args:{contextid:b,element:f},done:function(b){if(0==b.branches.length){this.noElements(a,f);return}e.render("tool_dataprivacy/context_tree_branches",b).then(function(b){a.after(b);this.removeListeners();this.registerEventListeners();this.expand(a);a.data("loaded",1)}.bind(this)).fail(d.exception)}.bind(this),fail:d.exception}])};l.prototype.noElements=function(a,b){a.data("expandcontextid","");a.data("expandelement","");this.strings.then(function(c){var d=2;if("module"==b){d=3}else if("course"==b){d=4}a.text(c[d])}).fail(d.exception)};l.prototype.collapse=function(a){a.data("expanded",0);a.siblings("nav").addClass("hidden");a.find("> i").removeClass("fa-minus");a.find("> i").addClass("fa-plus")};l.prototype.expand=function(a){a.data("expanded",1);a.siblings("nav").removeClass("hidden");a.find("> i").removeClass("fa-plus");a.find("> i").removeClass("fa-circle-o-notch fa-spin");a.find("> i").addClass("fa-minus")};return{init:function init(a,b,c){return new l(a,b,c)}}});
-//# sourceMappingURL=data_registry.min.js.map
+/**
+ * Request actions.
+ *
+ * @module tool_dataprivacy/data_registry
+ * @copyright 2018 David Monllao
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/data_registry",["jquery","core/str","core/ajax","core/notification","core/templates","core/modal_factory","core/modal_events","core/fragment","tool_dataprivacy/add_purpose","tool_dataprivacy/add_category"],(function($,Str,Ajax,Notification,Templates,ModalFactory,ModalEvents,Fragment,AddPurpose,AddCategory){var SELECTORS_TREE_NODES="[data-context-tree-node=1]",SELECTORS_FORM_CONTAINER="#context-form-container",DataRegistry=function(systemContextId,initContextLevel,initContextId){this.systemContextId=systemContextId,this.currentContextLevel=initContextLevel,this.currentContextId=initContextId,this.init()};return DataRegistry.prototype.systemContextId=0,DataRegistry.prototype.currentContextLevel=0,DataRegistry.prototype.currentContextId=0,DataRegistry.prototype.addpurpose=null,DataRegistry.prototype.addcategory=null,DataRegistry.prototype.init=function(){this.addpurpose=AddPurpose.getInstance(this.systemContextId),this.addcategory=AddCategory.getInstance(this.systemContextId);this.strings=Str.get_strings([{key:"changessaved",component:"moodle"},{key:"contextpurposecategorysaved",component:"tool_dataprivacy"},{key:"noblockstoload",component:"tool_dataprivacy"},{key:"noactivitiestoload",component:"tool_dataprivacy"},{key:"nocoursestoload",component:"tool_dataprivacy"}]),this.registerEventListeners(),this.currentContextId?this.loadForm("context_form",[this.currentContextId],this.submitContextFormAjax.bind(this)):this.loadForm("contextlevel_form",[this.currentContextLevel],this.submitContextLevelFormAjax.bind(this))},DataRegistry.prototype.registerEventListeners=function(){$(SELECTORS_TREE_NODES).on("click",function(ev){ev.preventDefault();var trigger=$(ev.currentTarget);$(SELECTORS_TREE_NODES).removeClass("active"),trigger.addClass("active");var contextLevel=trigger.data("contextlevel"),contextId=trigger.data("contextid");if(contextLevel)window.history.pushState({},null,"?contextlevel="+contextLevel),this.addpurpose.removeListeners(),this.addcategory.removeListeners(),this.currentContextLevel=contextLevel,this.loadForm("contextlevel_form",[this.currentContextLevel],this.submitContextLevelFormAjax.bind(this));else if(contextId)window.history.pushState({},null,"?contextid="+contextId),this.addpurpose.removeListeners(),this.addcategory.removeListeners(),this.currentContextId=contextId,this.loadForm("context_form",[this.currentContextId],this.submitContextFormAjax.bind(this));else{var expandContextId=trigger.data("expandcontextid"),expandElement=trigger.data("expandelement"),expanded=trigger.data("expanded");expandElement&&(expanded?this.collapse(trigger):!trigger.data("loaded")&&expandContextId&&expandElement?(trigger.find("> i").removeClass("fa-plus"),trigger.find("> i").addClass("fa-circle-o-notch fa-spin"),this.loadExtra(trigger,expandContextId,expandElement)):this.expand(trigger))}}.bind(this))},DataRegistry.prototype.removeListeners=function(){$(SELECTORS_TREE_NODES).off("click")},DataRegistry.prototype.loadForm=function(fragmentName,fragmentArgs,formSubmitCallback){this.clearForm(),Fragment.loadFragment("tool_dataprivacy",fragmentName,this.systemContextId,fragmentArgs).done(function(html,js){$(SELECTORS_FORM_CONTAINER).html(html),Templates.runTemplateJS(js),this.addpurpose.registerEventListeners(),this.addcategory.registerEventListeners(),$(SELECTORS_FORM_CONTAINER).on("submit","form",formSubmitCallback)}.bind(this)).fail(Notification.exception)},DataRegistry.prototype.clearForm=function(){$(SELECTORS_FORM_CONTAINER).off("submit","form")},DataRegistry.prototype.submitForm=function(e){e.preventDefault(),$(SELECTORS_FORM_CONTAINER).find("form").submit()},DataRegistry.prototype.submitContextLevelFormAjax=function(e){this.submitFormAjax(e,"tool_dataprivacy_set_contextlevel_form")},DataRegistry.prototype.submitContextFormAjax=function(e){this.submitFormAjax(e,"tool_dataprivacy_set_context_form")},DataRegistry.prototype.submitFormAjax=function(e,saveMethodName){e.preventDefault();var formData=$(SELECTORS_FORM_CONTAINER).find("form").serialize();return this.strings.then((function(strings){Ajax.call([{methodname:saveMethodName,args:{jsonformdata:JSON.stringify(formData)},done:function(){Notification.alert(strings[0],strings[1])},fail:Notification.exception}])})).catch(Notification.exception)},DataRegistry.prototype.loadExtra=function(parentNode,expandContextId,expandElement){Ajax.call([{methodname:"tool_dataprivacy_tree_extra_branches",args:{contextid:expandContextId,element:expandElement},done:function(data){0!=data.branches.length?Templates.render("tool_dataprivacy/context_tree_branches",data).then(function(html){parentNode.after(html),this.removeListeners(),this.registerEventListeners(),this.expand(parentNode),parentNode.data("loaded",1)}.bind(this)).fail(Notification.exception):this.noElements(parentNode,expandElement)}.bind(this),fail:Notification.exception}])},DataRegistry.prototype.noElements=function(node,expandElement){node.data("expandcontextid",""),node.data("expandelement",""),this.strings.then((function(strings){var key=2;"module"==expandElement?key=3:"course"==expandElement&&(key=4),node.text(strings[key])})).fail(Notification.exception)},DataRegistry.prototype.collapse=function(node){node.data("expanded",0),node.siblings("nav").addClass("hidden"),node.find("> i").removeClass("fa-minus"),node.find("> i").addClass("fa-plus")},DataRegistry.prototype.expand=function(node){node.data("expanded",1),node.siblings("nav").removeClass("hidden"),node.find("> i").removeClass("fa-plus"),node.find("> i").removeClass("fa-circle-o-notch fa-spin"),node.find("> i").addClass("fa-minus")},{init:function(systemContextId,initContextLevel,initContextId){return new DataRegistry(systemContextId,initContextLevel,initContextId)}}}));
+
+//# sourceMappingURL=data_registry.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/data_registry.min.js.map b/admin/tool/dataprivacy/amd/build/data_registry.min.js.map
index 02e3bb008c7..235aef226ce 100644
--- a/admin/tool/dataprivacy/amd/build/data_registry.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/data_registry.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/data_registry.js"],"names":["define","$","Str","Ajax","Notification","Templates","ModalFactory","ModalEvents","Fragment","AddPurpose","AddCategory","SELECTORS","TREE_NODES","FORM_CONTAINER","DataRegistry","systemContextId","initContextLevel","initContextId","currentContextLevel","currentContextId","init","prototype","addpurpose","addcategory","getInstance","strings","get_strings","key","component","registerEventListeners","loadForm","submitContextFormAjax","bind","submitContextLevelFormAjax","on","ev","preventDefault","trigger","currentTarget","removeClass","addClass","contextLevel","data","contextId","window","history","pushState","removeListeners","expandContextId","expandElement","expanded","expand","find","loadExtra","collapse","off","fragmentName","fragmentArgs","formSubmitCallback","clearForm","fragment","loadFragment","done","html","js","runTemplateJS","fail","exception","submitForm","e","submit","submitFormAjax","saveMethodName","formData","serialize","then","call","methodname","args","jsonformdata","JSON","stringify","alert","catch","parentNode","contextid","element","branches","length","noElements","render","after","node","text","siblings"],"mappings":"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","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 .\n\n/**\n * Request actions.\n *\n * @module tool_dataprivacy/data_registry\n * @copyright 2018 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/str', 'core/ajax', 'core/notification', 'core/templates', 'core/modal_factory',\n 'core/modal_events', 'core/fragment', 'tool_dataprivacy/add_purpose', 'tool_dataprivacy/add_category'],\n function($, Str, Ajax, Notification, Templates, ModalFactory, ModalEvents, Fragment, AddPurpose, AddCategory) {\n\n var SELECTORS = {\n TREE_NODES: '[data-context-tree-node=1]',\n FORM_CONTAINER: '#context-form-container',\n };\n\n var DataRegistry = function(systemContextId, initContextLevel, initContextId) {\n this.systemContextId = systemContextId;\n this.currentContextLevel = initContextLevel;\n this.currentContextId = initContextId;\n this.init();\n };\n\n /**\n * @var {int} systemContextId\n * @private\n */\n DataRegistry.prototype.systemContextId = 0;\n\n /**\n * @var {int} currentContextLevel\n * @private\n */\n DataRegistry.prototype.currentContextLevel = 0;\n\n /**\n * @var {int} currentContextId\n * @private\n */\n DataRegistry.prototype.currentContextId = 0;\n\n /**\n * @var {AddPurpose} addpurpose\n * @private\n */\n DataRegistry.prototype.addpurpose = null;\n\n /**\n * @var {AddCategory} addcategory\n * @private\n */\n DataRegistry.prototype.addcategory = null;\n\n DataRegistry.prototype.init = function() {\n // Add purpose and category modals always at system context.\n this.addpurpose = AddPurpose.getInstance(this.systemContextId);\n this.addcategory = AddCategory.getInstance(this.systemContextId);\n\n var stringKeys = [\n {\n key: 'changessaved',\n component: 'moodle'\n }, {\n key: 'contextpurposecategorysaved',\n component: 'tool_dataprivacy'\n }, {\n key: 'noblockstoload',\n component: 'tool_dataprivacy'\n }, {\n key: 'noactivitiestoload',\n component: 'tool_dataprivacy'\n }, {\n key: 'nocoursestoload',\n component: 'tool_dataprivacy'\n }\n ];\n this.strings = Str.get_strings(stringKeys);\n\n this.registerEventListeners();\n\n // Load the default context level form.\n if (this.currentContextId) {\n this.loadForm('context_form', [this.currentContextId], this.submitContextFormAjax.bind(this));\n } else {\n this.loadForm('contextlevel_form', [this.currentContextLevel], this.submitContextLevelFormAjax.bind(this));\n }\n };\n\n DataRegistry.prototype.registerEventListeners = function() {\n $(SELECTORS.TREE_NODES).on('click', function(ev) {\n ev.preventDefault();\n\n var trigger = $(ev.currentTarget);\n\n // Active node.\n $(SELECTORS.TREE_NODES).removeClass('active');\n trigger.addClass('active');\n\n var contextLevel = trigger.data('contextlevel');\n var contextId = trigger.data('contextid');\n if (contextLevel) {\n // Context level level.\n\n window.history.pushState({}, null, '?contextlevel=' + contextLevel);\n\n // Remove previous add purpose and category listeners to avoid memory leaks.\n this.addpurpose.removeListeners();\n this.addcategory.removeListeners();\n\n // Load the context level form.\n this.currentContextLevel = contextLevel;\n this.loadForm('contextlevel_form', [this.currentContextLevel], this.submitContextLevelFormAjax.bind(this));\n } else if (contextId) {\n // Context instance level.\n\n window.history.pushState({}, null, '?contextid=' + contextId);\n\n // Remove previous add purpose and category listeners to avoid memory leaks.\n this.addpurpose.removeListeners();\n this.addcategory.removeListeners();\n\n // Load the context level form.\n this.currentContextId = contextId;\n this.loadForm('context_form', [this.currentContextId], this.submitContextFormAjax.bind(this));\n } else {\n // Expandable nodes.\n\n var expandContextId = trigger.data('expandcontextid');\n var expandElement = trigger.data('expandelement');\n var expanded = trigger.data('expanded');\n\n // Extra checking that there is an expandElement because we remove it after loading 0 branches.\n if (expandElement) {\n\n if (!expanded) {\n if (trigger.data('loaded') || !expandContextId || !expandElement) {\n this.expand(trigger);\n } else {\n\n trigger.find('> i').removeClass('fa-plus');\n trigger.find('> i').addClass('fa-circle-o-notch fa-spin');\n this.loadExtra(trigger, expandContextId, expandElement);\n }\n } else {\n this.collapse(trigger);\n }\n }\n }\n\n }.bind(this));\n };\n\n DataRegistry.prototype.removeListeners = function() {\n $(SELECTORS.TREE_NODES).off('click');\n };\n\n DataRegistry.prototype.loadForm = function(fragmentName, fragmentArgs, formSubmitCallback) {\n\n this.clearForm();\n\n var fragment = Fragment.loadFragment('tool_dataprivacy', fragmentName, this.systemContextId, fragmentArgs);\n fragment.done(function(html, js) {\n\n $(SELECTORS.FORM_CONTAINER).html(html);\n Templates.runTemplateJS(js);\n\n this.addpurpose.registerEventListeners();\n this.addcategory.registerEventListeners();\n\n // We also catch the form submit event and use it to submit the form with ajax.\n $(SELECTORS.FORM_CONTAINER).on('submit', 'form', formSubmitCallback);\n\n }.bind(this)).fail(Notification.exception);\n };\n\n DataRegistry.prototype.clearForm = function() {\n // Remove previous listeners.\n $(SELECTORS.FORM_CONTAINER).off('submit', 'form');\n };\n\n /**\n * This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.\n *\n * @method submitForm\n * @param {Event} e Form submission event.\n * @private\n */\n DataRegistry.prototype.submitForm = function(e) {\n e.preventDefault();\n $(SELECTORS.FORM_CONTAINER).find('form').submit();\n };\n\n DataRegistry.prototype.submitContextLevelFormAjax = function(e) {\n this.submitFormAjax(e, 'tool_dataprivacy_set_contextlevel_form');\n };\n\n DataRegistry.prototype.submitContextFormAjax = function(e) {\n this.submitFormAjax(e, 'tool_dataprivacy_set_context_form');\n };\n\n DataRegistry.prototype.submitFormAjax = function(e, saveMethodName) {\n // We don't want to do a real form submission.\n e.preventDefault();\n\n // Convert all the form elements values to a serialised string.\n var formData = $(SELECTORS.FORM_CONTAINER).find('form').serialize();\n return this.strings.then(function(strings) {\n Ajax.call([{\n methodname: saveMethodName,\n args: {jsonformdata: JSON.stringify(formData)},\n done: function() {\n Notification.alert(strings[0], strings[1]);\n },\n fail: Notification.exception\n }]);\n return;\n }).catch(Notification.exception);\n\n };\n\n DataRegistry.prototype.loadExtra = function(parentNode, expandContextId, expandElement) {\n\n Ajax.call([{\n methodname: 'tool_dataprivacy_tree_extra_branches',\n args: {\n contextid: expandContextId,\n element: expandElement,\n },\n done: function(data) {\n if (data.branches.length == 0) {\n this.noElements(parentNode, expandElement);\n return;\n }\n Templates.render('tool_dataprivacy/context_tree_branches', data)\n .then(function(html) {\n parentNode.after(html);\n this.removeListeners();\n this.registerEventListeners();\n this.expand(parentNode);\n parentNode.data('loaded', 1);\n return;\n }.bind(this))\n .fail(Notification.exception);\n }.bind(this),\n fail: Notification.exception\n }]);\n };\n\n DataRegistry.prototype.noElements = function(node, expandElement) {\n node.data('expandcontextid', '');\n node.data('expandelement', '');\n this.strings.then(function(strings) {\n\n // 2 = blocks, 3 = activities, 4 = courses (although courses is not likely really).\n var key = 2;\n if (expandElement == 'module') {\n key = 3;\n } else if (expandElement == 'course') {\n key = 4;\n }\n node.text(strings[key]);\n return;\n }).fail(Notification.exception);\n };\n\n DataRegistry.prototype.collapse = function(node) {\n node.data('expanded', 0);\n node.siblings('nav').addClass('hidden');\n node.find('> i').removeClass('fa-minus');\n node.find('> i').addClass('fa-plus');\n };\n\n DataRegistry.prototype.expand = function(node) {\n node.data('expanded', 1);\n node.siblings('nav').removeClass('hidden');\n node.find('> i').removeClass('fa-plus');\n // Also remove the spinning one if data was just loaded.\n node.find('> i').removeClass('fa-circle-o-notch fa-spin');\n node.find('> i').addClass('fa-minus');\n };\n return /** @alias module:tool_dataprivacy/data_registry */ {\n\n /**\n * Initialise the page.\n *\n * @param {Number} systemContextId\n * @param {Number} initContextLevel\n * @param {Number} initContextId\n * @return {DataRegistry}\n */\n init: function(systemContextId, initContextLevel, initContextId) {\n return new DataRegistry(systemContextId, initContextLevel, initContextId);\n }\n };\n }\n);\n\n"],"file":"data_registry.min.js"}
\ No newline at end of file
+{"version":3,"file":"data_registry.min.js","sources":["../src/data_registry.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 .\n\n/**\n * Request actions.\n *\n * @module tool_dataprivacy/data_registry\n * @copyright 2018 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/str', 'core/ajax', 'core/notification', 'core/templates', 'core/modal_factory',\n 'core/modal_events', 'core/fragment', 'tool_dataprivacy/add_purpose', 'tool_dataprivacy/add_category'],\n function($, Str, Ajax, Notification, Templates, ModalFactory, ModalEvents, Fragment, AddPurpose, AddCategory) {\n\n var SELECTORS = {\n TREE_NODES: '[data-context-tree-node=1]',\n FORM_CONTAINER: '#context-form-container',\n };\n\n var DataRegistry = function(systemContextId, initContextLevel, initContextId) {\n this.systemContextId = systemContextId;\n this.currentContextLevel = initContextLevel;\n this.currentContextId = initContextId;\n this.init();\n };\n\n /**\n * @var {int} systemContextId\n * @private\n */\n DataRegistry.prototype.systemContextId = 0;\n\n /**\n * @var {int} currentContextLevel\n * @private\n */\n DataRegistry.prototype.currentContextLevel = 0;\n\n /**\n * @var {int} currentContextId\n * @private\n */\n DataRegistry.prototype.currentContextId = 0;\n\n /**\n * @var {AddPurpose} addpurpose\n * @private\n */\n DataRegistry.prototype.addpurpose = null;\n\n /**\n * @var {AddCategory} addcategory\n * @private\n */\n DataRegistry.prototype.addcategory = null;\n\n DataRegistry.prototype.init = function() {\n // Add purpose and category modals always at system context.\n this.addpurpose = AddPurpose.getInstance(this.systemContextId);\n this.addcategory = AddCategory.getInstance(this.systemContextId);\n\n var stringKeys = [\n {\n key: 'changessaved',\n component: 'moodle'\n }, {\n key: 'contextpurposecategorysaved',\n component: 'tool_dataprivacy'\n }, {\n key: 'noblockstoload',\n component: 'tool_dataprivacy'\n }, {\n key: 'noactivitiestoload',\n component: 'tool_dataprivacy'\n }, {\n key: 'nocoursestoload',\n component: 'tool_dataprivacy'\n }\n ];\n this.strings = Str.get_strings(stringKeys);\n\n this.registerEventListeners();\n\n // Load the default context level form.\n if (this.currentContextId) {\n this.loadForm('context_form', [this.currentContextId], this.submitContextFormAjax.bind(this));\n } else {\n this.loadForm('contextlevel_form', [this.currentContextLevel], this.submitContextLevelFormAjax.bind(this));\n }\n };\n\n DataRegistry.prototype.registerEventListeners = function() {\n $(SELECTORS.TREE_NODES).on('click', function(ev) {\n ev.preventDefault();\n\n var trigger = $(ev.currentTarget);\n\n // Active node.\n $(SELECTORS.TREE_NODES).removeClass('active');\n trigger.addClass('active');\n\n var contextLevel = trigger.data('contextlevel');\n var contextId = trigger.data('contextid');\n if (contextLevel) {\n // Context level level.\n\n window.history.pushState({}, null, '?contextlevel=' + contextLevel);\n\n // Remove previous add purpose and category listeners to avoid memory leaks.\n this.addpurpose.removeListeners();\n this.addcategory.removeListeners();\n\n // Load the context level form.\n this.currentContextLevel = contextLevel;\n this.loadForm('contextlevel_form', [this.currentContextLevel], this.submitContextLevelFormAjax.bind(this));\n } else if (contextId) {\n // Context instance level.\n\n window.history.pushState({}, null, '?contextid=' + contextId);\n\n // Remove previous add purpose and category listeners to avoid memory leaks.\n this.addpurpose.removeListeners();\n this.addcategory.removeListeners();\n\n // Load the context level form.\n this.currentContextId = contextId;\n this.loadForm('context_form', [this.currentContextId], this.submitContextFormAjax.bind(this));\n } else {\n // Expandable nodes.\n\n var expandContextId = trigger.data('expandcontextid');\n var expandElement = trigger.data('expandelement');\n var expanded = trigger.data('expanded');\n\n // Extra checking that there is an expandElement because we remove it after loading 0 branches.\n if (expandElement) {\n\n if (!expanded) {\n if (trigger.data('loaded') || !expandContextId || !expandElement) {\n this.expand(trigger);\n } else {\n\n trigger.find('> i').removeClass('fa-plus');\n trigger.find('> i').addClass('fa-circle-o-notch fa-spin');\n this.loadExtra(trigger, expandContextId, expandElement);\n }\n } else {\n this.collapse(trigger);\n }\n }\n }\n\n }.bind(this));\n };\n\n DataRegistry.prototype.removeListeners = function() {\n $(SELECTORS.TREE_NODES).off('click');\n };\n\n DataRegistry.prototype.loadForm = function(fragmentName, fragmentArgs, formSubmitCallback) {\n\n this.clearForm();\n\n var fragment = Fragment.loadFragment('tool_dataprivacy', fragmentName, this.systemContextId, fragmentArgs);\n fragment.done(function(html, js) {\n\n $(SELECTORS.FORM_CONTAINER).html(html);\n Templates.runTemplateJS(js);\n\n this.addpurpose.registerEventListeners();\n this.addcategory.registerEventListeners();\n\n // We also catch the form submit event and use it to submit the form with ajax.\n $(SELECTORS.FORM_CONTAINER).on('submit', 'form', formSubmitCallback);\n\n }.bind(this)).fail(Notification.exception);\n };\n\n DataRegistry.prototype.clearForm = function() {\n // Remove previous listeners.\n $(SELECTORS.FORM_CONTAINER).off('submit', 'form');\n };\n\n /**\n * This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.\n *\n * @method submitForm\n * @param {Event} e Form submission event.\n * @private\n */\n DataRegistry.prototype.submitForm = function(e) {\n e.preventDefault();\n $(SELECTORS.FORM_CONTAINER).find('form').submit();\n };\n\n DataRegistry.prototype.submitContextLevelFormAjax = function(e) {\n this.submitFormAjax(e, 'tool_dataprivacy_set_contextlevel_form');\n };\n\n DataRegistry.prototype.submitContextFormAjax = function(e) {\n this.submitFormAjax(e, 'tool_dataprivacy_set_context_form');\n };\n\n DataRegistry.prototype.submitFormAjax = function(e, saveMethodName) {\n // We don't want to do a real form submission.\n e.preventDefault();\n\n // Convert all the form elements values to a serialised string.\n var formData = $(SELECTORS.FORM_CONTAINER).find('form').serialize();\n return this.strings.then(function(strings) {\n Ajax.call([{\n methodname: saveMethodName,\n args: {jsonformdata: JSON.stringify(formData)},\n done: function() {\n Notification.alert(strings[0], strings[1]);\n },\n fail: Notification.exception\n }]);\n return;\n }).catch(Notification.exception);\n\n };\n\n DataRegistry.prototype.loadExtra = function(parentNode, expandContextId, expandElement) {\n\n Ajax.call([{\n methodname: 'tool_dataprivacy_tree_extra_branches',\n args: {\n contextid: expandContextId,\n element: expandElement,\n },\n done: function(data) {\n if (data.branches.length == 0) {\n this.noElements(parentNode, expandElement);\n return;\n }\n Templates.render('tool_dataprivacy/context_tree_branches', data)\n .then(function(html) {\n parentNode.after(html);\n this.removeListeners();\n this.registerEventListeners();\n this.expand(parentNode);\n parentNode.data('loaded', 1);\n return;\n }.bind(this))\n .fail(Notification.exception);\n }.bind(this),\n fail: Notification.exception\n }]);\n };\n\n DataRegistry.prototype.noElements = function(node, expandElement) {\n node.data('expandcontextid', '');\n node.data('expandelement', '');\n this.strings.then(function(strings) {\n\n // 2 = blocks, 3 = activities, 4 = courses (although courses is not likely really).\n var key = 2;\n if (expandElement == 'module') {\n key = 3;\n } else if (expandElement == 'course') {\n key = 4;\n }\n node.text(strings[key]);\n return;\n }).fail(Notification.exception);\n };\n\n DataRegistry.prototype.collapse = function(node) {\n node.data('expanded', 0);\n node.siblings('nav').addClass('hidden');\n node.find('> i').removeClass('fa-minus');\n node.find('> i').addClass('fa-plus');\n };\n\n DataRegistry.prototype.expand = function(node) {\n node.data('expanded', 1);\n node.siblings('nav').removeClass('hidden');\n node.find('> i').removeClass('fa-plus');\n // Also remove the spinning one if data was just loaded.\n node.find('> i').removeClass('fa-circle-o-notch fa-spin');\n node.find('> i').addClass('fa-minus');\n };\n return /** @alias module:tool_dataprivacy/data_registry */ {\n\n /**\n * Initialise the page.\n *\n * @param {Number} systemContextId\n * @param {Number} initContextLevel\n * @param {Number} initContextId\n * @return {DataRegistry}\n */\n init: function(systemContextId, initContextLevel, initContextId) {\n return new DataRegistry(systemContextId, initContextLevel, initContextId);\n }\n };\n }\n);\n\n"],"names":["define","$","Str","Ajax","Notification","Templates","ModalFactory","ModalEvents","Fragment","AddPurpose","AddCategory","SELECTORS","DataRegistry","systemContextId","initContextLevel","initContextId","currentContextLevel","currentContextId","init","prototype","addpurpose","addcategory","getInstance","this","strings","get_strings","key","component","registerEventListeners","loadForm","submitContextFormAjax","bind","submitContextLevelFormAjax","on","ev","preventDefault","trigger","currentTarget","removeClass","addClass","contextLevel","data","contextId","window","history","pushState","removeListeners","expandContextId","expandElement","expanded","collapse","find","loadExtra","expand","off","fragmentName","fragmentArgs","formSubmitCallback","clearForm","loadFragment","done","html","js","runTemplateJS","fail","exception","submitForm","e","submit","submitFormAjax","saveMethodName","formData","serialize","then","call","methodname","args","jsonformdata","JSON","stringify","alert","catch","parentNode","contextid","element","branches","length","render","after","noElements","node","text","siblings"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/data_request_modal.min.js b/admin/tool/dataprivacy/amd/build/data_request_modal.min.js
index 2027d4408fd..bb9b4c44ef3 100644
--- a/admin/tool/dataprivacy/amd/build/data_request_modal.min.js
+++ b/admin/tool/dataprivacy/amd/build/data_request_modal.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/data_request_modal",["jquery","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","tool_dataprivacy/events"],function(a,b,c,d,e,f){var g=!1,h={APPROVE_BUTTON:"[data-action=\"approve\"]",DENY_BUTTON:"[data-action=\"deny\"]",COMPLETE_BUTTON:"[data-action=\"complete\"]"},i=function(a){d.call(this,a)};i.TYPE="tool_dataprivacy-data_request";i.prototype=Object.create(d.prototype);i.prototype.constructor=i;i.prototype.registerEventListeners=function(){d.prototype.registerEventListeners.call(this);this.getModal().on(c.events.activate,h.APPROVE_BUTTON,function(b,c){var d=a.Event(f.approve);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this));this.getModal().on(c.events.activate,h.DENY_BUTTON,function(b,c){var d=a.Event(f.deny);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this));this.getModal().on(c.events.activate,h.COMPLETE_BUTTON,function(b,c){var d=a.Event(f.complete);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this))};if(!g){e.register(i.TYPE,i,"tool_dataprivacy/data_request_modal");g=!0}return i});
-//# sourceMappingURL=data_request_modal.min.js.map
+/**
+ * Request actions.
+ *
+ * @module tool_dataprivacy/data_request_modal
+ * @copyright 2018 Jun Pataleta
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/data_request_modal",["jquery","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","tool_dataprivacy/events"],(function($,Notification,CustomEvents,Modal,ModalRegistry,DataPrivacyEvents){var registered=!1,SELECTORS_APPROVE_BUTTON='[data-action="approve"]',SELECTORS_DENY_BUTTON='[data-action="deny"]',SELECTORS_COMPLETE_BUTTON='[data-action="complete"]',ModalDataRequest=function(root){Modal.call(this,root)};return ModalDataRequest.TYPE="tool_dataprivacy-data_request",(ModalDataRequest.prototype=Object.create(Modal.prototype)).constructor=ModalDataRequest,ModalDataRequest.prototype.registerEventListeners=function(){Modal.prototype.registerEventListeners.call(this),this.getModal().on(CustomEvents.events.activate,SELECTORS_APPROVE_BUTTON,function(e,data){var approveEvent=$.Event(DataPrivacyEvents.approve);this.getRoot().trigger(approveEvent,this),approveEvent.isDefaultPrevented()||(this.hide(),data.originalEvent.preventDefault())}.bind(this)),this.getModal().on(CustomEvents.events.activate,SELECTORS_DENY_BUTTON,function(e,data){var denyEvent=$.Event(DataPrivacyEvents.deny);this.getRoot().trigger(denyEvent,this),denyEvent.isDefaultPrevented()||(this.hide(),data.originalEvent.preventDefault())}.bind(this)),this.getModal().on(CustomEvents.events.activate,SELECTORS_COMPLETE_BUTTON,function(e,data){var completeEvent=$.Event(DataPrivacyEvents.complete);this.getRoot().trigger(completeEvent,this),completeEvent.isDefaultPrevented()||(this.hide(),data.originalEvent.preventDefault())}.bind(this))},registered||(ModalRegistry.register(ModalDataRequest.TYPE,ModalDataRequest,"tool_dataprivacy/data_request_modal"),registered=!0),ModalDataRequest}));
+
+//# sourceMappingURL=data_request_modal.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/data_request_modal.min.js.map b/admin/tool/dataprivacy/amd/build/data_request_modal.min.js.map
index b8e2c8bb9d9..ef4fbb7deda 100644
--- a/admin/tool/dataprivacy/amd/build/data_request_modal.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/data_request_modal.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/data_request_modal.js"],"names":["define","$","Notification","CustomEvents","Modal","ModalRegistry","DataPrivacyEvents","registered","SELECTORS","APPROVE_BUTTON","DENY_BUTTON","COMPLETE_BUTTON","ModalDataRequest","root","call","TYPE","prototype","Object","create","constructor","registerEventListeners","getModal","on","events","activate","e","data","approveEvent","Event","approve","getRoot","trigger","isDefaultPrevented","hide","originalEvent","preventDefault","bind","denyEvent","deny","completeEvent","complete","register"],"mappings":"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","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 .\n\n/**\n * Request actions.\n *\n * @module tool_dataprivacy/data_request_modal\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/notification', 'core/custom_interaction_events', 'core/modal', 'core/modal_registry',\n 'tool_dataprivacy/events'],\n function($, Notification, CustomEvents, Modal, ModalRegistry, DataPrivacyEvents) {\n\n var registered = false;\n var SELECTORS = {\n APPROVE_BUTTON: '[data-action=\"approve\"]',\n DENY_BUTTON: '[data-action=\"deny\"]',\n COMPLETE_BUTTON: '[data-action=\"complete\"]'\n };\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var ModalDataRequest = function(root) {\n Modal.call(this, root);\n };\n\n ModalDataRequest.TYPE = 'tool_dataprivacy-data_request';\n ModalDataRequest.prototype = Object.create(Modal.prototype);\n ModalDataRequest.prototype.constructor = ModalDataRequest;\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n */\n ModalDataRequest.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.APPROVE_BUTTON, function(e, data) {\n var approveEvent = $.Event(DataPrivacyEvents.approve);\n this.getRoot().trigger(approveEvent, this);\n\n if (!approveEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.DENY_BUTTON, function(e, data) {\n var denyEvent = $.Event(DataPrivacyEvents.deny);\n this.getRoot().trigger(denyEvent, this);\n\n if (!denyEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.COMPLETE_BUTTON, function(e, data) {\n var completeEvent = $.Event(DataPrivacyEvents.complete);\n this.getRoot().trigger(completeEvent, this);\n\n if (!completeEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n };\n\n // Automatically register with the modal registry the first time this module is imported so that you can create modals\n // of this type using the modal factory.\n if (!registered) {\n ModalRegistry.register(ModalDataRequest.TYPE, ModalDataRequest, 'tool_dataprivacy/data_request_modal');\n registered = true;\n }\n\n return ModalDataRequest;\n });"],"file":"data_request_modal.min.js"}
\ No newline at end of file
+{"version":3,"file":"data_request_modal.min.js","sources":["../src/data_request_modal.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 .\n\n/**\n * Request actions.\n *\n * @module tool_dataprivacy/data_request_modal\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/notification', 'core/custom_interaction_events', 'core/modal', 'core/modal_registry',\n 'tool_dataprivacy/events'],\n function($, Notification, CustomEvents, Modal, ModalRegistry, DataPrivacyEvents) {\n\n var registered = false;\n var SELECTORS = {\n APPROVE_BUTTON: '[data-action=\"approve\"]',\n DENY_BUTTON: '[data-action=\"deny\"]',\n COMPLETE_BUTTON: '[data-action=\"complete\"]'\n };\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var ModalDataRequest = function(root) {\n Modal.call(this, root);\n };\n\n ModalDataRequest.TYPE = 'tool_dataprivacy-data_request';\n ModalDataRequest.prototype = Object.create(Modal.prototype);\n ModalDataRequest.prototype.constructor = ModalDataRequest;\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n */\n ModalDataRequest.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.APPROVE_BUTTON, function(e, data) {\n var approveEvent = $.Event(DataPrivacyEvents.approve);\n this.getRoot().trigger(approveEvent, this);\n\n if (!approveEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.DENY_BUTTON, function(e, data) {\n var denyEvent = $.Event(DataPrivacyEvents.deny);\n this.getRoot().trigger(denyEvent, this);\n\n if (!denyEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.COMPLETE_BUTTON, function(e, data) {\n var completeEvent = $.Event(DataPrivacyEvents.complete);\n this.getRoot().trigger(completeEvent, this);\n\n if (!completeEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n };\n\n // Automatically register with the modal registry the first time this module is imported so that you can create modals\n // of this type using the modal factory.\n if (!registered) {\n ModalRegistry.register(ModalDataRequest.TYPE, ModalDataRequest, 'tool_dataprivacy/data_request_modal');\n registered = true;\n }\n\n return ModalDataRequest;\n });"],"names":["define","$","Notification","CustomEvents","Modal","ModalRegistry","DataPrivacyEvents","registered","SELECTORS","ModalDataRequest","root","call","this","TYPE","prototype","Object","create","constructor","registerEventListeners","getModal","on","events","activate","e","data","approveEvent","Event","approve","getRoot","trigger","isDefaultPrevented","hide","originalEvent","preventDefault","bind","denyEvent","deny","completeEvent","complete","register"],"mappings":";;;;;;;AAsBAA,6CAAO,CAAC,SAAU,oBAAqB,iCAAkC,aAAc,sBAC/E,4BACJ,SAASC,EAAGC,aAAcC,aAAcC,MAAOC,cAAeC,uBAEtDC,YAAa,EACbC,yBACgB,0BADhBA,sBAEa,uBAFbA,0BAGiB,2BAQjBC,iBAAmB,SAASC,MAC5BN,MAAMO,KAAKC,KAAMF,cAGrBD,iBAAiBI,KAAO,iCACxBJ,iBAAiBK,UAAYC,OAAOC,OAAOZ,MAAMU,YACtBG,YAAcR,iBAOzCA,iBAAiBK,UAAUI,uBAAyB,WAEhDd,MAAMU,UAAUI,uBAAuBP,KAAKC,WAEvCO,WAAWC,GAAGjB,aAAakB,OAAOC,SAAUd,yBAA0B,SAASe,EAAGC,UAC/EC,aAAexB,EAAEyB,MAAMpB,kBAAkBqB,cACxCC,UAAUC,QAAQJ,aAAcb,MAEhCa,aAAaK,4BACTC,OACLP,KAAKQ,cAAcC,mBAEzBC,KAAKtB,YAEFO,WAAWC,GAAGjB,aAAakB,OAAOC,SAAUd,sBAAuB,SAASe,EAAGC,UAC5EW,UAAYlC,EAAEyB,MAAMpB,kBAAkB8B,WACrCR,UAAUC,QAAQM,UAAWvB,MAE7BuB,UAAUL,4BACNC,OACLP,KAAKQ,cAAcC,mBAEzBC,KAAKtB,YAEFO,WAAWC,GAAGjB,aAAakB,OAAOC,SAAUd,0BAA2B,SAASe,EAAGC,UAChFa,cAAgBpC,EAAEyB,MAAMpB,kBAAkBgC,eACzCV,UAAUC,QAAQQ,cAAezB,MAEjCyB,cAAcP,4BACVC,OACLP,KAAKQ,cAAcC,mBAEzBC,KAAKtB,QAKNL,aACDF,cAAckC,SAAS9B,iBAAiBI,KAAMJ,iBAAkB,uCAChEF,YAAa,GAGVE"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/defaultsactions.min.js b/admin/tool/dataprivacy/amd/build/defaultsactions.min.js
index fa8e7fcac27..765cd98cf54 100644
--- a/admin/tool/dataprivacy/amd/build/defaultsactions.min.js
+++ b/admin/tool/dataprivacy/amd/build/defaultsactions.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/defaultsactions",["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events","core/templates"],function(a,b,c,d,f,g,h){var k={EDIT_LEVEL_DEFAULTS:"[data-action=\"edit-level-defaults\"]",NEW_ACTIVITY_DEFAULTS:"[data-action=\"new-activity-defaults\"]",EDIT_ACTIVITY_DEFAULTS:"[data-action=\"edit-activity-defaults\"]",DELETE_ACTIVITY_DEFAULTS:"[data-action=\"delete-activity-defaults\"]"},l=-1,m=function(){this.registerEvents()};m.prototype.registerEvents=function(){a(k.EDIT_LEVEL_DEFAULTS).click(function(f){f.preventDefault();var e=a(this),g=e.data("contextlevel"),h=e.data("category"),j=e.data("purpose"),k=b.call([{methodname:"tool_dataprivacy_get_category_options",args:{}},{methodname:"tool_dataprivacy_get_purpose_options",args:{}}]),l=d.get_string("editdefaults","tool_dataprivacy",a("#defaults-header").text());a.when(k[0],k[1],l).then(function(a,b,c){var d=a.options,e=b.options;i(c,g,h,j,null,d,e,null);return!0}).catch(c.exception)});a(k.NEW_ACTIVITY_DEFAULTS).click(function(f){f.preventDefault();var e=a(this),g=e.data("contextlevel"),h=b.call([{methodname:"tool_dataprivacy_get_category_options",args:{}},{methodname:"tool_dataprivacy_get_purpose_options",args:{}},{methodname:"tool_dataprivacy_get_activity_options",args:{nodefaults:!0}}]),j=d.get_string("addnewdefaults","tool_dataprivacy");a.when(h[0],h[1],h[2],j).then(function(a,b,c,d){var e=a.options,f=b.options,h=c.options;i(d,g,null,null,null,e,f,h);return!0}).catch(c.exception)});a(k.EDIT_ACTIVITY_DEFAULTS).click(function(f){f.preventDefault();var e=a(this),g=e.data("contextlevel"),h=e.data("category"),j=e.data("purpose"),k=e.data("activityname"),l=b.call([{methodname:"tool_dataprivacy_get_category_options",args:{}},{methodname:"tool_dataprivacy_get_purpose_options",args:{}},{methodname:"tool_dataprivacy_get_activity_options",args:{}}]),m=d.get_string("editmoduledefaults","tool_dataprivacy");a.when(l[0],l[1],l[2],m).then(function(a,b,c,d){var e=a.options,f=b.options,l=c.options;i(d,g,h,j,k,e,f,l);return!0}).catch(c.exception)});a(k.DELETE_ACTIVITY_DEFAULTS).click(function(b){b.preventDefault();var e=a(this),i=e.data("contextlevel"),k=e.data("activityname"),m=e.data("activitydisplayname");f.create({title:d.get_string("deletedefaults","tool_dataprivacy",m),body:h.render("tool_dataprivacy/delete_activity_defaults",{activityname:m}),type:f.types.SAVE_CANCEL,large:!0}).then(function(a){a.setSaveButtonText(d.get_string("delete"));a.getRoot().on(g.save,function(){j(i,l,l,k,!1)});a.getRoot().on(g.hidden,function(){a.destroy()});a.show();return!0}).catch(c.exception)})};function i(b,d,e,i,k,l,m,n){if(null!==e){l.forEach(function(a){if(a.id===e){a.selected=!0}})}if(null!==i){m.forEach(function(a){if(a.id===i){a.selected=!0}})}var o={contextlevel:d,categoryoptions:l,purposeoptions:m};if(null!==n&&n.length){if(null===k){o.newactivitydefaults=!0}else{n.forEach(function(a){if(k===a.name){a.selected=!0}})}o.modemodule=!0;o.activityoptions=n}f.create({title:b,body:h.render("tool_dataprivacy/category_purpose_form",o),type:f.types.SAVE_CANCEL,large:!0}).then(function(b){b.getRoot().on(g.save,function(){var b=a("#activity"),c="undefined"!=typeof b?b.val():null,d=a("#override"),e="undefined"!=typeof d?d.is(":checked"):!1;j(a("#contextlevel").val(),a("#category").val(),a("#purpose").val(),c,e)});b.getRoot().on(g.hidden,function(){b.destroy()});b.show();return b}).catch(c.exception)}function j(a,c,d,e,f){b.call([{methodname:"tool_dataprivacy_set_context_defaults",args:{contextlevel:a,category:c,purpose:d,override:f,activity:e}}])[0].done(function(a){if(a.result){window.location.reload()}})}return{init:function init(){return new m}}});
-//# sourceMappingURL=defaultsactions.min.js.map
+/**
+ * AMD module for data registry defaults actions.
+ *
+ * @module tool_dataprivacy/defaultsactions
+ * @copyright 2018 Jun Pataleta
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/defaultsactions",["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events","core/templates"],(function($,Ajax,Notification,Str,ModalFactory,ModalEvents,Templates){var ACTIONS_EDIT_LEVEL_DEFAULTS='[data-action="edit-level-defaults"]',ACTIONS_NEW_ACTIVITY_DEFAULTS='[data-action="new-activity-defaults"]',ACTIONS_EDIT_ACTIVITY_DEFAULTS='[data-action="edit-activity-defaults"]',ACTIONS_DELETE_ACTIVITY_DEFAULTS='[data-action="delete-activity-defaults"]',DefaultsActions=function(){this.registerEvents()};function showDefaultsFormModal(title,contextLevel,category,purpose,activity,categoryOptions,purposeOptions,activityOptions){null!==category&&categoryOptions.forEach((function(currentValue){currentValue.id===category&&(currentValue.selected=!0)})),null!==purpose&&purposeOptions.forEach((function(currentValue){currentValue.id===purpose&&(currentValue.selected=!0)}));var templateContext={contextlevel:contextLevel,categoryoptions:categoryOptions,purposeoptions:purposeOptions};null!==activityOptions&&activityOptions.length&&(null===activity?templateContext.newactivitydefaults=!0:activityOptions.forEach((function(currentValue){activity===currentValue.name&&(currentValue.selected=!0)})),templateContext.modemodule=!0,templateContext.activityoptions=activityOptions),ModalFactory.create({title:title,body:Templates.render("tool_dataprivacy/category_purpose_form",templateContext),type:ModalFactory.types.SAVE_CANCEL,large:!0}).then((function(modal){return modal.getRoot().on(ModalEvents.save,(function(){var activity=$("#activity"),activityVal=void 0!==activity?activity.val():null,override=$("#override"),overrideVal=void 0!==override&&override.is(":checked");setContextDefaults($("#contextlevel").val(),$("#category").val(),$("#purpose").val(),activityVal,overrideVal)})),modal.getRoot().on(ModalEvents.hidden,(function(){modal.destroy()})),modal.show(),modal})).catch(Notification.exception)}function setContextDefaults(contextLevel,category,purpose,activity,override){var request={methodname:"tool_dataprivacy_set_context_defaults",args:{contextlevel:contextLevel,category:category,purpose:purpose,override:override,activity:activity}};Ajax.call([request])[0].done((function(data){data.result&&window.location.reload()}))}return DefaultsActions.prototype.registerEvents=function(){$(ACTIONS_EDIT_LEVEL_DEFAULTS).click((function(e){e.preventDefault();var button=$(this),contextLevel=button.data("contextlevel"),category=button.data("category"),purpose=button.data("purpose"),promises=Ajax.call([{methodname:"tool_dataprivacy_get_category_options",args:{}},{methodname:"tool_dataprivacy_get_purpose_options",args:{}}]),titlePromise=Str.get_string("editdefaults","tool_dataprivacy",$("#defaults-header").text());$.when(promises[0],promises[1],titlePromise).then((function(categoryResponse,purposeResponse,title){var categories=categoryResponse.options,purposes=purposeResponse.options;return showDefaultsFormModal(title,contextLevel,category,purpose,null,categories,purposes,null),!0})).catch(Notification.exception)})),$(ACTIONS_NEW_ACTIVITY_DEFAULTS).click((function(e){e.preventDefault();var contextLevel=$(this).data("contextlevel"),promises=Ajax.call([{methodname:"tool_dataprivacy_get_category_options",args:{}},{methodname:"tool_dataprivacy_get_purpose_options",args:{}},{methodname:"tool_dataprivacy_get_activity_options",args:{nodefaults:!0}}]),titlePromise=Str.get_string("addnewdefaults","tool_dataprivacy");$.when(promises[0],promises[1],promises[2],titlePromise).then((function(categoryResponse,purposeResponse,activityResponse,title){var categories=categoryResponse.options,purposes=purposeResponse.options,activities=activityResponse.options;return showDefaultsFormModal(title,contextLevel,null,null,null,categories,purposes,activities),!0})).catch(Notification.exception)})),$(ACTIONS_EDIT_ACTIVITY_DEFAULTS).click((function(e){e.preventDefault();var button=$(this),contextLevel=button.data("contextlevel"),category=button.data("category"),purpose=button.data("purpose"),activity=button.data("activityname"),promises=Ajax.call([{methodname:"tool_dataprivacy_get_category_options",args:{}},{methodname:"tool_dataprivacy_get_purpose_options",args:{}},{methodname:"tool_dataprivacy_get_activity_options",args:{}}]),titlePromise=Str.get_string("editmoduledefaults","tool_dataprivacy");$.when(promises[0],promises[1],promises[2],titlePromise).then((function(categoryResponse,purposeResponse,activityResponse,title){var categories=categoryResponse.options,purposes=purposeResponse.options,activities=activityResponse.options;return showDefaultsFormModal(title,contextLevel,category,purpose,activity,categories,purposes,activities),!0})).catch(Notification.exception)})),$(ACTIONS_DELETE_ACTIVITY_DEFAULTS).click((function(e){e.preventDefault();var button=$(this),contextLevel=button.data("contextlevel"),activity=button.data("activityname"),activityDisplayName=button.data("activitydisplayname");ModalFactory.create({title:Str.get_string("deletedefaults","tool_dataprivacy",activityDisplayName),body:Templates.render("tool_dataprivacy/delete_activity_defaults",{activityname:activityDisplayName}),type:ModalFactory.types.SAVE_CANCEL,large:!0}).then((function(modal){return modal.setSaveButtonText(Str.get_string("delete")),modal.getRoot().on(ModalEvents.save,(function(){setContextDefaults(contextLevel,-1,-1,activity,!1)})),modal.getRoot().on(ModalEvents.hidden,(function(){modal.destroy()})),modal.show(),!0})).catch(Notification.exception)}))},{init:function(){return new DefaultsActions}}}));
+
+//# sourceMappingURL=defaultsactions.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/defaultsactions.min.js.map b/admin/tool/dataprivacy/amd/build/defaultsactions.min.js.map
index 0b988052be1..50b7d083a24 100644
--- a/admin/tool/dataprivacy/amd/build/defaultsactions.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/defaultsactions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/defaultsactions.js"],"names":["define","$","Ajax","Notification","Str","ModalFactory","ModalEvents","Templates","ACTIONS","EDIT_LEVEL_DEFAULTS","NEW_ACTIVITY_DEFAULTS","EDIT_ACTIVITY_DEFAULTS","DELETE_ACTIVITY_DEFAULTS","INHERIT","DefaultsActions","registerEvents","prototype","click","e","preventDefault","button","contextLevel","data","category","purpose","promises","call","methodname","args","titlePromise","get_string","text","when","then","categoryResponse","purposeResponse","title","categories","options","purposes","showDefaultsFormModal","catch","exception","activityResponse","activities","activity","activityDisplayName","create","body","render","type","types","SAVE_CANCEL","large","modal","setSaveButtonText","getRoot","on","save","setContextDefaults","hidden","destroy","show","categoryOptions","purposeOptions","activityOptions","forEach","currentValue","id","selected","templateContext","length","newactivitydefaults","name","modemodule","activityoptions","activityVal","val","override","overrideVal","is","done","result","window","location","reload"],"mappings":"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","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 .\n\n/**\n * AMD module for data registry defaults actions.\n *\n * @module tool_dataprivacy/defaultsactions\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/templates'],\nfunction($, Ajax, Notification, Str, ModalFactory, ModalEvents, Templates) {\n\n /**\n * List of action selectors.\n *\n * @type {{EDIT_LEVEL_DEFAULTS: string}}\n * @type {{NEW_ACTIVITY_DEFAULTS: string}}\n * @type {{EDIT_ACTIVITY_DEFAULTS: string}}\n * @type {{DELETE_ACTIVITY_DEFAULTS: string}}\n */\n var ACTIONS = {\n EDIT_LEVEL_DEFAULTS: '[data-action=\"edit-level-defaults\"]',\n NEW_ACTIVITY_DEFAULTS: '[data-action=\"new-activity-defaults\"]',\n EDIT_ACTIVITY_DEFAULTS: '[data-action=\"edit-activity-defaults\"]',\n DELETE_ACTIVITY_DEFAULTS: '[data-action=\"delete-activity-defaults\"]'\n };\n\n /** @type {{INHERIT: Number}} **/\n var INHERIT = -1;\n\n /**\n * DefaultsActions class.\n */\n var DefaultsActions = function() {\n this.registerEvents();\n };\n\n /**\n * Register event listeners.\n */\n DefaultsActions.prototype.registerEvents = function() {\n $(ACTIONS.EDIT_LEVEL_DEFAULTS).click(function(e) {\n e.preventDefault();\n\n var button = $(this);\n var contextLevel = button.data('contextlevel');\n var category = button.data('category');\n var purpose = button.data('purpose');\n\n // Get options.\n var requests = [\n {methodname: 'tool_dataprivacy_get_category_options', args: {}},\n {methodname: 'tool_dataprivacy_get_purpose_options', args: {}}\n ];\n\n var promises = Ajax.call(requests);\n var titlePromise = Str.get_string('editdefaults', 'tool_dataprivacy', $('#defaults-header').text());\n $.when(promises[0], promises[1], titlePromise).then(function(categoryResponse, purposeResponse, title) {\n var categories = categoryResponse.options;\n var purposes = purposeResponse.options;\n showDefaultsFormModal(title, contextLevel, category, purpose, null, categories, purposes, null);\n\n return true;\n }).catch(Notification.exception);\n });\n\n $(ACTIONS.NEW_ACTIVITY_DEFAULTS).click(function(e) {\n e.preventDefault();\n\n var button = $(this);\n var contextLevel = button.data('contextlevel');\n\n // Get options.\n var requests = [\n {methodname: 'tool_dataprivacy_get_category_options', args: {}},\n {methodname: 'tool_dataprivacy_get_purpose_options', args: {}},\n {methodname: 'tool_dataprivacy_get_activity_options', args: {'nodefaults': true}}\n ];\n\n var promises = Ajax.call(requests);\n var titlePromise = Str.get_string('addnewdefaults', 'tool_dataprivacy');\n\n $.when(promises[0], promises[1], promises[2], titlePromise).then(\n function(categoryResponse, purposeResponse, activityResponse, title) {\n var categories = categoryResponse.options;\n var purposes = purposeResponse.options;\n var activities = activityResponse.options;\n\n showDefaultsFormModal(title, contextLevel, null, null, null, categories, purposes, activities);\n\n return true;\n\n }).catch(Notification.exception);\n }\n );\n\n $(ACTIONS.EDIT_ACTIVITY_DEFAULTS).click(function(e) {\n e.preventDefault();\n\n var button = $(this);\n var contextLevel = button.data('contextlevel');\n var category = button.data('category');\n var purpose = button.data('purpose');\n var activity = button.data('activityname');\n\n // Get options.\n var requests = [\n {methodname: 'tool_dataprivacy_get_category_options', args: {}},\n {methodname: 'tool_dataprivacy_get_purpose_options', args: {}},\n {methodname: 'tool_dataprivacy_get_activity_options', args: {}}\n ];\n\n var promises = Ajax.call(requests);\n var titlePromise = Str.get_string('editmoduledefaults', 'tool_dataprivacy');\n\n $.when(promises[0], promises[1], promises[2], titlePromise).then(\n function(categoryResponse, purposeResponse, activityResponse, title) {\n var categories = categoryResponse.options;\n var purposes = purposeResponse.options;\n var activities = activityResponse.options;\n\n showDefaultsFormModal(title, contextLevel, category, purpose, activity, categories, purposes, activities);\n\n return true;\n\n }).catch(Notification.exception);\n }\n );\n\n $(ACTIONS.DELETE_ACTIVITY_DEFAULTS).click(function(e) {\n e.preventDefault();\n\n var button = $(this);\n var contextLevel = button.data('contextlevel');\n var activity = button.data('activityname');\n var activityDisplayName = button.data('activitydisplayname');\n // Set category and purpose to inherit (-1).\n var category = INHERIT;\n var purpose = INHERIT;\n\n ModalFactory.create({\n title: Str.get_string('deletedefaults', 'tool_dataprivacy', activityDisplayName),\n body: Templates.render('tool_dataprivacy/delete_activity_defaults', {\"activityname\": activityDisplayName}),\n type: ModalFactory.types.SAVE_CANCEL,\n large: true\n }).then(function(modal) {\n modal.setSaveButtonText(Str.get_string('delete'));\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function() {\n setContextDefaults(contextLevel, category, purpose, activity, false);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n modal.show();\n\n return true;\n }).catch(Notification.exception);\n });\n };\n\n /**\n * Prepares and renders the modal for setting the defaults for the given context level/plugin.\n *\n * @param {String} title The modal's title.\n * @param {Number} contextLevel The context level to set defaults for.\n * @param {Number} category The current category ID.\n * @param {Number} purpose The current purpose ID.\n * @param {String} activity The plugin name of the activity. Optional.\n * @param {Array} categoryOptions The list of category options.\n * @param {Array} purposeOptions The list of purpose options.\n * @param {Array} activityOptions The list of activity options. Optional.\n */\n function showDefaultsFormModal(title, contextLevel, category, purpose, activity,\n categoryOptions, purposeOptions, activityOptions) {\n\n if (category !== null) {\n categoryOptions.forEach(function(currentValue) {\n if (currentValue.id === category) {\n currentValue.selected = true;\n }\n });\n }\n\n if (purpose !== null) {\n purposeOptions.forEach(function(currentValue) {\n if (currentValue.id === purpose) {\n currentValue.selected = true;\n }\n });\n }\n\n var templateContext = {\n \"contextlevel\": contextLevel,\n \"categoryoptions\": categoryOptions,\n \"purposeoptions\": purposeOptions\n };\n\n // Check the activityOptions parameter that was passed.\n if (activityOptions !== null && activityOptions.length) {\n // Check the activity parameter that was passed.\n if (activity === null) {\n // We're setting a new defaults for a module.\n templateContext.newactivitydefaults = true;\n\n } else {\n // Edit mode. Set selection.\n activityOptions.forEach(function(currentValue) {\n if (activity === currentValue.name) {\n currentValue.selected = true;\n }\n });\n }\n\n templateContext.modemodule = true;\n templateContext.activityoptions = activityOptions;\n }\n\n ModalFactory.create({\n title: title,\n body: Templates.render('tool_dataprivacy/category_purpose_form', templateContext),\n type: ModalFactory.types.SAVE_CANCEL,\n large: true\n }).then(function(modal) {\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function() {\n var activity = $('#activity');\n var activityVal = typeof activity !== 'undefined' ? activity.val() : null;\n var override = $('#override');\n var overrideVal = typeof override !== 'undefined' ? override.is(':checked') : false;\n\n setContextDefaults($('#contextlevel').val(), $('#category').val(), $('#purpose').val(), activityVal, overrideVal);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n modal.show();\n\n return modal;\n }).catch(Notification.exception);\n }\n\n /**\n * Calls a the tool_dataprivacy_set_context_defaults WS function.\n *\n * @param {Number} contextLevel The context level.\n * @param {Number} category The category ID.\n * @param {Number} purpose The purpose ID.\n * @param {String} activity The plugin name of the activity module.\n * @param {Boolean} override Whether to override custom instances.\n */\n function setContextDefaults(contextLevel, category, purpose, activity, override) {\n var request = {\n methodname: 'tool_dataprivacy_set_context_defaults',\n args: {\n 'contextlevel': contextLevel,\n 'category': category,\n 'purpose': purpose,\n 'override': override,\n 'activity': activity\n }\n };\n\n Ajax.call([request])[0].done(function(data) {\n if (data.result) {\n window.location.reload();\n }\n });\n }\n\n return /** @alias module:tool_dataprivacy/defaultsactions */ {\n // Public variables and functions.\n\n /**\n * Initialise the module.\n *\n * @method init\n * @return {DefaultsActions}\n */\n 'init': function() {\n return new DefaultsActions();\n }\n };\n});\n"],"file":"defaultsactions.min.js"}
\ No newline at end of file
+{"version":3,"file":"defaultsactions.min.js","sources":["../src/defaultsactions.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 .\n\n/**\n * AMD module for data registry defaults actions.\n *\n * @module tool_dataprivacy/defaultsactions\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/templates'],\nfunction($, Ajax, Notification, Str, ModalFactory, ModalEvents, Templates) {\n\n /**\n * List of action selectors.\n *\n * @type {{EDIT_LEVEL_DEFAULTS: string}}\n * @type {{NEW_ACTIVITY_DEFAULTS: string}}\n * @type {{EDIT_ACTIVITY_DEFAULTS: string}}\n * @type {{DELETE_ACTIVITY_DEFAULTS: string}}\n */\n var ACTIONS = {\n EDIT_LEVEL_DEFAULTS: '[data-action=\"edit-level-defaults\"]',\n NEW_ACTIVITY_DEFAULTS: '[data-action=\"new-activity-defaults\"]',\n EDIT_ACTIVITY_DEFAULTS: '[data-action=\"edit-activity-defaults\"]',\n DELETE_ACTIVITY_DEFAULTS: '[data-action=\"delete-activity-defaults\"]'\n };\n\n /** @type {{INHERIT: Number}} **/\n var INHERIT = -1;\n\n /**\n * DefaultsActions class.\n */\n var DefaultsActions = function() {\n this.registerEvents();\n };\n\n /**\n * Register event listeners.\n */\n DefaultsActions.prototype.registerEvents = function() {\n $(ACTIONS.EDIT_LEVEL_DEFAULTS).click(function(e) {\n e.preventDefault();\n\n var button = $(this);\n var contextLevel = button.data('contextlevel');\n var category = button.data('category');\n var purpose = button.data('purpose');\n\n // Get options.\n var requests = [\n {methodname: 'tool_dataprivacy_get_category_options', args: {}},\n {methodname: 'tool_dataprivacy_get_purpose_options', args: {}}\n ];\n\n var promises = Ajax.call(requests);\n var titlePromise = Str.get_string('editdefaults', 'tool_dataprivacy', $('#defaults-header').text());\n $.when(promises[0], promises[1], titlePromise).then(function(categoryResponse, purposeResponse, title) {\n var categories = categoryResponse.options;\n var purposes = purposeResponse.options;\n showDefaultsFormModal(title, contextLevel, category, purpose, null, categories, purposes, null);\n\n return true;\n }).catch(Notification.exception);\n });\n\n $(ACTIONS.NEW_ACTIVITY_DEFAULTS).click(function(e) {\n e.preventDefault();\n\n var button = $(this);\n var contextLevel = button.data('contextlevel');\n\n // Get options.\n var requests = [\n {methodname: 'tool_dataprivacy_get_category_options', args: {}},\n {methodname: 'tool_dataprivacy_get_purpose_options', args: {}},\n {methodname: 'tool_dataprivacy_get_activity_options', args: {'nodefaults': true}}\n ];\n\n var promises = Ajax.call(requests);\n var titlePromise = Str.get_string('addnewdefaults', 'tool_dataprivacy');\n\n $.when(promises[0], promises[1], promises[2], titlePromise).then(\n function(categoryResponse, purposeResponse, activityResponse, title) {\n var categories = categoryResponse.options;\n var purposes = purposeResponse.options;\n var activities = activityResponse.options;\n\n showDefaultsFormModal(title, contextLevel, null, null, null, categories, purposes, activities);\n\n return true;\n\n }).catch(Notification.exception);\n }\n );\n\n $(ACTIONS.EDIT_ACTIVITY_DEFAULTS).click(function(e) {\n e.preventDefault();\n\n var button = $(this);\n var contextLevel = button.data('contextlevel');\n var category = button.data('category');\n var purpose = button.data('purpose');\n var activity = button.data('activityname');\n\n // Get options.\n var requests = [\n {methodname: 'tool_dataprivacy_get_category_options', args: {}},\n {methodname: 'tool_dataprivacy_get_purpose_options', args: {}},\n {methodname: 'tool_dataprivacy_get_activity_options', args: {}}\n ];\n\n var promises = Ajax.call(requests);\n var titlePromise = Str.get_string('editmoduledefaults', 'tool_dataprivacy');\n\n $.when(promises[0], promises[1], promises[2], titlePromise).then(\n function(categoryResponse, purposeResponse, activityResponse, title) {\n var categories = categoryResponse.options;\n var purposes = purposeResponse.options;\n var activities = activityResponse.options;\n\n showDefaultsFormModal(title, contextLevel, category, purpose, activity, categories, purposes, activities);\n\n return true;\n\n }).catch(Notification.exception);\n }\n );\n\n $(ACTIONS.DELETE_ACTIVITY_DEFAULTS).click(function(e) {\n e.preventDefault();\n\n var button = $(this);\n var contextLevel = button.data('contextlevel');\n var activity = button.data('activityname');\n var activityDisplayName = button.data('activitydisplayname');\n // Set category and purpose to inherit (-1).\n var category = INHERIT;\n var purpose = INHERIT;\n\n ModalFactory.create({\n title: Str.get_string('deletedefaults', 'tool_dataprivacy', activityDisplayName),\n body: Templates.render('tool_dataprivacy/delete_activity_defaults', {\"activityname\": activityDisplayName}),\n type: ModalFactory.types.SAVE_CANCEL,\n large: true\n }).then(function(modal) {\n modal.setSaveButtonText(Str.get_string('delete'));\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function() {\n setContextDefaults(contextLevel, category, purpose, activity, false);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n modal.show();\n\n return true;\n }).catch(Notification.exception);\n });\n };\n\n /**\n * Prepares and renders the modal for setting the defaults for the given context level/plugin.\n *\n * @param {String} title The modal's title.\n * @param {Number} contextLevel The context level to set defaults for.\n * @param {Number} category The current category ID.\n * @param {Number} purpose The current purpose ID.\n * @param {String} activity The plugin name of the activity. Optional.\n * @param {Array} categoryOptions The list of category options.\n * @param {Array} purposeOptions The list of purpose options.\n * @param {Array} activityOptions The list of activity options. Optional.\n */\n function showDefaultsFormModal(title, contextLevel, category, purpose, activity,\n categoryOptions, purposeOptions, activityOptions) {\n\n if (category !== null) {\n categoryOptions.forEach(function(currentValue) {\n if (currentValue.id === category) {\n currentValue.selected = true;\n }\n });\n }\n\n if (purpose !== null) {\n purposeOptions.forEach(function(currentValue) {\n if (currentValue.id === purpose) {\n currentValue.selected = true;\n }\n });\n }\n\n var templateContext = {\n \"contextlevel\": contextLevel,\n \"categoryoptions\": categoryOptions,\n \"purposeoptions\": purposeOptions\n };\n\n // Check the activityOptions parameter that was passed.\n if (activityOptions !== null && activityOptions.length) {\n // Check the activity parameter that was passed.\n if (activity === null) {\n // We're setting a new defaults for a module.\n templateContext.newactivitydefaults = true;\n\n } else {\n // Edit mode. Set selection.\n activityOptions.forEach(function(currentValue) {\n if (activity === currentValue.name) {\n currentValue.selected = true;\n }\n });\n }\n\n templateContext.modemodule = true;\n templateContext.activityoptions = activityOptions;\n }\n\n ModalFactory.create({\n title: title,\n body: Templates.render('tool_dataprivacy/category_purpose_form', templateContext),\n type: ModalFactory.types.SAVE_CANCEL,\n large: true\n }).then(function(modal) {\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function() {\n var activity = $('#activity');\n var activityVal = typeof activity !== 'undefined' ? activity.val() : null;\n var override = $('#override');\n var overrideVal = typeof override !== 'undefined' ? override.is(':checked') : false;\n\n setContextDefaults($('#contextlevel').val(), $('#category').val(), $('#purpose').val(), activityVal, overrideVal);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n modal.show();\n\n return modal;\n }).catch(Notification.exception);\n }\n\n /**\n * Calls a the tool_dataprivacy_set_context_defaults WS function.\n *\n * @param {Number} contextLevel The context level.\n * @param {Number} category The category ID.\n * @param {Number} purpose The purpose ID.\n * @param {String} activity The plugin name of the activity module.\n * @param {Boolean} override Whether to override custom instances.\n */\n function setContextDefaults(contextLevel, category, purpose, activity, override) {\n var request = {\n methodname: 'tool_dataprivacy_set_context_defaults',\n args: {\n 'contextlevel': contextLevel,\n 'category': category,\n 'purpose': purpose,\n 'override': override,\n 'activity': activity\n }\n };\n\n Ajax.call([request])[0].done(function(data) {\n if (data.result) {\n window.location.reload();\n }\n });\n }\n\n return /** @alias module:tool_dataprivacy/defaultsactions */ {\n // Public variables and functions.\n\n /**\n * Initialise the module.\n *\n * @method init\n * @return {DefaultsActions}\n */\n 'init': function() {\n return new DefaultsActions();\n }\n };\n});\n"],"names":["define","$","Ajax","Notification","Str","ModalFactory","ModalEvents","Templates","ACTIONS","DefaultsActions","registerEvents","showDefaultsFormModal","title","contextLevel","category","purpose","activity","categoryOptions","purposeOptions","activityOptions","forEach","currentValue","id","selected","templateContext","length","newactivitydefaults","name","modemodule","activityoptions","create","body","render","type","types","SAVE_CANCEL","large","then","modal","getRoot","on","save","activityVal","val","override","overrideVal","is","setContextDefaults","hidden","destroy","show","catch","exception","request","methodname","args","call","done","data","result","window","location","reload","prototype","click","e","preventDefault","button","this","promises","titlePromise","get_string","text","when","categoryResponse","purposeResponse","categories","options","purposes","activityResponse","activities","activityDisplayName","setSaveButtonText"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/effective_retention_period.min.js b/admin/tool/dataprivacy/amd/build/effective_retention_period.min.js
index b7bd5b769fc..7079d003fc0 100644
--- a/admin/tool/dataprivacy/amd/build/effective_retention_period.min.js
+++ b/admin/tool/dataprivacy/amd/build/effective_retention_period.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/effective_retention_period",["jquery"],function(a){var b={PURPOSE_SELECT:"#id_purposeid",RETENTION_FIELD:"#fitem_id_retention_current [data-fieldtype=static]"},c=function(a){this.purposeRetentionPeriods=a;this.registerEventListeners()},d=function(){a(b.PURPOSE_SELECT).off("change")};c.prototype.purposeRetentionPeriods=[];c.prototype.registerEventListeners=function(){a(b.PURPOSE_SELECT).on("change",function(c){var d=a(c.currentTarget).val(),e=this.purposeRetentionPeriods[d];a(b.RETENTION_FIELD).text(e)}.bind(this))};return{init:function init(a){d();return new c(a)}}});
-//# sourceMappingURL=effective_retention_period.min.js.map
+/**
+ * Module to update the displayed retention period.
+ *
+ * @module tool_dataprivacy/effective_retention_period
+ * @copyright 2018 David Monllao
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/effective_retention_period",["jquery"],(function($){var SELECTORS_PURPOSE_SELECT="#id_purposeid",SELECTORS_RETENTION_FIELD="#fitem_id_retention_current [data-fieldtype=static]",EffectiveRetentionPeriod=function(purposeRetentionPeriods){this.purposeRetentionPeriods=purposeRetentionPeriods,this.registerEventListeners()};return EffectiveRetentionPeriod.prototype.purposeRetentionPeriods=[],EffectiveRetentionPeriod.prototype.registerEventListeners=function(){$(SELECTORS_PURPOSE_SELECT).on("change",function(ev){var selected=$(ev.currentTarget).val(),selectedPurpose=this.purposeRetentionPeriods[selected];$(SELECTORS_RETENTION_FIELD).text(selectedPurpose)}.bind(this))},{init:function(purposeRetentionPeriods){return $(SELECTORS_PURPOSE_SELECT).off("change"),new EffectiveRetentionPeriod(purposeRetentionPeriods)}}}));
+
+//# sourceMappingURL=effective_retention_period.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/effective_retention_period.min.js.map b/admin/tool/dataprivacy/amd/build/effective_retention_period.min.js.map
index e8e3d14390e..ac590ba9ea6 100644
--- a/admin/tool/dataprivacy/amd/build/effective_retention_period.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/effective_retention_period.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/effective_retention_period.js"],"names":["define","$","SELECTORS","PURPOSE_SELECT","RETENTION_FIELD","EffectiveRetentionPeriod","purposeRetentionPeriods","registerEventListeners","removeListeners","off","prototype","on","ev","selected","currentTarget","val","selectedPurpose","text","bind","init"],"mappings":"AAsBAA,OAAM,+CAAC,CAAC,QAAD,CAAD,CACF,SAASC,CAAT,CAAY,IAEJC,CAAAA,CAAS,CAAG,CACZC,cAAc,CAAE,eADJ,CAEZC,eAAe,CAAE,qDAFL,CAFR,CAYJC,CAAwB,CAAG,SAASC,CAAT,CAAkC,CAC7D,KAAKA,uBAAL,CAA+BA,CAA/B,CACA,KAAKC,sBAAL,EACH,CAfO,CAsBJC,CAAe,CAAG,UAAW,CAC7BP,CAAC,CAACC,CAAS,CAACC,cAAX,CAAD,CAA4BM,GAA5B,CAAgC,QAAhC,CACH,CAxBO,CA8BRJ,CAAwB,CAACK,SAAzB,CAAmCJ,uBAAnC,CAA6D,EAA7D,CAOAD,CAAwB,CAACK,SAAzB,CAAmCH,sBAAnC,CAA4D,UAAW,CAEnEN,CAAC,CAACC,CAAS,CAACC,cAAX,CAAD,CAA4BQ,EAA5B,CAA+B,QAA/B,CAAyC,SAASC,CAAT,CAAa,IAC9CC,CAAAA,CAAQ,CAAGZ,CAAC,CAACW,CAAE,CAACE,aAAJ,CAAD,CAAoBC,GAApB,EADmC,CAE9CC,CAAe,CAAG,KAAKV,uBAAL,CAA6BO,CAA7B,CAF4B,CAGlDZ,CAAC,CAACC,CAAS,CAACE,eAAX,CAAD,CAA6Ba,IAA7B,CAAkCD,CAAlC,CACH,CAJwC,CAIvCE,IAJuC,CAIlC,IAJkC,CAAzC,CAKH,CAPD,CASA,MAAwE,CACpEC,IAAI,CAAE,cAASb,CAAT,CAAkC,CAEpCE,CAAe,GACf,MAAO,IAAIH,CAAAA,CAAJ,CAA6BC,CAA7B,CACV,CALmE,CAO3E,CAtDC,CAAN","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 .\n\n/**\n * Module to update the displayed retention period.\n *\n * @module tool_dataprivacy/effective_retention_period\n * @copyright 2018 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery'],\n function($) {\n\n var SELECTORS = {\n PURPOSE_SELECT: '#id_purposeid',\n RETENTION_FIELD: '#fitem_id_retention_current [data-fieldtype=static]',\n };\n\n /**\n * Constructor for the retention period display.\n *\n * @param {Array} purposeRetentionPeriods Associative array of purposeids with effective retention period at this context\n */\n var EffectiveRetentionPeriod = function(purposeRetentionPeriods) {\n this.purposeRetentionPeriods = purposeRetentionPeriods;\n this.registerEventListeners();\n };\n\n /**\n * Removes the current 'change' listeners.\n *\n * Useful when a new form is loaded.\n */\n var removeListeners = function() {\n $(SELECTORS.PURPOSE_SELECT).off('change');\n };\n\n /**\n * @var {Array} purposeRetentionPeriods\n * @private\n */\n EffectiveRetentionPeriod.prototype.purposeRetentionPeriods = [];\n\n /**\n * Add purpose change listeners.\n *\n * @method registerEventListeners\n */\n EffectiveRetentionPeriod.prototype.registerEventListeners = function() {\n\n $(SELECTORS.PURPOSE_SELECT).on('change', function(ev) {\n var selected = $(ev.currentTarget).val();\n var selectedPurpose = this.purposeRetentionPeriods[selected];\n $(SELECTORS.RETENTION_FIELD).text(selectedPurpose);\n }.bind(this));\n };\n\n return /** @alias module:tool_dataprivacy/effective_retention_period */ {\n init: function(purposeRetentionPeriods) {\n // Remove previously attached listeners.\n removeListeners();\n return new EffectiveRetentionPeriod(purposeRetentionPeriods);\n }\n };\n }\n);\n\n"],"file":"effective_retention_period.min.js"}
\ No newline at end of file
+{"version":3,"file":"effective_retention_period.min.js","sources":["../src/effective_retention_period.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 .\n\n/**\n * Module to update the displayed retention period.\n *\n * @module tool_dataprivacy/effective_retention_period\n * @copyright 2018 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery'],\n function($) {\n\n var SELECTORS = {\n PURPOSE_SELECT: '#id_purposeid',\n RETENTION_FIELD: '#fitem_id_retention_current [data-fieldtype=static]',\n };\n\n /**\n * Constructor for the retention period display.\n *\n * @param {Array} purposeRetentionPeriods Associative array of purposeids with effective retention period at this context\n */\n var EffectiveRetentionPeriod = function(purposeRetentionPeriods) {\n this.purposeRetentionPeriods = purposeRetentionPeriods;\n this.registerEventListeners();\n };\n\n /**\n * Removes the current 'change' listeners.\n *\n * Useful when a new form is loaded.\n */\n var removeListeners = function() {\n $(SELECTORS.PURPOSE_SELECT).off('change');\n };\n\n /**\n * @var {Array} purposeRetentionPeriods\n * @private\n */\n EffectiveRetentionPeriod.prototype.purposeRetentionPeriods = [];\n\n /**\n * Add purpose change listeners.\n *\n * @method registerEventListeners\n */\n EffectiveRetentionPeriod.prototype.registerEventListeners = function() {\n\n $(SELECTORS.PURPOSE_SELECT).on('change', function(ev) {\n var selected = $(ev.currentTarget).val();\n var selectedPurpose = this.purposeRetentionPeriods[selected];\n $(SELECTORS.RETENTION_FIELD).text(selectedPurpose);\n }.bind(this));\n };\n\n return /** @alias module:tool_dataprivacy/effective_retention_period */ {\n init: function(purposeRetentionPeriods) {\n // Remove previously attached listeners.\n removeListeners();\n return new EffectiveRetentionPeriod(purposeRetentionPeriods);\n }\n };\n }\n);\n\n"],"names":["define","$","SELECTORS","EffectiveRetentionPeriod","purposeRetentionPeriods","registerEventListeners","prototype","on","ev","selected","currentTarget","val","selectedPurpose","this","text","bind","init","off"],"mappings":";;;;;;;AAsBAA,qDAAO,CAAC,WACJ,SAASC,OAEDC,yBACgB,gBADhBA,0BAEiB,sDAQjBC,yBAA2B,SAASC,8BAC/BA,wBAA0BA,6BAC1BC,iCAgBTF,yBAAyBG,UAAUF,wBAA0B,GAO7DD,yBAAyBG,UAAUD,uBAAyB,WAExDJ,EAAEC,0BAA0BK,GAAG,SAAU,SAASC,QAC1CC,SAAWR,EAAEO,GAAGE,eAAeC,MAC/BC,gBAAkBC,KAAKT,wBAAwBK,UACnDR,EAAEC,2BAA2BY,KAAKF,kBACpCG,KAAKF,QAG6D,CACpEG,KAAM,SAASZ,gCAxBfH,EAAEC,0BAA0Be,IAAI,UA2BrB,IAAId,yBAAyBC"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/events.min.js b/admin/tool/dataprivacy/amd/build/events.min.js
index acae406b7dc..f5ee42396d0 100644
--- a/admin/tool/dataprivacy/amd/build/events.min.js
+++ b/admin/tool/dataprivacy/amd/build/events.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/events",[],function(){return{approve:"tool_dataprivacy-data_request:approve",bulkApprove:"tool_dataprivacy-data_request:bulk_approve",deny:"tool_dataprivacy-data_request:deny",bulkDeny:"tool_dataprivacy-data_request:bulk_deny",complete:"tool_dataprivacy-data_request:complete"}});
-//# sourceMappingURL=events.min.js.map
+/**
+ * Contain the events the data privacy tool can fire.
+ *
+ * @module tool_dataprivacy/events
+ * @copyright 2018 Jun Pataleta
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/events",[],(function(){return{approve:"tool_dataprivacy-data_request:approve",bulkApprove:"tool_dataprivacy-data_request:bulk_approve",deny:"tool_dataprivacy-data_request:deny",bulkDeny:"tool_dataprivacy-data_request:bulk_deny",complete:"tool_dataprivacy-data_request:complete"}}));
+
+//# sourceMappingURL=events.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/events.min.js.map b/admin/tool/dataprivacy/amd/build/events.min.js.map
index 60293f3a3d7..287e52800b6 100644
--- a/admin/tool/dataprivacy/amd/build/events.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/events.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/events.js"],"names":["define","approve","bulkApprove","deny","bulkDeny","complete"],"mappings":"AAsBAA,OAAM,2BAAC,EAAD,CAAK,UAAW,CAClB,MAAO,CACHC,OAAO,CAAE,uCADN,CAEHC,WAAW,CAAE,4CAFV,CAGHC,IAAI,CAAE,oCAHH,CAIHC,QAAQ,CAAE,yCAJP,CAKHC,QAAQ,CAAE,wCALP,CAOV,CARK,CAAN","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 .\n\n/**\n * Contain the events the data privacy tool can fire.\n *\n * @module tool_dataprivacy/events\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n approve: 'tool_dataprivacy-data_request:approve',\n bulkApprove: 'tool_dataprivacy-data_request:bulk_approve',\n deny: 'tool_dataprivacy-data_request:deny',\n bulkDeny: 'tool_dataprivacy-data_request:bulk_deny',\n complete: 'tool_dataprivacy-data_request:complete'\n };\n});\n"],"file":"events.min.js"}
\ No newline at end of file
+{"version":3,"file":"events.min.js","sources":["../src/events.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 .\n\n/**\n * Contain the events the data privacy tool can fire.\n *\n * @module tool_dataprivacy/events\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n approve: 'tool_dataprivacy-data_request:approve',\n bulkApprove: 'tool_dataprivacy-data_request:bulk_approve',\n deny: 'tool_dataprivacy-data_request:deny',\n bulkDeny: 'tool_dataprivacy-data_request:bulk_deny',\n complete: 'tool_dataprivacy-data_request:complete'\n };\n});\n"],"names":["define","approve","bulkApprove","deny","bulkDeny","complete"],"mappings":";;;;;;;AAsBAA,iCAAO,IAAI,iBACA,CACHC,QAAS,wCACTC,YAAa,6CACbC,KAAM,qCACNC,SAAU,0CACVC,SAAU"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/expand_contract.min.js b/admin/tool/dataprivacy/amd/build/expand_contract.min.js
index 7f73e4c65dd..4e4c3e93fa0 100644
--- a/admin/tool/dataprivacy/amd/build/expand_contract.min.js
+++ b/admin/tool/dataprivacy/amd/build/expand_contract.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/expand_contract",["jquery","core/url","core/str"],function(a,b,c){var d=a(""),e=a(""),f={EXPAND:"fa-caret-right",COLLAPSE:"fa-caret-down"};return{expandCollapse:function expandCollapse(a,b){if(a.hasClass("hide")){a.removeClass("hide");a.addClass("visible");a.attr("aria-expanded",!0);b.find(":header i.fa").removeClass(f.EXPAND);b.find(":header i.fa").addClass(f.COLLAPSE);b.find(":header img.icon").attr("src",d.attr("src"))}else{a.removeClass("visible");a.addClass("hide");a.attr("aria-expanded",!1);b.find(":header i.fa").removeClass(f.COLLAPSE);b.find(":header i.fa").addClass(f.EXPAND);b.find(":header img.icon").attr("src",e.attr("src"))}},expandCollapseAll:function expandCollapseAll(b){var g="visible"==b?"hide":"visible",h="visible"==b?!0:!1,i="visible"==b?f.EXPAND:f.COLLAPSE,j="visible"==b?f.COLLAPSE:f.EXPAND,k="visible"==b?d.attr("src"):e.attr("src");a("."+g).each(function(){a(this).removeClass(g);a(this).addClass(b);a(this).attr("aria-expanded",h)});a(".tool_dataprivacy-expand-all").data("visibilityState",g);c.get_string(g,"tool_dataprivacy").then(function(b){a(".tool_dataprivacy-expand-all").html(b)}).catch(Notification.exception);a(":header i.fa").each(function(){a(this).removeClass(i);a(this).addClass(j)});a(":header img.icon").each(function(){a(this).attr("src",k)})}}});
-//# sourceMappingURL=expand_contract.min.js.map
+/**
+ * Potential user selector module.
+ *
+ * @module tool_dataprivacy/expand_contract
+ * @copyright 2018 Adrian Greeve
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/expand_contract",["jquery","core/url","core/str"],(function($,url,str){var expandedImage=$(''),collapsedImage=$(''),CLASSES_EXPAND="fa-caret-right",CLASSES_COLLAPSE="fa-caret-down";return{expandCollapse:function(targetnode,thisnode){targetnode.hasClass("hide")?(targetnode.removeClass("hide"),targetnode.addClass("visible"),targetnode.attr("aria-expanded",!0),thisnode.find(":header i.fa").removeClass(CLASSES_EXPAND),thisnode.find(":header i.fa").addClass(CLASSES_COLLAPSE),thisnode.find(":header img.icon").attr("src",expandedImage.attr("src"))):(targetnode.removeClass("visible"),targetnode.addClass("hide"),targetnode.attr("aria-expanded",!1),thisnode.find(":header i.fa").removeClass(CLASSES_COLLAPSE),thisnode.find(":header i.fa").addClass(CLASSES_EXPAND),thisnode.find(":header img.icon").attr("src",collapsedImage.attr("src")))},expandCollapseAll:function(nextstate){var currentstate="visible"==nextstate?"hide":"visible",ariaexpandedstate="visible"==nextstate,iconclassnow="visible"==nextstate?CLASSES_EXPAND:CLASSES_COLLAPSE,iconclassnext="visible"==nextstate?CLASSES_COLLAPSE:CLASSES_EXPAND,imagenow="visible"==nextstate?expandedImage.attr("src"):collapsedImage.attr("src");$("."+currentstate).each((function(){$(this).removeClass(currentstate),$(this).addClass(nextstate),$(this).attr("aria-expanded",ariaexpandedstate)})),$(".tool_dataprivacy-expand-all").data("visibilityState",currentstate),str.get_string(currentstate,"tool_dataprivacy").then((function(langString){$(".tool_dataprivacy-expand-all").html(langString)})).catch(Notification.exception),$(":header i.fa").each((function(){$(this).removeClass(iconclassnow),$(this).addClass(iconclassnext)})),$(":header img.icon").each((function(){$(this).attr("src",imagenow)}))}}}));
+
+//# sourceMappingURL=expand_contract.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/expand_contract.min.js.map b/admin/tool/dataprivacy/amd/build/expand_contract.min.js.map
index cd1ba61d3fd..f14dcd9e805 100644
--- a/admin/tool/dataprivacy/amd/build/expand_contract.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/expand_contract.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/expand_contract.js"],"names":["define","$","url","str","expandedImage","imageUrl","collapsedImage","CLASSES","EXPAND","COLLAPSE","expandCollapse","targetnode","thisnode","hasClass","removeClass","addClass","attr","find","expandCollapseAll","nextstate","currentstate","ariaexpandedstate","iconclassnow","iconclassnext","imagenow","each","data","get_string","then","langString","html","catch","Notification","exception"],"mappings":"AAuBAA,OAAM,oCAAC,CAAC,QAAD,CAAW,UAAX,CAAuB,UAAvB,CAAD,CAAqC,SAASC,CAAT,CAAYC,CAAZ,CAAiBC,CAAjB,CAAsB,IAEzDC,CAAAA,CAAa,CAAGH,CAAC,CAAC,uBAAsBC,CAAG,CAACG,QAAJ,CAAa,YAAb,CAAtB,CAAmD,MAApD,CAFwC,CAGzDC,CAAc,CAAGL,CAAC,CAAC,uBAAsBC,CAAG,CAACG,QAAJ,CAAa,aAAb,CAAtB,CAAoD,MAArD,CAHuC,CAQzDE,CAAO,CAAG,CACVC,MAAM,CAAE,gBADE,CAEVC,QAAQ,CAAE,eAFA,CAR+C,CAa7D,MAA6D,CAOzDC,cAAc,CAAE,wBAASC,CAAT,CAAqBC,CAArB,CAA+B,CAC3C,GAAID,CAAU,CAACE,QAAX,CAAoB,MAApB,CAAJ,CAAiC,CAC7BF,CAAU,CAACG,WAAX,CAAuB,MAAvB,EACAH,CAAU,CAACI,QAAX,CAAoB,SAApB,EACAJ,CAAU,CAACK,IAAX,CAAgB,eAAhB,KACAJ,CAAQ,CAACK,IAAT,CAAc,cAAd,EAA8BH,WAA9B,CAA0CP,CAAO,CAACC,MAAlD,EACAI,CAAQ,CAACK,IAAT,CAAc,cAAd,EAA8BF,QAA9B,CAAuCR,CAAO,CAACE,QAA/C,EACAG,CAAQ,CAACK,IAAT,CAAc,kBAAd,EAAkCD,IAAlC,CAAuC,KAAvC,CAA8CZ,CAAa,CAACY,IAAd,CAAmB,KAAnB,CAA9C,CACH,CAPD,IAOO,CACHL,CAAU,CAACG,WAAX,CAAuB,SAAvB,EACAH,CAAU,CAACI,QAAX,CAAoB,MAApB,EACAJ,CAAU,CAACK,IAAX,CAAgB,eAAhB,KACAJ,CAAQ,CAACK,IAAT,CAAc,cAAd,EAA8BH,WAA9B,CAA0CP,CAAO,CAACE,QAAlD,EACAG,CAAQ,CAACK,IAAT,CAAc,cAAd,EAA8BF,QAA9B,CAAuCR,CAAO,CAACC,MAA/C,EACAI,CAAQ,CAACK,IAAT,CAAc,kBAAd,EAAkCD,IAAlC,CAAuC,KAAvC,CAA8CV,CAAc,CAACU,IAAf,CAAoB,KAApB,CAA9C,CACH,CACJ,CAvBwD,CA8BzDE,iBAAiB,CAAE,2BAASC,CAAT,CAAoB,IAC/BC,CAAAA,CAAY,CAAiB,SAAb,EAAAD,CAAD,CAA2B,MAA3B,CAAoC,SADpB,CAE/BE,CAAiB,CAAiB,SAAb,EAAAF,CAAD,MAFW,CAG/BG,CAAY,CAAiB,SAAb,EAAAH,CAAD,CAA2BZ,CAAO,CAACC,MAAnC,CAA4CD,CAAO,CAACE,QAHpC,CAI/Bc,CAAa,CAAiB,SAAb,EAAAJ,CAAD,CAA2BZ,CAAO,CAACE,QAAnC,CAA8CF,CAAO,CAACC,MAJvC,CAK/BgB,CAAQ,CAAiB,SAAb,EAAAL,CAAD,CAA2Bf,CAAa,CAACY,IAAd,CAAmB,KAAnB,CAA3B,CAAuDV,CAAc,CAACU,IAAf,CAAoB,KAApB,CALnC,CAMnCf,CAAC,CAAC,IAAMmB,CAAP,CAAD,CAAsBK,IAAtB,CAA2B,UAAW,CAClCxB,CAAC,CAAC,IAAD,CAAD,CAAQa,WAAR,CAAoBM,CAApB,EACAnB,CAAC,CAAC,IAAD,CAAD,CAAQc,QAAR,CAAiBI,CAAjB,EACAlB,CAAC,CAAC,IAAD,CAAD,CAAQe,IAAR,CAAa,eAAb,CAA8BK,CAA9B,CACH,CAJD,EAKApB,CAAC,CAAC,8BAAD,CAAD,CAAkCyB,IAAlC,CAAuC,iBAAvC,CAA0DN,CAA1D,EAEAjB,CAAG,CAACwB,UAAJ,CAAeP,CAAf,CAA6B,kBAA7B,EAAiDQ,IAAjD,CAAsD,SAASC,CAAT,CAAqB,CACvE5B,CAAC,CAAC,8BAAD,CAAD,CAAkC6B,IAAlC,CAAuCD,CAAvC,CAEH,CAHD,EAGGE,KAHH,CAGSC,YAAY,CAACC,SAHtB,EAKAhC,CAAC,CAAC,cAAD,CAAD,CAAkBwB,IAAlB,CAAuB,UAAW,CAC9BxB,CAAC,CAAC,IAAD,CAAD,CAAQa,WAAR,CAAoBQ,CAApB,EACArB,CAAC,CAAC,IAAD,CAAD,CAAQc,QAAR,CAAiBQ,CAAjB,CACH,CAHD,EAIAtB,CAAC,CAAC,kBAAD,CAAD,CAAsBwB,IAAtB,CAA2B,UAAW,CAClCxB,CAAC,CAAC,IAAD,CAAD,CAAQe,IAAR,CAAa,KAAb,CAAoBQ,CAApB,CACH,CAFD,CAGH,CAvDwD,CAyDhE,CAtEK,CAAN","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 .\n\n/**\n * Potential user selector module.\n *\n * @module tool_dataprivacy/expand_contract\n * @copyright 2018 Adrian Greeve\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/url', 'core/str'], function($, url, str) {\n\n var expandedImage = $('');\n var collapsedImage = $('');\n\n /*\n * Class names to apply when expanding/collapsing nodes.\n */\n var CLASSES = {\n EXPAND: 'fa-caret-right',\n COLLAPSE: 'fa-caret-down'\n };\n\n return /** @alias module:tool_dataprivacy/expand-collapse */ {\n /**\n * Expand or collapse a selected node.\n *\n * @param {object} targetnode The node that we want to expand / collapse\n * @param {object} thisnode The node that was clicked.\n */\n expandCollapse: function(targetnode, thisnode) {\n if (targetnode.hasClass('hide')) {\n targetnode.removeClass('hide');\n targetnode.addClass('visible');\n targetnode.attr('aria-expanded', true);\n thisnode.find(':header i.fa').removeClass(CLASSES.EXPAND);\n thisnode.find(':header i.fa').addClass(CLASSES.COLLAPSE);\n thisnode.find(':header img.icon').attr('src', expandedImage.attr('src'));\n } else {\n targetnode.removeClass('visible');\n targetnode.addClass('hide');\n targetnode.attr('aria-expanded', false);\n thisnode.find(':header i.fa').removeClass(CLASSES.COLLAPSE);\n thisnode.find(':header i.fa').addClass(CLASSES.EXPAND);\n thisnode.find(':header img.icon').attr('src', collapsedImage.attr('src'));\n }\n },\n\n /**\n * Expand or collapse all nodes on this page.\n *\n * @param {string} nextstate The next state to change to.\n */\n expandCollapseAll: function(nextstate) {\n var currentstate = (nextstate == 'visible') ? 'hide' : 'visible';\n var ariaexpandedstate = (nextstate == 'visible') ? true : false;\n var iconclassnow = (nextstate == 'visible') ? CLASSES.EXPAND : CLASSES.COLLAPSE;\n var iconclassnext = (nextstate == 'visible') ? CLASSES.COLLAPSE : CLASSES.EXPAND;\n var imagenow = (nextstate == 'visible') ? expandedImage.attr('src') : collapsedImage.attr('src');\n $('.' + currentstate).each(function() {\n $(this).removeClass(currentstate);\n $(this).addClass(nextstate);\n $(this).attr('aria-expanded', ariaexpandedstate);\n });\n $('.tool_dataprivacy-expand-all').data('visibilityState', currentstate);\n\n str.get_string(currentstate, 'tool_dataprivacy').then(function(langString) {\n $('.tool_dataprivacy-expand-all').html(langString);\n return;\n }).catch(Notification.exception);\n\n $(':header i.fa').each(function() {\n $(this).removeClass(iconclassnow);\n $(this).addClass(iconclassnext);\n });\n $(':header img.icon').each(function() {\n $(this).attr('src', imagenow);\n });\n }\n };\n});\n"],"file":"expand_contract.min.js"}
\ No newline at end of file
+{"version":3,"file":"expand_contract.min.js","sources":["../src/expand_contract.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 .\n\n/**\n * Potential user selector module.\n *\n * @module tool_dataprivacy/expand_contract\n * @copyright 2018 Adrian Greeve\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/url', 'core/str'], function($, url, str) {\n\n var expandedImage = $('');\n var collapsedImage = $('');\n\n /*\n * Class names to apply when expanding/collapsing nodes.\n */\n var CLASSES = {\n EXPAND: 'fa-caret-right',\n COLLAPSE: 'fa-caret-down'\n };\n\n return /** @alias module:tool_dataprivacy/expand-collapse */ {\n /**\n * Expand or collapse a selected node.\n *\n * @param {object} targetnode The node that we want to expand / collapse\n * @param {object} thisnode The node that was clicked.\n */\n expandCollapse: function(targetnode, thisnode) {\n if (targetnode.hasClass('hide')) {\n targetnode.removeClass('hide');\n targetnode.addClass('visible');\n targetnode.attr('aria-expanded', true);\n thisnode.find(':header i.fa').removeClass(CLASSES.EXPAND);\n thisnode.find(':header i.fa').addClass(CLASSES.COLLAPSE);\n thisnode.find(':header img.icon').attr('src', expandedImage.attr('src'));\n } else {\n targetnode.removeClass('visible');\n targetnode.addClass('hide');\n targetnode.attr('aria-expanded', false);\n thisnode.find(':header i.fa').removeClass(CLASSES.COLLAPSE);\n thisnode.find(':header i.fa').addClass(CLASSES.EXPAND);\n thisnode.find(':header img.icon').attr('src', collapsedImage.attr('src'));\n }\n },\n\n /**\n * Expand or collapse all nodes on this page.\n *\n * @param {string} nextstate The next state to change to.\n */\n expandCollapseAll: function(nextstate) {\n var currentstate = (nextstate == 'visible') ? 'hide' : 'visible';\n var ariaexpandedstate = (nextstate == 'visible') ? true : false;\n var iconclassnow = (nextstate == 'visible') ? CLASSES.EXPAND : CLASSES.COLLAPSE;\n var iconclassnext = (nextstate == 'visible') ? CLASSES.COLLAPSE : CLASSES.EXPAND;\n var imagenow = (nextstate == 'visible') ? expandedImage.attr('src') : collapsedImage.attr('src');\n $('.' + currentstate).each(function() {\n $(this).removeClass(currentstate);\n $(this).addClass(nextstate);\n $(this).attr('aria-expanded', ariaexpandedstate);\n });\n $('.tool_dataprivacy-expand-all').data('visibilityState', currentstate);\n\n str.get_string(currentstate, 'tool_dataprivacy').then(function(langString) {\n $('.tool_dataprivacy-expand-all').html(langString);\n return;\n }).catch(Notification.exception);\n\n $(':header i.fa').each(function() {\n $(this).removeClass(iconclassnow);\n $(this).addClass(iconclassnext);\n });\n $(':header img.icon').each(function() {\n $(this).attr('src', imagenow);\n });\n }\n };\n});\n"],"names":["define","$","url","str","expandedImage","imageUrl","collapsedImage","CLASSES","expandCollapse","targetnode","thisnode","hasClass","removeClass","addClass","attr","find","expandCollapseAll","nextstate","currentstate","ariaexpandedstate","iconclassnow","iconclassnext","imagenow","each","this","data","get_string","then","langString","html","catch","Notification","exception"],"mappings":";;;;;;;AAuBAA,0CAAO,CAAC,SAAU,WAAY,aAAa,SAASC,EAAGC,IAAKC,SAEpDC,cAAgBH,EAAE,oBAAsBC,IAAIG,SAAS,cAAgB,OACrEC,eAAiBL,EAAE,oBAAsBC,IAAIG,SAAS,eAAiB,OAKvEE,eACQ,iBADRA,iBAEU,sBAG+C,CAOzDC,eAAgB,SAASC,WAAYC,UAC7BD,WAAWE,SAAS,SACpBF,WAAWG,YAAY,QACvBH,WAAWI,SAAS,WACpBJ,WAAWK,KAAK,iBAAiB,GACjCJ,SAASK,KAAK,gBAAgBH,YAAYL,gBAC1CG,SAASK,KAAK,gBAAgBF,SAASN,kBACvCG,SAASK,KAAK,oBAAoBD,KAAK,MAAOV,cAAcU,KAAK,UAEjEL,WAAWG,YAAY,WACvBH,WAAWI,SAAS,QACpBJ,WAAWK,KAAK,iBAAiB,GACjCJ,SAASK,KAAK,gBAAgBH,YAAYL,kBAC1CG,SAASK,KAAK,gBAAgBF,SAASN,gBACvCG,SAASK,KAAK,oBAAoBD,KAAK,MAAOR,eAAeQ,KAAK,UAS1EE,kBAAmB,SAASC,eACpBC,aAA6B,WAAbD,UAA0B,OAAS,UACnDE,kBAAkC,WAAbF,UACrBG,aAA6B,WAAbH,UAA0BV,eAAiBA,iBAC3Dc,cAA8B,WAAbJ,UAA0BV,iBAAmBA,eAC9De,SAAyB,WAAbL,UAA0Bb,cAAcU,KAAK,OAASR,eAAeQ,KAAK,OAC1Fb,EAAE,IAAMiB,cAAcK,MAAK,WACvBtB,EAAEuB,MAAMZ,YAAYM,cACpBjB,EAAEuB,MAAMX,SAASI,WACjBhB,EAAEuB,MAAMV,KAAK,gBAAiBK,sBAElClB,EAAE,gCAAgCwB,KAAK,kBAAmBP,cAE1Df,IAAIuB,WAAWR,aAAc,oBAAoBS,MAAK,SAASC,YAC3D3B,EAAE,gCAAgC4B,KAAKD,eAExCE,MAAMC,aAAaC,WAEtB/B,EAAE,gBAAgBsB,MAAK,WACnBtB,EAAEuB,MAAMZ,YAAYQ,cACpBnB,EAAEuB,MAAMX,SAASQ,kBAErBpB,EAAE,oBAAoBsB,MAAK,WACvBtB,EAAEuB,MAAMV,KAAK,MAAOQ"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/form-user-selector.min.js b/admin/tool/dataprivacy/amd/build/form-user-selector.min.js
index 72a0c40be9a..e0b5040af02 100644
--- a/admin/tool/dataprivacy/amd/build/form-user-selector.min.js
+++ b/admin/tool/dataprivacy/amd/build/form-user-selector.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/form-user-selector",["jquery","core/ajax","core/templates"],function(a,b,c){return{processResults:function processResults(b,c){var d=[];a.each(c,function(a,b){d.push({value:b.id,label:b._label})});return d},transport:function transport(d,e,f,g){var h=b.call([{methodname:"tool_dataprivacy_get_users",args:{query:e}}]);h[0].then(function(b){var d=[],e=0;a.each(b,function(a,b){d.push(c.render("tool_dataprivacy/form-user-selector-suggestion",b))});return a.when.apply(a.when,d).then(function(){var c=arguments;a.each(b,function(a,b){b._label=c[e];e++});f(b)})}).fail(g)}}});
-//# sourceMappingURL=form-user-selector.min.js.map
+/**
+ * Potential user selector module.
+ *
+ * @module tool_dataprivacy/form-user-selector
+ * @copyright 2018 Jun Pataleta
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/form-user-selector",["jquery","core/ajax","core/templates"],(function($,Ajax,Templates){return{processResults:function(selector,results){var users=[];return $.each(results,(function(index,user){users.push({value:user.id,label:user._label})})),users},transport:function(selector,query,success,failure){Ajax.call([{methodname:"tool_dataprivacy_get_users",args:{query:query}}])[0].then((function(results){var promises=[],i=0;return $.each(results,(function(index,user){promises.push(Templates.render("tool_dataprivacy/form-user-selector-suggestion",user))})),$.when.apply($.when,promises).then((function(){var args=arguments;$.each(results,(function(index,user){user._label=args[i],i++})),success(results)}))})).fail(failure)}}}));
+
+//# sourceMappingURL=form-user-selector.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/form-user-selector.min.js.map b/admin/tool/dataprivacy/amd/build/form-user-selector.min.js.map
index 1b0b75a5037..5d218425475 100644
--- a/admin/tool/dataprivacy/amd/build/form-user-selector.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/form-user-selector.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/form-user-selector.js"],"names":["define","$","Ajax","Templates","processResults","selector","results","users","each","index","user","push","value","id","label","_label","transport","query","success","failure","promise","call","methodname","args","then","promises","i","render","when","apply","arguments","fail"],"mappings":"AAuBAA,OAAM,uCAAC,CAAC,QAAD,CAAW,WAAX,CAAwB,gBAAxB,CAAD,CAA4C,SAASC,CAAT,CAAYC,CAAZ,CAAkBC,CAAlB,CAA6B,CAE3E,MAAgE,CAE5DC,cAAc,CAAE,wBAASC,CAAT,CAAmBC,CAAnB,CAA4B,CACxC,GAAIC,CAAAA,CAAK,CAAG,EAAZ,CACAN,CAAC,CAACO,IAAF,CAAOF,CAAP,CAAgB,SAASG,CAAT,CAAgBC,CAAhB,CAAsB,CAClCH,CAAK,CAACI,IAAN,CAAW,CACPC,KAAK,CAAEF,CAAI,CAACG,EADL,CAEPC,KAAK,CAAEJ,CAAI,CAACK,MAFL,CAAX,CAIH,CALD,EAMA,MAAOR,CAAAA,CACV,CAX2D,CAa5DS,SAAS,CAAE,mBAASX,CAAT,CAAmBY,CAAnB,CAA0BC,CAA1B,CAAmCC,CAAnC,CAA4C,CACnD,GAAIC,CAAAA,CAAO,CAEDlB,CAAI,CAACmB,IAAL,CAAU,CAAC,CACjBC,UAAU,CAAE,4BADK,CAEjBC,IAAI,CAAE,CACFN,KAAK,CAAEA,CADL,CAFW,CAAD,CAAV,CAFV,CASAG,CAAO,CAAC,CAAD,CAAP,CAAWI,IAAX,CAAgB,SAASlB,CAAT,CAAkB,CAC9B,GAAImB,CAAAA,CAAQ,CAAG,EAAf,CACIC,CAAC,CAAG,CADR,CAIAzB,CAAC,CAACO,IAAF,CAAOF,CAAP,CAAgB,SAASG,CAAT,CAAgBC,CAAhB,CAAsB,CAClCe,CAAQ,CAACd,IAAT,CAAcR,CAAS,CAACwB,MAAV,CAAiB,gDAAjB,CAAmEjB,CAAnE,CAAd,CACH,CAFD,EAKA,MAAOT,CAAAA,CAAC,CAAC2B,IAAF,CAAOC,KAAP,CAAa5B,CAAC,CAAC2B,IAAf,CAAqBH,CAArB,EAA+BD,IAA/B,CAAoC,UAAW,CAClD,GAAID,CAAAA,CAAI,CAAGO,SAAX,CACA7B,CAAC,CAACO,IAAF,CAAOF,CAAP,CAAgB,SAASG,CAAT,CAAgBC,CAAhB,CAAsB,CAClCA,CAAI,CAACK,MAAL,CAAcQ,CAAI,CAACG,CAAD,CAAlB,CACAA,CAAC,EACJ,CAHD,EAIAR,CAAO,CAACZ,CAAD,CAEV,CARM,CAUV,CApBD,EAoBGyB,IApBH,CAoBQZ,CApBR,CAqBH,CA5C2D,CAgDnE,CAlDK,CAAN","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 .\n\n/**\n * Potential user selector module.\n *\n * @module tool_dataprivacy/form-user-selector\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) {\n\n return /** @alias module:tool_dataprivacy/form-user-selector */ {\n\n processResults: function(selector, results) {\n var users = [];\n $.each(results, function(index, user) {\n users.push({\n value: user.id,\n label: user._label\n });\n });\n return users;\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n\n promise = Ajax.call([{\n methodname: 'tool_dataprivacy_get_users',\n args: {\n query: query\n }\n }]);\n\n promise[0].then(function(results) {\n var promises = [],\n i = 0;\n\n // Render the label.\n $.each(results, function(index, user) {\n promises.push(Templates.render('tool_dataprivacy/form-user-selector-suggestion', user));\n });\n\n // Apply the label to the results.\n return $.when.apply($.when, promises).then(function() {\n var args = arguments;\n $.each(results, function(index, user) {\n user._label = args[i];\n i++;\n });\n success(results);\n return;\n });\n\n }).fail(failure);\n }\n\n };\n\n});\n"],"file":"form-user-selector.min.js"}
\ No newline at end of file
+{"version":3,"file":"form-user-selector.min.js","sources":["../src/form-user-selector.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 .\n\n/**\n * Potential user selector module.\n *\n * @module tool_dataprivacy/form-user-selector\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) {\n\n return /** @alias module:tool_dataprivacy/form-user-selector */ {\n\n processResults: function(selector, results) {\n var users = [];\n $.each(results, function(index, user) {\n users.push({\n value: user.id,\n label: user._label\n });\n });\n return users;\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n\n promise = Ajax.call([{\n methodname: 'tool_dataprivacy_get_users',\n args: {\n query: query\n }\n }]);\n\n promise[0].then(function(results) {\n var promises = [],\n i = 0;\n\n // Render the label.\n $.each(results, function(index, user) {\n promises.push(Templates.render('tool_dataprivacy/form-user-selector-suggestion', user));\n });\n\n // Apply the label to the results.\n return $.when.apply($.when, promises).then(function() {\n var args = arguments;\n $.each(results, function(index, user) {\n user._label = args[i];\n i++;\n });\n success(results);\n return;\n });\n\n }).fail(failure);\n }\n\n };\n\n});\n"],"names":["define","$","Ajax","Templates","processResults","selector","results","users","each","index","user","push","value","id","label","_label","transport","query","success","failure","call","methodname","args","then","promises","i","render","when","apply","arguments","fail"],"mappings":";;;;;;;AAuBAA,6CAAO,CAAC,SAAU,YAAa,mBAAmB,SAASC,EAAGC,KAAMC,iBAEA,CAE5DC,eAAgB,SAASC,SAAUC,aAC3BC,MAAQ,UACZN,EAAEO,KAAKF,SAAS,SAASG,MAAOC,MAC5BH,MAAMI,KAAK,CACPC,MAAOF,KAAKG,GACZC,MAAOJ,KAAKK,YAGbR,OAGXS,UAAW,SAASX,SAAUY,MAAOC,QAASC,SAGhCjB,KAAKkB,KAAK,CAAC,CACjBC,WAAY,6BACZC,KAAM,CACFL,MAAOA,UAIP,GAAGM,MAAK,SAASjB,aACjBkB,SAAW,GACXC,EAAI,SAGRxB,EAAEO,KAAKF,SAAS,SAASG,MAAOC,MAC5Bc,SAASb,KAAKR,UAAUuB,OAAO,iDAAkDhB,UAI9ET,EAAE0B,KAAKC,MAAM3B,EAAE0B,KAAMH,UAAUD,MAAK,eACnCD,KAAOO,UACX5B,EAAEO,KAAKF,SAAS,SAASG,MAAOC,MAC5BA,KAAKK,OAASO,KAAKG,GACnBA,OAEJP,QAAQZ,eAIbwB,KAAKX"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/myrequestactions.min.js b/admin/tool/dataprivacy/amd/build/myrequestactions.min.js
index b1b7317c48a..ebad9a83240 100644
--- a/admin/tool/dataprivacy/amd/build/myrequestactions.min.js
+++ b/admin/tool/dataprivacy/amd/build/myrequestactions.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/myrequestactions",["exports","core/ajax","core/notification","core/pending","core/str"],function(a,b,c,d,e){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=f(b);c=f(c);d=f(d);function f(a){return a&&a.__esModule?a:{default:a}}function g(a,b){return m(a)||l(a,b)||j(a,b)||h()}function h(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function j(a,b){if(!a)return;if("string"==typeof a)return k(a,b);var c=Object.prototype.toString.call(a).slice(8,-1);if("Object"===c&&a.constructor)c=a.constructor.name;if("Map"===c||"Set"===c)return Array.from(c);if("Arguments"===c||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(c))return k(a,b)}function k(a,b){if(null==b||b>a.length)b=a.length;for(var c=0,d=Array(b);c{document.addEventListener("click",(event=>{const triggerElement=event.target.closest(SELECTORS_CANCEL_REQUEST);if(null===triggerElement)return;event.preventDefault();(0,_str.get_strings)([{key:"cancelrequest",component:"tool_dataprivacy"},{key:"cancelrequestconfirmation",component:"tool_dataprivacy"}]).then((_ref=>{let[cancelRequest,cancelConfirm]=_ref;return _notification.default.confirm(cancelRequest,cancelConfirm,cancelRequest,null,(()=>{const pendingPromise=new _pending.default("tool/dataprivacy:cancelRequest"),request={methodname:"tool_dataprivacy_cancel_data_request",args:{requestid:triggerElement.dataset.requestid}};_ajax.default.call([request])[0].then((response=>(response.result?window.location.reload():_notification.default.addNotification({type:"error",message:response.warnings[0].message}),pendingPromise.resolve()))).catch(_notification.default.exception)}))})).catch()}))}}));
+
+//# sourceMappingURL=myrequestactions.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/myrequestactions.min.js.map b/admin/tool/dataprivacy/amd/build/myrequestactions.min.js.map
index a0ee7a25871..ac1d3817f17 100644
--- a/admin/tool/dataprivacy/amd/build/myrequestactions.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/myrequestactions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/myrequestactions.js"],"names":["SELECTORS","CANCEL_REQUEST","init","document","addEventListener","event","triggerElement","target","closest","preventDefault","key","component","then","cancelRequest","cancelConfirm","Notification","confirm","pendingPromise","Pending","request","methodname","args","requestid","dataset","Ajax","call","response","result","window","location","reload","addNotification","type","message","warnings","resolve","catch","exception"],"mappings":"kNAuBA,OACA,OACA,O,khCAGMA,CAAAA,CAAS,CAAG,CACdC,cAAc,CAAE,0CADF,C,QAOE,QAAPC,CAAAA,IAAO,EAAM,CACtBC,QAAQ,CAACC,gBAAT,CAA0B,OAA1B,CAAmC,SAAAC,CAAK,CAAI,CACxC,GAAMC,CAAAA,CAAc,CAAGD,CAAK,CAACE,MAAN,CAAaC,OAAb,CAAqBR,CAAS,CAACC,cAA/B,CAAvB,CACA,GAAuB,IAAnB,GAAAK,CAAJ,CAA6B,CACzB,MACH,CAEDD,CAAK,CAACI,cAAN,GAOA,kBALwB,CACpB,CAACC,GAAG,CAAE,eAAN,CAAuBC,SAAS,CAAE,kBAAlC,CADoB,CAEpB,CAACD,GAAG,CAAE,2BAAN,CAAmCC,SAAS,CAAE,kBAA9C,CAFoB,CAKxB,EAA4BC,IAA5B,CAAiC,WAAoC,cAAlCC,CAAkC,MAAnBC,CAAmB,MACjE,MAAOC,WAAaC,OAAb,CAAqBH,CAArB,CAAoCC,CAApC,CAAmDD,CAAnD,CAAkE,IAAlE,CAAwE,UAAM,IAC3EI,CAAAA,CAAc,CAAG,GAAIC,UAAJ,CAAY,gCAAZ,CAD0D,CAE3EC,CAAO,CAAG,CACZC,UAAU,CAAE,sCADA,CAEZC,IAAI,CAAE,CAACC,SAAS,CAAEhB,CAAc,CAACiB,OAAf,CAAuBD,SAAnC,CAFM,CAFiE,CAOjFE,UAAKC,IAAL,CAAU,CAACN,CAAD,CAAV,EAAqB,CAArB,EAAwBP,IAAxB,CAA6B,SAAAc,CAAQ,CAAI,CACrC,GAAIA,CAAQ,CAACC,MAAb,CAAqB,CACjBC,MAAM,CAACC,QAAP,CAAgBC,MAAhB,EACH,CAFD,IAEO,CACHf,UAAagB,eAAb,CAA6B,CACzBC,IAAI,CAAE,OADmB,CAEzBC,OAAO,CAAEP,CAAQ,CAACQ,QAAT,CAAkB,CAAlB,EAAqBD,OAFL,CAA7B,CAIH,CACD,MAAOhB,CAAAA,CAAc,CAACkB,OAAf,EACV,CAVD,EAUGC,KAVH,CAUSrB,UAAasB,SAVtB,CAWH,CAlBM,CAmBV,CApBD,EAoBGD,KApBH,EAqBH,CAlCD,CAmCH,C","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 .\n\n/**\n * AMD module to enable users to manage their own data requests.\n *\n * @module tool_dataprivacy/myrequestactions\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\nimport Notification from 'core/notification';\nimport Pending from 'core/pending';\nimport {get_strings as getStrings} from 'core/str';\n\nconst SELECTORS = {\n CANCEL_REQUEST: '[data-action=\"cancel\"][data-requestid]',\n};\n\n/**\n * Initialize module\n */\nexport const init = () => {\n document.addEventListener('click', event => {\n const triggerElement = event.target.closest(SELECTORS.CANCEL_REQUEST);\n if (triggerElement === null) {\n return;\n }\n\n event.preventDefault();\n\n const requiredStrings = [\n {key: 'cancelrequest', component: 'tool_dataprivacy'},\n {key: 'cancelrequestconfirmation', component: 'tool_dataprivacy'},\n ];\n\n getStrings(requiredStrings).then(([cancelRequest, cancelConfirm]) => {\n return Notification.confirm(cancelRequest, cancelConfirm, cancelRequest, null, () => {\n const pendingPromise = new Pending('tool/dataprivacy:cancelRequest');\n const request = {\n methodname: 'tool_dataprivacy_cancel_data_request',\n args: {requestid: triggerElement.dataset.requestid}\n };\n\n Ajax.call([request])[0].then(response => {\n if (response.result) {\n window.location.reload();\n } else {\n Notification.addNotification({\n type: 'error',\n message: response.warnings[0].message\n });\n }\n return pendingPromise.resolve();\n }).catch(Notification.exception);\n });\n }).catch();\n });\n};\n"],"file":"myrequestactions.min.js"}
\ No newline at end of file
+{"version":3,"file":"myrequestactions.min.js","sources":["../src/myrequestactions.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 .\n\n/**\n * AMD module to enable users to manage their own data requests.\n *\n * @module tool_dataprivacy/myrequestactions\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\nimport Notification from 'core/notification';\nimport Pending from 'core/pending';\nimport {get_strings as getStrings} from 'core/str';\n\nconst SELECTORS = {\n CANCEL_REQUEST: '[data-action=\"cancel\"][data-requestid]',\n};\n\n/**\n * Initialize module\n */\nexport const init = () => {\n document.addEventListener('click', event => {\n const triggerElement = event.target.closest(SELECTORS.CANCEL_REQUEST);\n if (triggerElement === null) {\n return;\n }\n\n event.preventDefault();\n\n const requiredStrings = [\n {key: 'cancelrequest', component: 'tool_dataprivacy'},\n {key: 'cancelrequestconfirmation', component: 'tool_dataprivacy'},\n ];\n\n getStrings(requiredStrings).then(([cancelRequest, cancelConfirm]) => {\n return Notification.confirm(cancelRequest, cancelConfirm, cancelRequest, null, () => {\n const pendingPromise = new Pending('tool/dataprivacy:cancelRequest');\n const request = {\n methodname: 'tool_dataprivacy_cancel_data_request',\n args: {requestid: triggerElement.dataset.requestid}\n };\n\n Ajax.call([request])[0].then(response => {\n if (response.result) {\n window.location.reload();\n } else {\n Notification.addNotification({\n type: 'error',\n message: response.warnings[0].message\n });\n }\n return pendingPromise.resolve();\n }).catch(Notification.exception);\n });\n }).catch();\n });\n};\n"],"names":["SELECTORS","document","addEventListener","event","triggerElement","target","closest","preventDefault","key","component","then","_ref","cancelRequest","cancelConfirm","Notification","confirm","pendingPromise","Pending","request","methodname","args","requestid","dataset","call","response","result","window","location","reload","addNotification","type","message","warnings","resolve","catch","exception"],"mappings":";;;;;;;0NA4BMA,yBACc,uDAMA,KAChBC,SAASC,iBAAiB,SAASC,cACzBC,eAAiBD,MAAME,OAAOC,QAAQN,6BACrB,OAAnBI,sBAIJD,MAAMI,sCAEkB,CACpB,CAACC,IAAK,gBAAiBC,UAAW,oBAClC,CAACD,IAAK,4BAA6BC,UAAW,sBAGtBC,MAAKC,WAAEC,cAAeC,2BACvCC,sBAAaC,QAAQH,cAAeC,cAAeD,cAAe,MAAM,WACrEI,eAAiB,IAAIC,iBAAQ,kCAC7BC,QAAU,CACZC,WAAY,uCACZC,KAAM,CAACC,UAAWjB,eAAekB,QAAQD,0BAGxCE,KAAK,CAACL,UAAU,GAAGR,MAAKc,WACrBA,SAASC,OACTC,OAAOC,SAASC,+BAEHC,gBAAgB,CACzBC,KAAM,QACNC,QAASP,SAASQ,SAAS,GAAGD,UAG/Bf,eAAeiB,aACvBC,MAAMpB,sBAAaqB,iBAE3BD"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/purposesactions.min.js b/admin/tool/dataprivacy/amd/build/purposesactions.min.js
index 765e5ef4102..edcabcf6e51 100644
--- a/admin/tool/dataprivacy/amd/build/purposesactions.min.js
+++ b/admin/tool/dataprivacy/amd/build/purposesactions.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/purposesactions",["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events"],function(a,b,c,d,e,f){var g={DELETE:"[data-action=\"deletepurpose\"]"},h=function(){this.registerEvents()};h.prototype.registerEvents=function(){a(g.DELETE).click(function(g){g.preventDefault();var h=a(this).data("id"),i=a(this).data("name");d.get_strings([{key:"deletepurpose",component:"tool_dataprivacy"},{key:"deletepurposetext",component:"tool_dataprivacy",param:i},{key:"delete"}]).then(function(d){var g=d[0],i=d[1],j=d[2];return e.create({title:g,body:i,type:e.types.SAVE_CANCEL}).then(function(d){d.setSaveButtonText(j);d.getRoot().on(f.save,function(){b.call([{methodname:"tool_dataprivacy_delete_purpose",args:{id:h}}])[0].done(function(b){if(b.result){a("tr[data-purposeid=\""+h+"\"]").remove()}else{c.addNotification({message:b.warnings[0].message,type:"error"})}}).fail(c.exception)});d.getRoot().on(f.hidden,function(){d.destroy()});return d})}).done(function(a){a.show()}).fail(c.exception)})};return{init:function init(){return new h}}});
-//# sourceMappingURL=purposesactions.min.js.map
+/**
+ * AMD module for purposes actions.
+ *
+ * @module tool_dataprivacy/purposesactions
+ * @copyright 2018 David Monllao
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/purposesactions",["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events"],(function($,Ajax,Notification,Str,ModalFactory,ModalEvents){var ACTIONS_DELETE='[data-action="deletepurpose"]',PurposesActions=function(){this.registerEvents()};return PurposesActions.prototype.registerEvents=function(){$(ACTIONS_DELETE).click((function(e){e.preventDefault();var id=$(this).data("id"),stringkeys=[{key:"deletepurpose",component:"tool_dataprivacy"},{key:"deletepurposetext",component:"tool_dataprivacy",param:$(this).data("name")},{key:"delete"}];Str.get_strings(stringkeys).then((function(langStrings){var title=langStrings[0],confirmMessage=langStrings[1],buttonText=langStrings[2];return ModalFactory.create({title:title,body:confirmMessage,type:ModalFactory.types.SAVE_CANCEL}).then((function(modal){return modal.setSaveButtonText(buttonText),modal.getRoot().on(ModalEvents.save,(function(){var request={methodname:"tool_dataprivacy_delete_purpose",args:{id:id}};Ajax.call([request])[0].done((function(data){data.result?$('tr[data-purposeid="'+id+'"]').remove():Notification.addNotification({message:data.warnings[0].message,type:"error"})})).fail(Notification.exception)})),modal.getRoot().on(ModalEvents.hidden,(function(){modal.destroy()})),modal}))})).done((function(modal){modal.show()})).fail(Notification.exception)}))},{init:function(){return new PurposesActions}}}));
+
+//# sourceMappingURL=purposesactions.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/purposesactions.min.js.map b/admin/tool/dataprivacy/amd/build/purposesactions.min.js.map
index 6ac9001c7a5..6e7f8f4da8f 100644
--- a/admin/tool/dataprivacy/amd/build/purposesactions.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/purposesactions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/purposesactions.js"],"names":["define","$","Ajax","Notification","Str","ModalFactory","ModalEvents","ACTIONS","DELETE","PurposesActions","registerEvents","prototype","click","e","preventDefault","id","data","purposename","get_strings","key","component","param","then","langStrings","title","confirmMessage","buttonText","create","body","type","types","SAVE_CANCEL","modal","setSaveButtonText","getRoot","on","save","call","methodname","args","done","result","remove","addNotification","message","warnings","fail","exception","hidden","destroy","show"],"mappings":"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","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 .\n\n/**\n * AMD module for purposes actions.\n *\n * @module tool_dataprivacy/purposesactions\n * @copyright 2018 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events'],\nfunction($, Ajax, Notification, Str, ModalFactory, ModalEvents) {\n\n /**\n * List of action selectors.\n *\n * @type {{DELETE: string}}\n */\n var ACTIONS = {\n DELETE: '[data-action=\"deletepurpose\"]',\n };\n\n /**\n * PurposesActions class.\n */\n var PurposesActions = function() {\n this.registerEvents();\n };\n\n /**\n * Register event listeners.\n */\n PurposesActions.prototype.registerEvents = function() {\n $(ACTIONS.DELETE).click(function(e) {\n e.preventDefault();\n\n var id = $(this).data('id');\n var purposename = $(this).data('name');\n var stringkeys = [\n {\n key: 'deletepurpose',\n component: 'tool_dataprivacy'\n },\n {\n key: 'deletepurposetext',\n component: 'tool_dataprivacy',\n param: purposename\n },\n {\n key: 'delete'\n }\n ];\n\n Str.get_strings(stringkeys).then(function(langStrings) {\n var title = langStrings[0];\n var confirmMessage = langStrings[1];\n var buttonText = langStrings[2];\n return ModalFactory.create({\n title: title,\n body: confirmMessage,\n type: ModalFactory.types.SAVE_CANCEL\n }).then(function(modal) {\n modal.setSaveButtonText(buttonText);\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function() {\n\n var request = {\n methodname: 'tool_dataprivacy_delete_purpose',\n args: {'id': id}\n };\n\n Ajax.call([request])[0].done(function(data) {\n if (data.result) {\n $('tr[data-purposeid=\"' + id + '\"]').remove();\n } else {\n Notification.addNotification({\n message: data.warnings[0].message,\n type: 'error'\n });\n }\n }).fail(Notification.exception);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n return modal;\n });\n }).done(function(modal) {\n modal.show();\n\n }).fail(Notification.exception);\n });\n };\n\n return /** @alias module:tool_dataprivacy/purposesactions */ {\n // Public variables and functions.\n\n /**\n * Initialise the module.\n *\n * @method init\n * @return {PurposesActions}\n */\n 'init': function() {\n return new PurposesActions();\n }\n };\n});\n"],"file":"purposesactions.min.js"}
\ No newline at end of file
+{"version":3,"file":"purposesactions.min.js","sources":["../src/purposesactions.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 .\n\n/**\n * AMD module for purposes actions.\n *\n * @module tool_dataprivacy/purposesactions\n * @copyright 2018 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events'],\nfunction($, Ajax, Notification, Str, ModalFactory, ModalEvents) {\n\n /**\n * List of action selectors.\n *\n * @type {{DELETE: string}}\n */\n var ACTIONS = {\n DELETE: '[data-action=\"deletepurpose\"]',\n };\n\n /**\n * PurposesActions class.\n */\n var PurposesActions = function() {\n this.registerEvents();\n };\n\n /**\n * Register event listeners.\n */\n PurposesActions.prototype.registerEvents = function() {\n $(ACTIONS.DELETE).click(function(e) {\n e.preventDefault();\n\n var id = $(this).data('id');\n var purposename = $(this).data('name');\n var stringkeys = [\n {\n key: 'deletepurpose',\n component: 'tool_dataprivacy'\n },\n {\n key: 'deletepurposetext',\n component: 'tool_dataprivacy',\n param: purposename\n },\n {\n key: 'delete'\n }\n ];\n\n Str.get_strings(stringkeys).then(function(langStrings) {\n var title = langStrings[0];\n var confirmMessage = langStrings[1];\n var buttonText = langStrings[2];\n return ModalFactory.create({\n title: title,\n body: confirmMessage,\n type: ModalFactory.types.SAVE_CANCEL\n }).then(function(modal) {\n modal.setSaveButtonText(buttonText);\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function() {\n\n var request = {\n methodname: 'tool_dataprivacy_delete_purpose',\n args: {'id': id}\n };\n\n Ajax.call([request])[0].done(function(data) {\n if (data.result) {\n $('tr[data-purposeid=\"' + id + '\"]').remove();\n } else {\n Notification.addNotification({\n message: data.warnings[0].message,\n type: 'error'\n });\n }\n }).fail(Notification.exception);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n return modal;\n });\n }).done(function(modal) {\n modal.show();\n\n }).fail(Notification.exception);\n });\n };\n\n return /** @alias module:tool_dataprivacy/purposesactions */ {\n // Public variables and functions.\n\n /**\n * Initialise the module.\n *\n * @method init\n * @return {PurposesActions}\n */\n 'init': function() {\n return new PurposesActions();\n }\n };\n});\n"],"names":["define","$","Ajax","Notification","Str","ModalFactory","ModalEvents","ACTIONS","PurposesActions","registerEvents","prototype","click","e","preventDefault","id","this","data","stringkeys","key","component","param","get_strings","then","langStrings","title","confirmMessage","buttonText","create","body","type","types","SAVE_CANCEL","modal","setSaveButtonText","getRoot","on","save","request","methodname","args","call","done","result","remove","addNotification","message","warnings","fail","exception","hidden","destroy","show"],"mappings":";;;;;;;AAsBAA,0CAAO,CACH,SACA,YACA,oBACA,WACA,qBACA,sBACJ,SAASC,EAAGC,KAAMC,aAAcC,IAAKC,aAAcC,iBAO3CC,eACQ,gCAMRC,gBAAkB,gBACbC,yBAMTD,gBAAgBE,UAAUD,eAAiB,WACvCR,EAAEM,gBAAgBI,OAAM,SAASC,GAC7BA,EAAEC,qBAEEC,GAAKb,EAAEc,MAAMC,KAAK,MAElBC,WAAa,CACb,CACIC,IAAK,gBACLC,UAAW,oBAEf,CACID,IAAK,oBACLC,UAAW,mBACXC,MATUnB,EAAEc,MAAMC,KAAK,SAW3B,CACIE,IAAK,WAIbd,IAAIiB,YAAYJ,YAAYK,MAAK,SAASC,iBAClCC,MAAQD,YAAY,GACpBE,eAAiBF,YAAY,GAC7BG,WAAaH,YAAY,UACtBlB,aAAasB,OAAO,CACvBH,MAAOA,MACPI,KAAMH,eACNI,KAAMxB,aAAayB,MAAMC,cAC1BT,MAAK,SAASU,cACbA,MAAMC,kBAAkBP,YAGxBM,MAAME,UAAUC,GAAG7B,YAAY8B,MAAM,eAE7BC,QAAU,CACVC,WAAY,kCACZC,KAAM,IAAOzB,KAGjBZ,KAAKsC,KAAK,CAACH,UAAU,GAAGI,MAAK,SAASzB,MAC9BA,KAAK0B,OACLzC,EAAE,sBAAwBa,GAAK,MAAM6B,SAErCxC,aAAayC,gBAAgB,CACzBC,QAAS7B,KAAK8B,SAAS,GAAGD,QAC1BhB,KAAM,aAGfkB,KAAK5C,aAAa6C,cAIzBhB,MAAME,UAAUC,GAAG7B,YAAY2C,QAAQ,WAEnCjB,MAAMkB,aAGHlB,YAEZS,MAAK,SAAST,OACbA,MAAMmB,UAEPJ,KAAK5C,aAAa6C,eAIgC,MASjD,kBACG,IAAIxC"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/request_filter.min.js b/admin/tool/dataprivacy/amd/build/request_filter.min.js
index ed608348291..048c7629f17 100644
--- a/admin/tool/dataprivacy/amd/build/request_filter.min.js
+++ b/admin/tool/dataprivacy/amd/build/request_filter.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/request_filter",["jquery","core/form-autocomplete","core/str","core/notification"],function(a,b,c,d){var e={REQUEST_FILTERS:"#request-filters"},f=function init(){c.get_strings([{key:"filter",component:"moodle"},{key:"nofiltersapplied",component:"moodle"}]).then(function(a){var c=a[0],d=a[1];return b.enhance(e.REQUEST_FILTERS,!1,"",c,!1,!0,d,!0)}).fail(d.exception);var f=a(e.REQUEST_FILTERS).val();a(e.REQUEST_FILTERS).on("change",function(){var b=a(this).val();if(f.join(",")!==b.join(",")){if(0===b.length){a("#filters-cleared").val(1)}a(this.form).submit()}})};return{init:function init(){f()}}});
-//# sourceMappingURL=request_filter.min.js.map
+/**
+ * JS module for the data requests filter.
+ *
+ * @module tool_dataprivacy/request_filter
+ * @copyright 2018 Jun Pataleta
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/request_filter",["jquery","core/form-autocomplete","core/str","core/notification"],(function($,Autocomplete,Str,Notification){var SELECTORS_REQUEST_FILTERS="#request-filters";return{init:function(){!function(){Str.get_strings([{key:"filter",component:"moodle"},{key:"nofiltersapplied",component:"moodle"}]).then((function(langstrings){var placeholder=langstrings[0],noSelectionString=langstrings[1];return Autocomplete.enhance(SELECTORS_REQUEST_FILTERS,!1,"",placeholder,!1,!0,noSelectionString,!0)})).fail(Notification.exception);var last=$(SELECTORS_REQUEST_FILTERS).val();$(SELECTORS_REQUEST_FILTERS).on("change",(function(){var current=$(this).val();last.join(",")!==current.join(",")&&(0===current.length&&$("#filters-cleared").val(1),$(this.form).submit())}))}()}}}));
+
+//# sourceMappingURL=request_filter.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/request_filter.min.js.map b/admin/tool/dataprivacy/amd/build/request_filter.min.js.map
index 15634cd24d4..2bc86c5ab28 100644
--- a/admin/tool/dataprivacy/amd/build/request_filter.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/request_filter.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/request_filter.js"],"names":["define","$","Autocomplete","Str","Notification","SELECTORS","REQUEST_FILTERS","init","get_strings","key","component","then","langstrings","placeholder","noSelectionString","enhance","fail","exception","last","val","on","current","join","length","form","submit"],"mappings":"AAsBAA,OAAM,mCAAC,CAAC,QAAD,CAAW,wBAAX,CAAqC,UAArC,CAAiD,mBAAjD,CAAD,CAAwE,SAASC,CAAT,CAAYC,CAAZ,CAA0BC,CAA1B,CAA+BC,CAA/B,CAA6C,IAQnHC,CAAAA,CAAS,CAAG,CACZC,eAAe,CAAE,kBADL,CARuG,CAkBnHC,CAAI,CAAG,QAAPA,CAAAA,IAAO,EAAW,CAYlBJ,CAAG,CAACK,WAAJ,CAXiB,CACb,CACIC,GAAG,CAAE,QADT,CAEIC,SAAS,CAAE,QAFf,CADa,CAKb,CACID,GAAG,CAAE,kBADT,CAEIC,SAAS,CAAE,QAFf,CALa,CAWjB,EAA4BC,IAA5B,CAAiC,SAASC,CAAT,CAAsB,IAC/CC,CAAAA,CAAW,CAAGD,CAAW,CAAC,CAAD,CADsB,CAE/CE,CAAiB,CAAGF,CAAW,CAAC,CAAD,CAFgB,CAGnD,MAAOV,CAAAA,CAAY,CAACa,OAAb,CAAqBV,CAAS,CAACC,eAA/B,IAAuD,EAAvD,CAA2DO,CAA3D,OAAqFC,CAArF,IACV,CAJD,EAIGE,IAJH,CAIQZ,CAAY,CAACa,SAJrB,EAMA,GAAIC,CAAAA,CAAI,CAAGjB,CAAC,CAACI,CAAS,CAACC,eAAX,CAAD,CAA6Ba,GAA7B,EAAX,CACAlB,CAAC,CAACI,CAAS,CAACC,eAAX,CAAD,CAA6Bc,EAA7B,CAAgC,QAAhC,CAA0C,UAAW,CACjD,GAAIC,CAAAA,CAAO,CAAGpB,CAAC,CAAC,IAAD,CAAD,CAAQkB,GAAR,EAAd,CAEA,GAAID,CAAI,CAACI,IAAL,CAAU,GAAV,IAAmBD,CAAO,CAACC,IAAR,CAAa,GAAb,CAAvB,CAA0C,CAEtC,GAAuB,CAAnB,GAAAD,CAAO,CAACE,MAAZ,CAA0B,CACtBtB,CAAC,CAAC,kBAAD,CAAD,CAAsBkB,GAAtB,CAA0B,CAA1B,CACH,CACDlB,CAAC,CAAC,KAAKuB,IAAN,CAAD,CAAaC,MAAb,EACH,CACJ,CAVD,CAWH,CAhDsH,CAkDvH,MAAmD,CAM/ClB,IAAI,CAAE,eAAW,CACbA,CAAI,EACP,CAR8C,CAUtD,CA5DK,CAAN","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 .\n\n/**\n * JS module for the data requests filter.\n *\n * @module tool_dataprivacy/request_filter\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/form-autocomplete', 'core/str', 'core/notification'], function($, Autocomplete, Str, Notification) {\n\n /**\n * Selectors.\n *\n * @access private\n * @type {{REQUEST_FILTERS: string}}\n */\n var SELECTORS = {\n REQUEST_FILTERS: '#request-filters'\n };\n\n /**\n * Init function.\n *\n * @method init\n * @private\n */\n var init = function() {\n var stringkeys = [\n {\n key: 'filter',\n component: 'moodle'\n },\n {\n key: 'nofiltersapplied',\n component: 'moodle'\n }\n ];\n\n Str.get_strings(stringkeys).then(function(langstrings) {\n var placeholder = langstrings[0];\n var noSelectionString = langstrings[1];\n return Autocomplete.enhance(SELECTORS.REQUEST_FILTERS, false, '', placeholder, false, true, noSelectionString, true);\n }).fail(Notification.exception);\n\n var last = $(SELECTORS.REQUEST_FILTERS).val();\n $(SELECTORS.REQUEST_FILTERS).on('change', function() {\n var current = $(this).val();\n // Prevent form from submitting unnecessarily, eg. on blur when no filter is selected.\n if (last.join(',') !== current.join(',')) {\n // If we're submitting without filters, set the hidden input 'filters-cleared' to 1.\n if (current.length === 0) {\n $('#filters-cleared').val(1);\n }\n $(this.form).submit();\n }\n });\n };\n\n return /** @alias module:core/form-autocomplete */ {\n /**\n * Initialise the unified user filter.\n *\n * @method init\n */\n init: function() {\n init();\n }\n };\n});\n"],"file":"request_filter.min.js"}
\ No newline at end of file
+{"version":3,"file":"request_filter.min.js","sources":["../src/request_filter.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 .\n\n/**\n * JS module for the data requests filter.\n *\n * @module tool_dataprivacy/request_filter\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/form-autocomplete', 'core/str', 'core/notification'], function($, Autocomplete, Str, Notification) {\n\n /**\n * Selectors.\n *\n * @access private\n * @type {{REQUEST_FILTERS: string}}\n */\n var SELECTORS = {\n REQUEST_FILTERS: '#request-filters'\n };\n\n /**\n * Init function.\n *\n * @method init\n * @private\n */\n var init = function() {\n var stringkeys = [\n {\n key: 'filter',\n component: 'moodle'\n },\n {\n key: 'nofiltersapplied',\n component: 'moodle'\n }\n ];\n\n Str.get_strings(stringkeys).then(function(langstrings) {\n var placeholder = langstrings[0];\n var noSelectionString = langstrings[1];\n return Autocomplete.enhance(SELECTORS.REQUEST_FILTERS, false, '', placeholder, false, true, noSelectionString, true);\n }).fail(Notification.exception);\n\n var last = $(SELECTORS.REQUEST_FILTERS).val();\n $(SELECTORS.REQUEST_FILTERS).on('change', function() {\n var current = $(this).val();\n // Prevent form from submitting unnecessarily, eg. on blur when no filter is selected.\n if (last.join(',') !== current.join(',')) {\n // If we're submitting without filters, set the hidden input 'filters-cleared' to 1.\n if (current.length === 0) {\n $('#filters-cleared').val(1);\n }\n $(this.form).submit();\n }\n });\n };\n\n return /** @alias module:core/form-autocomplete */ {\n /**\n * Initialise the unified user filter.\n *\n * @method init\n */\n init: function() {\n init();\n }\n };\n});\n"],"names":["define","$","Autocomplete","Str","Notification","SELECTORS","init","get_strings","key","component","then","langstrings","placeholder","noSelectionString","enhance","fail","exception","last","val","on","current","this","join","length","form","submit"],"mappings":";;;;;;;AAsBAA,yCAAO,CAAC,SAAU,yBAA0B,WAAY,sBAAsB,SAASC,EAAGC,aAAcC,IAAKC,kBAQrGC,0BACiB,yBAyC8B,CAM/CC,KAAM,YAtCC,WAYPH,IAAII,YAXa,CACb,CACIC,IAAK,SACLC,UAAW,UAEf,CACID,IAAK,mBACLC,UAAW,YAISC,MAAK,SAASC,iBAClCC,YAAcD,YAAY,GAC1BE,kBAAoBF,YAAY,UAC7BT,aAAaY,QAAQT,2BAA2B,EAAO,GAAIO,aAAa,GAAO,EAAMC,mBAAmB,MAChHE,KAAKX,aAAaY,eAEjBC,KAAOhB,EAAEI,2BAA2Ba,MACxCjB,EAAEI,2BAA2Bc,GAAG,UAAU,eAClCC,QAAUnB,EAAEoB,MAAMH,MAElBD,KAAKK,KAAK,OAASF,QAAQE,KAAK,OAET,IAAnBF,QAAQG,QACRtB,EAAE,oBAAoBiB,IAAI,GAE9BjB,EAAEoB,KAAKG,MAAMC,aAYjBnB"}
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/requestactions.min.js b/admin/tool/dataprivacy/amd/build/requestactions.min.js
index 3c081e89dda..e77bb08fd2d 100644
--- a/admin/tool/dataprivacy/amd/build/requestactions.min.js
+++ b/admin/tool/dataprivacy/amd/build/requestactions.min.js
@@ -1,2 +1,10 @@
-define ("tool_dataprivacy/requestactions",["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events","core/templates","tool_dataprivacy/data_request_modal","tool_dataprivacy/events"],function(a,b,c,d,e,f,g,h,i){var q={APPROVE_REQUEST:"[data-action=\"approve\"]",DENY_REQUEST:"[data-action=\"deny\"]",VIEW_REQUEST:"[data-action=\"view\"]",MARK_COMPLETE:"[data-action=\"complete\"]",CHANGE_BULK_ACTION:"[id=\"bulk-action\"]",CONFIRM_BULK_ACTION:"[id=\"confirm-bulk-action\"]",SELECT_ALL:"[data-action=\"selectall\"]"},r={APPROVE:1,DENY:2},s={SELECT_REQUEST:".selectrequests"},t=function(){this.registerEvents()};t.prototype.registerEvents=function(){a(q.VIEW_REQUEST).click(function(d){d.preventDefault();var k=a(this).data("requestid"),m=b.call([{methodname:"tool_dataprivacy_get_data_request",args:{requestid:k}}]);a.when(m[0]).then(function(a){if(a.result){return a.result}c.addNotification({message:a.warnings[0].message,type:"error"});return!1}).then(function(a){var b=g.render("tool_dataprivacy/request_details",a),c={approvedeny:a.approvedeny,canmarkcomplete:a.canmarkcomplete};return e.create({title:a.typename,body:b,type:h.TYPE,large:!0,templateContext:c})}).then(function(a){a.getRoot().on(i.approve,function(){o(i.approve,j(k))});a.getRoot().on(i.deny,function(){o(i.deny,l(k))});a.getRoot().on(i.complete,function(){p("tool_dataprivacy_mark_complete",{requestid:k})});a.getRoot().on(f.hidden,function(){a.destroy()});a.show()}).catch(c.exception)});a(q.APPROVE_REQUEST).click(function(b){b.preventDefault();var c=a(this).data("requestid");o(i.approve,j(c))});a(q.DENY_REQUEST).click(function(b){b.preventDefault();var c=a(this).data("requestid");o(i.deny,l(c))});a(q.MARK_COMPLETE).click(function(b){b.preventDefault();var c=a(this).data("requestid");o(i.complete,n(c))});a(q.CONFIRM_BULK_ACTION).click(function(){var b=[],e="",f={},g=[{key:"selectbulkaction",component:"tool_dataprivacy"},{key:"selectdatarequests",component:"tool_dataprivacy"},{key:"ok"}],h=parseInt(a("#bulk-action").val());if(h!=r.APPROVE&&h!=r.DENY){d.get_strings(g).done(function(a){c.alert("",a[0],a[2])}).fail(c.exception);return}a(".selectrequests:checked").each(function(){b.push(a(this).val())});if(1>b.length){d.get_strings(g).done(function(a){c.alert("",a[1],a[2])}).fail(c.exception);return}switch(h){case r.APPROVE:e=i.bulkApprove;f=k(b);break;case r.DENY:e=i.bulkDeny;f=m(b);}o(e,f)});a(q.SELECT_ALL).change(function(b){b.preventDefault();var c=a(this).is(":checked");a(s.SELECT_REQUEST).prop("checked",c)})};function j(a){return{wsfunction:"tool_dataprivacy_approve_data_request",wsparams:{requestid:a}}}function k(a){return{wsfunction:"tool_dataprivacy_bulk_approve_data_requests",wsparams:{requestids:a}}}function l(a){return{wsfunction:"tool_dataprivacy_deny_data_request",wsparams:{requestid:a}}}function m(a){return{wsfunction:"tool_dataprivacy_bulk_deny_data_requests",wsparams:{requestids:a}}}function n(a){return{wsfunction:"tool_dataprivacy_mark_complete",wsparams:{requestid:a}}}function o(a,b){var g=[];switch(a){case i.approve:g=[{key:"approverequest",component:"tool_dataprivacy"},{key:"confirmapproval",component:"tool_dataprivacy"}];break;case i.bulkApprove:g=[{key:"bulkapproverequests",component:"tool_dataprivacy"},{key:"confirmbulkapproval",component:"tool_dataprivacy"}];break;case i.deny:g=[{key:"denyrequest",component:"tool_dataprivacy"},{key:"confirmdenial",component:"tool_dataprivacy"}];break;case i.bulkDeny:g=[{key:"bulkdenyrequests",component:"tool_dataprivacy"},{key:"confirmbulkdenial",component:"tool_dataprivacy"}];break;case i.complete:g=[{key:"markcomplete",component:"tool_dataprivacy"},{key:"confirmcompletion",component:"tool_dataprivacy"}];break;}var h="";d.get_strings(g).then(function(a){h=a[0];var b=a[1];return e.create({title:h,body:b,type:e.types.SAVE_CANCEL})}).then(function(a){a.setSaveButtonText(h);a.getRoot().on(f.save,function(){p(b.wsfunction,b.wsparams)});a.getRoot().on(f.hidden,function(){a.destroy()});a.show()}).catch(c.exception)}function p(a,d){b.call([{methodname:a,args:d}])[0].done(function(a){if(a.result){window.location.reload()}else{c.addNotification({message:a.warnings[0].message,type:"error"})}}).fail(c.exception)}return t});
-//# sourceMappingURL=requestactions.min.js.map
+/**
+ * Request actions.
+ *
+ * @module tool_dataprivacy/requestactions
+ * @copyright 2018 Jun Pataleta
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_dataprivacy/requestactions",["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events","core/templates","tool_dataprivacy/data_request_modal","tool_dataprivacy/events"],(function($,Ajax,Notification,Str,ModalFactory,ModalEvents,Templates,ModalDataRequest,DataPrivacyEvents){var ACTIONS_APPROVE_REQUEST='[data-action="approve"]',ACTIONS_DENY_REQUEST='[data-action="deny"]',ACTIONS_VIEW_REQUEST='[data-action="view"]',ACTIONS_MARK_COMPLETE='[data-action="complete"]',ACTIONS_CONFIRM_BULK_ACTION='[id="confirm-bulk-action"]',ACTIONS_SELECT_ALL='[data-action="selectall"]',BULK_ACTIONS_APPROVE=1,BULK_ACTIONS_DENY=2,SELECTORS_SELECT_REQUEST=".selectrequests",RequestActions=function(){this.registerEvents()};function approveEventWsData(requestId){return{wsfunction:"tool_dataprivacy_approve_data_request",wsparams:{requestid:requestId}}}function denyEventWsData(requestId){return{wsfunction:"tool_dataprivacy_deny_data_request",wsparams:{requestid:requestId}}}function showConfirmation(action,wsdata){var keys=[];switch(action){case DataPrivacyEvents.approve:keys=[{key:"approverequest",component:"tool_dataprivacy"},{key:"confirmapproval",component:"tool_dataprivacy"}];break;case DataPrivacyEvents.bulkApprove:keys=[{key:"bulkapproverequests",component:"tool_dataprivacy"},{key:"confirmbulkapproval",component:"tool_dataprivacy"}];break;case DataPrivacyEvents.deny:keys=[{key:"denyrequest",component:"tool_dataprivacy"},{key:"confirmdenial",component:"tool_dataprivacy"}];break;case DataPrivacyEvents.bulkDeny:keys=[{key:"bulkdenyrequests",component:"tool_dataprivacy"},{key:"confirmbulkdenial",component:"tool_dataprivacy"}];break;case DataPrivacyEvents.complete:keys=[{key:"markcomplete",component:"tool_dataprivacy"},{key:"confirmcompletion",component:"tool_dataprivacy"}]}var modalTitle="";Str.get_strings(keys).then((function(langStrings){modalTitle=langStrings[0];var confirmMessage=langStrings[1];return ModalFactory.create({title:modalTitle,body:confirmMessage,type:ModalFactory.types.SAVE_CANCEL})})).then((function(modal){modal.setSaveButtonText(modalTitle),modal.getRoot().on(ModalEvents.save,(function(){handleSave(wsdata.wsfunction,wsdata.wsparams)})),modal.getRoot().on(ModalEvents.hidden,(function(){modal.destroy()})),modal.show()})).catch(Notification.exception)}function handleSave(wsfunction,params){var request={methodname:wsfunction,args:params};Ajax.call([request])[0].done((function(data){data.result?window.location.reload():Notification.addNotification({message:data.warnings[0].message,type:"error"})})).fail(Notification.exception)}return RequestActions.prototype.registerEvents=function(){$(ACTIONS_VIEW_REQUEST).click((function(e){e.preventDefault();var requestId=$(this).data("requestid"),request={methodname:"tool_dataprivacy_get_data_request",args:{requestid:requestId}},promises=Ajax.call([request]);$.when(promises[0]).then((function(data){return data.result?data.result:(Notification.addNotification({message:data.warnings[0].message,type:"error"}),!1)})).then((function(data){var body=Templates.render("tool_dataprivacy/request_details",data),templateContext={approvedeny:data.approvedeny,canmarkcomplete:data.canmarkcomplete};return ModalFactory.create({title:data.typename,body:body,type:ModalDataRequest.TYPE,large:!0,templateContext:templateContext})})).then((function(modal){modal.getRoot().on(DataPrivacyEvents.approve,(function(){showConfirmation(DataPrivacyEvents.approve,approveEventWsData(requestId))})),modal.getRoot().on(DataPrivacyEvents.deny,(function(){showConfirmation(DataPrivacyEvents.deny,denyEventWsData(requestId))})),modal.getRoot().on(DataPrivacyEvents.complete,(function(){handleSave("tool_dataprivacy_mark_complete",{requestid:requestId})})),modal.getRoot().on(ModalEvents.hidden,(function(){modal.destroy()})),modal.show()})).catch(Notification.exception)})),$(ACTIONS_APPROVE_REQUEST).click((function(e){e.preventDefault();var requestId=$(this).data("requestid");showConfirmation(DataPrivacyEvents.approve,approveEventWsData(requestId))})),$(ACTIONS_DENY_REQUEST).click((function(e){e.preventDefault();var requestId=$(this).data("requestid");showConfirmation(DataPrivacyEvents.deny,denyEventWsData(requestId))})),$(ACTIONS_MARK_COMPLETE).click((function(e){e.preventDefault();var requestId=$(this).data("requestid");showConfirmation(DataPrivacyEvents.complete,function(requestId){return{wsfunction:"tool_dataprivacy_mark_complete",wsparams:{requestid:requestId}}}(requestId))})),$(ACTIONS_CONFIRM_BULK_ACTION).click((function(){var requestIds=[],actionEvent="",wsdata={},bulkActionKeys=[{key:"selectbulkaction",component:"tool_dataprivacy"},{key:"selectdatarequests",component:"tool_dataprivacy"},{key:"ok"}],bulkaction=parseInt($("#bulk-action").val());if(bulkaction==BULK_ACTIONS_APPROVE||bulkaction==BULK_ACTIONS_DENY)if($(".selectrequests:checked").each((function(){requestIds.push($(this).val())})),requestIds.length<1)Str.get_strings(bulkActionKeys).done((function(langStrings){Notification.alert("",langStrings[1],langStrings[2])})).fail(Notification.exception);else{switch(bulkaction){case BULK_ACTIONS_APPROVE:actionEvent=DataPrivacyEvents.bulkApprove,wsdata=function(requestIds){return{wsfunction:"tool_dataprivacy_bulk_approve_data_requests",wsparams:{requestids:requestIds}}}(requestIds);break;case BULK_ACTIONS_DENY:actionEvent=DataPrivacyEvents.bulkDeny,wsdata=function(requestIds){return{wsfunction:"tool_dataprivacy_bulk_deny_data_requests",wsparams:{requestids:requestIds}}}(requestIds)}showConfirmation(actionEvent,wsdata)}else Str.get_strings(bulkActionKeys).done((function(langStrings){Notification.alert("",langStrings[0],langStrings[2])})).fail(Notification.exception)})),$(ACTIONS_SELECT_ALL).change((function(e){e.preventDefault();var selectAll=$(this).is(":checked");$(SELECTORS_SELECT_REQUEST).prop("checked",selectAll)}))},RequestActions}));
+
+//# sourceMappingURL=requestactions.min.js.map
\ No newline at end of file
diff --git a/admin/tool/dataprivacy/amd/build/requestactions.min.js.map b/admin/tool/dataprivacy/amd/build/requestactions.min.js.map
index f88c1fdcd2c..4d822b3e809 100644
--- a/admin/tool/dataprivacy/amd/build/requestactions.min.js.map
+++ b/admin/tool/dataprivacy/amd/build/requestactions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/requestactions.js"],"names":["define","$","Ajax","Notification","Str","ModalFactory","ModalEvents","Templates","ModalDataRequest","DataPrivacyEvents","ACTIONS","APPROVE_REQUEST","DENY_REQUEST","VIEW_REQUEST","MARK_COMPLETE","CHANGE_BULK_ACTION","CONFIRM_BULK_ACTION","SELECT_ALL","BULK_ACTIONS","APPROVE","DENY","SELECTORS","SELECT_REQUEST","RequestActions","registerEvents","prototype","click","e","preventDefault","requestId","data","promises","call","methodname","args","when","then","result","addNotification","message","warnings","type","body","render","templateContext","approvedeny","canmarkcomplete","create","title","typename","TYPE","large","modal","getRoot","on","approve","showConfirmation","approveEventWsData","deny","denyEventWsData","complete","handleSave","hidden","destroy","show","catch","exception","completeEventWsData","requestIds","actionEvent","wsdata","bulkActionKeys","key","component","bulkaction","parseInt","val","get_strings","done","langStrings","alert","fail","each","push","length","bulkApprove","bulkApproveEventWsData","bulkDeny","bulkDenyEventWsData","change","selectAll","is","prop","action","keys","modalTitle","confirmMessage","types","SAVE_CANCEL","setSaveButtonText","save","wsfunction","wsparams","params","window","location","reload"],"mappings":"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","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 .\n\n/**\n * Request actions.\n *\n * @module tool_dataprivacy/requestactions\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/templates',\n 'tool_dataprivacy/data_request_modal',\n 'tool_dataprivacy/events'],\nfunction($, Ajax, Notification, Str, ModalFactory, ModalEvents, Templates, ModalDataRequest, DataPrivacyEvents) {\n\n /**\n * List of action selectors.\n *\n * @type {{APPROVE_REQUEST: string}}\n * @type {{DENY_REQUEST: string}}\n * @type {{VIEW_REQUEST: string}}\n * @type {{MARK_COMPLETE: string}}\n * @type {{CHANGE_BULK_ACTION: string}}\n * @type {{CONFIRM_BULK_ACTION: string}}\n * @type {{SELECT_ALL: string}}\n */\n var ACTIONS = {\n APPROVE_REQUEST: '[data-action=\"approve\"]',\n DENY_REQUEST: '[data-action=\"deny\"]',\n VIEW_REQUEST: '[data-action=\"view\"]',\n MARK_COMPLETE: '[data-action=\"complete\"]',\n CHANGE_BULK_ACTION: '[id=\"bulk-action\"]',\n CONFIRM_BULK_ACTION: '[id=\"confirm-bulk-action\"]',\n SELECT_ALL: '[data-action=\"selectall\"]'\n };\n\n /**\n * List of available bulk actions.\n *\n * @type {{APPROVE: number}}\n * @type {{DENY: number}}\n */\n var BULK_ACTIONS = {\n APPROVE: 1,\n DENY: 2\n };\n\n /**\n * List of selectors.\n *\n * @type {{SELECT_REQUEST: string}}\n */\n var SELECTORS = {\n SELECT_REQUEST: '.selectrequests'\n };\n\n /**\n * RequestActions class.\n */\n var RequestActions = function() {\n this.registerEvents();\n };\n\n /**\n * Register event listeners.\n */\n RequestActions.prototype.registerEvents = function() {\n $(ACTIONS.VIEW_REQUEST).click(function(e) {\n e.preventDefault();\n\n var requestId = $(this).data('requestid');\n\n // Cancel the request.\n var params = {\n 'requestid': requestId\n };\n\n var request = {\n methodname: 'tool_dataprivacy_get_data_request',\n args: params\n };\n\n var promises = Ajax.call([request]);\n $.when(promises[0]).then(function(data) {\n if (data.result) {\n return data.result;\n }\n // Fail.\n Notification.addNotification({\n message: data.warnings[0].message,\n type: 'error'\n });\n return false;\n\n }).then(function(data) {\n var body = Templates.render('tool_dataprivacy/request_details', data);\n var templateContext = {\n approvedeny: data.approvedeny,\n canmarkcomplete: data.canmarkcomplete\n };\n return ModalFactory.create({\n title: data.typename,\n body: body,\n type: ModalDataRequest.TYPE,\n large: true,\n templateContext: templateContext\n });\n\n }).then(function(modal) {\n // Handle approve event.\n modal.getRoot().on(DataPrivacyEvents.approve, function() {\n showConfirmation(DataPrivacyEvents.approve, approveEventWsData(requestId));\n });\n\n // Handle deny event.\n modal.getRoot().on(DataPrivacyEvents.deny, function() {\n showConfirmation(DataPrivacyEvents.deny, denyEventWsData(requestId));\n });\n\n // Handle send event.\n modal.getRoot().on(DataPrivacyEvents.complete, function() {\n var params = {\n 'requestid': requestId\n };\n handleSave('tool_dataprivacy_mark_complete', params);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n // Show the modal!\n modal.show();\n\n return;\n\n }).catch(Notification.exception);\n });\n\n $(ACTIONS.APPROVE_REQUEST).click(function(e) {\n e.preventDefault();\n\n var requestId = $(this).data('requestid');\n showConfirmation(DataPrivacyEvents.approve, approveEventWsData(requestId));\n });\n\n $(ACTIONS.DENY_REQUEST).click(function(e) {\n e.preventDefault();\n\n var requestId = $(this).data('requestid');\n showConfirmation(DataPrivacyEvents.deny, denyEventWsData(requestId));\n });\n\n $(ACTIONS.MARK_COMPLETE).click(function(e) {\n e.preventDefault();\n\n var requestId = $(this).data('requestid');\n showConfirmation(DataPrivacyEvents.complete, completeEventWsData(requestId));\n });\n\n $(ACTIONS.CONFIRM_BULK_ACTION).click(function() {\n var requestIds = [];\n var actionEvent = '';\n var wsdata = {};\n var bulkActionKeys = [\n {\n key: 'selectbulkaction',\n component: 'tool_dataprivacy'\n },\n {\n key: 'selectdatarequests',\n component: 'tool_dataprivacy'\n },\n {\n key: 'ok'\n }\n ];\n\n var bulkaction = parseInt($('#bulk-action').val());\n\n if (bulkaction != BULK_ACTIONS.APPROVE && bulkaction != BULK_ACTIONS.DENY) {\n Str.get_strings(bulkActionKeys).done(function(langStrings) {\n Notification.alert('', langStrings[0], langStrings[2]);\n }).fail(Notification.exception);\n\n return;\n }\n\n $(\".selectrequests:checked\").each(function() {\n requestIds.push($(this).val());\n });\n\n if (requestIds.length < 1) {\n Str.get_strings(bulkActionKeys).done(function(langStrings) {\n Notification.alert('', langStrings[1], langStrings[2]);\n }).fail(Notification.exception);\n\n return;\n }\n\n switch (bulkaction) {\n case BULK_ACTIONS.APPROVE:\n actionEvent = DataPrivacyEvents.bulkApprove;\n wsdata = bulkApproveEventWsData(requestIds);\n break;\n case BULK_ACTIONS.DENY:\n actionEvent = DataPrivacyEvents.bulkDeny;\n wsdata = bulkDenyEventWsData(requestIds);\n }\n\n showConfirmation(actionEvent, wsdata);\n });\n\n $(ACTIONS.SELECT_ALL).change(function(e) {\n e.preventDefault();\n\n var selectAll = $(this).is(':checked');\n $(SELECTORS.SELECT_REQUEST).prop('checked', selectAll);\n });\n };\n\n /**\n * Return the webservice data for the approve request action.\n *\n * @param {Number} requestId The ID of the request.\n * @return {Object}\n */\n function approveEventWsData(requestId) {\n return {\n 'wsfunction': 'tool_dataprivacy_approve_data_request',\n 'wsparams': {'requestid': requestId}\n };\n }\n\n /**\n * Return the webservice data for the bulk approve request action.\n *\n * @param {Array} requestIds The array of request ID's.\n * @return {Object}\n */\n function bulkApproveEventWsData(requestIds) {\n return {\n 'wsfunction': 'tool_dataprivacy_bulk_approve_data_requests',\n 'wsparams': {'requestids': requestIds}\n };\n }\n\n /**\n * Return the webservice data for the deny request action.\n *\n * @param {Number} requestId The ID of the request.\n * @return {Object}\n */\n function denyEventWsData(requestId) {\n return {\n 'wsfunction': 'tool_dataprivacy_deny_data_request',\n 'wsparams': {'requestid': requestId}\n };\n }\n\n /**\n * Return the webservice data for the bulk deny request action.\n *\n * @param {Array} requestIds The array of request ID's.\n * @return {Object}\n */\n function bulkDenyEventWsData(requestIds) {\n return {\n 'wsfunction': 'tool_dataprivacy_bulk_deny_data_requests',\n 'wsparams': {'requestids': requestIds}\n };\n }\n\n /**\n * Return the webservice data for the complete request action.\n *\n * @param {Number} requestId The ID of the request.\n * @return {Object}\n */\n function completeEventWsData(requestId) {\n return {\n 'wsfunction': 'tool_dataprivacy_mark_complete',\n 'wsparams': {'requestid': requestId}\n };\n }\n\n /**\n * Show the confirmation dialogue.\n *\n * @param {String} action The action name.\n * @param {Object} wsdata Object containing ws data.\n */\n function showConfirmation(action, wsdata) {\n var keys = [];\n\n switch (action) {\n case DataPrivacyEvents.approve:\n keys = [\n {\n key: 'approverequest',\n component: 'tool_dataprivacy'\n },\n {\n key: 'confirmapproval',\n component: 'tool_dataprivacy'\n }\n ];\n break;\n case DataPrivacyEvents.bulkApprove:\n keys = [\n {\n key: 'bulkapproverequests',\n component: 'tool_dataprivacy'\n },\n {\n key: 'confirmbulkapproval',\n component: 'tool_dataprivacy'\n }\n ];\n break;\n case DataPrivacyEvents.deny:\n keys = [\n {\n key: 'denyrequest',\n component: 'tool_dataprivacy'\n },\n {\n key: 'confirmdenial',\n component: 'tool_dataprivacy'\n }\n ];\n break;\n case DataPrivacyEvents.bulkDeny:\n keys = [\n {\n key: 'bulkdenyrequests',\n component: 'tool_dataprivacy'\n },\n {\n key: 'confirmbulkdenial',\n component: 'tool_dataprivacy'\n }\n ];\n break;\n case DataPrivacyEvents.complete:\n keys = [\n {\n key: 'markcomplete',\n component: 'tool_dataprivacy'\n },\n {\n key: 'confirmcompletion',\n component: 'tool_dataprivacy'\n }\n ];\n break;\n }\n\n var modalTitle = '';\n Str.get_strings(keys).then(function(langStrings) {\n modalTitle = langStrings[0];\n var confirmMessage = langStrings[1];\n return ModalFactory.create({\n title: modalTitle,\n body: confirmMessage,\n type: ModalFactory.types.SAVE_CANCEL\n });\n }).then(function(modal) {\n modal.setSaveButtonText(modalTitle);\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function() {\n handleSave(wsdata.wsfunction, wsdata.wsparams);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n modal.show();\n\n return;\n\n }).catch(Notification.exception);\n }\n\n /**\n * Calls a web service function and reloads the page on success and shows a notification.\n * Displays an error notification, otherwise.\n *\n * @param {String} wsfunction The web service function to call.\n * @param {Object} params The parameters for the web service functoon.\n */\n function handleSave(wsfunction, params) {\n // Confirm the request.\n var request = {\n methodname: wsfunction,\n args: params\n };\n\n Ajax.call([request])[0].done(function(data) {\n if (data.result) {\n // On success, reload the page so that the data request table will be updated.\n // TODO: Probably in the future, better to reload the table or the target data request via AJAX.\n window.location.reload();\n } else {\n // Add the notification.\n Notification.addNotification({\n message: data.warnings[0].message,\n type: 'error'\n });\n }\n }).fail(Notification.exception);\n }\n\n return RequestActions;\n});\n"],"file":"requestactions.min.js"}
\ No newline at end of file
+{"version":3,"file":"requestactions.min.js","sources":["../src/requestactions.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 .\n\n/**\n * Request actions.\n *\n * @module tool_dataprivacy/requestactions\n * @copyright 2018 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/templates',\n 'tool_dataprivacy/data_request_modal',\n 'tool_dataprivacy/events'],\nfunction($, Ajax, Notification, Str, ModalFactory, ModalEvents, Templates, ModalDataRequest, DataPrivacyEvents) {\n\n /**\n * List of action selectors.\n *\n * @type {{APPROVE_REQUEST: string}}\n * @type {{DENY_REQUEST: string}}\n * @type {{VIEW_REQUEST: string}}\n * @type {{MARK_COMPLETE: string}}\n * @type {{CHANGE_BULK_ACTION: string}}\n * @type {{CONFIRM_BULK_ACTION: string}}\n * @type {{SELECT_ALL: string}}\n */\n var ACTIONS = {\n APPROVE_REQUEST: '[data-action=\"approve\"]',\n DENY_REQUEST: '[data-action=\"deny\"]',\n VIEW_REQUEST: '[data-action=\"view\"]',\n MARK_COMPLETE: '[data-action=\"complete\"]',\n CHANGE_BULK_ACTION: '[id=\"bulk-action\"]',\n CONFIRM_BULK_ACTION: '[id=\"confirm-bulk-action\"]',\n SELECT_ALL: '[data-action=\"selectall\"]'\n };\n\n /**\n * List of available bulk actions.\n *\n * @type {{APPROVE: number}}\n * @type {{DENY: number}}\n */\n var BULK_ACTIONS = {\n APPROVE: 1,\n DENY: 2\n };\n\n /**\n * List of selectors.\n *\n * @type {{SELECT_REQUEST: string}}\n */\n var SELECTORS = {\n SELECT_REQUEST: '.selectrequests'\n };\n\n /**\n * RequestActions class.\n */\n var RequestActions = function() {\n this.registerEvents();\n };\n\n /**\n * Register event listeners.\n */\n RequestActions.prototype.registerEvents = function() {\n $(ACTIONS.VIEW_REQUEST).click(function(e) {\n e.preventDefault();\n\n var requestId = $(this).data('requestid');\n\n // Cancel the request.\n var params = {\n 'requestid': requestId\n };\n\n var request = {\n methodname: 'tool_dataprivacy_get_data_request',\n args: params\n };\n\n var promises = Ajax.call([request]);\n $.when(promises[0]).then(function(data) {\n if (data.result) {\n return data.result;\n }\n // Fail.\n Notification.addNotification({\n message: data.warnings[0].message,\n type: 'error'\n });\n return false;\n\n }).then(function(data) {\n var body = Templates.render('tool_dataprivacy/request_details', data);\n var templateContext = {\n approvedeny: data.approvedeny,\n canmarkcomplete: data.canmarkcomplete\n };\n return ModalFactory.create({\n title: data.typename,\n body: body,\n type: ModalDataRequest.TYPE,\n large: true,\n templateContext: templateContext\n });\n\n }).then(function(modal) {\n // Handle approve event.\n modal.getRoot().on(DataPrivacyEvents.approve, function() {\n showConfirmation(DataPrivacyEvents.approve, approveEventWsData(requestId));\n });\n\n // Handle deny event.\n modal.getRoot().on(DataPrivacyEvents.deny, function() {\n showConfirmation(DataPrivacyEvents.deny, denyEventWsData(requestId));\n });\n\n // Handle send event.\n modal.getRoot().on(DataPrivacyEvents.complete, function() {\n var params = {\n 'requestid': requestId\n };\n handleSave('tool_dataprivacy_mark_complete', params);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n // Show the modal!\n modal.show();\n\n return;\n\n }).catch(Notification.exception);\n });\n\n $(ACTIONS.APPROVE_REQUEST).click(function(e) {\n e.preventDefault();\n\n var requestId = $(this).data('requestid');\n showConfirmation(DataPrivacyEvents.approve, approveEventWsData(requestId));\n });\n\n $(ACTIONS.DENY_REQUEST).click(function(e) {\n e.preventDefault();\n\n var requestId = $(this).data('requestid');\n showConfirmation(DataPrivacyEvents.deny, denyEventWsData(requestId));\n });\n\n $(ACTIONS.MARK_COMPLETE).click(function(e) {\n e.preventDefault();\n\n var requestId = $(this).data('requestid');\n showConfirmation(DataPrivacyEvents.complete, completeEventWsData(requestId));\n });\n\n $(ACTIONS.CONFIRM_BULK_ACTION).click(function() {\n var requestIds = [];\n var actionEvent = '';\n var wsdata = {};\n var bulkActionKeys = [\n {\n key: 'selectbulkaction',\n component: 'tool_dataprivacy'\n },\n {\n key: 'selectdatarequests',\n component: 'tool_dataprivacy'\n },\n {\n key: 'ok'\n }\n ];\n\n var bulkaction = parseInt($('#bulk-action').val());\n\n if (bulkaction != BULK_ACTIONS.APPROVE && bulkaction != BULK_ACTIONS.DENY) {\n Str.get_strings(bulkActionKeys).done(function(langStrings) {\n Notification.alert('', langStrings[0], langStrings[2]);\n }).fail(Notification.exception);\n\n return;\n }\n\n $(\".selectrequests:checked\").each(function() {\n requestIds.push($(this).val());\n });\n\n if (requestIds.length < 1) {\n Str.get_strings(bulkActionKeys).done(function(langStrings) {\n Notification.alert('', langStrings[1], langStrings[2]);\n }).fail(Notification.exception);\n\n return;\n }\n\n switch (bulkaction) {\n case BULK_ACTIONS.APPROVE:\n actionEvent = DataPrivacyEvents.bulkApprove;\n wsdata = bulkApproveEventWsData(requestIds);\n break;\n case BULK_ACTIONS.DENY:\n actionEvent = DataPrivacyEvents.bulkDeny;\n wsdata = bulkDenyEventWsData(requestIds);\n }\n\n showConfirmation(actionEvent, wsdata);\n });\n\n $(ACTIONS.SELECT_ALL).change(function(e) {\n e.preventDefault();\n\n var selectAll = $(this).is(':checked');\n $(SELECTORS.SELECT_REQUEST).prop('checked', selectAll);\n });\n };\n\n /**\n * Return the webservice data for the approve request action.\n *\n * @param {Number} requestId The ID of the request.\n * @return {Object}\n */\n function approveEventWsData(requestId) {\n return {\n 'wsfunction': 'tool_dataprivacy_approve_data_request',\n 'wsparams': {'requestid': requestId}\n };\n }\n\n /**\n * Return the webservice data for the bulk approve request action.\n *\n * @param {Array} requestIds The array of request ID's.\n * @return {Object}\n */\n function bulkApproveEventWsData(requestIds) {\n return {\n 'wsfunction': 'tool_dataprivacy_bulk_approve_data_requests',\n 'wsparams': {'requestids': requestIds}\n };\n }\n\n /**\n * Return the webservice data for the deny request action.\n *\n * @param {Number} requestId The ID of the request.\n * @return {Object}\n */\n function denyEventWsData(requestId) {\n return {\n 'wsfunction': 'tool_dataprivacy_deny_data_request',\n 'wsparams': {'requestid': requestId}\n };\n }\n\n /**\n * Return the webservice data for the bulk deny request action.\n *\n * @param {Array} requestIds The array of request ID's.\n * @return {Object}\n */\n function bulkDenyEventWsData(requestIds) {\n return {\n 'wsfunction': 'tool_dataprivacy_bulk_deny_data_requests',\n 'wsparams': {'requestids': requestIds}\n };\n }\n\n /**\n * Return the webservice data for the complete request action.\n *\n * @param {Number} requestId The ID of the request.\n * @return {Object}\n */\n function completeEventWsData(requestId) {\n return {\n 'wsfunction': 'tool_dataprivacy_mark_complete',\n 'wsparams': {'requestid': requestId}\n };\n }\n\n /**\n * Show the confirmation dialogue.\n *\n * @param {String} action The action name.\n * @param {Object} wsdata Object containing ws data.\n */\n function showConfirmation(action, wsdata) {\n var keys = [];\n\n switch (action) {\n case DataPrivacyEvents.approve:\n keys = [\n {\n key: 'approverequest',\n component: 'tool_dataprivacy'\n },\n {\n key: 'confirmapproval',\n component: 'tool_dataprivacy'\n }\n ];\n break;\n case DataPrivacyEvents.bulkApprove:\n keys = [\n {\n key: 'bulkapproverequests',\n component: 'tool_dataprivacy'\n },\n {\n key: 'confirmbulkapproval',\n component: 'tool_dataprivacy'\n }\n ];\n break;\n case DataPrivacyEvents.deny:\n keys = [\n {\n key: 'denyrequest',\n component: 'tool_dataprivacy'\n },\n {\n key: 'confirmdenial',\n component: 'tool_dataprivacy'\n }\n ];\n break;\n case DataPrivacyEvents.bulkDeny:\n keys = [\n {\n key: 'bulkdenyrequests',\n component: 'tool_dataprivacy'\n },\n {\n key: 'confirmbulkdenial',\n component: 'tool_dataprivacy'\n }\n ];\n break;\n case DataPrivacyEvents.complete:\n keys = [\n {\n key: 'markcomplete',\n component: 'tool_dataprivacy'\n },\n {\n key: 'confirmcompletion',\n component: 'tool_dataprivacy'\n }\n ];\n break;\n }\n\n var modalTitle = '';\n Str.get_strings(keys).then(function(langStrings) {\n modalTitle = langStrings[0];\n var confirmMessage = langStrings[1];\n return ModalFactory.create({\n title: modalTitle,\n body: confirmMessage,\n type: ModalFactory.types.SAVE_CANCEL\n });\n }).then(function(modal) {\n modal.setSaveButtonText(modalTitle);\n\n // Handle save event.\n modal.getRoot().on(ModalEvents.save, function() {\n handleSave(wsdata.wsfunction, wsdata.wsparams);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n modal.show();\n\n return;\n\n }).catch(Notification.exception);\n }\n\n /**\n * Calls a web service function and reloads the page on success and shows a notification.\n * Displays an error notification, otherwise.\n *\n * @param {String} wsfunction The web service function to call.\n * @param {Object} params The parameters for the web service functoon.\n */\n function handleSave(wsfunction, params) {\n // Confirm the request.\n var request = {\n methodname: wsfunction,\n args: params\n };\n\n Ajax.call([request])[0].done(function(data) {\n if (data.result) {\n // On success, reload the page so that the data request table will be updated.\n // TODO: Probably in the future, better to reload the table or the target data request via AJAX.\n window.location.reload();\n } else {\n // Add the notification.\n Notification.addNotification({\n message: data.warnings[0].message,\n type: 'error'\n });\n }\n }).fail(Notification.exception);\n }\n\n return RequestActions;\n});\n"],"names":["define","$","Ajax","Notification","Str","ModalFactory","ModalEvents","Templates","ModalDataRequest","DataPrivacyEvents","ACTIONS","BULK_ACTIONS","SELECTORS","RequestActions","registerEvents","approveEventWsData","requestId","denyEventWsData","showConfirmation","action","wsdata","keys","approve","key","component","bulkApprove","deny","bulkDeny","complete","modalTitle","get_strings","then","langStrings","confirmMessage","create","title","body","type","types","SAVE_CANCEL","modal","setSaveButtonText","getRoot","on","save","handleSave","wsfunction","wsparams","hidden","destroy","show","catch","exception","params","request","methodname","args","call","done","data","result","window","location","reload","addNotification","message","warnings","fail","prototype","click","e","preventDefault","this","promises","when","render","templateContext","approvedeny","canmarkcomplete","typename","TYPE","large","completeEventWsData","requestIds","actionEvent","bulkActionKeys","bulkaction","parseInt","val","each","push","length","alert","bulkApproveEventWsData","bulkDenyEventWsData","change","selectAll","is","prop"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/langimport/amd/build/search.min.js b/admin/tool/langimport/amd/build/search.min.js
index 9f2b1aacce2..d3313c3c3bd 100644
--- a/admin/tool/langimport/amd/build/search.min.js
+++ b/admin/tool/langimport/amd/build/search.min.js
@@ -1,2 +1,10 @@
-define ("tool_langimport/search",["exports","core/pending","core/utils"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);function d(a,b){return j(a)||h(a,b)||f(a,b)||e()}function e(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function f(a,b){if(!a)return;if("string"==typeof a)return g(a,b);var c=Object.prototype.toString.call(a).slice(8,-1);if("Object"===c&&a.constructor)c=a.constructor.name;if("Map"===c||"Set"===c)return Array.from(c);if("Arguments"===c||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(c))return g(a,b)}function g(a,b){if(null==b||b>a.length)b=a.length;for(var c=0,d=Array(b);c
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_pending=(obj=_pending)&&obj.__esModule?obj:{default:obj};const SELECTORS_AVAILABLE_LANG_SELECT="select",SELECTORS_AVAILABLE_LANG_SEARCH='[data-action="search"]';var _default={init:form=>{const availableLangsElement=form.querySelector(SELECTORS_AVAILABLE_LANG_SELECT),availableLangsFilter=event=>{const pendingPromise=new _pending.default("tool_langimport/search:filter");availableLangsElement.querySelectorAll("option").forEach((option=>{option.remove()}));const searchTerm=event.target.value.toLowerCase(),availableLanguages=JSON.parse(availableLangsElement.dataset.availableLanguages),filteredLanguages=Object.keys(availableLanguages).reduce(((matches,langcode)=>(availableLanguages[langcode].toLowerCase().includes(searchTerm)&&(matches[langcode]=availableLanguages[langcode]),matches)),[]);Object.entries(filteredLanguages).forEach((_ref=>{let[langcode,langname]=_ref;const option=document.createElement("option");option.value=langcode,option.innerText=langname,availableLangsElement.append(option)})),pendingPromise.resolve()},availableLanguages={};availableLangsElement.querySelectorAll("option").forEach((option=>{availableLanguages[option.value]=option.text})),availableLangsElement.dataset.availableLanguages=JSON.stringify(availableLanguages);const availableLangsSearch=form.querySelector(SELECTORS_AVAILABLE_LANG_SEARCH);availableLangsSearch.addEventListener("keydown",(event=>{"Enter"===event.key&&event.preventDefault()})),availableLangsSearch.addEventListener("keyup",(event=>{const pendingPromise=new _pending.default("tool_langimport/search:keyup");(0,_utils.debounce)(availableLangsFilter,250)(event),setTimeout((()=>{pendingPromise.resolve()}),250)}))}};return _exports.default=_default,_exports.default}));
+
+//# sourceMappingURL=search.min.js.map
\ No newline at end of file
diff --git a/admin/tool/langimport/amd/build/search.min.js.map b/admin/tool/langimport/amd/build/search.min.js.map
index 638ecd66d01..04116ba2df7 100644
--- a/admin/tool/langimport/amd/build/search.min.js.map
+++ b/admin/tool/langimport/amd/build/search.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/search.js"],"names":["SELECTORS","AVAILABLE_LANG_SELECT","AVAILABLE_LANG_SEARCH","DEBOUNCE_TIMER","init","form","availableLangsElement","querySelector","availableLangsFilter","event","pendingPromise","Pending","querySelectorAll","forEach","option","remove","searchTerm","target","value","toLowerCase","availableLanguages","JSON","parse","dataset","filteredLanguages","Object","keys","reduce","matches","langcode","includes","entries","langname","document","createElement","innerText","append","resolve","text","stringify","availableLangsSearch","addEventListener","key","preventDefault","setTimeout"],"mappings":"wKAuBA,uD,+9BAGMA,CAAAA,CAAS,CAAG,CACdC,qBAAqB,CAAE,QADT,CAEdC,qBAAqB,CAAE,0BAFT,C,CAKZC,CAAc,CAAG,G,WAiER,CACXC,IAAI,CA3DK,QAAPA,CAAAA,IAAO,CAACC,CAAD,CAAU,IACbC,CAAAA,CAAqB,CAAGD,CAAI,CAACE,aAAL,CAAmBP,CAAS,CAACC,qBAA7B,CADX,CAGbO,CAAoB,CAAG,SAACC,CAAD,CAAW,CACpC,GAAMC,CAAAA,CAAc,CAAG,GAAIC,UAAJ,CAAY,+BAAZ,CAAvB,CAGAL,CAAqB,CAACM,gBAAtB,CAAuC,QAAvC,EAAiDC,OAAjD,CAAyD,SAACC,CAAD,CAAY,CACjEA,CAAM,CAACC,MAAP,EACH,CAFD,EAJoC,GAS9BC,CAAAA,CAAU,CAAGP,CAAK,CAACQ,MAAN,CAAaC,KAAb,CAAmBC,WAAnB,EATiB,CAU9BC,CAAkB,CAAGC,IAAI,CAACC,KAAL,CAAWhB,CAAqB,CAACiB,OAAtB,CAA8BH,kBAAzC,CAVS,CAW9BI,CAAiB,CAAGC,MAAM,CAACC,IAAP,CAAYN,CAAZ,EAAgCO,MAAhC,CAAuC,SAACC,CAAD,CAAUC,CAAV,CAAuB,CACpF,GAAIT,CAAkB,CAACS,CAAD,CAAlB,CAA6BV,WAA7B,GAA2CW,QAA3C,CAAoDd,CAApD,CAAJ,CAAqE,CACjEY,CAAO,CAACC,CAAD,CAAP,CAAoBT,CAAkB,CAACS,CAAD,CACzC,CACD,MAAOD,CAAAA,CACV,CALyB,CAKvB,EALuB,CAXU,CAmBpCH,MAAM,CAACM,OAAP,CAAeP,CAAf,EAAkCX,OAAlC,CAA0C,WAA0B,cAAxBgB,CAAwB,MAAdG,CAAc,MAC1DlB,CAAM,CAAGmB,QAAQ,CAACC,aAAT,CAAuB,QAAvB,CADiD,CAEhEpB,CAAM,CAACI,KAAP,CAAeW,CAAf,CACAf,CAAM,CAACqB,SAAP,CAAmBH,CAAnB,CACA1B,CAAqB,CAAC8B,MAAtB,CAA6BtB,CAA7B,CACH,CALD,EAOAJ,CAAc,CAAC2B,OAAf,EACH,CA9BkB,CAiCbjB,CAAkB,CAAG,EAjCR,CAkCnBd,CAAqB,CAACM,gBAAtB,CAAuC,QAAvC,EAAiDC,OAAjD,CAAyD,SAACC,CAAD,CAAY,CACjEM,CAAkB,CAACN,CAAM,CAACI,KAAR,CAAlB,CAAmCJ,CAAM,CAACwB,IAC7C,CAFD,EAGAhC,CAAqB,CAACiB,OAAtB,CAA8BH,kBAA9B,CAAmDC,IAAI,CAACkB,SAAL,CAAenB,CAAf,CAAnD,CAGA,GAAMoB,CAAAA,CAAoB,CAAGnC,CAAI,CAACE,aAAL,CAAmBP,CAAS,CAACE,qBAA7B,CAA7B,CACAsC,CAAoB,CAACC,gBAArB,CAAsC,SAAtC,CAAiD,SAAChC,CAAD,CAAW,CACxD,GAAkB,OAAd,GAAAA,CAAK,CAACiC,GAAV,CAA2B,CACvBjC,CAAK,CAACkC,cAAN,EACH,CACJ,CAJD,EAOAH,CAAoB,CAACC,gBAArB,CAAsC,OAAtC,CAA+C,SAAChC,CAAD,CAAW,CACtD,GAAMC,CAAAA,CAAc,CAAG,GAAIC,UAAJ,CAAY,8BAAZ,CAAvB,CAEA,eAASH,CAAT,CAA+BL,CAA/B,EAA+CM,CAA/C,EACAmC,UAAU,CAAC,UAAM,CACblC,CAAc,CAAC2B,OAAf,EACH,CAFS,CAEPlC,CAFO,CAGb,CAPD,CAQH,CAEc,C","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 .\n\n/**\n * Add search filtering of available language packs\n *\n * @module tool_langimport/search\n * @copyright 2021 Paul Holden \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Pending from 'core/pending';\nimport {debounce} from 'core/utils';\n\nconst SELECTORS = {\n AVAILABLE_LANG_SELECT: 'select',\n AVAILABLE_LANG_SEARCH: '[data-action=\"search\"]',\n};\n\nconst DEBOUNCE_TIMER = 250;\n\n/**\n * Initialize module\n *\n * @param {Element} form\n */\nconst init = (form) => {\n const availableLangsElement = form.querySelector(SELECTORS.AVAILABLE_LANG_SELECT);\n\n const availableLangsFilter = (event) => {\n const pendingPromise = new Pending('tool_langimport/search:filter');\n\n // Remove existing options.\n availableLangsElement.querySelectorAll('option').forEach((option) => {\n option.remove();\n });\n\n // Filter for matching languages.\n const searchTerm = event.target.value.toLowerCase();\n const availableLanguages = JSON.parse(availableLangsElement.dataset.availableLanguages);\n const filteredLanguages = Object.keys(availableLanguages).reduce((matches, langcode) => {\n if (availableLanguages[langcode].toLowerCase().includes(searchTerm)) {\n matches[langcode] = availableLanguages[langcode];\n }\n return matches;\n }, []);\n\n // Re-create filtered options.\n Object.entries(filteredLanguages).forEach(([langcode, langname]) => {\n const option = document.createElement('option');\n option.value = langcode;\n option.innerText = langname;\n availableLangsElement.append(option);\n });\n\n pendingPromise.resolve();\n };\n\n // Cache initial available language options.\n const availableLanguages = {};\n availableLangsElement.querySelectorAll('option').forEach((option) => {\n availableLanguages[option.value] = option.text;\n });\n availableLangsElement.dataset.availableLanguages = JSON.stringify(availableLanguages);\n\n // Register event listeners on the search element.\n const availableLangsSearch = form.querySelector(SELECTORS.AVAILABLE_LANG_SEARCH);\n availableLangsSearch.addEventListener('keydown', (event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n }\n });\n\n // Debounce the event listener to allow the user to finish typing.\n availableLangsSearch.addEventListener('keyup', (event) => {\n const pendingPromise = new Pending('tool_langimport/search:keyup');\n\n debounce(availableLangsFilter, DEBOUNCE_TIMER)(event);\n setTimeout(() => {\n pendingPromise.resolve();\n }, DEBOUNCE_TIMER);\n });\n};\n\nexport default {\n init: init,\n};\n"],"file":"search.min.js"}
\ No newline at end of file
+{"version":3,"file":"search.min.js","sources":["../src/search.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 .\n\n/**\n * Add search filtering of available language packs\n *\n * @module tool_langimport/search\n * @copyright 2021 Paul Holden \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Pending from 'core/pending';\nimport {debounce} from 'core/utils';\n\nconst SELECTORS = {\n AVAILABLE_LANG_SELECT: 'select',\n AVAILABLE_LANG_SEARCH: '[data-action=\"search\"]',\n};\n\nconst DEBOUNCE_TIMER = 250;\n\n/**\n * Initialize module\n *\n * @param {Element} form\n */\nconst init = (form) => {\n const availableLangsElement = form.querySelector(SELECTORS.AVAILABLE_LANG_SELECT);\n\n const availableLangsFilter = (event) => {\n const pendingPromise = new Pending('tool_langimport/search:filter');\n\n // Remove existing options.\n availableLangsElement.querySelectorAll('option').forEach((option) => {\n option.remove();\n });\n\n // Filter for matching languages.\n const searchTerm = event.target.value.toLowerCase();\n const availableLanguages = JSON.parse(availableLangsElement.dataset.availableLanguages);\n const filteredLanguages = Object.keys(availableLanguages).reduce((matches, langcode) => {\n if (availableLanguages[langcode].toLowerCase().includes(searchTerm)) {\n matches[langcode] = availableLanguages[langcode];\n }\n return matches;\n }, []);\n\n // Re-create filtered options.\n Object.entries(filteredLanguages).forEach(([langcode, langname]) => {\n const option = document.createElement('option');\n option.value = langcode;\n option.innerText = langname;\n availableLangsElement.append(option);\n });\n\n pendingPromise.resolve();\n };\n\n // Cache initial available language options.\n const availableLanguages = {};\n availableLangsElement.querySelectorAll('option').forEach((option) => {\n availableLanguages[option.value] = option.text;\n });\n availableLangsElement.dataset.availableLanguages = JSON.stringify(availableLanguages);\n\n // Register event listeners on the search element.\n const availableLangsSearch = form.querySelector(SELECTORS.AVAILABLE_LANG_SEARCH);\n availableLangsSearch.addEventListener('keydown', (event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n }\n });\n\n // Debounce the event listener to allow the user to finish typing.\n availableLangsSearch.addEventListener('keyup', (event) => {\n const pendingPromise = new Pending('tool_langimport/search:keyup');\n\n debounce(availableLangsFilter, DEBOUNCE_TIMER)(event);\n setTimeout(() => {\n pendingPromise.resolve();\n }, DEBOUNCE_TIMER);\n });\n};\n\nexport default {\n init: init,\n};\n"],"names":["SELECTORS","init","form","availableLangsElement","querySelector","availableLangsFilter","event","pendingPromise","Pending","querySelectorAll","forEach","option","remove","searchTerm","target","value","toLowerCase","availableLanguages","JSON","parse","dataset","filteredLanguages","Object","keys","reduce","matches","langcode","includes","entries","_ref","langname","document","createElement","innerText","append","resolve","text","stringify","availableLangsSearch","addEventListener","key","preventDefault","setTimeout"],"mappings":";;;;;;;qJA0BMA,gCACqB,SADrBA,gCAEqB,sCAoEZ,CACXC,KA3DUC,aACJC,sBAAwBD,KAAKE,cAAcJ,iCAE3CK,qBAAwBC,cACpBC,eAAiB,IAAIC,iBAAQ,iCAGnCL,sBAAsBM,iBAAiB,UAAUC,SAASC,SACtDA,OAAOC,kBAILC,WAAaP,MAAMQ,OAAOC,MAAMC,cAChCC,mBAAqBC,KAAKC,MAAMhB,sBAAsBiB,QAAQH,oBAC9DI,kBAAoBC,OAAOC,KAAKN,oBAAoBO,QAAO,CAACC,QAASC,YACnET,mBAAmBS,UAAUV,cAAcW,SAASd,cACpDY,QAAQC,UAAYT,mBAAmBS,WAEpCD,UACR,IAGHH,OAAOM,QAAQP,mBAAmBX,SAAQmB,WAAEH,SAAUI,qBAC5CnB,OAASoB,SAASC,cAAc,UACtCrB,OAAOI,MAAQW,SACff,OAAOsB,UAAYH,SACnB3B,sBAAsB+B,OAAOvB,WAGjCJ,eAAe4B,WAIblB,mBAAqB,GAC3Bd,sBAAsBM,iBAAiB,UAAUC,SAASC,SACtDM,mBAAmBN,OAAOI,OAASJ,OAAOyB,QAE9CjC,sBAAsBiB,QAAQH,mBAAqBC,KAAKmB,UAAUpB,0BAG5DqB,qBAAuBpC,KAAKE,cAAcJ,iCAChDsC,qBAAqBC,iBAAiB,WAAYjC,QAC5B,UAAdA,MAAMkC,KACNlC,MAAMmC,oBAKdH,qBAAqBC,iBAAiB,SAAUjC,cACtCC,eAAiB,IAAIC,iBAAQ,oDAE1BH,qBA1DM,KA0DgCC,OAC/CoC,YAAW,KACPnC,eAAe4B,YA5DJ"}
\ No newline at end of file
diff --git a/admin/tool/licensemanager/amd/build/delete_license.min.js b/admin/tool/licensemanager/amd/build/delete_license.min.js
index 17dd2af256b..d9177e477f4 100644
--- a/admin/tool/licensemanager/amd/build/delete_license.min.js
+++ b/admin/tool/licensemanager/amd/build/delete_license.min.js
@@ -1,2 +1,10 @@
-define ("tool_licensemanager/delete_license",["jquery","core/modal_factory","core/modal_events","core/url","core/str"],function(a,b,c,d,e){var f=a(".delete-license");b.create({type:b.types.SAVE_CANCEL,title:e.get_string("deletelicense","tool_licensemanager"),body:e.get_string("deletelicenseconfirmmessage","tool_licensemanager"),preShowCallback:function preShowCallback(b,c){b=a(b);var e={action:"delete",license:b.data("license")};c.deleteURL=d.relativeUrl("/admin/tool/licensemanager/index.php",e,!0)},large:!0},f).done(function(a){a.getRoot().on(c.save,function(b){b.preventDefault();window.location.href=a.deleteURL})})});
-//# sourceMappingURL=delete_license.min.js.map
+/**
+ * Modal for confirming deletion of a custom license.
+ *
+ * @module tool_licensemanager/delete_license
+ * @copyright 2019 Tom Dickman
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_licensemanager/delete_license",["jquery","core/modal_factory","core/modal_events","core/url","core/str"],(function($,ModalFactory,ModalEvents,Url,String){var trigger=$(".delete-license");ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL,title:String.get_string("deletelicense","tool_licensemanager"),body:String.get_string("deletelicenseconfirmmessage","tool_licensemanager"),preShowCallback:function(triggerElement,modal){let params={action:"delete",license:(triggerElement=$(triggerElement)).data("license")};modal.deleteURL=Url.relativeUrl("/admin/tool/licensemanager/index.php",params,!0)},large:!0},trigger).done((function(modal){modal.getRoot().on(ModalEvents.save,(function(e){e.preventDefault(),window.location.href=modal.deleteURL}))}))}));
+
+//# sourceMappingURL=delete_license.min.js.map
\ No newline at end of file
diff --git a/admin/tool/licensemanager/amd/build/delete_license.min.js.map b/admin/tool/licensemanager/amd/build/delete_license.min.js.map
index ca10f407e80..71785b2bf5c 100644
--- a/admin/tool/licensemanager/amd/build/delete_license.min.js.map
+++ b/admin/tool/licensemanager/amd/build/delete_license.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/delete_license.js"],"names":["define","$","ModalFactory","ModalEvents","Url","String","trigger","create","type","types","SAVE_CANCEL","title","get_string","body","preShowCallback","triggerElement","modal","params","data","deleteURL","relativeUrl","large","done","getRoot","on","save","e","preventDefault","window","location","href"],"mappings":"AAsBAA,OAAM,sCAAC,CAAC,QAAD,CAAW,oBAAX,CAAiC,mBAAjC,CAAsD,UAAtD,CAAkE,UAAlE,CAAD,CACF,SAASC,CAAT,CAAYC,CAAZ,CAA0BC,CAA1B,CAAuCC,CAAvC,CAA4CC,CAA5C,CAAoD,CAEhD,GAAIC,CAAAA,CAAO,CAAGL,CAAC,CAAC,iBAAD,CAAf,CACAC,CAAY,CAACK,MAAb,CAAoB,CAChBC,IAAI,CAAEN,CAAY,CAACO,KAAb,CAAmBC,WADT,CAEhBC,KAAK,CAAEN,CAAM,CAACO,UAAP,CAAkB,eAAlB,CAAmC,qBAAnC,CAFS,CAGhBC,IAAI,CAAER,CAAM,CAACO,UAAP,CAAkB,6BAAlB,CAAiD,qBAAjD,CAHU,CAIhBE,eAAe,CAAE,yBAASC,CAAT,CAAyBC,CAAzB,CAAgC,CAC7CD,CAAc,CAAGd,CAAC,CAACc,CAAD,CAAlB,CACA,GAAIE,CAAAA,CAAM,CAAG,CACT,OAAU,QADD,CAET,QAAWF,CAAc,CAACG,IAAf,CAAoB,SAApB,CAFF,CAAb,CAIAF,CAAK,CAACG,SAAN,CAAkBf,CAAG,CAACgB,WAAJ,CAAgB,sCAAhB,CAAwDH,CAAxD,IACrB,CAXe,CAYhBI,KAAK,GAZW,CAApB,CAaGf,CAbH,EAcKgB,IAdL,CAcU,SAASN,CAAT,CAAgB,CAClBA,CAAK,CAACO,OAAN,GAAgBC,EAAhB,CAAmBrB,CAAW,CAACsB,IAA/B,CAAqC,SAASC,CAAT,CAAY,CAE7CA,CAAC,CAACC,cAAF,GAEAC,MAAM,CAACC,QAAP,CAAgBC,IAAhB,CAAuBd,CAAK,CAACG,SAChC,CALD,CAMH,CArBL,CAsBH,CA1BC,CAAN","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 .\n\n/**\n * Modal for confirming deletion of a custom license.\n *\n * @module tool_licensemanager/delete_license\n * @copyright 2019 Tom Dickman \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/modal_factory', 'core/modal_events', 'core/url', 'core/str'],\n function($, ModalFactory, ModalEvents, Url, String) {\n\n var trigger = $('.delete-license');\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: String.get_string('deletelicense', 'tool_licensemanager'),\n body: String.get_string('deletelicenseconfirmmessage', 'tool_licensemanager'),\n preShowCallback: function(triggerElement, modal) {\n triggerElement = $(triggerElement);\n let params = {\n 'action': 'delete',\n 'license': triggerElement.data('license')\n };\n modal.deleteURL = Url.relativeUrl('/admin/tool/licensemanager/index.php', params, true);\n },\n large: true,\n }, trigger)\n .done(function(modal) {\n modal.getRoot().on(ModalEvents.save, function(e) {\n // Stop the default save button behaviour which is to close the modal.\n e.preventDefault();\n // Redirect to delete url.\n window.location.href = modal.deleteURL;\n });\n });\n });\n"],"file":"delete_license.min.js"}
\ No newline at end of file
+{"version":3,"file":"delete_license.min.js","sources":["../src/delete_license.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 .\n\n/**\n * Modal for confirming deletion of a custom license.\n *\n * @module tool_licensemanager/delete_license\n * @copyright 2019 Tom Dickman \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/modal_factory', 'core/modal_events', 'core/url', 'core/str'],\n function($, ModalFactory, ModalEvents, Url, String) {\n\n var trigger = $('.delete-license');\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: String.get_string('deletelicense', 'tool_licensemanager'),\n body: String.get_string('deletelicenseconfirmmessage', 'tool_licensemanager'),\n preShowCallback: function(triggerElement, modal) {\n triggerElement = $(triggerElement);\n let params = {\n 'action': 'delete',\n 'license': triggerElement.data('license')\n };\n modal.deleteURL = Url.relativeUrl('/admin/tool/licensemanager/index.php', params, true);\n },\n large: true,\n }, trigger)\n .done(function(modal) {\n modal.getRoot().on(ModalEvents.save, function(e) {\n // Stop the default save button behaviour which is to close the modal.\n e.preventDefault();\n // Redirect to delete url.\n window.location.href = modal.deleteURL;\n });\n });\n });\n"],"names":["define","$","ModalFactory","ModalEvents","Url","String","trigger","create","type","types","SAVE_CANCEL","title","get_string","body","preShowCallback","triggerElement","modal","params","data","deleteURL","relativeUrl","large","done","getRoot","on","save","e","preventDefault","window","location","href"],"mappings":";;;;;;;AAsBAA,4CAAO,CAAC,SAAU,qBAAsB,oBAAqB,WAAY,aACrE,SAASC,EAAGC,aAAcC,YAAaC,IAAKC,YAEpCC,QAAUL,EAAE,mBAChBC,aAAaK,OAAO,CAChBC,KAAMN,aAAaO,MAAMC,YACzBC,MAAON,OAAOO,WAAW,gBAAiB,uBAC1CC,KAAMR,OAAOO,WAAW,8BAA+B,uBACvDE,gBAAiB,SAASC,eAAgBC,WAElCC,OAAS,QACC,kBAFdF,eAAiBd,EAAEc,iBAGWG,KAAK,YAEnCF,MAAMG,UAAYf,IAAIgB,YAAY,uCAAwCH,QAAQ,IAEtFI,OAAO,GACRf,SACEgB,MAAK,SAASN,OACXA,MAAMO,UAAUC,GAAGrB,YAAYsB,MAAM,SAASC,GAE1CA,EAAEC,iBAEFC,OAAOC,SAASC,KAAOd,MAAMG"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/actionselector.min.js b/admin/tool/lp/amd/build/actionselector.min.js
index b082d803853..86d4019f3a8 100644
--- a/admin/tool/lp/amd/build/actionselector.min.js
+++ b/admin/tool/lp/amd/build/actionselector.min.js
@@ -1,2 +1,14 @@
-define ("tool_lp/actionselector",["jquery","core/notification","core/ajax","core/templates","tool_lp/dialogue","tool_lp/event_base"],function(a,b,c,d,e,f){var g=function(a,b,c,d,e){var g=this;f.prototype.constructor.apply(this,[]);g._title=a;g._message=b;g._actions=c;g._confirm=d;g._cancel=e;g._selectedValue=null;g._reset()};g.prototype=Object.create(f.prototype);g.prototype._selectedValue=null;g.prototype._popup=null;g.prototype._title=null;g.prototype._message=null;g.prototype._actions=null;g.prototype._confirm=null;g.prototype._cancel=null;g.prototype._afterRender=function(){var b=this;b._find("[data-action=\"action-selector-confirm\"]").attr("disabled","disabled");b._find("[data-region=\"action-selector-radio-buttons\"]").change(function(){b._selectedValue=a("input[type='radio']:checked").val();b._find("[data-action=\"action-selector-confirm\"]").removeAttr("disabled");b._refresh.bind(b)});b._find("[data-action=\"action-selector-cancel\"]").click(function(a){a.preventDefault();b.close()});b._find("[data-action=\"action-selector-confirm\"]").click(function(a){a.preventDefault();if(!b._selectedValue.length){return}b._trigger("save",{action:b._selectedValue});b.close()})};g.prototype.close=function(){var a=this;a._popup.close();a._reset()};g.prototype.display=function(){var a=this;return a._render().then(function(b){a._popup=new e(a._title,b,a._afterRender.bind(a))}).fail(b.exception)};g.prototype._find=function(b){return a(this._popup.getContent()).find(b)};g.prototype._refresh=function(){var a=this;return a._render().then(function(b){a._find("[data-region=\"action-selector\"]").replaceWith(b);a._afterRender()})};g.prototype._render=function(){var a=this,b=[];for(var c in a._actions){b.push(a._actions[c])}var e={message:a._message,choices:b,confirm:a._confirm,cancel:a._cancel};return d.render("tool_lp/action_selector",e)};g.prototype._reset=function(){this._popup=null;this._selectedValue=""};return g});
-//# sourceMappingURL=actionselector.min.js.map
+/**
+ * Action selector.
+ *
+ * To handle 'save' events use: actionselector.on('save')
+ * This will receive the information to display in popup.
+ * The actions have the format [{'text': sometext, 'value' : somevalue}].
+ *
+ * @module tool_lp/actionselector
+ * @copyright 2016 Serge Gauthier -
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/actionselector",["jquery","core/notification","core/ajax","core/templates","tool_lp/dialogue","tool_lp/event_base"],(function($,Notification,Ajax,Templates,Dialogue,EventBase){var ActionSelector=function(title,message,actions,confirm,cancel){EventBase.prototype.constructor.apply(this,[]),this._title=title,this._message=message,this._actions=actions,this._confirm=confirm,this._cancel=cancel,this._selectedValue=null,this._reset()};return(ActionSelector.prototype=Object.create(EventBase.prototype))._selectedValue=null,ActionSelector.prototype._popup=null,ActionSelector.prototype._title=null,ActionSelector.prototype._message=null,ActionSelector.prototype._actions=null,ActionSelector.prototype._confirm=null,ActionSelector.prototype._cancel=null,ActionSelector.prototype._afterRender=function(){var self=this;self._find('[data-action="action-selector-confirm"]').attr("disabled","disabled"),self._find('[data-region="action-selector-radio-buttons"]').change((function(){self._selectedValue=$("input[type='radio']:checked").val(),self._find('[data-action="action-selector-confirm"]').removeAttr("disabled"),self._refresh.bind(self)})),self._find('[data-action="action-selector-cancel"]').click((function(e){e.preventDefault(),self.close()})),self._find('[data-action="action-selector-confirm"]').click((function(e){e.preventDefault(),self._selectedValue.length&&(self._trigger("save",{action:self._selectedValue}),self.close())}))},ActionSelector.prototype.close=function(){this._popup.close(),this._reset()},ActionSelector.prototype.display=function(){var self=this;return self._render().then((function(html){self._popup=new Dialogue(self._title,html,self._afterRender.bind(self))})).fail(Notification.exception)},ActionSelector.prototype._find=function(selector){return $(this._popup.getContent()).find(selector)},ActionSelector.prototype._refresh=function(){var self=this;return self._render().then((function(html){self._find('[data-region="action-selector"]').replaceWith(html),self._afterRender()}))},ActionSelector.prototype._render=function(){var choices=[];for(var i in this._actions)choices.push(this._actions[i]);var content={message:this._message,choices:choices,confirm:this._confirm,cancel:this._cancel};return Templates.render("tool_lp/action_selector",content)},ActionSelector.prototype._reset=function(){this._popup=null,this._selectedValue=""},ActionSelector}));
+
+//# sourceMappingURL=actionselector.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/actionselector.min.js.map b/admin/tool/lp/amd/build/actionselector.min.js.map
index f114d9ad751..1061e04a7e2 100644
--- a/admin/tool/lp/amd/build/actionselector.min.js.map
+++ b/admin/tool/lp/amd/build/actionselector.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/actionselector.js"],"names":["define","$","Notification","Ajax","Templates","Dialogue","EventBase","ActionSelector","title","message","actions","confirm","cancel","self","prototype","constructor","apply","_title","_message","_actions","_confirm","_cancel","_selectedValue","_reset","Object","create","_popup","_afterRender","_find","attr","change","val","removeAttr","_refresh","bind","click","e","preventDefault","close","length","_trigger","action","display","_render","then","html","fail","exception","selector","getContent","find","replaceWith","choices","i","push","content","render"],"mappings":"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","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 .\n\n/**\n * Action selector.\n *\n * To handle 'save' events use: actionselector.on('save')\n * This will receive the information to display in popup.\n * The actions have the format [{'text': sometext, 'value' : somevalue}].\n *\n * @module tool_lp/actionselector\n * @copyright 2016 Serge Gauthier - \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/templates',\n 'tool_lp/dialogue',\n 'tool_lp/event_base'],\n function($, Notification, Ajax, Templates, Dialogue, EventBase) {\n\n /**\n * Action selector class.\n *\n * @class tool_lp/actionselector\n * @param {String} title The title of popup.\n * @param {String} message The message to display.\n * @param {object} actions The actions that can be selected.\n * @param {String} confirm Text for confirm button.\n * @param {String} cancel Text for cancel button.\n */\n var ActionSelector = function(title, message, actions, confirm, cancel) {\n var self = this;\n\n EventBase.prototype.constructor.apply(this, []);\n self._title = title;\n self._message = message;\n self._actions = actions;\n self._confirm = confirm;\n self._cancel = cancel;\n self._selectedValue = null;\n self._reset();\n };\n\n ActionSelector.prototype = Object.create(EventBase.prototype);\n\n /** @property {String} The value that was selected. */\n ActionSelector.prototype._selectedValue = null;\n /** @property {Dialogue} The reference to the dialogue. */\n ActionSelector.prototype._popup = null;\n /** @property {String} The title of popup. */\n ActionSelector.prototype._title = null;\n /** @property {String} The message in popup. */\n ActionSelector.prototype._message = null;\n /** @property {object} The information for radion buttons. */\n ActionSelector.prototype._actions = null;\n /** @property {String} The text for confirm button. */\n ActionSelector.prototype._confirm = null;\n /** @property {String} The text for cancel button. */\n ActionSelector.prototype._cancel = null;\n\n /**\n * Hook to executed after the view is rendered.\n *\n * @method _afterRender\n */\n ActionSelector.prototype._afterRender = function() {\n var self = this;\n\n // Confirm button is disabled until a choice is done.\n self._find('[data-action=\"action-selector-confirm\"]').attr('disabled', 'disabled');\n\n // Add listener for radio buttons change.\n self._find('[data-region=\"action-selector-radio-buttons\"]').change(function() {\n self._selectedValue = $(\"input[type='radio']:checked\").val();\n self._find('[data-action=\"action-selector-confirm\"]').removeAttr('disabled');\n self._refresh.bind(self);\n });\n\n // Add listener for cancel.\n self._find('[data-action=\"action-selector-cancel\"]').click(function(e) {\n e.preventDefault();\n self.close();\n });\n\n // Add listener for confirm.\n self._find('[data-action=\"action-selector-confirm\"]').click(function(e) {\n e.preventDefault();\n if (!self._selectedValue.length) {\n return;\n }\n self._trigger('save', {action: self._selectedValue});\n self.close();\n });\n };\n\n /**\n * Close the dialogue.\n *\n * @method close\n */\n ActionSelector.prototype.close = function() {\n var self = this;\n self._popup.close();\n self._reset();\n };\n\n /**\n * Opens the action selector.\n *\n * @method display\n * @return {Promise}\n */\n ActionSelector.prototype.display = function() {\n var self = this;\n return self._render().then(function(html) {\n self._popup = new Dialogue(\n self._title,\n html,\n self._afterRender.bind(self)\n );\n return;\n }).fail(Notification.exception);\n };\n\n /**\n * Find a node in the dialogue.\n *\n * @param {String} selector\n * @return {JQuery} The node\n * @method _find\n */\n ActionSelector.prototype._find = function(selector) {\n return $(this._popup.getContent()).find(selector);\n };\n\n /**\n * Refresh the view.\n *\n * @method _refresh\n * @return {Promise}\n */\n ActionSelector.prototype._refresh = function() {\n var self = this;\n return self._render().then(function(html) {\n self._find('[data-region=\"action-selector\"]').replaceWith(html);\n self._afterRender();\n return;\n });\n };\n\n /**\n * Render the dialogue.\n *\n * @method _render\n * @return {Promise}\n */\n ActionSelector.prototype._render = function() {\n var self = this;\n var choices = [];\n for (var i in self._actions) {\n choices.push(self._actions[i]);\n }\n var content = {'message': self._message, 'choices': choices,\n 'confirm': self._confirm, 'cancel': self._cancel};\n\n return Templates.render('tool_lp/action_selector', content);\n };\n\n /**\n * Reset the dialogue properties.\n *\n * This does not reset everything, just enough to reset the UI.\n *\n * @method _reset\n */\n ActionSelector.prototype._reset = function() {\n this._popup = null;\n this._selectedValue = '';\n };\n\n return ActionSelector;\n\n});\n"],"file":"actionselector.min.js"}
\ No newline at end of file
+{"version":3,"file":"actionselector.min.js","sources":["../src/actionselector.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 .\n\n/**\n * Action selector.\n *\n * To handle 'save' events use: actionselector.on('save')\n * This will receive the information to display in popup.\n * The actions have the format [{'text': sometext, 'value' : somevalue}].\n *\n * @module tool_lp/actionselector\n * @copyright 2016 Serge Gauthier - \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/templates',\n 'tool_lp/dialogue',\n 'tool_lp/event_base'],\n function($, Notification, Ajax, Templates, Dialogue, EventBase) {\n\n /**\n * Action selector class.\n *\n * @class tool_lp/actionselector\n * @param {String} title The title of popup.\n * @param {String} message The message to display.\n * @param {object} actions The actions that can be selected.\n * @param {String} confirm Text for confirm button.\n * @param {String} cancel Text for cancel button.\n */\n var ActionSelector = function(title, message, actions, confirm, cancel) {\n var self = this;\n\n EventBase.prototype.constructor.apply(this, []);\n self._title = title;\n self._message = message;\n self._actions = actions;\n self._confirm = confirm;\n self._cancel = cancel;\n self._selectedValue = null;\n self._reset();\n };\n\n ActionSelector.prototype = Object.create(EventBase.prototype);\n\n /** @property {String} The value that was selected. */\n ActionSelector.prototype._selectedValue = null;\n /** @property {Dialogue} The reference to the dialogue. */\n ActionSelector.prototype._popup = null;\n /** @property {String} The title of popup. */\n ActionSelector.prototype._title = null;\n /** @property {String} The message in popup. */\n ActionSelector.prototype._message = null;\n /** @property {object} The information for radion buttons. */\n ActionSelector.prototype._actions = null;\n /** @property {String} The text for confirm button. */\n ActionSelector.prototype._confirm = null;\n /** @property {String} The text for cancel button. */\n ActionSelector.prototype._cancel = null;\n\n /**\n * Hook to executed after the view is rendered.\n *\n * @method _afterRender\n */\n ActionSelector.prototype._afterRender = function() {\n var self = this;\n\n // Confirm button is disabled until a choice is done.\n self._find('[data-action=\"action-selector-confirm\"]').attr('disabled', 'disabled');\n\n // Add listener for radio buttons change.\n self._find('[data-region=\"action-selector-radio-buttons\"]').change(function() {\n self._selectedValue = $(\"input[type='radio']:checked\").val();\n self._find('[data-action=\"action-selector-confirm\"]').removeAttr('disabled');\n self._refresh.bind(self);\n });\n\n // Add listener for cancel.\n self._find('[data-action=\"action-selector-cancel\"]').click(function(e) {\n e.preventDefault();\n self.close();\n });\n\n // Add listener for confirm.\n self._find('[data-action=\"action-selector-confirm\"]').click(function(e) {\n e.preventDefault();\n if (!self._selectedValue.length) {\n return;\n }\n self._trigger('save', {action: self._selectedValue});\n self.close();\n });\n };\n\n /**\n * Close the dialogue.\n *\n * @method close\n */\n ActionSelector.prototype.close = function() {\n var self = this;\n self._popup.close();\n self._reset();\n };\n\n /**\n * Opens the action selector.\n *\n * @method display\n * @return {Promise}\n */\n ActionSelector.prototype.display = function() {\n var self = this;\n return self._render().then(function(html) {\n self._popup = new Dialogue(\n self._title,\n html,\n self._afterRender.bind(self)\n );\n return;\n }).fail(Notification.exception);\n };\n\n /**\n * Find a node in the dialogue.\n *\n * @param {String} selector\n * @return {JQuery} The node\n * @method _find\n */\n ActionSelector.prototype._find = function(selector) {\n return $(this._popup.getContent()).find(selector);\n };\n\n /**\n * Refresh the view.\n *\n * @method _refresh\n * @return {Promise}\n */\n ActionSelector.prototype._refresh = function() {\n var self = this;\n return self._render().then(function(html) {\n self._find('[data-region=\"action-selector\"]').replaceWith(html);\n self._afterRender();\n return;\n });\n };\n\n /**\n * Render the dialogue.\n *\n * @method _render\n * @return {Promise}\n */\n ActionSelector.prototype._render = function() {\n var self = this;\n var choices = [];\n for (var i in self._actions) {\n choices.push(self._actions[i]);\n }\n var content = {'message': self._message, 'choices': choices,\n 'confirm': self._confirm, 'cancel': self._cancel};\n\n return Templates.render('tool_lp/action_selector', content);\n };\n\n /**\n * Reset the dialogue properties.\n *\n * This does not reset everything, just enough to reset the UI.\n *\n * @method _reset\n */\n ActionSelector.prototype._reset = function() {\n this._popup = null;\n this._selectedValue = '';\n };\n\n return ActionSelector;\n\n});\n"],"names":["define","$","Notification","Ajax","Templates","Dialogue","EventBase","ActionSelector","title","message","actions","confirm","cancel","prototype","constructor","apply","this","_title","_message","_actions","_confirm","_cancel","_selectedValue","_reset","Object","create","_popup","_afterRender","self","_find","attr","change","val","removeAttr","_refresh","bind","click","e","preventDefault","close","length","_trigger","action","display","_render","then","html","fail","exception","selector","getContent","find","replaceWith","choices","i","push","content","render"],"mappings":";;;;;;;;;;;AA2BAA,gCAAO,CAAC,SACA,oBACA,YACA,iBACA,mBACA,uBACA,SAASC,EAAGC,aAAcC,KAAMC,UAAWC,SAAUC,eAYrDC,eAAiB,SAASC,MAAOC,QAASC,QAASC,QAASC,QAG5DN,UAAUO,UAAUC,YAAYC,MAAMC,KAAM,IAFjCA,KAGNC,OAAST,MAHHQ,KAINE,SAAWT,QAJLO,KAKNG,SAAWT,QALLM,KAMNI,SAAWT,QANLK,KAONK,QAAUT,OAPJI,KAQNM,eAAiB,KARXN,KASNO,iBAGThB,eAAeM,UAAYW,OAAOC,OAAOnB,UAAUO,YAG1BS,eAAiB,KAE1Cf,eAAeM,UAAUa,OAAS,KAElCnB,eAAeM,UAAUI,OAAS,KAElCV,eAAeM,UAAUK,SAAW,KAEpCX,eAAeM,UAAUM,SAAW,KAEpCZ,eAAeM,UAAUO,SAAW,KAEpCb,eAAeM,UAAUQ,QAAU,KAOnCd,eAAeM,UAAUc,aAAe,eAChCC,KAAOZ,KAGXY,KAAKC,MAAM,2CAA2CC,KAAK,WAAY,YAGvEF,KAAKC,MAAM,iDAAiDE,QAAO,WAC/DH,KAAKN,eAAiBrB,EAAE,+BAA+B+B,MACvDJ,KAAKC,MAAM,2CAA2CI,WAAW,YACjEL,KAAKM,SAASC,KAAKP,SAIvBA,KAAKC,MAAM,0CAA0CO,OAAM,SAASC,GAChEA,EAAEC,iBACFV,KAAKW,WAITX,KAAKC,MAAM,2CAA2CO,OAAM,SAASC,GACjEA,EAAEC,iBACGV,KAAKN,eAAekB,SAGzBZ,KAAKa,SAAS,OAAQ,CAACC,OAAQd,KAAKN,iBACpCM,KAAKW,aASbhC,eAAeM,UAAU0B,MAAQ,WAClBvB,KACNU,OAAOa,QADDvB,KAENO,UASThB,eAAeM,UAAU8B,QAAU,eAC3Bf,KAAOZ,YACJY,KAAKgB,UAAUC,MAAK,SAASC,MAChClB,KAAKF,OAAS,IAAIrB,SACduB,KAAKX,OACL6B,KACAlB,KAAKD,aAAaQ,KAAKP,UAG5BmB,KAAK7C,aAAa8C,YAUzBzC,eAAeM,UAAUgB,MAAQ,SAASoB,iBAC/BhD,EAAEe,KAAKU,OAAOwB,cAAcC,KAAKF,WAS5C1C,eAAeM,UAAUqB,SAAW,eAC5BN,KAAOZ,YACJY,KAAKgB,UAAUC,MAAK,SAASC,MAChClB,KAAKC,MAAM,mCAAmCuB,YAAYN,MAC1DlB,KAAKD,mBAWbpB,eAAeM,UAAU+B,QAAU,eAE3BS,QAAU,OACT,IAAIC,KAFEtC,KAEQG,SACfkC,QAAQE,KAHDvC,KAGWG,SAASmC,QAE3BE,QAAU,SALHxC,KAKoBE,iBAAqBmC,gBALzCrC,KAMSI,gBANTJ,KAMkCK,gBAEtCjB,UAAUqD,OAAO,0BAA2BD,UAUvDjD,eAAeM,UAAUU,OAAS,gBACzBG,OAAS,UACTJ,eAAiB,IAGnBf"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencies.min.js b/admin/tool/lp/amd/build/competencies.min.js
index 867ec94c464..a80300bd855 100644
--- a/admin/tool/lp/amd/build/competencies.min.js
+++ b/admin/tool/lp/amd/build/competencies.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/competencies",["jquery","core/notification","core/ajax","core/templates","core/str","tool_lp/competencypicker","tool_lp/dragdrop-reorder","core/pending"],function(a,b,c,d,e,f,g,h){var i=function(b,c,d){this.itemid=b;this.itemtype=c;this.pageContextId=d;this.pickerInstance=null;a("[data-region=\"actions\"] button").prop("disabled",!1);this.registerEvents();this.registerDragDrop()};i.prototype.registerDragDrop=function(){var a=this;e.get_string("movecompetency","tool_lp").done(function(b){g.dragdrop("movecompetency",b,{identifier:"movecompetency",component:"tool_lp"},{identifier:"movecompetencyafter",component:"tool_lp"},"drag-samenode","drag-parentnode","drag-handlecontainer",function(b,c){a.handleDrop(b,c)})}).fail(b.exception)};i.prototype.handleDrop=function(d,e){var f=a(d).data("id"),g=a(e).data("id"),h=this,i=[];if("course"==h.itemtype){i=c.call([{methodname:"core_competency_reorder_course_competency",args:{courseid:h.itemid,competencyidfrom:f,competencyidto:g}}])}else if("template"==h.itemtype){i=c.call([{methodname:"core_competency_reorder_template_competency",args:{templateid:h.itemid,competencyidfrom:f,competencyidto:g}}])}else if("plan"==h.itemtype){i=c.call([{methodname:"core_competency_reorder_plan_competency",args:{planid:h.itemid,competencyidfrom:f,competencyidto:g}}])}else{return}i[0].fail(b.exception)};i.prototype.pickCompetency=function(){var g=this,i,j,k,l;if(!g.pickerInstance){if("template"===g.itemtype||"course"===g.itemtype){l="parents"}g.pickerInstance=new f(g.pageContextId,!1,l);g.pickerInstance.on("save",function(f,e){var l=e.competencyIds,m=new h;if("course"===g.itemtype){i=[];a.each(l,function(a,b){i.push({methodname:"core_competency_add_competency_to_course",args:{courseid:g.itemid,competencyid:b}})});i.push({methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:g.itemid,moduleid:0}});j="tool_lp/course_competencies_page";k="coursecompetenciespage"}else if("template"===g.itemtype){i=[];a.each(l,function(a,b){i.push({methodname:"core_competency_add_competency_to_template",args:{templateid:g.itemid,competencyid:b}})});i.push({methodname:"tool_lp_data_for_template_competencies_page",args:{templateid:g.itemid,pagecontext:{contextid:g.pageContextId}}});j="tool_lp/template_competencies_page";k="templatecompetenciespage"}else if("plan"===g.itemtype){i=[];a.each(l,function(a,b){i.push({methodname:"core_competency_add_competency_to_plan",args:{planid:g.itemid,competencyid:b}})});i.push({methodname:"tool_lp_data_for_plan_page",args:{planid:g.itemid}});j="tool_lp/plan_page";k="plan-page"}c.call(i)[i.length-1].then(function(a){return d.render(j,a)}).then(function(b,c){d.replaceNode(a("[data-region=\""+k+"\"]"),b,c)}).then(m.resolve).catch(b.exception)})}return g.pickerInstance.display()};i.prototype.doDelete=function(e){var f=this,g=[],h="",i="";if("course"==f.itemtype){g=c.call([{methodname:"core_competency_remove_competency_from_course",args:{courseid:f.itemid,competencyid:e}},{methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:f.itemid,moduleid:0}}]);h="tool_lp/course_competencies_page";i="coursecompetenciespage"}else if("template"==f.itemtype){g=c.call([{methodname:"core_competency_remove_competency_from_template",args:{templateid:f.itemid,competencyid:e}},{methodname:"tool_lp_data_for_template_competencies_page",args:{templateid:f.itemid,pagecontext:{contextid:f.pageContextId}}}]);h="tool_lp/template_competencies_page";i="templatecompetenciespage"}else if("plan"==f.itemtype){g=c.call([{methodname:"core_competency_remove_competency_from_plan",args:{planid:f.itemid,competencyid:e}},{methodname:"tool_lp_data_for_plan_page",args:{planid:f.itemid}}]);h="tool_lp/plan_page";i="plan-page"}g[1].done(function(c){d.render(h,c).done(function(b,c){a("[data-region=\""+i+"\"]").replaceWith(b);d.runTemplateJS(c)}).fail(b.exception)}).fail(b.exception)};i.prototype.deleteHandler=function(a){var d=this,f=[],g;if("course"==d.itemtype){g="unlinkcompetencycourse"}else if("template"==d.itemtype){g="unlinkcompetencytemplate"}else if("plan"==d.itemtype){g="unlinkcompetencyplan"}else{return}f=c.call([{methodname:"core_competency_read_competency",args:{id:a}}]);f[0].done(function(c){e.get_strings([{key:"confirm",component:"moodle"},{key:g,component:"tool_lp",param:c.shortname},{key:"confirm",component:"moodle"},{key:"cancel",component:"moodle"}]).done(function(c){b.confirm(c[0],c[1],c[2],c[3],function(){d.doDelete(a)})}).fail(b.exception)}).fail(b.exception)};i.prototype.registerEvents=function(){var f=this;if("course"==f.itemtype){a("[data-region=\"coursecompetenciespage\"]").on("change","select[data-field=\"ruleoutcome\"]",function(g){var e=new h,i=[],j=a(g.target).data("id"),k=a(g.target).val();i=c.call([{methodname:"core_competency_set_course_competency_ruleoutcome",args:{coursecompetencyid:j,ruleoutcome:k}},{methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:f.itemid,moduleid:0}}]);i[1].then(function(a){return d.render("tool_lp/course_competencies_page",a)}).then(function(b,c){return d.replaceNode(a("[data-region=\""+"coursecompetenciespage"+"\"]"),b,c)}).then(e.resolve).catch(b.exception)})}a("[data-region=\"actions\"] button").click(function(a){var b=new h;a.preventDefault();f.pickCompetency().then(b.resolve).catch()});a("[data-action=\"delete-competency-link\"]").click(function(b){b.preventDefault();var c=a(b.target).closest("[data-id]").data("id");f.deleteHandler(c)})};return i});
-//# sourceMappingURL=competencies.min.js.map
+/**
+ * Handle add/remove competency links.
+ *
+ * @module tool_lp/competencies
+ * @copyright 2015 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/competencies",["jquery","core/notification","core/ajax","core/templates","core/str","tool_lp/competencypicker","tool_lp/dragdrop-reorder","core/pending"],(function($,notification,ajax,templates,str,Picker,dragdrop,Pending){var competencies=function(itemid,itemtype,pagectxid){this.itemid=itemid,this.itemtype=itemtype,this.pageContextId=pagectxid,this.pickerInstance=null,$('[data-region="actions"] button').prop("disabled",!1),this.registerEvents(),this.registerDragDrop()};return competencies.prototype.registerDragDrop=function(){var localthis=this;str.get_string("movecompetency","tool_lp").done((function(movestring){dragdrop.dragdrop("movecompetency",movestring,{identifier:"movecompetency",component:"tool_lp"},{identifier:"movecompetencyafter",component:"tool_lp"},"drag-samenode","drag-parentnode","drag-handlecontainer",(function(drag,drop){localthis.handleDrop(drag,drop)}))})).fail(notification.exception)},competencies.prototype.handleDrop=function(drag,drop){var fromid=$(drag).data("id"),toid=$(drop).data("id"),requests=[];if("course"==this.itemtype)requests=ajax.call([{methodname:"core_competency_reorder_course_competency",args:{courseid:this.itemid,competencyidfrom:fromid,competencyidto:toid}}]);else if("template"==this.itemtype)requests=ajax.call([{methodname:"core_competency_reorder_template_competency",args:{templateid:this.itemid,competencyidfrom:fromid,competencyidto:toid}}]);else{if("plan"!=this.itemtype)return;requests=ajax.call([{methodname:"core_competency_reorder_plan_competency",args:{planid:this.itemid,competencyidfrom:fromid,competencyidto:toid}}])}requests[0].fail(notification.exception)},competencies.prototype.pickCompetency=function(){var requests,pagerender,pageregion,pageContextIncludes,self=this;return self.pickerInstance||("template"!==self.itemtype&&"course"!==self.itemtype||(pageContextIncludes="parents"),self.pickerInstance=new Picker(self.pageContextId,!1,pageContextIncludes),self.pickerInstance.on("save",(function(e,data){var compIds=data.competencyIds,pendingPromise=new Pending;"course"===self.itemtype?(requests=[],$.each(compIds,(function(index,compId){requests.push({methodname:"core_competency_add_competency_to_course",args:{courseid:self.itemid,competencyid:compId}})})),requests.push({methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:self.itemid,moduleid:0}}),pagerender="tool_lp/course_competencies_page",pageregion="coursecompetenciespage"):"template"===self.itemtype?(requests=[],$.each(compIds,(function(index,compId){requests.push({methodname:"core_competency_add_competency_to_template",args:{templateid:self.itemid,competencyid:compId}})})),requests.push({methodname:"tool_lp_data_for_template_competencies_page",args:{templateid:self.itemid,pagecontext:{contextid:self.pageContextId}}}),pagerender="tool_lp/template_competencies_page",pageregion="templatecompetenciespage"):"plan"===self.itemtype&&(requests=[],$.each(compIds,(function(index,compId){requests.push({methodname:"core_competency_add_competency_to_plan",args:{planid:self.itemid,competencyid:compId}})})),requests.push({methodname:"tool_lp_data_for_plan_page",args:{planid:self.itemid}}),pagerender="tool_lp/plan_page",pageregion="plan-page"),ajax.call(requests)[requests.length-1].then((function(context){return templates.render(pagerender,context)})).then((function(html,js){templates.replaceNode($('[data-region="'+pageregion+'"]'),html,js)})).then(pendingPromise.resolve).catch(notification.exception)}))),self.pickerInstance.display()},competencies.prototype.doDelete=function(deleteid){var requests=[],pagerender="",pageregion="";"course"==this.itemtype?(requests=ajax.call([{methodname:"core_competency_remove_competency_from_course",args:{courseid:this.itemid,competencyid:deleteid}},{methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:this.itemid,moduleid:0}}]),pagerender="tool_lp/course_competencies_page",pageregion="coursecompetenciespage"):"template"==this.itemtype?(requests=ajax.call([{methodname:"core_competency_remove_competency_from_template",args:{templateid:this.itemid,competencyid:deleteid}},{methodname:"tool_lp_data_for_template_competencies_page",args:{templateid:this.itemid,pagecontext:{contextid:this.pageContextId}}}]),pagerender="tool_lp/template_competencies_page",pageregion="templatecompetenciespage"):"plan"==this.itemtype&&(requests=ajax.call([{methodname:"core_competency_remove_competency_from_plan",args:{planid:this.itemid,competencyid:deleteid}},{methodname:"tool_lp_data_for_plan_page",args:{planid:this.itemid}}]),pagerender="tool_lp/plan_page",pageregion="plan-page"),requests[1].done((function(context){templates.render(pagerender,context).done((function(html,js){$('[data-region="'+pageregion+'"]').replaceWith(html),templates.runTemplateJS(js)})).fail(notification.exception)})).fail(notification.exception)},competencies.prototype.deleteHandler=function(deleteid){var message,localthis=this;if("course"==localthis.itemtype)message="unlinkcompetencycourse";else if("template"==localthis.itemtype)message="unlinkcompetencytemplate";else{if("plan"!=localthis.itemtype)return;message="unlinkcompetencyplan"}ajax.call([{methodname:"core_competency_read_competency",args:{id:deleteid}}])[0].done((function(competency){str.get_strings([{key:"confirm",component:"moodle"},{key:message,component:"tool_lp",param:competency.shortname},{key:"confirm",component:"moodle"},{key:"cancel",component:"moodle"}]).done((function(strings){notification.confirm(strings[0],strings[1],strings[2],strings[3],(function(){localthis.doDelete(deleteid)}))})).fail(notification.exception)})).fail(notification.exception)},competencies.prototype.registerEvents=function(){var localthis=this;"course"==localthis.itemtype&&$('[data-region="coursecompetenciespage"]').on("change",'select[data-field="ruleoutcome"]',(function(e){var pendingPromise=new Pending,coursecompetencyid=$(e.target).data("id"),ruleoutcome=$(e.target).val();ajax.call([{methodname:"core_competency_set_course_competency_ruleoutcome",args:{coursecompetencyid:coursecompetencyid,ruleoutcome:ruleoutcome}},{methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:localthis.itemid,moduleid:0}}])[1].then((function(context){return templates.render("tool_lp/course_competencies_page",context)})).then((function(html,js){return templates.replaceNode($('[data-region="coursecompetenciespage"]'),html,js)})).then(pendingPromise.resolve).catch(notification.exception)})),$('[data-region="actions"] button').click((function(e){var pendingPromise=new Pending;e.preventDefault(),localthis.pickCompetency().then(pendingPromise.resolve).catch()})),$('[data-action="delete-competency-link"]').click((function(e){e.preventDefault();var deleteid=$(e.target).closest("[data-id]").data("id");localthis.deleteHandler(deleteid)}))},competencies}));
+
+//# sourceMappingURL=competencies.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencies.min.js.map b/admin/tool/lp/amd/build/competencies.min.js.map
index fe7e6ed9854..38cbcbe25d1 100644
--- a/admin/tool/lp/amd/build/competencies.min.js.map
+++ b/admin/tool/lp/amd/build/competencies.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/competencies.js"],"names":["define","$","notification","ajax","templates","str","Picker","dragdrop","Pending","competencies","itemid","itemtype","pagectxid","pageContextId","pickerInstance","prop","registerEvents","registerDragDrop","prototype","localthis","get_string","done","movestring","identifier","component","drag","drop","handleDrop","fail","exception","fromid","data","toid","requests","call","methodname","args","courseid","competencyidfrom","competencyidto","templateid","planid","pickCompetency","self","pagerender","pageregion","pageContextIncludes","on","e","compIds","competencyIds","pendingPromise","each","index","compId","push","competencyid","moduleid","pagecontext","contextid","length","then","context","render","html","js","replaceNode","resolve","catch","display","doDelete","deleteid","replaceWith","runTemplateJS","deleteHandler","message","id","competency","get_strings","key","param","shortname","strings","confirm","coursecompetencyid","target","ruleoutcome","val","click","preventDefault","closest"],"mappings":"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","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 .\n\n/**\n * Handle add/remove competency links.\n *\n * @module tool_lp/competencies\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/templates',\n 'core/str',\n 'tool_lp/competencypicker',\n 'tool_lp/dragdrop-reorder',\n 'core/pending'],\n function($, notification, ajax, templates, str, Picker, dragdrop, Pending) {\n\n /**\n * Constructor\n *\n * @class tool_lp/competencies\n * @param {Number} itemid\n * @param {String} itemtype\n * @param {Number} pagectxid\n */\n var competencies = function(itemid, itemtype, pagectxid) {\n this.itemid = itemid;\n this.itemtype = itemtype;\n this.pageContextId = pagectxid;\n this.pickerInstance = null;\n\n $('[data-region=\"actions\"] button').prop('disabled', false);\n this.registerEvents();\n this.registerDragDrop();\n };\n\n /**\n * Initialise the drag/drop code.\n * @method registerDragDrop\n */\n competencies.prototype.registerDragDrop = function() {\n var localthis = this;\n // Init this module.\n str.get_string('movecompetency', 'tool_lp').done(\n function(movestring) {\n dragdrop.dragdrop('movecompetency',\n movestring,\n {identifier: 'movecompetency', component: 'tool_lp'},\n {identifier: 'movecompetencyafter', component: 'tool_lp'},\n 'drag-samenode',\n 'drag-parentnode',\n 'drag-handlecontainer',\n function(drag, drop) {\n localthis.handleDrop(drag, drop);\n });\n }\n ).fail(notification.exception);\n\n };\n\n /**\n * Handle a drop from a drag/drop operation.\n *\n * @method handleDrop\n * @param {DOMNode} drag The dragged node.\n * @param {DOMNode} drop The dropped on node.\n */\n competencies.prototype.handleDrop = function(drag, drop) {\n var fromid = $(drag).data('id');\n var toid = $(drop).data('id');\n var localthis = this;\n var requests = [];\n\n if (localthis.itemtype == 'course') {\n requests = ajax.call([\n {\n methodname: 'core_competency_reorder_course_competency',\n args: {courseid: localthis.itemid, competencyidfrom: fromid, competencyidto: toid}\n }\n ]);\n } else if (localthis.itemtype == 'template') {\n requests = ajax.call([\n {\n methodname: 'core_competency_reorder_template_competency',\n args: {templateid: localthis.itemid, competencyidfrom: fromid, competencyidto: toid}\n }\n ]);\n } else if (localthis.itemtype == 'plan') {\n requests = ajax.call([\n {\n methodname: 'core_competency_reorder_plan_competency',\n args: {planid: localthis.itemid, competencyidfrom: fromid, competencyidto: toid}\n }\n ]);\n } else {\n return;\n }\n\n requests[0].fail(notification.exception);\n };\n\n /**\n * Pick a competency\n *\n * @method pickCompetency\n * @return {Promise}\n */\n competencies.prototype.pickCompetency = function() {\n var self = this;\n var requests;\n var pagerender;\n var pageregion;\n var pageContextIncludes;\n\n if (!self.pickerInstance) {\n if (self.itemtype === 'template' || self.itemtype === 'course') {\n pageContextIncludes = 'parents';\n }\n self.pickerInstance = new Picker(self.pageContextId, false, pageContextIncludes);\n self.pickerInstance.on('save', function(e, data) {\n var compIds = data.competencyIds;\n var pendingPromise = new Pending();\n\n if (self.itemtype === \"course\") {\n requests = [];\n\n $.each(compIds, function(index, compId) {\n requests.push({\n methodname: 'core_competency_add_competency_to_course',\n args: {courseid: self.itemid, competencyid: compId}\n });\n });\n requests.push({\n methodname: 'tool_lp_data_for_course_competencies_page',\n args: {courseid: self.itemid, moduleid: 0}\n });\n\n pagerender = 'tool_lp/course_competencies_page';\n pageregion = 'coursecompetenciespage';\n\n } else if (self.itemtype === \"template\") {\n requests = [];\n\n $.each(compIds, function(index, compId) {\n requests.push({\n methodname: 'core_competency_add_competency_to_template',\n args: {templateid: self.itemid, competencyid: compId}\n });\n });\n requests.push({\n methodname: 'tool_lp_data_for_template_competencies_page',\n args: {templateid: self.itemid, pagecontext: {contextid: self.pageContextId}}\n });\n pagerender = 'tool_lp/template_competencies_page';\n pageregion = 'templatecompetenciespage';\n } else if (self.itemtype === \"plan\") {\n requests = [];\n\n $.each(compIds, function(index, compId) {\n requests.push({\n methodname: 'core_competency_add_competency_to_plan',\n args: {planid: self.itemid, competencyid: compId}\n });\n });\n requests.push({\n methodname: 'tool_lp_data_for_plan_page',\n args: {planid: self.itemid}\n });\n pagerender = 'tool_lp/plan_page';\n pageregion = 'plan-page';\n }\n ajax.call(requests)[requests.length - 1]\n .then(function(context) {\n return templates.render(pagerender, context);\n })\n .then(function(html, js) {\n templates.replaceNode($('[data-region=\"' + pageregion + '\"]'), html, js);\n return;\n })\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n });\n }\n\n return self.pickerInstance.display();\n };\n\n /**\n * Delete the link between competency and course, template or plan. Reload the page.\n *\n * @method doDelete\n * @param {int} deleteid The id of record to delete.\n */\n competencies.prototype.doDelete = function(deleteid) {\n var localthis = this;\n var requests = [],\n pagerender = '',\n pageregion = '';\n\n // Delete the link and reload the page template.\n if (localthis.itemtype == 'course') {\n requests = ajax.call([\n {methodname: 'core_competency_remove_competency_from_course',\n args: {courseid: localthis.itemid, competencyid: deleteid}},\n {methodname: 'tool_lp_data_for_course_competencies_page',\n args: {courseid: localthis.itemid, moduleid: 0}}\n ]);\n pagerender = 'tool_lp/course_competencies_page';\n pageregion = 'coursecompetenciespage';\n } else if (localthis.itemtype == 'template') {\n requests = ajax.call([\n {methodname: 'core_competency_remove_competency_from_template',\n args: {templateid: localthis.itemid, competencyid: deleteid}},\n {methodname: 'tool_lp_data_for_template_competencies_page',\n args: {templateid: localthis.itemid, pagecontext: {contextid: localthis.pageContextId}}}\n ]);\n pagerender = 'tool_lp/template_competencies_page';\n pageregion = 'templatecompetenciespage';\n } else if (localthis.itemtype == 'plan') {\n requests = ajax.call([\n {methodname: 'core_competency_remove_competency_from_plan',\n args: {planid: localthis.itemid, competencyid: deleteid}},\n {methodname: 'tool_lp_data_for_plan_page',\n args: {planid: localthis.itemid}}\n ]);\n pagerender = 'tool_lp/plan_page';\n pageregion = 'plan-page';\n }\n\n requests[1].done(function(context) {\n templates.render(pagerender, context).done(function(html, js) {\n $('[data-region=\"' + pageregion + '\"]').replaceWith(html);\n templates.runTemplateJS(js);\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n /**\n * Show a confirm dialogue before deleting a competency.\n *\n * @method deleteHandler\n * @param {int} deleteid The id of record to delete.\n */\n competencies.prototype.deleteHandler = function(deleteid) {\n var localthis = this;\n var requests = [];\n var message;\n\n if (localthis.itemtype == 'course') {\n message = 'unlinkcompetencycourse';\n } else if (localthis.itemtype == 'template') {\n message = 'unlinkcompetencytemplate';\n } else if (localthis.itemtype == 'plan') {\n message = 'unlinkcompetencyplan';\n } else {\n return;\n }\n\n requests = ajax.call([{\n methodname: 'core_competency_read_competency',\n args: {id: deleteid}\n }]);\n\n requests[0].done(function(competency) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: message, component: 'tool_lp', param: competency.shortname},\n {key: 'confirm', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Unlink the competency X from the course?\n strings[2], // Confirm.\n strings[3], // Cancel.\n function() {\n localthis.doDelete(deleteid);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Register the javascript event handlers for this page.\n *\n * @method registerEvents\n */\n competencies.prototype.registerEvents = function() {\n var localthis = this;\n\n if (localthis.itemtype == 'course') {\n // Course completion rule handling.\n $('[data-region=\"coursecompetenciespage\"]').on('change', 'select[data-field=\"ruleoutcome\"]', function(e) {\n var pendingPromise = new Pending();\n var requests = [];\n var pagerender = 'tool_lp/course_competencies_page';\n var pageregion = 'coursecompetenciespage';\n var coursecompetencyid = $(e.target).data('id');\n var ruleoutcome = $(e.target).val();\n requests = ajax.call([\n {methodname: 'core_competency_set_course_competency_ruleoutcome',\n args: {coursecompetencyid: coursecompetencyid, ruleoutcome: ruleoutcome}},\n {methodname: 'tool_lp_data_for_course_competencies_page',\n args: {courseid: localthis.itemid, moduleid: 0}}\n ]);\n\n requests[1].then(function(context) {\n return templates.render(pagerender, context);\n })\n .then(function(html, js) {\n return templates.replaceNode($('[data-region=\"' + pageregion + '\"]'), html, js);\n })\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n });\n }\n\n $('[data-region=\"actions\"] button').click(function(e) {\n var pendingPromise = new Pending();\n e.preventDefault();\n\n localthis.pickCompetency()\n .then(pendingPromise.resolve)\n .catch();\n });\n $('[data-action=\"delete-competency-link\"]').click(function(e) {\n e.preventDefault();\n\n var deleteid = $(e.target).closest('[data-id]').data('id');\n localthis.deleteHandler(deleteid);\n });\n };\n\n return /** @alias module:tool_lp/competencies */ competencies;\n});\n"],"file":"competencies.min.js"}
\ No newline at end of file
+{"version":3,"file":"competencies.min.js","sources":["../src/competencies.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 .\n\n/**\n * Handle add/remove competency links.\n *\n * @module tool_lp/competencies\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/templates',\n 'core/str',\n 'tool_lp/competencypicker',\n 'tool_lp/dragdrop-reorder',\n 'core/pending'],\n function($, notification, ajax, templates, str, Picker, dragdrop, Pending) {\n\n /**\n * Constructor\n *\n * @class tool_lp/competencies\n * @param {Number} itemid\n * @param {String} itemtype\n * @param {Number} pagectxid\n */\n var competencies = function(itemid, itemtype, pagectxid) {\n this.itemid = itemid;\n this.itemtype = itemtype;\n this.pageContextId = pagectxid;\n this.pickerInstance = null;\n\n $('[data-region=\"actions\"] button').prop('disabled', false);\n this.registerEvents();\n this.registerDragDrop();\n };\n\n /**\n * Initialise the drag/drop code.\n * @method registerDragDrop\n */\n competencies.prototype.registerDragDrop = function() {\n var localthis = this;\n // Init this module.\n str.get_string('movecompetency', 'tool_lp').done(\n function(movestring) {\n dragdrop.dragdrop('movecompetency',\n movestring,\n {identifier: 'movecompetency', component: 'tool_lp'},\n {identifier: 'movecompetencyafter', component: 'tool_lp'},\n 'drag-samenode',\n 'drag-parentnode',\n 'drag-handlecontainer',\n function(drag, drop) {\n localthis.handleDrop(drag, drop);\n });\n }\n ).fail(notification.exception);\n\n };\n\n /**\n * Handle a drop from a drag/drop operation.\n *\n * @method handleDrop\n * @param {DOMNode} drag The dragged node.\n * @param {DOMNode} drop The dropped on node.\n */\n competencies.prototype.handleDrop = function(drag, drop) {\n var fromid = $(drag).data('id');\n var toid = $(drop).data('id');\n var localthis = this;\n var requests = [];\n\n if (localthis.itemtype == 'course') {\n requests = ajax.call([\n {\n methodname: 'core_competency_reorder_course_competency',\n args: {courseid: localthis.itemid, competencyidfrom: fromid, competencyidto: toid}\n }\n ]);\n } else if (localthis.itemtype == 'template') {\n requests = ajax.call([\n {\n methodname: 'core_competency_reorder_template_competency',\n args: {templateid: localthis.itemid, competencyidfrom: fromid, competencyidto: toid}\n }\n ]);\n } else if (localthis.itemtype == 'plan') {\n requests = ajax.call([\n {\n methodname: 'core_competency_reorder_plan_competency',\n args: {planid: localthis.itemid, competencyidfrom: fromid, competencyidto: toid}\n }\n ]);\n } else {\n return;\n }\n\n requests[0].fail(notification.exception);\n };\n\n /**\n * Pick a competency\n *\n * @method pickCompetency\n * @return {Promise}\n */\n competencies.prototype.pickCompetency = function() {\n var self = this;\n var requests;\n var pagerender;\n var pageregion;\n var pageContextIncludes;\n\n if (!self.pickerInstance) {\n if (self.itemtype === 'template' || self.itemtype === 'course') {\n pageContextIncludes = 'parents';\n }\n self.pickerInstance = new Picker(self.pageContextId, false, pageContextIncludes);\n self.pickerInstance.on('save', function(e, data) {\n var compIds = data.competencyIds;\n var pendingPromise = new Pending();\n\n if (self.itemtype === \"course\") {\n requests = [];\n\n $.each(compIds, function(index, compId) {\n requests.push({\n methodname: 'core_competency_add_competency_to_course',\n args: {courseid: self.itemid, competencyid: compId}\n });\n });\n requests.push({\n methodname: 'tool_lp_data_for_course_competencies_page',\n args: {courseid: self.itemid, moduleid: 0}\n });\n\n pagerender = 'tool_lp/course_competencies_page';\n pageregion = 'coursecompetenciespage';\n\n } else if (self.itemtype === \"template\") {\n requests = [];\n\n $.each(compIds, function(index, compId) {\n requests.push({\n methodname: 'core_competency_add_competency_to_template',\n args: {templateid: self.itemid, competencyid: compId}\n });\n });\n requests.push({\n methodname: 'tool_lp_data_for_template_competencies_page',\n args: {templateid: self.itemid, pagecontext: {contextid: self.pageContextId}}\n });\n pagerender = 'tool_lp/template_competencies_page';\n pageregion = 'templatecompetenciespage';\n } else if (self.itemtype === \"plan\") {\n requests = [];\n\n $.each(compIds, function(index, compId) {\n requests.push({\n methodname: 'core_competency_add_competency_to_plan',\n args: {planid: self.itemid, competencyid: compId}\n });\n });\n requests.push({\n methodname: 'tool_lp_data_for_plan_page',\n args: {planid: self.itemid}\n });\n pagerender = 'tool_lp/plan_page';\n pageregion = 'plan-page';\n }\n ajax.call(requests)[requests.length - 1]\n .then(function(context) {\n return templates.render(pagerender, context);\n })\n .then(function(html, js) {\n templates.replaceNode($('[data-region=\"' + pageregion + '\"]'), html, js);\n return;\n })\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n });\n }\n\n return self.pickerInstance.display();\n };\n\n /**\n * Delete the link between competency and course, template or plan. Reload the page.\n *\n * @method doDelete\n * @param {int} deleteid The id of record to delete.\n */\n competencies.prototype.doDelete = function(deleteid) {\n var localthis = this;\n var requests = [],\n pagerender = '',\n pageregion = '';\n\n // Delete the link and reload the page template.\n if (localthis.itemtype == 'course') {\n requests = ajax.call([\n {methodname: 'core_competency_remove_competency_from_course',\n args: {courseid: localthis.itemid, competencyid: deleteid}},\n {methodname: 'tool_lp_data_for_course_competencies_page',\n args: {courseid: localthis.itemid, moduleid: 0}}\n ]);\n pagerender = 'tool_lp/course_competencies_page';\n pageregion = 'coursecompetenciespage';\n } else if (localthis.itemtype == 'template') {\n requests = ajax.call([\n {methodname: 'core_competency_remove_competency_from_template',\n args: {templateid: localthis.itemid, competencyid: deleteid}},\n {methodname: 'tool_lp_data_for_template_competencies_page',\n args: {templateid: localthis.itemid, pagecontext: {contextid: localthis.pageContextId}}}\n ]);\n pagerender = 'tool_lp/template_competencies_page';\n pageregion = 'templatecompetenciespage';\n } else if (localthis.itemtype == 'plan') {\n requests = ajax.call([\n {methodname: 'core_competency_remove_competency_from_plan',\n args: {planid: localthis.itemid, competencyid: deleteid}},\n {methodname: 'tool_lp_data_for_plan_page',\n args: {planid: localthis.itemid}}\n ]);\n pagerender = 'tool_lp/plan_page';\n pageregion = 'plan-page';\n }\n\n requests[1].done(function(context) {\n templates.render(pagerender, context).done(function(html, js) {\n $('[data-region=\"' + pageregion + '\"]').replaceWith(html);\n templates.runTemplateJS(js);\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n /**\n * Show a confirm dialogue before deleting a competency.\n *\n * @method deleteHandler\n * @param {int} deleteid The id of record to delete.\n */\n competencies.prototype.deleteHandler = function(deleteid) {\n var localthis = this;\n var requests = [];\n var message;\n\n if (localthis.itemtype == 'course') {\n message = 'unlinkcompetencycourse';\n } else if (localthis.itemtype == 'template') {\n message = 'unlinkcompetencytemplate';\n } else if (localthis.itemtype == 'plan') {\n message = 'unlinkcompetencyplan';\n } else {\n return;\n }\n\n requests = ajax.call([{\n methodname: 'core_competency_read_competency',\n args: {id: deleteid}\n }]);\n\n requests[0].done(function(competency) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: message, component: 'tool_lp', param: competency.shortname},\n {key: 'confirm', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Unlink the competency X from the course?\n strings[2], // Confirm.\n strings[3], // Cancel.\n function() {\n localthis.doDelete(deleteid);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Register the javascript event handlers for this page.\n *\n * @method registerEvents\n */\n competencies.prototype.registerEvents = function() {\n var localthis = this;\n\n if (localthis.itemtype == 'course') {\n // Course completion rule handling.\n $('[data-region=\"coursecompetenciespage\"]').on('change', 'select[data-field=\"ruleoutcome\"]', function(e) {\n var pendingPromise = new Pending();\n var requests = [];\n var pagerender = 'tool_lp/course_competencies_page';\n var pageregion = 'coursecompetenciespage';\n var coursecompetencyid = $(e.target).data('id');\n var ruleoutcome = $(e.target).val();\n requests = ajax.call([\n {methodname: 'core_competency_set_course_competency_ruleoutcome',\n args: {coursecompetencyid: coursecompetencyid, ruleoutcome: ruleoutcome}},\n {methodname: 'tool_lp_data_for_course_competencies_page',\n args: {courseid: localthis.itemid, moduleid: 0}}\n ]);\n\n requests[1].then(function(context) {\n return templates.render(pagerender, context);\n })\n .then(function(html, js) {\n return templates.replaceNode($('[data-region=\"' + pageregion + '\"]'), html, js);\n })\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n });\n }\n\n $('[data-region=\"actions\"] button').click(function(e) {\n var pendingPromise = new Pending();\n e.preventDefault();\n\n localthis.pickCompetency()\n .then(pendingPromise.resolve)\n .catch();\n });\n $('[data-action=\"delete-competency-link\"]').click(function(e) {\n e.preventDefault();\n\n var deleteid = $(e.target).closest('[data-id]').data('id');\n localthis.deleteHandler(deleteid);\n });\n };\n\n return /** @alias module:tool_lp/competencies */ competencies;\n});\n"],"names":["define","$","notification","ajax","templates","str","Picker","dragdrop","Pending","competencies","itemid","itemtype","pagectxid","pageContextId","pickerInstance","prop","registerEvents","registerDragDrop","prototype","localthis","this","get_string","done","movestring","identifier","component","drag","drop","handleDrop","fail","exception","fromid","data","toid","requests","call","methodname","args","courseid","competencyidfrom","competencyidto","templateid","planid","pickCompetency","pagerender","pageregion","pageContextIncludes","self","on","e","compIds","competencyIds","pendingPromise","each","index","compId","push","competencyid","moduleid","pagecontext","contextid","length","then","context","render","html","js","replaceNode","resolve","catch","display","doDelete","deleteid","replaceWith","runTemplateJS","deleteHandler","message","id","competency","get_strings","key","param","shortname","strings","confirm","coursecompetencyid","target","ruleoutcome","val","click","preventDefault","closest"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competency_outcomes.min.js b/admin/tool/lp/amd/build/competency_outcomes.min.js
index ae3938f0be3..a1e39dd4f5d 100644
--- a/admin/tool/lp/amd/build/competency_outcomes.min.js
+++ b/admin/tool/lp/amd/build/competency_outcomes.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/competency_outcomes",["jquery","core/str"],function(a,b){return{NONE:0,EVIDENCE:1,COMPLETE:2,RECOMMEND:3,getAll:function getAll(){var a=this;return b.get_strings([{key:"competencyoutcome_none",component:"tool_lp"},{key:"competencyoutcome_evidence",component:"tool_lp"},{key:"competencyoutcome_recommend",component:"tool_lp"},{key:"competencyoutcome_complete",component:"tool_lp"}]).then(function(b){var c={};c[a.NONE]={code:a.NONE,name:b[0]};c[a.EVIDENCE]={code:a.EVIDENCE,name:b[1]};c[a.RECOMMEND]={code:a.RECOMMEND,name:b[2]};c[a.COMPLETE]={code:a.COMPLETE,name:b[3]};return c})},getString:function getString(b){var c=this,d=c.getAll();return d.then(function(c){if("undefined"==typeof c[b]){return a.Deferred().reject().promise()}return c[b].name})}}});
-//# sourceMappingURL=competency_outcomes.min.js.map
+/**
+ * Competency rule config.
+ *
+ * @module tool_lp/competency_outcomes
+ * @copyright 2015 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/competency_outcomes",["jquery","core/str"],(function($,Str){return{NONE:0,EVIDENCE:1,COMPLETE:2,RECOMMEND:3,getAll:function(){var self=this;return Str.get_strings([{key:"competencyoutcome_none",component:"tool_lp"},{key:"competencyoutcome_evidence",component:"tool_lp"},{key:"competencyoutcome_recommend",component:"tool_lp"},{key:"competencyoutcome_complete",component:"tool_lp"}]).then((function(strings){var outcomes={};return outcomes[self.NONE]={code:self.NONE,name:strings[0]},outcomes[self.EVIDENCE]={code:self.EVIDENCE,name:strings[1]},outcomes[self.RECOMMEND]={code:self.RECOMMEND,name:strings[2]},outcomes[self.COMPLETE]={code:self.COMPLETE,name:strings[3]},outcomes}))},getString:function(id){return this.getAll().then((function(outcomes){return void 0===outcomes[id]?$.Deferred().reject().promise():outcomes[id].name}))}}}));
+
+//# sourceMappingURL=competency_outcomes.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competency_outcomes.min.js.map b/admin/tool/lp/amd/build/competency_outcomes.min.js.map
index 3a38fcdc31a..e3bf7de9983 100644
--- a/admin/tool/lp/amd/build/competency_outcomes.min.js.map
+++ b/admin/tool/lp/amd/build/competency_outcomes.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/competency_outcomes.js"],"names":["define","$","Str","NONE","EVIDENCE","COMPLETE","RECOMMEND","getAll","self","get_strings","key","component","then","strings","outcomes","code","name","getString","id","all","Deferred","reject","promise"],"mappings":"AAuBAA,OAAM,+BAAC,CAAC,QAAD,CACC,UADD,CAAD,CAEE,SAASC,CAAT,CAAYC,CAAZ,CAAiB,CAOrB,MAAO,CAEHC,IAAI,EAFD,CAGHC,QAAQ,EAHL,CAIHC,QAAQ,EAJL,CAKHC,SAAS,EALN,CAaHC,MAAM,CAAE,iBAAW,CACf,GAAIC,CAAAA,CAAI,CAAG,IAAX,CACA,MAAON,CAAAA,CAAG,CAACO,WAAJ,CAAgB,CACnB,CAACC,GAAG,CAAE,wBAAN,CAAgCC,SAAS,CAAE,SAA3C,CADmB,CAEnB,CAACD,GAAG,CAAE,4BAAN,CAAoCC,SAAS,CAAE,SAA/C,CAFmB,CAGnB,CAACD,GAAG,CAAE,6BAAN,CAAqCC,SAAS,CAAE,SAAhD,CAHmB,CAInB,CAACD,GAAG,CAAE,4BAAN,CAAoCC,SAAS,CAAE,SAA/C,CAJmB,CAAhB,EAKJC,IALI,CAKC,SAASC,CAAT,CAAkB,CACtB,GAAIC,CAAAA,CAAQ,CAAG,EAAf,CACAA,CAAQ,CAACN,CAAI,CAACL,IAAN,CAAR,CAAsB,CAACY,IAAI,CAAEP,CAAI,CAACL,IAAZ,CAAkBa,IAAI,CAAEH,CAAO,CAAC,CAAD,CAA/B,CAAtB,CACAC,CAAQ,CAACN,CAAI,CAACJ,QAAN,CAAR,CAA0B,CAACW,IAAI,CAAEP,CAAI,CAACJ,QAAZ,CAAsBY,IAAI,CAAEH,CAAO,CAAC,CAAD,CAAnC,CAA1B,CACAC,CAAQ,CAACN,CAAI,CAACF,SAAN,CAAR,CAA2B,CAACS,IAAI,CAAEP,CAAI,CAACF,SAAZ,CAAuBU,IAAI,CAAEH,CAAO,CAAC,CAAD,CAApC,CAA3B,CACAC,CAAQ,CAACN,CAAI,CAACH,QAAN,CAAR,CAA0B,CAACU,IAAI,CAAEP,CAAI,CAACH,QAAZ,CAAsBW,IAAI,CAAEH,CAAO,CAAC,CAAD,CAAnC,CAA1B,CACA,MAAOC,CAAAA,CACV,CAZM,CAaV,CA5BE,CAqCHG,SAAS,CAAE,mBAASC,CAAT,CAAa,CACpB,GAAIV,CAAAA,CAAI,CAAG,IAAX,CACIW,CAAG,CAAGX,CAAI,CAACD,MAAL,EADV,CAGA,MAAOY,CAAAA,CAAG,CAACP,IAAJ,CAAS,SAASE,CAAT,CAAmB,CAC/B,GAA4B,WAAxB,QAAOA,CAAAA,CAAQ,CAACI,CAAD,CAAnB,CAAyC,CACrC,MAAOjB,CAAAA,CAAC,CAACmB,QAAF,GAAaC,MAAb,GAAsBC,OAAtB,EACV,CACD,MAAOR,CAAAA,CAAQ,CAACI,CAAD,CAAR,CAAaF,IACvB,CALM,CAMV,CA/CE,CAiDV,CA1DK,CAAN","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 .\n\n/**\n * Competency rule config.\n *\n * @module tool_lp/competency_outcomes\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/str'],\n function($, Str) {\n\n var OUTCOME_NONE = 0,\n OUTCOME_EVIDENCE = 1,\n OUTCOME_COMPLETE = 2,\n OUTCOME_RECOMMEND = 3;\n\n return {\n\n NONE: OUTCOME_NONE,\n EVIDENCE: OUTCOME_EVIDENCE,\n COMPLETE: OUTCOME_COMPLETE,\n RECOMMEND: OUTCOME_RECOMMEND,\n\n /**\n * Get all the outcomes.\n *\n * @return {Object} Indexed by outcome code, contains code and name.\n * @method getAll\n */\n getAll: function() {\n var self = this;\n return Str.get_strings([\n {key: 'competencyoutcome_none', component: 'tool_lp'},\n {key: 'competencyoutcome_evidence', component: 'tool_lp'},\n {key: 'competencyoutcome_recommend', component: 'tool_lp'},\n {key: 'competencyoutcome_complete', component: 'tool_lp'},\n ]).then(function(strings) {\n var outcomes = {};\n outcomes[self.NONE] = {code: self.NONE, name: strings[0]};\n outcomes[self.EVIDENCE] = {code: self.EVIDENCE, name: strings[1]};\n outcomes[self.RECOMMEND] = {code: self.RECOMMEND, name: strings[2]};\n outcomes[self.COMPLETE] = {code: self.COMPLETE, name: strings[3]};\n return outcomes;\n });\n },\n\n /**\n * Get the string for an outcome.\n *\n * @param {Number} id The outcome code.\n * @return {Promise} Resolved with the string.\n * @method getString\n */\n getString: function(id) {\n var self = this,\n all = self.getAll();\n\n return all.then(function(outcomes) {\n if (typeof outcomes[id] === 'undefined') {\n return $.Deferred().reject().promise();\n }\n return outcomes[id].name;\n });\n }\n };\n});\n"],"file":"competency_outcomes.min.js"}
\ No newline at end of file
+{"version":3,"file":"competency_outcomes.min.js","sources":["../src/competency_outcomes.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 .\n\n/**\n * Competency rule config.\n *\n * @module tool_lp/competency_outcomes\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/str'],\n function($, Str) {\n\n var OUTCOME_NONE = 0,\n OUTCOME_EVIDENCE = 1,\n OUTCOME_COMPLETE = 2,\n OUTCOME_RECOMMEND = 3;\n\n return {\n\n NONE: OUTCOME_NONE,\n EVIDENCE: OUTCOME_EVIDENCE,\n COMPLETE: OUTCOME_COMPLETE,\n RECOMMEND: OUTCOME_RECOMMEND,\n\n /**\n * Get all the outcomes.\n *\n * @return {Object} Indexed by outcome code, contains code and name.\n * @method getAll\n */\n getAll: function() {\n var self = this;\n return Str.get_strings([\n {key: 'competencyoutcome_none', component: 'tool_lp'},\n {key: 'competencyoutcome_evidence', component: 'tool_lp'},\n {key: 'competencyoutcome_recommend', component: 'tool_lp'},\n {key: 'competencyoutcome_complete', component: 'tool_lp'},\n ]).then(function(strings) {\n var outcomes = {};\n outcomes[self.NONE] = {code: self.NONE, name: strings[0]};\n outcomes[self.EVIDENCE] = {code: self.EVIDENCE, name: strings[1]};\n outcomes[self.RECOMMEND] = {code: self.RECOMMEND, name: strings[2]};\n outcomes[self.COMPLETE] = {code: self.COMPLETE, name: strings[3]};\n return outcomes;\n });\n },\n\n /**\n * Get the string for an outcome.\n *\n * @param {Number} id The outcome code.\n * @return {Promise} Resolved with the string.\n * @method getString\n */\n getString: function(id) {\n var self = this,\n all = self.getAll();\n\n return all.then(function(outcomes) {\n if (typeof outcomes[id] === 'undefined') {\n return $.Deferred().reject().promise();\n }\n return outcomes[id].name;\n });\n }\n };\n});\n"],"names":["define","$","Str","NONE","EVIDENCE","COMPLETE","RECOMMEND","getAll","self","this","get_strings","key","component","then","strings","outcomes","code","name","getString","id","Deferred","reject","promise"],"mappings":";;;;;;;AAuBAA,qCAAO,CAAC,SACA,aACA,SAASC,EAAGC,WAOT,CAEHC,KAPe,EAQfC,SAPmB,EAQnBC,SAPmB,EAQnBC,UAPoB,EAepBC,OAAQ,eACAC,KAAOC,YACJP,IAAIQ,YAAY,CACnB,CAACC,IAAK,yBAA0BC,UAAW,WAC3C,CAACD,IAAK,6BAA8BC,UAAW,WAC/C,CAACD,IAAK,8BAA+BC,UAAW,WAChD,CAACD,IAAK,6BAA8BC,UAAW,aAChDC,MAAK,SAASC,aACTC,SAAW,UACfA,SAASP,KAAKL,MAAQ,CAACa,KAAMR,KAAKL,KAAMc,KAAMH,QAAQ,IACtDC,SAASP,KAAKJ,UAAY,CAACY,KAAMR,KAAKJ,SAAUa,KAAMH,QAAQ,IAC9DC,SAASP,KAAKF,WAAa,CAACU,KAAMR,KAAKF,UAAWW,KAAMH,QAAQ,IAChEC,SAASP,KAAKH,UAAY,CAACW,KAAMR,KAAKH,SAAUY,KAAMH,QAAQ,IACvDC,aAWfG,UAAW,SAASC,WACLV,KACIF,SAEJM,MAAK,SAASE,sBACO,IAAjBA,SAASI,IACTlB,EAAEmB,WAAWC,SAASC,UAE1BP,SAASI,IAAIF"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competency_plan_navigation.min.js b/admin/tool/lp/amd/build/competency_plan_navigation.min.js
index fbf44da2b37..de5ef7683a9 100644
--- a/admin/tool/lp/amd/build/competency_plan_navigation.min.js
+++ b/admin/tool/lp/amd/build/competency_plan_navigation.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/competency_plan_navigation",["jquery"],function(a){var b=function(b,c,d,e,f){this._baseUrl=c;this._userId=d+"";this._competencyId=e+"";this._planId=f;this._ignoreFirstCompetency=!0;a(b).on("change",this._competencyChanged.bind(this))};b.prototype._competencyChanged=function(b){if(this._ignoreFirstCompetency){this._ignoreFirstCompetency=!1;return}var c=a(b.target).val(),d="?userid="+this._userId+"&planid="+this._planId+"&competencyid="+c;document.location=this._baseUrl+d};b.prototype._competencyId=null;b.prototype._userId=null;b.prototype._planId=null;b.prototype._baseUrl=null;b.prototype._ignoreFirstCompetency=null;return b});
-//# sourceMappingURL=competency_plan_navigation.min.js.map
+/**
+ * Event click on selecting competency in the competency autocomplete.
+ *
+ * @module tool_lp/competency_plan_navigation
+ * @copyright 2016 Issam Taboubi
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/competency_plan_navigation",["jquery"],(function($){var CompetencyPlanNavigation=function(competencySelector,baseUrl,userId,competencyId,planId){this._baseUrl=baseUrl,this._userId=userId+"",this._competencyId=competencyId+"",this._planId=planId,this._ignoreFirstCompetency=!0,$(competencySelector).on("change",this._competencyChanged.bind(this))};return CompetencyPlanNavigation.prototype._competencyChanged=function(e){if(this._ignoreFirstCompetency)this._ignoreFirstCompetency=!1;else{var newCompetencyId=$(e.target).val(),queryStr="?userid="+this._userId+"&planid="+this._planId+"&competencyid="+newCompetencyId;document.location=this._baseUrl+queryStr}},CompetencyPlanNavigation.prototype._competencyId=null,CompetencyPlanNavigation.prototype._userId=null,CompetencyPlanNavigation.prototype._planId=null,CompetencyPlanNavigation.prototype._baseUrl=null,CompetencyPlanNavigation.prototype._ignoreFirstCompetency=null,CompetencyPlanNavigation}));
+
+//# sourceMappingURL=competency_plan_navigation.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competency_plan_navigation.min.js.map b/admin/tool/lp/amd/build/competency_plan_navigation.min.js.map
index 8b9c63dd49f..613139fd6e8 100644
--- a/admin/tool/lp/amd/build/competency_plan_navigation.min.js.map
+++ b/admin/tool/lp/amd/build/competency_plan_navigation.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/competency_plan_navigation.js"],"names":["define","$","CompetencyPlanNavigation","competencySelector","baseUrl","userId","competencyId","planId","_baseUrl","_userId","_competencyId","_planId","_ignoreFirstCompetency","on","_competencyChanged","bind","prototype","e","newCompetencyId","target","val","queryStr","document","location"],"mappings":"AAuBAA,OAAM,sCAAC,CAAC,QAAD,CAAD,CAAa,SAASC,CAAT,CAAY,CAY3B,GAAIC,CAAAA,CAAwB,CAAG,SAASC,CAAT,CAA6BC,CAA7B,CAAsCC,CAAtC,CAA8CC,CAA9C,CAA4DC,CAA5D,CAAoE,CAC/F,KAAKC,QAAL,CAAgBJ,CAAhB,CACA,KAAKK,OAAL,CAAeJ,CAAM,CAAG,EAAxB,CACA,KAAKK,aAAL,CAAqBJ,CAAY,CAAG,EAApC,CACA,KAAKK,OAAL,CAAeJ,CAAf,CACA,KAAKK,sBAAL,IAEAX,CAAC,CAACE,CAAD,CAAD,CAAsBU,EAAtB,CAAyB,QAAzB,CAAmC,KAAKC,kBAAL,CAAwBC,IAAxB,CAA6B,IAA7B,CAAnC,CACH,CARD,CAgBAb,CAAwB,CAACc,SAAzB,CAAmCF,kBAAnC,CAAwD,SAASG,CAAT,CAAY,CAChE,GAAI,KAAKL,sBAAT,CAAiC,CAC7B,KAAKA,sBAAL,IACA,MACH,CAJ+D,GAK5DM,CAAAA,CAAe,CAAGjB,CAAC,CAACgB,CAAC,CAACE,MAAH,CAAD,CAAYC,GAAZ,EAL0C,CAM5DC,CAAQ,CAAG,WAAa,KAAKZ,OAAlB,CAA4B,UAA5B,CAAyC,KAAKE,OAA9C,CAAwD,gBAAxD,CAA2EO,CAN1B,CAOhEI,QAAQ,CAACC,QAAT,CAAoB,KAAKf,QAAL,CAAgBa,CACvC,CARD,CAWAnB,CAAwB,CAACc,SAAzB,CAAmCN,aAAnC,CAAmD,IAAnD,CAEAR,CAAwB,CAACc,SAAzB,CAAmCP,OAAnC,CAA6C,IAA7C,CAEAP,CAAwB,CAACc,SAAzB,CAAmCL,OAAnC,CAA6C,IAA7C,CAEAT,CAAwB,CAACc,SAAzB,CAAmCR,QAAnC,CAA8C,IAA9C,CAEAN,CAAwB,CAACc,SAAzB,CAAmCJ,sBAAnC,CAA4D,IAA5D,CAEA,MAAOV,CAAAA,CACV,CAlDK,CAAN","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 .\n\n/**\n * Event click on selecting competency in the competency autocomplete.\n *\n * @module tool_lp/competency_plan_navigation\n * @copyright 2016 Issam Taboubi \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function($) {\n\n /**\n * CompetencyPlanNavigation\n *\n * @class\n * @param {String} competencySelector The selector of the competency element.\n * @param {String} baseUrl The base url for the page (no params).\n * @param {Number} userId The user id\n * @param {Number} competencyId The competency id\n * @param {Number} planId The plan id\n */\n var CompetencyPlanNavigation = function(competencySelector, baseUrl, userId, competencyId, planId) {\n this._baseUrl = baseUrl;\n this._userId = userId + '';\n this._competencyId = competencyId + '';\n this._planId = planId;\n this._ignoreFirstCompetency = true;\n\n $(competencySelector).on('change', this._competencyChanged.bind(this));\n };\n\n /**\n * The competency was changed in the select list.\n *\n * @method _competencyChanged\n * @param {Event} e\n */\n CompetencyPlanNavigation.prototype._competencyChanged = function(e) {\n if (this._ignoreFirstCompetency) {\n this._ignoreFirstCompetency = false;\n return;\n }\n var newCompetencyId = $(e.target).val();\n var queryStr = '?userid=' + this._userId + '&planid=' + this._planId + '&competencyid=' + newCompetencyId;\n document.location = this._baseUrl + queryStr;\n };\n\n /** @property {Number} The id of the competency. */\n CompetencyPlanNavigation.prototype._competencyId = null;\n /** @property {Number} The id of the user. */\n CompetencyPlanNavigation.prototype._userId = null;\n /** @property {Number} The id of the plan. */\n CompetencyPlanNavigation.prototype._planId = null;\n /** @property {String} Plugin base url. */\n CompetencyPlanNavigation.prototype._baseUrl = null;\n /** @property {Boolean} Ignore the first change event for competencies. */\n CompetencyPlanNavigation.prototype._ignoreFirstCompetency = null;\n\n return CompetencyPlanNavigation;\n});\n"],"file":"competency_plan_navigation.min.js"}
\ No newline at end of file
+{"version":3,"file":"competency_plan_navigation.min.js","sources":["../src/competency_plan_navigation.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 .\n\n/**\n * Event click on selecting competency in the competency autocomplete.\n *\n * @module tool_lp/competency_plan_navigation\n * @copyright 2016 Issam Taboubi \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function($) {\n\n /**\n * CompetencyPlanNavigation\n *\n * @class\n * @param {String} competencySelector The selector of the competency element.\n * @param {String} baseUrl The base url for the page (no params).\n * @param {Number} userId The user id\n * @param {Number} competencyId The competency id\n * @param {Number} planId The plan id\n */\n var CompetencyPlanNavigation = function(competencySelector, baseUrl, userId, competencyId, planId) {\n this._baseUrl = baseUrl;\n this._userId = userId + '';\n this._competencyId = competencyId + '';\n this._planId = planId;\n this._ignoreFirstCompetency = true;\n\n $(competencySelector).on('change', this._competencyChanged.bind(this));\n };\n\n /**\n * The competency was changed in the select list.\n *\n * @method _competencyChanged\n * @param {Event} e\n */\n CompetencyPlanNavigation.prototype._competencyChanged = function(e) {\n if (this._ignoreFirstCompetency) {\n this._ignoreFirstCompetency = false;\n return;\n }\n var newCompetencyId = $(e.target).val();\n var queryStr = '?userid=' + this._userId + '&planid=' + this._planId + '&competencyid=' + newCompetencyId;\n document.location = this._baseUrl + queryStr;\n };\n\n /** @property {Number} The id of the competency. */\n CompetencyPlanNavigation.prototype._competencyId = null;\n /** @property {Number} The id of the user. */\n CompetencyPlanNavigation.prototype._userId = null;\n /** @property {Number} The id of the plan. */\n CompetencyPlanNavigation.prototype._planId = null;\n /** @property {String} Plugin base url. */\n CompetencyPlanNavigation.prototype._baseUrl = null;\n /** @property {Boolean} Ignore the first change event for competencies. */\n CompetencyPlanNavigation.prototype._ignoreFirstCompetency = null;\n\n return CompetencyPlanNavigation;\n});\n"],"names":["define","$","CompetencyPlanNavigation","competencySelector","baseUrl","userId","competencyId","planId","_baseUrl","_userId","_competencyId","_planId","_ignoreFirstCompetency","on","this","_competencyChanged","bind","prototype","e","newCompetencyId","target","val","queryStr","document","location"],"mappings":";;;;;;;AAuBAA,4CAAO,CAAC,WAAW,SAASC,OAYpBC,yBAA2B,SAASC,mBAAoBC,QAASC,OAAQC,aAAcC,aAClFC,SAAWJ,aACXK,QAAUJ,OAAS,QACnBK,cAAgBJ,aAAe,QAC/BK,QAAUJ,YACVK,wBAAyB,EAE9BX,EAAEE,oBAAoBU,GAAG,SAAUC,KAAKC,mBAAmBC,KAAKF,eASpEZ,yBAAyBe,UAAUF,mBAAqB,SAASG,MACzDJ,KAAKF,4BACAA,wBAAyB,WAG9BO,gBAAkBlB,EAAEiB,EAAEE,QAAQC,MAC9BC,SAAW,WAAaR,KAAKL,QAAU,WAAaK,KAAKH,QAAU,iBAAmBQ,gBAC1FI,SAASC,SAAWV,KAAKN,SAAWc,WAIxCpB,yBAAyBe,UAAUP,cAAgB,KAEnDR,yBAAyBe,UAAUR,QAAU,KAE7CP,yBAAyBe,UAAUN,QAAU,KAE7CT,yBAAyBe,UAAUT,SAAW,KAE9CN,yBAAyBe,UAAUL,uBAAyB,KAErDV"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competency_rule.min.js b/admin/tool/lp/amd/build/competency_rule.min.js
index 1315e57b049..032876db145 100644
--- a/admin/tool/lp/amd/build/competency_rule.min.js
+++ b/admin/tool/lp/amd/build/competency_rule.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/competency_rule",["jquery"],function(a){var b=function(b){this._eventNode=a("
");this._ready=a.Deferred();this._tree=b};b.prototype._competency=null;b.prototype._eventNode=null;b.prototype._ready=null;b.prototype._tree=null;b.prototype.canConfig=function(){return this._tree.hasChildren(this._competency.id)};b.prototype.getConfig=function(){return null};b.prototype.getType=function(){throw new Error("Not implemented")};b.prototype.init=function(){return this._load()};b.prototype.injectTemplate=function(){return a.Deferred().reject().promise()};b.prototype.isValid=function(){return!1};b.prototype._load=function(){return a.when()};b.prototype.on=function(a,b){this._eventNode.on(a,b)};b.prototype.setTargetCompetency=function(a){this._competency=a};b.prototype._trigger=function(a,b){this._eventNode.trigger(a,[b])};b.prototype._triggerChange=function(){this._trigger("change",this)};return b});
-//# sourceMappingURL=competency_rule.min.js.map
+/**
+ * Competency rule base module.
+ *
+ * @module tool_lp/competencyrule
+ * @copyright 2015 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/competency_rule",["jquery"],(function($){var Rule=function(tree){this._eventNode=$("
"),this._ready=$.Deferred(),this._tree=tree};return Rule.prototype._competency=null,Rule.prototype._eventNode=null,Rule.prototype._ready=null,Rule.prototype._tree=null,Rule.prototype.canConfig=function(){return this._tree.hasChildren(this._competency.id)},Rule.prototype.getConfig=function(){return null},Rule.prototype.getType=function(){throw new Error("Not implemented")},Rule.prototype.init=function(){return this._load()},Rule.prototype.injectTemplate=function(){return $.Deferred().reject().promise()},Rule.prototype.isValid=function(){return!1},Rule.prototype._load=function(){return $.when()},Rule.prototype.on=function(type,handler){this._eventNode.on(type,handler)},Rule.prototype.setTargetCompetency=function(competency){this._competency=competency},Rule.prototype._trigger=function(type,data){this._eventNode.trigger(type,[data])},Rule.prototype._triggerChange=function(){this._trigger("change",this)},Rule}));
+
+//# sourceMappingURL=competency_rule.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competency_rule.min.js.map b/admin/tool/lp/amd/build/competency_rule.min.js.map
index 1ca5191e836..a0fe9913190 100644
--- a/admin/tool/lp/amd/build/competency_rule.min.js.map
+++ b/admin/tool/lp/amd/build/competency_rule.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/competency_rule.js"],"names":["define","$","Rule","tree","_eventNode","_ready","Deferred","_tree","prototype","_competency","canConfig","hasChildren","id","getConfig","getType","Error","init","_load","injectTemplate","reject","promise","isValid","when","on","type","handler","setTargetCompetency","competency","_trigger","data","trigger","_triggerChange"],"mappings":"AAuBAA,OAAM,2BAAC,CAAC,QAAD,CAAD,CAAa,SAASC,CAAT,CAAY,CAa3B,GAAIC,CAAAA,CAAI,CAAG,SAASC,CAAT,CAAe,CACtB,KAAKC,UAAL,CAAkBH,CAAC,CAAC,OAAD,CAAnB,CACA,KAAKI,MAAL,CAAcJ,CAAC,CAACK,QAAF,EAAd,CACA,KAAKC,KAAL,CAAaJ,CAChB,CAJD,CAOAD,CAAI,CAACM,SAAL,CAAeC,WAAf,CAA6B,IAA7B,CAEAP,CAAI,CAACM,SAAL,CAAeJ,UAAf,CAA4B,IAA5B,CAEAF,CAAI,CAACM,SAAL,CAAeH,MAAf,CAAwB,IAAxB,CAEAH,CAAI,CAACM,SAAL,CAAeD,KAAf,CAAuB,IAAvB,CAQAL,CAAI,CAACM,SAAL,CAAeE,SAAf,CAA2B,UAAW,CAClC,MAAO,MAAKH,KAAL,CAAWI,WAAX,CAAuB,KAAKF,WAAL,CAAiBG,EAAxC,CACV,CAFD,CAYAV,CAAI,CAACM,SAAL,CAAeK,SAAf,CAA2B,UAAW,CAClC,MAAO,KACV,CAFD,CAYAX,CAAI,CAACM,SAAL,CAAeM,OAAf,CAAyB,UAAW,CAChC,KAAM,IAAIC,CAAAA,KAAJ,CAAU,iBAAV,CACT,CAFD,CAYAb,CAAI,CAACM,SAAL,CAAeQ,IAAf,CAAsB,UAAW,CAC7B,MAAO,MAAKC,KAAL,EACV,CAFD,CAUAf,CAAI,CAACM,SAAL,CAAeU,cAAf,CAAgC,UAAW,CACvC,MAAOjB,CAAAA,CAAC,CAACK,QAAF,GAAaa,MAAb,GAAsBC,OAAtB,EACV,CAFD,CAYAlB,CAAI,CAACM,SAAL,CAAea,OAAf,CAAyB,UAAW,CAChC,QACH,CAFD,CAWAnB,CAAI,CAACM,SAAL,CAAeS,KAAf,CAAuB,UAAW,CAC9B,MAAOhB,CAAAA,CAAC,CAACqB,IAAF,EACV,CAFD,CAWApB,CAAI,CAACM,SAAL,CAAee,EAAf,CAAoB,SAASC,CAAT,CAAeC,CAAf,CAAwB,CACxC,KAAKrB,UAAL,CAAgBmB,EAAhB,CAAmBC,CAAnB,CAAyBC,CAAzB,CACH,CAFD,CAUAvB,CAAI,CAACM,SAAL,CAAekB,mBAAf,CAAqC,SAASC,CAAT,CAAqB,CACtD,KAAKlB,WAAL,CAAmBkB,CACtB,CAFD,CAYAzB,CAAI,CAACM,SAAL,CAAeoB,QAAf,CAA0B,SAASJ,CAAT,CAAeK,CAAf,CAAqB,CAC3C,KAAKzB,UAAL,CAAgB0B,OAAhB,CAAwBN,CAAxB,CAA8B,CAACK,CAAD,CAA9B,CACH,CAFD,CAUA3B,CAAI,CAACM,SAAL,CAAeuB,cAAf,CAAgC,UAAW,CACvC,KAAKH,QAAL,CAAc,QAAd,CAAwB,IAAxB,CACH,CAFD,CAIA,MAAoD1B,CAAAA,CAEvD,CAxJK,CAAN","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 .\n\n/**\n * Competency rule base module.\n *\n * @module tool_lp/competencyrule\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function($) {\n\n /**\n * Competency rule abstract class.\n *\n * Any competency rule should extend this object. The event 'change' should be\n * triggered on the instance when the configuration has changed. This will allow\n * the components using the rule to gather the config, or check its validity.\n *\n * this._triggerChange();\n *\n * @param {Tree} tree The competency tree.\n */\n var Rule = function(tree) {\n this._eventNode = $('
');\n this._ready = $.Deferred();\n this._tree = tree;\n };\n\n /** @property {Object} The current competency. */\n Rule.prototype._competency = null;\n /** @property {Node} The node we attach the events to. */\n Rule.prototype._eventNode = null;\n /** @property {Promise} Resolved when the object is ready. */\n Rule.prototype._ready = null;\n /** @property {Tree} The competency tree. */\n Rule.prototype._tree = null;\n\n /**\n * Whether or not the current competency can be configured using this rule.\n *\n * @return {Boolean}\n * @method canConfig\n */\n Rule.prototype.canConfig = function() {\n return this._tree.hasChildren(this._competency.id);\n };\n\n /**\n * The config established by this rule.\n *\n * To override in subclasses when relevant.\n *\n * @return {String|null}\n * @method getConfig\n */\n Rule.prototype.getConfig = function() {\n return null;\n };\n\n // eslint-disable-line valid-jsdoc\n /**\n * Return the type of the module.\n *\n * @return {String}\n * @method getType\n */\n // eslint-enable-line valid-jsdoc\n Rule.prototype.getType = function() {\n throw new Error('Not implemented');\n };\n\n /**\n * The init process.\n *\n * Do not override this, instead override _load.\n *\n * @return {Promise} Revoled when the plugin is initialised.\n * @method init\n */\n Rule.prototype.init = function() {\n return this._load();\n };\n\n /**\n * Callback to inject the template.\n *\n * @returns {Promise} Resolved when done.\n * @method injectTemplate\n */\n Rule.prototype.injectTemplate = function() {\n return $.Deferred().reject().promise();\n };\n\n /**\n * Whether or not the current config is valid.\n *\n * Plugins should override this.\n *\n * @return {Boolean}\n * @method _isValid\n */\n Rule.prototype.isValid = function() {\n return false;\n };\n\n /**\n * Load the class.\n *\n * @return {Promise}\n * @method _load\n * @protected\n */\n Rule.prototype._load = function() {\n return $.when();\n };\n\n /**\n * Register an event listener.\n *\n * @param {String} type The event type.\n * @param {Function} handler The event listener.\n * @method on\n */\n Rule.prototype.on = function(type, handler) {\n this._eventNode.on(type, handler);\n };\n\n /**\n * Sets the current competency.\n *\n * @param {Competency} competency\n * @method setTargetCompetency\n */\n Rule.prototype.setTargetCompetency = function(competency) {\n this._competency = competency;\n };\n\n /**\n * Trigger an event.\n *\n * @param {String} type The type of event.\n * @param {Object} data The data to pass to the listeners.\n * @method _trigger\n * @protected\n */\n Rule.prototype._trigger = function(type, data) {\n this._eventNode.trigger(type, [data]);\n };\n\n /**\n * Trigger the change event.\n *\n * @method _triggerChange\n * @protected\n */\n Rule.prototype._triggerChange = function() {\n this._trigger('change', this);\n };\n\n return /** @alias module:tool_lp/competency_rule */ Rule;\n\n});\n"],"file":"competency_rule.min.js"}
\ No newline at end of file
+{"version":3,"file":"competency_rule.min.js","sources":["../src/competency_rule.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 .\n\n/**\n * Competency rule base module.\n *\n * @module tool_lp/competencyrule\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function($) {\n\n /**\n * Competency rule abstract class.\n *\n * Any competency rule should extend this object. The event 'change' should be\n * triggered on the instance when the configuration has changed. This will allow\n * the components using the rule to gather the config, or check its validity.\n *\n * this._triggerChange();\n *\n * @param {Tree} tree The competency tree.\n */\n var Rule = function(tree) {\n this._eventNode = $('
');\n this._ready = $.Deferred();\n this._tree = tree;\n };\n\n /** @property {Object} The current competency. */\n Rule.prototype._competency = null;\n /** @property {Node} The node we attach the events to. */\n Rule.prototype._eventNode = null;\n /** @property {Promise} Resolved when the object is ready. */\n Rule.prototype._ready = null;\n /** @property {Tree} The competency tree. */\n Rule.prototype._tree = null;\n\n /**\n * Whether or not the current competency can be configured using this rule.\n *\n * @return {Boolean}\n * @method canConfig\n */\n Rule.prototype.canConfig = function() {\n return this._tree.hasChildren(this._competency.id);\n };\n\n /**\n * The config established by this rule.\n *\n * To override in subclasses when relevant.\n *\n * @return {String|null}\n * @method getConfig\n */\n Rule.prototype.getConfig = function() {\n return null;\n };\n\n // eslint-disable-line valid-jsdoc\n /**\n * Return the type of the module.\n *\n * @return {String}\n * @method getType\n */\n // eslint-enable-line valid-jsdoc\n Rule.prototype.getType = function() {\n throw new Error('Not implemented');\n };\n\n /**\n * The init process.\n *\n * Do not override this, instead override _load.\n *\n * @return {Promise} Revoled when the plugin is initialised.\n * @method init\n */\n Rule.prototype.init = function() {\n return this._load();\n };\n\n /**\n * Callback to inject the template.\n *\n * @returns {Promise} Resolved when done.\n * @method injectTemplate\n */\n Rule.prototype.injectTemplate = function() {\n return $.Deferred().reject().promise();\n };\n\n /**\n * Whether or not the current config is valid.\n *\n * Plugins should override this.\n *\n * @return {Boolean}\n * @method _isValid\n */\n Rule.prototype.isValid = function() {\n return false;\n };\n\n /**\n * Load the class.\n *\n * @return {Promise}\n * @method _load\n * @protected\n */\n Rule.prototype._load = function() {\n return $.when();\n };\n\n /**\n * Register an event listener.\n *\n * @param {String} type The event type.\n * @param {Function} handler The event listener.\n * @method on\n */\n Rule.prototype.on = function(type, handler) {\n this._eventNode.on(type, handler);\n };\n\n /**\n * Sets the current competency.\n *\n * @param {Competency} competency\n * @method setTargetCompetency\n */\n Rule.prototype.setTargetCompetency = function(competency) {\n this._competency = competency;\n };\n\n /**\n * Trigger an event.\n *\n * @param {String} type The type of event.\n * @param {Object} data The data to pass to the listeners.\n * @method _trigger\n * @protected\n */\n Rule.prototype._trigger = function(type, data) {\n this._eventNode.trigger(type, [data]);\n };\n\n /**\n * Trigger the change event.\n *\n * @method _triggerChange\n * @protected\n */\n Rule.prototype._triggerChange = function() {\n this._trigger('change', this);\n };\n\n return /** @alias module:tool_lp/competency_rule */ Rule;\n\n});\n"],"names":["define","$","Rule","tree","_eventNode","_ready","Deferred","_tree","prototype","_competency","canConfig","this","hasChildren","id","getConfig","getType","Error","init","_load","injectTemplate","reject","promise","isValid","when","on","type","handler","setTargetCompetency","competency","_trigger","data","trigger","_triggerChange"],"mappings":";;;;;;;AAuBAA,iCAAO,CAAC,WAAW,SAASC,OAapBC,KAAO,SAASC,WACXC,WAAaH,EAAE,cACfI,OAASJ,EAAEK,gBACXC,MAAQJ,aAIjBD,KAAKM,UAAUC,YAAc,KAE7BP,KAAKM,UAAUJ,WAAa,KAE5BF,KAAKM,UAAUH,OAAS,KAExBH,KAAKM,UAAUD,MAAQ,KAQvBL,KAAKM,UAAUE,UAAY,kBAChBC,KAAKJ,MAAMK,YAAYD,KAAKF,YAAYI,KAWnDX,KAAKM,UAAUM,UAAY,kBAChB,MAWXZ,KAAKM,UAAUO,QAAU,iBACf,IAAIC,MAAM,oBAWpBd,KAAKM,UAAUS,KAAO,kBACXN,KAAKO,SAShBhB,KAAKM,UAAUW,eAAiB,kBACrBlB,EAAEK,WAAWc,SAASC,WAWjCnB,KAAKM,UAAUc,QAAU,kBACd,GAUXpB,KAAKM,UAAUU,MAAQ,kBACZjB,EAAEsB,QAUbrB,KAAKM,UAAUgB,GAAK,SAASC,KAAMC,cAC1BtB,WAAWoB,GAAGC,KAAMC,UAS7BxB,KAAKM,UAAUmB,oBAAsB,SAASC,iBACrCnB,YAAcmB,YAWvB1B,KAAKM,UAAUqB,SAAW,SAASJ,KAAMK,WAChC1B,WAAW2B,QAAQN,KAAM,CAACK,QASnC5B,KAAKM,UAAUwB,eAAiB,gBACvBH,SAAS,SAAUlB,OAGwBT"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competency_rule_all.min.js b/admin/tool/lp/amd/build/competency_rule_all.min.js
index c396c7fcfc9..812d645ebed 100644
--- a/admin/tool/lp/amd/build/competency_rule_all.min.js
+++ b/admin/tool/lp/amd/build/competency_rule_all.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/competency_rule_all",["jquery","core/str","tool_lp/competency_rule"],function(a,b,c){var d=function(){c.apply(this,arguments)};d.prototype=Object.create(c.prototype);d.prototype.getType=function(){return"core_competency\\competency_rule_all"};d.prototype.isValid=function(){return!0};return d});
-//# sourceMappingURL=competency_rule_all.min.js.map
+/**
+ * Competency rule all module.
+ *
+ * @module tool_lp/competency_rule_all
+ * @copyright 2015 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/competency_rule_all",["jquery","core/str","tool_lp/competency_rule"],(function($,Str,RuleBase){var Rule=function(){RuleBase.apply(this,arguments)};return(Rule.prototype=Object.create(RuleBase.prototype)).getType=function(){return"core_competency\\competency_rule_all"},Rule.prototype.isValid=function(){return!0},Rule}));
+
+//# sourceMappingURL=competency_rule_all.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competency_rule_all.min.js.map b/admin/tool/lp/amd/build/competency_rule_all.min.js.map
index 9e6113d704c..cb5f90d05f7 100644
--- a/admin/tool/lp/amd/build/competency_rule_all.min.js.map
+++ b/admin/tool/lp/amd/build/competency_rule_all.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/competency_rule_all.js"],"names":["define","$","Str","RuleBase","Rule","apply","arguments","prototype","Object","create","getType","isValid"],"mappings":"AAuBAA,OAAM,+BAAC,CAAC,QAAD,CACC,UADD,CAEC,yBAFD,CAAD,CAIE,SAASC,CAAT,CAAYC,CAAZ,CAAiBC,CAAjB,CAA2B,CAO/B,GAAIC,CAAAA,CAAI,CAAG,UAAW,CAClBD,CAAQ,CAACE,KAAT,CAAe,IAAf,CAAqBC,SAArB,CACH,CAFD,CAGAF,CAAI,CAACG,SAAL,CAAiBC,MAAM,CAACC,MAAP,CAAcN,CAAQ,CAACI,SAAvB,CAAjB,CAQAH,CAAI,CAACG,SAAL,CAAeG,OAAf,CAAyB,UAAW,CAChC,MAAO,sCACV,CAFD,CAUAN,CAAI,CAACG,SAAL,CAAeI,OAAf,CAAyB,UAAW,CAChC,QACH,CAFD,CAIA,MAAOP,CAAAA,CACV,CArCK,CAAN","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 .\n\n/**\n * Competency rule all module.\n *\n * @module tool_lp/competency_rule_all\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/str',\n 'tool_lp/competency_rule',\n ],\n function($, Str, RuleBase) {\n\n /**\n * Competency rule all class.\n *\n * @class tool_lp/competency_rule_all\n */\n var Rule = function() {\n RuleBase.apply(this, arguments);\n };\n Rule.prototype = Object.create(RuleBase.prototype);\n\n /**\n * Return the type of the module.\n *\n * @return {String}\n * @method getType\n */\n Rule.prototype.getType = function() {\n return 'core_competency\\\\competency_rule_all';\n };\n\n /**\n * Whether or not the current config is valid.\n *\n * @return {Boolean}\n * @method isValid\n */\n Rule.prototype.isValid = function() {\n return true;\n };\n\n return Rule;\n});\n"],"file":"competency_rule_all.min.js"}
\ No newline at end of file
+{"version":3,"file":"competency_rule_all.min.js","sources":["../src/competency_rule_all.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 .\n\n/**\n * Competency rule all module.\n *\n * @module tool_lp/competency_rule_all\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/str',\n 'tool_lp/competency_rule',\n ],\n function($, Str, RuleBase) {\n\n /**\n * Competency rule all class.\n *\n * @class tool_lp/competency_rule_all\n */\n var Rule = function() {\n RuleBase.apply(this, arguments);\n };\n Rule.prototype = Object.create(RuleBase.prototype);\n\n /**\n * Return the type of the module.\n *\n * @return {String}\n * @method getType\n */\n Rule.prototype.getType = function() {\n return 'core_competency\\\\competency_rule_all';\n };\n\n /**\n * Whether or not the current config is valid.\n *\n * @return {Boolean}\n * @method isValid\n */\n Rule.prototype.isValid = function() {\n return true;\n };\n\n return Rule;\n});\n"],"names":["define","$","Str","RuleBase","Rule","apply","this","arguments","prototype","Object","create","getType","isValid"],"mappings":";;;;;;;AAuBAA,qCAAO,CAAC,SACA,WACA,4BAEA,SAASC,EAAGC,IAAKC,cAOjBC,KAAO,WACPD,SAASE,MAAMC,KAAMC,mBAEzBH,KAAKI,UAAYC,OAAOC,OAAOP,SAASK,YAQzBG,QAAU,iBACd,wCASXP,KAAKI,UAAUI,QAAU,kBACd,GAGJR"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competency_rule_points.min.js b/admin/tool/lp/amd/build/competency_rule_points.min.js
index 1a034201667..fb104b99183 100644
--- a/admin/tool/lp/amd/build/competency_rule_points.min.js
+++ b/admin/tool/lp/amd/build/competency_rule_points.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/competency_rule_points",["jquery","core/str","core/templates","tool_lp/competency_rule"],function(a,b,c,d){var e=function(){d.apply(this,arguments)};e.prototype=Object.create(d.prototype);e.prototype._container=null;e.prototype._templateLoaded=!1;e.prototype.getConfig=function(){return JSON.stringify({base:{points:this._getRequiredPoints()},competencies:this._getCompetenciesConfig()})};e.prototype._getCompetenciesConfig=function(){var b=[];this._container.find("[data-competency]").each(function(){var c=a(this),d=c.data("competency"),e=parseInt(c.find("[name=\"points\"]").val(),10),f=c.find("[name=\"required\"]").prop("checked");b.push({id:d,points:e,required:f?1:0})});return b};e.prototype._getRequiredPoints=function(){return parseInt(this._container.find("[name=\"requiredpoints\"]").val()||1,10)};e.prototype.getType=function(){return"core_competency\\competency_rule_points"};e.prototype.injectTemplate=function(b){var d=this,e=this._tree.getChildren(this._competency.id),f,g={base:{points:2},competencies:[]};this._templateLoaded=!1;if(d._competency.ruletype==d.getType()){try{g=JSON.parse(d._competency.ruleconfig)}catch(a){}}f={requiredpoints:g&&g.base?g.base.points:2,competency:d._competency,children:[]};a.each(e,function(b,c){var d={id:c.id,shortname:c.shortname,required:!1,points:0};if(g){a.each(g.competencies,function(a,b){if(b.id==d.id){d.required=b.required?!0:!1;d.points=b.points}})}f.children.push(d)});return c.render("tool_lp/competency_rule_points",f).then(function(a){d._container=b;b.html(a);b.find("input").change(function(){d._triggerChange()});d._templateLoaded=!0;d._triggerChange()})};e.prototype.isValid=function(){if(!this._templateLoaded){return!1}var b=this._getRequiredPoints(),c=0,d=!0;a.each(this._getCompetenciesConfig(),function(a,b){if(0>b.points){d=!1}c+=b.points});d=d&&c>=b;return d};return e});
-//# sourceMappingURL=competency_rule_points.min.js.map
+/**
+ * Competency rule points module.
+ *
+ * @module tool_lp/competency_rule_all
+ * @copyright 2015 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/competency_rule_points",["jquery","core/str","core/templates","tool_lp/competency_rule"],(function($,Str,Templates,RuleBase){var Rule=function(){RuleBase.apply(this,arguments)};return(Rule.prototype=Object.create(RuleBase.prototype))._container=null,Rule.prototype._templateLoaded=!1,Rule.prototype.getConfig=function(){return JSON.stringify({base:{points:this._getRequiredPoints()},competencies:this._getCompetenciesConfig()})},Rule.prototype._getCompetenciesConfig=function(){var competencies=[];return this._container.find("[data-competency]").each((function(){var node=$(this),id=node.data("competency"),points=parseInt(node.find('[name="points"]').val(),10),required=node.find('[name="required"]').prop("checked");competencies.push({id:id,points:points,required:required?1:0})})),competencies},Rule.prototype._getRequiredPoints=function(){return parseInt(this._container.find('[name="requiredpoints"]').val()||1,10)},Rule.prototype.getType=function(){return"core_competency\\competency_rule_points"},Rule.prototype.injectTemplate=function(container){var context,self=this,children=this._tree.getChildren(this._competency.id),config={base:{points:2},competencies:[]};if(this._templateLoaded=!1,self._competency.ruletype==self.getType())try{config=JSON.parse(self._competency.ruleconfig)}catch(e){}return context={requiredpoints:config&&config.base?config.base.points:2,competency:self._competency,children:[]},$.each(children,(function(index,child){var competency={id:child.id,shortname:child.shortname,required:!1,points:0};config&&$.each(config.competencies,(function(index,comp){comp.id==competency.id&&(competency.required=!!comp.required,competency.points=comp.points)})),context.children.push(competency)})),Templates.render("tool_lp/competency_rule_points",context).then((function(html){self._container=container,container.html(html),container.find("input").change((function(){self._triggerChange()})),self._templateLoaded=!0,self._triggerChange()}))},Rule.prototype.isValid=function(){if(!this._templateLoaded)return!1;var required=this._getRequiredPoints(),max=0,valid=!0;return $.each(this._getCompetenciesConfig(),(function(index,competency){competency.points<0&&(valid=!1),max+=competency.points})),valid=valid&&max>=required},Rule}));
+
+//# sourceMappingURL=competency_rule_points.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competency_rule_points.min.js.map b/admin/tool/lp/amd/build/competency_rule_points.min.js.map
index 0402a73f950..d3583f13916 100644
--- a/admin/tool/lp/amd/build/competency_rule_points.min.js.map
+++ b/admin/tool/lp/amd/build/competency_rule_points.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/competency_rule_points.js"],"names":["define","$","Str","Templates","RuleBase","Rule","apply","arguments","prototype","Object","create","_container","_templateLoaded","getConfig","JSON","stringify","base","points","_getRequiredPoints","competencies","_getCompetenciesConfig","find","each","node","id","data","parseInt","val","required","prop","push","getType","injectTemplate","container","self","children","_tree","getChildren","_competency","context","config","ruletype","parse","ruleconfig","e","requiredpoints","competency","index","child","shortname","comp","render","then","html","change","_triggerChange","isValid","max","valid"],"mappings":"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","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 .\n\n/**\n * Competency rule points module.\n *\n * @module tool_lp/competency_rule_all\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/str',\n 'core/templates',\n 'tool_lp/competency_rule',\n ],\n function($, Str, Templates, RuleBase) {\n\n /**\n * Competency rule points class.\n */\n var Rule = function() {\n RuleBase.apply(this, arguments);\n };\n Rule.prototype = Object.create(RuleBase.prototype);\n\n /** @property {Node} Reference to the container in which the template was included. */\n Rule.prototype._container = null;\n /** @property {Boolean} Whether or not the template was included. */\n Rule.prototype._templateLoaded = false;\n\n /**\n * The config established by this rule.\n *\n * @return {String}\n * @method getConfig\n */\n Rule.prototype.getConfig = function() {\n return JSON.stringify({\n base: {\n points: this._getRequiredPoints(),\n },\n competencies: this._getCompetenciesConfig()\n });\n };\n\n /**\n * Gathers the input provided by the user for competencies.\n *\n * @return {Array} Containing id, points and required.\n * @method _getCompetenciesConfig\n * @protected\n */\n Rule.prototype._getCompetenciesConfig = function() {\n var competencies = [];\n\n this._container.find('[data-competency]').each(function() {\n var node = $(this),\n id = node.data('competency'),\n points = parseInt(node.find('[name=\"points\"]').val(), 10),\n required = node.find('[name=\"required\"]').prop('checked');\n\n competencies.push({\n id: id,\n points: points,\n required: required ? 1 : 0\n });\n });\n\n return competencies;\n };\n\n /**\n * Fetches the required points set by the user.\n *\n * @return {Number}\n * @method _getRequiredPoints\n * @protected\n */\n Rule.prototype._getRequiredPoints = function() {\n return parseInt(this._container.find('[name=\"requiredpoints\"]').val() || 1, 10);\n };\n\n /**\n * Return the type of the module.\n *\n * @return {String}\n * @method getType\n */\n Rule.prototype.getType = function() {\n return 'core_competency\\\\competency_rule_points';\n };\n\n /**\n * Callback to inject the template.\n *\n * @param {Node} container Node to inject in.\n * @return {Promise} Resolved when done.\n * @method injectTemplate\n */\n Rule.prototype.injectTemplate = function(container) {\n var self = this,\n children = this._tree.getChildren(this._competency.id),\n context,\n config = {\n base: {points: 2},\n competencies: []\n };\n\n this._templateLoaded = false;\n\n // Only pre-load the configuration when the competency is using this rule.\n if (self._competency.ruletype == self.getType()) {\n try {\n config = JSON.parse(self._competency.ruleconfig);\n } catch (e) {\n // eslint-disable-line no-empty\n }\n }\n\n context = {\n requiredpoints: (config && config.base) ? config.base.points : 2,\n competency: self._competency,\n children: []\n };\n\n $.each(children, function(index, child) {\n var competency = {\n id: child.id,\n shortname: child.shortname,\n required: false,\n points: 0\n };\n\n if (config) {\n $.each(config.competencies, function(index, comp) {\n if (comp.id == competency.id) {\n competency.required = comp.required ? true : false;\n competency.points = comp.points;\n }\n });\n }\n\n context.children.push(competency);\n });\n\n return Templates.render('tool_lp/competency_rule_points', context).then(function(html) {\n self._container = container;\n container.html(html);\n container.find('input').change(function() {\n self._triggerChange();\n });\n\n // We're done, let's trigger a change.\n self._templateLoaded = true;\n self._triggerChange();\n return;\n });\n };\n\n /**\n * Whether or not the current config is valid.\n *\n * @return {Boolean}\n * @method isValid\n */\n Rule.prototype.isValid = function() {\n if (!this._templateLoaded) {\n return false;\n }\n\n var required = this._getRequiredPoints(),\n max = 0,\n valid = true;\n\n $.each(this._getCompetenciesConfig(), function(index, competency) {\n if (competency.points < 0) {\n valid = false;\n }\n max += competency.points;\n });\n\n valid = valid && max >= required;\n return valid;\n };\n\n return Rule;\n});\n"],"file":"competency_rule_points.min.js"}
\ No newline at end of file
+{"version":3,"file":"competency_rule_points.min.js","sources":["../src/competency_rule_points.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 .\n\n/**\n * Competency rule points module.\n *\n * @module tool_lp/competency_rule_all\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/str',\n 'core/templates',\n 'tool_lp/competency_rule',\n ],\n function($, Str, Templates, RuleBase) {\n\n /**\n * Competency rule points class.\n */\n var Rule = function() {\n RuleBase.apply(this, arguments);\n };\n Rule.prototype = Object.create(RuleBase.prototype);\n\n /** @property {Node} Reference to the container in which the template was included. */\n Rule.prototype._container = null;\n /** @property {Boolean} Whether or not the template was included. */\n Rule.prototype._templateLoaded = false;\n\n /**\n * The config established by this rule.\n *\n * @return {String}\n * @method getConfig\n */\n Rule.prototype.getConfig = function() {\n return JSON.stringify({\n base: {\n points: this._getRequiredPoints(),\n },\n competencies: this._getCompetenciesConfig()\n });\n };\n\n /**\n * Gathers the input provided by the user for competencies.\n *\n * @return {Array} Containing id, points and required.\n * @method _getCompetenciesConfig\n * @protected\n */\n Rule.prototype._getCompetenciesConfig = function() {\n var competencies = [];\n\n this._container.find('[data-competency]').each(function() {\n var node = $(this),\n id = node.data('competency'),\n points = parseInt(node.find('[name=\"points\"]').val(), 10),\n required = node.find('[name=\"required\"]').prop('checked');\n\n competencies.push({\n id: id,\n points: points,\n required: required ? 1 : 0\n });\n });\n\n return competencies;\n };\n\n /**\n * Fetches the required points set by the user.\n *\n * @return {Number}\n * @method _getRequiredPoints\n * @protected\n */\n Rule.prototype._getRequiredPoints = function() {\n return parseInt(this._container.find('[name=\"requiredpoints\"]').val() || 1, 10);\n };\n\n /**\n * Return the type of the module.\n *\n * @return {String}\n * @method getType\n */\n Rule.prototype.getType = function() {\n return 'core_competency\\\\competency_rule_points';\n };\n\n /**\n * Callback to inject the template.\n *\n * @param {Node} container Node to inject in.\n * @return {Promise} Resolved when done.\n * @method injectTemplate\n */\n Rule.prototype.injectTemplate = function(container) {\n var self = this,\n children = this._tree.getChildren(this._competency.id),\n context,\n config = {\n base: {points: 2},\n competencies: []\n };\n\n this._templateLoaded = false;\n\n // Only pre-load the configuration when the competency is using this rule.\n if (self._competency.ruletype == self.getType()) {\n try {\n config = JSON.parse(self._competency.ruleconfig);\n } catch (e) {\n // eslint-disable-line no-empty\n }\n }\n\n context = {\n requiredpoints: (config && config.base) ? config.base.points : 2,\n competency: self._competency,\n children: []\n };\n\n $.each(children, function(index, child) {\n var competency = {\n id: child.id,\n shortname: child.shortname,\n required: false,\n points: 0\n };\n\n if (config) {\n $.each(config.competencies, function(index, comp) {\n if (comp.id == competency.id) {\n competency.required = comp.required ? true : false;\n competency.points = comp.points;\n }\n });\n }\n\n context.children.push(competency);\n });\n\n return Templates.render('tool_lp/competency_rule_points', context).then(function(html) {\n self._container = container;\n container.html(html);\n container.find('input').change(function() {\n self._triggerChange();\n });\n\n // We're done, let's trigger a change.\n self._templateLoaded = true;\n self._triggerChange();\n return;\n });\n };\n\n /**\n * Whether or not the current config is valid.\n *\n * @return {Boolean}\n * @method isValid\n */\n Rule.prototype.isValid = function() {\n if (!this._templateLoaded) {\n return false;\n }\n\n var required = this._getRequiredPoints(),\n max = 0,\n valid = true;\n\n $.each(this._getCompetenciesConfig(), function(index, competency) {\n if (competency.points < 0) {\n valid = false;\n }\n max += competency.points;\n });\n\n valid = valid && max >= required;\n return valid;\n };\n\n return Rule;\n});\n"],"names":["define","$","Str","Templates","RuleBase","Rule","apply","this","arguments","prototype","Object","create","_container","_templateLoaded","getConfig","JSON","stringify","base","points","_getRequiredPoints","competencies","_getCompetenciesConfig","find","each","node","id","data","parseInt","val","required","prop","push","getType","injectTemplate","container","context","self","children","_tree","getChildren","_competency","config","ruletype","parse","ruleconfig","e","requiredpoints","competency","index","child","shortname","comp","render","then","html","change","_triggerChange","isValid","max","valid"],"mappings":";;;;;;;AAuBAA,wCAAO,CAAC,SACA,WACA,iBACA,4BAEA,SAASC,EAAGC,IAAKC,UAAWC,cAK5BC,KAAO,WACPD,SAASE,MAAMC,KAAMC,mBAEzBH,KAAKI,UAAYC,OAAOC,OAAOP,SAASK,YAGzBG,WAAa,KAE5BP,KAAKI,UAAUI,iBAAkB,EAQjCR,KAAKI,UAAUK,UAAY,kBAChBC,KAAKC,UAAU,CAClBC,KAAM,CACFC,OAAQX,KAAKY,sBAEjBC,aAAcb,KAAKc,4BAW3BhB,KAAKI,UAAUY,uBAAyB,eAChCD,aAAe,eAEdR,WAAWU,KAAK,qBAAqBC,MAAK,eACvCC,KAAOvB,EAAEM,MACTkB,GAAKD,KAAKE,KAAK,cACfR,OAASS,SAASH,KAAKF,KAAK,mBAAmBM,MAAO,IACtDC,SAAWL,KAAKF,KAAK,qBAAqBQ,KAAK,WAEnDV,aAAaW,KAAK,CACdN,GAAIA,GACJP,OAAQA,OACRW,SAAUA,SAAW,EAAI,OAI1BT,cAUXf,KAAKI,UAAUU,mBAAqB,kBACzBQ,SAASpB,KAAKK,WAAWU,KAAK,2BAA2BM,OAAS,EAAG,KAShFvB,KAAKI,UAAUuB,QAAU,iBACd,2CAUX3B,KAAKI,UAAUwB,eAAiB,SAASC,eAGjCC,QAFAC,KAAO7B,KACP8B,SAAW9B,KAAK+B,MAAMC,YAAYhC,KAAKiC,YAAYf,IAEnDgB,OAAS,CACLxB,KAAM,CAACC,OAAQ,GACfE,aAAc,YAGjBP,iBAAkB,EAGnBuB,KAAKI,YAAYE,UAAYN,KAAKJ,cAE9BS,OAAS1B,KAAK4B,MAAMP,KAAKI,YAAYI,YACvC,MAAOC,WAKbV,QAAU,CACNW,eAAiBL,QAAUA,OAAOxB,KAAQwB,OAAOxB,KAAKC,OAAS,EAC/D6B,WAAYX,KAAKI,YACjBH,SAAU,IAGdpC,EAAEsB,KAAKc,UAAU,SAASW,MAAOC,WACzBF,WAAa,CACbtB,GAAIwB,MAAMxB,GACVyB,UAAWD,MAAMC,UACjBrB,UAAU,EACVX,OAAQ,GAGRuB,QACAxC,EAAEsB,KAAKkB,OAAOrB,cAAc,SAAS4B,MAAOG,MACpCA,KAAK1B,IAAMsB,WAAWtB,KACtBsB,WAAWlB,WAAWsB,KAAKtB,SAC3BkB,WAAW7B,OAASiC,KAAKjC,WAKrCiB,QAAQE,SAASN,KAAKgB,eAGnB5C,UAAUiD,OAAO,iCAAkCjB,SAASkB,MAAK,SAASC,MAC7ElB,KAAKxB,WAAasB,UAClBA,UAAUoB,KAAKA,MACfpB,UAAUZ,KAAK,SAASiC,QAAO,WAC3BnB,KAAKoB,oBAITpB,KAAKvB,iBAAkB,EACvBuB,KAAKoB,qBAWbnD,KAAKI,UAAUgD,QAAU,eAChBlD,KAAKM,uBACC,MAGPgB,SAAWtB,KAAKY,qBAChBuC,IAAM,EACNC,OAAQ,SAEZ1D,EAAEsB,KAAKhB,KAAKc,0BAA0B,SAAS2B,MAAOD,YAC9CA,WAAW7B,OAAS,IACpByC,OAAQ,GAEZD,KAAOX,WAAW7B,UAGtByC,MAAQA,OAASD,KAAO7B,UAIrBxB"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencyactions.min.js b/admin/tool/lp/amd/build/competencyactions.min.js
index 838c6249d6a..030afdb723b 100644
--- a/admin/tool/lp/amd/build/competencyactions.min.js
+++ b/admin/tool/lp/amd/build/competencyactions.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/competencyactions",["jquery","core/url","core/templates","core/notification","core/str","core/ajax","tool_lp/dragdrop-reorder","tool_lp/tree","tool_lp/dialogue","tool_lp/menubar","tool_lp/competencypicker","tool_lp/competency_outcomes","tool_lp/competencyruleconfig","core/pending"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n){var o=null,p=null,q=null,r,s,t,u,v,w,x=null,y=function(){var c=a("[data-region=\"competencyactions\"]").data("competency"),f={competencyframeworkid:o.getCompetencyFrameworkId(),pagecontextid:r};if(null!==c){f.parentid=c.id}var g=function(){var c=a.param(f);window.location=b.relativeUrl("/admin/tool/lp/editcompetency.php?"+c)};if(null!==c&&o.hasRule(c.id)){e.get_strings([{key:"confirm",component:"moodle"},{key:"addingcompetencywillresetparentrule",component:"tool_lp",param:c.shortname},{key:"yes",component:"core"},{key:"no",component:"core"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],g)}).fail(d.exception)}else{g()}},z=function(){var b=a("[data-region=\"filtercompetencies\"]").data("frameworkid"),c=f.call([{methodname:"core_competency_set_parent_competency",args:{competencyid:p,parentid:q}},{methodname:"tool_lp_data_for_competencies_manage_page",args:{competencyframeworkid:b,search:a("[data-region=\"filtercompetencies\"] input").val()}}]);c[1].done(F).fail(d.exception)},A=function(){q="undefined"==typeof q?0:q;if(q==p){return}var a=o.getCompetency(q)||{},b=o.getCompetency(p)||{},c="movecompetencywillresetrules",f=!1;if(b.parentid==q){return}if(a.path&&0<=a.path.indexOf("/"+b.id+"/")){c="movecompetencytochildofselfwillresetrules";f=f||o.hasRule(b.id)}f=f||o.hasRule(a.id)||o.hasRule(b.parentid);if(f){e.get_strings([{key:"confirm",component:"moodle"},{key:c,component:"tool_lp"},{key:"yes",component:"moodle"},{key:"no",component:"moodle"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],z)}).fail(d.exception)}else{z()}},B=function(b){var c=a(b.getContent()),d=c.find("[data-enhance=movetree]"),e=new h(d,!1);e.on("selectionchanged",function(b,c){var d=c.selected;q=a(d).data("id")});d.show();c.on("click","[data-action=\"move\"]",function(){b.close();A()});c.on("click","[data-action=\"cancel\"]",function(){b.close()})},C=function(a,b){var c;for(c=0;cspan",P).on("dragover","li>span",Q).on("dragenter","li>span",R).on("dragleave","li>span",S).on("drop","li>span",T);b.on("selectionchanged",_);t=new m(o,w);t.on("save",M.bind(this))}}});
-//# sourceMappingURL=competencyactions.min.js.map
+/**
+ * Handle selection changes and actions on the competency tree.
+ *
+ * @module tool_lp/competencyactions
+ * @copyright 2015 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/competencyactions",["jquery","core/url","core/templates","core/notification","core/str","core/ajax","tool_lp/dragdrop-reorder","tool_lp/tree","tool_lp/dialogue","tool_lp/menubar","tool_lp/competencypicker","tool_lp/competency_outcomes","tool_lp/competencyruleconfig","core/pending"],(function($,url,templates,notification,str,ajax,dragdrop,Ariatree,Dialogue,menubar,Picker,Outcomes,RuleConfig,Pending){var pageContextId,pickerInstance,ruleConfigInstance,relatedTarget,taxonomiesConstants,rulesModules,treeModel=null,moveSource=null,moveTarget=null,selectedCompetencyId=null,addHandler=function(){var parent=$('[data-region="competencyactions"]').data("competency"),params={competencyframeworkid:treeModel.getCompetencyFrameworkId(),pagecontextid:pageContextId};null!==parent&&(params.parentid=parent.id);var relocate=function(){var queryparams=$.param(params);window.location=url.relativeUrl("/admin/tool/lp/editcompetency.php?"+queryparams)};null!==parent&&treeModel.hasRule(parent.id)?str.get_strings([{key:"confirm",component:"moodle"},{key:"addingcompetencywillresetparentrule",component:"tool_lp",param:parent.shortname},{key:"yes",component:"core"},{key:"no",component:"core"}]).done((function(strings){notification.confirm(strings[0],strings[1],strings[2],strings[3],relocate)})).fail(notification.exception):relocate()},doMove=function(){var frameworkid=$('[data-region="filtercompetencies"]').data("frameworkid");ajax.call([{methodname:"core_competency_set_parent_competency",args:{competencyid:moveSource,parentid:moveTarget}},{methodname:"tool_lp_data_for_competencies_manage_page",args:{competencyframeworkid:frameworkid,search:$('[data-region="filtercompetencies"] input').val()}}])[1].done(reloadPage).fail(notification.exception)},confirmMove=function(){if((moveTarget=void 0===moveTarget?0:moveTarget)!=moveSource){var targetComp=treeModel.getCompetency(moveTarget)||{},sourceComp=treeModel.getCompetency(moveSource)||{},confirmMessage="movecompetencywillresetrules",showConfirm=!1;sourceComp.parentid!=moveTarget&&(targetComp.path&&targetComp.path.indexOf("/"+sourceComp.id+"/")>=0&&(confirmMessage="movecompetencytochildofselfwillresetrules",showConfirm=showConfirm||treeModel.hasRule(sourceComp.id)),(showConfirm=showConfirm||treeModel.hasRule(targetComp.id)||treeModel.hasRule(sourceComp.parentid))?str.get_strings([{key:"confirm",component:"moodle"},{key:confirmMessage,component:"tool_lp"},{key:"yes",component:"moodle"},{key:"no",component:"moodle"}]).done((function(strings){notification.confirm(strings[0],strings[1],strings[2],strings[3],doMove)})).fail(notification.exception):doMove())}},initMovePopup=function(popup){var body=$(popup.getContent()),treeRoot=body.find("[data-enhance=movetree]");new Ariatree(treeRoot,!1).on("selectionchanged",(function(evt,params){var target=params.selected;moveTarget=$(target).data("id")})),treeRoot.show(),body.on("click",'[data-action="move"]',(function(){popup.close(),confirmMove()})),body.on("click",'[data-action="cancel"]',(function(){popup.close()}))},addCompetencyChildren=function(parent,competencies){var i;for(i=0;ispan",dragStart).on("dragover","li>span",allowDrop).on("dragenter","li>span",dragEnter).on("dragleave","li>span",dragLeave).on("drop","li>span",dropOver),model.on("selectionchanged",selectionChanged),(ruleConfigInstance=new RuleConfig(treeModel,rulesModules)).on("save",ruleConfigSaveHandler.bind(this))}}}));
+
+//# sourceMappingURL=competencyactions.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencyactions.min.js.map b/admin/tool/lp/amd/build/competencyactions.min.js.map
index 34dffce4b06..aeac60ed8e9 100644
--- a/admin/tool/lp/amd/build/competencyactions.min.js.map
+++ b/admin/tool/lp/amd/build/competencyactions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/competencyactions.js"],"names":["define","$","url","templates","notification","str","ajax","dragdrop","Ariatree","Dialogue","menubar","Picker","Outcomes","RuleConfig","Pending","treeModel","moveSource","moveTarget","pageContextId","pickerInstance","ruleConfigInstance","relatedTarget","taxonomiesConstants","rulesModules","selectedCompetencyId","addHandler","parent","data","params","competencyframeworkid","getCompetencyFrameworkId","pagecontextid","parentid","id","relocate","queryparams","param","window","location","relativeUrl","hasRule","get_strings","key","component","shortname","done","strings","confirm","fail","exception","doMove","frameworkid","requests","call","methodname","args","competencyid","search","val","reloadPage","confirmMove","targetComp","getCompetency","sourceComp","confirmMessage","showConfirm","path","indexOf","initMovePopup","popup","body","getContent","treeRoot","find","tree","on","evt","target","selected","show","close","addCompetencyChildren","competencies","i","length","haschildren","children","moveHandler","e","preventDefault","competency","searchtext","when","apply","framework","competenciestree","onecompetency","render","editHandler","context","newhtml","newjs","replaceWith","runTemplateJS","updateSearchHandler","moveUpHandler","moveDownHandler","seeCoursesHandler","courses","html","get_string","linkedcourses","relateCompetenciesHandler","pendingPromise","compIds","competencyIds","calls","each","index","value","push","relatedcompetencyid","promises","then","js","updatedRelatedCompetencies","resolve","catch","setDisallowedCompetencyIDs","display","ruleConfigHandler","setTargetCompetencyId","ruleConfigSaveHandler","config","update","idnumber","description","descriptionformat","ruletype","ruleoutcome","ruleconfig","promise","result","renderCompetencySummary","doDelete","success","alert","deleteCompetencyHandler","dragStart","originalEvent","dataTransfer","setData","allowDrop","dropEffect","dragEnter","addClass","dragLeave","removeClass","dropOver","getData","deleteRelatedHandler","relatedid","substr","removeRelated","triggerCompetencyViewedEvent","getTaxonomyAtLevel","level","constant","Deferred","showdeleterelatedaction","showrelatedcompetencies","showrule","pluginbaseurl","NONE","getString","name","modInfo","type","strs","rule","outcome","replaceNodeContents","strAddTaxonomy","strSelectedTaxonomy","selectionChanged","node","btn","actionMenu","selectedTitle","sublevel","closeAll","clone","remove","end","text","hide","getCompetencyLevel","parseTaxonomies","taxonomiesstr","all","split","unshift","init","model","pagectxid","taxonomies","rulesMods","enhance","bind","top"],"mappings":"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","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 .\n\n/**\n * Handle selection changes and actions on the competency tree.\n *\n * @module tool_lp/competencyactions\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/url',\n 'core/templates',\n 'core/notification',\n 'core/str',\n 'core/ajax',\n 'tool_lp/dragdrop-reorder',\n 'tool_lp/tree',\n 'tool_lp/dialogue',\n 'tool_lp/menubar',\n 'tool_lp/competencypicker',\n 'tool_lp/competency_outcomes',\n 'tool_lp/competencyruleconfig',\n 'core/pending',\n ],\n function(\n $, url, templates, notification, str, ajax, dragdrop, Ariatree, Dialogue, menubar, Picker, Outcomes, RuleConfig, Pending\n ) {\n\n // Private variables and functions.\n /** @var {Object} treeModel - This is an object representing the nodes in the tree. */\n var treeModel = null;\n /** @var {Node} moveSource - The start of a drag operation */\n var moveSource = null;\n /** @var {Node} moveTarget - The end of a drag operation */\n var moveTarget = null;\n /** @var {Number} pageContextId The page context ID. */\n var pageContextId;\n /** @var {Object} Picker instance. */\n var pickerInstance;\n /** @var {Object} Rule config instance. */\n var ruleConfigInstance;\n /** @var {Object} The competency we're picking a relation to. */\n var relatedTarget;\n /** @var {Object} Taxonomy constants indexed per level. */\n var taxonomiesConstants;\n /** @var {Array} The rules modules. Values are object containing type, namd and amd. */\n var rulesModules;\n /** @var {Number} the selected competency ID. */\n var selectedCompetencyId = null;\n\n /**\n * Respond to choosing the \"Add\" menu item for the selected node in the tree.\n * @method addHandler\n */\n var addHandler = function() {\n var parent = $('[data-region=\"competencyactions\"]').data('competency');\n\n var params = {\n competencyframeworkid: treeModel.getCompetencyFrameworkId(),\n pagecontextid: pageContextId\n };\n\n if (parent !== null) {\n // We are adding at a sub node.\n params.parentid = parent.id;\n }\n\n var relocate = function() {\n var queryparams = $.param(params);\n window.location = url.relativeUrl('/admin/tool/lp/editcompetency.php?' + queryparams);\n };\n\n if (parent !== null && treeModel.hasRule(parent.id)) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'addingcompetencywillresetparentrule', component: 'tool_lp', param: parent.shortname},\n {key: 'yes', component: 'core'},\n {key: 'no', component: 'core'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0],\n strings[1],\n strings[2],\n strings[3],\n relocate\n );\n }).fail(notification.exception);\n } else {\n relocate();\n }\n };\n\n /**\n * A source and destination has been chosen - so time to complete a move.\n * @method doMove\n */\n var doMove = function() {\n var frameworkid = $('[data-region=\"filtercompetencies\"]').data('frameworkid');\n var requests = ajax.call([{\n methodname: 'core_competency_set_parent_competency',\n args: {competencyid: moveSource, parentid: moveTarget}\n }, {\n methodname: 'tool_lp_data_for_competencies_manage_page',\n args: {competencyframeworkid: frameworkid,\n search: $('[data-region=\"filtercompetencies\"] input').val()}\n }]);\n requests[1].done(reloadPage).fail(notification.exception);\n };\n\n /**\n * Confirms a competency move.\n *\n * @method confirmMove\n */\n var confirmMove = function() {\n moveTarget = typeof moveTarget === \"undefined\" ? 0 : moveTarget;\n if (moveTarget == moveSource) {\n // No move to do.\n return;\n }\n\n var targetComp = treeModel.getCompetency(moveTarget) || {},\n sourceComp = treeModel.getCompetency(moveSource) || {},\n confirmMessage = 'movecompetencywillresetrules',\n showConfirm = false;\n\n // We shouldn't be moving the competency to the same parent.\n if (sourceComp.parentid == moveTarget) {\n return;\n }\n\n // If we are moving to a child of self.\n if (targetComp.path && targetComp.path.indexOf('/' + sourceComp.id + '/') >= 0) {\n confirmMessage = 'movecompetencytochildofselfwillresetrules';\n\n // Show a confirmation if self has rules, as they'll disappear.\n showConfirm = showConfirm || treeModel.hasRule(sourceComp.id);\n }\n\n // Show a confirmation if the current parent, or the destination have rules.\n showConfirm = showConfirm || (treeModel.hasRule(targetComp.id) || treeModel.hasRule(sourceComp.parentid));\n\n // Show confirm, and/or do the things.\n if (showConfirm) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: confirmMessage, component: 'tool_lp'},\n {key: 'yes', component: 'moodle'},\n {key: 'no', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Delete competency X?\n strings[2], // Delete.\n strings[3], // Cancel.\n doMove\n );\n }).fail(notification.exception);\n\n } else {\n doMove();\n }\n };\n\n /**\n * A move competency popup was opened - initialise the aria tree in it.\n * @method initMovePopup\n * @param {dialogue} popup The tool_lp/dialogue that was created.\n */\n var initMovePopup = function(popup) {\n var body = $(popup.getContent());\n var treeRoot = body.find('[data-enhance=movetree]');\n var tree = new Ariatree(treeRoot, false);\n tree.on('selectionchanged', function(evt, params) {\n var target = params.selected;\n moveTarget = $(target).data('id');\n });\n treeRoot.show();\n\n body.on('click', '[data-action=\"move\"]', function() {\n popup.close();\n confirmMove();\n });\n body.on('click', '[data-action=\"cancel\"]', function() {\n popup.close();\n });\n };\n\n /**\n * Turn a flat list of competencies into a tree structure (recursive).\n * @method addCompetencyChildren\n * @param {Object} parent The current parent node in the tree\n * @param {Object[]} competencies The flat list of competencies\n */\n var addCompetencyChildren = function(parent, competencies) {\n var i;\n\n for (i = 0; i < competencies.length; i++) {\n if (competencies[i].parentid == parent.id) {\n parent.haschildren = true;\n competencies[i].children = [];\n competencies[i].haschildren = false;\n parent.children[parent.children.length] = competencies[i];\n addCompetencyChildren(competencies[i], competencies);\n }\n }\n };\n\n /**\n * A node was chosen and \"Move\" was selected from the menu. Open a popup to select the target.\n * @param {Event} e\n * @method moveHandler\n */\n var moveHandler = function(e) {\n e.preventDefault();\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n\n // Remember what we are moving.\n moveSource = competency.id;\n\n // Load data for the template.\n var requests = ajax.call([\n {\n methodname: 'core_competency_search_competencies',\n args: {\n competencyframeworkid: competency.competencyframeworkid,\n searchtext: ''\n }\n }, {\n methodname: 'core_competency_read_competency_framework',\n args: {\n id: competency.competencyframeworkid\n }\n }\n ]);\n\n // When all data has arrived, continue.\n $.when.apply(null, requests).done(function(competencies, framework) {\n\n // Expand the list of competencies into a tree.\n var i;\n var competenciestree = [];\n for (i = 0; i < competencies.length; i++) {\n var onecompetency = competencies[i];\n if (onecompetency.parentid == \"0\") {\n onecompetency.children = [];\n onecompetency.haschildren = 0;\n competenciestree[competenciestree.length] = onecompetency;\n addCompetencyChildren(onecompetency, competencies);\n }\n }\n\n str.get_strings([\n {key: 'movecompetency', component: 'tool_lp', param: competency.shortname},\n {key: 'move', component: 'tool_lp'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n\n var context = {\n framework: framework,\n competencies: competenciestree\n };\n\n templates.render('tool_lp/competencies_move_tree', context)\n .done(function(tree) {\n new Dialogue(\n strings[0], // Move competency x.\n tree, // The move tree.\n initMovePopup\n );\n\n }).fail(notification.exception);\n\n }).fail(notification.exception);\n\n }).fail(notification.exception);\n\n };\n\n /**\n * Edit the selected competency.\n * @method editHandler\n */\n var editHandler = function() {\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n\n var params = {\n competencyframeworkid: treeModel.getCompetencyFrameworkId(),\n id: competency.id,\n parentid: competency.parentid,\n pagecontextid: pageContextId\n };\n\n var queryparams = $.param(params);\n window.location = url.relativeUrl('/admin/tool/lp/editcompetency.php?' + queryparams);\n };\n\n /**\n * Re-render the page with the latest data.\n * @param {Object} context\n * @method reloadPage\n */\n var reloadPage = function(context) {\n templates.render('tool_lp/manage_competencies_page', context)\n .done(function(newhtml, newjs) {\n $('[data-region=\"managecompetencies\"]').replaceWith(newhtml);\n templates.runTemplateJS(newjs);\n })\n .fail(notification.exception);\n };\n\n /**\n * Perform a search and render the page with the new search results.\n * @param {Event} e\n * @method updateSearchHandler\n */\n var updateSearchHandler = function(e) {\n e.preventDefault();\n\n var frameworkid = $('[data-region=\"filtercompetencies\"]').data('frameworkid');\n\n var requests = ajax.call([{\n methodname: 'tool_lp_data_for_competencies_manage_page',\n args: {competencyframeworkid: frameworkid,\n search: $('[data-region=\"filtercompetencies\"] input').val()}\n }]);\n requests[0].done(reloadPage).fail(notification.exception);\n };\n\n /**\n * Move a competency \"up\". This only affects the sort order within the same branch of the tree.\n * @method moveUpHandler\n */\n var moveUpHandler = function() {\n // We are chaining ajax requests here.\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n var requests = ajax.call([{\n methodname: 'core_competency_move_up_competency',\n args: {id: competency.id}\n }, {\n methodname: 'tool_lp_data_for_competencies_manage_page',\n args: {competencyframeworkid: competency.competencyframeworkid,\n search: $('[data-region=\"filtercompetencies\"] input').val()}\n }]);\n requests[1].done(reloadPage).fail(notification.exception);\n };\n\n /**\n * Move a competency \"down\". This only affects the sort order within the same branch of the tree.\n * @method moveDownHandler\n */\n var moveDownHandler = function() {\n // We are chaining ajax requests here.\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n var requests = ajax.call([{\n methodname: 'core_competency_move_down_competency',\n args: {id: competency.id}\n }, {\n methodname: 'tool_lp_data_for_competencies_manage_page',\n args: {competencyframeworkid: competency.competencyframeworkid,\n search: $('[data-region=\"filtercompetencies\"] input').val()}\n }]);\n requests[1].done(reloadPage).fail(notification.exception);\n };\n\n /**\n * Open a dialogue to show all the courses using the selected competency.\n * @method seeCoursesHandler\n */\n var seeCoursesHandler = function() {\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n\n var requests = ajax.call([{\n methodname: 'tool_lp_list_courses_using_competency',\n args: {id: competency.id}\n }]);\n\n requests[0].done(function(courses) {\n var context = {\n courses: courses\n };\n templates.render('tool_lp/linked_courses_summary', context).done(function(html) {\n str.get_string('linkedcourses', 'tool_lp').done(function(linkedcourses) {\n new Dialogue(\n linkedcourses, // Title.\n html, // The linked courses.\n initMovePopup\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Open a competencies popup to relate competencies.\n *\n * @method relateCompetenciesHandler\n */\n var relateCompetenciesHandler = function() {\n relatedTarget = $('[data-region=\"competencyactions\"]').data('competency');\n\n if (!pickerInstance) {\n pickerInstance = new Picker(pageContextId, relatedTarget.competencyframeworkid);\n pickerInstance.on('save', function(e, data) {\n var pendingPromise = new Pending();\n var compIds = data.competencyIds;\n\n var calls = [];\n $.each(compIds, function(index, value) {\n calls.push({\n methodname: 'core_competency_add_related_competency',\n args: {competencyid: value, relatedcompetencyid: relatedTarget.id}\n });\n });\n\n calls.push({\n methodname: 'tool_lp_data_for_related_competencies_section',\n args: {competencyid: relatedTarget.id}\n });\n\n var promises = ajax.call(calls);\n\n promises[calls.length - 1].then(function(context) {\n return templates.render('tool_lp/related_competencies', context);\n }).then(function(html, js) {\n $('[data-region=\"relatedcompetencies\"]').replaceWith(html);\n templates.runTemplateJS(js);\n updatedRelatedCompetencies();\n return;\n })\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n });\n }\n\n pickerInstance.setDisallowedCompetencyIDs([relatedTarget.id]);\n pickerInstance.display();\n };\n\n var ruleConfigHandler = function(e) {\n e.preventDefault();\n relatedTarget = $('[data-region=\"competencyactions\"]').data('competency');\n ruleConfigInstance.setTargetCompetencyId(relatedTarget.id);\n ruleConfigInstance.display();\n };\n\n var ruleConfigSaveHandler = function(e, config) {\n var update = {\n id: relatedTarget.id,\n shortname: relatedTarget.shortname,\n idnumber: relatedTarget.idnumber,\n description: relatedTarget.description,\n descriptionformat: relatedTarget.descriptionformat,\n ruletype: config.ruletype,\n ruleoutcome: config.ruleoutcome,\n ruleconfig: config.ruleconfig\n };\n var promise = ajax.call([{\n methodname: 'core_competency_update_competency',\n args: {competency: update}\n }]);\n promise[0].then(function(result) {\n if (result) {\n relatedTarget.ruletype = config.ruletype;\n relatedTarget.ruleoutcome = config.ruleoutcome;\n relatedTarget.ruleconfig = config.ruleconfig;\n renderCompetencySummary(relatedTarget);\n }\n return;\n }).catch(notification.exception);\n };\n\n /**\n * Delete a competency.\n * @method doDelete\n */\n var doDelete = function() {\n // We are chaining ajax requests here.\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n var requests = ajax.call([{\n methodname: 'core_competency_delete_competency',\n args: {id: competency.id}\n }, {\n methodname: 'tool_lp_data_for_competencies_manage_page',\n args: {competencyframeworkid: competency.competencyframeworkid,\n search: $('[data-region=\"filtercompetencies\"] input').val()}\n }]);\n requests[0].done(function(success) {\n if (success === false) {\n str.get_strings([\n {key: 'competencycannotbedeleted', component: 'tool_lp', param: competency.shortname},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.alert(\n null,\n strings[0]\n );\n }).fail(notification.exception);\n }\n }).fail(notification.exception);\n requests[1].done(reloadPage).fail(notification.exception);\n };\n\n /**\n * Show a confirm dialogue before deleting a competency.\n * @method deleteCompetencyHandler\n */\n var deleteCompetencyHandler = function() {\n var competency = $('[data-region=\"competencyactions\"]').data('competency'),\n confirmMessage = 'deletecompetency';\n\n if (treeModel.hasRule(competency.parentid)) {\n confirmMessage = 'deletecompetencyparenthasrule';\n }\n\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: confirmMessage, component: 'tool_lp', param: competency.shortname},\n {key: 'delete', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Delete competency X?\n strings[2], // Delete.\n strings[3], // Cancel.\n doDelete\n );\n }).fail(notification.exception);\n };\n\n /**\n * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).\n * @method dragStart\n * @param {Event} e\n */\n var dragStart = function(e) {\n e.originalEvent.dataTransfer.setData('text', $(e.target).parent().data('id'));\n };\n\n /**\n * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).\n * @method allowDrop\n * @param {Event} e\n */\n var allowDrop = function(e) {\n e.originalEvent.dataTransfer.dropEffect = 'move';\n e.preventDefault();\n };\n\n /**\n * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).\n * @method dragEnter\n * @param {Event} e\n */\n var dragEnter = function(e) {\n e.preventDefault();\n $(this).addClass('currentdragtarget');\n };\n\n /**\n * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).\n * @method dragLeave\n * @param {Event} e\n */\n var dragLeave = function(e) {\n e.preventDefault();\n $(this).removeClass('currentdragtarget');\n };\n\n /**\n * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).\n * @method dropOver\n * @param {Event} e\n */\n var dropOver = function(e) {\n e.preventDefault();\n moveSource = e.originalEvent.dataTransfer.getData('text');\n moveTarget = $(e.target).parent().data('id');\n $(this).removeClass('currentdragtarget');\n\n confirmMove();\n };\n\n /**\n * Deletes a related competency without confirmation.\n *\n * @param {Event} e The event that triggered the action.\n * @method deleteRelatedHandler\n */\n var deleteRelatedHandler = function(e) {\n e.preventDefault();\n\n var relatedid = this.id.substr(11);\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n var removeRelated = ajax.call([\n {methodname: 'core_competency_remove_related_competency',\n args: {relatedcompetencyid: relatedid, competencyid: competency.id}},\n {methodname: 'tool_lp_data_for_related_competencies_section',\n args: {competencyid: competency.id}}\n ]);\n\n removeRelated[1].done(function(context) {\n templates.render('tool_lp/related_competencies', context).done(function(html) {\n $('[data-region=\"relatedcompetencies\"]').replaceWith(html);\n updatedRelatedCompetencies();\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Updates the competencies list (with relations) and add listeners.\n *\n * @method updatedRelatedCompetencies\n */\n var updatedRelatedCompetencies = function() {\n\n // Listeners to newly loaded related competencies.\n $('[data-action=\"deleterelation\"]').on('click', deleteRelatedHandler);\n\n };\n\n /**\n * Log the competency viewed event.\n *\n * @param {Object} competency The competency.\n * @method triggerCompetencyViewedEvent\n */\n var triggerCompetencyViewedEvent = function(competency) {\n if (competency.id !== selectedCompetencyId) {\n // Set the selected competency id.\n selectedCompetencyId = competency.id;\n ajax.call([{\n methodname: 'core_competency_competency_viewed',\n args: {id: competency.id}\n }]);\n }\n };\n\n /**\n * Return the taxonomy constant for a level.\n *\n * @param {Number} level The level.\n * @return {String}\n * @function getTaxonomyAtLevel\n */\n var getTaxonomyAtLevel = function(level) {\n var constant = taxonomiesConstants[level];\n if (!constant) {\n constant = 'competency';\n }\n return constant;\n };\n\n /**\n * Render the competency summary.\n *\n * @param {Object} competency The competency.\n */\n var renderCompetencySummary = function(competency) {\n var promise = $.Deferred().resolve().promise(),\n context = {};\n\n context.competency = competency;\n context.showdeleterelatedaction = true;\n context.showrelatedcompetencies = true;\n context.showrule = false;\n context.pluginbaseurl = url.relativeUrl('/admin/tool/lp');\n\n if (competency.ruleoutcome != Outcomes.NONE) {\n // Get the outcome and rule name.\n promise = Outcomes.getString(competency.ruleoutcome).then(function(str) {\n var name;\n $.each(rulesModules, function(index, modInfo) {\n if (modInfo.type == competency.ruletype) {\n name = modInfo.name;\n }\n });\n return [str, name];\n });\n }\n\n promise.then(function(strs) {\n if (typeof strs !== 'undefined') {\n context.showrule = true;\n context.rule = {\n outcome: strs[0],\n type: strs[1]\n };\n }\n return context;\n }).then(function(context) {\n return templates.render('tool_lp/competency_summary', context);\n }).then(function(html) {\n $('[data-region=\"competencyinfo\"]').html(html);\n $('[data-action=\"deleterelation\"]').on('click', deleteRelatedHandler);\n return templates.render('tool_lp/loading', {});\n }).then(function(html, js) {\n templates.replaceNodeContents('[data-region=\"relatedcompetencies\"]', html, js);\n return ajax.call([{\n methodname: 'tool_lp_data_for_related_competencies_section',\n args: {competencyid: competency.id}\n }])[0];\n }).then(function(context) {\n return templates.render('tool_lp/related_competencies', context);\n }).then(function(html, js) {\n $('[data-region=\"relatedcompetencies\"]').replaceWith(html);\n templates.runTemplateJS(js);\n updatedRelatedCompetencies();\n return;\n }).catch(notification.exception);\n };\n\n /**\n * Return the string \"Add \".\n *\n * @param {Number} level The level.\n * @return {String}\n * @function strAddTaxonomy\n */\n var strAddTaxonomy = function(level) {\n return str.get_string('taxonomy_add_' + getTaxonomyAtLevel(level), 'tool_lp');\n };\n\n /**\n * Return the string \"Selected \".\n *\n * @param {Number} level The level.\n * @return {String}\n * @function strSelectedTaxonomy\n */\n var strSelectedTaxonomy = function(level) {\n return str.get_string('taxonomy_selected_' + getTaxonomyAtLevel(level), 'tool_lp');\n };\n\n /**\n * Handler when a node in the aria tree is selected.\n * @method selectionChanged\n * @param {Event} evt The event that triggered the selection change.\n * @param {Object} params The parameters for the event. Contains a list of selected nodes.\n * @return {Boolean}\n */\n var selectionChanged = function(evt, params) {\n var node = params.selected,\n id = $(node).data('id'),\n btn = $('[data-region=\"competencyactions\"] [data-action=\"add\"]'),\n actionMenu = $('[data-region=\"competencyactionsmenu\"]'),\n selectedTitle = $('[data-region=\"selected-competency\"]'),\n level = 0,\n sublevel = 1;\n\n menubar.closeAll();\n\n if (typeof id === \"undefined\") {\n // Assume this is the root of the tree.\n // Here we are only getting the text from the top of the tree, to do it we clone the tree,\n // remove all children and then call text on the result.\n $('[data-region=\"competencyinfo\"]').html(node.clone().children().remove().end().text());\n $('[data-region=\"competencyactions\"]').data('competency', null);\n actionMenu.hide();\n\n } else {\n var competency = treeModel.getCompetency(id);\n\n level = treeModel.getCompetencyLevel(id);\n sublevel = level + 1;\n\n actionMenu.show();\n $('[data-region=\"competencyactions\"]').data('competency', competency);\n renderCompetencySummary(competency);\n // Log Competency viewed event.\n triggerCompetencyViewedEvent(competency);\n }\n strSelectedTaxonomy(level).then(function(str) {\n selectedTitle.text(str);\n return;\n }).catch(notification.exception);\n\n strAddTaxonomy(sublevel).then(function(str) {\n btn.show()\n .find('[data-region=\"term\"]')\n .text(str);\n return;\n }).catch(notification.exception);\n\n // We handled this event so consume it.\n evt.preventDefault();\n return false;\n };\n\n /**\n * Return the string \"Selected \".\n *\n * @function parseTaxonomies\n * @param {String} taxonomiesstr Comma separated list of taxonomies.\n * @return {Array} of level => taxonomystr\n */\n var parseTaxonomies = function(taxonomiesstr) {\n var all = taxonomiesstr.split(',');\n all.unshift(\"\");\n delete all[0];\n\n // Note we don't need to fill holes, because other functions check for empty anyway.\n return all;\n };\n\n return {\n /**\n * Initialise this page (attach event handlers etc).\n *\n * @method init\n * @param {Object} model The tree model provides some useful functions for loading and searching competencies.\n * @param {Number} pagectxid The page context ID.\n * @param {Object} taxonomies Constants indexed by level.\n * @param {Object} rulesMods The modules of the rules.\n */\n init: function(model, pagectxid, taxonomies, rulesMods) {\n treeModel = model;\n pageContextId = pagectxid;\n taxonomiesConstants = parseTaxonomies(taxonomies);\n rulesModules = rulesMods;\n\n $('[data-region=\"competencyactions\"] [data-action=\"add\"]').on('click', addHandler);\n\n menubar.enhance('.competencyactionsmenu', {\n '[data-action=\"edit\"]': editHandler,\n '[data-action=\"delete\"]': deleteCompetencyHandler,\n '[data-action=\"move\"]': moveHandler,\n '[data-action=\"moveup\"]': moveUpHandler,\n '[data-action=\"movedown\"]': moveDownHandler,\n '[data-action=\"linkedcourses\"]': seeCoursesHandler,\n '[data-action=\"relatedcompetencies\"]': relateCompetenciesHandler.bind(this),\n '[data-action=\"competencyrules\"]': ruleConfigHandler.bind(this)\n });\n $('[data-region=\"competencyactionsmenu\"]').hide();\n $('[data-region=\"competencyactions\"] [data-action=\"add\"]').hide();\n\n $('[data-region=\"filtercompetencies\"]').on('submit', updateSearchHandler);\n // Simple html5 drag drop because we already added an accessible alternative.\n var top = $('[data-region=\"managecompetencies\"] [data-enhance=\"tree\"]');\n top.on('dragstart', 'li>span', dragStart)\n .on('dragover', 'li>span', allowDrop)\n .on('dragenter', 'li>span', dragEnter)\n .on('dragleave', 'li>span', dragLeave)\n .on('drop', 'li>span', dropOver);\n\n model.on('selectionchanged', selectionChanged);\n\n // Prepare the configuration tool.\n ruleConfigInstance = new RuleConfig(treeModel, rulesModules);\n ruleConfigInstance.on('save', ruleConfigSaveHandler.bind(this));\n }\n };\n});\n"],"file":"competencyactions.min.js"}
\ No newline at end of file
+{"version":3,"file":"competencyactions.min.js","sources":["../src/competencyactions.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 .\n\n/**\n * Handle selection changes and actions on the competency tree.\n *\n * @module tool_lp/competencyactions\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/url',\n 'core/templates',\n 'core/notification',\n 'core/str',\n 'core/ajax',\n 'tool_lp/dragdrop-reorder',\n 'tool_lp/tree',\n 'tool_lp/dialogue',\n 'tool_lp/menubar',\n 'tool_lp/competencypicker',\n 'tool_lp/competency_outcomes',\n 'tool_lp/competencyruleconfig',\n 'core/pending',\n ],\n function(\n $, url, templates, notification, str, ajax, dragdrop, Ariatree, Dialogue, menubar, Picker, Outcomes, RuleConfig, Pending\n ) {\n\n // Private variables and functions.\n /** @var {Object} treeModel - This is an object representing the nodes in the tree. */\n var treeModel = null;\n /** @var {Node} moveSource - The start of a drag operation */\n var moveSource = null;\n /** @var {Node} moveTarget - The end of a drag operation */\n var moveTarget = null;\n /** @var {Number} pageContextId The page context ID. */\n var pageContextId;\n /** @var {Object} Picker instance. */\n var pickerInstance;\n /** @var {Object} Rule config instance. */\n var ruleConfigInstance;\n /** @var {Object} The competency we're picking a relation to. */\n var relatedTarget;\n /** @var {Object} Taxonomy constants indexed per level. */\n var taxonomiesConstants;\n /** @var {Array} The rules modules. Values are object containing type, namd and amd. */\n var rulesModules;\n /** @var {Number} the selected competency ID. */\n var selectedCompetencyId = null;\n\n /**\n * Respond to choosing the \"Add\" menu item for the selected node in the tree.\n * @method addHandler\n */\n var addHandler = function() {\n var parent = $('[data-region=\"competencyactions\"]').data('competency');\n\n var params = {\n competencyframeworkid: treeModel.getCompetencyFrameworkId(),\n pagecontextid: pageContextId\n };\n\n if (parent !== null) {\n // We are adding at a sub node.\n params.parentid = parent.id;\n }\n\n var relocate = function() {\n var queryparams = $.param(params);\n window.location = url.relativeUrl('/admin/tool/lp/editcompetency.php?' + queryparams);\n };\n\n if (parent !== null && treeModel.hasRule(parent.id)) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'addingcompetencywillresetparentrule', component: 'tool_lp', param: parent.shortname},\n {key: 'yes', component: 'core'},\n {key: 'no', component: 'core'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0],\n strings[1],\n strings[2],\n strings[3],\n relocate\n );\n }).fail(notification.exception);\n } else {\n relocate();\n }\n };\n\n /**\n * A source and destination has been chosen - so time to complete a move.\n * @method doMove\n */\n var doMove = function() {\n var frameworkid = $('[data-region=\"filtercompetencies\"]').data('frameworkid');\n var requests = ajax.call([{\n methodname: 'core_competency_set_parent_competency',\n args: {competencyid: moveSource, parentid: moveTarget}\n }, {\n methodname: 'tool_lp_data_for_competencies_manage_page',\n args: {competencyframeworkid: frameworkid,\n search: $('[data-region=\"filtercompetencies\"] input').val()}\n }]);\n requests[1].done(reloadPage).fail(notification.exception);\n };\n\n /**\n * Confirms a competency move.\n *\n * @method confirmMove\n */\n var confirmMove = function() {\n moveTarget = typeof moveTarget === \"undefined\" ? 0 : moveTarget;\n if (moveTarget == moveSource) {\n // No move to do.\n return;\n }\n\n var targetComp = treeModel.getCompetency(moveTarget) || {},\n sourceComp = treeModel.getCompetency(moveSource) || {},\n confirmMessage = 'movecompetencywillresetrules',\n showConfirm = false;\n\n // We shouldn't be moving the competency to the same parent.\n if (sourceComp.parentid == moveTarget) {\n return;\n }\n\n // If we are moving to a child of self.\n if (targetComp.path && targetComp.path.indexOf('/' + sourceComp.id + '/') >= 0) {\n confirmMessage = 'movecompetencytochildofselfwillresetrules';\n\n // Show a confirmation if self has rules, as they'll disappear.\n showConfirm = showConfirm || treeModel.hasRule(sourceComp.id);\n }\n\n // Show a confirmation if the current parent, or the destination have rules.\n showConfirm = showConfirm || (treeModel.hasRule(targetComp.id) || treeModel.hasRule(sourceComp.parentid));\n\n // Show confirm, and/or do the things.\n if (showConfirm) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: confirmMessage, component: 'tool_lp'},\n {key: 'yes', component: 'moodle'},\n {key: 'no', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Delete competency X?\n strings[2], // Delete.\n strings[3], // Cancel.\n doMove\n );\n }).fail(notification.exception);\n\n } else {\n doMove();\n }\n };\n\n /**\n * A move competency popup was opened - initialise the aria tree in it.\n * @method initMovePopup\n * @param {dialogue} popup The tool_lp/dialogue that was created.\n */\n var initMovePopup = function(popup) {\n var body = $(popup.getContent());\n var treeRoot = body.find('[data-enhance=movetree]');\n var tree = new Ariatree(treeRoot, false);\n tree.on('selectionchanged', function(evt, params) {\n var target = params.selected;\n moveTarget = $(target).data('id');\n });\n treeRoot.show();\n\n body.on('click', '[data-action=\"move\"]', function() {\n popup.close();\n confirmMove();\n });\n body.on('click', '[data-action=\"cancel\"]', function() {\n popup.close();\n });\n };\n\n /**\n * Turn a flat list of competencies into a tree structure (recursive).\n * @method addCompetencyChildren\n * @param {Object} parent The current parent node in the tree\n * @param {Object[]} competencies The flat list of competencies\n */\n var addCompetencyChildren = function(parent, competencies) {\n var i;\n\n for (i = 0; i < competencies.length; i++) {\n if (competencies[i].parentid == parent.id) {\n parent.haschildren = true;\n competencies[i].children = [];\n competencies[i].haschildren = false;\n parent.children[parent.children.length] = competencies[i];\n addCompetencyChildren(competencies[i], competencies);\n }\n }\n };\n\n /**\n * A node was chosen and \"Move\" was selected from the menu. Open a popup to select the target.\n * @param {Event} e\n * @method moveHandler\n */\n var moveHandler = function(e) {\n e.preventDefault();\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n\n // Remember what we are moving.\n moveSource = competency.id;\n\n // Load data for the template.\n var requests = ajax.call([\n {\n methodname: 'core_competency_search_competencies',\n args: {\n competencyframeworkid: competency.competencyframeworkid,\n searchtext: ''\n }\n }, {\n methodname: 'core_competency_read_competency_framework',\n args: {\n id: competency.competencyframeworkid\n }\n }\n ]);\n\n // When all data has arrived, continue.\n $.when.apply(null, requests).done(function(competencies, framework) {\n\n // Expand the list of competencies into a tree.\n var i;\n var competenciestree = [];\n for (i = 0; i < competencies.length; i++) {\n var onecompetency = competencies[i];\n if (onecompetency.parentid == \"0\") {\n onecompetency.children = [];\n onecompetency.haschildren = 0;\n competenciestree[competenciestree.length] = onecompetency;\n addCompetencyChildren(onecompetency, competencies);\n }\n }\n\n str.get_strings([\n {key: 'movecompetency', component: 'tool_lp', param: competency.shortname},\n {key: 'move', component: 'tool_lp'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n\n var context = {\n framework: framework,\n competencies: competenciestree\n };\n\n templates.render('tool_lp/competencies_move_tree', context)\n .done(function(tree) {\n new Dialogue(\n strings[0], // Move competency x.\n tree, // The move tree.\n initMovePopup\n );\n\n }).fail(notification.exception);\n\n }).fail(notification.exception);\n\n }).fail(notification.exception);\n\n };\n\n /**\n * Edit the selected competency.\n * @method editHandler\n */\n var editHandler = function() {\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n\n var params = {\n competencyframeworkid: treeModel.getCompetencyFrameworkId(),\n id: competency.id,\n parentid: competency.parentid,\n pagecontextid: pageContextId\n };\n\n var queryparams = $.param(params);\n window.location = url.relativeUrl('/admin/tool/lp/editcompetency.php?' + queryparams);\n };\n\n /**\n * Re-render the page with the latest data.\n * @param {Object} context\n * @method reloadPage\n */\n var reloadPage = function(context) {\n templates.render('tool_lp/manage_competencies_page', context)\n .done(function(newhtml, newjs) {\n $('[data-region=\"managecompetencies\"]').replaceWith(newhtml);\n templates.runTemplateJS(newjs);\n })\n .fail(notification.exception);\n };\n\n /**\n * Perform a search and render the page with the new search results.\n * @param {Event} e\n * @method updateSearchHandler\n */\n var updateSearchHandler = function(e) {\n e.preventDefault();\n\n var frameworkid = $('[data-region=\"filtercompetencies\"]').data('frameworkid');\n\n var requests = ajax.call([{\n methodname: 'tool_lp_data_for_competencies_manage_page',\n args: {competencyframeworkid: frameworkid,\n search: $('[data-region=\"filtercompetencies\"] input').val()}\n }]);\n requests[0].done(reloadPage).fail(notification.exception);\n };\n\n /**\n * Move a competency \"up\". This only affects the sort order within the same branch of the tree.\n * @method moveUpHandler\n */\n var moveUpHandler = function() {\n // We are chaining ajax requests here.\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n var requests = ajax.call([{\n methodname: 'core_competency_move_up_competency',\n args: {id: competency.id}\n }, {\n methodname: 'tool_lp_data_for_competencies_manage_page',\n args: {competencyframeworkid: competency.competencyframeworkid,\n search: $('[data-region=\"filtercompetencies\"] input').val()}\n }]);\n requests[1].done(reloadPage).fail(notification.exception);\n };\n\n /**\n * Move a competency \"down\". This only affects the sort order within the same branch of the tree.\n * @method moveDownHandler\n */\n var moveDownHandler = function() {\n // We are chaining ajax requests here.\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n var requests = ajax.call([{\n methodname: 'core_competency_move_down_competency',\n args: {id: competency.id}\n }, {\n methodname: 'tool_lp_data_for_competencies_manage_page',\n args: {competencyframeworkid: competency.competencyframeworkid,\n search: $('[data-region=\"filtercompetencies\"] input').val()}\n }]);\n requests[1].done(reloadPage).fail(notification.exception);\n };\n\n /**\n * Open a dialogue to show all the courses using the selected competency.\n * @method seeCoursesHandler\n */\n var seeCoursesHandler = function() {\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n\n var requests = ajax.call([{\n methodname: 'tool_lp_list_courses_using_competency',\n args: {id: competency.id}\n }]);\n\n requests[0].done(function(courses) {\n var context = {\n courses: courses\n };\n templates.render('tool_lp/linked_courses_summary', context).done(function(html) {\n str.get_string('linkedcourses', 'tool_lp').done(function(linkedcourses) {\n new Dialogue(\n linkedcourses, // Title.\n html, // The linked courses.\n initMovePopup\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Open a competencies popup to relate competencies.\n *\n * @method relateCompetenciesHandler\n */\n var relateCompetenciesHandler = function() {\n relatedTarget = $('[data-region=\"competencyactions\"]').data('competency');\n\n if (!pickerInstance) {\n pickerInstance = new Picker(pageContextId, relatedTarget.competencyframeworkid);\n pickerInstance.on('save', function(e, data) {\n var pendingPromise = new Pending();\n var compIds = data.competencyIds;\n\n var calls = [];\n $.each(compIds, function(index, value) {\n calls.push({\n methodname: 'core_competency_add_related_competency',\n args: {competencyid: value, relatedcompetencyid: relatedTarget.id}\n });\n });\n\n calls.push({\n methodname: 'tool_lp_data_for_related_competencies_section',\n args: {competencyid: relatedTarget.id}\n });\n\n var promises = ajax.call(calls);\n\n promises[calls.length - 1].then(function(context) {\n return templates.render('tool_lp/related_competencies', context);\n }).then(function(html, js) {\n $('[data-region=\"relatedcompetencies\"]').replaceWith(html);\n templates.runTemplateJS(js);\n updatedRelatedCompetencies();\n return;\n })\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n });\n }\n\n pickerInstance.setDisallowedCompetencyIDs([relatedTarget.id]);\n pickerInstance.display();\n };\n\n var ruleConfigHandler = function(e) {\n e.preventDefault();\n relatedTarget = $('[data-region=\"competencyactions\"]').data('competency');\n ruleConfigInstance.setTargetCompetencyId(relatedTarget.id);\n ruleConfigInstance.display();\n };\n\n var ruleConfigSaveHandler = function(e, config) {\n var update = {\n id: relatedTarget.id,\n shortname: relatedTarget.shortname,\n idnumber: relatedTarget.idnumber,\n description: relatedTarget.description,\n descriptionformat: relatedTarget.descriptionformat,\n ruletype: config.ruletype,\n ruleoutcome: config.ruleoutcome,\n ruleconfig: config.ruleconfig\n };\n var promise = ajax.call([{\n methodname: 'core_competency_update_competency',\n args: {competency: update}\n }]);\n promise[0].then(function(result) {\n if (result) {\n relatedTarget.ruletype = config.ruletype;\n relatedTarget.ruleoutcome = config.ruleoutcome;\n relatedTarget.ruleconfig = config.ruleconfig;\n renderCompetencySummary(relatedTarget);\n }\n return;\n }).catch(notification.exception);\n };\n\n /**\n * Delete a competency.\n * @method doDelete\n */\n var doDelete = function() {\n // We are chaining ajax requests here.\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n var requests = ajax.call([{\n methodname: 'core_competency_delete_competency',\n args: {id: competency.id}\n }, {\n methodname: 'tool_lp_data_for_competencies_manage_page',\n args: {competencyframeworkid: competency.competencyframeworkid,\n search: $('[data-region=\"filtercompetencies\"] input').val()}\n }]);\n requests[0].done(function(success) {\n if (success === false) {\n str.get_strings([\n {key: 'competencycannotbedeleted', component: 'tool_lp', param: competency.shortname},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.alert(\n null,\n strings[0]\n );\n }).fail(notification.exception);\n }\n }).fail(notification.exception);\n requests[1].done(reloadPage).fail(notification.exception);\n };\n\n /**\n * Show a confirm dialogue before deleting a competency.\n * @method deleteCompetencyHandler\n */\n var deleteCompetencyHandler = function() {\n var competency = $('[data-region=\"competencyactions\"]').data('competency'),\n confirmMessage = 'deletecompetency';\n\n if (treeModel.hasRule(competency.parentid)) {\n confirmMessage = 'deletecompetencyparenthasrule';\n }\n\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: confirmMessage, component: 'tool_lp', param: competency.shortname},\n {key: 'delete', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Delete competency X?\n strings[2], // Delete.\n strings[3], // Cancel.\n doDelete\n );\n }).fail(notification.exception);\n };\n\n /**\n * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).\n * @method dragStart\n * @param {Event} e\n */\n var dragStart = function(e) {\n e.originalEvent.dataTransfer.setData('text', $(e.target).parent().data('id'));\n };\n\n /**\n * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).\n * @method allowDrop\n * @param {Event} e\n */\n var allowDrop = function(e) {\n e.originalEvent.dataTransfer.dropEffect = 'move';\n e.preventDefault();\n };\n\n /**\n * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).\n * @method dragEnter\n * @param {Event} e\n */\n var dragEnter = function(e) {\n e.preventDefault();\n $(this).addClass('currentdragtarget');\n };\n\n /**\n * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).\n * @method dragLeave\n * @param {Event} e\n */\n var dragLeave = function(e) {\n e.preventDefault();\n $(this).removeClass('currentdragtarget');\n };\n\n /**\n * HTML5 implementation of drag/drop (there is an accesible alternative in the menus).\n * @method dropOver\n * @param {Event} e\n */\n var dropOver = function(e) {\n e.preventDefault();\n moveSource = e.originalEvent.dataTransfer.getData('text');\n moveTarget = $(e.target).parent().data('id');\n $(this).removeClass('currentdragtarget');\n\n confirmMove();\n };\n\n /**\n * Deletes a related competency without confirmation.\n *\n * @param {Event} e The event that triggered the action.\n * @method deleteRelatedHandler\n */\n var deleteRelatedHandler = function(e) {\n e.preventDefault();\n\n var relatedid = this.id.substr(11);\n var competency = $('[data-region=\"competencyactions\"]').data('competency');\n var removeRelated = ajax.call([\n {methodname: 'core_competency_remove_related_competency',\n args: {relatedcompetencyid: relatedid, competencyid: competency.id}},\n {methodname: 'tool_lp_data_for_related_competencies_section',\n args: {competencyid: competency.id}}\n ]);\n\n removeRelated[1].done(function(context) {\n templates.render('tool_lp/related_competencies', context).done(function(html) {\n $('[data-region=\"relatedcompetencies\"]').replaceWith(html);\n updatedRelatedCompetencies();\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Updates the competencies list (with relations) and add listeners.\n *\n * @method updatedRelatedCompetencies\n */\n var updatedRelatedCompetencies = function() {\n\n // Listeners to newly loaded related competencies.\n $('[data-action=\"deleterelation\"]').on('click', deleteRelatedHandler);\n\n };\n\n /**\n * Log the competency viewed event.\n *\n * @param {Object} competency The competency.\n * @method triggerCompetencyViewedEvent\n */\n var triggerCompetencyViewedEvent = function(competency) {\n if (competency.id !== selectedCompetencyId) {\n // Set the selected competency id.\n selectedCompetencyId = competency.id;\n ajax.call([{\n methodname: 'core_competency_competency_viewed',\n args: {id: competency.id}\n }]);\n }\n };\n\n /**\n * Return the taxonomy constant for a level.\n *\n * @param {Number} level The level.\n * @return {String}\n * @function getTaxonomyAtLevel\n */\n var getTaxonomyAtLevel = function(level) {\n var constant = taxonomiesConstants[level];\n if (!constant) {\n constant = 'competency';\n }\n return constant;\n };\n\n /**\n * Render the competency summary.\n *\n * @param {Object} competency The competency.\n */\n var renderCompetencySummary = function(competency) {\n var promise = $.Deferred().resolve().promise(),\n context = {};\n\n context.competency = competency;\n context.showdeleterelatedaction = true;\n context.showrelatedcompetencies = true;\n context.showrule = false;\n context.pluginbaseurl = url.relativeUrl('/admin/tool/lp');\n\n if (competency.ruleoutcome != Outcomes.NONE) {\n // Get the outcome and rule name.\n promise = Outcomes.getString(competency.ruleoutcome).then(function(str) {\n var name;\n $.each(rulesModules, function(index, modInfo) {\n if (modInfo.type == competency.ruletype) {\n name = modInfo.name;\n }\n });\n return [str, name];\n });\n }\n\n promise.then(function(strs) {\n if (typeof strs !== 'undefined') {\n context.showrule = true;\n context.rule = {\n outcome: strs[0],\n type: strs[1]\n };\n }\n return context;\n }).then(function(context) {\n return templates.render('tool_lp/competency_summary', context);\n }).then(function(html) {\n $('[data-region=\"competencyinfo\"]').html(html);\n $('[data-action=\"deleterelation\"]').on('click', deleteRelatedHandler);\n return templates.render('tool_lp/loading', {});\n }).then(function(html, js) {\n templates.replaceNodeContents('[data-region=\"relatedcompetencies\"]', html, js);\n return ajax.call([{\n methodname: 'tool_lp_data_for_related_competencies_section',\n args: {competencyid: competency.id}\n }])[0];\n }).then(function(context) {\n return templates.render('tool_lp/related_competencies', context);\n }).then(function(html, js) {\n $('[data-region=\"relatedcompetencies\"]').replaceWith(html);\n templates.runTemplateJS(js);\n updatedRelatedCompetencies();\n return;\n }).catch(notification.exception);\n };\n\n /**\n * Return the string \"Add \".\n *\n * @param {Number} level The level.\n * @return {String}\n * @function strAddTaxonomy\n */\n var strAddTaxonomy = function(level) {\n return str.get_string('taxonomy_add_' + getTaxonomyAtLevel(level), 'tool_lp');\n };\n\n /**\n * Return the string \"Selected \".\n *\n * @param {Number} level The level.\n * @return {String}\n * @function strSelectedTaxonomy\n */\n var strSelectedTaxonomy = function(level) {\n return str.get_string('taxonomy_selected_' + getTaxonomyAtLevel(level), 'tool_lp');\n };\n\n /**\n * Handler when a node in the aria tree is selected.\n * @method selectionChanged\n * @param {Event} evt The event that triggered the selection change.\n * @param {Object} params The parameters for the event. Contains a list of selected nodes.\n * @return {Boolean}\n */\n var selectionChanged = function(evt, params) {\n var node = params.selected,\n id = $(node).data('id'),\n btn = $('[data-region=\"competencyactions\"] [data-action=\"add\"]'),\n actionMenu = $('[data-region=\"competencyactionsmenu\"]'),\n selectedTitle = $('[data-region=\"selected-competency\"]'),\n level = 0,\n sublevel = 1;\n\n menubar.closeAll();\n\n if (typeof id === \"undefined\") {\n // Assume this is the root of the tree.\n // Here we are only getting the text from the top of the tree, to do it we clone the tree,\n // remove all children and then call text on the result.\n $('[data-region=\"competencyinfo\"]').html(node.clone().children().remove().end().text());\n $('[data-region=\"competencyactions\"]').data('competency', null);\n actionMenu.hide();\n\n } else {\n var competency = treeModel.getCompetency(id);\n\n level = treeModel.getCompetencyLevel(id);\n sublevel = level + 1;\n\n actionMenu.show();\n $('[data-region=\"competencyactions\"]').data('competency', competency);\n renderCompetencySummary(competency);\n // Log Competency viewed event.\n triggerCompetencyViewedEvent(competency);\n }\n strSelectedTaxonomy(level).then(function(str) {\n selectedTitle.text(str);\n return;\n }).catch(notification.exception);\n\n strAddTaxonomy(sublevel).then(function(str) {\n btn.show()\n .find('[data-region=\"term\"]')\n .text(str);\n return;\n }).catch(notification.exception);\n\n // We handled this event so consume it.\n evt.preventDefault();\n return false;\n };\n\n /**\n * Return the string \"Selected \".\n *\n * @function parseTaxonomies\n * @param {String} taxonomiesstr Comma separated list of taxonomies.\n * @return {Array} of level => taxonomystr\n */\n var parseTaxonomies = function(taxonomiesstr) {\n var all = taxonomiesstr.split(',');\n all.unshift(\"\");\n delete all[0];\n\n // Note we don't need to fill holes, because other functions check for empty anyway.\n return all;\n };\n\n return {\n /**\n * Initialise this page (attach event handlers etc).\n *\n * @method init\n * @param {Object} model The tree model provides some useful functions for loading and searching competencies.\n * @param {Number} pagectxid The page context ID.\n * @param {Object} taxonomies Constants indexed by level.\n * @param {Object} rulesMods The modules of the rules.\n */\n init: function(model, pagectxid, taxonomies, rulesMods) {\n treeModel = model;\n pageContextId = pagectxid;\n taxonomiesConstants = parseTaxonomies(taxonomies);\n rulesModules = rulesMods;\n\n $('[data-region=\"competencyactions\"] [data-action=\"add\"]').on('click', addHandler);\n\n menubar.enhance('.competencyactionsmenu', {\n '[data-action=\"edit\"]': editHandler,\n '[data-action=\"delete\"]': deleteCompetencyHandler,\n '[data-action=\"move\"]': moveHandler,\n '[data-action=\"moveup\"]': moveUpHandler,\n '[data-action=\"movedown\"]': moveDownHandler,\n '[data-action=\"linkedcourses\"]': seeCoursesHandler,\n '[data-action=\"relatedcompetencies\"]': relateCompetenciesHandler.bind(this),\n '[data-action=\"competencyrules\"]': ruleConfigHandler.bind(this)\n });\n $('[data-region=\"competencyactionsmenu\"]').hide();\n $('[data-region=\"competencyactions\"] [data-action=\"add\"]').hide();\n\n $('[data-region=\"filtercompetencies\"]').on('submit', updateSearchHandler);\n // Simple html5 drag drop because we already added an accessible alternative.\n var top = $('[data-region=\"managecompetencies\"] [data-enhance=\"tree\"]');\n top.on('dragstart', 'li>span', dragStart)\n .on('dragover', 'li>span', allowDrop)\n .on('dragenter', 'li>span', dragEnter)\n .on('dragleave', 'li>span', dragLeave)\n .on('drop', 'li>span', dropOver);\n\n model.on('selectionchanged', selectionChanged);\n\n // Prepare the configuration tool.\n ruleConfigInstance = new RuleConfig(treeModel, rulesModules);\n ruleConfigInstance.on('save', ruleConfigSaveHandler.bind(this));\n }\n };\n});\n"],"names":["define","$","url","templates","notification","str","ajax","dragdrop","Ariatree","Dialogue","menubar","Picker","Outcomes","RuleConfig","Pending","pageContextId","pickerInstance","ruleConfigInstance","relatedTarget","taxonomiesConstants","rulesModules","treeModel","moveSource","moveTarget","selectedCompetencyId","addHandler","parent","data","params","competencyframeworkid","getCompetencyFrameworkId","pagecontextid","parentid","id","relocate","queryparams","param","window","location","relativeUrl","hasRule","get_strings","key","component","shortname","done","strings","confirm","fail","exception","doMove","frameworkid","call","methodname","args","competencyid","search","val","reloadPage","confirmMove","targetComp","getCompetency","sourceComp","confirmMessage","showConfirm","path","indexOf","initMovePopup","popup","body","getContent","treeRoot","find","on","evt","target","selected","show","close","addCompetencyChildren","competencies","i","length","haschildren","children","moveHandler","e","preventDefault","competency","requests","searchtext","when","apply","framework","competenciestree","onecompetency","context","render","tree","editHandler","newhtml","newjs","replaceWith","runTemplateJS","updateSearchHandler","moveUpHandler","moveDownHandler","seeCoursesHandler","courses","html","get_string","linkedcourses","relateCompetenciesHandler","pendingPromise","compIds","competencyIds","calls","each","index","value","push","relatedcompetencyid","then","js","updatedRelatedCompetencies","resolve","catch","setDisallowedCompetencyIDs","display","ruleConfigHandler","setTargetCompetencyId","ruleConfigSaveHandler","config","update","idnumber","description","descriptionformat","ruletype","ruleoutcome","ruleconfig","result","renderCompetencySummary","doDelete","success","alert","deleteCompetencyHandler","dragStart","originalEvent","dataTransfer","setData","allowDrop","dropEffect","dragEnter","this","addClass","dragLeave","removeClass","dropOver","getData","deleteRelatedHandler","relatedid","substr","getTaxonomyAtLevel","level","constant","promise","Deferred","showdeleterelatedaction","showrelatedcompetencies","showrule","pluginbaseurl","NONE","getString","name","modInfo","type","strs","rule","outcome","replaceNodeContents","selectionChanged","node","btn","actionMenu","selectedTitle","sublevel","closeAll","clone","remove","end","text","hide","getCompetencyLevel","triggerCompetencyViewedEvent","strSelectedTaxonomy","strAddTaxonomy","init","model","pagectxid","taxonomies","rulesMods","all","split","unshift","enhance","bind"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencydialogue.min.js b/admin/tool/lp/amd/build/competencydialogue.min.js
index 53a0e337f32..c06ba3594da 100644
--- a/admin/tool/lp/amd/build/competencydialogue.min.js
+++ b/admin/tool/lp/amd/build/competencydialogue.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/competencydialogue",["jquery","core/notification","core/ajax","core/templates","core/str","tool_lp/dialogue"],function(a,b,c,d,e,f){var g,h=function(){};h.prototype.triggerCompetencyViewedEvent=function(a){c.call([{methodname:"core_competency_competency_viewed",args:{id:a}}])};h.prototype.showDialogue=function(a,c){var e=this.getCompetencyDataPromise(a,c),g=this;e.done(function(c){d.render("tool_lp/competency_summary",c).done(function(b){g.triggerCompetencyViewedEvent(a);new f(c.competency.shortname,b)}).fail(b.exception)}).fail(b.exception)};h.prototype.showDialogueFromData=function(a){var c=this;d.render("tool_lp/competency_summary",a).done(function(b){c.triggerCompetencyViewedEvent(a.id);new f(a.shortname,b,c.enhanceDialogue)}).fail(b.exception)};h.prototype.clickEventHandler=function(b){var c=b.data.compdialogue,d=a(b.currentTarget),e=d.data("id"),f=!d.data("excluderelated"),g=d.data("includecourses");c.showDialogue(e,{includerelated:f,includecourses:g});b.preventDefault()};h.prototype.getCompetencyDataPromise=function(a,d){var e=c.call([{methodname:"tool_lp_data_for_competency_summary",args:{competencyid:a,includerelated:d.includerelated||!1,includecourses:d.includecourses||!1}}]);return e[0].then(function(a){return a}).fail(b.exception)};return{init:function init(){if("undefined"!=typeof g){return}g=new h;a("body").delegate("[data-action=\"competency-dialogue\"]","click",{compdialogue:g},g.clickEventHandler.bind(g))}}});
-//# sourceMappingURL=competencydialogue.min.js.map
+/**
+ * Display Competency in dialogue box.
+ *
+ * @module tool_lp/Competencydialogue
+ * @copyright 2015 Issam Taboubi
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/competencydialogue",["jquery","core/notification","core/ajax","core/templates","core/str","tool_lp/dialogue"],(function($,notification,ajax,templates,str,Dialogue){var instance,Competencydialogue=function(){};return Competencydialogue.prototype.triggerCompetencyViewedEvent=function(competencyId){ajax.call([{methodname:"core_competency_competency_viewed",args:{id:competencyId}}])},Competencydialogue.prototype.showDialogue=function(competencyid,options){var datapromise=this.getCompetencyDataPromise(competencyid,options),localthis=this;datapromise.done((function(data){templates.render("tool_lp/competency_summary",data).done((function(html){localthis.triggerCompetencyViewedEvent(competencyid),new Dialogue(data.competency.shortname,html)})).fail(notification.exception)})).fail(notification.exception)},Competencydialogue.prototype.showDialogueFromData=function(dataSource){var localthis=this;templates.render("tool_lp/competency_summary",dataSource).done((function(html){localthis.triggerCompetencyViewedEvent(dataSource.id),new Dialogue(dataSource.shortname,html,localthis.enhanceDialogue)})).fail(notification.exception)},Competencydialogue.prototype.clickEventHandler=function(e){var compdialogue=e.data.compdialogue,currentTarget=$(e.currentTarget),competencyid=currentTarget.data("id"),includerelated=!currentTarget.data("excluderelated"),includecourses=currentTarget.data("includecourses");compdialogue.showDialogue(competencyid,{includerelated:includerelated,includecourses:includecourses}),e.preventDefault()},Competencydialogue.prototype.getCompetencyDataPromise=function(competencyid,options){return ajax.call([{methodname:"tool_lp_data_for_competency_summary",args:{competencyid:competencyid,includerelated:options.includerelated||!1,includecourses:options.includecourses||!1}}])[0].then((function(context){return context})).fail(notification.exception)},{init:function(){void 0===instance&&(instance=new Competencydialogue,$("body").delegate('[data-action="competency-dialogue"]',"click",{compdialogue:instance},instance.clickEventHandler.bind(instance)))}}}));
+
+//# sourceMappingURL=competencydialogue.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencydialogue.min.js.map b/admin/tool/lp/amd/build/competencydialogue.min.js.map
index 9ed99d48920..3a66a43e0e3 100644
--- a/admin/tool/lp/amd/build/competencydialogue.min.js.map
+++ b/admin/tool/lp/amd/build/competencydialogue.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/competencydialogue.js"],"names":["define","$","notification","ajax","templates","str","Dialogue","instance","Competencydialogue","prototype","triggerCompetencyViewedEvent","competencyId","call","methodname","args","id","showDialogue","competencyid","options","datapromise","getCompetencyDataPromise","localthis","done","data","render","html","competency","shortname","fail","exception","showDialogueFromData","dataSource","enhanceDialogue","clickEventHandler","e","compdialogue","currentTarget","includerelated","includecourses","preventDefault","requests","then","context","init","delegate","bind"],"mappings":"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","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 .\n\n/**\n * Display Competency in dialogue box.\n *\n * @module tool_lp/Competencydialogue\n * @copyright 2015 Issam Taboubi \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/templates',\n 'core/str',\n 'tool_lp/dialogue'],\n function($, notification, ajax, templates, str, Dialogue) {\n\n /**\n * The main instance we'll be working with.\n *\n * @type {Competencydialogue}\n */\n var instance;\n\n /**\n * Constructor for CompetencyDialogue.\n */\n var Competencydialogue = function() {\n // Intentionally left empty.\n };\n\n /**\n * Log the competency viewed event.\n *\n * @param {Number} competencyId The competency ID.\n * @method triggerCompetencyViewedEvent\n */\n Competencydialogue.prototype.triggerCompetencyViewedEvent = function(competencyId) {\n ajax.call([{\n methodname: 'core_competency_competency_viewed',\n args: {id: competencyId}\n }]);\n };\n\n /**\n * Display a dialogue box by competencyid.\n *\n * @param {Number} competencyid The competency ID.\n * @param {Object} options The options.\n * @method showDialogue\n */\n Competencydialogue.prototype.showDialogue = function(competencyid, options) {\n\n var datapromise = this.getCompetencyDataPromise(competencyid, options);\n var localthis = this;\n datapromise.done(function(data) {\n // Inner Html in the dialogue content.\n templates.render('tool_lp/competency_summary', data)\n .done(function(html) {\n // Log competency viewed event.\n localthis.triggerCompetencyViewedEvent(competencyid);\n\n // Show the dialogue.\n new Dialogue(\n data.competency.shortname,\n html\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Display a dialogue box from data.\n *\n * @param {Object} dataSource data to be used to display dialogue box\n * @method showDialogueFromData\n */\n Competencydialogue.prototype.showDialogueFromData = function(dataSource) {\n\n var localthis = this;\n // Inner Html in the dialogue content.\n templates.render('tool_lp/competency_summary', dataSource)\n .done(function(html) {\n // Log competency viewed event.\n localthis.triggerCompetencyViewedEvent(dataSource.id);\n\n // Show the dialogue.\n new Dialogue(\n dataSource.shortname,\n html,\n localthis.enhanceDialogue\n );\n }).fail(notification.exception);\n };\n\n /**\n * The action on the click event.\n *\n * @param {Event} e event click\n * @method clickEventHandler\n */\n Competencydialogue.prototype.clickEventHandler = function(e) {\n\n var compdialogue = e.data.compdialogue;\n var currentTarget = $(e.currentTarget);\n var competencyid = currentTarget.data('id');\n var includerelated = !(currentTarget.data('excluderelated'));\n var includecourses = currentTarget.data('includecourses');\n\n // Show the dialogue box.\n compdialogue.showDialogue(competencyid, {\n includerelated: includerelated,\n includecourses: includecourses\n });\n e.preventDefault();\n };\n\n /**\n * Get a promise on data competency.\n *\n * @param {Number} competencyid\n * @param {Object} options\n * @return {Promise} return promise on data request\n * @method getCompetencyDataPromise\n */\n Competencydialogue.prototype.getCompetencyDataPromise = function(competencyid, options) {\n\n var requests = ajax.call([\n {methodname: 'tool_lp_data_for_competency_summary',\n args: {competencyid: competencyid,\n includerelated: options.includerelated || false,\n includecourses: options.includecourses || false\n }\n }\n ]);\n\n return requests[0].then(function(context) {\n return context;\n }).fail(notification.exception);\n };\n\n return /** @alias module:tool_lp/competencydialogue */ {\n\n /**\n * Initialise the competency dialogue module.\n *\n * Only the first call matters.\n */\n init: function() {\n if (typeof instance !== 'undefined') {\n return;\n }\n\n // Instantiate the one instance and delegate event on the body.\n instance = new Competencydialogue();\n $('body').delegate('[data-action=\"competency-dialogue\"]', 'click', {compdialogue: instance},\n instance.clickEventHandler.bind(instance));\n }\n };\n});\n"],"file":"competencydialogue.min.js"}
\ No newline at end of file
+{"version":3,"file":"competencydialogue.min.js","sources":["../src/competencydialogue.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 .\n\n/**\n * Display Competency in dialogue box.\n *\n * @module tool_lp/Competencydialogue\n * @copyright 2015 Issam Taboubi \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/templates',\n 'core/str',\n 'tool_lp/dialogue'],\n function($, notification, ajax, templates, str, Dialogue) {\n\n /**\n * The main instance we'll be working with.\n *\n * @type {Competencydialogue}\n */\n var instance;\n\n /**\n * Constructor for CompetencyDialogue.\n */\n var Competencydialogue = function() {\n // Intentionally left empty.\n };\n\n /**\n * Log the competency viewed event.\n *\n * @param {Number} competencyId The competency ID.\n * @method triggerCompetencyViewedEvent\n */\n Competencydialogue.prototype.triggerCompetencyViewedEvent = function(competencyId) {\n ajax.call([{\n methodname: 'core_competency_competency_viewed',\n args: {id: competencyId}\n }]);\n };\n\n /**\n * Display a dialogue box by competencyid.\n *\n * @param {Number} competencyid The competency ID.\n * @param {Object} options The options.\n * @method showDialogue\n */\n Competencydialogue.prototype.showDialogue = function(competencyid, options) {\n\n var datapromise = this.getCompetencyDataPromise(competencyid, options);\n var localthis = this;\n datapromise.done(function(data) {\n // Inner Html in the dialogue content.\n templates.render('tool_lp/competency_summary', data)\n .done(function(html) {\n // Log competency viewed event.\n localthis.triggerCompetencyViewedEvent(competencyid);\n\n // Show the dialogue.\n new Dialogue(\n data.competency.shortname,\n html\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Display a dialogue box from data.\n *\n * @param {Object} dataSource data to be used to display dialogue box\n * @method showDialogueFromData\n */\n Competencydialogue.prototype.showDialogueFromData = function(dataSource) {\n\n var localthis = this;\n // Inner Html in the dialogue content.\n templates.render('tool_lp/competency_summary', dataSource)\n .done(function(html) {\n // Log competency viewed event.\n localthis.triggerCompetencyViewedEvent(dataSource.id);\n\n // Show the dialogue.\n new Dialogue(\n dataSource.shortname,\n html,\n localthis.enhanceDialogue\n );\n }).fail(notification.exception);\n };\n\n /**\n * The action on the click event.\n *\n * @param {Event} e event click\n * @method clickEventHandler\n */\n Competencydialogue.prototype.clickEventHandler = function(e) {\n\n var compdialogue = e.data.compdialogue;\n var currentTarget = $(e.currentTarget);\n var competencyid = currentTarget.data('id');\n var includerelated = !(currentTarget.data('excluderelated'));\n var includecourses = currentTarget.data('includecourses');\n\n // Show the dialogue box.\n compdialogue.showDialogue(competencyid, {\n includerelated: includerelated,\n includecourses: includecourses\n });\n e.preventDefault();\n };\n\n /**\n * Get a promise on data competency.\n *\n * @param {Number} competencyid\n * @param {Object} options\n * @return {Promise} return promise on data request\n * @method getCompetencyDataPromise\n */\n Competencydialogue.prototype.getCompetencyDataPromise = function(competencyid, options) {\n\n var requests = ajax.call([\n {methodname: 'tool_lp_data_for_competency_summary',\n args: {competencyid: competencyid,\n includerelated: options.includerelated || false,\n includecourses: options.includecourses || false\n }\n }\n ]);\n\n return requests[0].then(function(context) {\n return context;\n }).fail(notification.exception);\n };\n\n return /** @alias module:tool_lp/competencydialogue */ {\n\n /**\n * Initialise the competency dialogue module.\n *\n * Only the first call matters.\n */\n init: function() {\n if (typeof instance !== 'undefined') {\n return;\n }\n\n // Instantiate the one instance and delegate event on the body.\n instance = new Competencydialogue();\n $('body').delegate('[data-action=\"competency-dialogue\"]', 'click', {compdialogue: instance},\n instance.clickEventHandler.bind(instance));\n }\n };\n});\n"],"names":["define","$","notification","ajax","templates","str","Dialogue","instance","Competencydialogue","prototype","triggerCompetencyViewedEvent","competencyId","call","methodname","args","id","showDialogue","competencyid","options","datapromise","this","getCompetencyDataPromise","localthis","done","data","render","html","competency","shortname","fail","exception","showDialogueFromData","dataSource","enhanceDialogue","clickEventHandler","e","compdialogue","currentTarget","includerelated","includecourses","preventDefault","then","context","init","delegate","bind"],"mappings":";;;;;;;AAsBAA,oCAAO,CAAC,SACA,oBACA,YACA,iBACA,WACA,qBACD,SAASC,EAAGC,aAAcC,KAAMC,UAAWC,IAAKC,cAO/CC,SAKAC,mBAAqB,oBAUzBA,mBAAmBC,UAAUC,6BAA+B,SAASC,cACjER,KAAKS,KAAK,CAAC,CACHC,WAAY,oCACZC,KAAM,CAACC,GAAIJ,kBAWvBH,mBAAmBC,UAAUO,aAAe,SAASC,aAAcC,aAE3DC,YAAcC,KAAKC,yBAAyBJ,aAAcC,SAC1DI,UAAYF,KAChBD,YAAYI,MAAK,SAASC,MAEtBpB,UAAUqB,OAAO,6BAA8BD,MAC1CD,MAAK,SAASG,MAEXJ,UAAUZ,6BAA6BO,kBAGnCX,SACAkB,KAAKG,WAAWC,UAChBF,SAELG,KAAK3B,aAAa4B,cAC1BD,KAAK3B,aAAa4B,YASzBtB,mBAAmBC,UAAUsB,qBAAuB,SAASC,gBAErDV,UAAYF,KAEhBhB,UAAUqB,OAAO,6BAA8BO,YAC1CT,MAAK,SAASG,MAEXJ,UAAUZ,6BAA6BsB,WAAWjB,QAG9CT,SACA0B,WAAWJ,UACXF,KACAJ,UAAUW,oBAEfJ,KAAK3B,aAAa4B,YAS7BtB,mBAAmBC,UAAUyB,kBAAoB,SAASC,OAElDC,aAAeD,EAAEX,KAAKY,aACtBC,cAAgBpC,EAAEkC,EAAEE,eACpBpB,aAAeoB,cAAcb,KAAK,MAClCc,gBAAmBD,cAAcb,KAAK,kBACtCe,eAAiBF,cAAcb,KAAK,kBAGxCY,aAAapB,aAAaC,aAAc,CACpCqB,eAAgBA,eAChBC,eAAgBA,iBAEpBJ,EAAEK,kBAWNhC,mBAAmBC,UAAUY,yBAA2B,SAASJ,aAAcC,gBAE5Df,KAAKS,KAAK,CACrB,CAACC,WAAY,sCACXC,KAAM,CAACG,aAAcA,aACbqB,eAAgBpB,QAAQoB,iBAAkB,EAC1CC,eAAgBrB,QAAQqB,iBAAkB,MAKxC,GAAGE,MAAK,SAASC,gBACvBA,WACPb,KAAK3B,aAAa4B,YAG8B,CAOnDa,KAAM,gBACsB,IAAbpC,WAKXA,SAAW,IAAIC,mBACfP,EAAE,QAAQ2C,SAAS,sCAAuC,QAAS,CAACR,aAAc7B,UAC9EA,SAAS2B,kBAAkBW,KAAKtC"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencypicker.min.js b/admin/tool/lp/amd/build/competencypicker.min.js
index ec38fee95eb..37c9d3e8d79 100644
--- a/admin/tool/lp/amd/build/competencypicker.min.js
+++ b/admin/tool/lp/amd/build/competencypicker.min.js
@@ -1,2 +1,14 @@
-define ("tool_lp/competencypicker",["jquery","core/notification","core/ajax","core/templates","tool_lp/dialogue","core/str","tool_lp/tree","core/pending"],function(a,b,c,d,e,f,g,h){var i=function(b,c,d,e){var f=this;f._eventNode=a("");f._frameworks=[];f._reset();f._pageContextId=b;f._pageContextIncludes=d||"children";f._multiSelect="undefined"==typeof e||!0===e;if(c){f._frameworkId=c;f._singleFramework=!0}};i.prototype._competencies=null;i.prototype._disallowedCompetencyIDs=null;i.prototype._eventNode=null;i.prototype._frameworks=null;i.prototype._frameworkId=null;i.prototype._pageContextId=null;i.prototype._pageContextIncludes=null;i.prototype._popup=null;i.prototype._searchText="";i.prototype._selectedCompetencies=null;i.prototype._singleFramework=!1;i.prototype._multiSelect=!0;i.prototype._onlyVisible=!0;i.prototype._afterRender=function(){var c=this,d=new g(c._find("[data-enhance=linktree]"),c._multiSelect);c._find("[data-enhance=linktree]").show();d.on("selectionchanged",function(b,d){var e=d.selected;b.preventDefault();var f=[];a.each(e,function(b,d){var e=a(d).data("id"),g=!0;if("undefined"==typeof e){g=!1}else{a.each(c._disallowedCompetencyIDs,function(a,b){if(b==e){g=!1}})}if(g){f.push(e)}});c._selectedCompetencies=f;if(!c._selectedCompetencies.length){c._find("[data-region=\"competencylinktree\"] [data-action=\"add\"]").attr("disabled","disabled")}else{c._find("[data-region=\"competencylinktree\"] [data-action=\"add\"]").removeAttr("disabled")}});if(!c._singleFramework){c._find("[data-action=\"chooseframework\"]").change(function(d){c._frameworkId=a(d.target).val();c._loadCompetencies().then(c._refresh.bind(c)).catch(b.exception)})}c._find("[data-region=\"filtercompetencies\"] button").click(function(b){b.preventDefault();a(b.target).attr("disabled","disabled");c._searchText=c._find("[data-region=\"filtercompetencies\"] input").val()||"";return c._refresh().always(function(){a(b.target).removeAttr("disabled")})});c._find("[data-region=\"competencylinktree\"] [data-action=\"cancel\"]").click(function(a){a.preventDefault();c.close()});c._find("[data-region=\"competencylinktree\"] [data-action=\"add\"]").click(function(a){a.preventDefault();var b=new h;if(!c._selectedCompetencies.length){return}if(c._multiSelect){c._trigger("save",{competencyIds:c._selectedCompetencies})}else{c._trigger("save",{competencyId:c._selectedCompetencies[0]})}c.close();b.resolve()});var e=c._selectedCompetencies.slice(0);a.each(e,function(a,b){var e=c._find("[data-id="+b+"]");if(e.length){d.toggleItem(e);d.updateFocus(e)}})};i.prototype.close=function(){var a=this;a._popup.close();a._reset()};i.prototype.display=function(){var c=this;return a.when(f.get_string("competencypicker","tool_lp"),c._render()).then(function(a,b){c._popup=new e(a,b[0],c._afterRender.bind(c))}).catch(b.exception)};i.prototype._fetchCompetencies=function(a,d){var e=this;return c.call([{methodname:"core_competency_search_competencies",args:{searchtext:d,competencyframeworkid:a}}])[0].done(function(a){function b(a,c){for(var d=0;d
"),this._frameworks=[],this._reset(),this._pageContextId=pageContextId,this._pageContextIncludes=pageContextIncludes||"children",this._multiSelect=void 0===multiSelect||!0===multiSelect,singleFramework&&(this._frameworkId=singleFramework,this._singleFramework=!0)};return Picker.prototype._competencies=null,Picker.prototype._disallowedCompetencyIDs=null,Picker.prototype._eventNode=null,Picker.prototype._frameworks=null,Picker.prototype._frameworkId=null,Picker.prototype._pageContextId=null,Picker.prototype._pageContextIncludes=null,Picker.prototype._popup=null,Picker.prototype._searchText="",Picker.prototype._selectedCompetencies=null,Picker.prototype._singleFramework=!1,Picker.prototype._multiSelect=!0,Picker.prototype._onlyVisible=!0,Picker.prototype._afterRender=function(){var self=this,tree=new Tree(self._find("[data-enhance=linktree]"),self._multiSelect);self._find("[data-enhance=linktree]").show(),tree.on("selectionchanged",(function(evt,params){var selected=params.selected;evt.preventDefault();var validIds=[];$.each(selected,(function(index,item){var compId=$(item).data("id"),valid=!0;void 0===compId?valid=!1:$.each(self._disallowedCompetencyIDs,(function(i,id){id==compId&&(valid=!1)})),valid&&validIds.push(compId)})),self._selectedCompetencies=validIds,self._selectedCompetencies.length?self._find('[data-region="competencylinktree"] [data-action="add"]').removeAttr("disabled"):self._find('[data-region="competencylinktree"] [data-action="add"]').attr("disabled","disabled")})),self._singleFramework||self._find('[data-action="chooseframework"]').change((function(e){self._frameworkId=$(e.target).val(),self._loadCompetencies().then(self._refresh.bind(self)).catch(Notification.exception)})),self._find('[data-region="filtercompetencies"] button').click((function(e){return e.preventDefault(),$(e.target).attr("disabled","disabled"),self._searchText=self._find('[data-region="filtercompetencies"] input').val()||"",self._refresh().always((function(){$(e.target).removeAttr("disabled")}))})),self._find('[data-region="competencylinktree"] [data-action="cancel"]').click((function(e){e.preventDefault(),self.close()})),self._find('[data-region="competencylinktree"] [data-action="add"]').click((function(e){e.preventDefault();var pendingPromise=new Pending;self._selectedCompetencies.length&&(self._multiSelect?self._trigger("save",{competencyIds:self._selectedCompetencies}):self._trigger("save",{competencyId:self._selectedCompetencies[0]}),self.close(),pendingPromise.resolve())}));var currentItems=self._selectedCompetencies.slice(0);$.each(currentItems,(function(index,id){var node=self._find("[data-id="+id+"]");node.length&&(tree.toggleItem(node),tree.updateFocus(node))}))},Picker.prototype.close=function(){this._popup.close(),this._reset()},Picker.prototype.display=function(){var self=this;return $.when(Str.get_string("competencypicker","tool_lp"),self._render()).then((function(title,render){self._popup=new Dialogue(title,render[0],self._afterRender.bind(self))})).catch(Notification.exception)},Picker.prototype._fetchCompetencies=function(frameworkId,searchText){var self=this;return Ajax.call([{methodname:"core_competency_search_competencies",args:{searchtext:searchText,competencyframeworkid:frameworkId}}])[0].done((function(competencies){function addCompetencyChildren(parent,competencies){for(var i=0;i0?$.when():(self._singleFramework?Ajax.call([{methodname:"core_competency_read_competency_framework",args:{id:this._frameworkId}}])[0].then((function(framework){return[framework]})):Ajax.call([{methodname:"core_competency_list_competency_frameworks",args:{sort:"shortname",context:{contextid:self._pageContextId},includes:self._pageContextIncludes,onlyvisible:self._onlyVisible}}])[0]).done((function(frameworks){self._frameworks=frameworks})).fail(Notification.exception)},Picker.prototype.on=function(type,handler){this._eventNode.on(type,handler)},Picker.prototype._preRender=function(){var self=this;return self._loadFrameworks().then((function(){return!self._frameworkId&&self._frameworks.length>0&&(self._frameworkId=self._frameworks[0].id),self._frameworkId?self._loadCompetencies():(self._frameworks=[],$.when())}))},Picker.prototype._refresh=function(){var self=this;return self._render().then((function(html){self._find('[data-region="competencylinktree"]').replaceWith(html),self._afterRender()}))},Picker.prototype._render=function(){var self=this;return self._preRender().then((function(){self._singleFramework||$.each(self._frameworks,(function(i,framework){framework.id==self._frameworkId?framework.selected=!0:framework.selected=!1}));var context={competencies:self._competencies,framework:self._getFramework(self._frameworkId),frameworks:self._frameworks,search:self._searchText,singleFramework:self._singleFramework};return Templates.render("tool_lp/competency_picker",context)}))},Picker.prototype._reset=function(){this._competencies=[],this._disallowedCompetencyIDs=[],this._popup=null,this._searchText="",this._selectedCompetencies=[]},Picker.prototype.setDisallowedCompetencyIDs=function(ids){this._disallowedCompetencyIDs=ids},Picker.prototype._trigger=function(type,data){this._eventNode.trigger(type,[data])},Picker}));
+
+//# sourceMappingURL=competencypicker.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencypicker.min.js.map b/admin/tool/lp/amd/build/competencypicker.min.js.map
index 24af47b4232..6fca0dc076b 100644
--- a/admin/tool/lp/amd/build/competencypicker.min.js.map
+++ b/admin/tool/lp/amd/build/competencypicker.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/competencypicker.js"],"names":["define","$","Notification","Ajax","Templates","Dialogue","Str","Tree","Pending","Picker","pageContextId","singleFramework","pageContextIncludes","multiSelect","self","_eventNode","_frameworks","_reset","_pageContextId","_pageContextIncludes","_multiSelect","_frameworkId","_singleFramework","prototype","_competencies","_disallowedCompetencyIDs","_popup","_searchText","_selectedCompetencies","_onlyVisible","_afterRender","tree","_find","show","on","evt","params","selected","preventDefault","validIds","each","index","item","compId","data","valid","i","id","push","length","attr","removeAttr","change","e","target","val","_loadCompetencies","then","_refresh","bind","catch","exception","click","always","close","pendingPromise","_trigger","competencyIds","competencyId","resolve","currentItems","slice","node","toggleItem","updateFocus","display","when","get_string","_render","title","render","_fetchCompetencies","frameworkId","searchText","call","methodname","args","searchtext","competencyframeworkid","done","competencies","addCompetencyChildren","parent","parentid","haschildren","children","comp","fail","selector","getContent","find","_getFramework","fid","frm","f","_loadFrameworks","promise","framework","sort","context","contextid","includes","onlyvisible","frameworks","type","handler","_preRender","html","replaceWith","search","setDisallowedCompetencyIDs","ids","trigger"],"mappings":"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","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 .\n\n/**\n * Competency picker.\n *\n * To handle 'save' events use: picker.on('save')\n * This will receive a object with either a single 'competencyId', or an array in 'competencyIds'\n * depending on the value of multiSelect.\n *\n * @module tool_lp/competencypicker\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/templates',\n 'tool_lp/dialogue',\n 'core/str',\n 'tool_lp/tree',\n 'core/pending'\n ],\n function($, Notification, Ajax, Templates, Dialogue, Str, Tree, Pending) {\n\n /**\n * Competency picker class.\n * @param {Number} pageContextId The page context ID.\n * @param {Number|false} singleFramework The ID of the framework when limited to one.\n * @param {String} pageContextIncludes One of 'children', 'parents', 'self'.\n * @param {Boolean} multiSelect Support multi-select in the tree.\n */\n var Picker = function(pageContextId, singleFramework, pageContextIncludes, multiSelect) {\n var self = this;\n self._eventNode = $('');\n self._frameworks = [];\n self._reset();\n\n self._pageContextId = pageContextId;\n self._pageContextIncludes = pageContextIncludes || 'children';\n self._multiSelect = (typeof multiSelect === 'undefined' || multiSelect === true);\n if (singleFramework) {\n self._frameworkId = singleFramework;\n self._singleFramework = true;\n }\n };\n\n /** @property {Array} The competencies fetched. */\n Picker.prototype._competencies = null;\n /** @property {Array} The competencies that cannot be picked. */\n Picker.prototype._disallowedCompetencyIDs = null;\n /** @property {Node} The node we attach the events to. */\n Picker.prototype._eventNode = null;\n /** @property {Array} The list of frameworks fetched. */\n Picker.prototype._frameworks = null;\n /** @property {Number} The current framework ID. */\n Picker.prototype._frameworkId = null;\n /** @property {Number} The page context ID. */\n Picker.prototype._pageContextId = null;\n /** @property {Number} Relevant contexts inclusion. */\n Picker.prototype._pageContextIncludes = null;\n /** @property {Dialogue} The reference to the dialogue. */\n Picker.prototype._popup = null;\n /** @property {String} The string we filter the competencies with. */\n Picker.prototype._searchText = '';\n /** @property {Object} The competency that was selected. */\n Picker.prototype._selectedCompetencies = null;\n /** @property {Boolean} Whether we can browse frameworks or not. */\n Picker.prototype._singleFramework = false;\n /** @property {Boolean} Do we allow multi select? */\n Picker.prototype._multiSelect = true;\n /** @property {Boolean} Do we allow to display hidden framework? */\n Picker.prototype._onlyVisible = true;\n\n /**\n * Hook to executed after the view is rendered.\n *\n * @method _afterRender\n */\n Picker.prototype._afterRender = function() {\n var self = this;\n\n // Initialise the tree.\n var tree = new Tree(self._find('[data-enhance=linktree]'), self._multiSelect);\n\n // To prevent jiggling we only show the tree after it is enhanced.\n self._find('[data-enhance=linktree]').show();\n\n tree.on('selectionchanged', function(evt, params) {\n var selected = params.selected;\n evt.preventDefault();\n var validIds = [];\n $.each(selected, function(index, item) {\n var compId = $(item).data('id'),\n valid = true;\n\n if (typeof compId === 'undefined') {\n // Do not allow picking nodes with no id.\n valid = false;\n } else {\n $.each(self._disallowedCompetencyIDs, function(i, id) {\n if (id == compId) {\n valid = false;\n }\n });\n }\n if (valid) {\n validIds.push(compId);\n }\n });\n\n self._selectedCompetencies = validIds;\n\n // TODO Implement disabling of nodes in the tree module somehow.\n if (!self._selectedCompetencies.length) {\n self._find('[data-region=\"competencylinktree\"] [data-action=\"add\"]').attr('disabled', 'disabled');\n } else {\n self._find('[data-region=\"competencylinktree\"] [data-action=\"add\"]').removeAttr('disabled');\n }\n });\n\n // Add listener for framework change.\n if (!self._singleFramework) {\n self._find('[data-action=\"chooseframework\"]').change(function(e) {\n self._frameworkId = $(e.target).val();\n self._loadCompetencies().then(self._refresh.bind(self)).catch(Notification.exception);\n });\n }\n\n // Add listener for search.\n self._find('[data-region=\"filtercompetencies\"] button').click(function(e) {\n e.preventDefault();\n $(e.target).attr('disabled', 'disabled');\n self._searchText = self._find('[data-region=\"filtercompetencies\"] input').val() || '';\n return self._refresh().always(function() {\n $(e.target).removeAttr('disabled');\n });\n });\n\n // Add listener for cancel.\n self._find('[data-region=\"competencylinktree\"] [data-action=\"cancel\"]').click(function(e) {\n e.preventDefault();\n self.close();\n });\n\n // Add listener for add.\n self._find('[data-region=\"competencylinktree\"] [data-action=\"add\"]').click(function(e) {\n e.preventDefault();\n var pendingPromise = new Pending();\n if (!self._selectedCompetencies.length) {\n return;\n }\n\n if (self._multiSelect) {\n self._trigger('save', {competencyIds: self._selectedCompetencies});\n } else {\n // We checked above that the array has at least one value.\n self._trigger('save', {competencyId: self._selectedCompetencies[0]});\n }\n\n // The dialogue here is a YUI dialogue and doesn't support Promises at all.\n // However, it is typically synchronous so this shoudl suffice.\n self.close();\n pendingPromise.resolve();\n });\n\n // The list of selected competencies will be modified while looping (because of the listeners above).\n var currentItems = self._selectedCompetencies.slice(0);\n\n $.each(currentItems, function(index, id) {\n var node = self._find('[data-id=' + id + ']');\n if (node.length) {\n tree.toggleItem(node);\n tree.updateFocus(node);\n }\n });\n\n };\n\n /**\n * Close the dialogue.\n *\n * @method close\n */\n Picker.prototype.close = function() {\n var self = this;\n self._popup.close();\n self._reset();\n };\n\n /**\n * Opens the picker.\n *\n * @method display\n * @return {Promise}\n */\n Picker.prototype.display = function() {\n var self = this;\n return $.when(Str.get_string('competencypicker', 'tool_lp'), self._render())\n .then(function(title, render) {\n self._popup = new Dialogue(\n title,\n render[0],\n self._afterRender.bind(self)\n );\n return;\n }).catch(Notification.exception);\n };\n\n /**\n * Fetch the competencies.\n *\n * @param {Number} frameworkId The frameworkId.\n * @param {String} searchText Limit the competencies to those matching the text.\n * @method _fetchCompetencies\n * @return {Promise}\n */\n Picker.prototype._fetchCompetencies = function(frameworkId, searchText) {\n var self = this;\n\n return Ajax.call([\n {methodname: 'core_competency_search_competencies', args: {\n searchtext: searchText,\n competencyframeworkid: frameworkId\n }}\n ])[0].done(function(competencies) {\n /**\n * @param {Object} parent\n * @param {Array} competencies\n */\n function addCompetencyChildren(parent, competencies) {\n for (var i = 0; i < competencies.length; i++) {\n if (competencies[i].parentid == parent.id) {\n parent.haschildren = true;\n competencies[i].children = [];\n competencies[i].haschildren = false;\n parent.children[parent.children.length] = competencies[i];\n addCompetencyChildren(competencies[i], competencies);\n }\n }\n }\n\n // Expand the list of competencies into a tree.\n var i, comp;\n var tree = [];\n for (i = 0; i < competencies.length; i++) {\n comp = competencies[i];\n if (comp.parentid == \"0\") { // Loose check for now, because WS returns a string.\n comp.children = [];\n comp.haschildren = 0;\n tree[tree.length] = comp;\n addCompetencyChildren(comp, competencies);\n }\n }\n\n self._competencies = tree;\n\n }).fail(Notification.exception);\n };\n\n /**\n * Find a node in the dialogue.\n *\n * @param {String} selector\n * @return {JQuery}\n * @method _find\n */\n Picker.prototype._find = function(selector) {\n return $(this._popup.getContent()).find(selector);\n };\n\n /**\n * Convenience method to get a framework object.\n *\n * @param {Number} fid The framework ID.\n * @return {Object}\n * @method _getFramework\n */\n Picker.prototype._getFramework = function(fid) {\n var frm;\n $.each(this._frameworks, function(i, f) {\n if (f.id == fid) {\n frm = f;\n return;\n }\n });\n return frm;\n };\n\n /**\n * Load the competencies.\n *\n * @method _loadCompetencies\n * @return {Promise}\n */\n Picker.prototype._loadCompetencies = function() {\n return this._fetchCompetencies(this._frameworkId, this._searchText);\n };\n\n /**\n * Load the frameworks.\n *\n * @method _loadFrameworks\n * @return {Promise}\n */\n Picker.prototype._loadFrameworks = function() {\n var promise,\n self = this;\n\n // Quit early because we already have the data.\n if (self._frameworks.length > 0) {\n return $.when();\n }\n\n if (self._singleFramework) {\n promise = Ajax.call([\n {methodname: 'core_competency_read_competency_framework', args: {\n id: this._frameworkId\n }}\n ])[0].then(function(framework) {\n return [framework];\n });\n } else {\n promise = Ajax.call([\n {methodname: 'core_competency_list_competency_frameworks', args: {\n sort: 'shortname',\n context: {contextid: self._pageContextId},\n includes: self._pageContextIncludes,\n onlyvisible: self._onlyVisible\n }}\n ])[0];\n }\n\n return promise.done(function(frameworks) {\n self._frameworks = frameworks;\n }).fail(Notification.exception);\n };\n\n /**\n * Register an event listener.\n *\n * @param {String} type The event type.\n * @param {Function} handler The event listener.\n * @method on\n */\n Picker.prototype.on = function(type, handler) {\n this._eventNode.on(type, handler);\n };\n\n /**\n * Hook to executed before render.\n *\n * @method _preRender\n * @return {Promise}\n */\n Picker.prototype._preRender = function() {\n var self = this;\n return self._loadFrameworks().then(function() {\n if (!self._frameworkId && self._frameworks.length > 0) {\n self._frameworkId = self._frameworks[0].id;\n }\n\n // We could not set a framework ID, that probably means there are no frameworks accessible.\n if (!self._frameworkId) {\n self._frameworks = [];\n return $.when();\n }\n\n return self._loadCompetencies();\n });\n };\n\n /**\n * Refresh the view.\n *\n * @method _refresh\n * @return {Promise}\n */\n Picker.prototype._refresh = function() {\n var self = this;\n return self._render().then(function(html) {\n self._find('[data-region=\"competencylinktree\"]').replaceWith(html);\n self._afterRender();\n return;\n });\n };\n\n /**\n * Render the dialogue.\n *\n * @method _render\n * @return {Promise}\n */\n Picker.prototype._render = function() {\n var self = this;\n return self._preRender().then(function() {\n\n if (!self._singleFramework) {\n $.each(self._frameworks, function(i, framework) {\n if (framework.id == self._frameworkId) {\n framework.selected = true;\n } else {\n framework.selected = false;\n }\n });\n }\n\n var context = {\n competencies: self._competencies,\n framework: self._getFramework(self._frameworkId),\n frameworks: self._frameworks,\n search: self._searchText,\n singleFramework: self._singleFramework,\n };\n\n return Templates.render('tool_lp/competency_picker', context);\n });\n };\n\n /**\n * Reset the dialogue properties.\n *\n * This does not reset everything, just enough to reset the UI.\n *\n * @method _reset\n */\n Picker.prototype._reset = function() {\n this._competencies = [];\n this._disallowedCompetencyIDs = [];\n this._popup = null;\n this._searchText = '';\n this._selectedCompetencies = [];\n };\n\n /**\n * Set what competencies cannot be picked.\n *\n * This needs to be set after reset/close.\n *\n * @param {Number[]} ids The IDs.\n * @method _setDisallowedCompetencyIDs\n */\n Picker.prototype.setDisallowedCompetencyIDs = function(ids) {\n this._disallowedCompetencyIDs = ids;\n };\n\n /**\n * Trigger an event.\n *\n * @param {String} type The type of event.\n * @param {Object} data The data to pass to the listeners.\n * @method _reset\n */\n Picker.prototype._trigger = function(type, data) {\n this._eventNode.trigger(type, [data]);\n };\n\n return Picker;\n\n});\n"],"file":"competencypicker.min.js"}
\ No newline at end of file
+{"version":3,"file":"competencypicker.min.js","sources":["../src/competencypicker.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 .\n\n/**\n * Competency picker.\n *\n * To handle 'save' events use: picker.on('save')\n * This will receive a object with either a single 'competencyId', or an array in 'competencyIds'\n * depending on the value of multiSelect.\n *\n * @module tool_lp/competencypicker\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/templates',\n 'tool_lp/dialogue',\n 'core/str',\n 'tool_lp/tree',\n 'core/pending'\n ],\n function($, Notification, Ajax, Templates, Dialogue, Str, Tree, Pending) {\n\n /**\n * Competency picker class.\n * @param {Number} pageContextId The page context ID.\n * @param {Number|false} singleFramework The ID of the framework when limited to one.\n * @param {String} pageContextIncludes One of 'children', 'parents', 'self'.\n * @param {Boolean} multiSelect Support multi-select in the tree.\n */\n var Picker = function(pageContextId, singleFramework, pageContextIncludes, multiSelect) {\n var self = this;\n self._eventNode = $('');\n self._frameworks = [];\n self._reset();\n\n self._pageContextId = pageContextId;\n self._pageContextIncludes = pageContextIncludes || 'children';\n self._multiSelect = (typeof multiSelect === 'undefined' || multiSelect === true);\n if (singleFramework) {\n self._frameworkId = singleFramework;\n self._singleFramework = true;\n }\n };\n\n /** @property {Array} The competencies fetched. */\n Picker.prototype._competencies = null;\n /** @property {Array} The competencies that cannot be picked. */\n Picker.prototype._disallowedCompetencyIDs = null;\n /** @property {Node} The node we attach the events to. */\n Picker.prototype._eventNode = null;\n /** @property {Array} The list of frameworks fetched. */\n Picker.prototype._frameworks = null;\n /** @property {Number} The current framework ID. */\n Picker.prototype._frameworkId = null;\n /** @property {Number} The page context ID. */\n Picker.prototype._pageContextId = null;\n /** @property {Number} Relevant contexts inclusion. */\n Picker.prototype._pageContextIncludes = null;\n /** @property {Dialogue} The reference to the dialogue. */\n Picker.prototype._popup = null;\n /** @property {String} The string we filter the competencies with. */\n Picker.prototype._searchText = '';\n /** @property {Object} The competency that was selected. */\n Picker.prototype._selectedCompetencies = null;\n /** @property {Boolean} Whether we can browse frameworks or not. */\n Picker.prototype._singleFramework = false;\n /** @property {Boolean} Do we allow multi select? */\n Picker.prototype._multiSelect = true;\n /** @property {Boolean} Do we allow to display hidden framework? */\n Picker.prototype._onlyVisible = true;\n\n /**\n * Hook to executed after the view is rendered.\n *\n * @method _afterRender\n */\n Picker.prototype._afterRender = function() {\n var self = this;\n\n // Initialise the tree.\n var tree = new Tree(self._find('[data-enhance=linktree]'), self._multiSelect);\n\n // To prevent jiggling we only show the tree after it is enhanced.\n self._find('[data-enhance=linktree]').show();\n\n tree.on('selectionchanged', function(evt, params) {\n var selected = params.selected;\n evt.preventDefault();\n var validIds = [];\n $.each(selected, function(index, item) {\n var compId = $(item).data('id'),\n valid = true;\n\n if (typeof compId === 'undefined') {\n // Do not allow picking nodes with no id.\n valid = false;\n } else {\n $.each(self._disallowedCompetencyIDs, function(i, id) {\n if (id == compId) {\n valid = false;\n }\n });\n }\n if (valid) {\n validIds.push(compId);\n }\n });\n\n self._selectedCompetencies = validIds;\n\n // TODO Implement disabling of nodes in the tree module somehow.\n if (!self._selectedCompetencies.length) {\n self._find('[data-region=\"competencylinktree\"] [data-action=\"add\"]').attr('disabled', 'disabled');\n } else {\n self._find('[data-region=\"competencylinktree\"] [data-action=\"add\"]').removeAttr('disabled');\n }\n });\n\n // Add listener for framework change.\n if (!self._singleFramework) {\n self._find('[data-action=\"chooseframework\"]').change(function(e) {\n self._frameworkId = $(e.target).val();\n self._loadCompetencies().then(self._refresh.bind(self)).catch(Notification.exception);\n });\n }\n\n // Add listener for search.\n self._find('[data-region=\"filtercompetencies\"] button').click(function(e) {\n e.preventDefault();\n $(e.target).attr('disabled', 'disabled');\n self._searchText = self._find('[data-region=\"filtercompetencies\"] input').val() || '';\n return self._refresh().always(function() {\n $(e.target).removeAttr('disabled');\n });\n });\n\n // Add listener for cancel.\n self._find('[data-region=\"competencylinktree\"] [data-action=\"cancel\"]').click(function(e) {\n e.preventDefault();\n self.close();\n });\n\n // Add listener for add.\n self._find('[data-region=\"competencylinktree\"] [data-action=\"add\"]').click(function(e) {\n e.preventDefault();\n var pendingPromise = new Pending();\n if (!self._selectedCompetencies.length) {\n return;\n }\n\n if (self._multiSelect) {\n self._trigger('save', {competencyIds: self._selectedCompetencies});\n } else {\n // We checked above that the array has at least one value.\n self._trigger('save', {competencyId: self._selectedCompetencies[0]});\n }\n\n // The dialogue here is a YUI dialogue and doesn't support Promises at all.\n // However, it is typically synchronous so this shoudl suffice.\n self.close();\n pendingPromise.resolve();\n });\n\n // The list of selected competencies will be modified while looping (because of the listeners above).\n var currentItems = self._selectedCompetencies.slice(0);\n\n $.each(currentItems, function(index, id) {\n var node = self._find('[data-id=' + id + ']');\n if (node.length) {\n tree.toggleItem(node);\n tree.updateFocus(node);\n }\n });\n\n };\n\n /**\n * Close the dialogue.\n *\n * @method close\n */\n Picker.prototype.close = function() {\n var self = this;\n self._popup.close();\n self._reset();\n };\n\n /**\n * Opens the picker.\n *\n * @method display\n * @return {Promise}\n */\n Picker.prototype.display = function() {\n var self = this;\n return $.when(Str.get_string('competencypicker', 'tool_lp'), self._render())\n .then(function(title, render) {\n self._popup = new Dialogue(\n title,\n render[0],\n self._afterRender.bind(self)\n );\n return;\n }).catch(Notification.exception);\n };\n\n /**\n * Fetch the competencies.\n *\n * @param {Number} frameworkId The frameworkId.\n * @param {String} searchText Limit the competencies to those matching the text.\n * @method _fetchCompetencies\n * @return {Promise}\n */\n Picker.prototype._fetchCompetencies = function(frameworkId, searchText) {\n var self = this;\n\n return Ajax.call([\n {methodname: 'core_competency_search_competencies', args: {\n searchtext: searchText,\n competencyframeworkid: frameworkId\n }}\n ])[0].done(function(competencies) {\n /**\n * @param {Object} parent\n * @param {Array} competencies\n */\n function addCompetencyChildren(parent, competencies) {\n for (var i = 0; i < competencies.length; i++) {\n if (competencies[i].parentid == parent.id) {\n parent.haschildren = true;\n competencies[i].children = [];\n competencies[i].haschildren = false;\n parent.children[parent.children.length] = competencies[i];\n addCompetencyChildren(competencies[i], competencies);\n }\n }\n }\n\n // Expand the list of competencies into a tree.\n var i, comp;\n var tree = [];\n for (i = 0; i < competencies.length; i++) {\n comp = competencies[i];\n if (comp.parentid == \"0\") { // Loose check for now, because WS returns a string.\n comp.children = [];\n comp.haschildren = 0;\n tree[tree.length] = comp;\n addCompetencyChildren(comp, competencies);\n }\n }\n\n self._competencies = tree;\n\n }).fail(Notification.exception);\n };\n\n /**\n * Find a node in the dialogue.\n *\n * @param {String} selector\n * @return {JQuery}\n * @method _find\n */\n Picker.prototype._find = function(selector) {\n return $(this._popup.getContent()).find(selector);\n };\n\n /**\n * Convenience method to get a framework object.\n *\n * @param {Number} fid The framework ID.\n * @return {Object}\n * @method _getFramework\n */\n Picker.prototype._getFramework = function(fid) {\n var frm;\n $.each(this._frameworks, function(i, f) {\n if (f.id == fid) {\n frm = f;\n return;\n }\n });\n return frm;\n };\n\n /**\n * Load the competencies.\n *\n * @method _loadCompetencies\n * @return {Promise}\n */\n Picker.prototype._loadCompetencies = function() {\n return this._fetchCompetencies(this._frameworkId, this._searchText);\n };\n\n /**\n * Load the frameworks.\n *\n * @method _loadFrameworks\n * @return {Promise}\n */\n Picker.prototype._loadFrameworks = function() {\n var promise,\n self = this;\n\n // Quit early because we already have the data.\n if (self._frameworks.length > 0) {\n return $.when();\n }\n\n if (self._singleFramework) {\n promise = Ajax.call([\n {methodname: 'core_competency_read_competency_framework', args: {\n id: this._frameworkId\n }}\n ])[0].then(function(framework) {\n return [framework];\n });\n } else {\n promise = Ajax.call([\n {methodname: 'core_competency_list_competency_frameworks', args: {\n sort: 'shortname',\n context: {contextid: self._pageContextId},\n includes: self._pageContextIncludes,\n onlyvisible: self._onlyVisible\n }}\n ])[0];\n }\n\n return promise.done(function(frameworks) {\n self._frameworks = frameworks;\n }).fail(Notification.exception);\n };\n\n /**\n * Register an event listener.\n *\n * @param {String} type The event type.\n * @param {Function} handler The event listener.\n * @method on\n */\n Picker.prototype.on = function(type, handler) {\n this._eventNode.on(type, handler);\n };\n\n /**\n * Hook to executed before render.\n *\n * @method _preRender\n * @return {Promise}\n */\n Picker.prototype._preRender = function() {\n var self = this;\n return self._loadFrameworks().then(function() {\n if (!self._frameworkId && self._frameworks.length > 0) {\n self._frameworkId = self._frameworks[0].id;\n }\n\n // We could not set a framework ID, that probably means there are no frameworks accessible.\n if (!self._frameworkId) {\n self._frameworks = [];\n return $.when();\n }\n\n return self._loadCompetencies();\n });\n };\n\n /**\n * Refresh the view.\n *\n * @method _refresh\n * @return {Promise}\n */\n Picker.prototype._refresh = function() {\n var self = this;\n return self._render().then(function(html) {\n self._find('[data-region=\"competencylinktree\"]').replaceWith(html);\n self._afterRender();\n return;\n });\n };\n\n /**\n * Render the dialogue.\n *\n * @method _render\n * @return {Promise}\n */\n Picker.prototype._render = function() {\n var self = this;\n return self._preRender().then(function() {\n\n if (!self._singleFramework) {\n $.each(self._frameworks, function(i, framework) {\n if (framework.id == self._frameworkId) {\n framework.selected = true;\n } else {\n framework.selected = false;\n }\n });\n }\n\n var context = {\n competencies: self._competencies,\n framework: self._getFramework(self._frameworkId),\n frameworks: self._frameworks,\n search: self._searchText,\n singleFramework: self._singleFramework,\n };\n\n return Templates.render('tool_lp/competency_picker', context);\n });\n };\n\n /**\n * Reset the dialogue properties.\n *\n * This does not reset everything, just enough to reset the UI.\n *\n * @method _reset\n */\n Picker.prototype._reset = function() {\n this._competencies = [];\n this._disallowedCompetencyIDs = [];\n this._popup = null;\n this._searchText = '';\n this._selectedCompetencies = [];\n };\n\n /**\n * Set what competencies cannot be picked.\n *\n * This needs to be set after reset/close.\n *\n * @param {Number[]} ids The IDs.\n * @method _setDisallowedCompetencyIDs\n */\n Picker.prototype.setDisallowedCompetencyIDs = function(ids) {\n this._disallowedCompetencyIDs = ids;\n };\n\n /**\n * Trigger an event.\n *\n * @param {String} type The type of event.\n * @param {Object} data The data to pass to the listeners.\n * @method _reset\n */\n Picker.prototype._trigger = function(type, data) {\n this._eventNode.trigger(type, [data]);\n };\n\n return Picker;\n\n});\n"],"names":["define","$","Notification","Ajax","Templates","Dialogue","Str","Tree","Pending","Picker","pageContextId","singleFramework","pageContextIncludes","multiSelect","this","_eventNode","_frameworks","_reset","_pageContextId","_pageContextIncludes","_multiSelect","_frameworkId","_singleFramework","prototype","_competencies","_disallowedCompetencyIDs","_popup","_searchText","_selectedCompetencies","_onlyVisible","_afterRender","self","tree","_find","show","on","evt","params","selected","preventDefault","validIds","each","index","item","compId","data","valid","i","id","push","length","removeAttr","attr","change","e","target","val","_loadCompetencies","then","_refresh","bind","catch","exception","click","always","close","pendingPromise","_trigger","competencyIds","competencyId","resolve","currentItems","slice","node","toggleItem","updateFocus","display","when","get_string","_render","title","render","_fetchCompetencies","frameworkId","searchText","call","methodname","args","searchtext","competencyframeworkid","done","competencies","addCompetencyChildren","parent","parentid","haschildren","children","comp","fail","selector","getContent","find","_getFramework","fid","frm","f","_loadFrameworks","framework","sort","context","contextid","includes","onlyvisible","frameworks","type","handler","_preRender","html","replaceWith","search","setDisallowedCompetencyIDs","ids","trigger"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencypicker_user_plans.min.js b/admin/tool/lp/amd/build/competencypicker_user_plans.min.js
index 460dd5cb7ad..77da9c7c7b7 100644
--- a/admin/tool/lp/amd/build/competencypicker_user_plans.min.js
+++ b/admin/tool/lp/amd/build/competencypicker_user_plans.min.js
@@ -1,2 +1,15 @@
-define ("tool_lp/competencypicker_user_plans",["jquery","core/notification","core/ajax","core/templates","core/str","tool_lp/tree","tool_lp/competencypicker"],function(a,b,c,d,e,f,g){var h=function(a,b,c){g.prototype.constructor.apply(this,[1,!1,"self",c]);this._userId=a;this._plans=[];if(b){this._planId=b;this._singlePlan=!0}};h.prototype=Object.create(g.prototype);h.prototype._plans=null;h.prototype._planId=null;h.prototype._singlePlan=!1;h.prototype._userId=null;h.prototype._afterRender=function(){var c=this;g.prototype._afterRender.apply(c,arguments);if(!c._singlePlan){c._find("[data-action=\"chooseplan\"]").change(function(d){c._planId=a(d.target).val();c._loadCompetencies().then(c._refresh.bind(c)).catch(b.exception)})}};h.prototype._fetchCompetencies=function(a,d){var e=this;return c.call([{methodname:"core_competency_list_plan_competencies",args:{id:a}}])[0].done(function(a){var b,c,f=[];for(b=0;bc.shortname.toLowerCase().indexOf(d.toLowerCase())){continue}c.children=[];c.haschildren=0;f.push(c)}e._competencies=f}).fail(b.exception)};h.prototype._getPlan=function(b){var c;a.each(this._plans,function(a,d){if(d.id==b){c=d}});return c};h.prototype._loadCompetencies=function(){return this._fetchCompetencies(this._planId,this._searchText)};h.prototype._loadPlans=function(){var d,e=this;if(00?$.when():(self._singlePlan?Ajax.call([{methodname:"core_competency_read_plan",args:{id:this._planId}}])[0].then((function(plan){return[plan]})):Ajax.call([{methodname:"core_competency_list_user_plans",args:{userid:self._userId}}])[0]).done((function(plans){self._plans=plans})).fail(Notification.exception)},Picker.prototype._preRender=function(){var self=this;return self._loadPlans().then((function(){return!self._planId&&self._plans.length>0&&(self._planId=self._plans[0].id),self._planId?self._loadCompetencies():(self._plans=[],$.when())}))},Picker.prototype._render=function(){var self=this;return self._preRender().then((function(){self._singlePlan||$.each(self._plans,(function(i,plan){plan.id==self._planId?plan.selected=!0:plan.selected=!1}));var context={competencies:self._competencies,plan:self._getPlan(self._planId),plans:self._plans,search:self._searchText,singlePlan:self._singlePlan};return Templates.render("tool_lp/competency_picker_user_plans",context)}))},Picker}));
+
+//# sourceMappingURL=competencypicker_user_plans.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencypicker_user_plans.min.js.map b/admin/tool/lp/amd/build/competencypicker_user_plans.min.js.map
index c84dcf7a316..26cd77c5717 100644
--- a/admin/tool/lp/amd/build/competencypicker_user_plans.min.js.map
+++ b/admin/tool/lp/amd/build/competencypicker_user_plans.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/competencypicker_user_plans.js"],"names":["define","$","Notification","Ajax","Templates","Str","Tree","PickerBase","Picker","userId","singlePlan","multiSelect","prototype","constructor","apply","_userId","_plans","_planId","_singlePlan","Object","create","_afterRender","self","arguments","_find","change","e","target","val","_loadCompetencies","then","_refresh","bind","catch","exception","_fetchCompetencies","planId","searchText","call","methodname","args","id","done","competencies","i","comp","tree","length","competency","shortname","toLowerCase","indexOf","children","haschildren","push","_competencies","fail","_getPlan","plan","each","f","_searchText","_loadPlans","promise","when","userid","plans","_preRender","_render","selected","context","search","render"],"mappings":"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","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 .\n\n/**\n * Competency picker from user plans.\n *\n * To handle 'save' events use: picker.on('save').\n *\n * This will receive a object with either a single 'competencyId', or an array in 'competencyIds'\n * depending on the value of multiSelect.\n *\n * @module tool_lp/competencypicker_user_plans\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/templates',\n 'core/str',\n 'tool_lp/tree',\n 'tool_lp/competencypicker'\n ],\n function($, Notification, Ajax, Templates, Str, Tree, PickerBase) {\n\n /**\n * Competency picker in plan class.\n *\n * @class tool_lp/competencypicker_user_plans\n * @param {Number} userId\n * @param {Number|false} singlePlan The ID of the plan when limited to one.\n * @param {Boolean} multiSelect Support multi-select in the tree.\n */\n var Picker = function(userId, singlePlan, multiSelect) {\n PickerBase.prototype.constructor.apply(this, [1, false, 'self', multiSelect]);\n this._userId = userId;\n this._plans = [];\n\n if (singlePlan) {\n this._planId = singlePlan;\n this._singlePlan = true;\n }\n };\n Picker.prototype = Object.create(PickerBase.prototype);\n\n /** @property {Array} The list of plans fetched. */\n Picker.prototype._plans = null;\n /** @property {Number} The current plan ID. */\n Picker.prototype._planId = null;\n /** @property {Boolean} Whether we can browse plans or not. */\n Picker.prototype._singlePlan = false;\n /** @property {Number} The user the plans belongs to. */\n Picker.prototype._userId = null;\n\n /**\n * Hook to executed after the view is rendered.\n *\n * @method _afterRender\n */\n Picker.prototype._afterRender = function() {\n var self = this;\n PickerBase.prototype._afterRender.apply(self, arguments);\n\n // Add listener for framework change.\n if (!self._singlePlan) {\n self._find('[data-action=\"chooseplan\"]').change(function(e) {\n self._planId = $(e.target).val();\n self._loadCompetencies().then(self._refresh.bind(self))\n .catch(Notification.exception);\n });\n }\n };\n\n /**\n * Fetch the competencies.\n *\n * @param {Number} planId The planId.\n * @param {String} searchText Limit the competencies to those matching the text.\n * @method _fetchCompetencies\n * @return {Promise} The promise object.\n */\n Picker.prototype._fetchCompetencies = function(planId, searchText) {\n var self = this;\n\n return Ajax.call([\n {methodname: 'core_competency_list_plan_competencies', args: {\n id: planId\n }}\n ])[0].done(function(competencies) {\n\n // Expand the list of competencies into a fake tree.\n var i, comp;\n var tree = [];\n for (i = 0; i < competencies.length; i++) {\n comp = competencies[i].competency;\n if (comp.shortname.toLowerCase().indexOf(searchText.toLowerCase()) < 0) {\n continue;\n }\n comp.children = [];\n comp.haschildren = 0;\n tree.push(comp);\n }\n\n self._competencies = tree;\n\n }).fail(Notification.exception);\n };\n\n /**\n * Convenience method to get a plan object.\n *\n * @param {Number} id The plan ID.\n * @return {Object|undefined} The plan.\n * @method _getPlan\n */\n Picker.prototype._getPlan = function(id) {\n var plan;\n $.each(this._plans, function(i, f) {\n if (f.id == id) {\n plan = f;\n return;\n }\n });\n return plan;\n };\n\n /**\n * Load the competencies.\n *\n * @method _loadCompetencies\n * @return {Promise}\n */\n Picker.prototype._loadCompetencies = function() {\n return this._fetchCompetencies(this._planId, this._searchText);\n };\n\n /**\n * Load the plans.\n *\n * @method _loadPlans\n * @return {Promise}\n */\n Picker.prototype._loadPlans = function() {\n var promise,\n self = this;\n\n // Quit early because we already have the data.\n if (self._plans.length > 0) {\n return $.when();\n }\n\n if (self._singlePlan) {\n promise = Ajax.call([\n {methodname: 'core_competency_read_plan', args: {\n id: this._planId\n }}\n ])[0].then(function(plan) {\n return [plan];\n });\n } else {\n promise = Ajax.call([\n {methodname: 'core_competency_list_user_plans', args: {\n userid: self._userId\n }}\n ])[0];\n }\n\n return promise.done(function(plans) {\n self._plans = plans;\n }).fail(Notification.exception);\n };\n\n /**\n * Hook to executed before render.\n *\n * @method _preRender\n * @return {Promise}\n */\n Picker.prototype._preRender = function() {\n var self = this;\n return self._loadPlans().then(function() {\n if (!self._planId && self._plans.length > 0) {\n self._planId = self._plans[0].id;\n }\n\n // We could not set a framework ID, that probably means there are no frameworks accessible.\n if (!self._planId) {\n self._plans = [];\n return $.when();\n }\n\n return self._loadCompetencies();\n });\n };\n\n /**\n * Render the dialogue.\n *\n * @method _render\n * @return {Promise}\n */\n Picker.prototype._render = function() {\n var self = this;\n return self._preRender().then(function() {\n\n if (!self._singlePlan) {\n $.each(self._plans, function(i, plan) {\n if (plan.id == self._planId) {\n plan.selected = true;\n } else {\n plan.selected = false;\n }\n });\n }\n\n var context = {\n competencies: self._competencies,\n plan: self._getPlan(self._planId),\n plans: self._plans,\n search: self._searchText,\n singlePlan: self._singlePlan,\n };\n\n return Templates.render('tool_lp/competency_picker_user_plans', context);\n });\n };\n\n return Picker;\n});\n"],"file":"competencypicker_user_plans.min.js"}
\ No newline at end of file
+{"version":3,"file":"competencypicker_user_plans.min.js","sources":["../src/competencypicker_user_plans.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 .\n\n/**\n * Competency picker from user plans.\n *\n * To handle 'save' events use: picker.on('save').\n *\n * This will receive a object with either a single 'competencyId', or an array in 'competencyIds'\n * depending on the value of multiSelect.\n *\n * @module tool_lp/competencypicker_user_plans\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/templates',\n 'core/str',\n 'tool_lp/tree',\n 'tool_lp/competencypicker'\n ],\n function($, Notification, Ajax, Templates, Str, Tree, PickerBase) {\n\n /**\n * Competency picker in plan class.\n *\n * @class tool_lp/competencypicker_user_plans\n * @param {Number} userId\n * @param {Number|false} singlePlan The ID of the plan when limited to one.\n * @param {Boolean} multiSelect Support multi-select in the tree.\n */\n var Picker = function(userId, singlePlan, multiSelect) {\n PickerBase.prototype.constructor.apply(this, [1, false, 'self', multiSelect]);\n this._userId = userId;\n this._plans = [];\n\n if (singlePlan) {\n this._planId = singlePlan;\n this._singlePlan = true;\n }\n };\n Picker.prototype = Object.create(PickerBase.prototype);\n\n /** @property {Array} The list of plans fetched. */\n Picker.prototype._plans = null;\n /** @property {Number} The current plan ID. */\n Picker.prototype._planId = null;\n /** @property {Boolean} Whether we can browse plans or not. */\n Picker.prototype._singlePlan = false;\n /** @property {Number} The user the plans belongs to. */\n Picker.prototype._userId = null;\n\n /**\n * Hook to executed after the view is rendered.\n *\n * @method _afterRender\n */\n Picker.prototype._afterRender = function() {\n var self = this;\n PickerBase.prototype._afterRender.apply(self, arguments);\n\n // Add listener for framework change.\n if (!self._singlePlan) {\n self._find('[data-action=\"chooseplan\"]').change(function(e) {\n self._planId = $(e.target).val();\n self._loadCompetencies().then(self._refresh.bind(self))\n .catch(Notification.exception);\n });\n }\n };\n\n /**\n * Fetch the competencies.\n *\n * @param {Number} planId The planId.\n * @param {String} searchText Limit the competencies to those matching the text.\n * @method _fetchCompetencies\n * @return {Promise} The promise object.\n */\n Picker.prototype._fetchCompetencies = function(planId, searchText) {\n var self = this;\n\n return Ajax.call([\n {methodname: 'core_competency_list_plan_competencies', args: {\n id: planId\n }}\n ])[0].done(function(competencies) {\n\n // Expand the list of competencies into a fake tree.\n var i, comp;\n var tree = [];\n for (i = 0; i < competencies.length; i++) {\n comp = competencies[i].competency;\n if (comp.shortname.toLowerCase().indexOf(searchText.toLowerCase()) < 0) {\n continue;\n }\n comp.children = [];\n comp.haschildren = 0;\n tree.push(comp);\n }\n\n self._competencies = tree;\n\n }).fail(Notification.exception);\n };\n\n /**\n * Convenience method to get a plan object.\n *\n * @param {Number} id The plan ID.\n * @return {Object|undefined} The plan.\n * @method _getPlan\n */\n Picker.prototype._getPlan = function(id) {\n var plan;\n $.each(this._plans, function(i, f) {\n if (f.id == id) {\n plan = f;\n return;\n }\n });\n return plan;\n };\n\n /**\n * Load the competencies.\n *\n * @method _loadCompetencies\n * @return {Promise}\n */\n Picker.prototype._loadCompetencies = function() {\n return this._fetchCompetencies(this._planId, this._searchText);\n };\n\n /**\n * Load the plans.\n *\n * @method _loadPlans\n * @return {Promise}\n */\n Picker.prototype._loadPlans = function() {\n var promise,\n self = this;\n\n // Quit early because we already have the data.\n if (self._plans.length > 0) {\n return $.when();\n }\n\n if (self._singlePlan) {\n promise = Ajax.call([\n {methodname: 'core_competency_read_plan', args: {\n id: this._planId\n }}\n ])[0].then(function(plan) {\n return [plan];\n });\n } else {\n promise = Ajax.call([\n {methodname: 'core_competency_list_user_plans', args: {\n userid: self._userId\n }}\n ])[0];\n }\n\n return promise.done(function(plans) {\n self._plans = plans;\n }).fail(Notification.exception);\n };\n\n /**\n * Hook to executed before render.\n *\n * @method _preRender\n * @return {Promise}\n */\n Picker.prototype._preRender = function() {\n var self = this;\n return self._loadPlans().then(function() {\n if (!self._planId && self._plans.length > 0) {\n self._planId = self._plans[0].id;\n }\n\n // We could not set a framework ID, that probably means there are no frameworks accessible.\n if (!self._planId) {\n self._plans = [];\n return $.when();\n }\n\n return self._loadCompetencies();\n });\n };\n\n /**\n * Render the dialogue.\n *\n * @method _render\n * @return {Promise}\n */\n Picker.prototype._render = function() {\n var self = this;\n return self._preRender().then(function() {\n\n if (!self._singlePlan) {\n $.each(self._plans, function(i, plan) {\n if (plan.id == self._planId) {\n plan.selected = true;\n } else {\n plan.selected = false;\n }\n });\n }\n\n var context = {\n competencies: self._competencies,\n plan: self._getPlan(self._planId),\n plans: self._plans,\n search: self._searchText,\n singlePlan: self._singlePlan,\n };\n\n return Templates.render('tool_lp/competency_picker_user_plans', context);\n });\n };\n\n return Picker;\n});\n"],"names":["define","$","Notification","Ajax","Templates","Str","Tree","PickerBase","Picker","userId","singlePlan","multiSelect","prototype","constructor","apply","this","_userId","_plans","_planId","_singlePlan","Object","create","_afterRender","self","arguments","_find","change","e","target","val","_loadCompetencies","then","_refresh","bind","catch","exception","_fetchCompetencies","planId","searchText","call","methodname","args","id","done","competencies","i","comp","tree","length","competency","shortname","toLowerCase","indexOf","children","haschildren","push","_competencies","fail","_getPlan","plan","each","f","_searchText","_loadPlans","when","userid","plans","_preRender","_render","selected","context","search","render"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencyruleconfig.min.js b/admin/tool/lp/amd/build/competencyruleconfig.min.js
index d52ffcb4aec..11b49530409 100644
--- a/admin/tool/lp/amd/build/competencyruleconfig.min.js
+++ b/admin/tool/lp/amd/build/competencyruleconfig.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/competencyruleconfig",["jquery","core/notification","core/templates","tool_lp/dialogue","tool_lp/competency_outcomes","core/str"],function(a,b,c,d,e,f){var g=function(b,c){this._eventNode=a("");this._tree=b;this._rulesModules=c;this._setUp()};g.prototype._competency=null;g.prototype._eventNode=null;g.prototype._outcomesOption=null;g.prototype._popup=null;g.prototype._ready=null;g.prototype._rules=null;g.prototype._rulesModules=null;g.prototype._tree=null;g.prototype._afterChange=function(){if(!this._isValid()){this._find("[data-action=\"save\"]").prop("disabled",!0)}else{this._find("[data-action=\"save\"]").prop("disabled",!1)}};g.prototype._afterRuleConfigChange=function(a,b){if(b!=this._getRule()){return}this._afterChange()};g.prototype._afterRender=function(){var a=this;a._find("[name=\"outcome\"]").on("change",function(){a._switchedOutcome()}).trigger("change");a._find("[name=\"rule\"]").on("change",function(){a._switchedRule()}).trigger("change");a._find("[data-action=\"save\"]").on("click",function(){a._trigger("save",a._getConfig());a.close()});a._find("[data-action=\"cancel\"]").on("click",function(){a.close()})};g.prototype.canBeConfigured=function(){var b=!1;a.each(this._rules,function(a,c){if(c.canConfig()){b=!0}});return b};g.prototype.close=function(){this._popup.close();this._popup=null};g.prototype.display=function(){var c=this;if(!c._competency){return!1}return a.when(f.get_string("competencyrule","tool_lp"),c._render()).then(function(a,b){c._popup=new d(a,b[0],c._afterRender.bind(c))}).fail(b.exception)};g.prototype._find=function(b){return a(this._popup.getContent()).find(b)};g.prototype._getApplicableOutcomesOptions=function(){var b=this,c=[];a.each(b._outcomesOption,function(a,d){c.push({code:d.code,name:d.name,selected:d.code==b._competency.ruleoutcome?!0:!1})});return c};g.prototype._getApplicableRulesOptions=function(){var b=this,c=[];a.each(b._rules,function(a,d){if(!d.canConfig()){return}c.push({name:b._getRuleName(d.getType()),type:d.getType(),selected:d.getType()==b._competency.ruletype?!0:!1})});return c};g.prototype._getConfig=function(){var a=this._getRule();return{ruletype:a?a.getType():null,ruleconfig:a?a.getConfig():null,ruleoutcome:this._getOutcome()}};g.prototype._getOutcome=function(){return this._find("[name=\"outcome\"]").val()};g.prototype._getRule=function(){var b,c=this._find("[name=\"rule\"]").val();a.each(this._rules,function(a,d){if(d.getType()==c){b=d}});return b};g.prototype._getRuleName=function(b){var c=this,d;a.each(c._rulesModules,function(a,c){if(c.type==b){d=c.name}});return d};g.prototype._initOutcomes=function(){var a=this;return e.getAll().then(function(b){a._outcomesOption=b})};g.prototype._initRules=function(){var b=this,c=[];a.each(b._rules,function(d,e){var f=e.init().then(function(){e.setTargetCompetency(b._competency);e.on("change",b._afterRuleConfigChange.bind(b))},function(){b._rules.splice(d,1);return a.when()});c.push(f)});return a.when.apply(a.when,c)};g.prototype._isValid=function(){var a=this._getOutcome(),b=this._getRule();if(a==e.NONE){return!0}else if(!b){return!1}return b.isValid()};g.prototype.on=function(a,b){this._eventNode.on(a,b)};g.prototype._preRender=function(){return this.ready()};g.prototype.ready=function(){return this._ready.promise()};g.prototype._render=function(){var a=this;return this._preRender().then(function(){var b;if(!a.canBeConfigured()){b=!1}else{b={};b.outcomes=a._getApplicableOutcomesOptions();b.rules=a._getApplicableRulesOptions()}var d={competencyshortname:a._competency.shortname,config:b};return c.render("tool_lp/competency_rule_config",d)})};g.prototype.setTargetCompetencyId=function(b){var c=this;c._competency=c._tree.getCompetency(b);a.each(c._rules,function(a,b){b.setTargetCompetency(c._competency)})};g.prototype._setUp=function(){var b=this,c=[],d=[];b._ready=a.Deferred();b._rules=[];a.each(b._rulesModules,function(a,b){d.push(b.amd)});require(d,function(){a.each(arguments,function(a,c){var d=new c(b._tree);b._rules.push(d)});c.push(b._initRules());c.push(b._initOutcomes());a.when.apply(a.when,c).always(function(){b._ready.resolve()})})};g.prototype._switchedOutcome=function(){var a=this,b=a._getOutcome();if(b==e.NONE){a._find("[data-region=\"rule-type\"]").hide().find("[name=\"rule\"]").val(-1);a._find("[data-region=\"rule-config\"]").empty().hide();a._afterChange();return}a._find("[data-region=\"rule-type\"]").show();a._find("[data-region=\"rule-config\"]").show();a._afterChange()};g.prototype._switchedRule=function(){var a=this,b=a._find("[data-region=\"rule-config\"]"),c=a._getRule();if(!c){b.empty().hide();a._afterChange();return}c.injectTemplate(b).then(function(){b.show()}).always(function(){a._afterChange()}).catch(function(){b.empty().hide()})};g.prototype._trigger=function(a,b){this._eventNode.trigger(a,[b])};return g});
-//# sourceMappingURL=competencyruleconfig.min.js.map
+/**
+ * Competency rule config.
+ *
+ * @module tool_lp/competencyruleconfig
+ * @copyright 2015 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/competencyruleconfig",["jquery","core/notification","core/templates","tool_lp/dialogue","tool_lp/competency_outcomes","core/str"],(function($,Notification,Templates,Dialogue,Outcomes,Str){var RuleConfig=function(tree,rulesModules){this._eventNode=$(""),this._tree=tree,this._rulesModules=rulesModules,this._setUp()};return RuleConfig.prototype._competency=null,RuleConfig.prototype._eventNode=null,RuleConfig.prototype._outcomesOption=null,RuleConfig.prototype._popup=null,RuleConfig.prototype._ready=null,RuleConfig.prototype._rules=null,RuleConfig.prototype._rulesModules=null,RuleConfig.prototype._tree=null,RuleConfig.prototype._afterChange=function(){this._isValid()?this._find('[data-action="save"]').prop("disabled",!1):this._find('[data-action="save"]').prop("disabled",!0)},RuleConfig.prototype._afterRuleConfigChange=function(e,rule){rule==this._getRule()&&this._afterChange()},RuleConfig.prototype._afterRender=function(){var self=this;self._find('[name="outcome"]').on("change",(function(){self._switchedOutcome()})).trigger("change"),self._find('[name="rule"]').on("change",(function(){self._switchedRule()})).trigger("change"),self._find('[data-action="save"]').on("click",(function(){self._trigger("save",self._getConfig()),self.close()})),self._find('[data-action="cancel"]').on("click",(function(){self.close()}))},RuleConfig.prototype.canBeConfigured=function(){var can=!1;return $.each(this._rules,(function(index,rule){rule.canConfig()&&(can=!0)})),can},RuleConfig.prototype.close=function(){this._popup.close(),this._popup=null},RuleConfig.prototype.display=function(){var self=this;return!!self._competency&&$.when(Str.get_string("competencyrule","tool_lp"),self._render()).then((function(title,render){self._popup=new Dialogue(title,render[0],self._afterRender.bind(self))})).fail(Notification.exception)},RuleConfig.prototype._find=function(selector){return $(this._popup.getContent()).find(selector)},RuleConfig.prototype._getApplicableOutcomesOptions=function(){var self=this,options=[];return $.each(self._outcomesOption,(function(index,outcome){options.push({code:outcome.code,name:outcome.name,selected:outcome.code==self._competency.ruleoutcome})})),options},RuleConfig.prototype._getApplicableRulesOptions=function(){var self=this,options=[];return $.each(self._rules,(function(index,rule){rule.canConfig()&&options.push({name:self._getRuleName(rule.getType()),type:rule.getType(),selected:rule.getType()==self._competency.ruletype})})),options},RuleConfig.prototype._getConfig=function(){var rule=this._getRule();return{ruletype:rule?rule.getType():null,ruleconfig:rule?rule.getConfig():null,ruleoutcome:this._getOutcome()}},RuleConfig.prototype._getOutcome=function(){return this._find('[name="outcome"]').val()},RuleConfig.prototype._getRule=function(){var result,type=this._find('[name="rule"]').val();return $.each(this._rules,(function(index,rule){rule.getType()!=type||(result=rule)})),result},RuleConfig.prototype._getRuleName=function(type){var name;return $.each(this._rulesModules,(function(index,modInfo){modInfo.type!=type||(name=modInfo.name)})),name},RuleConfig.prototype._initOutcomes=function(){var self=this;return Outcomes.getAll().then((function(outcomes){self._outcomesOption=outcomes}))},RuleConfig.prototype._initRules=function(){var self=this,promises=[];return $.each(self._rules,(function(index,rule){var promise=rule.init().then((function(){rule.setTargetCompetency(self._competency),rule.on("change",self._afterRuleConfigChange.bind(self))}),(function(){return self._rules.splice(index,1),$.when()}));promises.push(promise)})),$.when.apply($.when,promises)},RuleConfig.prototype._isValid=function(){var outcome=this._getOutcome(),rule=this._getRule();return outcome==Outcomes.NONE||!!rule&&rule.isValid()},RuleConfig.prototype.on=function(type,handler){this._eventNode.on(type,handler)},RuleConfig.prototype._preRender=function(){return this.ready()},RuleConfig.prototype.ready=function(){return this._ready.promise()},RuleConfig.prototype._render=function(){var self=this;return this._preRender().then((function(){var config;self.canBeConfigured()?((config={}).outcomes=self._getApplicableOutcomesOptions(),config.rules=self._getApplicableRulesOptions()):config=!1;var context={competencyshortname:self._competency.shortname,config:config};return Templates.render("tool_lp/competency_rule_config",context)}))},RuleConfig.prototype.setTargetCompetencyId=function(competencyId){var self=this;self._competency=self._tree.getCompetency(competencyId),$.each(self._rules,(function(index,rule){rule.setTargetCompetency(self._competency)}))},RuleConfig.prototype._setUp=function(){var self=this,promises=[],modules=[];self._ready=$.Deferred(),self._rules=[],$.each(self._rulesModules,(function(index,rule){modules.push(rule.amd)})),require(modules,(function(){$.each(arguments,(function(index,Module){var rule=new Module(self._tree);self._rules.push(rule)})),promises.push(self._initRules()),promises.push(self._initOutcomes()),$.when.apply($.when,promises).always((function(){self._ready.resolve()}))}))},RuleConfig.prototype._switchedOutcome=function(){if(this._getOutcome()==Outcomes.NONE)return this._find('[data-region="rule-type"]').hide().find('[name="rule"]').val(-1),this._find('[data-region="rule-config"]').empty().hide(),void this._afterChange();this._find('[data-region="rule-type"]').show(),this._find('[data-region="rule-config"]').show(),this._afterChange()},RuleConfig.prototype._switchedRule=function(){var self=this,container=self._find('[data-region="rule-config"]'),rule=self._getRule();if(!rule)return container.empty().hide(),void self._afterChange();rule.injectTemplate(container).then((function(){container.show()})).always((function(){self._afterChange()})).catch((function(){container.empty().hide()}))},RuleConfig.prototype._trigger=function(type,data){this._eventNode.trigger(type,[data])},RuleConfig}));
+
+//# sourceMappingURL=competencyruleconfig.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencyruleconfig.min.js.map b/admin/tool/lp/amd/build/competencyruleconfig.min.js.map
index 27dcc816d18..abb941a1722 100644
--- a/admin/tool/lp/amd/build/competencyruleconfig.min.js.map
+++ b/admin/tool/lp/amd/build/competencyruleconfig.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/competencyruleconfig.js"],"names":["define","$","Notification","Templates","Dialogue","Outcomes","Str","RuleConfig","tree","rulesModules","_eventNode","_tree","_rulesModules","_setUp","prototype","_competency","_outcomesOption","_popup","_ready","_rules","_afterChange","_isValid","_find","prop","_afterRuleConfigChange","e","rule","_getRule","_afterRender","self","on","_switchedOutcome","trigger","_switchedRule","_trigger","_getConfig","close","canBeConfigured","can","each","index","canConfig","display","when","get_string","_render","then","title","render","bind","fail","exception","selector","getContent","find","_getApplicableOutcomesOptions","options","outcome","push","code","name","selected","ruleoutcome","_getApplicableRulesOptions","_getRuleName","getType","type","ruletype","ruleconfig","getConfig","_getOutcome","val","result","modInfo","_initOutcomes","getAll","outcomes","_initRules","promises","promise","init","setTargetCompetency","splice","apply","NONE","isValid","handler","_preRender","ready","config","rules","context","competencyshortname","shortname","setTargetCompetencyId","competencyId","getCompetency","modules","Deferred","amd","require","arguments","Module","always","resolve","hide","empty","show","container","injectTemplate","catch","data"],"mappings":"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","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 .\n\n/**\n * Competency rule config.\n *\n * @module tool_lp/competencyruleconfig\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/templates',\n 'tool_lp/dialogue',\n 'tool_lp/competency_outcomes',\n 'core/str'],\n function($, Notification, Templates, Dialogue, Outcomes, Str) {\n\n /**\n * Competency rule class.\n *\n * When implementing this you should attach a listener to the event 'save'\n * on the instance. E.g.\n *\n * var config = new RuleConfig(tree, modules);\n * config.on('save', function(e, config) { ... });\n *\n * @param {competencytree} tree The competency tree.\n * @param {Array} rulesModules The modules containing the rules: [{ typeName: { amd: amdModule, name: ruleName }}].\n */\n var RuleConfig = function(tree, rulesModules) {\n this._eventNode = $('');\n this._tree = tree;\n this._rulesModules = rulesModules;\n this._setUp();\n };\n\n /** @property {Object} The current competency. */\n RuleConfig.prototype._competency = null;\n /** @property {Node} The node we attach the events to. */\n RuleConfig.prototype._eventNode = null;\n /** @property {Array} Outcomes options. */\n RuleConfig.prototype._outcomesOption = null;\n /** @property {Dialogue} The dialogue. */\n RuleConfig.prototype._popup = null;\n /** @property {Promise} Resolved when the module is ready. */\n RuleConfig.prototype._ready = null;\n /** @property {Array} The rules. */\n RuleConfig.prototype._rules = null;\n /** @property {Array} The rules modules. */\n RuleConfig.prototype._rulesModules = null;\n /** @property {competencytree} The competency tree. */\n RuleConfig.prototype._tree = null;\n\n /**\n * After change.\n *\n * Triggered when a change occured.\n *\n * @method _afterChange\n * @protected\n */\n RuleConfig.prototype._afterChange = function() {\n if (!this._isValid()) {\n this._find('[data-action=\"save\"]').prop('disabled', true);\n } else {\n this._find('[data-action=\"save\"]').prop('disabled', false);\n }\n };\n\n /**\n * After change in rule's config.\n *\n * Triggered when a change occured in a specific rule config.\n *\n * @method _afterRuleConfigChange\n * @protected\n * @param {Event} e\n * @param {Rule} rule\n */\n RuleConfig.prototype._afterRuleConfigChange = function(e, rule) {\n if (rule != this._getRule()) {\n // This rule is not the current one any more, we can ignore.\n return;\n }\n this._afterChange();\n };\n\n /**\n * After render hook.\n *\n * @method _afterRender\n * @protected\n */\n RuleConfig.prototype._afterRender = function() {\n var self = this;\n\n self._find('[name=\"outcome\"]').on('change', function() {\n self._switchedOutcome();\n }).trigger('change');\n\n self._find('[name=\"rule\"]').on('change', function() {\n self._switchedRule();\n }).trigger('change');\n\n self._find('[data-action=\"save\"]').on('click', function() {\n self._trigger('save', self._getConfig());\n self.close();\n });\n\n self._find('[data-action=\"cancel\"]').on('click', function() {\n self.close();\n });\n };\n\n /**\n * Whether the current competency can be configured.\n *\n * @return {Boolean}\n * @method canBeConfigured\n */\n RuleConfig.prototype.canBeConfigured = function() {\n var can = false;\n $.each(this._rules, function(index, rule) {\n if (rule.canConfig()) {\n can = true;\n return;\n }\n });\n return can;\n };\n\n /**\n * Close the dialogue.\n *\n * @method close\n */\n RuleConfig.prototype.close = function() {\n this._popup.close();\n this._popup = null;\n };\n\n /**\n * Opens the picker.\n *\n * @method display\n * @returns {Promise}\n */\n RuleConfig.prototype.display = function() {\n var self = this;\n if (!self._competency) {\n return false;\n }\n return $.when(Str.get_string('competencyrule', 'tool_lp'), self._render())\n .then(function(title, render) {\n self._popup = new Dialogue(\n title,\n render[0],\n self._afterRender.bind(self)\n );\n return;\n }).fail(Notification.exception);\n };\n\n /**\n * Find a node in the dialogue.\n *\n * @param {String} selector\n * @return {JQuery}\n * @method _find\n * @protected\n */\n RuleConfig.prototype._find = function(selector) {\n return $(this._popup.getContent()).find(selector);\n };\n\n /**\n * Get the applicable outcome options.\n *\n * @return {Array}\n * @method _getApplicableOutcomesOptions\n * @protected\n */\n RuleConfig.prototype._getApplicableOutcomesOptions = function() {\n var self = this,\n options = [];\n\n $.each(self._outcomesOption, function(index, outcome) {\n options.push({\n code: outcome.code,\n name: outcome.name,\n selected: (outcome.code == self._competency.ruleoutcome) ? true : false,\n });\n });\n\n return options;\n };\n\n /**\n * Get the applicable rules options.\n *\n * @return {Array}\n * @method _getApplicableRulesOptions\n * @protected\n */\n RuleConfig.prototype._getApplicableRulesOptions = function() {\n var self = this,\n options = [];\n\n $.each(self._rules, function(index, rule) {\n if (!rule.canConfig()) {\n return;\n }\n options.push({\n name: self._getRuleName(rule.getType()),\n type: rule.getType(),\n selected: (rule.getType() == self._competency.ruletype) ? true : false,\n });\n });\n\n return options;\n };\n\n /**\n * Get the full config for the competency.\n *\n * @return {Object} Contains rule, ruleoutcome and ruleconfig.\n * @method _getConfig\n * @protected\n */\n RuleConfig.prototype._getConfig = function() {\n var rule = this._getRule();\n return {\n ruletype: rule ? rule.getType() : null,\n ruleconfig: rule ? rule.getConfig() : null,\n ruleoutcome: this._getOutcome()\n };\n };\n\n /**\n * Get the selected outcome code.\n *\n * @return {String}\n * @method _getOutcome\n * @protected\n */\n RuleConfig.prototype._getOutcome = function() {\n return this._find('[name=\"outcome\"]').val();\n };\n\n /**\n * Get the selected rule.\n *\n * @return {null|Rule}\n * @method _getRule\n * @protected\n */\n RuleConfig.prototype._getRule = function() {\n var result,\n type = this._find('[name=\"rule\"]').val();\n\n $.each(this._rules, function(index, rule) {\n if (rule.getType() == type) {\n result = rule;\n return;\n }\n });\n\n return result;\n };\n\n /**\n * Return the name of a rule.\n *\n * @param {String} type The type of a rule.\n * @return {String}\n * @method _getRuleName\n * @protected\n */\n RuleConfig.prototype._getRuleName = function(type) {\n var self = this,\n name;\n $.each(self._rulesModules, function(index, modInfo) {\n if (modInfo.type == type) {\n name = modInfo.name;\n return;\n }\n });\n return name;\n };\n\n /**\n * Initialise the outcomes.\n *\n * @return {Promise}\n * @method _initOutcomes\n * @protected\n */\n RuleConfig.prototype._initOutcomes = function() {\n var self = this;\n return Outcomes.getAll().then(function(outcomes) {\n self._outcomesOption = outcomes;\n return;\n });\n };\n\n /**\n * Initialise the rules.\n *\n * @return {Promise}\n * @method _initRules\n * @protected\n */\n RuleConfig.prototype._initRules = function() {\n var self = this,\n promises = [];\n $.each(self._rules, function(index, rule) {\n var promise = rule.init().then(function() {\n rule.setTargetCompetency(self._competency);\n rule.on('change', self._afterRuleConfigChange.bind(self));\n return;\n }, function() {\n // Upon failure remove the rule, and resolve the promise.\n self._rules.splice(index, 1);\n return $.when();\n });\n promises.push(promise);\n });\n\n return $.when.apply($.when, promises);\n };\n\n /**\n * Whether or not the current config is valid.\n *\n * @return {Boolean}\n * @method _isValid\n * @protected\n */\n RuleConfig.prototype._isValid = function() {\n var outcome = this._getOutcome(),\n rule = this._getRule();\n\n if (outcome == Outcomes.NONE) {\n return true;\n } else if (!rule) {\n return false;\n }\n\n return rule.isValid();\n };\n\n /**\n * Register an event listener.\n *\n * @param {String} type The event type.\n * @param {Function} handler The event listener.\n * @method on\n */\n RuleConfig.prototype.on = function(type, handler) {\n this._eventNode.on(type, handler);\n };\n\n /**\n * Hook to executed before render.\n *\n * @method _preRender\n * @protected\n * @return {Promise}\n */\n RuleConfig.prototype._preRender = function() {\n // We need to have all the information about the rule plugins first.\n return this.ready();\n };\n\n /**\n * Returns a promise that is resolved when the module is ready.\n *\n * @return {Promise}\n * @method ready\n * @protected\n */\n RuleConfig.prototype.ready = function() {\n return this._ready.promise();\n };\n\n /**\n * Render the dialogue.\n *\n * @method _render\n * @protected\n * @return {Promise}\n */\n RuleConfig.prototype._render = function() {\n var self = this;\n return this._preRender().then(function() {\n var config;\n\n if (!self.canBeConfigured()) {\n config = false;\n } else {\n config = {};\n config.outcomes = self._getApplicableOutcomesOptions();\n config.rules = self._getApplicableRulesOptions();\n }\n\n var context = {\n competencyshortname: self._competency.shortname,\n config: config\n };\n\n return Templates.render('tool_lp/competency_rule_config', context);\n });\n };\n\n /**\n * Set the target competency.\n *\n * @param {Number} competencyId The target competency Id.\n * @method setTargetCompetencyId\n */\n RuleConfig.prototype.setTargetCompetencyId = function(competencyId) {\n var self = this;\n self._competency = self._tree.getCompetency(competencyId);\n $.each(self._rules, function(index, rule) {\n rule.setTargetCompetency(self._competency);\n });\n };\n\n /**\n * Set up the instance.\n *\n * @method _setUp\n * @protected\n */\n RuleConfig.prototype._setUp = function() {\n var self = this,\n promises = [],\n modules = [];\n\n self._ready = $.Deferred();\n self._rules = [];\n\n $.each(self._rulesModules, function(index, rule) {\n modules.push(rule.amd);\n });\n\n // Load all the modules.\n require(modules, function() {\n $.each(arguments, function(index, Module) {\n // Instantiate the rule and listen to it.\n var rule = new Module(self._tree);\n self._rules.push(rule);\n });\n\n // Load all the option values.\n promises.push(self._initRules());\n promises.push(self._initOutcomes());\n\n // Ready when everything is done.\n $.when.apply($.when, promises).always(function() {\n self._ready.resolve();\n });\n });\n };\n\n /**\n * Called when the user switches outcome.\n *\n * @method _switchedOutcome\n * @protected\n */\n RuleConfig.prototype._switchedOutcome = function() {\n var self = this,\n type = self._getOutcome();\n\n if (type == Outcomes.NONE) {\n // Reset to defaults.\n self._find('[data-region=\"rule-type\"]').hide()\n .find('[name=\"rule\"]').val(-1);\n self._find('[data-region=\"rule-config\"]').empty().hide();\n self._afterChange();\n return;\n }\n\n self._find('[data-region=\"rule-type\"]').show();\n self._find('[data-region=\"rule-config\"]').show();\n self._afterChange();\n };\n\n /**\n * Called when the user switches rule.\n *\n * @method _switchedRule\n * @protected\n */\n RuleConfig.prototype._switchedRule = function() {\n var self = this,\n container = self._find('[data-region=\"rule-config\"]'),\n rule = self._getRule();\n\n if (!rule) {\n container.empty().hide();\n self._afterChange();\n return;\n }\n rule.injectTemplate(container).then(function() {\n container.show();\n return;\n }).always(function() {\n self._afterChange();\n }).catch(function() {\n container.empty().hide();\n });\n };\n\n /**\n * Trigger an event.\n *\n * @param {String} type The type of event.\n * @param {Object} data The data to pass to the listeners.\n * @method _trigger\n * @protected\n */\n RuleConfig.prototype._trigger = function(type, data) {\n this._eventNode.trigger(type, [data]);\n };\n\n return /** @alias module:tool_lp/competencyruleconfig */ RuleConfig;\n\n});\n"],"file":"competencyruleconfig.min.js"}
\ No newline at end of file
+{"version":3,"file":"competencyruleconfig.min.js","sources":["../src/competencyruleconfig.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 .\n\n/**\n * Competency rule config.\n *\n * @module tool_lp/competencyruleconfig\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/templates',\n 'tool_lp/dialogue',\n 'tool_lp/competency_outcomes',\n 'core/str'],\n function($, Notification, Templates, Dialogue, Outcomes, Str) {\n\n /**\n * Competency rule class.\n *\n * When implementing this you should attach a listener to the event 'save'\n * on the instance. E.g.\n *\n * var config = new RuleConfig(tree, modules);\n * config.on('save', function(e, config) { ... });\n *\n * @param {competencytree} tree The competency tree.\n * @param {Array} rulesModules The modules containing the rules: [{ typeName: { amd: amdModule, name: ruleName }}].\n */\n var RuleConfig = function(tree, rulesModules) {\n this._eventNode = $('');\n this._tree = tree;\n this._rulesModules = rulesModules;\n this._setUp();\n };\n\n /** @property {Object} The current competency. */\n RuleConfig.prototype._competency = null;\n /** @property {Node} The node we attach the events to. */\n RuleConfig.prototype._eventNode = null;\n /** @property {Array} Outcomes options. */\n RuleConfig.prototype._outcomesOption = null;\n /** @property {Dialogue} The dialogue. */\n RuleConfig.prototype._popup = null;\n /** @property {Promise} Resolved when the module is ready. */\n RuleConfig.prototype._ready = null;\n /** @property {Array} The rules. */\n RuleConfig.prototype._rules = null;\n /** @property {Array} The rules modules. */\n RuleConfig.prototype._rulesModules = null;\n /** @property {competencytree} The competency tree. */\n RuleConfig.prototype._tree = null;\n\n /**\n * After change.\n *\n * Triggered when a change occured.\n *\n * @method _afterChange\n * @protected\n */\n RuleConfig.prototype._afterChange = function() {\n if (!this._isValid()) {\n this._find('[data-action=\"save\"]').prop('disabled', true);\n } else {\n this._find('[data-action=\"save\"]').prop('disabled', false);\n }\n };\n\n /**\n * After change in rule's config.\n *\n * Triggered when a change occured in a specific rule config.\n *\n * @method _afterRuleConfigChange\n * @protected\n * @param {Event} e\n * @param {Rule} rule\n */\n RuleConfig.prototype._afterRuleConfigChange = function(e, rule) {\n if (rule != this._getRule()) {\n // This rule is not the current one any more, we can ignore.\n return;\n }\n this._afterChange();\n };\n\n /**\n * After render hook.\n *\n * @method _afterRender\n * @protected\n */\n RuleConfig.prototype._afterRender = function() {\n var self = this;\n\n self._find('[name=\"outcome\"]').on('change', function() {\n self._switchedOutcome();\n }).trigger('change');\n\n self._find('[name=\"rule\"]').on('change', function() {\n self._switchedRule();\n }).trigger('change');\n\n self._find('[data-action=\"save\"]').on('click', function() {\n self._trigger('save', self._getConfig());\n self.close();\n });\n\n self._find('[data-action=\"cancel\"]').on('click', function() {\n self.close();\n });\n };\n\n /**\n * Whether the current competency can be configured.\n *\n * @return {Boolean}\n * @method canBeConfigured\n */\n RuleConfig.prototype.canBeConfigured = function() {\n var can = false;\n $.each(this._rules, function(index, rule) {\n if (rule.canConfig()) {\n can = true;\n return;\n }\n });\n return can;\n };\n\n /**\n * Close the dialogue.\n *\n * @method close\n */\n RuleConfig.prototype.close = function() {\n this._popup.close();\n this._popup = null;\n };\n\n /**\n * Opens the picker.\n *\n * @method display\n * @returns {Promise}\n */\n RuleConfig.prototype.display = function() {\n var self = this;\n if (!self._competency) {\n return false;\n }\n return $.when(Str.get_string('competencyrule', 'tool_lp'), self._render())\n .then(function(title, render) {\n self._popup = new Dialogue(\n title,\n render[0],\n self._afterRender.bind(self)\n );\n return;\n }).fail(Notification.exception);\n };\n\n /**\n * Find a node in the dialogue.\n *\n * @param {String} selector\n * @return {JQuery}\n * @method _find\n * @protected\n */\n RuleConfig.prototype._find = function(selector) {\n return $(this._popup.getContent()).find(selector);\n };\n\n /**\n * Get the applicable outcome options.\n *\n * @return {Array}\n * @method _getApplicableOutcomesOptions\n * @protected\n */\n RuleConfig.prototype._getApplicableOutcomesOptions = function() {\n var self = this,\n options = [];\n\n $.each(self._outcomesOption, function(index, outcome) {\n options.push({\n code: outcome.code,\n name: outcome.name,\n selected: (outcome.code == self._competency.ruleoutcome) ? true : false,\n });\n });\n\n return options;\n };\n\n /**\n * Get the applicable rules options.\n *\n * @return {Array}\n * @method _getApplicableRulesOptions\n * @protected\n */\n RuleConfig.prototype._getApplicableRulesOptions = function() {\n var self = this,\n options = [];\n\n $.each(self._rules, function(index, rule) {\n if (!rule.canConfig()) {\n return;\n }\n options.push({\n name: self._getRuleName(rule.getType()),\n type: rule.getType(),\n selected: (rule.getType() == self._competency.ruletype) ? true : false,\n });\n });\n\n return options;\n };\n\n /**\n * Get the full config for the competency.\n *\n * @return {Object} Contains rule, ruleoutcome and ruleconfig.\n * @method _getConfig\n * @protected\n */\n RuleConfig.prototype._getConfig = function() {\n var rule = this._getRule();\n return {\n ruletype: rule ? rule.getType() : null,\n ruleconfig: rule ? rule.getConfig() : null,\n ruleoutcome: this._getOutcome()\n };\n };\n\n /**\n * Get the selected outcome code.\n *\n * @return {String}\n * @method _getOutcome\n * @protected\n */\n RuleConfig.prototype._getOutcome = function() {\n return this._find('[name=\"outcome\"]').val();\n };\n\n /**\n * Get the selected rule.\n *\n * @return {null|Rule}\n * @method _getRule\n * @protected\n */\n RuleConfig.prototype._getRule = function() {\n var result,\n type = this._find('[name=\"rule\"]').val();\n\n $.each(this._rules, function(index, rule) {\n if (rule.getType() == type) {\n result = rule;\n return;\n }\n });\n\n return result;\n };\n\n /**\n * Return the name of a rule.\n *\n * @param {String} type The type of a rule.\n * @return {String}\n * @method _getRuleName\n * @protected\n */\n RuleConfig.prototype._getRuleName = function(type) {\n var self = this,\n name;\n $.each(self._rulesModules, function(index, modInfo) {\n if (modInfo.type == type) {\n name = modInfo.name;\n return;\n }\n });\n return name;\n };\n\n /**\n * Initialise the outcomes.\n *\n * @return {Promise}\n * @method _initOutcomes\n * @protected\n */\n RuleConfig.prototype._initOutcomes = function() {\n var self = this;\n return Outcomes.getAll().then(function(outcomes) {\n self._outcomesOption = outcomes;\n return;\n });\n };\n\n /**\n * Initialise the rules.\n *\n * @return {Promise}\n * @method _initRules\n * @protected\n */\n RuleConfig.prototype._initRules = function() {\n var self = this,\n promises = [];\n $.each(self._rules, function(index, rule) {\n var promise = rule.init().then(function() {\n rule.setTargetCompetency(self._competency);\n rule.on('change', self._afterRuleConfigChange.bind(self));\n return;\n }, function() {\n // Upon failure remove the rule, and resolve the promise.\n self._rules.splice(index, 1);\n return $.when();\n });\n promises.push(promise);\n });\n\n return $.when.apply($.when, promises);\n };\n\n /**\n * Whether or not the current config is valid.\n *\n * @return {Boolean}\n * @method _isValid\n * @protected\n */\n RuleConfig.prototype._isValid = function() {\n var outcome = this._getOutcome(),\n rule = this._getRule();\n\n if (outcome == Outcomes.NONE) {\n return true;\n } else if (!rule) {\n return false;\n }\n\n return rule.isValid();\n };\n\n /**\n * Register an event listener.\n *\n * @param {String} type The event type.\n * @param {Function} handler The event listener.\n * @method on\n */\n RuleConfig.prototype.on = function(type, handler) {\n this._eventNode.on(type, handler);\n };\n\n /**\n * Hook to executed before render.\n *\n * @method _preRender\n * @protected\n * @return {Promise}\n */\n RuleConfig.prototype._preRender = function() {\n // We need to have all the information about the rule plugins first.\n return this.ready();\n };\n\n /**\n * Returns a promise that is resolved when the module is ready.\n *\n * @return {Promise}\n * @method ready\n * @protected\n */\n RuleConfig.prototype.ready = function() {\n return this._ready.promise();\n };\n\n /**\n * Render the dialogue.\n *\n * @method _render\n * @protected\n * @return {Promise}\n */\n RuleConfig.prototype._render = function() {\n var self = this;\n return this._preRender().then(function() {\n var config;\n\n if (!self.canBeConfigured()) {\n config = false;\n } else {\n config = {};\n config.outcomes = self._getApplicableOutcomesOptions();\n config.rules = self._getApplicableRulesOptions();\n }\n\n var context = {\n competencyshortname: self._competency.shortname,\n config: config\n };\n\n return Templates.render('tool_lp/competency_rule_config', context);\n });\n };\n\n /**\n * Set the target competency.\n *\n * @param {Number} competencyId The target competency Id.\n * @method setTargetCompetencyId\n */\n RuleConfig.prototype.setTargetCompetencyId = function(competencyId) {\n var self = this;\n self._competency = self._tree.getCompetency(competencyId);\n $.each(self._rules, function(index, rule) {\n rule.setTargetCompetency(self._competency);\n });\n };\n\n /**\n * Set up the instance.\n *\n * @method _setUp\n * @protected\n */\n RuleConfig.prototype._setUp = function() {\n var self = this,\n promises = [],\n modules = [];\n\n self._ready = $.Deferred();\n self._rules = [];\n\n $.each(self._rulesModules, function(index, rule) {\n modules.push(rule.amd);\n });\n\n // Load all the modules.\n require(modules, function() {\n $.each(arguments, function(index, Module) {\n // Instantiate the rule and listen to it.\n var rule = new Module(self._tree);\n self._rules.push(rule);\n });\n\n // Load all the option values.\n promises.push(self._initRules());\n promises.push(self._initOutcomes());\n\n // Ready when everything is done.\n $.when.apply($.when, promises).always(function() {\n self._ready.resolve();\n });\n });\n };\n\n /**\n * Called when the user switches outcome.\n *\n * @method _switchedOutcome\n * @protected\n */\n RuleConfig.prototype._switchedOutcome = function() {\n var self = this,\n type = self._getOutcome();\n\n if (type == Outcomes.NONE) {\n // Reset to defaults.\n self._find('[data-region=\"rule-type\"]').hide()\n .find('[name=\"rule\"]').val(-1);\n self._find('[data-region=\"rule-config\"]').empty().hide();\n self._afterChange();\n return;\n }\n\n self._find('[data-region=\"rule-type\"]').show();\n self._find('[data-region=\"rule-config\"]').show();\n self._afterChange();\n };\n\n /**\n * Called when the user switches rule.\n *\n * @method _switchedRule\n * @protected\n */\n RuleConfig.prototype._switchedRule = function() {\n var self = this,\n container = self._find('[data-region=\"rule-config\"]'),\n rule = self._getRule();\n\n if (!rule) {\n container.empty().hide();\n self._afterChange();\n return;\n }\n rule.injectTemplate(container).then(function() {\n container.show();\n return;\n }).always(function() {\n self._afterChange();\n }).catch(function() {\n container.empty().hide();\n });\n };\n\n /**\n * Trigger an event.\n *\n * @param {String} type The type of event.\n * @param {Object} data The data to pass to the listeners.\n * @method _trigger\n * @protected\n */\n RuleConfig.prototype._trigger = function(type, data) {\n this._eventNode.trigger(type, [data]);\n };\n\n return /** @alias module:tool_lp/competencyruleconfig */ RuleConfig;\n\n});\n"],"names":["define","$","Notification","Templates","Dialogue","Outcomes","Str","RuleConfig","tree","rulesModules","_eventNode","_tree","_rulesModules","_setUp","prototype","_competency","_outcomesOption","_popup","_ready","_rules","_afterChange","this","_isValid","_find","prop","_afterRuleConfigChange","e","rule","_getRule","_afterRender","self","on","_switchedOutcome","trigger","_switchedRule","_trigger","_getConfig","close","canBeConfigured","can","each","index","canConfig","display","when","get_string","_render","then","title","render","bind","fail","exception","selector","getContent","find","_getApplicableOutcomesOptions","options","outcome","push","code","name","selected","ruleoutcome","_getApplicableRulesOptions","_getRuleName","getType","type","ruletype","ruleconfig","getConfig","_getOutcome","val","result","modInfo","_initOutcomes","getAll","outcomes","_initRules","promises","promise","init","setTargetCompetency","splice","apply","NONE","isValid","handler","_preRender","ready","config","rules","context","competencyshortname","shortname","setTargetCompetencyId","competencyId","getCompetency","modules","Deferred","amd","require","arguments","Module","always","resolve","hide","empty","show","container","injectTemplate","catch","data"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencytree.min.js b/admin/tool/lp/amd/build/competencytree.min.js
index 305c88a3c7f..6f3ab53f3da 100644
--- a/admin/tool/lp/amd/build/competencytree.min.js
+++ b/admin/tool/lp/amd/build/competencytree.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/competencytree",["core/ajax","core/notification","core/templates","tool_lp/tree","tool_lp/competency_outcomes","jquery"],function(a,b,c,d,e,f){var g={},h=0,j="",k="",l="",m=!1,n=function(a,b){var c=0,d=!1;a.haschildren=!1;a.children=[];for(c=0;c
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/competencytree",["core/ajax","core/notification","core/templates","tool_lp/tree","tool_lp/competency_outcomes","jquery"],(function(ajax,notification,templates,Ariatree,CompOutcomes,$){var competencies={},competencyFrameworkId=0,competencyFrameworkShortName="",treeSelector="",currentNodeId="",competencyFramworkCanManage=!1,addChildren=function(parent,all){var i=0,current=!1;for(parent.haschildren=!1,parent.children=[],i=0;i0&&(currentNodeId=competencyid),this.on("selectionchanged",rememberCurrent)},on:function(eventname,handler){$(treeSelector).on(eventname,handler)},getChildren:function(id){var children=[];return $.each(competencies,(function(index,competency){competency.parentid==id&&children.push(competency)})),children},getCompetencyFrameworkId:function(){return competencyFrameworkId},getCompetency:function(id){return competencies[id]},getCompetencyLevel:function(id){return this.getCompetency(id).path.replace(/^\/|\/$/g,"").split("/").length},hasChildren:function(id){return this.getChildren(id).length>0},hasRule:function(id){var comp=this.getCompetency(id);return!!comp&&(comp.ruleoutcome!=CompOutcomes.OUTCOME_NONE&&comp.ruletype)},reloadCompetencies:function(){return loadCompetencies("").fail(notification.exception)},listCompetencies:function(){return competencies}}}));
+
+//# sourceMappingURL=competencytree.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/competencytree.min.js.map b/admin/tool/lp/amd/build/competencytree.min.js.map
index 5d07f95700c..30b8cbf7e8e 100644
--- a/admin/tool/lp/amd/build/competencytree.min.js.map
+++ b/admin/tool/lp/amd/build/competencytree.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/competencytree.js"],"names":["define","ajax","notification","templates","Ariatree","CompOutcomes","$","competencies","competencyFrameworkId","competencyFrameworkShortName","treeSelector","currentNodeId","competencyFramworkCanManage","addChildren","parent","all","i","current","haschildren","children","length","parentid","id","push","loadCompetencies","searchtext","deferred","Deferred","render","done","loadinghtml","loadingjs","replaceNodeContents","promises","call","methodname","args","competencyframeworkid","result","competency","parseInt","context","shortname","canmanage","html","js","tree","node","find","selectItem","updateFocus","resolve","fail","reject","promise","rememberCurrent","evt","params","selected","attr","init","search","selector","competencyid","exception","on","eventname","handler","getChildren","each","index","getCompetencyFrameworkId","getCompetency","getCompetencyLevel","level","path","replace","split","hasChildren","hasRule","comp","ruleoutcome","OUTCOME_NONE","ruletype","reloadCompetencies","listCompetencies"],"mappings":"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","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 .\n\n/**\n * Handle selection changes on the competency tree.\n *\n * @module tool_lp/competencyselect\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['core/ajax', 'core/notification', 'core/templates', 'tool_lp/tree', 'tool_lp/competency_outcomes', 'jquery'],\n function(ajax, notification, templates, Ariatree, CompOutcomes, $) {\n\n // Private variables and functions.\n /** @var {Object[]} competencies - Cached list of competencies */\n var competencies = {};\n\n /** @var {Number} competencyFrameworkId - The current framework id */\n var competencyFrameworkId = 0;\n\n /** @var {String} competencyFrameworkShortName - The current framework short name */\n var competencyFrameworkShortName = '';\n\n /** @var {String} treeSelector - The selector for the root of the tree. */\n var treeSelector = '';\n\n /** @var {String} currentNodeId - The data-id of the current node in the tree. */\n var currentNodeId = '';\n\n /** @var {Boolean} competencyFramworkCanManage - Can manage the competencies framework */\n var competencyFramworkCanManage = false;\n\n /**\n * Build a tree from the flat list of competencies.\n * @param {Object} parent The parent competency.\n * @param {Array} all The list of all competencies.\n */\n var addChildren = function(parent, all) {\n var i = 0;\n var current = false;\n parent.haschildren = false;\n parent.children = [];\n for (i = 0; i < all.length; i++) {\n current = all[i];\n if (current.parentid == parent.id) {\n parent.haschildren = true;\n parent.children.push(current);\n addChildren(current, all);\n }\n }\n };\n\n /**\n * Load the list of competencies via ajax. Competencies are filtered by the searchtext.\n * @param {String} searchtext The text to filter on.\n * @return {promise}\n */\n var loadCompetencies = function(searchtext) {\n var deferred = $.Deferred();\n\n templates.render('tool_lp/loading', {}).done(function(loadinghtml, loadingjs) {\n templates.replaceNodeContents($(treeSelector), loadinghtml, loadingjs);\n\n var promises = ajax.call([{\n methodname: 'core_competency_search_competencies',\n args: {\n searchtext: searchtext,\n competencyframeworkid: competencyFrameworkId\n }\n }]);\n promises[0].done(function(result) {\n competencies = {};\n var i = 0;\n for (i = 0; i < result.length; i++) {\n competencies[result[i].id] = result[i];\n }\n\n var children = [];\n var competency = false;\n for (i = 0; i < result.length; i++) {\n competency = result[i];\n if (parseInt(competency.parentid, 10) === 0) {\n children.push(competency);\n addChildren(competency, result);\n }\n }\n var context = {\n shortname: competencyFrameworkShortName,\n canmanage: competencyFramworkCanManage,\n competencies: children\n };\n templates.render('tool_lp/competencies_tree_root', context).done(function(html, js) {\n templates.replaceNodeContents($(treeSelector), $(html).html(), js);\n var tree = new Ariatree(treeSelector, false);\n\n if (currentNodeId) {\n var node = $(treeSelector).find('[data-id=' + currentNodeId + ']');\n if (node.length) {\n tree.selectItem(node);\n tree.updateFocus(node);\n }\n }\n deferred.resolve(competencies);\n }).fail(deferred.reject);\n }).fail(deferred.reject);\n });\n\n return deferred.promise();\n };\n\n /**\n * Whenever the current item in the tree is changed - remember the \"id\".\n * @param {Event} evt\n * @param {Object} params The parameters for the event (This is the selected node).\n */\n var rememberCurrent = function(evt, params) {\n var node = params.selected;\n currentNodeId = node.attr('data-id');\n };\n\n return /** @alias module:tool_lp/competencytree */ {\n // Public variables and functions.\n /**\n * Initialise the tree.\n *\n * @param {Number} id The competency framework id.\n * @param {String} shortname The framework shortname\n * @param {String} search The current search string\n * @param {String} selector The selector for the tree div\n * @param {Boolean} canmanage Can manage the competencies\n * @param {Number} competencyid The id of the competency to show first\n */\n init: function(id, shortname, search, selector, canmanage, competencyid) {\n competencyFrameworkId = id;\n competencyFrameworkShortName = shortname;\n competencyFramworkCanManage = canmanage;\n treeSelector = selector;\n loadCompetencies(search).fail(notification.exception);\n if (competencyid > 0) {\n currentNodeId = competencyid;\n }\n\n this.on('selectionchanged', rememberCurrent);\n },\n\n /**\n * Add an event handler for custom events emitted by the tree.\n *\n * @param {String} eventname The name of the event - only \"selectionchanged\" for now\n * @param {Function} handler The handler for the event.\n */\n on: function(eventname, handler) {\n // We can't use the tree on function directly\n // because the tree gets rebuilt whenever the search string changes,\n // instead we attach the listner to the root node of the tree which never\n // gets destroyed (same as \"on()\" code in the tree.js).\n $(treeSelector).on(eventname, handler);\n },\n\n /**\n * Get the children of a competency.\n *\n * @param {Number} id The competency ID.\n * @return {Array}\n * @method getChildren\n */\n getChildren: function(id) {\n var children = [];\n $.each(competencies, function(index, competency) {\n if (competency.parentid == id) {\n children.push(competency);\n }\n });\n return children;\n },\n\n /**\n * Get the competency framework id this model was initiliased with.\n *\n * @return {Number}\n */\n getCompetencyFrameworkId: function() {\n return competencyFrameworkId;\n },\n\n /**\n * Get a competency by id\n *\n * @param {Number} id The competency id\n * @return {Object}\n */\n getCompetency: function(id) {\n return competencies[id];\n },\n\n /**\n * Get the competency level.\n *\n * @param {Number} id The competency ID.\n * @return {Number}\n */\n getCompetencyLevel: function(id) {\n var competency = this.getCompetency(id),\n level = competency.path.replace(/^\\/|\\/$/g, '').split('/').length;\n return level;\n },\n\n /**\n * Whether a competency has children.\n *\n * @param {Number} id The competency ID.\n * @return {Boolean}\n * @method hasChildren\n */\n hasChildren: function(id) {\n return this.getChildren(id).length > 0;\n },\n\n /**\n * Does the competency have a rule?\n *\n * @param {Number} id The competency ID.\n * @return {Boolean}\n */\n hasRule: function(id) {\n var comp = this.getCompetency(id);\n if (comp) {\n return comp.ruleoutcome != CompOutcomes.OUTCOME_NONE\n && comp.ruletype;\n }\n return false;\n },\n\n /**\n * Reload all the page competencies framework competencies.\n * @method reloadCompetencies\n * @return {Promise}\n */\n reloadCompetencies: function() {\n return loadCompetencies('').fail(notification.exception);\n },\n\n /**\n * Get all competencies for this framework.\n *\n * @return {Object[]}\n */\n listCompetencies: function() {\n return competencies;\n },\n\n };\n });\n"],"file":"competencytree.min.js"}
\ No newline at end of file
+{"version":3,"file":"competencytree.min.js","sources":["../src/competencytree.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 .\n\n/**\n * Handle selection changes on the competency tree.\n *\n * @module tool_lp/competencyselect\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['core/ajax', 'core/notification', 'core/templates', 'tool_lp/tree', 'tool_lp/competency_outcomes', 'jquery'],\n function(ajax, notification, templates, Ariatree, CompOutcomes, $) {\n\n // Private variables and functions.\n /** @var {Object[]} competencies - Cached list of competencies */\n var competencies = {};\n\n /** @var {Number} competencyFrameworkId - The current framework id */\n var competencyFrameworkId = 0;\n\n /** @var {String} competencyFrameworkShortName - The current framework short name */\n var competencyFrameworkShortName = '';\n\n /** @var {String} treeSelector - The selector for the root of the tree. */\n var treeSelector = '';\n\n /** @var {String} currentNodeId - The data-id of the current node in the tree. */\n var currentNodeId = '';\n\n /** @var {Boolean} competencyFramworkCanManage - Can manage the competencies framework */\n var competencyFramworkCanManage = false;\n\n /**\n * Build a tree from the flat list of competencies.\n * @param {Object} parent The parent competency.\n * @param {Array} all The list of all competencies.\n */\n var addChildren = function(parent, all) {\n var i = 0;\n var current = false;\n parent.haschildren = false;\n parent.children = [];\n for (i = 0; i < all.length; i++) {\n current = all[i];\n if (current.parentid == parent.id) {\n parent.haschildren = true;\n parent.children.push(current);\n addChildren(current, all);\n }\n }\n };\n\n /**\n * Load the list of competencies via ajax. Competencies are filtered by the searchtext.\n * @param {String} searchtext The text to filter on.\n * @return {promise}\n */\n var loadCompetencies = function(searchtext) {\n var deferred = $.Deferred();\n\n templates.render('tool_lp/loading', {}).done(function(loadinghtml, loadingjs) {\n templates.replaceNodeContents($(treeSelector), loadinghtml, loadingjs);\n\n var promises = ajax.call([{\n methodname: 'core_competency_search_competencies',\n args: {\n searchtext: searchtext,\n competencyframeworkid: competencyFrameworkId\n }\n }]);\n promises[0].done(function(result) {\n competencies = {};\n var i = 0;\n for (i = 0; i < result.length; i++) {\n competencies[result[i].id] = result[i];\n }\n\n var children = [];\n var competency = false;\n for (i = 0; i < result.length; i++) {\n competency = result[i];\n if (parseInt(competency.parentid, 10) === 0) {\n children.push(competency);\n addChildren(competency, result);\n }\n }\n var context = {\n shortname: competencyFrameworkShortName,\n canmanage: competencyFramworkCanManage,\n competencies: children\n };\n templates.render('tool_lp/competencies_tree_root', context).done(function(html, js) {\n templates.replaceNodeContents($(treeSelector), $(html).html(), js);\n var tree = new Ariatree(treeSelector, false);\n\n if (currentNodeId) {\n var node = $(treeSelector).find('[data-id=' + currentNodeId + ']');\n if (node.length) {\n tree.selectItem(node);\n tree.updateFocus(node);\n }\n }\n deferred.resolve(competencies);\n }).fail(deferred.reject);\n }).fail(deferred.reject);\n });\n\n return deferred.promise();\n };\n\n /**\n * Whenever the current item in the tree is changed - remember the \"id\".\n * @param {Event} evt\n * @param {Object} params The parameters for the event (This is the selected node).\n */\n var rememberCurrent = function(evt, params) {\n var node = params.selected;\n currentNodeId = node.attr('data-id');\n };\n\n return /** @alias module:tool_lp/competencytree */ {\n // Public variables and functions.\n /**\n * Initialise the tree.\n *\n * @param {Number} id The competency framework id.\n * @param {String} shortname The framework shortname\n * @param {String} search The current search string\n * @param {String} selector The selector for the tree div\n * @param {Boolean} canmanage Can manage the competencies\n * @param {Number} competencyid The id of the competency to show first\n */\n init: function(id, shortname, search, selector, canmanage, competencyid) {\n competencyFrameworkId = id;\n competencyFrameworkShortName = shortname;\n competencyFramworkCanManage = canmanage;\n treeSelector = selector;\n loadCompetencies(search).fail(notification.exception);\n if (competencyid > 0) {\n currentNodeId = competencyid;\n }\n\n this.on('selectionchanged', rememberCurrent);\n },\n\n /**\n * Add an event handler for custom events emitted by the tree.\n *\n * @param {String} eventname The name of the event - only \"selectionchanged\" for now\n * @param {Function} handler The handler for the event.\n */\n on: function(eventname, handler) {\n // We can't use the tree on function directly\n // because the tree gets rebuilt whenever the search string changes,\n // instead we attach the listner to the root node of the tree which never\n // gets destroyed (same as \"on()\" code in the tree.js).\n $(treeSelector).on(eventname, handler);\n },\n\n /**\n * Get the children of a competency.\n *\n * @param {Number} id The competency ID.\n * @return {Array}\n * @method getChildren\n */\n getChildren: function(id) {\n var children = [];\n $.each(competencies, function(index, competency) {\n if (competency.parentid == id) {\n children.push(competency);\n }\n });\n return children;\n },\n\n /**\n * Get the competency framework id this model was initiliased with.\n *\n * @return {Number}\n */\n getCompetencyFrameworkId: function() {\n return competencyFrameworkId;\n },\n\n /**\n * Get a competency by id\n *\n * @param {Number} id The competency id\n * @return {Object}\n */\n getCompetency: function(id) {\n return competencies[id];\n },\n\n /**\n * Get the competency level.\n *\n * @param {Number} id The competency ID.\n * @return {Number}\n */\n getCompetencyLevel: function(id) {\n var competency = this.getCompetency(id),\n level = competency.path.replace(/^\\/|\\/$/g, '').split('/').length;\n return level;\n },\n\n /**\n * Whether a competency has children.\n *\n * @param {Number} id The competency ID.\n * @return {Boolean}\n * @method hasChildren\n */\n hasChildren: function(id) {\n return this.getChildren(id).length > 0;\n },\n\n /**\n * Does the competency have a rule?\n *\n * @param {Number} id The competency ID.\n * @return {Boolean}\n */\n hasRule: function(id) {\n var comp = this.getCompetency(id);\n if (comp) {\n return comp.ruleoutcome != CompOutcomes.OUTCOME_NONE\n && comp.ruletype;\n }\n return false;\n },\n\n /**\n * Reload all the page competencies framework competencies.\n * @method reloadCompetencies\n * @return {Promise}\n */\n reloadCompetencies: function() {\n return loadCompetencies('').fail(notification.exception);\n },\n\n /**\n * Get all competencies for this framework.\n *\n * @return {Object[]}\n */\n listCompetencies: function() {\n return competencies;\n },\n\n };\n });\n"],"names":["define","ajax","notification","templates","Ariatree","CompOutcomes","$","competencies","competencyFrameworkId","competencyFrameworkShortName","treeSelector","currentNodeId","competencyFramworkCanManage","addChildren","parent","all","i","current","haschildren","children","length","parentid","id","push","loadCompetencies","searchtext","deferred","Deferred","render","done","loadinghtml","loadingjs","replaceNodeContents","call","methodname","args","competencyframeworkid","result","competency","parseInt","context","shortname","canmanage","html","js","tree","node","find","selectItem","updateFocus","resolve","fail","reject","promise","rememberCurrent","evt","params","selected","attr","init","search","selector","competencyid","exception","on","eventname","handler","getChildren","each","index","getCompetencyFrameworkId","getCompetency","getCompetencyLevel","this","path","replace","split","hasChildren","hasRule","comp","ruleoutcome","OUTCOME_NONE","ruletype","reloadCompetencies","listCompetencies"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/course_competency_settings.min.js b/admin/tool/lp/amd/build/course_competency_settings.min.js
index 496c31ddee0..71086022821 100644
--- a/admin/tool/lp/amd/build/course_competency_settings.min.js
+++ b/admin/tool/lp/amd/build/course_competency_settings.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/course_competency_settings",["jquery","core/notification","tool_lp/dialogue","core/str","core/ajax","core/templates","core/pending"],function(a,b,c,d,f,g,h){var i=function(b){a(b).on("click",this.configureSettings.bind(this))};i.prototype._dialogue=null;i.prototype.configureSettings=function(f){var e=new h,i=a(f.target).closest("a").data("courseid"),j=a(f.target).closest("a").data("pushratingstouserplans");f.preventDefault();a.when(d.get_string("configurecoursecompetencysettings","tool_lp"),g.render("tool_lp/course_competency_settings",{courseid:i,settings:{pushratingstouserplans:j}})).then(function(a,b){this._dialogue=new c(a,b[0],this.addListeners.bind(this));return this._dialogue}.bind(this)).then(e.resolve).catch(b.exception)};i.prototype.addListeners=function(){var a=this._find("[data-action=\"save\"]");a.on("click",this.saveSettings.bind(this));var b=this._find("[data-action=\"cancel\"]");b.on("click",this.cancelChanges.bind(this))};i.prototype.cancelChanges=function(a){a.preventDefault();this._dialogue.close()};i.prototype._find=function(b){return a("[data-region=\"coursecompetencysettings\"]").find(b)};i.prototype.saveSettings=function(a){var c=new h;a.preventDefault();var d=this._find("input[name=\"pushratingstouserplans\"]:checked").val(),e=this._find("input[name=\"courseid\"]").val();f.call([{methodname:"core_competency_update_course_competency_settings",args:{courseid:e,settings:{pushratingstouserplans:d}}}])[0].then(function(){return this.refreshCourseCompetenciesPage()}.bind(this)).then(c.resolve).catch(b.exception)};i.prototype.refreshCourseCompetenciesPage=function(){var c=this._find("input[name=\"courseid\"]").val(),d=new h;f.call([{methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:c,moduleid:0}}])[0].then(function(a){return g.render("tool_lp/course_competencies_page",a)}).then(function(b,c){g.replaceNode(a("[data-region=\"coursecompetenciespage\"]"),b,c);this._dialogue.close()}.bind(this)).then(d.resolve).catch(b.exception)};return i});
-//# sourceMappingURL=course_competency_settings.min.js.map
+/**
+ * Change the course competency settings in a popup.
+ *
+ * @module tool_lp/configurecoursecompetencysettings
+ * @copyright 2015 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/course_competency_settings",["jquery","core/notification","tool_lp/dialogue","core/str","core/ajax","core/templates","core/pending"],(function($,notification,Dialogue,str,ajax,templates,Pending){var settingsMod=function(selector){$(selector).on("click",this.configureSettings.bind(this))};return settingsMod.prototype._dialogue=null,settingsMod.prototype.configureSettings=function(e){var pendingPromise=new Pending,context={courseid:$(e.target).closest("a").data("courseid"),settings:{pushratingstouserplans:$(e.target).closest("a").data("pushratingstouserplans")}};e.preventDefault(),$.when(str.get_string("configurecoursecompetencysettings","tool_lp"),templates.render("tool_lp/course_competency_settings",context)).then(function(title,templateResult){return this._dialogue=new Dialogue(title,templateResult[0],this.addListeners.bind(this)),this._dialogue}.bind(this)).then(pendingPromise.resolve).catch(notification.exception)},settingsMod.prototype.addListeners=function(){this._find('[data-action="save"]').on("click",this.saveSettings.bind(this)),this._find('[data-action="cancel"]').on("click",this.cancelChanges.bind(this))},settingsMod.prototype.cancelChanges=function(e){e.preventDefault(),this._dialogue.close()},settingsMod.prototype._find=function(selector){return $('[data-region="coursecompetencysettings"]').find(selector)},settingsMod.prototype.saveSettings=function(e){var pendingPromise=new Pending;e.preventDefault();var newValue=this._find('input[name="pushratingstouserplans"]:checked').val(),courseId=this._find('input[name="courseid"]').val(),settings={pushratingstouserplans:newValue};ajax.call([{methodname:"core_competency_update_course_competency_settings",args:{courseid:courseId,settings:settings}}])[0].then(function(){return this.refreshCourseCompetenciesPage()}.bind(this)).then(pendingPromise.resolve).catch(notification.exception)},settingsMod.prototype.refreshCourseCompetenciesPage=function(){var courseId=this._find('input[name="courseid"]').val(),pendingPromise=new Pending;ajax.call([{methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:courseId,moduleid:0}}])[0].then((function(context){return templates.render("tool_lp/course_competencies_page",context)})).then(function(html,js){templates.replaceNode($('[data-region="coursecompetenciespage"]'),html,js),this._dialogue.close()}.bind(this)).then(pendingPromise.resolve).catch(notification.exception)},settingsMod}));
+
+//# sourceMappingURL=course_competency_settings.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/course_competency_settings.min.js.map b/admin/tool/lp/amd/build/course_competency_settings.min.js.map
index 2011dcea9e3..f473cf570da 100644
--- a/admin/tool/lp/amd/build/course_competency_settings.min.js.map
+++ b/admin/tool/lp/amd/build/course_competency_settings.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/course_competency_settings.js"],"names":["define","$","notification","Dialogue","str","ajax","templates","Pending","settingsMod","selector","on","configureSettings","bind","prototype","_dialogue","e","pendingPromise","courseid","target","closest","data","currentValue","preventDefault","when","get_string","render","settings","pushratingstouserplans","then","title","templateResult","addListeners","resolve","catch","exception","save","_find","saveSettings","cancel","cancelChanges","close","find","newValue","val","courseId","call","methodname","args","refreshCourseCompetenciesPage","moduleid","context","html","js","replaceNode"],"mappings":"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","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 .\n\n/**\n * Change the course competency settings in a popup.\n *\n * @module tool_lp/configurecoursecompetencysettings\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/notification',\n 'tool_lp/dialogue',\n 'core/str',\n 'core/ajax',\n 'core/templates',\n 'core/pending'\n ],\n function($, notification, Dialogue, str, ajax, templates, Pending) {\n\n /**\n * Constructor\n *\n * @param {String} selector - selector for the links to open the dialogue.\n */\n var settingsMod = function(selector) {\n $(selector).on('click', this.configureSettings.bind(this));\n };\n\n /** @property {Dialogue} Reference to the dialogue that we opened. */\n settingsMod.prototype._dialogue = null;\n\n /**\n * Open the configure settings dialogue.\n *\n * @param {Event} e\n * @method configureSettings\n */\n settingsMod.prototype.configureSettings = function(e) {\n var pendingPromise = new Pending();\n var courseid = $(e.target).closest('a').data('courseid');\n var currentValue = $(e.target).closest('a').data('pushratingstouserplans');\n var context = {\n courseid: courseid,\n settings: {pushratingstouserplans: currentValue}\n };\n e.preventDefault();\n\n $.when(\n str.get_string('configurecoursecompetencysettings', 'tool_lp'),\n templates.render('tool_lp/course_competency_settings', context),\n )\n .then(function(title, templateResult) {\n this._dialogue = new Dialogue(\n title,\n templateResult[0],\n this.addListeners.bind(this)\n );\n\n return this._dialogue;\n }.bind(this))\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n };\n\n /**\n * Add the save listener to the form.\n *\n * @method addSaveListener\n */\n settingsMod.prototype.addListeners = function() {\n var save = this._find('[data-action=\"save\"]');\n save.on('click', this.saveSettings.bind(this));\n var cancel = this._find('[data-action=\"cancel\"]');\n cancel.on('click', this.cancelChanges.bind(this));\n };\n\n /**\n * Cancel the changes.\n *\n * @param {Event} e\n * @method cancelChanges\n */\n settingsMod.prototype.cancelChanges = function(e) {\n e.preventDefault();\n this._dialogue.close();\n };\n\n /**\n * Cancel the changes.\n *\n * @param {String} selector\n * @return {JQuery}\n */\n settingsMod.prototype._find = function(selector) {\n return $('[data-region=\"coursecompetencysettings\"]').find(selector);\n };\n\n /**\n * Save the settings.\n *\n * @param {Event} e\n * @method saveSettings\n */\n settingsMod.prototype.saveSettings = function(e) {\n var pendingPromise = new Pending();\n e.preventDefault();\n\n var newValue = this._find('input[name=\"pushratingstouserplans\"]:checked').val();\n var courseId = this._find('input[name=\"courseid\"]').val();\n var settings = {pushratingstouserplans: newValue};\n\n ajax.call([\n {methodname: 'core_competency_update_course_competency_settings',\n args: {courseid: courseId, settings: settings}}\n ])[0]\n .then(function() {\n return this.refreshCourseCompetenciesPage();\n }.bind(this))\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n\n };\n\n /**\n * Refresh the course competencies page.\n *\n * @method saveSettings\n */\n settingsMod.prototype.refreshCourseCompetenciesPage = function() {\n var courseId = this._find('input[name=\"courseid\"]').val();\n var pendingPromise = new Pending();\n\n ajax.call([\n {methodname: 'tool_lp_data_for_course_competencies_page',\n args: {courseid: courseId, moduleid: 0}}\n ])[0]\n .then(function(context) {\n return templates.render('tool_lp/course_competencies_page', context);\n })\n .then(function(html, js) {\n templates.replaceNode($('[data-region=\"coursecompetenciespage\"]'), html, js);\n this._dialogue.close();\n\n return;\n }.bind(this))\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n };\n\n return /** @alias module:tool_lp/configurecoursecompetencysettings */ settingsMod;\n});\n"],"file":"course_competency_settings.min.js"}
\ No newline at end of file
+{"version":3,"file":"course_competency_settings.min.js","sources":["../src/course_competency_settings.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 .\n\n/**\n * Change the course competency settings in a popup.\n *\n * @module tool_lp/configurecoursecompetencysettings\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/notification',\n 'tool_lp/dialogue',\n 'core/str',\n 'core/ajax',\n 'core/templates',\n 'core/pending'\n ],\n function($, notification, Dialogue, str, ajax, templates, Pending) {\n\n /**\n * Constructor\n *\n * @param {String} selector - selector for the links to open the dialogue.\n */\n var settingsMod = function(selector) {\n $(selector).on('click', this.configureSettings.bind(this));\n };\n\n /** @property {Dialogue} Reference to the dialogue that we opened. */\n settingsMod.prototype._dialogue = null;\n\n /**\n * Open the configure settings dialogue.\n *\n * @param {Event} e\n * @method configureSettings\n */\n settingsMod.prototype.configureSettings = function(e) {\n var pendingPromise = new Pending();\n var courseid = $(e.target).closest('a').data('courseid');\n var currentValue = $(e.target).closest('a').data('pushratingstouserplans');\n var context = {\n courseid: courseid,\n settings: {pushratingstouserplans: currentValue}\n };\n e.preventDefault();\n\n $.when(\n str.get_string('configurecoursecompetencysettings', 'tool_lp'),\n templates.render('tool_lp/course_competency_settings', context),\n )\n .then(function(title, templateResult) {\n this._dialogue = new Dialogue(\n title,\n templateResult[0],\n this.addListeners.bind(this)\n );\n\n return this._dialogue;\n }.bind(this))\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n };\n\n /**\n * Add the save listener to the form.\n *\n * @method addSaveListener\n */\n settingsMod.prototype.addListeners = function() {\n var save = this._find('[data-action=\"save\"]');\n save.on('click', this.saveSettings.bind(this));\n var cancel = this._find('[data-action=\"cancel\"]');\n cancel.on('click', this.cancelChanges.bind(this));\n };\n\n /**\n * Cancel the changes.\n *\n * @param {Event} e\n * @method cancelChanges\n */\n settingsMod.prototype.cancelChanges = function(e) {\n e.preventDefault();\n this._dialogue.close();\n };\n\n /**\n * Cancel the changes.\n *\n * @param {String} selector\n * @return {JQuery}\n */\n settingsMod.prototype._find = function(selector) {\n return $('[data-region=\"coursecompetencysettings\"]').find(selector);\n };\n\n /**\n * Save the settings.\n *\n * @param {Event} e\n * @method saveSettings\n */\n settingsMod.prototype.saveSettings = function(e) {\n var pendingPromise = new Pending();\n e.preventDefault();\n\n var newValue = this._find('input[name=\"pushratingstouserplans\"]:checked').val();\n var courseId = this._find('input[name=\"courseid\"]').val();\n var settings = {pushratingstouserplans: newValue};\n\n ajax.call([\n {methodname: 'core_competency_update_course_competency_settings',\n args: {courseid: courseId, settings: settings}}\n ])[0]\n .then(function() {\n return this.refreshCourseCompetenciesPage();\n }.bind(this))\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n\n };\n\n /**\n * Refresh the course competencies page.\n *\n * @method saveSettings\n */\n settingsMod.prototype.refreshCourseCompetenciesPage = function() {\n var courseId = this._find('input[name=\"courseid\"]').val();\n var pendingPromise = new Pending();\n\n ajax.call([\n {methodname: 'tool_lp_data_for_course_competencies_page',\n args: {courseid: courseId, moduleid: 0}}\n ])[0]\n .then(function(context) {\n return templates.render('tool_lp/course_competencies_page', context);\n })\n .then(function(html, js) {\n templates.replaceNode($('[data-region=\"coursecompetenciespage\"]'), html, js);\n this._dialogue.close();\n\n return;\n }.bind(this))\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n };\n\n return /** @alias module:tool_lp/configurecoursecompetencysettings */ settingsMod;\n});\n"],"names":["define","$","notification","Dialogue","str","ajax","templates","Pending","settingsMod","selector","on","this","configureSettings","bind","prototype","_dialogue","e","pendingPromise","context","courseid","target","closest","data","settings","pushratingstouserplans","preventDefault","when","get_string","render","then","title","templateResult","addListeners","resolve","catch","exception","_find","saveSettings","cancelChanges","close","find","newValue","val","courseId","call","methodname","args","refreshCourseCompetenciesPage","moduleid","html","js","replaceNode"],"mappings":";;;;;;;AAsBAA,4CAAO,CAAC,SACA,oBACA,mBACA,WACA,YACA,iBACA,iBAED,SAASC,EAAGC,aAAcC,SAAUC,IAAKC,KAAMC,UAAWC,aAOzDC,YAAc,SAASC,UACvBR,EAAEQ,UAAUC,GAAG,QAASC,KAAKC,kBAAkBC,KAAKF,eAIxDH,YAAYM,UAAUC,UAAY,KAQlCP,YAAYM,UAAUF,kBAAoB,SAASI,OAC3CC,eAAiB,IAAIV,QAGrBW,QAAU,CACVC,SAHWlB,EAAEe,EAAEI,QAAQC,QAAQ,KAAKC,KAAK,YAIzCC,SAAU,CAACC,uBAHIvB,EAAEe,EAAEI,QAAQC,QAAQ,KAAKC,KAAK,4BAKjDN,EAAES,iBAEFxB,EAAEyB,KACEtB,IAAIuB,WAAW,oCAAqC,WACpDrB,UAAUsB,OAAO,qCAAsCV,UAE1DW,KAAK,SAASC,MAAOC,4BACbhB,UAAY,IAAIZ,SACjB2B,MACAC,eAAe,GACfpB,KAAKqB,aAAanB,KAAKF,OAGpBA,KAAKI,WACdF,KAAKF,OACNkB,KAAKZ,eAAegB,SACpBC,MAAMhC,aAAaiC,YAQxB3B,YAAYM,UAAUkB,aAAe,WACtBrB,KAAKyB,MAAM,wBACjB1B,GAAG,QAASC,KAAK0B,aAAaxB,KAAKF,OAC3BA,KAAKyB,MAAM,0BACjB1B,GAAG,QAASC,KAAK2B,cAAczB,KAAKF,QAS/CH,YAAYM,UAAUwB,cAAgB,SAAStB,GAC3CA,EAAES,sBACGV,UAAUwB,SASnB/B,YAAYM,UAAUsB,MAAQ,SAAS3B,iBAC5BR,EAAE,4CAA4CuC,KAAK/B,WAS9DD,YAAYM,UAAUuB,aAAe,SAASrB,OACtCC,eAAiB,IAAIV,QACzBS,EAAES,qBAEEgB,SAAW9B,KAAKyB,MAAM,gDAAgDM,MACtEC,SAAWhC,KAAKyB,MAAM,0BAA0BM,MAChDnB,SAAW,CAACC,uBAAwBiB,UAExCpC,KAAKuC,KAAK,CACN,CAACC,WAAY,oDACXC,KAAM,CAAC3B,SAAUwB,SAAUpB,SAAUA,aACxC,GACFM,KAAK,kBACKlB,KAAKoC,iCACdlC,KAAKF,OACNkB,KAAKZ,eAAegB,SACpBC,MAAMhC,aAAaiC,YASxB3B,YAAYM,UAAUiC,8BAAgC,eAC9CJ,SAAWhC,KAAKyB,MAAM,0BAA0BM,MAChDzB,eAAiB,IAAIV,QAEzBF,KAAKuC,KAAK,CACN,CAACC,WAAY,4CACXC,KAAM,CAAC3B,SAAUwB,SAAUK,SAAU,MACxC,GACFnB,MAAK,SAASX,gBACJZ,UAAUsB,OAAO,mCAAoCV,YAE/DW,KAAK,SAASoB,KAAMC,IACjB5C,UAAU6C,YAAYlD,EAAE,0CAA2CgD,KAAMC,SACpEnC,UAAUwB,SAGjB1B,KAAKF,OACNkB,KAAKZ,eAAegB,SACpBC,MAAMhC,aAAaiC,YAG8C3B"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/dialogue.min.js b/admin/tool/lp/amd/build/dialogue.min.js
index 6e0c86cdfbd..21d72a304b2 100644
--- a/admin/tool/lp/amd/build/dialogue.min.js
+++ b/admin/tool/lp/amd/build/dialogue.min.js
@@ -1,2 +1,11 @@
-define ("tool_lp/dialogue",["core/yui"],function(a){var b=function(b,c,d,e,f){M.util.js_pending("tool_lp/dialogue:dialogue");this.yuiDialogue=null;var g=this;if("undefined"==typeof f){f=!1}a.use("moodle-core-notification","timers",function(){var h="480px";if(f){h="800px"}g.yuiDialogue=new M.core.dialogue({headerContent:b,bodyContent:c,draggable:!0,visible:!1,center:!0,modal:!0,width:h});g.yuiDialogue.before("visibleChange",function(){M.util.js_pending("tool_lp/dialogue:before:visibleChange")});g.yuiDialogue.after("visibleChange",function(b){if(b.newVal){if("undefined"!=typeof d){a.soon(function(){d(g);g.yuiDialogue.centerDialogue();M.util.js_complete("tool_lp/dialogue:before:visibleChange")})}else{M.util.js_complete("tool_lp/dialogue:before:visibleChange")}}else{if("undefined"!=typeof e){a.soon(function(){e(g);M.util.js_complete("tool_lp/dialogue:before:visibleChange")})}else{M.util.js_complete("tool_lp/dialogue:before:visibleChange")}}});g.yuiDialogue.show();M.util.js_complete("tool_lp/dialogue:dialogue")})};b.prototype.close=function(){this.yuiDialogue.hide();this.yuiDialogue.destroy()};b.prototype.getContent=function(){return this.yuiDialogue.bodyNode.getDOMNode()};return b});
-//# sourceMappingURL=dialogue.min.js.map
+/**
+ * Wrapper for the YUI M.core.notification class. Allows us to
+ * use the YUI version in AMD code until it is replaced.
+ *
+ * @module tool_lp/dialogue
+ * @copyright 2015 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/dialogue",["core/yui"],(function(Y){var dialogue=function(title,content,afterShow,afterHide,wide){M.util.js_pending("tool_lp/dialogue:dialogue"),this.yuiDialogue=null;var parent=this;void 0===wide&&(wide=!1),Y.use("moodle-core-notification","timers",(function(){var width="480px";wide&&(width="800px"),parent.yuiDialogue=new M.core.dialogue({headerContent:title,bodyContent:content,draggable:!0,visible:!1,center:!0,modal:!0,width:width}),parent.yuiDialogue.before("visibleChange",(function(){M.util.js_pending("tool_lp/dialogue:before:visibleChange")})),parent.yuiDialogue.after("visibleChange",(function(e){e.newVal?void 0!==afterShow?Y.soon((function(){afterShow(parent),parent.yuiDialogue.centerDialogue(),M.util.js_complete("tool_lp/dialogue:before:visibleChange")})):M.util.js_complete("tool_lp/dialogue:before:visibleChange"):void 0!==afterHide?Y.soon((function(){afterHide(parent),M.util.js_complete("tool_lp/dialogue:before:visibleChange")})):M.util.js_complete("tool_lp/dialogue:before:visibleChange")})),parent.yuiDialogue.show(),M.util.js_complete("tool_lp/dialogue:dialogue")}))};return dialogue.prototype.close=function(){this.yuiDialogue.hide(),this.yuiDialogue.destroy()},dialogue.prototype.getContent=function(){return this.yuiDialogue.bodyNode.getDOMNode()},dialogue}));
+
+//# sourceMappingURL=dialogue.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/dialogue.min.js.map b/admin/tool/lp/amd/build/dialogue.min.js.map
index 410139a4b1d..97577b8780a 100644
--- a/admin/tool/lp/amd/build/dialogue.min.js.map
+++ b/admin/tool/lp/amd/build/dialogue.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/dialogue.js"],"names":["define","Y","dialogue","title","content","afterShow","afterHide","wide","M","util","js_pending","yuiDialogue","parent","use","width","core","headerContent","bodyContent","draggable","visible","center","modal","before","after","e","newVal","soon","centerDialogue","js_complete","show","prototype","close","hide","destroy","getContent","bodyNode","getDOMNode"],"mappings":"AAuBAA,OAAM,oBAAC,CAAC,UAAD,CAAD,CAAe,SAASC,CAAT,CAAY,CAY7B,GAAIC,CAAAA,CAAQ,CAAG,SAASC,CAAT,CAAgBC,CAAhB,CAAyBC,CAAzB,CAAoCC,CAApC,CAA+CC,CAA/C,CAAqD,CAChEC,CAAC,CAACC,IAAF,CAAOC,UAAP,CAAkB,2BAAlB,EAEA,KAAKC,WAAL,CAAmB,IAAnB,CACA,GAAIC,CAAAA,CAAM,CAAG,IAAb,CAGA,GAAmB,WAAf,QAAOL,CAAAA,CAAX,CAAgC,CAC5BA,CAAI,GACP,CAEDN,CAAC,CAACY,GAAF,CAAM,0BAAN,CAAkC,QAAlC,CAA4C,UAAW,CACnD,GAAIC,CAAAA,CAAK,CAAG,OAAZ,CACA,GAAIP,CAAJ,CAAU,CACNO,CAAK,CAAG,OACX,CAEDF,CAAM,CAACD,WAAP,CAAqB,GAAIH,CAAAA,CAAC,CAACO,IAAF,CAAOb,QAAX,CAAoB,CACrCc,aAAa,CAAEb,CADsB,CAErCc,WAAW,CAAEb,CAFwB,CAGrCc,SAAS,GAH4B,CAIrCC,OAAO,GAJ8B,CAKrCC,MAAM,GAL+B,CAMrCC,KAAK,GANgC,CAOrCP,KAAK,CAAEA,CAP8B,CAApB,CAArB,CAUAF,CAAM,CAACD,WAAP,CAAmBW,MAAnB,CAA0B,eAA1B,CAA2C,UAAW,CAClDd,CAAC,CAACC,IAAF,CAAOC,UAAP,CAAkB,uCAAlB,CACH,CAFD,EAIAE,CAAM,CAACD,WAAP,CAAmBY,KAAnB,CAAyB,eAAzB,CAA0C,SAASC,CAAT,CAAY,CAClD,GAAIA,CAAC,CAACC,MAAN,CAAc,CAGV,GAA0B,WAArB,QAAOpB,CAAAA,CAAZ,CAAwC,CACpCJ,CAAC,CAACyB,IAAF,CAAO,UAAW,CACdrB,CAAS,CAACO,CAAD,CAAT,CACAA,CAAM,CAACD,WAAP,CAAmBgB,cAAnB,GACAnB,CAAC,CAACC,IAAF,CAAOmB,WAAP,CAAmB,uCAAnB,CACH,CAJD,CAKH,CAND,IAMO,CACHpB,CAAC,CAACC,IAAF,CAAOmB,WAAP,CAAmB,uCAAnB,CACH,CACJ,CAZD,IAYO,CACH,GAA0B,WAArB,QAAOtB,CAAAA,CAAZ,CAAwC,CACpCL,CAAC,CAACyB,IAAF,CAAO,UAAW,CACdpB,CAAS,CAACM,CAAD,CAAT,CACAJ,CAAC,CAACC,IAAF,CAAOmB,WAAP,CAAmB,uCAAnB,CACH,CAHD,CAIH,CALD,IAKO,CACHpB,CAAC,CAACC,IAAF,CAAOmB,WAAP,CAAmB,uCAAnB,CACH,CACJ,CACJ,CAvBD,EAyBAhB,CAAM,CAACD,WAAP,CAAmBkB,IAAnB,GACArB,CAAC,CAACC,IAAF,CAAOmB,WAAP,CAAmB,2BAAnB,CACH,CA/CD,CAgDH,CA3DD,CAgEA1B,CAAQ,CAAC4B,SAAT,CAAmBC,KAAnB,CAA2B,UAAW,CAClC,KAAKpB,WAAL,CAAiBqB,IAAjB,GACA,KAAKrB,WAAL,CAAiBsB,OAAjB,EACH,CAHD,CASA/B,CAAQ,CAAC4B,SAAT,CAAmBI,UAAnB,CAAgC,UAAW,CACvC,MAAO,MAAKvB,WAAL,CAAiBwB,QAAjB,CAA0BC,UAA1B,EACV,CAFD,CAIA,MAA6ClC,CAAAA,CAChD,CA1FK,CAAN","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 .\n\n/**\n * Wrapper for the YUI M.core.notification class. Allows us to\n * use the YUI version in AMD code until it is replaced.\n *\n * @module tool_lp/dialogue\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['core/yui'], function(Y) {\n\n // Private variables and functions.\n /**\n * Constructor\n *\n * @param {String} title Title for the window.\n * @param {String} content The content for the window.\n * @param {function} afterShow Callback executed after the window is opened.\n * @param {function} afterHide Callback executed after the window is closed.\n * @param {Boolean} wide Specify we want an extra wide dialogue (the size is standard, but wider than the default).\n */\n var dialogue = function(title, content, afterShow, afterHide, wide) {\n M.util.js_pending('tool_lp/dialogue:dialogue');\n\n this.yuiDialogue = null;\n var parent = this;\n\n // Default for wide is false.\n if (typeof wide == 'undefined') {\n wide = false;\n }\n\n Y.use('moodle-core-notification', 'timers', function() {\n var width = '480px';\n if (wide) {\n width = '800px';\n }\n\n parent.yuiDialogue = new M.core.dialogue({\n headerContent: title,\n bodyContent: content,\n draggable: true,\n visible: false,\n center: true,\n modal: true,\n width: width\n });\n\n parent.yuiDialogue.before('visibleChange', function() {\n M.util.js_pending('tool_lp/dialogue:before:visibleChange');\n });\n\n parent.yuiDialogue.after('visibleChange', function(e) {\n if (e.newVal) {\n // Delay the callback call to the next tick, otherwise it can happen that it is\n // executed before the dialogue constructor returns.\n if ((typeof afterShow !== 'undefined')) {\n Y.soon(function() {\n afterShow(parent);\n parent.yuiDialogue.centerDialogue();\n M.util.js_complete('tool_lp/dialogue:before:visibleChange');\n });\n } else {\n M.util.js_complete('tool_lp/dialogue:before:visibleChange');\n }\n } else {\n if ((typeof afterHide !== 'undefined')) {\n Y.soon(function() {\n afterHide(parent);\n M.util.js_complete('tool_lp/dialogue:before:visibleChange');\n });\n } else {\n M.util.js_complete('tool_lp/dialogue:before:visibleChange');\n }\n }\n });\n\n parent.yuiDialogue.show();\n M.util.js_complete('tool_lp/dialogue:dialogue');\n });\n };\n\n /**\n * Close this window.\n */\n dialogue.prototype.close = function() {\n this.yuiDialogue.hide();\n this.yuiDialogue.destroy();\n };\n\n /**\n * Get content.\n * @return {node}\n */\n dialogue.prototype.getContent = function() {\n return this.yuiDialogue.bodyNode.getDOMNode();\n };\n\n return /** @alias module:tool_lp/dialogue */ dialogue;\n});\n"],"file":"dialogue.min.js"}
\ No newline at end of file
+{"version":3,"file":"dialogue.min.js","sources":["../src/dialogue.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 .\n\n/**\n * Wrapper for the YUI M.core.notification class. Allows us to\n * use the YUI version in AMD code until it is replaced.\n *\n * @module tool_lp/dialogue\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['core/yui'], function(Y) {\n\n // Private variables and functions.\n /**\n * Constructor\n *\n * @param {String} title Title for the window.\n * @param {String} content The content for the window.\n * @param {function} afterShow Callback executed after the window is opened.\n * @param {function} afterHide Callback executed after the window is closed.\n * @param {Boolean} wide Specify we want an extra wide dialogue (the size is standard, but wider than the default).\n */\n var dialogue = function(title, content, afterShow, afterHide, wide) {\n M.util.js_pending('tool_lp/dialogue:dialogue');\n\n this.yuiDialogue = null;\n var parent = this;\n\n // Default for wide is false.\n if (typeof wide == 'undefined') {\n wide = false;\n }\n\n Y.use('moodle-core-notification', 'timers', function() {\n var width = '480px';\n if (wide) {\n width = '800px';\n }\n\n parent.yuiDialogue = new M.core.dialogue({\n headerContent: title,\n bodyContent: content,\n draggable: true,\n visible: false,\n center: true,\n modal: true,\n width: width\n });\n\n parent.yuiDialogue.before('visibleChange', function() {\n M.util.js_pending('tool_lp/dialogue:before:visibleChange');\n });\n\n parent.yuiDialogue.after('visibleChange', function(e) {\n if (e.newVal) {\n // Delay the callback call to the next tick, otherwise it can happen that it is\n // executed before the dialogue constructor returns.\n if ((typeof afterShow !== 'undefined')) {\n Y.soon(function() {\n afterShow(parent);\n parent.yuiDialogue.centerDialogue();\n M.util.js_complete('tool_lp/dialogue:before:visibleChange');\n });\n } else {\n M.util.js_complete('tool_lp/dialogue:before:visibleChange');\n }\n } else {\n if ((typeof afterHide !== 'undefined')) {\n Y.soon(function() {\n afterHide(parent);\n M.util.js_complete('tool_lp/dialogue:before:visibleChange');\n });\n } else {\n M.util.js_complete('tool_lp/dialogue:before:visibleChange');\n }\n }\n });\n\n parent.yuiDialogue.show();\n M.util.js_complete('tool_lp/dialogue:dialogue');\n });\n };\n\n /**\n * Close this window.\n */\n dialogue.prototype.close = function() {\n this.yuiDialogue.hide();\n this.yuiDialogue.destroy();\n };\n\n /**\n * Get content.\n * @return {node}\n */\n dialogue.prototype.getContent = function() {\n return this.yuiDialogue.bodyNode.getDOMNode();\n };\n\n return /** @alias module:tool_lp/dialogue */ dialogue;\n});\n"],"names":["define","Y","dialogue","title","content","afterShow","afterHide","wide","M","util","js_pending","yuiDialogue","parent","this","use","width","core","headerContent","bodyContent","draggable","visible","center","modal","before","after","e","newVal","soon","centerDialogue","js_complete","show","prototype","close","hide","destroy","getContent","bodyNode","getDOMNode"],"mappings":";;;;;;;;AAuBAA,0BAAO,CAAC,aAAa,SAASC,OAYtBC,SAAW,SAASC,MAAOC,QAASC,UAAWC,UAAWC,MAC1DC,EAAEC,KAAKC,WAAW,kCAEbC,YAAc,SACfC,OAASC,UAGM,IAARN,OACPA,MAAO,GAGXN,EAAEa,IAAI,2BAA4B,UAAU,eACpCC,MAAQ,QACRR,OACAQ,MAAQ,SAGZH,OAAOD,YAAc,IAAIH,EAAEQ,KAAKd,SAAS,CACrCe,cAAed,MACfe,YAAad,QACbe,WAAW,EACXC,SAAS,EACTC,QAAQ,EACRC,OAAO,EACPP,MAAOA,QAGXH,OAAOD,YAAYY,OAAO,iBAAiB,WACvCf,EAAEC,KAAKC,WAAW,4CAGtBE,OAAOD,YAAYa,MAAM,iBAAiB,SAASC,GAC3CA,EAAEC,YAGwB,IAAdrB,UACRJ,EAAE0B,MAAK,WACHtB,UAAUO,QACVA,OAAOD,YAAYiB,iBACnBpB,EAAEC,KAAKoB,YAAY,4CAGvBrB,EAAEC,KAAKoB,YAAY,8CAGG,IAAdvB,UACRL,EAAE0B,MAAK,WACHrB,UAAUM,QACVJ,EAAEC,KAAKoB,YAAY,4CAGvBrB,EAAEC,KAAKoB,YAAY,4CAK/BjB,OAAOD,YAAYmB,OACnBtB,EAAEC,KAAKoB,YAAY,wCAO3B3B,SAAS6B,UAAUC,MAAQ,gBAClBrB,YAAYsB,YACZtB,YAAYuB,WAOrBhC,SAAS6B,UAAUI,WAAa,kBACrBtB,KAAKF,YAAYyB,SAASC,cAGQnC"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/dragdrop-reorder.min.js b/admin/tool/lp/amd/build/dragdrop-reorder.min.js
index d83b1c62107..d5a282411ff 100644
--- a/admin/tool/lp/amd/build/dragdrop-reorder.min.js
+++ b/admin/tool/lp/amd/build/dragdrop-reorder.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/dragdrop-reorder",["core/str","core/yui"],function(a,b){var c=null,d=function(a){var b=a.drag.get("node"),c=a.drop.get("node");this.callback(b.getDOMNode(),c.getDOMNode())};return{dragdrop:function dragdrop(e,f,g,h,i,j,k,l){a.get_strings([{key:"emptydragdropregion",component:"moodle"},{key:"movecontent",component:"moodle"},{key:"tocontent",component:"moodle"}]).done(function(){b.use("moodle-tool_lp-dragdrop-reorder",function(){if(c){c.destroy()}c=M.tool_lp.dragdrop_reorder({group:e,dragHandleText:f,sameNodeText:g,parentNodeText:h,sameNodeClass:i,parentNodeClass:j,dragHandleInsertClass:k,callback:b.bind(d,{callback:l})})})})}}});
-//# sourceMappingURL=dragdrop-reorder.min.js.map
+/**
+ * Drag and drop reorder via HTML5.
+ *
+ * @module tool_lp/dragdrop-reorder
+ * @copyright 2015 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/dragdrop-reorder",["core/str","core/yui"],(function(str,Y){var dragDropInstance=null,proxyCallback=function(e){var dragNode=e.drag.get("node"),dropNode=e.drop.get("node");this.callback(dragNode.getDOMNode(),dropNode.getDOMNode())};return{dragdrop:function(group,dragHandleText,sameNodeText,parentNodeText,sameNodeClass,parentNodeClass,dragHandleInsertClass,callback){str.get_strings([{key:"emptydragdropregion",component:"moodle"},{key:"movecontent",component:"moodle"},{key:"tocontent",component:"moodle"}]).done((function(){Y.use("moodle-tool_lp-dragdrop-reorder",(function(){var context={callback:callback};dragDropInstance&&dragDropInstance.destroy(),dragDropInstance=M.tool_lp.dragdrop_reorder({group:group,dragHandleText:dragHandleText,sameNodeText:sameNodeText,parentNodeText:parentNodeText,sameNodeClass:sameNodeClass,parentNodeClass:parentNodeClass,dragHandleInsertClass:dragHandleInsertClass,callback:Y.bind(proxyCallback,context)})}))}))}}}));
+
+//# sourceMappingURL=dragdrop-reorder.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/dragdrop-reorder.min.js.map b/admin/tool/lp/amd/build/dragdrop-reorder.min.js.map
index fb8b59038a3..ed41f5b52a8 100644
--- a/admin/tool/lp/amd/build/dragdrop-reorder.min.js.map
+++ b/admin/tool/lp/amd/build/dragdrop-reorder.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/dragdrop-reorder.js"],"names":["define","str","Y","dragDropInstance","proxyCallback","e","dragNode","drag","get","dropNode","drop","callback","getDOMNode","dragdrop","group","dragHandleText","sameNodeText","parentNodeText","sameNodeClass","parentNodeClass","dragHandleInsertClass","get_strings","key","component","done","use","destroy","M","tool_lp","dragdrop_reorder","bind"],"mappings":"AAsBAA,OAAM,4BAAC,CAAC,UAAD,CAAa,UAAb,CAAD,CAA2B,SAASC,CAAT,CAAcC,CAAd,CAAiB,IAQ1CC,CAAAA,CAAgB,CAAG,IARuB,CAe1CC,CAAa,CAAG,SAASC,CAAT,CAAY,IACxBC,CAAAA,CAAQ,CAAGD,CAAC,CAACE,IAAF,CAAOC,GAAP,CAAW,MAAX,CADa,CAExBC,CAAQ,CAAGJ,CAAC,CAACK,IAAF,CAAOF,GAAP,CAAW,MAAX,CAFa,CAG5B,KAAKG,QAAL,CAAcL,CAAQ,CAACM,UAAT,EAAd,CAAqCH,CAAQ,CAACG,UAAT,EAArC,CACH,CAnB6C,CAqB9C,MAAqD,CAcjDC,QAAQ,CAAE,kBAASC,CAAT,CACSC,CADT,CAESC,CAFT,CAGSC,CAHT,CAISC,CAJT,CAKSC,CALT,CAMSC,CANT,CAOST,CAPT,CAOmB,CAGzBV,CAAG,CAACoB,WAAJ,CAAgB,CACZ,CAACC,GAAG,CAAE,qBAAN,CAA6BC,SAAS,CAAE,QAAxC,CADY,CAEZ,CAACD,GAAG,CAAE,aAAN,CAAqBC,SAAS,CAAE,QAAhC,CAFY,CAGZ,CAACD,GAAG,CAAE,WAAN,CAAmBC,SAAS,CAAE,QAA9B,CAHY,CAAhB,EAIGC,IAJH,CAIQ,UAAW,CACftB,CAAC,CAACuB,GAAF,CAAM,iCAAN,CAAyC,UAAW,CAKhD,GAAItB,CAAJ,CAAsB,CAClBA,CAAgB,CAACuB,OAAjB,EACH,CACDvB,CAAgB,CAAGwB,CAAC,CAACC,OAAF,CAAUC,gBAAV,CAA2B,CAC1Cf,KAAK,CAAEA,CADmC,CAE1CC,cAAc,CAAEA,CAF0B,CAG1CC,YAAY,CAAEA,CAH4B,CAI1CC,cAAc,CAAEA,CAJ0B,CAK1CC,aAAa,CAAEA,CAL2B,CAM1CC,eAAe,CAAEA,CANyB,CAO1CC,qBAAqB,CAAEA,CAPmB,CAQ1CT,QAAQ,CAAET,CAAC,CAAC4B,IAAF,CAAO1B,CAAP,CAdA,CACVO,QAAQ,CAAEA,CADA,CAcA,CARgC,CAA3B,CAUtB,CAlBD,CAmBH,CAxBD,CAyBH,CAjDgD,CAoDxD,CAzEK,CAAN","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 .\n\n/**\n * Drag and drop reorder via HTML5.\n *\n * @module tool_lp/dragdrop-reorder\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['core/str', 'core/yui'], function(str, Y) {\n // Private variables and functions.\n\n /**\n * Store the current instance of the core drag drop.\n *\n * @property {object} dragDropInstance M.tool_lp.dragdrop_reorder\n */\n var dragDropInstance = null;\n\n /**\n * Translate the drophit event from YUI\n * into simple drag and drop nodes.\n * @param {Y.Event} e The yui drop event.\n */\n var proxyCallback = function(e) {\n var dragNode = e.drag.get('node');\n var dropNode = e.drop.get('node');\n this.callback(dragNode.getDOMNode(), dropNode.getDOMNode());\n };\n\n return /** @alias module:tool_lp/dragdrop-reorder */ {\n // Public variables and functions.\n /**\n * Create an instance of M.tool_lp.dragdrop\n *\n * @param {String} group Unique string to identify this interaction.\n * @param {String} dragHandleText Alt text for the drag handle.\n * @param {String} sameNodeText Used in keyboard drag drop for the list of items target.\n * @param {String} parentNodeText Used in keyboard drag drop for the parent target.\n * @param {String} sameNodeClass class used to find the each of the list of items.\n * @param {String} parentNodeClass class used to find the container for the list of items.\n * @param {String} dragHandleInsertClass class used to find the location to insert the drag handles.\n * @param {function} callback Drop hit handler.\n */\n dragdrop: function(group,\n dragHandleText,\n sameNodeText,\n parentNodeText,\n sameNodeClass,\n parentNodeClass,\n dragHandleInsertClass,\n callback) {\n // Here we are wrapping YUI. This allows us to start transitioning, but\n // wait for a good alternative without having inconsistent UIs.\n str.get_strings([\n {key: 'emptydragdropregion', component: 'moodle'},\n {key: 'movecontent', component: 'moodle'},\n {key: 'tocontent', component: 'moodle'},\n ]).done(function() {\n Y.use('moodle-tool_lp-dragdrop-reorder', function() {\n\n var context = {\n callback: callback\n };\n if (dragDropInstance) {\n dragDropInstance.destroy();\n }\n dragDropInstance = M.tool_lp.dragdrop_reorder({\n group: group,\n dragHandleText: dragHandleText,\n sameNodeText: sameNodeText,\n parentNodeText: parentNodeText,\n sameNodeClass: sameNodeClass,\n parentNodeClass: parentNodeClass,\n dragHandleInsertClass: dragHandleInsertClass,\n callback: Y.bind(proxyCallback, context)\n });\n });\n });\n }\n\n };\n});\n"],"file":"dragdrop-reorder.min.js"}
\ No newline at end of file
+{"version":3,"file":"dragdrop-reorder.min.js","sources":["../src/dragdrop-reorder.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 .\n\n/**\n * Drag and drop reorder via HTML5.\n *\n * @module tool_lp/dragdrop-reorder\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['core/str', 'core/yui'], function(str, Y) {\n // Private variables and functions.\n\n /**\n * Store the current instance of the core drag drop.\n *\n * @property {object} dragDropInstance M.tool_lp.dragdrop_reorder\n */\n var dragDropInstance = null;\n\n /**\n * Translate the drophit event from YUI\n * into simple drag and drop nodes.\n * @param {Y.Event} e The yui drop event.\n */\n var proxyCallback = function(e) {\n var dragNode = e.drag.get('node');\n var dropNode = e.drop.get('node');\n this.callback(dragNode.getDOMNode(), dropNode.getDOMNode());\n };\n\n return /** @alias module:tool_lp/dragdrop-reorder */ {\n // Public variables and functions.\n /**\n * Create an instance of M.tool_lp.dragdrop\n *\n * @param {String} group Unique string to identify this interaction.\n * @param {String} dragHandleText Alt text for the drag handle.\n * @param {String} sameNodeText Used in keyboard drag drop for the list of items target.\n * @param {String} parentNodeText Used in keyboard drag drop for the parent target.\n * @param {String} sameNodeClass class used to find the each of the list of items.\n * @param {String} parentNodeClass class used to find the container for the list of items.\n * @param {String} dragHandleInsertClass class used to find the location to insert the drag handles.\n * @param {function} callback Drop hit handler.\n */\n dragdrop: function(group,\n dragHandleText,\n sameNodeText,\n parentNodeText,\n sameNodeClass,\n parentNodeClass,\n dragHandleInsertClass,\n callback) {\n // Here we are wrapping YUI. This allows us to start transitioning, but\n // wait for a good alternative without having inconsistent UIs.\n str.get_strings([\n {key: 'emptydragdropregion', component: 'moodle'},\n {key: 'movecontent', component: 'moodle'},\n {key: 'tocontent', component: 'moodle'},\n ]).done(function() {\n Y.use('moodle-tool_lp-dragdrop-reorder', function() {\n\n var context = {\n callback: callback\n };\n if (dragDropInstance) {\n dragDropInstance.destroy();\n }\n dragDropInstance = M.tool_lp.dragdrop_reorder({\n group: group,\n dragHandleText: dragHandleText,\n sameNodeText: sameNodeText,\n parentNodeText: parentNodeText,\n sameNodeClass: sameNodeClass,\n parentNodeClass: parentNodeClass,\n dragHandleInsertClass: dragHandleInsertClass,\n callback: Y.bind(proxyCallback, context)\n });\n });\n });\n }\n\n };\n});\n"],"names":["define","str","Y","dragDropInstance","proxyCallback","e","dragNode","drag","get","dropNode","drop","callback","getDOMNode","dragdrop","group","dragHandleText","sameNodeText","parentNodeText","sameNodeClass","parentNodeClass","dragHandleInsertClass","get_strings","key","component","done","use","context","destroy","M","tool_lp","dragdrop_reorder","bind"],"mappings":";;;;;;;AAsBAA,kCAAO,CAAC,WAAY,aAAa,SAASC,IAAKC,OAQvCC,iBAAmB,KAOnBC,cAAgB,SAASC,OACrBC,SAAWD,EAAEE,KAAKC,IAAI,QACtBC,SAAWJ,EAAEK,KAAKF,IAAI,aACrBG,SAASL,SAASM,aAAcH,SAASG,qBAGG,CAcjDC,SAAU,SAASC,MACAC,eACAC,aACAC,eACAC,cACAC,gBACAC,sBACAT,UAGfV,IAAIoB,YAAY,CACZ,CAACC,IAAK,sBAAuBC,UAAW,UACxC,CAACD,IAAK,cAAeC,UAAW,UAChC,CAACD,IAAK,YAAaC,UAAW,YAC/BC,MAAK,WACJtB,EAAEuB,IAAI,mCAAmC,eAEjCC,QAAU,CACVf,SAAUA,UAEVR,kBACAA,iBAAiBwB,UAErBxB,iBAAmByB,EAAEC,QAAQC,iBAAiB,CAC1ChB,MAAOA,MACPC,eAAgBA,eAChBC,aAAcA,aACdC,eAAgBA,eAChBC,cAAeA,cACfC,gBAAiBA,gBACjBC,sBAAuBA,sBACvBT,SAAUT,EAAE6B,KAAK3B,cAAesB"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/event_base.min.js b/admin/tool/lp/amd/build/event_base.min.js
index bd20aa13ce0..ab189053f91 100644
--- a/admin/tool/lp/amd/build/event_base.min.js
+++ b/admin/tool/lp/amd/build/event_base.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/event_base",["jquery"],function(a){var b=function(){this._eventNode=a("")};b.prototype._eventNode=null;b.prototype.on=function(a,b){this._eventNode.on(a,b)};b.prototype._trigger=function(a,b){this._eventNode.trigger(a,[b])};return b});
-//# sourceMappingURL=event_base.min.js.map
+/**
+ * Event base javascript module.
+ *
+ * @module tool_lp/event_base
+ * @copyright 2015 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/event_base",["jquery"],(function($){var Base=function(){this._eventNode=$("")};return Base.prototype._eventNode=null,Base.prototype.on=function(type,handler){this._eventNode.on(type,handler)},Base.prototype._trigger=function(type,data){this._eventNode.trigger(type,[data])},Base}));
+
+//# sourceMappingURL=event_base.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/event_base.min.js.map b/admin/tool/lp/amd/build/event_base.min.js.map
index d587f301884..5acbe6740c4 100644
--- a/admin/tool/lp/amd/build/event_base.min.js.map
+++ b/admin/tool/lp/amd/build/event_base.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/event_base.js"],"names":["define","$","Base","_eventNode","prototype","on","type","handler","_trigger","data","trigger"],"mappings":"AAsBAA,OAAM,sBAAC,CAAC,QAAD,CAAD,CAAa,SAASC,CAAT,CAAY,CAK3B,GAAIC,CAAAA,CAAI,CAAG,UAAW,CAClB,KAAKC,UAAL,CAAkBF,CAAC,CAAC,aAAD,CACtB,CAFD,CAKAC,CAAI,CAACE,SAAL,CAAeD,UAAf,CAA4B,IAA5B,CASAD,CAAI,CAACE,SAAL,CAAeC,EAAf,CAAoB,SAASC,CAAT,CAAeC,CAAf,CAAwB,CACxC,KAAKJ,UAAL,CAAgBE,EAAhB,CAAmBC,CAAnB,CAAyBC,CAAzB,CACH,CAFD,CAWAL,CAAI,CAACE,SAAL,CAAeI,QAAf,CAA0B,SAASF,CAAT,CAAeG,CAAf,CAAqB,CAC3C,KAAKN,UAAL,CAAgBO,OAAhB,CAAwBJ,CAAxB,CAA8B,CAACG,CAAD,CAA9B,CACH,CAFD,CAIA,MAA+CP,CAAAA,CAClD,CAnCK,CAAN","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 .\n\n/**\n * Event base javascript module.\n *\n * @module tool_lp/event_base\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery'], function($) {\n\n /**\n * Base class.\n */\n var Base = function() {\n this._eventNode = $('');\n };\n\n /** @property {Node} The node we attach the events to. */\n Base.prototype._eventNode = null;\n\n /**\n * Register an event listener.\n *\n * @param {String} type The event type.\n * @param {Function} handler The event listener.\n * @method on\n */\n Base.prototype.on = function(type, handler) {\n this._eventNode.on(type, handler);\n };\n\n /**\n * Trigger an event.\n *\n * @param {String} type The type of event.\n * @param {Object} data The data to pass to the listeners.\n * @method _trigger\n */\n Base.prototype._trigger = function(type, data) {\n this._eventNode.trigger(type, [data]);\n };\n\n return /** @alias module:tool_lp/event_base */ Base;\n});\n"],"file":"event_base.min.js"}
\ No newline at end of file
+{"version":3,"file":"event_base.min.js","sources":["../src/event_base.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 .\n\n/**\n * Event base javascript module.\n *\n * @module tool_lp/event_base\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery'], function($) {\n\n /**\n * Base class.\n */\n var Base = function() {\n this._eventNode = $('');\n };\n\n /** @property {Node} The node we attach the events to. */\n Base.prototype._eventNode = null;\n\n /**\n * Register an event listener.\n *\n * @param {String} type The event type.\n * @param {Function} handler The event listener.\n * @method on\n */\n Base.prototype.on = function(type, handler) {\n this._eventNode.on(type, handler);\n };\n\n /**\n * Trigger an event.\n *\n * @param {String} type The type of event.\n * @param {Object} data The data to pass to the listeners.\n * @method _trigger\n */\n Base.prototype._trigger = function(type, data) {\n this._eventNode.trigger(type, [data]);\n };\n\n return /** @alias module:tool_lp/event_base */ Base;\n});\n"],"names":["define","$","Base","_eventNode","prototype","on","type","handler","_trigger","data","trigger"],"mappings":";;;;;;;AAsBAA,4BAAO,CAAC,WAAW,SAASC,OAKpBC,KAAO,gBACFC,WAAaF,EAAE,uBAIxBC,KAAKE,UAAUD,WAAa,KAS5BD,KAAKE,UAAUC,GAAK,SAASC,KAAMC,cAC1BJ,WAAWE,GAAGC,KAAMC,UAU7BL,KAAKE,UAAUI,SAAW,SAASF,KAAMG,WAChCN,WAAWO,QAAQJ,KAAM,CAACG,QAGYP"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/evidence_delete.min.js b/admin/tool/lp/amd/build/evidence_delete.min.js
index d74b0d9f06b..dc56c219b5e 100644
--- a/admin/tool/lp/amd/build/evidence_delete.min.js
+++ b/admin/tool/lp/amd/build/evidence_delete.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/evidence_delete",["jquery","core/notification","core/ajax","core/str","core/log"],function(a,b,c,d,e){var f={};return{register:function register(g,h){if("undefined"!=typeof f[g]){return}f[g]=a("body").delegate(g,"click",function(f){var g=a(f.currentTarget).parents(h);if(!g.length||11)Log.error("None or too many evidence container were found.");else{var evidenceId=parent.data("id");evidenceId?(e.preventDefault(),e.stopPropagation(),Str.get_strings([{key:"confirm",component:"moodle"},{key:"areyousure",component:"moodle"},{key:"delete",component:"moodle"},{key:"cancel",component:"moodle"}]).done((function(strings){Notification.confirm(strings[0],strings[1],strings[2],strings[3],(function(){Ajax.call([{methodname:"core_competency_delete_evidence",args:{id:evidenceId}}])[0].then((function(){parent.remove()})).fail(Notification.exception)}))})).fail(Notification.exception)):Log.error("Evidence ID was not found.")}})))}}}));
+
+//# sourceMappingURL=evidence_delete.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/evidence_delete.min.js.map b/admin/tool/lp/amd/build/evidence_delete.min.js.map
index 285ff964b1d..f16b333f0b6 100644
--- a/admin/tool/lp/amd/build/evidence_delete.min.js.map
+++ b/admin/tool/lp/amd/build/evidence_delete.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/evidence_delete.js"],"names":["define","$","Notification","Ajax","Str","Log","selectors","register","triggerSelector","containerSelector","delegate","e","parent","currentTarget","parents","length","error","evidenceId","data","preventDefault","stopPropagation","get_strings","key","component","done","strings","confirm","promise","call","methodname","args","id","then","remove","fail","exception"],"mappings":"AAuBAA,OAAM,2BAAC,CAAC,QAAD,CACC,mBADD,CAEC,WAFD,CAGC,UAHD,CAIC,UAJD,CAAD,CAKE,SAASC,CAAT,CAAYC,CAAZ,CAA0BC,CAA1B,CAAgCC,CAAhC,CAAqCC,CAArC,CAA0C,IAE1CC,CAAAA,CAAS,CAAG,EAF8B,CA4D9C,MAAoD,CAShDC,QAAQ,CA3DG,QAAXA,CAAAA,QAAW,CAASC,CAAT,CAA0BC,CAA1B,CAA6C,CACxD,GAA0C,WAAtC,QAAOH,CAAAA,CAAS,CAACE,CAAD,CAApB,CAAuD,CACnD,MACH,CAEDF,CAAS,CAACE,CAAD,CAAT,CAA6BP,CAAC,CAAC,MAAD,CAAD,CAAUS,QAAV,CAAmBF,CAAnB,CAAoC,OAApC,CAA6C,SAASG,CAAT,CAAY,CAClF,GAAIC,CAAAA,CAAM,CAAGX,CAAC,CAACU,CAAC,CAACE,aAAH,CAAD,CAAmBC,OAAnB,CAA2BL,CAA3B,CAAb,CACA,GAAI,CAACG,CAAM,CAACG,MAAR,EAAkC,CAAhB,CAAAH,CAAM,CAACG,MAA7B,CAAyC,CACrCV,CAAG,CAACW,KAAJ,CAAU,iDAAV,EACA,MACH,CACD,GAAIC,CAAAA,CAAU,CAAGL,CAAM,CAACM,IAAP,CAAY,IAAZ,CAAjB,CACA,GAAI,CAACD,CAAL,CAAiB,CACbZ,CAAG,CAACW,KAAJ,CAAU,4BAAV,EACA,MACH,CAEDL,CAAC,CAACQ,cAAF,GACAR,CAAC,CAACS,eAAF,GAEAhB,CAAG,CAACiB,WAAJ,CAAgB,CACZ,CAACC,GAAG,CAAE,SAAN,CAAiBC,SAAS,CAAE,QAA5B,CADY,CAEZ,CAACD,GAAG,CAAE,YAAN,CAAoBC,SAAS,CAAE,QAA/B,CAFY,CAGZ,CAACD,GAAG,CAAE,QAAN,CAAgBC,SAAS,CAAE,QAA3B,CAHY,CAIZ,CAACD,GAAG,CAAE,QAAN,CAAgBC,SAAS,CAAE,QAA3B,CAJY,CAAhB,EAKGC,IALH,CAKQ,SAASC,CAAT,CAAkB,CACtBvB,CAAY,CAACwB,OAAb,CACID,CAAO,CAAC,CAAD,CADX,CAEIA,CAAO,CAAC,CAAD,CAFX,CAGIA,CAAO,CAAC,CAAD,CAHX,CAIIA,CAAO,CAAC,CAAD,CAJX,CAKI,UAAW,CACP,GAAIE,CAAAA,CAAO,CAAGxB,CAAI,CAACyB,IAAL,CAAU,CAAC,CACrBC,UAAU,CAAE,iCADS,CAErBC,IAAI,CAAE,CACFC,EAAE,CAAEd,CADF,CAFe,CAAD,CAAV,CAAd,CAMAU,CAAO,CAAC,CAAD,CAAP,CAAWK,IAAX,CAAgB,UAAW,CACvBpB,CAAM,CAACqB,MAAP,EAEH,CAHD,EAGGC,IAHH,CAGQhC,CAAY,CAACiC,SAHrB,CAIH,CAhBL,CAkBH,CAxBD,EAwBGD,IAxBH,CAwBQhC,CAAY,CAACiC,SAxBrB,CA2BH,CA1C4B,CA2ChC,CAEmD,CAYvD,CA7EK,CAAN","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 .\n\n/**\n * Evidence delete.\n *\n * @module tool_lp/evidence_delete\n * @copyright 2016 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/str',\n 'core/log'],\n function($, Notification, Ajax, Str, Log) {\n\n var selectors = {};\n\n /**\n * Register an event listener.\n *\n * @param {String} triggerSelector The node on which the click will happen.\n * @param {String} containerSelector The parent node that will be removed and contains the evidence ID.\n */\n var register = function(triggerSelector, containerSelector) {\n if (typeof selectors[triggerSelector] !== 'undefined') {\n return;\n }\n\n selectors[triggerSelector] = $('body').delegate(triggerSelector, 'click', function(e) {\n var parent = $(e.currentTarget).parents(containerSelector);\n if (!parent.length || parent.length > 1) {\n Log.error('None or too many evidence container were found.');\n return;\n }\n var evidenceId = parent.data('id');\n if (!evidenceId) {\n Log.error('Evidence ID was not found.');\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n\n Str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'areyousure', component: 'moodle'},\n {key: 'delete', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n Notification.confirm(\n strings[0], // Confirm.\n strings[1], // Are you sure?\n strings[2], // Delete.\n strings[3], // Cancel.\n function() {\n var promise = Ajax.call([{\n methodname: 'core_competency_delete_evidence',\n args: {\n id: evidenceId\n }\n }]);\n promise[0].then(function() {\n parent.remove();\n return;\n }).fail(Notification.exception);\n }\n );\n }).fail(Notification.exception);\n\n\n });\n };\n\n return /** @alias module:tool_lp/evidence_delete */ {\n\n /**\n * Register an event listener.\n *\n * @param {String} triggerSelector The node on which the click will happen.\n * @param {String} containerSelector The parent node that will be removed and contains the evidence ID.\n * @return {Void}\n */\n register: register\n };\n\n});\n"],"file":"evidence_delete.min.js"}
\ No newline at end of file
+{"version":3,"file":"evidence_delete.min.js","sources":["../src/evidence_delete.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 .\n\n/**\n * Evidence delete.\n *\n * @module tool_lp/evidence_delete\n * @copyright 2016 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/str',\n 'core/log'],\n function($, Notification, Ajax, Str, Log) {\n\n var selectors = {};\n\n /**\n * Register an event listener.\n *\n * @param {String} triggerSelector The node on which the click will happen.\n * @param {String} containerSelector The parent node that will be removed and contains the evidence ID.\n */\n var register = function(triggerSelector, containerSelector) {\n if (typeof selectors[triggerSelector] !== 'undefined') {\n return;\n }\n\n selectors[triggerSelector] = $('body').delegate(triggerSelector, 'click', function(e) {\n var parent = $(e.currentTarget).parents(containerSelector);\n if (!parent.length || parent.length > 1) {\n Log.error('None or too many evidence container were found.');\n return;\n }\n var evidenceId = parent.data('id');\n if (!evidenceId) {\n Log.error('Evidence ID was not found.');\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n\n Str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'areyousure', component: 'moodle'},\n {key: 'delete', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n Notification.confirm(\n strings[0], // Confirm.\n strings[1], // Are you sure?\n strings[2], // Delete.\n strings[3], // Cancel.\n function() {\n var promise = Ajax.call([{\n methodname: 'core_competency_delete_evidence',\n args: {\n id: evidenceId\n }\n }]);\n promise[0].then(function() {\n parent.remove();\n return;\n }).fail(Notification.exception);\n }\n );\n }).fail(Notification.exception);\n\n\n });\n };\n\n return /** @alias module:tool_lp/evidence_delete */ {\n\n /**\n * Register an event listener.\n *\n * @param {String} triggerSelector The node on which the click will happen.\n * @param {String} containerSelector The parent node that will be removed and contains the evidence ID.\n * @return {Void}\n */\n register: register\n };\n\n});\n"],"names":["define","$","Notification","Ajax","Str","Log","selectors","register","triggerSelector","containerSelector","delegate","e","parent","currentTarget","parents","length","error","evidenceId","data","preventDefault","stopPropagation","get_strings","key","component","done","strings","confirm","call","methodname","args","id","then","remove","fail","exception"],"mappings":";;;;;;;AAuBAA,iCAAO,CAAC,SACA,oBACA,YACA,WACA,aACA,SAASC,EAAGC,aAAcC,KAAMC,IAAKC,SAErCC,UAAY,SA0DoC,CAShDC,SA3DW,SAASC,gBAAiBC,wBACK,IAA/BH,UAAUE,mBAIrBF,UAAUE,iBAAmBP,EAAE,QAAQS,SAASF,gBAAiB,SAAS,SAASG,OAC3EC,OAASX,EAAEU,EAAEE,eAAeC,QAAQL,uBACnCG,OAAOG,QAAUH,OAAOG,OAAS,EAClCV,IAAIW,MAAM,4DAGVC,WAAaL,OAAOM,KAAK,MACxBD,YAKLN,EAAEQ,iBACFR,EAAES,kBAEFhB,IAAIiB,YAAY,CACZ,CAACC,IAAK,UAAWC,UAAW,UAC5B,CAACD,IAAK,aAAcC,UAAW,UAC/B,CAACD,IAAK,SAAUC,UAAW,UAC3B,CAACD,IAAK,SAAUC,UAAW,YAC5BC,MAAK,SAASC,SACbvB,aAAawB,QACTD,QAAQ,GACRA,QAAQ,GACRA,QAAQ,GACRA,QAAQ,IACR,WACkBtB,KAAKwB,KAAK,CAAC,CACrBC,WAAY,kCACZC,KAAM,CACFC,GAAIb,eAGJ,GAAGc,MAAK,WACZnB,OAAOoB,YAERC,KAAK/B,aAAagC,iBAG9BD,KAAK/B,aAAagC,YA/BjB7B,IAAIW,MAAM"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/form-cohort-selector.min.js b/admin/tool/lp/amd/build/form-cohort-selector.min.js
index 5a7a0144e19..bfa8a6bebbf 100644
--- a/admin/tool/lp/amd/build/form-cohort-selector.min.js
+++ b/admin/tool/lp/amd/build/form-cohort-selector.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/form-cohort-selector",["jquery","core/ajax","core/templates"],function(a,b,c){return{processResults:function processResults(b,c){var d=[];a.each(c,function(a,b){d.push({value:b.id,label:b._label})});return d},transport:function transport(d,e,f,g){var h,i=parseInt(a(d).data("contextid"),10),j=a(d).data("includes");h=b.call([{methodname:"tool_lp_search_cohorts",args:{query:e,context:{contextid:i},includes:j}}]);h[0].then(function(b){var d=[],e=0;a.each(b.cohorts,function(a,b){d.push(c.render("tool_lp/form-cohort-selector-suggestion",b))});return a.when.apply(a.when,d).then(function(){var c=arguments;a.each(b.cohorts,function(a,b){b._label=c[e];e++});f(b.cohorts)})}).catch(g)}}});
-//# sourceMappingURL=form-cohort-selector.min.js.map
+/**
+ * Cohort selector module.
+ *
+ * @module tool_lp/form-cohort-selector
+ * @copyright 2015 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/form-cohort-selector",["jquery","core/ajax","core/templates"],(function($,Ajax,Templates){return{processResults:function(selector,results){var cohorts=[];return $.each(results,(function(index,cohort){cohorts.push({value:cohort.id,label:cohort._label})})),cohorts},transport:function(selector,query,success,failure){var contextid=parseInt($(selector).data("contextid"),10),includes=$(selector).data("includes");Ajax.call([{methodname:"tool_lp_search_cohorts",args:{query:query,context:{contextid:contextid},includes:includes}}])[0].then((function(results){var promises=[],i=0;return $.each(results.cohorts,(function(index,cohort){promises.push(Templates.render("tool_lp/form-cohort-selector-suggestion",cohort))})),$.when.apply($.when,promises).then((function(){var args=arguments;$.each(results.cohorts,(function(index,cohort){cohort._label=args[i],i++})),success(results.cohorts)}))})).catch(failure)}}}));
+
+//# sourceMappingURL=form-cohort-selector.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/form-cohort-selector.min.js.map b/admin/tool/lp/amd/build/form-cohort-selector.min.js.map
index df2182978b6..aa365af512a 100644
--- a/admin/tool/lp/amd/build/form-cohort-selector.min.js.map
+++ b/admin/tool/lp/amd/build/form-cohort-selector.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/form-cohort-selector.js"],"names":["define","$","Ajax","Templates","processResults","selector","results","cohorts","each","index","cohort","push","value","id","label","_label","transport","query","success","failure","promise","contextid","parseInt","data","includes","call","methodname","args","context","then","promises","i","render","when","apply","arguments","catch"],"mappings":"AAuBAA,OAAM,gCAAC,CAAC,QAAD,CAAW,WAAX,CAAwB,gBAAxB,CAAD,CAA4C,SAASC,CAAT,CAAYC,CAAZ,CAAkBC,CAAlB,CAA6B,CAE3E,MAAyD,CAErDC,cAAc,CAAE,wBAASC,CAAT,CAAmBC,CAAnB,CAA4B,CACxC,GAAIC,CAAAA,CAAO,CAAG,EAAd,CACAN,CAAC,CAACO,IAAF,CAAOF,CAAP,CAAgB,SAASG,CAAT,CAAgBC,CAAhB,CAAwB,CACpCH,CAAO,CAACI,IAAR,CAAa,CACTC,KAAK,CAAEF,CAAM,CAACG,EADL,CAETC,KAAK,CAAEJ,CAAM,CAACK,MAFL,CAAb,CAIH,CALD,EAMA,MAAOR,CAAAA,CACV,CAXoD,CAarDS,SAAS,CAAE,mBAASX,CAAT,CAAmBY,CAAnB,CAA0BC,CAA1B,CAAmCC,CAAnC,CAA4C,CACnD,GAAIC,CAAAA,CAAJ,CACIC,CAAS,CAAGC,QAAQ,CAACrB,CAAC,CAACI,CAAD,CAAD,CAAYkB,IAAZ,CAAiB,WAAjB,CAAD,CAAgC,EAAhC,CADxB,CAEIC,CAAQ,CAAGvB,CAAC,CAACI,CAAD,CAAD,CAAYkB,IAAZ,CAAiB,UAAjB,CAFf,CAIAH,CAAO,CAAGlB,CAAI,CAACuB,IAAL,CAAU,CAAC,CACjBC,UAAU,CAAE,wBADK,CAEjBC,IAAI,CAAE,CACFV,KAAK,CAAEA,CADL,CAEFW,OAAO,CAAE,CAACP,SAAS,CAAEA,CAAZ,CAFP,CAGFG,QAAQ,CAAEA,CAHR,CAFW,CAAD,CAAV,CAAV,CAQAJ,CAAO,CAAC,CAAD,CAAP,CAAWS,IAAX,CAAgB,SAASvB,CAAT,CAAkB,CAC9B,GAAIwB,CAAAA,CAAQ,CAAG,EAAf,CACIC,CAAC,CAAG,CADR,CAIA9B,CAAC,CAACO,IAAF,CAAOF,CAAO,CAACC,OAAf,CAAwB,SAASE,CAAT,CAAgBC,CAAhB,CAAwB,CAC5CoB,CAAQ,CAACnB,IAAT,CAAcR,CAAS,CAAC6B,MAAV,CAAiB,yCAAjB,CAA4DtB,CAA5D,CAAd,CACH,CAFD,EAKA,MAAOT,CAAAA,CAAC,CAACgC,IAAF,CAAOC,KAAP,CAAajC,CAAC,CAACgC,IAAf,CAAqBH,CAArB,EAA+BD,IAA/B,CAAoC,UAAW,CAClD,GAAIF,CAAAA,CAAI,CAAGQ,SAAX,CACAlC,CAAC,CAACO,IAAF,CAAOF,CAAO,CAACC,OAAf,CAAwB,SAASE,CAAT,CAAgBC,CAAhB,CAAwB,CAC5CA,CAAM,CAACK,MAAP,CAAgBY,CAAI,CAACI,CAAD,CAApB,CACAA,CAAC,EACJ,CAHD,EAIAb,CAAO,CAACZ,CAAO,CAACC,OAAT,CAEV,CARM,CAUV,CApBD,EAoBG6B,KApBH,CAoBSjB,CApBT,CAqBH,CA/CoD,CAmD5D,CArDK,CAAN","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 .\n\n/**\n * Cohort selector module.\n *\n * @module tool_lp/form-cohort-selector\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) {\n\n return /** @alias module:tool_lp/form-cohort-selector */ {\n\n processResults: function(selector, results) {\n var cohorts = [];\n $.each(results, function(index, cohort) {\n cohorts.push({\n value: cohort.id,\n label: cohort._label\n });\n });\n return cohorts;\n },\n\n transport: function(selector, query, success, failure) {\n var promise,\n contextid = parseInt($(selector).data('contextid'), 10),\n includes = $(selector).data('includes');\n\n promise = Ajax.call([{\n methodname: 'tool_lp_search_cohorts',\n args: {\n query: query,\n context: {contextid: contextid},\n includes: includes\n }\n }]);\n promise[0].then(function(results) {\n var promises = [],\n i = 0;\n\n // Render the label.\n $.each(results.cohorts, function(index, cohort) {\n promises.push(Templates.render('tool_lp/form-cohort-selector-suggestion', cohort));\n });\n\n // Apply the label to the results.\n return $.when.apply($.when, promises).then(function() {\n var args = arguments;\n $.each(results.cohorts, function(index, cohort) {\n cohort._label = args[i];\n i++;\n });\n success(results.cohorts);\n return;\n });\n\n }).catch(failure);\n }\n\n };\n\n});\n"],"file":"form-cohort-selector.min.js"}
\ No newline at end of file
+{"version":3,"file":"form-cohort-selector.min.js","sources":["../src/form-cohort-selector.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 .\n\n/**\n * Cohort selector module.\n *\n * @module tool_lp/form-cohort-selector\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) {\n\n return /** @alias module:tool_lp/form-cohort-selector */ {\n\n processResults: function(selector, results) {\n var cohorts = [];\n $.each(results, function(index, cohort) {\n cohorts.push({\n value: cohort.id,\n label: cohort._label\n });\n });\n return cohorts;\n },\n\n transport: function(selector, query, success, failure) {\n var promise,\n contextid = parseInt($(selector).data('contextid'), 10),\n includes = $(selector).data('includes');\n\n promise = Ajax.call([{\n methodname: 'tool_lp_search_cohorts',\n args: {\n query: query,\n context: {contextid: contextid},\n includes: includes\n }\n }]);\n promise[0].then(function(results) {\n var promises = [],\n i = 0;\n\n // Render the label.\n $.each(results.cohorts, function(index, cohort) {\n promises.push(Templates.render('tool_lp/form-cohort-selector-suggestion', cohort));\n });\n\n // Apply the label to the results.\n return $.when.apply($.when, promises).then(function() {\n var args = arguments;\n $.each(results.cohorts, function(index, cohort) {\n cohort._label = args[i];\n i++;\n });\n success(results.cohorts);\n return;\n });\n\n }).catch(failure);\n }\n\n };\n\n});\n"],"names":["define","$","Ajax","Templates","processResults","selector","results","cohorts","each","index","cohort","push","value","id","label","_label","transport","query","success","failure","contextid","parseInt","data","includes","call","methodname","args","context","then","promises","i","render","when","apply","arguments","catch"],"mappings":";;;;;;;AAuBAA,sCAAO,CAAC,SAAU,YAAa,mBAAmB,SAASC,EAAGC,KAAMC,iBAEP,CAErDC,eAAgB,SAASC,SAAUC,aAC3BC,QAAU,UACdN,EAAEO,KAAKF,SAAS,SAASG,MAAOC,QAC5BH,QAAQI,KAAK,CACTC,MAAOF,OAAOG,GACdC,MAAOJ,OAAOK,YAGfR,SAGXS,UAAW,SAASX,SAAUY,MAAOC,QAASC,aAEtCC,UAAYC,SAASpB,EAAEI,UAAUiB,KAAK,aAAc,IACpDC,SAAWtB,EAAEI,UAAUiB,KAAK,YAEtBpB,KAAKsB,KAAK,CAAC,CACjBC,WAAY,yBACZC,KAAM,CACFT,MAAOA,MACPU,QAAS,CAACP,UAAWA,WACrBG,SAAUA,aAGV,GAAGK,MAAK,SAAStB,aACjBuB,SAAW,GACXC,EAAI,SAGR7B,EAAEO,KAAKF,QAAQC,SAAS,SAASE,MAAOC,QACpCmB,SAASlB,KAAKR,UAAU4B,OAAO,0CAA2CrB,YAIvET,EAAE+B,KAAKC,MAAMhC,EAAE+B,KAAMH,UAAUD,MAAK,eACnCF,KAAOQ,UACXjC,EAAEO,KAAKF,QAAQC,SAAS,SAASE,MAAOC,QACpCA,OAAOK,OAASW,KAAKI,GACrBA,OAEJZ,QAAQZ,QAAQC,eAIrB4B,MAAMhB"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/form-user-selector.min.js b/admin/tool/lp/amd/build/form-user-selector.min.js
index 0870d75389c..c22f5559c66 100644
--- a/admin/tool/lp/amd/build/form-user-selector.min.js
+++ b/admin/tool/lp/amd/build/form-user-selector.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/form-user-selector",["jquery","core/ajax","core/templates"],function(a,b,c){return{processResults:function processResults(b,c){var d=[];a.each(c,function(a,b){d.push({value:b.id,label:b._label})});return d},transport:function transport(d,e,f,g){var h,i=a(d).data("capability");if("undefined"==typeof i){i=""}h=b.call([{methodname:"tool_lp_search_users",args:{query:e,capability:i}}]);h[0].then(function(b){var d=[],e=0;a.each(b.users,function(b,e){var f=e,g=[];a.each(["idnumber","email","phone1","phone2","department","institution"],function(a,b){if("undefined"!=typeof e[b]&&""!==e[b]){f.hasidentity=!0;g.push(e[b])}});f.identity=g.join(", ");d.push(c.render("tool_lp/form-user-selector-suggestion",f))});return a.when.apply(a.when,d).then(function(){var c=arguments;a.each(b.users,function(a,b){b._label=c[e];e++});f(b.users)})}).catch(g)}}});
-//# sourceMappingURL=form-user-selector.min.js.map
+/**
+ * User selector module.
+ *
+ * @module tool_lp/form-user-selector
+ * @copyright 2015 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/form-user-selector",["jquery","core/ajax","core/templates"],(function($,Ajax,Templates){return{processResults:function(selector,results){var users=[];return $.each(results,(function(index,user){users.push({value:user.id,label:user._label})})),users},transport:function(selector,query,success,failure){var capability=$(selector).data("capability");void 0===capability&&(capability=""),Ajax.call([{methodname:"tool_lp_search_users",args:{query:query,capability:capability}}])[0].then((function(results){var promises=[],i=0;return $.each(results.users,(function(index,user){var ctx=user,identity=[];$.each(["idnumber","email","phone1","phone2","department","institution"],(function(i,k){void 0!==user[k]&&""!==user[k]&&(ctx.hasidentity=!0,identity.push(user[k]))})),ctx.identity=identity.join(", "),promises.push(Templates.render("tool_lp/form-user-selector-suggestion",ctx))})),$.when.apply($.when,promises).then((function(){var args=arguments;$.each(results.users,(function(index,user){user._label=args[i],i++})),success(results.users)}))})).catch(failure)}}}));
+
+//# sourceMappingURL=form-user-selector.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/form-user-selector.min.js.map b/admin/tool/lp/amd/build/form-user-selector.min.js.map
index 2a6ef1014dd..795c5d36195 100644
--- a/admin/tool/lp/amd/build/form-user-selector.min.js.map
+++ b/admin/tool/lp/amd/build/form-user-selector.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/form-user-selector.js"],"names":["define","$","Ajax","Templates","processResults","selector","results","users","each","index","user","push","value","id","label","_label","transport","query","success","failure","promise","capability","data","call","methodname","args","then","promises","i","ctx","identity","k","hasidentity","join","render","when","apply","arguments","catch"],"mappings":"AAuBAA,OAAM,8BAAC,CAAC,QAAD,CAAW,WAAX,CAAwB,gBAAxB,CAAD,CAA4C,SAASC,CAAT,CAAYC,CAAZ,CAAkBC,CAAlB,CAA6B,CAE3E,MAAuD,CAEnDC,cAAc,CAAE,wBAASC,CAAT,CAAmBC,CAAnB,CAA4B,CACxC,GAAIC,CAAAA,CAAK,CAAG,EAAZ,CACAN,CAAC,CAACO,IAAF,CAAOF,CAAP,CAAgB,SAASG,CAAT,CAAgBC,CAAhB,CAAsB,CAClCH,CAAK,CAACI,IAAN,CAAW,CACPC,KAAK,CAAEF,CAAI,CAACG,EADL,CAEPC,KAAK,CAAEJ,CAAI,CAACK,MAFL,CAAX,CAIH,CALD,EAMA,MAAOR,CAAAA,CACV,CAXkD,CAanDS,SAAS,CAAE,mBAASX,CAAT,CAAmBY,CAAnB,CAA0BC,CAA1B,CAAmCC,CAAnC,CAA4C,IAC/CC,CAAAA,CAD+C,CAE/CC,CAAU,CAAGpB,CAAC,CAACI,CAAD,CAAD,CAAYiB,IAAZ,CAAiB,YAAjB,CAFkC,CAGnD,GAA0B,WAAtB,QAAOD,CAAAA,CAAX,CAAuC,CACnCA,CAAU,CAAG,EAChB,CAEDD,CAAO,CAAGlB,CAAI,CAACqB,IAAL,CAAU,CAAC,CACjBC,UAAU,CAAE,sBADK,CAEjBC,IAAI,CAAE,CACFR,KAAK,CAAEA,CADL,CAEFI,UAAU,CAAEA,CAFV,CAFW,CAAD,CAAV,CAAV,CAQAD,CAAO,CAAC,CAAD,CAAP,CAAWM,IAAX,CAAgB,SAASpB,CAAT,CAAkB,CAC9B,GAAIqB,CAAAA,CAAQ,CAAG,EAAf,CACIC,CAAC,CAAG,CADR,CAIA3B,CAAC,CAACO,IAAF,CAAOF,CAAO,CAACC,KAAf,CAAsB,SAASE,CAAT,CAAgBC,CAAhB,CAAsB,CACxC,GAAImB,CAAAA,CAAG,CAAGnB,CAAV,CACIoB,CAAQ,CAAG,EADf,CAEA7B,CAAC,CAACO,IAAF,CAAO,CAAC,UAAD,CAAa,OAAb,CAAsB,QAAtB,CAAgC,QAAhC,CAA0C,YAA1C,CAAwD,aAAxD,CAAP,CAA+E,SAASoB,CAAT,CAAYG,CAAZ,CAAe,CAC1F,GAAuB,WAAnB,QAAOrB,CAAAA,CAAI,CAACqB,CAAD,CAAX,EAA8C,EAAZ,GAAArB,CAAI,CAACqB,CAAD,CAA1C,CAAsD,CAClDF,CAAG,CAACG,WAAJ,IACAF,CAAQ,CAACnB,IAAT,CAAcD,CAAI,CAACqB,CAAD,CAAlB,CACH,CACJ,CALD,EAMAF,CAAG,CAACC,QAAJ,CAAeA,CAAQ,CAACG,IAAT,CAAc,IAAd,CAAf,CACAN,CAAQ,CAAChB,IAAT,CAAcR,CAAS,CAAC+B,MAAV,CAAiB,uCAAjB,CAA0DL,CAA1D,CAAd,CACH,CAXD,EAcA,MAAO5B,CAAAA,CAAC,CAACkC,IAAF,CAAOC,KAAP,CAAanC,CAAC,CAACkC,IAAf,CAAqBR,CAArB,EAA+BD,IAA/B,CAAoC,UAAW,CAClD,GAAID,CAAAA,CAAI,CAAGY,SAAX,CACApC,CAAC,CAACO,IAAF,CAAOF,CAAO,CAACC,KAAf,CAAsB,SAASE,CAAT,CAAgBC,CAAhB,CAAsB,CACxCA,CAAI,CAACK,MAAL,CAAcU,CAAI,CAACG,CAAD,CAAlB,CACAA,CAAC,EACJ,CAHD,EAIAV,CAAO,CAACZ,CAAO,CAACC,KAAT,CAEV,CARM,CAUV,CA7BD,EA6BG+B,KA7BH,CA6BSnB,CA7BT,CA8BH,CA1DkD,CA8D1D,CAhEK,CAAN","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 .\n\n/**\n * User selector module.\n *\n * @module tool_lp/form-user-selector\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) {\n\n return /** @alias module:tool_lp/form-user-selector */ {\n\n processResults: function(selector, results) {\n var users = [];\n $.each(results, function(index, user) {\n users.push({\n value: user.id,\n label: user._label\n });\n });\n return users;\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n var capability = $(selector).data('capability');\n if (typeof capability === \"undefined\") {\n capability = '';\n }\n\n promise = Ajax.call([{\n methodname: 'tool_lp_search_users',\n args: {\n query: query,\n capability: capability\n }\n }]);\n\n promise[0].then(function(results) {\n var promises = [],\n i = 0;\n\n // Render the label.\n $.each(results.users, function(index, user) {\n var ctx = user,\n identity = [];\n $.each(['idnumber', 'email', 'phone1', 'phone2', 'department', 'institution'], function(i, k) {\n if (typeof user[k] !== 'undefined' && user[k] !== '') {\n ctx.hasidentity = true;\n identity.push(user[k]);\n }\n });\n ctx.identity = identity.join(', ');\n promises.push(Templates.render('tool_lp/form-user-selector-suggestion', ctx));\n });\n\n // Apply the label to the results.\n return $.when.apply($.when, promises).then(function() {\n var args = arguments;\n $.each(results.users, function(index, user) {\n user._label = args[i];\n i++;\n });\n success(results.users);\n return;\n });\n\n }).catch(failure);\n }\n\n };\n\n});\n"],"file":"form-user-selector.min.js"}
\ No newline at end of file
+{"version":3,"file":"form-user-selector.min.js","sources":["../src/form-user-selector.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 .\n\n/**\n * User selector module.\n *\n * @module tool_lp/form-user-selector\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) {\n\n return /** @alias module:tool_lp/form-user-selector */ {\n\n processResults: function(selector, results) {\n var users = [];\n $.each(results, function(index, user) {\n users.push({\n value: user.id,\n label: user._label\n });\n });\n return users;\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n var capability = $(selector).data('capability');\n if (typeof capability === \"undefined\") {\n capability = '';\n }\n\n promise = Ajax.call([{\n methodname: 'tool_lp_search_users',\n args: {\n query: query,\n capability: capability\n }\n }]);\n\n promise[0].then(function(results) {\n var promises = [],\n i = 0;\n\n // Render the label.\n $.each(results.users, function(index, user) {\n var ctx = user,\n identity = [];\n $.each(['idnumber', 'email', 'phone1', 'phone2', 'department', 'institution'], function(i, k) {\n if (typeof user[k] !== 'undefined' && user[k] !== '') {\n ctx.hasidentity = true;\n identity.push(user[k]);\n }\n });\n ctx.identity = identity.join(', ');\n promises.push(Templates.render('tool_lp/form-user-selector-suggestion', ctx));\n });\n\n // Apply the label to the results.\n return $.when.apply($.when, promises).then(function() {\n var args = arguments;\n $.each(results.users, function(index, user) {\n user._label = args[i];\n i++;\n });\n success(results.users);\n return;\n });\n\n }).catch(failure);\n }\n\n };\n\n});\n"],"names":["define","$","Ajax","Templates","processResults","selector","results","users","each","index","user","push","value","id","label","_label","transport","query","success","failure","capability","data","call","methodname","args","then","promises","i","ctx","identity","k","hasidentity","join","render","when","apply","arguments","catch"],"mappings":";;;;;;;AAuBAA,oCAAO,CAAC,SAAU,YAAa,mBAAmB,SAASC,EAAGC,KAAMC,iBAET,CAEnDC,eAAgB,SAASC,SAAUC,aAC3BC,MAAQ,UACZN,EAAEO,KAAKF,SAAS,SAASG,MAAOC,MAC5BH,MAAMI,KAAK,CACPC,MAAOF,KAAKG,GACZC,MAAOJ,KAAKK,YAGbR,OAGXS,UAAW,SAASX,SAAUY,MAAOC,QAASC,aAEtCC,WAAanB,EAAEI,UAAUgB,KAAK,mBACR,IAAfD,aACPA,WAAa,IAGPlB,KAAKoB,KAAK,CAAC,CACjBC,WAAY,uBACZC,KAAM,CACFP,MAAOA,MACPG,WAAYA,eAIZ,GAAGK,MAAK,SAASnB,aACjBoB,SAAW,GACXC,EAAI,SAGR1B,EAAEO,KAAKF,QAAQC,OAAO,SAASE,MAAOC,UAC9BkB,IAAMlB,KACNmB,SAAW,GACf5B,EAAEO,KAAK,CAAC,WAAY,QAAS,SAAU,SAAU,aAAc,gBAAgB,SAASmB,EAAGG,QAChE,IAAZpB,KAAKoB,IAAkC,KAAZpB,KAAKoB,KACvCF,IAAIG,aAAc,EAClBF,SAASlB,KAAKD,KAAKoB,QAG3BF,IAAIC,SAAWA,SAASG,KAAK,MAC7BN,SAASf,KAAKR,UAAU8B,OAAO,wCAAyCL,SAIrE3B,EAAEiC,KAAKC,MAAMlC,EAAEiC,KAAMR,UAAUD,MAAK,eACnCD,KAAOY,UACXnC,EAAEO,KAAKF,QAAQC,OAAO,SAASE,MAAOC,MAClCA,KAAKK,OAASS,KAAKG,GACnBA,OAEJT,QAAQZ,QAAQC,aAIrB8B,MAAMlB"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/form_competency_element.min.js b/admin/tool/lp/amd/build/form_competency_element.min.js
index c3937f2f8ac..5fbf4040bd3 100644
--- a/admin/tool/lp/amd/build/form_competency_element.min.js
+++ b/admin/tool/lp/amd/build/form_competency_element.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/form_competency_element",["jquery","tool_lp/competencypicker","core/ajax","core/notification","core/templates"],function(a,b,c,d,e){var f=null,g=1,h=function(){var b=a("[data-action=\"competencies\"]").val(),f=[],g=0;if(""!=b){b=b.split(",");for(g=0;g
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/form_competency_element",["jquery","tool_lp/competencypicker","core/ajax","core/notification","core/templates"],(function($,Picker,Ajax,Notification,Templates){var pickerInstance=null,pageContextId=1,renderCompetencies=function(){var currentCompetencies=$('[data-action="competencies"]').val(),requests=[],i=0;if(""!=currentCompetencies)for(currentCompetencies=currentCompetencies.split(","),i=0;i.\n\n/**\n * Badge select competency actions\n *\n * @module tool_lp/form_competency_element\n * @copyright 2019 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'tool_lp/competencypicker', 'core/ajax', 'core/notification', 'core/templates'],\n function($, Picker, Ajax, Notification, Templates) {\n\n var pickerInstance = null;\n\n var pageContextId = 1;\n\n /**\n * Re-render the list of selected competencies.\n *\n * @method renderCompetencies\n * @return {boolean}\n */\n var renderCompetencies = function() {\n var currentCompetencies = $('[data-action=\"competencies\"]').val();\n var requests = [];\n var i = 0;\n\n if (currentCompetencies != '') {\n currentCompetencies = currentCompetencies.split(',');\n for (i = 0; i < currentCompetencies.length; i++) {\n requests[requests.length] = {\n methodname: 'core_competency_read_competency',\n args: {id: currentCompetencies[i]}\n };\n }\n }\n\n $.when.apply($, Ajax.call(requests, false)).then(function() {\n var i = 0,\n competencies = [];\n\n for (i = 0; i < arguments.length; i++) {\n competencies[i] = arguments[i];\n }\n var context = {\n competencies: competencies\n };\n\n return Templates.render('tool_lp/form_competency_list', context);\n }).then(function(html, js) {\n Templates.replaceNode($('[data-region=\"competencies\"]'), html, js);\n return true;\n }).fail(Notification.exception);\n\n return true;\n };\n\n /**\n * Deselect a competency\n *\n * @method unpickCompetenciesHandler\n * @param {Event} e\n * @return {boolean}\n */\n var unpickCompetenciesHandler = function(e) {\n var currentCompetencies = $('[data-action=\"competencies\"]').val().split(','),\n newCompetencies = [],\n i,\n toRemove = $(e.currentTarget).data('id');\n\n for (i = 0; i < currentCompetencies.length; i++) {\n if (currentCompetencies[i] != toRemove) {\n newCompetencies[newCompetencies.length] = currentCompetencies[i];\n }\n }\n\n $('[data-action=\"competencies\"]').val(newCompetencies.join(','));\n\n return renderCompetencies();\n };\n\n /**\n * Open a competencies popup to relate competencies.\n *\n * @method pickCompetenciesHandler\n */\n var pickCompetenciesHandler = function() {\n var currentCompetencies = $('[data-action=\"competencies\"]').val().split(',');\n\n if (!pickerInstance) {\n pickerInstance = new Picker(pageContextId, false, 'parents', true);\n pickerInstance.on('save', function(e, data) {\n var before = $('[data-action=\"competencies\"]').val();\n var compIds = data.competencyIds;\n if (before != '') {\n compIds = compIds.concat(before.split(','));\n }\n var value = compIds.join(',');\n\n $('[data-action=\"competencies\"]').val(value);\n\n return renderCompetencies();\n });\n }\n\n pickerInstance.setDisallowedCompetencyIDs(currentCompetencies);\n pickerInstance.display();\n };\n\n return /** @alias module:tool_lp/form_competency_element */ {\n /**\n * Listen for clicks on the competency picker and push the changes to the form element.\n *\n * @method init\n * @param {Integer} contextId\n */\n init: function(contextId) {\n pageContextId = contextId;\n renderCompetencies();\n $('[data-action=\"select-competencies\"]').on('click', pickCompetenciesHandler);\n $('body').on('click', '[data-action=\"deselect-competency\"]', unpickCompetenciesHandler);\n }\n };\n});\n"],"file":"form_competency_element.min.js"}
\ No newline at end of file
+{"version":3,"file":"form_competency_element.min.js","sources":["../src/form_competency_element.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 .\n\n/**\n * Badge select competency actions\n *\n * @module tool_lp/form_competency_element\n * @copyright 2019 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'tool_lp/competencypicker', 'core/ajax', 'core/notification', 'core/templates'],\n function($, Picker, Ajax, Notification, Templates) {\n\n var pickerInstance = null;\n\n var pageContextId = 1;\n\n /**\n * Re-render the list of selected competencies.\n *\n * @method renderCompetencies\n * @return {boolean}\n */\n var renderCompetencies = function() {\n var currentCompetencies = $('[data-action=\"competencies\"]').val();\n var requests = [];\n var i = 0;\n\n if (currentCompetencies != '') {\n currentCompetencies = currentCompetencies.split(',');\n for (i = 0; i < currentCompetencies.length; i++) {\n requests[requests.length] = {\n methodname: 'core_competency_read_competency',\n args: {id: currentCompetencies[i]}\n };\n }\n }\n\n $.when.apply($, Ajax.call(requests, false)).then(function() {\n var i = 0,\n competencies = [];\n\n for (i = 0; i < arguments.length; i++) {\n competencies[i] = arguments[i];\n }\n var context = {\n competencies: competencies\n };\n\n return Templates.render('tool_lp/form_competency_list', context);\n }).then(function(html, js) {\n Templates.replaceNode($('[data-region=\"competencies\"]'), html, js);\n return true;\n }).fail(Notification.exception);\n\n return true;\n };\n\n /**\n * Deselect a competency\n *\n * @method unpickCompetenciesHandler\n * @param {Event} e\n * @return {boolean}\n */\n var unpickCompetenciesHandler = function(e) {\n var currentCompetencies = $('[data-action=\"competencies\"]').val().split(','),\n newCompetencies = [],\n i,\n toRemove = $(e.currentTarget).data('id');\n\n for (i = 0; i < currentCompetencies.length; i++) {\n if (currentCompetencies[i] != toRemove) {\n newCompetencies[newCompetencies.length] = currentCompetencies[i];\n }\n }\n\n $('[data-action=\"competencies\"]').val(newCompetencies.join(','));\n\n return renderCompetencies();\n };\n\n /**\n * Open a competencies popup to relate competencies.\n *\n * @method pickCompetenciesHandler\n */\n var pickCompetenciesHandler = function() {\n var currentCompetencies = $('[data-action=\"competencies\"]').val().split(',');\n\n if (!pickerInstance) {\n pickerInstance = new Picker(pageContextId, false, 'parents', true);\n pickerInstance.on('save', function(e, data) {\n var before = $('[data-action=\"competencies\"]').val();\n var compIds = data.competencyIds;\n if (before != '') {\n compIds = compIds.concat(before.split(','));\n }\n var value = compIds.join(',');\n\n $('[data-action=\"competencies\"]').val(value);\n\n return renderCompetencies();\n });\n }\n\n pickerInstance.setDisallowedCompetencyIDs(currentCompetencies);\n pickerInstance.display();\n };\n\n return /** @alias module:tool_lp/form_competency_element */ {\n /**\n * Listen for clicks on the competency picker and push the changes to the form element.\n *\n * @method init\n * @param {Integer} contextId\n */\n init: function(contextId) {\n pageContextId = contextId;\n renderCompetencies();\n $('[data-action=\"select-competencies\"]').on('click', pickCompetenciesHandler);\n $('body').on('click', '[data-action=\"deselect-competency\"]', unpickCompetenciesHandler);\n }\n };\n});\n"],"names":["define","$","Picker","Ajax","Notification","Templates","pickerInstance","pageContextId","renderCompetencies","currentCompetencies","val","requests","i","split","length","methodname","args","id","when","apply","call","then","competencies","arguments","context","render","html","js","replaceNode","fail","exception","unpickCompetenciesHandler","e","newCompetencies","toRemove","currentTarget","data","join","pickCompetenciesHandler","on","before","compIds","competencyIds","concat","value","setDisallowedCompetencyIDs","display","init","contextId"],"mappings":";;;;;;;AAsBAA,yCAAO,CAAC,SAAU,2BAA4B,YAAa,oBAAqB,mBACxE,SAASC,EAAGC,OAAQC,KAAMC,aAAcC,eAExCC,eAAiB,KAEjBC,cAAgB,EAQhBC,mBAAqB,eACjBC,oBAAsBR,EAAE,gCAAgCS,MACxDC,SAAW,GACXC,EAAI,KAEmB,IAAvBH,wBACAA,oBAAsBA,oBAAoBI,MAAM,KAC3CD,EAAI,EAAGA,EAAIH,oBAAoBK,OAAQF,IACxCD,SAASA,SAASG,QAAU,CACxBC,WAAY,kCACZC,KAAM,CAACC,GAAIR,oBAAoBG,YAK3CX,EAAEiB,KAAKC,MAAMlB,EAAGE,KAAKiB,KAAKT,UAAU,IAAQU,MAAK,eACzCT,EAAI,EACJU,aAAe,OAEdV,EAAI,EAAGA,EAAIW,UAAUT,OAAQF,IAC9BU,aAAaV,GAAKW,UAAUX,OAE5BY,QAAU,CACVF,aAAcA,qBAGXjB,UAAUoB,OAAO,+BAAgCD,YACzDH,MAAK,SAASK,KAAMC,WACnBtB,UAAUuB,YAAY3B,EAAE,gCAAiCyB,KAAMC,KACxD,KACRE,KAAKzB,aAAa0B,YAEd,GAUPC,0BAA4B,SAASC,OAGjCpB,EAFAH,oBAAsBR,EAAE,gCAAgCS,MAAMG,MAAM,KACpEoB,gBAAkB,GAElBC,SAAWjC,EAAE+B,EAAEG,eAAeC,KAAK,UAElCxB,EAAI,EAAGA,EAAIH,oBAAoBK,OAAQF,IACpCH,oBAAoBG,IAAMsB,WAC1BD,gBAAgBA,gBAAgBnB,QAAUL,oBAAoBG,WAItEX,EAAE,gCAAgCS,IAAIuB,gBAAgBI,KAAK,MAEpD7B,sBAQP8B,wBAA0B,eACtB7B,oBAAsBR,EAAE,gCAAgCS,MAAMG,MAAM,KAEnEP,iBACDA,eAAiB,IAAIJ,OAAOK,eAAe,EAAO,WAAW,IAC9CgC,GAAG,QAAQ,SAASP,EAAGI,UAC9BI,OAASvC,EAAE,gCAAgCS,MAC3C+B,QAAUL,KAAKM,cACL,IAAVF,SACAC,QAAUA,QAAQE,OAAOH,OAAO3B,MAAM,WAEtC+B,MAAQH,QAAQJ,KAAK,YAEzBpC,EAAE,gCAAgCS,IAAIkC,OAE/BpC,wBAIfF,eAAeuC,2BAA2BpC,qBAC1CH,eAAewC,iBAGyC,CAOxDC,KAAM,SAASC,WACXzC,cAAgByC,UAChBxC,qBACAP,EAAE,uCAAuCsC,GAAG,QAASD,yBACrDrC,EAAE,QAAQsC,GAAG,QAAS,sCAAuCR"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/frameworkactions.min.js b/admin/tool/lp/amd/build/frameworkactions.min.js
index 523461f0c27..c192d3a573d 100644
--- a/admin/tool/lp/amd/build/frameworkactions.min.js
+++ b/admin/tool/lp/amd/build/frameworkactions.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/frameworkactions",["jquery","core/templates","core/ajax","core/notification","core/str"],function(a,b,c,d,e){var f=0,g=0,h=function(c,d){a("[data-region=\"managecompetencies\"]").replaceWith(c);b.runTemplateJS(d)},i=function(a){b.render("tool_lp/manage_competency_frameworks_page",a).done(h).fail(d.exception)},j=function(b){b.preventDefault();g=a(this).attr("data-frameworkid");var e=c.call([{methodname:"core_competency_duplicate_competency_framework",args:{id:g}},{methodname:"tool_lp_data_for_competency_frameworks_manage_page",args:{pagecontext:{contextid:f}}}]);e[1].done(i).fail(d.exception)},k=function(){var a=c.call([{methodname:"core_competency_delete_competency_framework",args:{id:g}},{methodname:"tool_lp_data_for_competency_frameworks_manage_page",args:{pagecontext:{contextid:f}}}]);a[0].done(function(a){if(!1===a){var b=c.call([{methodname:"core_competency_read_competency_framework",args:{id:g}}]);b[0].done(function(a){e.get_strings([{key:"frameworkcannotbedeleted",component:"tool_lp",param:a.shortname},{key:"cancel",component:"moodle"}]).done(function(a){d.alert(null,a[0])}).fail(d.exception)})}}).fail(d.exception);a[1].done(i).fail(d.exception)},l=function(b){b.preventDefault();var f=a(this).attr("data-frameworkid");g=f;var h=c.call([{methodname:"core_competency_read_competency_framework",args:{id:g}}]);h[0].done(function(a){e.get_strings([{key:"confirm",component:"moodle"},{key:"deletecompetencyframework",component:"tool_lp",param:a.shortname},{key:"delete",component:"moodle"},{key:"cancel",component:"moodle"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],k)}).fail(d.exception)}).fail(d.exception)};return{deleteHandler:l,duplicateHandler:j,init:function init(a){f=a}}});
-//# sourceMappingURL=frameworkactions.min.js.map
+/**
+ * Competency frameworks actions via ajax.
+ *
+ * @module tool_lp/frameworkactions
+ * @copyright 2015 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/frameworkactions",["jquery","core/templates","core/ajax","core/notification","core/str"],(function($,templates,ajax,notification,str){var pagecontextid=0,frameworkid=0,updatePage=function(newhtml,newjs){$('[data-region="managecompetencies"]').replaceWith(newhtml),templates.runTemplateJS(newjs)},reloadList=function(context){templates.render("tool_lp/manage_competency_frameworks_page",context).done(updatePage).fail(notification.exception)},doDelete=function(){var requests=ajax.call([{methodname:"core_competency_delete_competency_framework",args:{id:frameworkid}},{methodname:"tool_lp_data_for_competency_frameworks_manage_page",args:{pagecontext:{contextid:pagecontextid}}}]);requests[0].done((function(success){!1===success&&ajax.call([{methodname:"core_competency_read_competency_framework",args:{id:frameworkid}}])[0].done((function(framework){str.get_strings([{key:"frameworkcannotbedeleted",component:"tool_lp",param:framework.shortname},{key:"cancel",component:"moodle"}]).done((function(strings){notification.alert(null,strings[0])})).fail(notification.exception)}))})).fail(notification.exception),requests[1].done(reloadList).fail(notification.exception)};return{deleteHandler:function(e){e.preventDefault();var id=$(this).attr("data-frameworkid");frameworkid=id,ajax.call([{methodname:"core_competency_read_competency_framework",args:{id:frameworkid}}])[0].done((function(framework){str.get_strings([{key:"confirm",component:"moodle"},{key:"deletecompetencyframework",component:"tool_lp",param:framework.shortname},{key:"delete",component:"moodle"},{key:"cancel",component:"moodle"}]).done((function(strings){notification.confirm(strings[0],strings[1],strings[2],strings[3],doDelete)})).fail(notification.exception)})).fail(notification.exception)},duplicateHandler:function(e){e.preventDefault(),frameworkid=$(this).attr("data-frameworkid"),ajax.call([{methodname:"core_competency_duplicate_competency_framework",args:{id:frameworkid}},{methodname:"tool_lp_data_for_competency_frameworks_manage_page",args:{pagecontext:{contextid:pagecontextid}}}])[1].done(reloadList).fail(notification.exception)},init:function(contextid){pagecontextid=contextid}}}));
+
+//# sourceMappingURL=frameworkactions.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/frameworkactions.min.js.map b/admin/tool/lp/amd/build/frameworkactions.min.js.map
index a661f254c5a..96e2bbfc0ee 100644
--- a/admin/tool/lp/amd/build/frameworkactions.min.js.map
+++ b/admin/tool/lp/amd/build/frameworkactions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/frameworkactions.js"],"names":["define","$","templates","ajax","notification","str","pagecontextid","frameworkid","updatePage","newhtml","newjs","replaceWith","runTemplateJS","reloadList","context","render","done","fail","exception","doDuplicate","e","preventDefault","attr","requests","call","methodname","args","id","pagecontext","contextid","doDelete","success","req","framework","get_strings","key","component","param","shortname","strings","alert","confirmDelete","confirm","deleteHandler","duplicateHandler","init"],"mappings":"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","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 .\n\n/**\n * Competency frameworks actions via ajax.\n *\n * @module tool_lp/frameworkactions\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'], function($, templates, ajax, notification, str) {\n // Private variables and functions.\n\n /** @var {Number} pagecontextid The id of the context */\n var pagecontextid = 0;\n\n /** @var {Number} frameworkid The id of the framework */\n var frameworkid = 0;\n\n /**\n * Callback to replace the dom element with the rendered template.\n *\n * @param {String} newhtml The new html to insert.\n * @param {String} newjs The new js to run.\n */\n var updatePage = function(newhtml, newjs) {\n $('[data-region=\"managecompetencies\"]').replaceWith(newhtml);\n templates.runTemplateJS(newjs);\n };\n\n /**\n * Callback to render the page template again and update the page.\n *\n * @param {Object} context The context for the template.\n */\n var reloadList = function(context) {\n templates.render('tool_lp/manage_competency_frameworks_page', context)\n .done(updatePage)\n .fail(notification.exception);\n };\n\n /**\n * Duplicate a framework and reload the page.\n * @method doDuplicate\n * @param {Event} e\n */\n var doDuplicate = function(e) {\n e.preventDefault();\n\n frameworkid = $(this).attr('data-frameworkid');\n\n // We are chaining ajax requests here.\n var requests = ajax.call([{\n methodname: 'core_competency_duplicate_competency_framework',\n args: {id: frameworkid}\n }, {\n methodname: 'tool_lp_data_for_competency_frameworks_manage_page',\n args: {\n pagecontext: {\n contextid: pagecontextid\n }\n }\n }]);\n requests[1].done(reloadList).fail(notification.exception);\n };\n /**\n * Delete a framework and reload the page.\n */\n var doDelete = function() {\n\n // We are chaining ajax requests here.\n var requests = ajax.call([{\n methodname: 'core_competency_delete_competency_framework',\n args: {id: frameworkid}\n }, {\n methodname: 'tool_lp_data_for_competency_frameworks_manage_page',\n args: {\n pagecontext: {\n contextid: pagecontextid\n }\n }\n }]);\n requests[0].done(function(success) {\n if (success === false) {\n var req = ajax.call([{\n methodname: 'core_competency_read_competency_framework',\n args: {id: frameworkid}\n }]);\n req[0].done(function(framework) {\n str.get_strings([\n {key: 'frameworkcannotbedeleted', component: 'tool_lp', param: framework.shortname},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.alert(\n null,\n strings[0]\n );\n }).fail(notification.exception);\n });\n }\n }).fail(notification.exception);\n requests[1].done(reloadList).fail(notification.exception);\n };\n\n /**\n * Handler for \"Delete competency framework\" actions.\n * @param {Event} e\n */\n var confirmDelete = function(e) {\n e.preventDefault();\n\n var id = $(this).attr('data-frameworkid');\n frameworkid = id;\n\n var requests = ajax.call([{\n methodname: 'core_competency_read_competency_framework',\n args: {id: frameworkid}\n }]);\n\n requests[0].done(function(framework) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'deletecompetencyframework', component: 'tool_lp', param: framework.shortname},\n {key: 'delete', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Delete competency framework X?\n strings[2], // Delete.\n strings[3], // Cancel.\n doDelete\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n\n return /** @alias module:tool_lp/frameworkactions */ {\n // Public variables and functions.\n\n /**\n * Expose the event handler for delete.\n * @method deleteHandler\n * @param {Event} e\n */\n deleteHandler: confirmDelete,\n\n /**\n * Expose the event handler for duplicate.\n * @method duplicateHandler\n * @param {Event} e\n */\n duplicateHandler: doDuplicate,\n\n /**\n * Initialise the module.\n * @method init\n * @param {Number} contextid The context id of the page.\n */\n init: function(contextid) {\n pagecontextid = contextid;\n }\n };\n});\n"],"file":"frameworkactions.min.js"}
\ No newline at end of file
+{"version":3,"file":"frameworkactions.min.js","sources":["../src/frameworkactions.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 .\n\n/**\n * Competency frameworks actions via ajax.\n *\n * @module tool_lp/frameworkactions\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'], function($, templates, ajax, notification, str) {\n // Private variables and functions.\n\n /** @var {Number} pagecontextid The id of the context */\n var pagecontextid = 0;\n\n /** @var {Number} frameworkid The id of the framework */\n var frameworkid = 0;\n\n /**\n * Callback to replace the dom element with the rendered template.\n *\n * @param {String} newhtml The new html to insert.\n * @param {String} newjs The new js to run.\n */\n var updatePage = function(newhtml, newjs) {\n $('[data-region=\"managecompetencies\"]').replaceWith(newhtml);\n templates.runTemplateJS(newjs);\n };\n\n /**\n * Callback to render the page template again and update the page.\n *\n * @param {Object} context The context for the template.\n */\n var reloadList = function(context) {\n templates.render('tool_lp/manage_competency_frameworks_page', context)\n .done(updatePage)\n .fail(notification.exception);\n };\n\n /**\n * Duplicate a framework and reload the page.\n * @method doDuplicate\n * @param {Event} e\n */\n var doDuplicate = function(e) {\n e.preventDefault();\n\n frameworkid = $(this).attr('data-frameworkid');\n\n // We are chaining ajax requests here.\n var requests = ajax.call([{\n methodname: 'core_competency_duplicate_competency_framework',\n args: {id: frameworkid}\n }, {\n methodname: 'tool_lp_data_for_competency_frameworks_manage_page',\n args: {\n pagecontext: {\n contextid: pagecontextid\n }\n }\n }]);\n requests[1].done(reloadList).fail(notification.exception);\n };\n /**\n * Delete a framework and reload the page.\n */\n var doDelete = function() {\n\n // We are chaining ajax requests here.\n var requests = ajax.call([{\n methodname: 'core_competency_delete_competency_framework',\n args: {id: frameworkid}\n }, {\n methodname: 'tool_lp_data_for_competency_frameworks_manage_page',\n args: {\n pagecontext: {\n contextid: pagecontextid\n }\n }\n }]);\n requests[0].done(function(success) {\n if (success === false) {\n var req = ajax.call([{\n methodname: 'core_competency_read_competency_framework',\n args: {id: frameworkid}\n }]);\n req[0].done(function(framework) {\n str.get_strings([\n {key: 'frameworkcannotbedeleted', component: 'tool_lp', param: framework.shortname},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.alert(\n null,\n strings[0]\n );\n }).fail(notification.exception);\n });\n }\n }).fail(notification.exception);\n requests[1].done(reloadList).fail(notification.exception);\n };\n\n /**\n * Handler for \"Delete competency framework\" actions.\n * @param {Event} e\n */\n var confirmDelete = function(e) {\n e.preventDefault();\n\n var id = $(this).attr('data-frameworkid');\n frameworkid = id;\n\n var requests = ajax.call([{\n methodname: 'core_competency_read_competency_framework',\n args: {id: frameworkid}\n }]);\n\n requests[0].done(function(framework) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'deletecompetencyframework', component: 'tool_lp', param: framework.shortname},\n {key: 'delete', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Delete competency framework X?\n strings[2], // Delete.\n strings[3], // Cancel.\n doDelete\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n\n return /** @alias module:tool_lp/frameworkactions */ {\n // Public variables and functions.\n\n /**\n * Expose the event handler for delete.\n * @method deleteHandler\n * @param {Event} e\n */\n deleteHandler: confirmDelete,\n\n /**\n * Expose the event handler for duplicate.\n * @method duplicateHandler\n * @param {Event} e\n */\n duplicateHandler: doDuplicate,\n\n /**\n * Initialise the module.\n * @method init\n * @param {Number} contextid The context id of the page.\n */\n init: function(contextid) {\n pagecontextid = contextid;\n }\n };\n});\n"],"names":["define","$","templates","ajax","notification","str","pagecontextid","frameworkid","updatePage","newhtml","newjs","replaceWith","runTemplateJS","reloadList","context","render","done","fail","exception","doDelete","requests","call","methodname","args","id","pagecontext","contextid","success","framework","get_strings","key","component","param","shortname","strings","alert","deleteHandler","e","preventDefault","this","attr","confirm","duplicateHandler","init"],"mappings":";;;;;;;AAsBAA,kCAAO,CAAC,SAAU,iBAAkB,YAAa,oBAAqB,aAAa,SAASC,EAAGC,UAAWC,KAAMC,aAAcC,SAItHC,cAAgB,EAGhBC,YAAc,EAQdC,WAAa,SAASC,QAASC,OAC/BT,EAAE,sCAAsCU,YAAYF,SACpDP,UAAUU,cAAcF,QAQxBG,WAAa,SAASC,SACtBZ,UAAUa,OAAO,4CAA6CD,SACzDE,KAAKR,YACLS,KAAKb,aAAac,YA8BvBC,SAAW,eAGPC,SAAWjB,KAAKkB,KAAK,CAAC,CACtBC,WAAY,8CACZC,KAAM,CAACC,GAAIjB,cACZ,CACCe,WAAY,qDACZC,KAAM,CACFE,YAAa,CACTC,UAAWpB,mBAIvBc,SAAS,GAAGJ,MAAK,SAASW,UACN,IAAZA,SACUxB,KAAKkB,KAAK,CAAC,CACjBC,WAAY,4CACZC,KAAM,CAACC,GAAIjB,gBAEX,GAAGS,MAAK,SAASY,WACjBvB,IAAIwB,YAAY,CACZ,CAACC,IAAK,2BAA4BC,UAAW,UAAWC,MAAOJ,UAAUK,WACzE,CAACH,IAAK,SAAUC,UAAW,YAC5Bf,MAAK,SAASkB,SACb9B,aAAa+B,MACT,KACAD,QAAQ,OAEbjB,KAAKb,aAAac,iBAG9BD,KAAKb,aAAac,WACrBE,SAAS,GAAGJ,KAAKH,YAAYI,KAAKb,aAAac,kBAsCE,CAQjDkB,cAvCgB,SAASC,GACzBA,EAAEC,qBAEEd,GAAKvB,EAAEsC,MAAMC,KAAK,oBACtBjC,YAAciB,GAECrB,KAAKkB,KAAK,CAAC,CACtBC,WAAY,4CACZC,KAAM,CAACC,GAAIjB,gBAGN,GAAGS,MAAK,SAASY,WACtBvB,IAAIwB,YAAY,CACZ,CAACC,IAAK,UAAWC,UAAW,UAC5B,CAACD,IAAK,4BAA6BC,UAAW,UAAWC,MAAOJ,UAAUK,WAC1E,CAACH,IAAK,SAAUC,UAAW,UAC3B,CAACD,IAAK,SAAUC,UAAW,YAC5Bf,MAAK,SAASkB,SACb9B,aAAaqC,QACTP,QAAQ,GACRA,QAAQ,GACRA,QAAQ,GACRA,QAAQ,GACRf,aAELF,KAAKb,aAAac,cACtBD,KAAKb,aAAac,YAoBrBwB,iBA5Gc,SAASL,GACvBA,EAAEC,iBAEF/B,YAAcN,EAAEsC,MAAMC,KAAK,oBAGZrC,KAAKkB,KAAK,CAAC,CACtBC,WAAY,iDACZC,KAAM,CAACC,GAAIjB,cACZ,CACCe,WAAY,qDACZC,KAAM,CACFE,YAAa,CACTC,UAAWpB,mBAId,GAAGU,KAAKH,YAAYI,KAAKb,aAAac,YAkG/CyB,KAAM,SAASjB,WACXpB,cAAgBoB"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/frameworks_datasource.min.js b/admin/tool/lp/amd/build/frameworks_datasource.min.js
index 7e4abb6a966..e0ad0ad1808 100644
--- a/admin/tool/lp/amd/build/frameworks_datasource.min.js
+++ b/admin/tool/lp/amd/build/frameworks_datasource.min.js
@@ -1,2 +1,12 @@
-define ("tool_lp/frameworks_datasource",["jquery","core/ajax","core/notification"],function(a,b,c){return{list:function list(c,d){var e={context:{contextid:c}};a.extend(e,"undefined"==typeof d?{}:d);return b.call([{methodname:"core_competency_list_competency_frameworks",args:e}])[0]},processResults:function processResults(b,c){var d=[];a.each(c,function(a,b){d.push({value:b.id,label:b.shortname+" "+b.idnumber})});return d},transport:function transport(b,d,e){var f=a(b),g=f.data("contextid"),h=f.data("onlyvisible");if(!g){throw new Error("The attribute data-contextid is required on "+b)}this.list(g,{query:d,onlyvisible:h}).then(e).catch(c.exception)}}});
-//# sourceMappingURL=frameworks_datasource.min.js.map
+/**
+ * Frameworks datasource.
+ *
+ * This module is compatible with core/form-autocomplete.
+ *
+ * @module tool_lp/frameworks_datasource
+ * @copyright 2016 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/frameworks_datasource",["jquery","core/ajax","core/notification"],(function($,Ajax,Notification){return{list:function(contextId,options){var args={context:{contextid:contextId}};return $.extend(args,void 0===options?{}:options),Ajax.call([{methodname:"core_competency_list_competency_frameworks",args:args}])[0]},processResults:function(selector,results){var options=[];return $.each(results,(function(index,data){options.push({value:data.id,label:data.shortname+" "+data.idnumber})})),options},transport:function(selector,query,callback){var el=$(selector),contextId=el.data("contextid"),onlyVisible=el.data("onlyvisible");if(!contextId)throw new Error("The attribute data-contextid is required on "+selector);this.list(contextId,{query:query,onlyvisible:onlyVisible}).then(callback).catch(Notification.exception)}}}));
+
+//# sourceMappingURL=frameworks_datasource.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/frameworks_datasource.min.js.map b/admin/tool/lp/amd/build/frameworks_datasource.min.js.map
index 1cfb8eecc1b..26a6873f93f 100644
--- a/admin/tool/lp/amd/build/frameworks_datasource.min.js.map
+++ b/admin/tool/lp/amd/build/frameworks_datasource.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/frameworks_datasource.js"],"names":["define","$","Ajax","Notification","list","contextId","options","args","context","contextid","extend","call","methodname","processResults","selector","results","each","index","data","push","value","id","label","shortname","idnumber","transport","query","callback","el","onlyVisible","Error","onlyvisible","then","catch","exception"],"mappings":"AAyBAA,OAAM,iCAAC,CAAC,QAAD,CAAW,WAAX,CAAwB,mBAAxB,CAAD,CAA+C,SAASC,CAAT,CAAYC,CAAZ,CAAkBC,CAAlB,CAAgC,CAEjF,MAAiE,CAS7DC,IAAI,CAAE,cAASC,CAAT,CAAoBC,CAApB,CAA6B,CAC/B,GAAIC,CAAAA,CAAI,CAAG,CACHC,OAAO,CAAE,CACLC,SAAS,CAAEJ,CADN,CADN,CAAX,CAMAJ,CAAC,CAACS,MAAF,CAASH,CAAT,CAAkC,WAAnB,QAAOD,CAAAA,CAAP,CAAiC,EAAjC,CAAsCA,CAArD,EACA,MAAOJ,CAAAA,CAAI,CAACS,IAAL,CAAU,CAAC,CACdC,UAAU,CAAE,4CADE,CAEdL,IAAI,CAAEA,CAFQ,CAAD,CAAV,EAGH,CAHG,CAIV,CArB4D,CA8B7DM,cAAc,CAAE,wBAASC,CAAT,CAAmBC,CAAnB,CAA4B,CACxC,GAAIT,CAAAA,CAAO,CAAG,EAAd,CACAL,CAAC,CAACe,IAAF,CAAOD,CAAP,CAAgB,SAASE,CAAT,CAAgBC,CAAhB,CAAsB,CAClCZ,CAAO,CAACa,IAAR,CAAa,CACTC,KAAK,CAAEF,CAAI,CAACG,EADH,CAETC,KAAK,CAAEJ,CAAI,CAACK,SAAL,CAAiB,GAAjB,CAAuBL,CAAI,CAACM,QAF1B,CAAb,CAIH,CALD,EAMA,MAAOlB,CAAAA,CACV,CAvC4D,CAiD7DmB,SAAS,CAAE,mBAASX,CAAT,CAAmBY,CAAnB,CAA0BC,CAA1B,CAAoC,CAC3C,GAAIC,CAAAA,CAAE,CAAG3B,CAAC,CAACa,CAAD,CAAV,CACIT,CAAS,CAAGuB,CAAE,CAACV,IAAH,CAAQ,WAAR,CADhB,CAEIW,CAAW,CAAGD,CAAE,CAACV,IAAH,CAAQ,aAAR,CAFlB,CAIA,GAAI,CAACb,CAAL,CAAgB,CACZ,KAAM,IAAIyB,CAAAA,KAAJ,CAAU,+CAAiDhB,CAA3D,CACT,CACD,KAAKV,IAAL,CAAUC,CAAV,CAAqB,CACjBqB,KAAK,CAAEA,CADU,CAEjBK,WAAW,CAAEF,CAFI,CAArB,EAGGG,IAHH,CAGQL,CAHR,EAGkBM,KAHlB,CAGwB9B,CAAY,CAAC+B,SAHrC,CAIH,CA7D4D,CAgEpE,CAlEK,CAAN","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 .\n\n/**\n * Frameworks datasource.\n *\n * This module is compatible with core/form-autocomplete.\n *\n * @module tool_lp/frameworks_datasource\n * @copyright 2016 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notification) {\n\n return /** @alias module:tool_lpmigrate/frameworks_datasource */ {\n\n /**\n * List frameworks.\n *\n * @param {Number} contextId The context ID.\n * @param {Object} options Additional parameters to pass to the external function.\n * @return {Promise}\n */\n list: function(contextId, options) {\n var args = {\n context: {\n contextid: contextId\n }\n };\n\n $.extend(args, typeof options === 'undefined' ? {} : options);\n return Ajax.call([{\n methodname: 'core_competency_list_competency_frameworks',\n args: args\n }])[0];\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.\n * @return {Array} New array of results.\n */\n processResults: function(selector, results) {\n var options = [];\n $.each(results, function(index, data) {\n options.push({\n value: data.id,\n label: data.shortname + ' ' + data.idnumber\n });\n });\n return options;\n },\n\n /**\n * Source of data for Ajax element.\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 */\n /* eslint-disable promise/no-callback-in-promise */\n transport: function(selector, query, callback) {\n var el = $(selector),\n contextId = el.data('contextid'),\n onlyVisible = el.data('onlyvisible');\n\n if (!contextId) {\n throw new Error('The attribute data-contextid is required on ' + selector);\n }\n this.list(contextId, {\n query: query,\n onlyvisible: onlyVisible,\n }).then(callback).catch(Notification.exception);\n }\n };\n\n});\n"],"file":"frameworks_datasource.min.js"}
\ No newline at end of file
+{"version":3,"file":"frameworks_datasource.min.js","sources":["../src/frameworks_datasource.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 .\n\n/**\n * Frameworks datasource.\n *\n * This module is compatible with core/form-autocomplete.\n *\n * @module tool_lp/frameworks_datasource\n * @copyright 2016 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notification) {\n\n return /** @alias module:tool_lpmigrate/frameworks_datasource */ {\n\n /**\n * List frameworks.\n *\n * @param {Number} contextId The context ID.\n * @param {Object} options Additional parameters to pass to the external function.\n * @return {Promise}\n */\n list: function(contextId, options) {\n var args = {\n context: {\n contextid: contextId\n }\n };\n\n $.extend(args, typeof options === 'undefined' ? {} : options);\n return Ajax.call([{\n methodname: 'core_competency_list_competency_frameworks',\n args: args\n }])[0];\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.\n * @return {Array} New array of results.\n */\n processResults: function(selector, results) {\n var options = [];\n $.each(results, function(index, data) {\n options.push({\n value: data.id,\n label: data.shortname + ' ' + data.idnumber\n });\n });\n return options;\n },\n\n /**\n * Source of data for Ajax element.\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 */\n /* eslint-disable promise/no-callback-in-promise */\n transport: function(selector, query, callback) {\n var el = $(selector),\n contextId = el.data('contextid'),\n onlyVisible = el.data('onlyvisible');\n\n if (!contextId) {\n throw new Error('The attribute data-contextid is required on ' + selector);\n }\n this.list(contextId, {\n query: query,\n onlyvisible: onlyVisible,\n }).then(callback).catch(Notification.exception);\n }\n };\n\n});\n"],"names":["define","$","Ajax","Notification","list","contextId","options","args","context","contextid","extend","call","methodname","processResults","selector","results","each","index","data","push","value","id","label","shortname","idnumber","transport","query","callback","el","onlyVisible","Error","onlyvisible","then","catch","exception"],"mappings":";;;;;;;;;AAyBAA,uCAAO,CAAC,SAAU,YAAa,sBAAsB,SAASC,EAAGC,KAAMC,oBAEF,CAS7DC,KAAM,SAASC,UAAWC,aAClBC,KAAO,CACHC,QAAS,CACLC,UAAWJ,mBAIvBJ,EAAES,OAAOH,UAAyB,IAAZD,QAA0B,GAAKA,SAC9CJ,KAAKS,KAAK,CAAC,CACdC,WAAY,6CACZL,KAAMA,QACN,IAURM,eAAgB,SAASC,SAAUC,aAC3BT,QAAU,UACdL,EAAEe,KAAKD,SAAS,SAASE,MAAOC,MAC5BZ,QAAQa,KAAK,CACTC,MAAOF,KAAKG,GACZC,MAAOJ,KAAKK,UAAY,IAAML,KAAKM,cAGpClB,SAWXmB,UAAW,SAASX,SAAUY,MAAOC,cAC7BC,GAAK3B,EAAEa,UACPT,UAAYuB,GAAGV,KAAK,aACpBW,YAAcD,GAAGV,KAAK,mBAErBb,gBACK,IAAIyB,MAAM,+CAAiDhB,eAEhEV,KAAKC,UAAW,CACjBqB,MAAOA,MACPK,YAAaF,cACdG,KAAKL,UAAUM,MAAM9B,aAAa+B"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/grade_dialogue.min.js b/admin/tool/lp/amd/build/grade_dialogue.min.js
index 9637bc9003a..a9c9c8d053b 100644
--- a/admin/tool/lp/amd/build/grade_dialogue.min.js
+++ b/admin/tool/lp/amd/build/grade_dialogue.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/grade_dialogue",["jquery","core/notification","core/templates","tool_lp/dialogue","tool_lp/event_base","core/str"],function(a,b,c,d,e,f){var g=function(a){e.prototype.constructor.apply(this,[]);this._ratingOptions=a};g.prototype=Object.create(e.prototype);g.prototype._popup=null;g.prototype._ratingOptions=null;g.prototype._afterRender=function(){var b=this._find("[data-action=\"rate\"]"),c=this._find("[name=\"rating\"]"),d=this._find("[name=\"comment\"]");this._find("[data-action=\"cancel\"]").click(function(a){a.preventDefault();this._trigger("cancelled");this.close()}.bind(this));c.change(function(){var c=a(this);if(!c.val()){b.prop("disabled",!0)}else{b.prop("disabled",!1)}}).change();b.click(function(a){a.preventDefault();var b=c.val();if(!b){return}this._trigger("rated",{rating:b,note:d.val()});this.close()}.bind(this))};g.prototype.close=function(){this._popup.close();this._popup=null};g.prototype.display=function(){M.util.js_pending("tool_lp/grade_dialogue:display");return a.when(f.get_string("rate","tool_lp"),this._render()).then(function(a,b){this._popup=new d(a,b[0],function(){this._afterRender();M.util.js_complete("tool_lp/grade_dialogue:display")}.bind(this));return this._popup}.bind(this)).catch(b.exception)};g.prototype._find=function(b){return a(this._popup.getContent()).find(b)};g.prototype._render=function(){var a={cangrade:this._canGrade,ratings:this._ratingOptions};return c.render("tool_lp/competency_grader",a)};return g});
-//# sourceMappingURL=grade_dialogue.min.js.map
+/**
+ * Grade dialogue.
+ *
+ * @module tool_lp/grade_dialogue
+ * @copyright 2016 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/grade_dialogue",["jquery","core/notification","core/templates","tool_lp/dialogue","tool_lp/event_base","core/str"],(function($,Notification,Templates,Dialogue,EventBase,Str){var Grade=function(ratingOptions){EventBase.prototype.constructor.apply(this,[]),this._ratingOptions=ratingOptions};return(Grade.prototype=Object.create(EventBase.prototype))._popup=null,Grade.prototype._ratingOptions=null,Grade.prototype._afterRender=function(){var btnRate=this._find('[data-action="rate"]'),lstRating=this._find('[name="rating"]'),txtComment=this._find('[name="comment"]');this._find('[data-action="cancel"]').click(function(e){e.preventDefault(),this._trigger("cancelled"),this.close()}.bind(this)),lstRating.change((function(){$(this).val()?btnRate.prop("disabled",!1):btnRate.prop("disabled",!0)})).change(),btnRate.click(function(e){e.preventDefault();var val=lstRating.val();val&&(this._trigger("rated",{rating:val,note:txtComment.val()}),this.close())}.bind(this))},Grade.prototype.close=function(){this._popup.close(),this._popup=null},Grade.prototype.display=function(){return M.util.js_pending("tool_lp/grade_dialogue:display"),$.when(Str.get_string("rate","tool_lp"),this._render()).then(function(title,templateResult){return this._popup=new Dialogue(title,templateResult[0],function(){this._afterRender(),M.util.js_complete("tool_lp/grade_dialogue:display")}.bind(this)),this._popup}.bind(this)).catch(Notification.exception)},Grade.prototype._find=function(selector){return $(this._popup.getContent()).find(selector)},Grade.prototype._render=function(){var context={cangrade:this._canGrade,ratings:this._ratingOptions};return Templates.render("tool_lp/competency_grader",context)},Grade}));
+
+//# sourceMappingURL=grade_dialogue.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/grade_dialogue.min.js.map b/admin/tool/lp/amd/build/grade_dialogue.min.js.map
index 333e741fe4e..52764f4e8fe 100644
--- a/admin/tool/lp/amd/build/grade_dialogue.min.js.map
+++ b/admin/tool/lp/amd/build/grade_dialogue.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/grade_dialogue.js"],"names":["define","$","Notification","Templates","Dialogue","EventBase","Str","Grade","ratingOptions","prototype","constructor","apply","_ratingOptions","Object","create","_popup","_afterRender","btnRate","_find","lstRating","txtComment","click","e","preventDefault","_trigger","close","bind","change","node","val","prop","display","M","util","js_pending","when","get_string","_render","then","title","templateResult","js_complete","catch","exception","selector","getContent","find","context","cangrade","_canGrade","ratings","render"],"mappings":"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","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 .\n\n/**\n * Grade dialogue.\n *\n * @module tool_lp/grade_dialogue\n * @copyright 2016 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/templates',\n 'tool_lp/dialogue',\n 'tool_lp/event_base',\n 'core/str'],\n function($, Notification, Templates, Dialogue, EventBase, Str) {\n\n /**\n * Grade dialogue class.\n *\n * @class tool_lp/grade_dialogue\n * @param {Array} ratingOptions\n */\n var Grade = function(ratingOptions) {\n EventBase.prototype.constructor.apply(this, []);\n this._ratingOptions = ratingOptions;\n };\n Grade.prototype = Object.create(EventBase.prototype);\n\n /** @property {Dialogue} The dialogue. */\n Grade.prototype._popup = null;\n /** @property {Array} Array of objects containing, 'value', 'name' and optionally 'selected'. */\n Grade.prototype._ratingOptions = null;\n\n /**\n * After render hook.\n *\n * @method _afterRender\n * @protected\n */\n Grade.prototype._afterRender = function() {\n var btnRate = this._find('[data-action=\"rate\"]'),\n lstRating = this._find('[name=\"rating\"]'),\n txtComment = this._find('[name=\"comment\"]');\n\n this._find('[data-action=\"cancel\"]').click(function(e) {\n e.preventDefault();\n this._trigger('cancelled');\n this.close();\n }.bind(this));\n\n lstRating.change(function() {\n var node = $(this);\n if (!node.val()) {\n btnRate.prop('disabled', true);\n } else {\n btnRate.prop('disabled', false);\n }\n }).change();\n\n btnRate.click(function(e) {\n e.preventDefault();\n var val = lstRating.val();\n if (!val) {\n return;\n }\n this._trigger('rated', {\n 'rating': val,\n 'note': txtComment.val()\n });\n this.close();\n }.bind(this));\n };\n\n /**\n * Close the dialogue.\n *\n * @method close\n */\n Grade.prototype.close = function() {\n this._popup.close();\n this._popup = null;\n };\n\n /**\n * Opens the picker.\n *\n * @method display\n * @return {Promise}\n */\n Grade.prototype.display = function() {\n M.util.js_pending('tool_lp/grade_dialogue:display');\n return $.when(\n Str.get_string('rate', 'tool_lp'),\n this._render()\n )\n .then(function(title, templateResult) {\n this._popup = new Dialogue(\n title,\n templateResult[0],\n function() {\n this._afterRender();\n M.util.js_complete('tool_lp/grade_dialogue:display');\n }.bind(this)\n );\n\n return this._popup;\n }.bind(this))\n .catch(Notification.exception);\n };\n\n /**\n * Find a node in the dialogue.\n *\n * @param {String} selector\n * @method _find\n * @returns {node} The node\n * @protected\n */\n Grade.prototype._find = function(selector) {\n return $(this._popup.getContent()).find(selector);\n };\n\n /**\n * Render the dialogue.\n *\n * @method _render\n * @protected\n * @return {Promise}\n */\n Grade.prototype._render = function() {\n var context = {\n cangrade: this._canGrade,\n ratings: this._ratingOptions\n };\n return Templates.render('tool_lp/competency_grader', context);\n };\n\n return Grade;\n});\n"],"file":"grade_dialogue.min.js"}
\ No newline at end of file
+{"version":3,"file":"grade_dialogue.min.js","sources":["../src/grade_dialogue.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 .\n\n/**\n * Grade dialogue.\n *\n * @module tool_lp/grade_dialogue\n * @copyright 2016 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/templates',\n 'tool_lp/dialogue',\n 'tool_lp/event_base',\n 'core/str'],\n function($, Notification, Templates, Dialogue, EventBase, Str) {\n\n /**\n * Grade dialogue class.\n *\n * @class tool_lp/grade_dialogue\n * @param {Array} ratingOptions\n */\n var Grade = function(ratingOptions) {\n EventBase.prototype.constructor.apply(this, []);\n this._ratingOptions = ratingOptions;\n };\n Grade.prototype = Object.create(EventBase.prototype);\n\n /** @property {Dialogue} The dialogue. */\n Grade.prototype._popup = null;\n /** @property {Array} Array of objects containing, 'value', 'name' and optionally 'selected'. */\n Grade.prototype._ratingOptions = null;\n\n /**\n * After render hook.\n *\n * @method _afterRender\n * @protected\n */\n Grade.prototype._afterRender = function() {\n var btnRate = this._find('[data-action=\"rate\"]'),\n lstRating = this._find('[name=\"rating\"]'),\n txtComment = this._find('[name=\"comment\"]');\n\n this._find('[data-action=\"cancel\"]').click(function(e) {\n e.preventDefault();\n this._trigger('cancelled');\n this.close();\n }.bind(this));\n\n lstRating.change(function() {\n var node = $(this);\n if (!node.val()) {\n btnRate.prop('disabled', true);\n } else {\n btnRate.prop('disabled', false);\n }\n }).change();\n\n btnRate.click(function(e) {\n e.preventDefault();\n var val = lstRating.val();\n if (!val) {\n return;\n }\n this._trigger('rated', {\n 'rating': val,\n 'note': txtComment.val()\n });\n this.close();\n }.bind(this));\n };\n\n /**\n * Close the dialogue.\n *\n * @method close\n */\n Grade.prototype.close = function() {\n this._popup.close();\n this._popup = null;\n };\n\n /**\n * Opens the picker.\n *\n * @method display\n * @return {Promise}\n */\n Grade.prototype.display = function() {\n M.util.js_pending('tool_lp/grade_dialogue:display');\n return $.when(\n Str.get_string('rate', 'tool_lp'),\n this._render()\n )\n .then(function(title, templateResult) {\n this._popup = new Dialogue(\n title,\n templateResult[0],\n function() {\n this._afterRender();\n M.util.js_complete('tool_lp/grade_dialogue:display');\n }.bind(this)\n );\n\n return this._popup;\n }.bind(this))\n .catch(Notification.exception);\n };\n\n /**\n * Find a node in the dialogue.\n *\n * @param {String} selector\n * @method _find\n * @returns {node} The node\n * @protected\n */\n Grade.prototype._find = function(selector) {\n return $(this._popup.getContent()).find(selector);\n };\n\n /**\n * Render the dialogue.\n *\n * @method _render\n * @protected\n * @return {Promise}\n */\n Grade.prototype._render = function() {\n var context = {\n cangrade: this._canGrade,\n ratings: this._ratingOptions\n };\n return Templates.render('tool_lp/competency_grader', context);\n };\n\n return Grade;\n});\n"],"names":["define","$","Notification","Templates","Dialogue","EventBase","Str","Grade","ratingOptions","prototype","constructor","apply","this","_ratingOptions","Object","create","_popup","_afterRender","btnRate","_find","lstRating","txtComment","click","e","preventDefault","_trigger","close","bind","change","val","prop","display","M","util","js_pending","when","get_string","_render","then","title","templateResult","js_complete","catch","exception","selector","getContent","find","context","cangrade","_canGrade","ratings","render"],"mappings":";;;;;;;AAuBAA,gCAAO,CAAC,SACA,oBACA,iBACA,mBACA,qBACA,aACA,SAASC,EAAGC,aAAcC,UAAWC,SAAUC,UAAWC,SAQ1DC,MAAQ,SAASC,eACjBH,UAAUI,UAAUC,YAAYC,MAAMC,KAAM,SACvCC,eAAiBL,sBAE1BD,MAAME,UAAYK,OAAOC,OAAOV,UAAUI,YAG1BO,OAAS,KAEzBT,MAAME,UAAUI,eAAiB,KAQjCN,MAAME,UAAUQ,aAAe,eACvBC,QAAUN,KAAKO,MAAM,wBACrBC,UAAYR,KAAKO,MAAM,mBACvBE,WAAaT,KAAKO,MAAM,yBAEvBA,MAAM,0BAA0BG,MAAM,SAASC,GAChDA,EAAEC,sBACGC,SAAS,kBACTC,SACPC,KAAKf,OAEPQ,UAAUQ,QAAO,WACF3B,EAAEW,MACHiB,MAGNX,QAAQY,KAAK,YAAY,GAFzBZ,QAAQY,KAAK,YAAY,MAI9BF,SAEHV,QAAQI,MAAM,SAASC,GACnBA,EAAEC,qBACEK,IAAMT,UAAUS,MACfA,WAGAJ,SAAS,QAAS,QACTI,SACFR,WAAWQ,aAElBH,UACPC,KAAKf,QAQXL,MAAME,UAAUiB,MAAQ,gBACfV,OAAOU,aACPV,OAAS,MASlBT,MAAME,UAAUsB,QAAU,kBACtBC,EAAEC,KAAKC,WAAW,kCACXjC,EAAEkC,KACL7B,IAAI8B,WAAW,OAAQ,WACvBxB,KAAKyB,WAERC,KAAK,SAASC,MAAOC,4BACbxB,OAAS,IAAIZ,SACdmC,MACAC,eAAe,GACf,gBACSvB,eACLe,EAAEC,KAAKQ,YAAY,mCACrBd,KAAKf,OAGJA,KAAKI,QACdW,KAAKf,OACN8B,MAAMxC,aAAayC,YAWxBpC,MAAME,UAAUU,MAAQ,SAASyB,iBACtB3C,EAAEW,KAAKI,OAAO6B,cAAcC,KAAKF,WAU5CrC,MAAME,UAAU4B,QAAU,eAClBU,QAAU,CACVC,SAAUpC,KAAKqC,UACfC,QAAStC,KAAKC,uBAEXV,UAAUgD,OAAO,4BAA6BJ,UAGlDxC"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/grade_user_competency_inline.min.js b/admin/tool/lp/amd/build/grade_user_competency_inline.min.js
index 45c08008cf2..8f267cb2658 100644
--- a/admin/tool/lp/amd/build/grade_user_competency_inline.min.js
+++ b/admin/tool/lp/amd/build/grade_user_competency_inline.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/grade_user_competency_inline",["jquery","core/notification","core/ajax","core/log","tool_lp/grade_dialogue","tool_lp/event_base","tool_lp/scalevalues"],function(a,b,c,d,e,f,g){var h=function(b,c,d,e,g,h,i){f.prototype.constructor.apply(this,[]);var j=a(b);if(!j.length){throw new Error("Could not find the trigger")}this._scaleId=c;this._competencyId=d;this._userId=e;this._planId=g;this._courseId=h;this._chooseStr=i;this._setUp();j.click(function(a){a.preventDefault();this._dialogue.display()}.bind(this));if(this._planId){this._methodName="core_competency_grade_competency_in_plan";this._args={competencyid:this._competencyId,planid:this._planId}}else if(this._courseId){this._methodName="core_competency_grade_competency_in_course";this._args={competencyid:this._competencyId,courseid:this._courseId,userid:this._userId}}else{this._methodName="core_competency_grade_competency";this._args={userid:this._userId,competencyid:this._competencyId}}};h.prototype=Object.create(f.prototype);h.prototype._setUp=function(){var a=[],d=this;M.util.js_pending("tool_lp/grade_user_competency_inline:_setUp");var f=g.get_values(d._scaleId);f.then(function(b){a.push({value:"",name:d._chooseStr});for(var c=0,e;c.\n\n/**\n * Module to enable inline editing of a comptency grade.\n *\n * @module tool_lp/grade_user_competency_inline\n * @copyright 2015 Damyon Wiese\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/log',\n 'tool_lp/grade_dialogue',\n 'tool_lp/event_base',\n 'tool_lp/scalevalues',\n ], function($, notification, ajax, log, GradeDialogue, EventBase, ScaleValues) {\n\n /**\n * InlineEditor\n *\n * @class tool_lp/grade_user_competency_inline\n * @param {String} selector The selector to trigger the grading.\n * @param {Number} scaleId The id of the scale for this competency.\n * @param {Number} competencyId The id of the competency.\n * @param {Number} userId The id of the user.\n * @param {Number} planId The id of the plan.\n * @param {Number} courseId The id of the course.\n * @param {String} chooseStr Language string for choose a rating.\n */\n var InlineEditor = function(selector, scaleId, competencyId, userId, planId, courseId, chooseStr) {\n EventBase.prototype.constructor.apply(this, []);\n\n var trigger = $(selector);\n if (!trigger.length) {\n throw new Error('Could not find the trigger');\n }\n\n this._scaleId = scaleId;\n this._competencyId = competencyId;\n this._userId = userId;\n this._planId = planId;\n this._courseId = courseId;\n this._chooseStr = chooseStr;\n this._setUp();\n\n trigger.click(function(e) {\n e.preventDefault();\n this._dialogue.display();\n }.bind(this));\n\n if (this._planId) {\n this._methodName = 'core_competency_grade_competency_in_plan';\n this._args = {\n competencyid: this._competencyId,\n planid: this._planId\n };\n } else if (this._courseId) {\n this._methodName = 'core_competency_grade_competency_in_course';\n this._args = {\n competencyid: this._competencyId,\n courseid: this._courseId,\n userid: this._userId\n };\n } else {\n this._methodName = 'core_competency_grade_competency';\n this._args = {\n userid: this._userId,\n competencyid: this._competencyId\n };\n }\n };\n InlineEditor.prototype = Object.create(EventBase.prototype);\n\n /**\n * Setup.\n *\n * @method _setUp\n */\n InlineEditor.prototype._setUp = function() {\n var options = [],\n self = this;\n\n M.util.js_pending('tool_lp/grade_user_competency_inline:_setUp');\n var promise = ScaleValues.get_values(self._scaleId);\n promise.then(function(scalevalues) {\n options.push({\n value: '',\n name: self._chooseStr\n });\n\n for (var i = 0; i < scalevalues.length; i++) {\n var optionConfig = scalevalues[i];\n options.push({\n value: optionConfig.id,\n name: optionConfig.name\n });\n }\n\n return options;\n })\n .then(function(options) {\n return new GradeDialogue(options);\n })\n .then(function(dialogue) {\n dialogue.on('rated', function(e, data) {\n var args = self._args;\n args.grade = data.rating;\n args.note = data.note;\n ajax.call([{\n methodname: self._methodName,\n args: args,\n done: function(evidence) {\n self._trigger('competencyupdated', {args: args, evidence: evidence});\n },\n fail: notification.exception\n }]);\n });\n\n return dialogue;\n })\n .then(function(dialogue) {\n self._dialogue = dialogue;\n\n M.util.js_complete('tool_lp/grade_user_competency_inline:_setUp');\n return;\n })\n .fail(notification.exception);\n };\n\n /** @property {Number} The scale id for this competency. */\n InlineEditor.prototype._scaleId = null;\n /** @property {Number} The id of the competency. */\n InlineEditor.prototype._competencyId = null;\n /** @property {Number} The id of the user. */\n InlineEditor.prototype._userId = null;\n /** @property {Number} The id of the plan. */\n InlineEditor.prototype._planId = null;\n /** @property {Number} The id of the course. */\n InlineEditor.prototype._courseId = null;\n /** @property {String} The text for Choose rating. */\n InlineEditor.prototype._chooseStr = null;\n /** @property {GradeDialogue} The grading dialogue. */\n InlineEditor.prototype._dialogue = null;\n\n return InlineEditor;\n});\n"],"file":"grade_user_competency_inline.min.js"}
\ No newline at end of file
+{"version":3,"file":"grade_user_competency_inline.min.js","sources":["../src/grade_user_competency_inline.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 .\n\n/**\n * Module to enable inline editing of a comptency grade.\n *\n * @module tool_lp/grade_user_competency_inline\n * @copyright 2015 Damyon Wiese\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/log',\n 'tool_lp/grade_dialogue',\n 'tool_lp/event_base',\n 'tool_lp/scalevalues',\n ], function($, notification, ajax, log, GradeDialogue, EventBase, ScaleValues) {\n\n /**\n * InlineEditor\n *\n * @class tool_lp/grade_user_competency_inline\n * @param {String} selector The selector to trigger the grading.\n * @param {Number} scaleId The id of the scale for this competency.\n * @param {Number} competencyId The id of the competency.\n * @param {Number} userId The id of the user.\n * @param {Number} planId The id of the plan.\n * @param {Number} courseId The id of the course.\n * @param {String} chooseStr Language string for choose a rating.\n */\n var InlineEditor = function(selector, scaleId, competencyId, userId, planId, courseId, chooseStr) {\n EventBase.prototype.constructor.apply(this, []);\n\n var trigger = $(selector);\n if (!trigger.length) {\n throw new Error('Could not find the trigger');\n }\n\n this._scaleId = scaleId;\n this._competencyId = competencyId;\n this._userId = userId;\n this._planId = planId;\n this._courseId = courseId;\n this._chooseStr = chooseStr;\n this._setUp();\n\n trigger.click(function(e) {\n e.preventDefault();\n this._dialogue.display();\n }.bind(this));\n\n if (this._planId) {\n this._methodName = 'core_competency_grade_competency_in_plan';\n this._args = {\n competencyid: this._competencyId,\n planid: this._planId\n };\n } else if (this._courseId) {\n this._methodName = 'core_competency_grade_competency_in_course';\n this._args = {\n competencyid: this._competencyId,\n courseid: this._courseId,\n userid: this._userId\n };\n } else {\n this._methodName = 'core_competency_grade_competency';\n this._args = {\n userid: this._userId,\n competencyid: this._competencyId\n };\n }\n };\n InlineEditor.prototype = Object.create(EventBase.prototype);\n\n /**\n * Setup.\n *\n * @method _setUp\n */\n InlineEditor.prototype._setUp = function() {\n var options = [],\n self = this;\n\n M.util.js_pending('tool_lp/grade_user_competency_inline:_setUp');\n var promise = ScaleValues.get_values(self._scaleId);\n promise.then(function(scalevalues) {\n options.push({\n value: '',\n name: self._chooseStr\n });\n\n for (var i = 0; i < scalevalues.length; i++) {\n var optionConfig = scalevalues[i];\n options.push({\n value: optionConfig.id,\n name: optionConfig.name\n });\n }\n\n return options;\n })\n .then(function(options) {\n return new GradeDialogue(options);\n })\n .then(function(dialogue) {\n dialogue.on('rated', function(e, data) {\n var args = self._args;\n args.grade = data.rating;\n args.note = data.note;\n ajax.call([{\n methodname: self._methodName,\n args: args,\n done: function(evidence) {\n self._trigger('competencyupdated', {args: args, evidence: evidence});\n },\n fail: notification.exception\n }]);\n });\n\n return dialogue;\n })\n .then(function(dialogue) {\n self._dialogue = dialogue;\n\n M.util.js_complete('tool_lp/grade_user_competency_inline:_setUp');\n return;\n })\n .fail(notification.exception);\n };\n\n /** @property {Number} The scale id for this competency. */\n InlineEditor.prototype._scaleId = null;\n /** @property {Number} The id of the competency. */\n InlineEditor.prototype._competencyId = null;\n /** @property {Number} The id of the user. */\n InlineEditor.prototype._userId = null;\n /** @property {Number} The id of the plan. */\n InlineEditor.prototype._planId = null;\n /** @property {Number} The id of the course. */\n InlineEditor.prototype._courseId = null;\n /** @property {String} The text for Choose rating. */\n InlineEditor.prototype._chooseStr = null;\n /** @property {GradeDialogue} The grading dialogue. */\n InlineEditor.prototype._dialogue = null;\n\n return InlineEditor;\n});\n"],"names":["define","$","notification","ajax","log","GradeDialogue","EventBase","ScaleValues","InlineEditor","selector","scaleId","competencyId","userId","planId","courseId","chooseStr","prototype","constructor","apply","this","trigger","length","Error","_scaleId","_competencyId","_userId","_planId","_courseId","_chooseStr","_setUp","click","e","preventDefault","_dialogue","display","bind","_methodName","_args","competencyid","planid","courseid","userid","Object","create","options","self","M","util","js_pending","get_values","then","scalevalues","push","value","name","i","optionConfig","id","dialogue","on","data","args","grade","rating","note","call","methodname","done","evidence","_trigger","fail","exception","js_complete"],"mappings":";;;;;;;AAuBAA,8CAAO,CAAC,SACA,oBACA,YACA,WACA,yBACA,qBACA,wBACD,SAASC,EAAGC,aAAcC,KAAMC,IAAKC,cAAeC,UAAWC,iBAc9DC,aAAe,SAASC,SAAUC,QAASC,aAAcC,OAAQC,OAAQC,SAAUC,WACnFT,UAAUU,UAAUC,YAAYC,MAAMC,KAAM,QAExCC,QAAUnB,EAAEQ,cACXW,QAAQC,aACH,IAAIC,MAAM,mCAGfC,SAAWb,aACXc,cAAgBb,kBAChBc,QAAUb,YACVc,QAAUb,YACVc,UAAYb,cACZc,WAAab,eACbc,SAELT,QAAQU,MAAM,SAASC,GACnBA,EAAEC,sBACGC,UAAUC,WACjBC,KAAKhB,OAEHA,KAAKO,cACAU,YAAc,gDACdC,MAAQ,CACTC,aAAcnB,KAAKK,cACnBe,OAAQpB,KAAKO,UAEVP,KAAKQ,gBACPS,YAAc,kDACdC,MAAQ,CACTC,aAAcnB,KAAKK,cACnBgB,SAAUrB,KAAKQ,UACfc,OAAQtB,KAAKM,gBAGZW,YAAc,wCACdC,MAAQ,CACTI,OAAQtB,KAAKM,QACba,aAAcnB,KAAKK,wBAI/BhB,aAAaQ,UAAY0B,OAAOC,OAAOrC,UAAUU,YAO1Ba,OAAS,eACxBe,QAAU,GACVC,KAAO1B,KAEX2B,EAAEC,KAAKC,WAAW,+CACJzC,YAAY0C,WAAWJ,KAAKtB,UAClC2B,MAAK,SAASC,aAClBP,QAAQQ,KAAK,CACTC,MAAO,GACPC,KAAMT,KAAKjB,iBAGV,IAAI2B,EAAI,EAAGA,EAAIJ,YAAY9B,OAAQkC,IAAK,KACrCC,aAAeL,YAAYI,GAC/BX,QAAQQ,KAAK,CACTC,MAAOG,aAAaC,GACpBH,KAAME,aAAaF,cAIpBV,WAEVM,MAAK,SAASN,gBACJ,IAAIvC,cAAcuC,YAE5BM,MAAK,SAASQ,iBACXA,SAASC,GAAG,SAAS,SAAS5B,EAAG6B,UACzBC,KAAOhB,KAAKR,MAChBwB,KAAKC,MAAQF,KAAKG,OAClBF,KAAKG,KAAOJ,KAAKI,KACjB7D,KAAK8D,KAAK,CAAC,CACPC,WAAYrB,KAAKT,YACjByB,KAAMA,KACNM,KAAM,SAASC,UACXvB,KAAKwB,SAAS,oBAAqB,CAACR,KAAMA,KAAMO,SAAUA,YAE9DE,KAAMpE,aAAaqE,gBAIpBb,YAEVR,MAAK,SAASQ,UACXb,KAAKZ,UAAYyB,SAEjBZ,EAAEC,KAAKyB,YAAY,kDAGtBF,KAAKpE,aAAaqE,YAIvB/D,aAAaQ,UAAUO,SAAW,KAElCf,aAAaQ,UAAUQ,cAAgB,KAEvChB,aAAaQ,UAAUS,QAAU,KAEjCjB,aAAaQ,UAAUU,QAAU,KAEjClB,aAAaQ,UAAUW,UAAY,KAEnCnB,aAAaQ,UAAUY,WAAa,KAEpCpB,aAAaQ,UAAUiB,UAAY,KAE5BzB"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/menubar.min.js b/admin/tool/lp/amd/build/menubar.min.js
index e71b3c84eb6..4f47be5ceac 100644
--- a/admin/tool/lp/amd/build/menubar.min.js
+++ b/admin/tool/lp/amd/build/menubar.min.js
@@ -1,2 +1,11 @@
-define ("tool_lp/menubar",["jquery"],function(a){var b=!1,c=!1,d=function(){a(".tool-lp-menu .tool-lp-sub-menu").attr("aria-hidden","true");c=!1},e=function(a,b){this.menuRoot=a;this.handlers=b;this.rootMenus=this.menuRoot.children("li");this.subMenus=this.rootMenus.children("ul");this.subMenuItems=this.subMenus.children("li");this.allItems=this.rootMenus.add(this.subMenuItems);this.activeItem=null;this.isChildOpen=!1;this.keys={tab:9,enter:13,esc:27,space:32,left:37,up:38,right:39,down:40};this.addAriaAttributes();this.addEventListeners()};e.prototype.openSubMenu=function(a){this.setOpenDirection();d();a.attr("aria-hidden","false");c=!0};e.prototype.addEventListeners=function(){var f=this;if(!1===b){a(document).click(function(){if(c){d()}});b=!0}this.subMenuItems.mouseenter(function(){a(this).addClass("menu-hover");return!0});this.subMenuItems.mouseout(function(){a(this).removeClass("menu-hover");return!0});this.allItems.click(function(b){return f.handleClick(a(this),b)});this.allItems.keydown(function(b){return f.handleKeyDown(a(this),b)});this.allItems.focus(function(){return f.handleFocus(a(this))});this.allItems.blur(function(){return f.handleBlur(a(this))})};e.prototype.handleClick=function(b,c){c.stopPropagation();var d=b.parent();if(d.is(".tool-lp-menu")){if("true"==b.children("ul").first().attr("aria-hidden")){this.openSubMenu(b.children("ul").first())}else{b.children("ul").first().attr("aria-hidden","true")}}else{this.allItems.removeClass("menu-hover menu-focus");this.activeItem=null;this.menuRoot.find("ul").not(".root-level").attr("aria-hidden","true");var e=b.find("a").first(),f=new a.Event("click");f.target=e;var g=!1;if(this.handlers){a.each(this.handlers,function(c,d){if(g){return}if(0a(window).height()){i=h+d;f.css("margin-top","-"+i+"px")}if(c){if(0>b.left-g){j=g-e;f.css("margin-right","-"+j+"px")}}else{if(b.left+g>a(window).width()){k=g-e;f.css("margin-left","-"+k+"px")}}if(!0){this.menuRoot.addClass("tool-lp-menu-open-left")}else{this.menuRoot.removeClass("tool-lp-menu-open-left")}};e.prototype.handleKeyDown=function(a,b){if(b.altKey||b.ctrlKey){return!0}switch(b.keyCode){case this.keys.tab:{this.menuRoot.find("ul").attr("aria-hidden","true");this.allItems.removeClass("menu-focus");this.activeItem=null;this.isChildOpen=!1;break}case this.keys.esc:{var c=a.parent();if(c.is(".tool-lp-menu")){a.children("ul").first().attr("aria-hidden","true")}else{this.activeItem=c.parent();this.isChildOpen=!1;this.activeItem.focus();c.attr("aria-hidden","true")}b.stopPropagation();return!1}case this.keys.enter:case this.keys.space:{return this.handleClick(a,b)}case this.keys.left:{this.activeItem=this.moveToPrevious(a);this.activeItem.focus();b.stopPropagation();return!1}case this.keys.right:{this.activeItem=this.moveToNext(a);this.activeItem.focus();b.stopPropagation();return!1}case this.keys.up:{this.activeItem=this.moveUp(a);this.activeItem.focus();b.stopPropagation();return!1}case this.keys.down:{this.activeItem=this.moveDown(a);this.activeItem.focus();b.stopPropagation();return!1}}return!0};e.prototype.moveToNext=function(a){var b=a.parent(),c=b.children("li"),d=c.length,e=c.index(a),f=null,g=null;if(b.is(".tool-lp-menu")){if(e
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/menubar",["jquery"],(function($){var documentClickHandlerRegistered=!1,menuActive=!1,closeAllSubMenus=function(){$(".tool-lp-menu .tool-lp-sub-menu").attr("aria-hidden","true"),menuActive=!1},Menubar=function(menuRoot,handlers){this.menuRoot=menuRoot,this.handlers=handlers,this.rootMenus=this.menuRoot.children("li"),this.subMenus=this.rootMenus.children("ul"),this.subMenuItems=this.subMenus.children("li"),this.allItems=this.rootMenus.add(this.subMenuItems),this.activeItem=null,this.isChildOpen=!1,this.keys={tab:9,enter:13,esc:27,space:32,left:37,up:38,right:39,down:40},this.addAriaAttributes(),this.addEventListeners()};return Menubar.prototype.openSubMenu=function(menu){this.setOpenDirection(),closeAllSubMenus(),menu.attr("aria-hidden","false"),menuActive=!0},Menubar.prototype.addEventListeners=function(){var currentThis=this;!1===documentClickHandlerRegistered&&($(document).click((function(){menuActive&&closeAllSubMenus()})),documentClickHandlerRegistered=!0),this.subMenuItems.mouseenter((function(){return $(this).addClass("menu-hover"),!0})),this.subMenuItems.mouseout((function(){return $(this).removeClass("menu-hover"),!0})),this.allItems.click((function(e){return currentThis.handleClick($(this),e)})),this.allItems.keydown((function(e){return currentThis.handleKeyDown($(this),e)})),this.allItems.focus((function(){return currentThis.handleFocus($(this))})),this.allItems.blur((function(){return currentThis.handleBlur($(this))}))},Menubar.prototype.handleClick=function(item,e){if(e.stopPropagation(),item.parent().is(".tool-lp-menu"))"true"==item.children("ul").first().attr("aria-hidden")?this.openSubMenu(item.children("ul").first()):item.children("ul").first().attr("aria-hidden","true");else{this.allItems.removeClass("menu-hover menu-focus"),this.activeItem=null,this.menuRoot.find("ul").not(".root-level").attr("aria-hidden","true");var anchor=item.find("a").first(),clickEvent=new $.Event("click");clickEvent.target=anchor;var eventHandled=!1;this.handlers&&$.each(this.handlers,(function(selector,handler){if(!eventHandled&&item.find(selector).length>0){var callable=$.proxy(handler,anchor);eventHandled=!1===callable(clickEvent)||clickEvent.isDefaultPrevented()}})),eventHandled||"#"===anchor.attr("href")||(window.location.href=anchor.attr("href"))}return!1},Menubar.prototype.handleFocus=function(item){if(null===this.activeItem)this.activeItem=item;else if(item[0]!=this.activeItem[0])return!0;var parentItems=this.activeItem.parentsUntil("ul.tool-lp-menu").filter("li");(this.allItems.removeClass("menu-focus"),this.activeItem.addClass("menu-focus"),parentItems.addClass("menu-focus"),!0===this.isChildOpen)&&(item.parent().is(".tool-lp-menu")&&"true"==item.attr("aria-haspopup")&&this.openSubMenu(item.children("ul").first()));return!0},Menubar.prototype.handleBlur=function(item){return item.removeClass("menu-focus"),!0},Menubar.prototype.setOpenDirection=function(){var pos=this.menuRoot.offset(),isRTL=$(document.body).hasClass("dir-rtl"),heightmenuRoot=this.rootMenus.outerHeight(),widthmenuRoot=this.rootMenus.outerWidth(),subMenuContainer=this.rootMenus.find("ul.tool-lp-sub-menu");subMenuContainer.css("margin-right",""),subMenuContainer.css("margin-left",""),subMenuContainer.css("margin-top",""),subMenuContainer.attr("aria-hidden",!1);var menuRealWidth=subMenuContainer.outerWidth(),menuRealHeight=subMenuContainer.outerHeight(),margintop=null,marginright=null,marginleft=null;pos.top-$(window).scrollTop()+menuRealHeight>$(window).height()&&(margintop=menuRealHeight+heightmenuRoot,subMenuContainer.css("margin-top","-"+margintop+"px")),isRTL?pos.left-menuRealWidth<0&&(marginright=menuRealWidth-widthmenuRoot,subMenuContainer.css("margin-right","-"+marginright+"px")):pos.left+menuRealWidth>$(window).width()&&(marginleft=menuRealWidth-widthmenuRoot,subMenuContainer.css("margin-left","-"+marginleft+"px")),this.menuRoot.addClass("tool-lp-menu-open-left")},Menubar.prototype.handleKeyDown=function(item,e){if(e.altKey||e.ctrlKey)return!0;switch(e.keyCode){case this.keys.tab:this.menuRoot.find("ul").attr("aria-hidden","true"),this.allItems.removeClass("menu-focus"),this.activeItem=null,this.isChildOpen=!1;break;case this.keys.esc:var itemUL=item.parent();return itemUL.is(".tool-lp-menu")?item.children("ul").first().attr("aria-hidden","true"):(this.activeItem=itemUL.parent(),this.isChildOpen=!1,this.activeItem.focus(),itemUL.attr("aria-hidden","true")),e.stopPropagation(),!1;case this.keys.enter:case this.keys.space:return this.handleClick(item,e);case this.keys.left:return this.activeItem=this.moveToPrevious(item),this.activeItem.focus(),e.stopPropagation(),!1;case this.keys.right:return this.activeItem=this.moveToNext(item),this.activeItem.focus(),e.stopPropagation(),!1;case this.keys.up:return this.activeItem=this.moveUp(item),this.activeItem.focus(),e.stopPropagation(),!1;case this.keys.down:return this.activeItem=this.moveDown(item),this.activeItem.focus(),e.stopPropagation(),!1}return!0},Menubar.prototype.moveToNext=function(item){var itemUL=item.parent(),menuItems=itemUL.children("li"),menuNum=menuItems.length,menuIndex=menuItems.index(item),newItem=null,childMenu=null;if(itemUL.is(".tool-lp-menu"))newItem=menuIndex0?item.prev():menuItems.last(),"true"==item.attr("aria-haspopup")&&"false"==(childMenu=item.children("ul").first()).attr("aria-hidden")&&(childMenu.attr("aria-hidden","true"),this.isChildOpen=!0),item.removeClass("menu-focus"),"true"===newItem.attr("aria-haspopup")&&!0===this.isChildOpen&&(childMenu=newItem.children("ul").first(),this.openSubMenu(childMenu));else{var parentLI=itemUL.parent();parentLI.parent().is(".tool-lp-menu")?(itemUL.attr("aria-hidden","true"),item.removeClass("menu-focus"),parentLI.removeClass("menu-focus"),(newItem=(menuIndex=this.rootMenus.index(parentLI))>0?parentLI.prev():this.rootMenus.last()).addClass("menu-focus"),"true"==newItem.attr("aria-haspopup")&&(childMenu=newItem.children("ul").first(),this.openSubMenu(childMenu),this.isChildOpen=!0,newItem=childMenu.children("li").first())):(newItem=itemUL.parent(),itemUL.attr("aria-hidden","true"),item.removeClass("menu-focus"))}return newItem},Menubar.prototype.moveDown=function(item,startChr){var itemUL=item.parent(),menuItems=itemUL.children("li").not(".separator"),menuNum=menuItems.length,menuIndex=menuItems.index(item),newItem=null,newItemUL=null;if(itemUL.is(".tool-lp-menu"))return"true"!=item.attr("aria-haspopup")?item:(newItem=(newItemUL=item.children("ul").first()).children("li").first(),this.openSubMenu(newItemUL),newItem);if(startChr){var match=!1,curNdx=menuIndex+1;for(curNdx==menuNum&&(curNdx=0);curNdx!=menuIndex;){if(menuItems.eq(curNdx).html().charAt(0).toLowerCase()==startChr){match=!0;break}(curNdx+=1)==menuNum&&(curNdx=0)}return!0===match?(newItem=menuItems.eq(curNdx),item.removeClass("menu-focus"),newItem):item}return newItem=menuIndex0?menuItems.eq(menuIndex-1):menuItems.last(),item.removeClass("menu-focus"),newItem)},Menubar.prototype.addAriaAttributes=function(){this.menuRoot.attr("role","menubar"),this.rootMenus.attr("role","menuitem"),this.rootMenus.attr("tabindex","0"),this.rootMenus.attr("aria-haspopup","true"),this.subMenus.attr("role","menu"),this.subMenus.attr("aria-hidden","true"),this.subMenuItems.attr("role","menuitem"),this.subMenuItems.attr("tabindex","-1"),this.menuRoot.addClass("tool-lp-menu"),this.allItems.addClass("tool-lp-menu-item"),this.rootMenus.addClass("tool-lp-root-menu"),this.subMenus.addClass("tool-lp-sub-menu"),this.subMenuItems.addClass("dropdown-item")},{enhance:function(selector,handler){$(selector).each((function(index,element){var menuRoot=$(element);!0!==menuRoot.data("menubarEnhanced")&&(new Menubar(menuRoot,handler),menuRoot.data("menubarEnhanced",!0))}))},closeAll:closeAllSubMenus}}));
+
+//# sourceMappingURL=menubar.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/menubar.min.js.map b/admin/tool/lp/amd/build/menubar.min.js.map
index 8da85b41543..01dbfe4212f 100644
--- a/admin/tool/lp/amd/build/menubar.min.js.map
+++ b/admin/tool/lp/amd/build/menubar.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/menubar.js"],"names":["define","$","documentClickHandlerRegistered","menuActive","closeAllSubMenus","attr","Menubar","menuRoot","handlers","rootMenus","children","subMenus","subMenuItems","allItems","add","activeItem","isChildOpen","keys","tab","enter","esc","space","left","up","right","down","addAriaAttributes","addEventListeners","prototype","openSubMenu","menu","setOpenDirection","currentThis","document","click","mouseenter","addClass","mouseout","removeClass","e","handleClick","keydown","handleKeyDown","focus","handleFocus","blur","handleBlur","item","stopPropagation","parentUL","parent","is","first","find","not","anchor","clickEvent","Event","target","eventHandled","each","selector","handler","length","callable","proxy","isDefaultPrevented","window","location","href","parentItems","parentsUntil","filter","itemUL","pos","offset","isRTL","body","hasClass","heightmenuRoot","outerHeight","widthmenuRoot","outerWidth","subMenuContainer","css","menuRealWidth","menuRealHeight","margintop","marginright","marginleft","top","scrollTop","height","width","altKey","ctrlKey","keyCode","moveToPrevious","moveToNext","moveUp","moveDown","menuItems","menuNum","menuIndex","index","newItem","childMenu","next","parentMenus","rootItem","last","prev","parentLI","startChr","newItemUL","match","curNdx","titleChr","eq","html","charAt","toLowerCase","enhance","element","data","closeAll"],"mappings":"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","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 .\n\n/**\n * Aria menubar functionality. Enhances a simple nested list structure into a full aria widget.\n * Based on the open ajax example: http://oaa-accessibility.org/example/26/\n *\n * @module tool_lp/menubar\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery'], function($) {\n\n /** @property {boolean} Flag to indicate if we have already registered a click event handler for the document. */\n var documentClickHandlerRegistered = false;\n\n /** @property {boolean} Flag to indicate whether there's an active, open menu. */\n var menuActive = false;\n\n /**\n * Close all open submenus anywhere in the page (there should only ever be one open at a time).\n *\n * @method closeAllSubMenus\n */\n var closeAllSubMenus = function() {\n $('.tool-lp-menu .tool-lp-sub-menu').attr('aria-hidden', 'true');\n // Every menu's closed at this point, so set the menu active flag to false.\n menuActive = false;\n };\n\n /**\n * Constructor\n *\n * @param {jQuery} menuRoot Jquery collection matching the root of the menu.\n * @param {Function[]} handlers called when a menu item is chosen.\n */\n var Menubar = function(menuRoot, handlers) {\n // Setup private class variables.\n this.menuRoot = menuRoot;\n this.handlers = handlers;\n this.rootMenus = this.menuRoot.children('li');\n this.subMenus = this.rootMenus.children('ul');\n this.subMenuItems = this.subMenus.children('li');\n this.allItems = this.rootMenus.add(this.subMenuItems);\n this.activeItem = null;\n this.isChildOpen = false;\n\n this.keys = {\n tab: 9,\n enter: 13,\n esc: 27,\n space: 32,\n left: 37,\n up: 38,\n right: 39,\n down: 40\n };\n\n this.addAriaAttributes();\n // Add the event listeners.\n this.addEventListeners();\n };\n\n /**\n * Open a submenu, first it closes all other sub-menus and sets the open direction.\n * @method openSubMenu\n * @param {Node} menu\n */\n Menubar.prototype.openSubMenu = function(menu) {\n this.setOpenDirection();\n closeAllSubMenus();\n menu.attr('aria-hidden', 'false');\n // Set menu active flag to true when a menu is opened.\n menuActive = true;\n };\n\n\n /**\n * Bind the event listeners to the DOM\n * @method addEventListeners\n */\n Menubar.prototype.addEventListeners = function() {\n var currentThis = this;\n\n // When clicking outside the menubar.\n if (documentClickHandlerRegistered === false) {\n $(document).click(function() {\n // Check if a menu is opened.\n if (menuActive) {\n // Close menu.\n closeAllSubMenus();\n }\n });\n // Set this flag to true so that we won't need to add a document click handler for the other Menubar instances.\n documentClickHandlerRegistered = true;\n }\n\n // Hovers.\n this.subMenuItems.mouseenter(function() {\n $(this).addClass('menu-hover');\n return true;\n });\n\n this.subMenuItems.mouseout(function() {\n $(this).removeClass('menu-hover');\n return true;\n });\n\n // Mouse listeners.\n this.allItems.click(function(e) {\n return currentThis.handleClick($(this), e);\n });\n\n // Key listeners.\n this.allItems.keydown(function(e) {\n return currentThis.handleKeyDown($(this), e);\n });\n\n this.allItems.focus(function() {\n return currentThis.handleFocus($(this));\n });\n\n this.allItems.blur(function() {\n return currentThis.handleBlur($(this));\n });\n };\n\n /**\n * Process click events for the top menus.\n *\n * @method handleClick\n * @param {Object} item is the jquery object of the item firing the event\n * @param {Event} e is the associated event object\n * @return {boolean} Returns false\n */\n Menubar.prototype.handleClick = function(item, e) {\n e.stopPropagation();\n\n var parentUL = item.parent();\n\n if (parentUL.is('.tool-lp-menu')) {\n // Toggle the child menu open/closed.\n if (item.children('ul').first().attr('aria-hidden') == 'true') {\n this.openSubMenu(item.children('ul').first());\n } else {\n item.children('ul').first().attr('aria-hidden', 'true');\n }\n } else {\n // Remove hover and focus styling.\n this.allItems.removeClass('menu-hover menu-focus');\n\n // Clear the active item.\n this.activeItem = null;\n\n // Close the menu.\n this.menuRoot.find('ul').not('.root-level').attr('aria-hidden', 'true');\n // Follow any link, or call the click handlers.\n var anchor = item.find('a').first();\n var clickEvent = new $.Event('click');\n clickEvent.target = anchor;\n var eventHandled = false;\n if (this.handlers) {\n $.each(this.handlers, function(selector, handler) {\n if (eventHandled) {\n return;\n }\n if (item.find(selector).length > 0) {\n var callable = $.proxy(handler, anchor);\n // False means stop propogatting events.\n eventHandled = (callable(clickEvent) === false) || clickEvent.isDefaultPrevented();\n }\n });\n }\n // If we didn't find a handler, and the HREF is # that probably means that\n // we are handling it from somewhere else. Let's just do nothing in that case.\n if (!eventHandled && anchor.attr('href') !== '#') {\n window.location.href = anchor.attr('href');\n }\n }\n return false;\n };\n\n /*\n * Process focus events for the menu.\n *\n * @method handleFocus\n * @param {Object} item is the jquery object of the item firing the event\n * @return boolean Returns false\n */\n Menubar.prototype.handleFocus = function(item) {\n\n // If activeItem is null, we are getting focus from outside the menu. Store\n // the item that triggered the event.\n if (this.activeItem === null) {\n this.activeItem = item;\n } else if (item[0] != this.activeItem[0]) {\n return true;\n }\n\n // Get the set of jquery objects for all the parent items of the active item.\n var parentItems = this.activeItem.parentsUntil('ul.tool-lp-menu').filter('li');\n\n // Remove focus styling from all other menu items.\n this.allItems.removeClass('menu-focus');\n\n // Add focus styling to the active item.\n this.activeItem.addClass('menu-focus');\n\n // Add focus styling to all parent items.\n parentItems.addClass('menu-focus');\n\n // If the bChildOpen flag has been set, open the active item's child menu (if applicable).\n if (this.isChildOpen === true) {\n\n var itemUL = item.parent();\n\n // If the itemUL is a root-level menu and item is a parent item,\n // show the child menu.\n if (itemUL.is('.tool-lp-menu') && (item.attr('aria-haspopup') == 'true')) {\n this.openSubMenu(item.children('ul').first());\n }\n }\n\n return true;\n };\n\n /*\n * Process blur events for the menu.\n *\n * @method handleBlur\n * @param {Object} item is the jquery object of the item firing the event\n * @return boolean Returns false\n */\n Menubar.prototype.handleBlur = function(item) {\n item.removeClass('menu-focus');\n\n return true;\n };\n\n /*\n * Determine if the menu should open to the left, or the right,\n * based on the screen size and menu position.\n * @method setOpenDirection\n */\n Menubar.prototype.setOpenDirection = function() {\n var pos = this.menuRoot.offset();\n var isRTL = $(document.body).hasClass('dir-rtl');\n var openLeft = true;\n var heightmenuRoot = this.rootMenus.outerHeight();\n var widthmenuRoot = this.rootMenus.outerWidth();\n // Sometimes the menuMinWidth is not enough to figure out if menu exceeds the window width.\n // So we have to calculate the real menu width.\n var subMenuContainer = this.rootMenus.find('ul.tool-lp-sub-menu');\n\n // Reset margins.\n subMenuContainer.css('margin-right', '');\n subMenuContainer.css('margin-left', '');\n subMenuContainer.css('margin-top', '');\n\n subMenuContainer.attr('aria-hidden', false);\n var menuRealWidth = subMenuContainer.outerWidth(),\n menuRealHeight = subMenuContainer.outerHeight();\n\n var margintop = null,\n marginright = null,\n marginleft = null;\n var top = pos.top - $(window).scrollTop();\n // Top is the same for RTL and LTR.\n if (top + menuRealHeight > $(window).height()) {\n margintop = menuRealHeight + heightmenuRoot;\n subMenuContainer.css('margin-top', '-' + margintop + 'px');\n }\n\n if (isRTL) {\n if (pos.left - menuRealWidth < 0) {\n marginright = menuRealWidth - widthmenuRoot;\n subMenuContainer.css('margin-right', '-' + marginright + 'px');\n }\n } else {\n if (pos.left + menuRealWidth > $(window).width()) {\n marginleft = menuRealWidth - widthmenuRoot;\n subMenuContainer.css('margin-left', '-' + marginleft + 'px');\n }\n }\n\n if (openLeft) {\n this.menuRoot.addClass('tool-lp-menu-open-left');\n } else {\n this.menuRoot.removeClass('tool-lp-menu-open-left');\n }\n\n };\n\n /*\n * Process keyDown events for the menu.\n *\n * @method handleKeyDown\n * @param {Object} item is the jquery object of the item firing the event\n * @param {Event} e is the associated event object\n * @return boolean Returns false if consuming the event\n */\n Menubar.prototype.handleKeyDown = function(item, e) {\n\n if (e.altKey || e.ctrlKey) {\n // Modifier key pressed: Do not process.\n return true;\n }\n\n switch (e.keyCode) {\n case this.keys.tab: {\n\n // Hide all menu items and update their aria attributes.\n this.menuRoot.find('ul').attr('aria-hidden', 'true');\n\n // Remove focus styling from all menu items.\n this.allItems.removeClass('menu-focus');\n\n this.activeItem = null;\n\n this.isChildOpen = false;\n\n break;\n }\n case this.keys.esc: {\n var itemUL = item.parent();\n\n if (itemUL.is('.tool-lp-menu')) {\n // Hide the child menu and update the aria attributes.\n item.children('ul').first().attr('aria-hidden', 'true');\n } else {\n\n // Move up one level.\n this.activeItem = itemUL.parent();\n\n // Reset the isChildOpen flag.\n this.isChildOpen = false;\n\n // Set focus on the new item.\n this.activeItem.focus();\n\n // Hide the active menu and update the aria attributes.\n itemUL.attr('aria-hidden', 'true');\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.enter:\n case this.keys.space: {\n // Trigger click handler.\n return this.handleClick(item, e);\n }\n\n case this.keys.left: {\n\n this.activeItem = this.moveToPrevious(item);\n\n this.activeItem.focus();\n\n e.stopPropagation();\n return false;\n }\n case this.keys.right: {\n\n this.activeItem = this.moveToNext(item);\n\n this.activeItem.focus();\n\n e.stopPropagation();\n return false;\n }\n case this.keys.up: {\n\n this.activeItem = this.moveUp(item);\n\n this.activeItem.focus();\n\n e.stopPropagation();\n return false;\n }\n case this.keys.down: {\n\n this.activeItem = this.moveDown(item);\n\n this.activeItem.focus();\n\n e.stopPropagation();\n return false;\n }\n }\n\n return true;\n\n };\n\n\n /**\n * Move to the next menu level.\n * This will be either the next root-level menu or the child of a menu parent. If\n * at the root level and the active item is the last in the menu, this function will loop\n * to the first menu item.\n *\n * If the menu is a horizontal menu, the first child element of the newly selected menu will\n * be selected\n *\n * @method moveToNext\n * @param {Object} item is the active menu item\n * @return {Object} Returns the item to move to. Returns item is no move is possible\n */\n Menubar.prototype.moveToNext = function(item) {\n // Item's containing menu.\n var itemUL = item.parent();\n\n // The items in the currently active menu.\n var menuItems = itemUL.children('li');\n\n // The number of items in the active menu.\n var menuNum = menuItems.length;\n // The items index in its menu.\n var menuIndex = menuItems.index(item);\n var newItem = null;\n var childMenu = null;\n\n if (itemUL.is('.tool-lp-menu')) {\n // This is the root level move to next sibling. This will require closing\n // the current child menu and opening the new one.\n\n if (menuIndex < menuNum - 1) {\n // Not the last root menu.\n newItem = item.next();\n } else { // Wrap to first item.\n newItem = menuItems.first();\n }\n\n // Close the current child menu (if applicable).\n if (item.attr('aria-haspopup') == 'true') {\n\n childMenu = item.children('ul').first();\n\n if (childMenu.attr('aria-hidden') == 'false') {\n // Update the child menu's aria-hidden attribute.\n childMenu.attr('aria-hidden', 'true');\n this.isChildOpen = true;\n }\n }\n\n // Remove the focus styling from the current menu.\n item.removeClass('menu-focus');\n\n // Open the new child menu (if applicable).\n if ((newItem.attr('aria-haspopup') === 'true') && (this.isChildOpen === true)) {\n\n childMenu = newItem.children('ul').first();\n\n // Update the child's aria-hidden attribute.\n this.openSubMenu(childMenu);\n }\n } else {\n // This is not the root level. If there is a child menu to be moved into, do that;\n // otherwise, move to the next root-level menu if there is one.\n if (item.attr('aria-haspopup') == 'true') {\n\n childMenu = item.children('ul').first();\n\n newItem = childMenu.children('li').first();\n\n // Show the child menu and update its aria attributes.\n this.openSubMenu(childMenu);\n } else {\n // At deepest level, move to the next root-level menu.\n\n var parentMenus = null;\n var rootItem = null;\n\n // Get list of all parent menus for item, up to the root level.\n parentMenus = item.parentsUntil('ul.tool-lp-menu').filter('ul').not('.tool-lp-menu');\n\n // Hide the current menu and update its aria attributes accordingly.\n parentMenus.attr('aria-hidden', 'true');\n\n // Remove the focus styling from the active menu.\n parentMenus.find('li').removeClass('menu-focus');\n parentMenus.last().parent().removeClass('menu-focus');\n\n // The containing root for the menu.\n rootItem = parentMenus.last().parent();\n\n menuIndex = this.rootMenus.index(rootItem);\n\n // If this is not the last root menu item, move to the next one.\n if (menuIndex < this.rootMenus.length - 1) {\n newItem = rootItem.next();\n } else {\n // Loop.\n newItem = this.rootMenus.first();\n }\n\n // Add the focus styling to the new menu.\n newItem.addClass('menu-focus');\n\n if (newItem.attr('aria-haspopup') == 'true') {\n childMenu = newItem.children('ul').first();\n\n newItem = childMenu.children('li').first();\n\n // Show the child menu and update it's aria attributes.\n this.openSubMenu(childMenu);\n this.isChildOpen = true;\n }\n }\n }\n\n return newItem;\n };\n\n /**\n * Member function to move to the previous menu level.\n * This will be either the previous root-level menu or the child of a menu parent. If\n * at the root level and the active item is the first in the menu, this function will loop\n * to the last menu item.\n *\n * If the menu is a horizontal menu, the first child element of the newly selected menu will\n * be selected\n *\n * @method moveToPrevious\n * @param {Object} item is the active menu item\n * @return {Object} Returns the item to move to. Returns item is no move is possible\n */\n Menubar.prototype.moveToPrevious = function(item) {\n // Item's containing menu.\n var itemUL = item.parent();\n // The items in the currently active menu.\n var menuItems = itemUL.children('li');\n // The items index in its menu.\n var menuIndex = menuItems.index(item);\n var newItem = null;\n var childMenu = null;\n\n if (itemUL.is('.tool-lp-menu')) {\n // This is the root level move to previous sibling. This will require closing\n // the current child menu and opening the new one.\n\n if (menuIndex > 0) {\n // Not the first root menu.\n newItem = item.prev();\n } else {\n // Wrap to last item.\n newItem = menuItems.last();\n }\n\n // Close the current child menu (if applicable).\n if (item.attr('aria-haspopup') == 'true') {\n childMenu = item.children('ul').first();\n\n if (childMenu.attr('aria-hidden') == 'false') {\n // Update the child menu's aria-hidden attribute.\n childMenu.attr('aria-hidden', 'true');\n this.isChildOpen = true;\n }\n }\n\n // Remove the focus styling from the current menu.\n item.removeClass('menu-focus');\n\n // Open the new child menu (if applicable).\n if ((newItem.attr('aria-haspopup') === 'true') && (this.isChildOpen === true)) {\n\n childMenu = newItem.children('ul').first();\n\n // Update the child's aria-hidden attribute.\n this.openSubMenu(childMenu);\n\n }\n } else {\n // This is not the root level. If there is a parent menu that is not the\n // root menu, move up one level; otherwise, move to first item of the previous\n // root menu.\n\n var parentLI = itemUL.parent();\n var parentUL = parentLI.parent();\n\n // If this is a vertical menu or is not the first child menu\n // of the root-level menu, move up one level.\n if (!parentUL.is('.tool-lp-menu')) {\n\n newItem = itemUL.parent();\n\n // Hide the active menu and update aria-hidden.\n itemUL.attr('aria-hidden', 'true');\n\n // Remove the focus highlight from the item.\n item.removeClass('menu-focus');\n\n } else {\n // Move to previous root-level menu.\n\n // Hide the current menu and update the aria attributes accordingly.\n itemUL.attr('aria-hidden', 'true');\n\n // Remove the focus styling from the active menu.\n item.removeClass('menu-focus');\n parentLI.removeClass('menu-focus');\n\n menuIndex = this.rootMenus.index(parentLI);\n\n if (menuIndex > 0) {\n // Move to the previous root-level menu.\n newItem = parentLI.prev();\n } else {\n // Loop to last root-level menu.\n newItem = this.rootMenus.last();\n }\n\n // Add the focus styling to the new menu.\n newItem.addClass('menu-focus');\n\n if (newItem.attr('aria-haspopup') == 'true') {\n childMenu = newItem.children('ul').first();\n\n // Show the child menu and update it's aria attributes.\n this.openSubMenu(childMenu);\n this.isChildOpen = true;\n\n newItem = childMenu.children('li').first();\n }\n }\n }\n\n return newItem;\n };\n\n /**\n * Member function to select the next item in a menu.\n * If the active item is the last in the menu, this function will loop to the\n * first menu item.\n *\n * @method moveDown\n * @param {Object} item is the active menu item\n * @param {String} startChr is the character to attempt to match against the beginning of the\n * menu item titles. If found, focus moves to the next menu item beginning with that character.\n * @return {Object} Returns the item to move to. Returns item is no move is possible\n */\n Menubar.prototype.moveDown = function(item, startChr) {\n // Item's containing menu.\n var itemUL = item.parent();\n // The items in the currently active menu.\n var menuItems = itemUL.children('li').not('.separator');\n // The number of items in the active menu.\n var menuNum = menuItems.length;\n // The items index in its menu.\n var menuIndex = menuItems.index(item);\n var newItem = null;\n var newItemUL = null;\n\n if (itemUL.is('.tool-lp-menu')) {\n // This is the root level menu.\n\n if (item.attr('aria-haspopup') != 'true') {\n // No child menu to move to.\n return item;\n }\n\n // Move to the first item in the child menu.\n newItemUL = item.children('ul').first();\n newItem = newItemUL.children('li').first();\n\n // Make sure the child menu is visible.\n this.openSubMenu(newItemUL);\n\n return newItem;\n }\n\n // If $item is not the last item in its menu, move to the next item. If startChr is specified, move\n // to the next item with a title that begins with that character.\n if (startChr) {\n var match = false;\n var curNdx = menuIndex + 1;\n\n // Check if the active item was the last one on the list.\n if (curNdx == menuNum) {\n curNdx = 0;\n }\n\n // Iterate through the menu items (starting from the current item and wrapping) until a match is found\n // or the loop returns to the current menu item.\n while (curNdx != menuIndex) {\n\n var titleChr = menuItems.eq(curNdx).html().charAt(0);\n\n if (titleChr.toLowerCase() == startChr) {\n match = true;\n break;\n }\n\n curNdx = curNdx + 1;\n\n if (curNdx == menuNum) {\n // Reached the end of the list, start again at the beginning.\n curNdx = 0;\n }\n }\n\n if (match === true) {\n newItem = menuItems.eq(curNdx);\n\n // Remove the focus styling from the current item.\n item.removeClass('menu-focus');\n\n return newItem;\n } else {\n return item;\n }\n } else {\n if (menuIndex < menuNum - 1) {\n newItem = menuItems.eq(menuIndex + 1);\n } else {\n newItem = menuItems.first();\n }\n }\n\n // Remove the focus styling from the current item.\n item.removeClass('menu-focus');\n\n return newItem;\n };\n\n /**\n * Function moveUp() is a member function to select the previous item in a menu.\n * If the active item is the first in the menu, this function will loop to the\n * last menu item.\n *\n * @method moveUp\n * @param {Object} item is the active menu item\n * @return {Object} Returns the item to move to. Returns item is no move is possible\n */\n Menubar.prototype.moveUp = function(item) {\n // Item's containing menu.\n var itemUL = item.parent();\n // The items in the currently active menu.\n var menuItems = itemUL.children('li').not('.separator');\n // The items index in its menu.\n var menuIndex = menuItems.index(item);\n var newItem = null;\n\n if (itemUL.is('.tool-lp-menu')) {\n // This is the root level menu.\n // Nothing to do.\n return item;\n }\n\n // If item is not the first item in its menu, move to the previous item.\n if (menuIndex > 0) {\n newItem = menuItems.eq(menuIndex - 1);\n } else {\n // Loop to top of menu.\n newItem = menuItems.last();\n }\n\n // Remove the focus styling from the current item.\n item.removeClass('menu-focus');\n\n return newItem;\n };\n\n /**\n * Enhance the dom with aria attributes.\n * @method addAriaAttributes\n */\n Menubar.prototype.addAriaAttributes = function() {\n this.menuRoot.attr('role', 'menubar');\n this.rootMenus.attr('role', 'menuitem');\n this.rootMenus.attr('tabindex', '0');\n this.rootMenus.attr('aria-haspopup', 'true');\n this.subMenus.attr('role', 'menu');\n this.subMenus.attr('aria-hidden', 'true');\n this.subMenuItems.attr('role', 'menuitem');\n this.subMenuItems.attr('tabindex', '-1');\n\n // For CSS styling and effects.\n this.menuRoot.addClass('tool-lp-menu');\n this.allItems.addClass('tool-lp-menu-item');\n this.rootMenus.addClass('tool-lp-root-menu');\n this.subMenus.addClass('tool-lp-sub-menu');\n this.subMenuItems.addClass('dropdown-item');\n };\n\n return /** @alias module:tool_lp/menubar */ {\n /**\n * Create a menu bar object for every node matching the selector.\n *\n * The expected DOM structure is shown below.\n *
<- This is the target of the selector parameter.\n *
<- This is repeated for each top level menu.\n * Text <- This is the text for the top level menu.\n *
<- This is a list of the entries in this top level menu.\n *
<- This is repeated for each menu entry.\n * Choice 1 <- The anchor for the menu.\n *
\n *
\n *
\n *
\n *\n * @method enhance\n * @param {String} selector - The selector for the outer most menu node.\n * @param {Function} handler - Javascript handler for when a menu item was chosen. If the\n * handler returns true (or does not exist), the\n * menu will look for an anchor with a link to follow.\n * For example, if the menu entry has a \"data-action\" attribute\n * and we want to call a javascript function when that entry is chosen,\n * we could pass a list of handlers like this:\n * { \"[data-action='add']\" : callAddFunction }\n */\n enhance: function(selector, handler) {\n $(selector).each(function(index, element) {\n var menuRoot = $(element);\n // Don't enhance the same menu twice.\n if (menuRoot.data(\"menubarEnhanced\") !== true) {\n (new Menubar(menuRoot, handler));\n menuRoot.data(\"menubarEnhanced\", true);\n }\n });\n },\n\n /**\n * Handy function to close all open menus anywhere on the page.\n * @method closeAll\n */\n closeAll: closeAllSubMenus\n };\n});\n"],"file":"menubar.min.js"}
\ No newline at end of file
+{"version":3,"file":"menubar.min.js","sources":["../src/menubar.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 .\n\n/**\n * Aria menubar functionality. Enhances a simple nested list structure into a full aria widget.\n * Based on the open ajax example: http://oaa-accessibility.org/example/26/\n *\n * @module tool_lp/menubar\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery'], function($) {\n\n /** @property {boolean} Flag to indicate if we have already registered a click event handler for the document. */\n var documentClickHandlerRegistered = false;\n\n /** @property {boolean} Flag to indicate whether there's an active, open menu. */\n var menuActive = false;\n\n /**\n * Close all open submenus anywhere in the page (there should only ever be one open at a time).\n *\n * @method closeAllSubMenus\n */\n var closeAllSubMenus = function() {\n $('.tool-lp-menu .tool-lp-sub-menu').attr('aria-hidden', 'true');\n // Every menu's closed at this point, so set the menu active flag to false.\n menuActive = false;\n };\n\n /**\n * Constructor\n *\n * @param {jQuery} menuRoot Jquery collection matching the root of the menu.\n * @param {Function[]} handlers called when a menu item is chosen.\n */\n var Menubar = function(menuRoot, handlers) {\n // Setup private class variables.\n this.menuRoot = menuRoot;\n this.handlers = handlers;\n this.rootMenus = this.menuRoot.children('li');\n this.subMenus = this.rootMenus.children('ul');\n this.subMenuItems = this.subMenus.children('li');\n this.allItems = this.rootMenus.add(this.subMenuItems);\n this.activeItem = null;\n this.isChildOpen = false;\n\n this.keys = {\n tab: 9,\n enter: 13,\n esc: 27,\n space: 32,\n left: 37,\n up: 38,\n right: 39,\n down: 40\n };\n\n this.addAriaAttributes();\n // Add the event listeners.\n this.addEventListeners();\n };\n\n /**\n * Open a submenu, first it closes all other sub-menus and sets the open direction.\n * @method openSubMenu\n * @param {Node} menu\n */\n Menubar.prototype.openSubMenu = function(menu) {\n this.setOpenDirection();\n closeAllSubMenus();\n menu.attr('aria-hidden', 'false');\n // Set menu active flag to true when a menu is opened.\n menuActive = true;\n };\n\n\n /**\n * Bind the event listeners to the DOM\n * @method addEventListeners\n */\n Menubar.prototype.addEventListeners = function() {\n var currentThis = this;\n\n // When clicking outside the menubar.\n if (documentClickHandlerRegistered === false) {\n $(document).click(function() {\n // Check if a menu is opened.\n if (menuActive) {\n // Close menu.\n closeAllSubMenus();\n }\n });\n // Set this flag to true so that we won't need to add a document click handler for the other Menubar instances.\n documentClickHandlerRegistered = true;\n }\n\n // Hovers.\n this.subMenuItems.mouseenter(function() {\n $(this).addClass('menu-hover');\n return true;\n });\n\n this.subMenuItems.mouseout(function() {\n $(this).removeClass('menu-hover');\n return true;\n });\n\n // Mouse listeners.\n this.allItems.click(function(e) {\n return currentThis.handleClick($(this), e);\n });\n\n // Key listeners.\n this.allItems.keydown(function(e) {\n return currentThis.handleKeyDown($(this), e);\n });\n\n this.allItems.focus(function() {\n return currentThis.handleFocus($(this));\n });\n\n this.allItems.blur(function() {\n return currentThis.handleBlur($(this));\n });\n };\n\n /**\n * Process click events for the top menus.\n *\n * @method handleClick\n * @param {Object} item is the jquery object of the item firing the event\n * @param {Event} e is the associated event object\n * @return {boolean} Returns false\n */\n Menubar.prototype.handleClick = function(item, e) {\n e.stopPropagation();\n\n var parentUL = item.parent();\n\n if (parentUL.is('.tool-lp-menu')) {\n // Toggle the child menu open/closed.\n if (item.children('ul').first().attr('aria-hidden') == 'true') {\n this.openSubMenu(item.children('ul').first());\n } else {\n item.children('ul').first().attr('aria-hidden', 'true');\n }\n } else {\n // Remove hover and focus styling.\n this.allItems.removeClass('menu-hover menu-focus');\n\n // Clear the active item.\n this.activeItem = null;\n\n // Close the menu.\n this.menuRoot.find('ul').not('.root-level').attr('aria-hidden', 'true');\n // Follow any link, or call the click handlers.\n var anchor = item.find('a').first();\n var clickEvent = new $.Event('click');\n clickEvent.target = anchor;\n var eventHandled = false;\n if (this.handlers) {\n $.each(this.handlers, function(selector, handler) {\n if (eventHandled) {\n return;\n }\n if (item.find(selector).length > 0) {\n var callable = $.proxy(handler, anchor);\n // False means stop propogatting events.\n eventHandled = (callable(clickEvent) === false) || clickEvent.isDefaultPrevented();\n }\n });\n }\n // If we didn't find a handler, and the HREF is # that probably means that\n // we are handling it from somewhere else. Let's just do nothing in that case.\n if (!eventHandled && anchor.attr('href') !== '#') {\n window.location.href = anchor.attr('href');\n }\n }\n return false;\n };\n\n /*\n * Process focus events for the menu.\n *\n * @method handleFocus\n * @param {Object} item is the jquery object of the item firing the event\n * @return boolean Returns false\n */\n Menubar.prototype.handleFocus = function(item) {\n\n // If activeItem is null, we are getting focus from outside the menu. Store\n // the item that triggered the event.\n if (this.activeItem === null) {\n this.activeItem = item;\n } else if (item[0] != this.activeItem[0]) {\n return true;\n }\n\n // Get the set of jquery objects for all the parent items of the active item.\n var parentItems = this.activeItem.parentsUntil('ul.tool-lp-menu').filter('li');\n\n // Remove focus styling from all other menu items.\n this.allItems.removeClass('menu-focus');\n\n // Add focus styling to the active item.\n this.activeItem.addClass('menu-focus');\n\n // Add focus styling to all parent items.\n parentItems.addClass('menu-focus');\n\n // If the bChildOpen flag has been set, open the active item's child menu (if applicable).\n if (this.isChildOpen === true) {\n\n var itemUL = item.parent();\n\n // If the itemUL is a root-level menu and item is a parent item,\n // show the child menu.\n if (itemUL.is('.tool-lp-menu') && (item.attr('aria-haspopup') == 'true')) {\n this.openSubMenu(item.children('ul').first());\n }\n }\n\n return true;\n };\n\n /*\n * Process blur events for the menu.\n *\n * @method handleBlur\n * @param {Object} item is the jquery object of the item firing the event\n * @return boolean Returns false\n */\n Menubar.prototype.handleBlur = function(item) {\n item.removeClass('menu-focus');\n\n return true;\n };\n\n /*\n * Determine if the menu should open to the left, or the right,\n * based on the screen size and menu position.\n * @method setOpenDirection\n */\n Menubar.prototype.setOpenDirection = function() {\n var pos = this.menuRoot.offset();\n var isRTL = $(document.body).hasClass('dir-rtl');\n var openLeft = true;\n var heightmenuRoot = this.rootMenus.outerHeight();\n var widthmenuRoot = this.rootMenus.outerWidth();\n // Sometimes the menuMinWidth is not enough to figure out if menu exceeds the window width.\n // So we have to calculate the real menu width.\n var subMenuContainer = this.rootMenus.find('ul.tool-lp-sub-menu');\n\n // Reset margins.\n subMenuContainer.css('margin-right', '');\n subMenuContainer.css('margin-left', '');\n subMenuContainer.css('margin-top', '');\n\n subMenuContainer.attr('aria-hidden', false);\n var menuRealWidth = subMenuContainer.outerWidth(),\n menuRealHeight = subMenuContainer.outerHeight();\n\n var margintop = null,\n marginright = null,\n marginleft = null;\n var top = pos.top - $(window).scrollTop();\n // Top is the same for RTL and LTR.\n if (top + menuRealHeight > $(window).height()) {\n margintop = menuRealHeight + heightmenuRoot;\n subMenuContainer.css('margin-top', '-' + margintop + 'px');\n }\n\n if (isRTL) {\n if (pos.left - menuRealWidth < 0) {\n marginright = menuRealWidth - widthmenuRoot;\n subMenuContainer.css('margin-right', '-' + marginright + 'px');\n }\n } else {\n if (pos.left + menuRealWidth > $(window).width()) {\n marginleft = menuRealWidth - widthmenuRoot;\n subMenuContainer.css('margin-left', '-' + marginleft + 'px');\n }\n }\n\n if (openLeft) {\n this.menuRoot.addClass('tool-lp-menu-open-left');\n } else {\n this.menuRoot.removeClass('tool-lp-menu-open-left');\n }\n\n };\n\n /*\n * Process keyDown events for the menu.\n *\n * @method handleKeyDown\n * @param {Object} item is the jquery object of the item firing the event\n * @param {Event} e is the associated event object\n * @return boolean Returns false if consuming the event\n */\n Menubar.prototype.handleKeyDown = function(item, e) {\n\n if (e.altKey || e.ctrlKey) {\n // Modifier key pressed: Do not process.\n return true;\n }\n\n switch (e.keyCode) {\n case this.keys.tab: {\n\n // Hide all menu items and update their aria attributes.\n this.menuRoot.find('ul').attr('aria-hidden', 'true');\n\n // Remove focus styling from all menu items.\n this.allItems.removeClass('menu-focus');\n\n this.activeItem = null;\n\n this.isChildOpen = false;\n\n break;\n }\n case this.keys.esc: {\n var itemUL = item.parent();\n\n if (itemUL.is('.tool-lp-menu')) {\n // Hide the child menu and update the aria attributes.\n item.children('ul').first().attr('aria-hidden', 'true');\n } else {\n\n // Move up one level.\n this.activeItem = itemUL.parent();\n\n // Reset the isChildOpen flag.\n this.isChildOpen = false;\n\n // Set focus on the new item.\n this.activeItem.focus();\n\n // Hide the active menu and update the aria attributes.\n itemUL.attr('aria-hidden', 'true');\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.enter:\n case this.keys.space: {\n // Trigger click handler.\n return this.handleClick(item, e);\n }\n\n case this.keys.left: {\n\n this.activeItem = this.moveToPrevious(item);\n\n this.activeItem.focus();\n\n e.stopPropagation();\n return false;\n }\n case this.keys.right: {\n\n this.activeItem = this.moveToNext(item);\n\n this.activeItem.focus();\n\n e.stopPropagation();\n return false;\n }\n case this.keys.up: {\n\n this.activeItem = this.moveUp(item);\n\n this.activeItem.focus();\n\n e.stopPropagation();\n return false;\n }\n case this.keys.down: {\n\n this.activeItem = this.moveDown(item);\n\n this.activeItem.focus();\n\n e.stopPropagation();\n return false;\n }\n }\n\n return true;\n\n };\n\n\n /**\n * Move to the next menu level.\n * This will be either the next root-level menu or the child of a menu parent. If\n * at the root level and the active item is the last in the menu, this function will loop\n * to the first menu item.\n *\n * If the menu is a horizontal menu, the first child element of the newly selected menu will\n * be selected\n *\n * @method moveToNext\n * @param {Object} item is the active menu item\n * @return {Object} Returns the item to move to. Returns item is no move is possible\n */\n Menubar.prototype.moveToNext = function(item) {\n // Item's containing menu.\n var itemUL = item.parent();\n\n // The items in the currently active menu.\n var menuItems = itemUL.children('li');\n\n // The number of items in the active menu.\n var menuNum = menuItems.length;\n // The items index in its menu.\n var menuIndex = menuItems.index(item);\n var newItem = null;\n var childMenu = null;\n\n if (itemUL.is('.tool-lp-menu')) {\n // This is the root level move to next sibling. This will require closing\n // the current child menu and opening the new one.\n\n if (menuIndex < menuNum - 1) {\n // Not the last root menu.\n newItem = item.next();\n } else { // Wrap to first item.\n newItem = menuItems.first();\n }\n\n // Close the current child menu (if applicable).\n if (item.attr('aria-haspopup') == 'true') {\n\n childMenu = item.children('ul').first();\n\n if (childMenu.attr('aria-hidden') == 'false') {\n // Update the child menu's aria-hidden attribute.\n childMenu.attr('aria-hidden', 'true');\n this.isChildOpen = true;\n }\n }\n\n // Remove the focus styling from the current menu.\n item.removeClass('menu-focus');\n\n // Open the new child menu (if applicable).\n if ((newItem.attr('aria-haspopup') === 'true') && (this.isChildOpen === true)) {\n\n childMenu = newItem.children('ul').first();\n\n // Update the child's aria-hidden attribute.\n this.openSubMenu(childMenu);\n }\n } else {\n // This is not the root level. If there is a child menu to be moved into, do that;\n // otherwise, move to the next root-level menu if there is one.\n if (item.attr('aria-haspopup') == 'true') {\n\n childMenu = item.children('ul').first();\n\n newItem = childMenu.children('li').first();\n\n // Show the child menu and update its aria attributes.\n this.openSubMenu(childMenu);\n } else {\n // At deepest level, move to the next root-level menu.\n\n var parentMenus = null;\n var rootItem = null;\n\n // Get list of all parent menus for item, up to the root level.\n parentMenus = item.parentsUntil('ul.tool-lp-menu').filter('ul').not('.tool-lp-menu');\n\n // Hide the current menu and update its aria attributes accordingly.\n parentMenus.attr('aria-hidden', 'true');\n\n // Remove the focus styling from the active menu.\n parentMenus.find('li').removeClass('menu-focus');\n parentMenus.last().parent().removeClass('menu-focus');\n\n // The containing root for the menu.\n rootItem = parentMenus.last().parent();\n\n menuIndex = this.rootMenus.index(rootItem);\n\n // If this is not the last root menu item, move to the next one.\n if (menuIndex < this.rootMenus.length - 1) {\n newItem = rootItem.next();\n } else {\n // Loop.\n newItem = this.rootMenus.first();\n }\n\n // Add the focus styling to the new menu.\n newItem.addClass('menu-focus');\n\n if (newItem.attr('aria-haspopup') == 'true') {\n childMenu = newItem.children('ul').first();\n\n newItem = childMenu.children('li').first();\n\n // Show the child menu and update it's aria attributes.\n this.openSubMenu(childMenu);\n this.isChildOpen = true;\n }\n }\n }\n\n return newItem;\n };\n\n /**\n * Member function to move to the previous menu level.\n * This will be either the previous root-level menu or the child of a menu parent. If\n * at the root level and the active item is the first in the menu, this function will loop\n * to the last menu item.\n *\n * If the menu is a horizontal menu, the first child element of the newly selected menu will\n * be selected\n *\n * @method moveToPrevious\n * @param {Object} item is the active menu item\n * @return {Object} Returns the item to move to. Returns item is no move is possible\n */\n Menubar.prototype.moveToPrevious = function(item) {\n // Item's containing menu.\n var itemUL = item.parent();\n // The items in the currently active menu.\n var menuItems = itemUL.children('li');\n // The items index in its menu.\n var menuIndex = menuItems.index(item);\n var newItem = null;\n var childMenu = null;\n\n if (itemUL.is('.tool-lp-menu')) {\n // This is the root level move to previous sibling. This will require closing\n // the current child menu and opening the new one.\n\n if (menuIndex > 0) {\n // Not the first root menu.\n newItem = item.prev();\n } else {\n // Wrap to last item.\n newItem = menuItems.last();\n }\n\n // Close the current child menu (if applicable).\n if (item.attr('aria-haspopup') == 'true') {\n childMenu = item.children('ul').first();\n\n if (childMenu.attr('aria-hidden') == 'false') {\n // Update the child menu's aria-hidden attribute.\n childMenu.attr('aria-hidden', 'true');\n this.isChildOpen = true;\n }\n }\n\n // Remove the focus styling from the current menu.\n item.removeClass('menu-focus');\n\n // Open the new child menu (if applicable).\n if ((newItem.attr('aria-haspopup') === 'true') && (this.isChildOpen === true)) {\n\n childMenu = newItem.children('ul').first();\n\n // Update the child's aria-hidden attribute.\n this.openSubMenu(childMenu);\n\n }\n } else {\n // This is not the root level. If there is a parent menu that is not the\n // root menu, move up one level; otherwise, move to first item of the previous\n // root menu.\n\n var parentLI = itemUL.parent();\n var parentUL = parentLI.parent();\n\n // If this is a vertical menu or is not the first child menu\n // of the root-level menu, move up one level.\n if (!parentUL.is('.tool-lp-menu')) {\n\n newItem = itemUL.parent();\n\n // Hide the active menu and update aria-hidden.\n itemUL.attr('aria-hidden', 'true');\n\n // Remove the focus highlight from the item.\n item.removeClass('menu-focus');\n\n } else {\n // Move to previous root-level menu.\n\n // Hide the current menu and update the aria attributes accordingly.\n itemUL.attr('aria-hidden', 'true');\n\n // Remove the focus styling from the active menu.\n item.removeClass('menu-focus');\n parentLI.removeClass('menu-focus');\n\n menuIndex = this.rootMenus.index(parentLI);\n\n if (menuIndex > 0) {\n // Move to the previous root-level menu.\n newItem = parentLI.prev();\n } else {\n // Loop to last root-level menu.\n newItem = this.rootMenus.last();\n }\n\n // Add the focus styling to the new menu.\n newItem.addClass('menu-focus');\n\n if (newItem.attr('aria-haspopup') == 'true') {\n childMenu = newItem.children('ul').first();\n\n // Show the child menu and update it's aria attributes.\n this.openSubMenu(childMenu);\n this.isChildOpen = true;\n\n newItem = childMenu.children('li').first();\n }\n }\n }\n\n return newItem;\n };\n\n /**\n * Member function to select the next item in a menu.\n * If the active item is the last in the menu, this function will loop to the\n * first menu item.\n *\n * @method moveDown\n * @param {Object} item is the active menu item\n * @param {String} startChr is the character to attempt to match against the beginning of the\n * menu item titles. If found, focus moves to the next menu item beginning with that character.\n * @return {Object} Returns the item to move to. Returns item is no move is possible\n */\n Menubar.prototype.moveDown = function(item, startChr) {\n // Item's containing menu.\n var itemUL = item.parent();\n // The items in the currently active menu.\n var menuItems = itemUL.children('li').not('.separator');\n // The number of items in the active menu.\n var menuNum = menuItems.length;\n // The items index in its menu.\n var menuIndex = menuItems.index(item);\n var newItem = null;\n var newItemUL = null;\n\n if (itemUL.is('.tool-lp-menu')) {\n // This is the root level menu.\n\n if (item.attr('aria-haspopup') != 'true') {\n // No child menu to move to.\n return item;\n }\n\n // Move to the first item in the child menu.\n newItemUL = item.children('ul').first();\n newItem = newItemUL.children('li').first();\n\n // Make sure the child menu is visible.\n this.openSubMenu(newItemUL);\n\n return newItem;\n }\n\n // If $item is not the last item in its menu, move to the next item. If startChr is specified, move\n // to the next item with a title that begins with that character.\n if (startChr) {\n var match = false;\n var curNdx = menuIndex + 1;\n\n // Check if the active item was the last one on the list.\n if (curNdx == menuNum) {\n curNdx = 0;\n }\n\n // Iterate through the menu items (starting from the current item and wrapping) until a match is found\n // or the loop returns to the current menu item.\n while (curNdx != menuIndex) {\n\n var titleChr = menuItems.eq(curNdx).html().charAt(0);\n\n if (titleChr.toLowerCase() == startChr) {\n match = true;\n break;\n }\n\n curNdx = curNdx + 1;\n\n if (curNdx == menuNum) {\n // Reached the end of the list, start again at the beginning.\n curNdx = 0;\n }\n }\n\n if (match === true) {\n newItem = menuItems.eq(curNdx);\n\n // Remove the focus styling from the current item.\n item.removeClass('menu-focus');\n\n return newItem;\n } else {\n return item;\n }\n } else {\n if (menuIndex < menuNum - 1) {\n newItem = menuItems.eq(menuIndex + 1);\n } else {\n newItem = menuItems.first();\n }\n }\n\n // Remove the focus styling from the current item.\n item.removeClass('menu-focus');\n\n return newItem;\n };\n\n /**\n * Function moveUp() is a member function to select the previous item in a menu.\n * If the active item is the first in the menu, this function will loop to the\n * last menu item.\n *\n * @method moveUp\n * @param {Object} item is the active menu item\n * @return {Object} Returns the item to move to. Returns item is no move is possible\n */\n Menubar.prototype.moveUp = function(item) {\n // Item's containing menu.\n var itemUL = item.parent();\n // The items in the currently active menu.\n var menuItems = itemUL.children('li').not('.separator');\n // The items index in its menu.\n var menuIndex = menuItems.index(item);\n var newItem = null;\n\n if (itemUL.is('.tool-lp-menu')) {\n // This is the root level menu.\n // Nothing to do.\n return item;\n }\n\n // If item is not the first item in its menu, move to the previous item.\n if (menuIndex > 0) {\n newItem = menuItems.eq(menuIndex - 1);\n } else {\n // Loop to top of menu.\n newItem = menuItems.last();\n }\n\n // Remove the focus styling from the current item.\n item.removeClass('menu-focus');\n\n return newItem;\n };\n\n /**\n * Enhance the dom with aria attributes.\n * @method addAriaAttributes\n */\n Menubar.prototype.addAriaAttributes = function() {\n this.menuRoot.attr('role', 'menubar');\n this.rootMenus.attr('role', 'menuitem');\n this.rootMenus.attr('tabindex', '0');\n this.rootMenus.attr('aria-haspopup', 'true');\n this.subMenus.attr('role', 'menu');\n this.subMenus.attr('aria-hidden', 'true');\n this.subMenuItems.attr('role', 'menuitem');\n this.subMenuItems.attr('tabindex', '-1');\n\n // For CSS styling and effects.\n this.menuRoot.addClass('tool-lp-menu');\n this.allItems.addClass('tool-lp-menu-item');\n this.rootMenus.addClass('tool-lp-root-menu');\n this.subMenus.addClass('tool-lp-sub-menu');\n this.subMenuItems.addClass('dropdown-item');\n };\n\n return /** @alias module:tool_lp/menubar */ {\n /**\n * Create a menu bar object for every node matching the selector.\n *\n * The expected DOM structure is shown below.\n *
<- This is the target of the selector parameter.\n *
<- This is repeated for each top level menu.\n * Text <- This is the text for the top level menu.\n *
<- This is a list of the entries in this top level menu.\n *
<- This is repeated for each menu entry.\n * Choice 1 <- The anchor for the menu.\n *
\n *
\n *
\n *
\n *\n * @method enhance\n * @param {String} selector - The selector for the outer most menu node.\n * @param {Function} handler - Javascript handler for when a menu item was chosen. If the\n * handler returns true (or does not exist), the\n * menu will look for an anchor with a link to follow.\n * For example, if the menu entry has a \"data-action\" attribute\n * and we want to call a javascript function when that entry is chosen,\n * we could pass a list of handlers like this:\n * { \"[data-action='add']\" : callAddFunction }\n */\n enhance: function(selector, handler) {\n $(selector).each(function(index, element) {\n var menuRoot = $(element);\n // Don't enhance the same menu twice.\n if (menuRoot.data(\"menubarEnhanced\") !== true) {\n (new Menubar(menuRoot, handler));\n menuRoot.data(\"menubarEnhanced\", true);\n }\n });\n },\n\n /**\n * Handy function to close all open menus anywhere on the page.\n * @method closeAll\n */\n closeAll: closeAllSubMenus\n };\n});\n"],"names":["define","$","documentClickHandlerRegistered","menuActive","closeAllSubMenus","attr","Menubar","menuRoot","handlers","rootMenus","this","children","subMenus","subMenuItems","allItems","add","activeItem","isChildOpen","keys","tab","enter","esc","space","left","up","right","down","addAriaAttributes","addEventListeners","prototype","openSubMenu","menu","setOpenDirection","currentThis","document","click","mouseenter","addClass","mouseout","removeClass","e","handleClick","keydown","handleKeyDown","focus","handleFocus","blur","handleBlur","item","stopPropagation","parent","is","first","find","not","anchor","clickEvent","Event","target","eventHandled","each","selector","handler","length","callable","proxy","isDefaultPrevented","window","location","href","parentItems","parentsUntil","filter","pos","offset","isRTL","body","hasClass","heightmenuRoot","outerHeight","widthmenuRoot","outerWidth","subMenuContainer","css","menuRealWidth","menuRealHeight","margintop","marginright","marginleft","top","scrollTop","height","width","altKey","ctrlKey","keyCode","itemUL","moveToPrevious","moveToNext","moveUp","moveDown","menuItems","menuNum","menuIndex","index","newItem","childMenu","next","parentMenus","rootItem","last","prev","parentLI","startChr","newItemUL","match","curNdx","eq","html","charAt","toLowerCase","enhance","element","data","closeAll"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/module_navigation.min.js b/admin/tool/lp/amd/build/module_navigation.min.js
index 917da94c8a0..e88d34c6c6f 100644
--- a/admin/tool/lp/amd/build/module_navigation.min.js
+++ b/admin/tool/lp/amd/build/module_navigation.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/module_navigation",["jquery"],function(a){var b=function(b,c,d,e){this._baseUrl=c;this._moduleId=e;this._courseId=d;a(b).on("change",this._moduleChanged.bind(this))};b.prototype._moduleChanged=function(b){var c=a(b.target).val(),d="?mod="+c+"&courseid="+this._courseId;document.location=this._baseUrl+d};b.prototype._courseId=null;b.prototype._moduleId=null;b.prototype._baseUrl=null;return b});
-//# sourceMappingURL=module_navigation.min.js.map
+/**
+ * Module to navigation between users in a course.
+ *
+ * @module tool_lp/module_navigation
+ * @copyright 2019 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/module_navigation",["jquery"],(function($){var ModuleNavigation=function(moduleSelector,baseUrl,courseId,moduleId){this._baseUrl=baseUrl,this._moduleId=moduleId,this._courseId=courseId,$(moduleSelector).on("change",this._moduleChanged.bind(this))};return ModuleNavigation.prototype._moduleChanged=function(e){var queryStr="?mod="+$(e.target).val()+"&courseid="+this._courseId;document.location=this._baseUrl+queryStr},ModuleNavigation.prototype._courseId=null,ModuleNavigation.prototype._moduleId=null,ModuleNavigation.prototype._baseUrl=null,ModuleNavigation}));
+
+//# sourceMappingURL=module_navigation.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/module_navigation.min.js.map b/admin/tool/lp/amd/build/module_navigation.min.js.map
index 6b1405383eb..adddb1a552d 100644
--- a/admin/tool/lp/amd/build/module_navigation.min.js.map
+++ b/admin/tool/lp/amd/build/module_navigation.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/module_navigation.js"],"names":["define","$","ModuleNavigation","moduleSelector","baseUrl","courseId","moduleId","_baseUrl","_moduleId","_courseId","on","_moduleChanged","bind","prototype","e","newModuleId","target","val","queryStr","document","location"],"mappings":"AAuBAA,OAAM,6BAAC,CAAC,QAAD,CAAD,CAAa,SAASC,CAAT,CAAY,CAW3B,GAAIC,CAAAA,CAAgB,CAAG,SAASC,CAAT,CAAyBC,CAAzB,CAAkCC,CAAlC,CAA4CC,CAA5C,CAAsD,CACzE,KAAKC,QAAL,CAAgBH,CAAhB,CACA,KAAKI,SAAL,CAAiBF,CAAjB,CACA,KAAKG,SAAL,CAAiBJ,CAAjB,CAEAJ,CAAC,CAACE,CAAD,CAAD,CAAkBO,EAAlB,CAAqB,QAArB,CAA+B,KAAKC,cAAL,CAAoBC,IAApB,CAAyB,IAAzB,CAA/B,CACH,CAND,CAcAV,CAAgB,CAACW,SAAjB,CAA2BF,cAA3B,CAA4C,SAASG,CAAT,CAAY,IAChDC,CAAAA,CAAW,CAAGd,CAAC,CAACa,CAAC,CAACE,MAAH,CAAD,CAAYC,GAAZ,EADkC,CAEhDC,CAAQ,CAAG,QAAUH,CAAV,CAAwB,YAAxB,CAAuC,KAAKN,SAFP,CAGpDU,QAAQ,CAACC,QAAT,CAAoB,KAAKb,QAAL,CAAgBW,CACvC,CAJD,CAOAhB,CAAgB,CAACW,SAAjB,CAA2BJ,SAA3B,CAAuC,IAAvC,CAEAP,CAAgB,CAACW,SAAjB,CAA2BL,SAA3B,CAAuC,IAAvC,CAEAN,CAAgB,CAACW,SAAjB,CAA2BN,QAA3B,CAAsC,IAAtC,CAEA,MAAOL,CAAAA,CACV,CAvCK,CAAN","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 .\n\n/**\n * Module to navigation between users in a course.\n *\n * @module tool_lp/module_navigation\n * @copyright 2019 Damyon Wiese\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function($) {\n\n /**\n * ModuleNavigation\n *\n * @class tool_lp/module_navigation\n * @param {String} moduleSelector The selector of the module element.\n * @param {String} baseUrl The base url for the page (no params).\n * @param {Number} courseId The course id\n * @param {Number} moduleId The activity module (filter)\n */\n var ModuleNavigation = function(moduleSelector, baseUrl, courseId, moduleId) {\n this._baseUrl = baseUrl;\n this._moduleId = moduleId;\n this._courseId = courseId;\n\n $(moduleSelector).on('change', this._moduleChanged.bind(this));\n };\n\n /**\n * The module was changed in the select list.\n *\n * @method _moduleChanged\n * @param {Event} e the event\n */\n ModuleNavigation.prototype._moduleChanged = function(e) {\n var newModuleId = $(e.target).val();\n var queryStr = '?mod=' + newModuleId + '&courseid=' + this._courseId;\n document.location = this._baseUrl + queryStr;\n };\n\n /** @property {Number} The id of the course. */\n ModuleNavigation.prototype._courseId = null;\n /** @property {Number} The id of the module. */\n ModuleNavigation.prototype._moduleId = null;\n /** @property {String} Plugin base url. */\n ModuleNavigation.prototype._baseUrl = null;\n\n return ModuleNavigation;\n});\n"],"file":"module_navigation.min.js"}
\ No newline at end of file
+{"version":3,"file":"module_navigation.min.js","sources":["../src/module_navigation.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 .\n\n/**\n * Module to navigation between users in a course.\n *\n * @module tool_lp/module_navigation\n * @copyright 2019 Damyon Wiese\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function($) {\n\n /**\n * ModuleNavigation\n *\n * @class tool_lp/module_navigation\n * @param {String} moduleSelector The selector of the module element.\n * @param {String} baseUrl The base url for the page (no params).\n * @param {Number} courseId The course id\n * @param {Number} moduleId The activity module (filter)\n */\n var ModuleNavigation = function(moduleSelector, baseUrl, courseId, moduleId) {\n this._baseUrl = baseUrl;\n this._moduleId = moduleId;\n this._courseId = courseId;\n\n $(moduleSelector).on('change', this._moduleChanged.bind(this));\n };\n\n /**\n * The module was changed in the select list.\n *\n * @method _moduleChanged\n * @param {Event} e the event\n */\n ModuleNavigation.prototype._moduleChanged = function(e) {\n var newModuleId = $(e.target).val();\n var queryStr = '?mod=' + newModuleId + '&courseid=' + this._courseId;\n document.location = this._baseUrl + queryStr;\n };\n\n /** @property {Number} The id of the course. */\n ModuleNavigation.prototype._courseId = null;\n /** @property {Number} The id of the module. */\n ModuleNavigation.prototype._moduleId = null;\n /** @property {String} Plugin base url. */\n ModuleNavigation.prototype._baseUrl = null;\n\n return ModuleNavigation;\n});\n"],"names":["define","$","ModuleNavigation","moduleSelector","baseUrl","courseId","moduleId","_baseUrl","_moduleId","_courseId","on","this","_moduleChanged","bind","prototype","e","queryStr","target","val","document","location"],"mappings":";;;;;;;AAuBAA,mCAAO,CAAC,WAAW,SAASC,OAWpBC,iBAAmB,SAASC,eAAgBC,QAASC,SAAUC,eAC1DC,SAAWH,aACXI,UAAYF,cACZG,UAAYJ,SAEjBJ,EAAEE,gBAAgBO,GAAG,SAAUC,KAAKC,eAAeC,KAAKF,eAS5DT,iBAAiBY,UAAUF,eAAiB,SAASG,OAE7CC,SAAW,QADGf,EAAEc,EAAEE,QAAQC,MACS,aAAeP,KAAKF,UAC3DU,SAASC,SAAWT,KAAKJ,SAAWS,UAIxCd,iBAAiBY,UAAUL,UAAY,KAEvCP,iBAAiBY,UAAUN,UAAY,KAEvCN,iBAAiBY,UAAUP,SAAW,KAE/BL"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/parentcompetency_form.min.js b/admin/tool/lp/amd/build/parentcompetency_form.min.js
index 87e8535bdcf..916755eeab3 100644
--- a/admin/tool/lp/amd/build/parentcompetency_form.min.js
+++ b/admin/tool/lp/amd/build/parentcompetency_form.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/parentcompetency_form",["jquery","core/ajax","core/str","tool_lp/competencypicker","core/templates","core/notification"],function(a,b,c,d,e,f){var g=function(a,b,c,d,e){this.buttonSelector=a;this.inputHiddenSelector=b;this.staticElementSelector=c;this.frameworkId=d;this.pageContextId=e;this.registerEvents()};g.prototype.buttonSelector=null;g.prototype.inputHiddenSelector=null;g.prototype.staticElementSelector=null;g.prototype.frameworkId=null;g.prototype.pageContextId=null;g.prototype.setParent=function(d){var e=this;if(0!==d.competencyId){b.call([{methodname:"core_competency_read_competency",args:{id:d.competencyId}}])[0].done(function(b){a(e.staticElementSelector).html(b.shortname);a(e.inputHiddenSelector).val(b.id)}).fail(f.exception)}else{c.get_string("competencyframeworkroot","tool_lp").then(function(b){a(e.staticElementSelector).html(b);a(e.inputHiddenSelector).val(d.competencyId)}).fail(f.exception)}};g.prototype.registerEvents=function(){var b=this;a(b.buttonSelector).on("click",function(a){a.preventDefault();var c=new d(b.pageContextId,b.frameworkId,"self",!1);c._render=function(){var a=this;return a._preRender().then(function(){var b={competencies:a._competencies,framework:a._getFramework(a._frameworkId),frameworks:a._frameworks,search:a._searchText,singleFramework:a._singleFramework};return e.render("tool_lp/competency_picker_competencyform",b)})};c.on("save",function(a,c){b.setParent(c)});c.display()})};return{init:function init(a,b,c,d,e){new g(a,b,c,d,e)}}});
-//# sourceMappingURL=parentcompetency_form.min.js.map
+/**
+ * Handle selecting parent competency in competency form.
+ *
+ * @module tool_lp/parentcompetency_form
+ * @copyright 2015 Issam Taboubi
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/parentcompetency_form",["jquery","core/ajax","core/str","tool_lp/competencypicker","core/templates","core/notification"],(function($,ajax,Str,Picker,Templates,Notification){var ParentCompetencyForm=function(buttonSelector,inputHiddenSelector,staticElementSelector,frameworkId,pageContextId){this.buttonSelector=buttonSelector,this.inputHiddenSelector=inputHiddenSelector,this.staticElementSelector=staticElementSelector,this.frameworkId=frameworkId,this.pageContextId=pageContextId,this.registerEvents()};return ParentCompetencyForm.prototype.buttonSelector=null,ParentCompetencyForm.prototype.inputHiddenSelector=null,ParentCompetencyForm.prototype.staticElementSelector=null,ParentCompetencyForm.prototype.frameworkId=null,ParentCompetencyForm.prototype.pageContextId=null,ParentCompetencyForm.prototype.setParent=function(data){var self=this;0!==data.competencyId?ajax.call([{methodname:"core_competency_read_competency",args:{id:data.competencyId}}])[0].done((function(competency){$(self.staticElementSelector).html(competency.shortname),$(self.inputHiddenSelector).val(competency.id)})).fail(Notification.exception):Str.get_string("competencyframeworkroot","tool_lp").then((function(rootframework){$(self.staticElementSelector).html(rootframework),$(self.inputHiddenSelector).val(data.competencyId)})).fail(Notification.exception)},ParentCompetencyForm.prototype.registerEvents=function(){var self=this;$(self.buttonSelector).on("click",(function(e){e.preventDefault();var picker=new Picker(self.pageContextId,self.frameworkId,"self",!1);picker._render=function(){var self=this;return self._preRender().then((function(){var context={competencies:self._competencies,framework:self._getFramework(self._frameworkId),frameworks:self._frameworks,search:self._searchText,singleFramework:self._singleFramework};return Templates.render("tool_lp/competency_picker_competencyform",context)}))},picker.on("save",(function(e,data){self.setParent(data)})),picker.display()}))},{init:function(buttonSelector,inputSelector,staticElementSelector,frameworkId,pageContextId){new ParentCompetencyForm(buttonSelector,inputSelector,staticElementSelector,frameworkId,pageContextId)}}}));
+
+//# sourceMappingURL=parentcompetency_form.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/parentcompetency_form.min.js.map b/admin/tool/lp/amd/build/parentcompetency_form.min.js.map
index df3600bea00..0b2c3238c2b 100644
--- a/admin/tool/lp/amd/build/parentcompetency_form.min.js.map
+++ b/admin/tool/lp/amd/build/parentcompetency_form.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/parentcompetency_form.js"],"names":["define","$","ajax","Str","Picker","Templates","Notification","ParentCompetencyForm","buttonSelector","inputHiddenSelector","staticElementSelector","frameworkId","pageContextId","registerEvents","prototype","setParent","data","self","competencyId","call","methodname","args","id","done","competency","html","shortname","val","fail","exception","get_string","then","rootframework","on","e","preventDefault","picker","_render","_preRender","context","competencies","_competencies","framework","_getFramework","_frameworkId","frameworks","_frameworks","search","_searchText","singleFramework","_singleFramework","render","display","init","inputSelector"],"mappings":"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","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 .\n\n/**\n * Handle selecting parent competency in competency form.\n *\n * @module tool_lp/parentcompetency_form\n * @copyright 2015 Issam Taboubi \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/str', 'tool_lp/competencypicker', 'core/templates', 'core/notification'],\n function($, ajax, Str, Picker, Templates, Notification) {\n\n /**\n * Parent Competency Form object.\n * @param {String} buttonSelector The parent competency button selector.\n * @param {String} inputHiddenSelector The hidden input field selector.\n * @param {String} staticElementSelector The static element displaying the parent competency.\n * @param {Number} frameworkId The competency framework ID.\n * @param {Number} pageContextId The page context ID.\n */\n var ParentCompetencyForm = function(buttonSelector,\n inputHiddenSelector,\n staticElementSelector,\n frameworkId,\n pageContextId) {\n this.buttonSelector = buttonSelector;\n this.inputHiddenSelector = inputHiddenSelector;\n this.staticElementSelector = staticElementSelector;\n this.frameworkId = frameworkId;\n this.pageContextId = pageContextId;\n\n // Register the events.\n this.registerEvents();\n };\n\n /** @var {String} The parent competency button selector. */\n ParentCompetencyForm.prototype.buttonSelector = null;\n /** @var {String} The hidden input field selector. */\n ParentCompetencyForm.prototype.inputHiddenSelector = null;\n /** @var {String} The static element displaying the parent competency. */\n ParentCompetencyForm.prototype.staticElementSelector = null;\n /** @var {Number} The competency framework ID. */\n ParentCompetencyForm.prototype.frameworkId = null;\n /** @var {Number} The page context ID. */\n ParentCompetencyForm.prototype.pageContextId = null;\n\n /**\n * Set the parent competency in the competency form.\n *\n * @param {Object} data Data containing selected competency.\n * @method setParent\n */\n ParentCompetencyForm.prototype.setParent = function(data) {\n var self = this;\n\n if (data.competencyId !== 0) {\n ajax.call([\n {methodname: 'core_competency_read_competency', args: {\n id: data.competencyId\n }}\n ])[0].done(function(competency) {\n $(self.staticElementSelector).html(competency.shortname);\n $(self.inputHiddenSelector).val(competency.id);\n }).fail(Notification.exception);\n } else {\n // Root of competency framework selected.\n Str.get_string('competencyframeworkroot', 'tool_lp').then(function(rootframework) {\n $(self.staticElementSelector).html(rootframework);\n $(self.inputHiddenSelector).val(data.competencyId);\n return;\n }).fail(Notification.exception);\n }\n };\n\n /**\n * Register the events of parent competency button click.\n *\n * @method registerEvents\n */\n ParentCompetencyForm.prototype.registerEvents = function() {\n var self = this;\n\n // Event on edit parent button.\n $(self.buttonSelector).on('click', function(e) {\n e.preventDefault();\n\n var picker = new Picker(self.pageContextId, self.frameworkId, 'self', false);\n\n // Override the render method to make framework selectable.\n picker._render = function() {\n var self = this;\n return self._preRender().then(function() {\n var context = {\n competencies: self._competencies,\n framework: self._getFramework(self._frameworkId),\n frameworks: self._frameworks,\n search: self._searchText,\n singleFramework: self._singleFramework,\n };\n\n return Templates.render('tool_lp/competency_picker_competencyform', context);\n });\n };\n\n // On selected competency.\n picker.on('save', function(e, data) {\n self.setParent(data);\n });\n\n picker.display();\n });\n };\n\n return {\n\n /**\n * Main initialisation.\n * @param {String} buttonSelector The parent competency button selector.\n * @param {String} inputSelector The hidden input field selector.\n * @param {String} staticElementSelector The static element displaying the parent competency.\n * @param {Number} frameworkId The competency framework ID.\n * @param {Number} pageContextId The page context ID.\n * @method init\n */\n init: function(buttonSelector,\n inputSelector,\n staticElementSelector,\n frameworkId,\n pageContextId) {\n // Create instance.\n new ParentCompetencyForm(buttonSelector,\n inputSelector,\n staticElementSelector,\n frameworkId,\n pageContextId);\n }\n };\n});\n"],"file":"parentcompetency_form.min.js"}
\ No newline at end of file
+{"version":3,"file":"parentcompetency_form.min.js","sources":["../src/parentcompetency_form.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 .\n\n/**\n * Handle selecting parent competency in competency form.\n *\n * @module tool_lp/parentcompetency_form\n * @copyright 2015 Issam Taboubi \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/str', 'tool_lp/competencypicker', 'core/templates', 'core/notification'],\n function($, ajax, Str, Picker, Templates, Notification) {\n\n /**\n * Parent Competency Form object.\n * @param {String} buttonSelector The parent competency button selector.\n * @param {String} inputHiddenSelector The hidden input field selector.\n * @param {String} staticElementSelector The static element displaying the parent competency.\n * @param {Number} frameworkId The competency framework ID.\n * @param {Number} pageContextId The page context ID.\n */\n var ParentCompetencyForm = function(buttonSelector,\n inputHiddenSelector,\n staticElementSelector,\n frameworkId,\n pageContextId) {\n this.buttonSelector = buttonSelector;\n this.inputHiddenSelector = inputHiddenSelector;\n this.staticElementSelector = staticElementSelector;\n this.frameworkId = frameworkId;\n this.pageContextId = pageContextId;\n\n // Register the events.\n this.registerEvents();\n };\n\n /** @var {String} The parent competency button selector. */\n ParentCompetencyForm.prototype.buttonSelector = null;\n /** @var {String} The hidden input field selector. */\n ParentCompetencyForm.prototype.inputHiddenSelector = null;\n /** @var {String} The static element displaying the parent competency. */\n ParentCompetencyForm.prototype.staticElementSelector = null;\n /** @var {Number} The competency framework ID. */\n ParentCompetencyForm.prototype.frameworkId = null;\n /** @var {Number} The page context ID. */\n ParentCompetencyForm.prototype.pageContextId = null;\n\n /**\n * Set the parent competency in the competency form.\n *\n * @param {Object} data Data containing selected competency.\n * @method setParent\n */\n ParentCompetencyForm.prototype.setParent = function(data) {\n var self = this;\n\n if (data.competencyId !== 0) {\n ajax.call([\n {methodname: 'core_competency_read_competency', args: {\n id: data.competencyId\n }}\n ])[0].done(function(competency) {\n $(self.staticElementSelector).html(competency.shortname);\n $(self.inputHiddenSelector).val(competency.id);\n }).fail(Notification.exception);\n } else {\n // Root of competency framework selected.\n Str.get_string('competencyframeworkroot', 'tool_lp').then(function(rootframework) {\n $(self.staticElementSelector).html(rootframework);\n $(self.inputHiddenSelector).val(data.competencyId);\n return;\n }).fail(Notification.exception);\n }\n };\n\n /**\n * Register the events of parent competency button click.\n *\n * @method registerEvents\n */\n ParentCompetencyForm.prototype.registerEvents = function() {\n var self = this;\n\n // Event on edit parent button.\n $(self.buttonSelector).on('click', function(e) {\n e.preventDefault();\n\n var picker = new Picker(self.pageContextId, self.frameworkId, 'self', false);\n\n // Override the render method to make framework selectable.\n picker._render = function() {\n var self = this;\n return self._preRender().then(function() {\n var context = {\n competencies: self._competencies,\n framework: self._getFramework(self._frameworkId),\n frameworks: self._frameworks,\n search: self._searchText,\n singleFramework: self._singleFramework,\n };\n\n return Templates.render('tool_lp/competency_picker_competencyform', context);\n });\n };\n\n // On selected competency.\n picker.on('save', function(e, data) {\n self.setParent(data);\n });\n\n picker.display();\n });\n };\n\n return {\n\n /**\n * Main initialisation.\n * @param {String} buttonSelector The parent competency button selector.\n * @param {String} inputSelector The hidden input field selector.\n * @param {String} staticElementSelector The static element displaying the parent competency.\n * @param {Number} frameworkId The competency framework ID.\n * @param {Number} pageContextId The page context ID.\n * @method init\n */\n init: function(buttonSelector,\n inputSelector,\n staticElementSelector,\n frameworkId,\n pageContextId) {\n // Create instance.\n new ParentCompetencyForm(buttonSelector,\n inputSelector,\n staticElementSelector,\n frameworkId,\n pageContextId);\n }\n };\n});\n"],"names":["define","$","ajax","Str","Picker","Templates","Notification","ParentCompetencyForm","buttonSelector","inputHiddenSelector","staticElementSelector","frameworkId","pageContextId","registerEvents","prototype","setParent","data","self","this","competencyId","call","methodname","args","id","done","competency","html","shortname","val","fail","exception","get_string","then","rootframework","on","e","preventDefault","picker","_render","_preRender","context","competencies","_competencies","framework","_getFramework","_frameworkId","frameworks","_frameworks","search","_searchText","singleFramework","_singleFramework","render","display","init","inputSelector"],"mappings":";;;;;;;AAsBAA,uCAAO,CAAC,SAAU,YAAa,WAAY,2BAA4B,iBAAkB,sBACrF,SAASC,EAAGC,KAAMC,IAAKC,OAAQC,UAAWC,kBAUtCC,qBAAuB,SAASC,eACAC,oBACAC,sBACAC,YACAC,oBAC3BJ,eAAiBA,oBACjBC,oBAAsBA,yBACtBC,sBAAwBA,2BACxBC,YAAcA,iBACdC,cAAgBA,mBAGhBC,yBAITN,qBAAqBO,UAAUN,eAAiB,KAEhDD,qBAAqBO,UAAUL,oBAAsB,KAErDF,qBAAqBO,UAAUJ,sBAAwB,KAEvDH,qBAAqBO,UAAUH,YAAc,KAE7CJ,qBAAqBO,UAAUF,cAAgB,KAQ/CL,qBAAqBO,UAAUC,UAAY,SAASC,UAC5CC,KAAOC,KAEe,IAAtBF,KAAKG,aACLjB,KAAKkB,KAAK,CACN,CAACC,WAAY,kCAAmCC,KAAM,CAClDC,GAAIP,KAAKG,iBAEd,GAAGK,MAAK,SAASC,YAChBxB,EAAEgB,KAAKP,uBAAuBgB,KAAKD,WAAWE,WAC9C1B,EAAEgB,KAAKR,qBAAqBmB,IAAIH,WAAWF,OAC5CM,KAAKvB,aAAawB,WAGrB3B,IAAI4B,WAAW,0BAA2B,WAAWC,MAAK,SAASC,eAC/DhC,EAAEgB,KAAKP,uBAAuBgB,KAAKO,eACnChC,EAAEgB,KAAKR,qBAAqBmB,IAAIZ,KAAKG,iBAEtCU,KAAKvB,aAAawB,YAS7BvB,qBAAqBO,UAAUD,eAAiB,eACxCI,KAAOC,KAGXjB,EAAEgB,KAAKT,gBAAgB0B,GAAG,SAAS,SAASC,GACxCA,EAAEC,qBAEEC,OAAS,IAAIjC,OAAOa,KAAKL,cAAeK,KAAKN,YAAa,QAAQ,GAGtE0B,OAAOC,QAAU,eACTrB,KAAOC,YACJD,KAAKsB,aAAaP,MAAK,eACtBQ,QAAU,CACVC,aAAcxB,KAAKyB,cACnBC,UAAW1B,KAAK2B,cAAc3B,KAAK4B,cACnCC,WAAY7B,KAAK8B,YACjBC,OAAQ/B,KAAKgC,YACbC,gBAAiBjC,KAAKkC,yBAGnB9C,UAAU+C,OAAO,2CAA4CZ,aAK5EH,OAAOH,GAAG,QAAQ,SAASC,EAAGnB,MAC1BC,KAAKF,UAAUC,SAGnBqB,OAAOgB,cAIR,CAWHC,KAAM,SAAS9C,eACC+C,cACA7C,sBACAC,YACAC,mBAERL,qBAAqBC,eACD+C,cACA7C,sBACAC,YACAC"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/planactions.min.js b/admin/tool/lp/amd/build/planactions.min.js
index 4edcfa09f06..009eb0dd64f 100644
--- a/admin/tool/lp/amd/build/planactions.min.js
+++ b/admin/tool/lp/amd/build/planactions.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/planactions",["jquery","core/templates","core/ajax","core/notification","core/str","tool_lp/menubar","tool_lp/dialogue"],function(a,b,c,d,e,f,g){var h=function(a){this._type=a;if("plan"===a){this._region="[data-region=\"plan-page\"]";this._planNode="[data-region=\"plan-page\"]";this._template="tool_lp/plan_page";this._contextMethod="tool_lp_data_for_plan_page"}else if("plans"===a){this._region="[data-region=\"plans\"]";this._planNode="[data-region=\"plan-node\"]";this._template="tool_lp/plans_page";this._contextMethod="tool_lp_data_for_plans_page"}else{throw new TypeError("Unexpected type.")}};h.prototype._contextMethod=null;h.prototype._planNode=null;h.prototype._region=null;h.prototype._template=null;h.prototype._type=null;h.prototype._getContextArgs=function(a){var b=this,c={};if("plan"===b._type){c={planid:a.id}}else if("plans"===b._type){c={userid:a.userid}}return c};h.prototype.refresh=function(b){var c=this._findPlanData(a(b));this._callAndRefresh([],c)};h.prototype._renderView=function(c){var d=this;return b.render(d._template,c).then(function(c,e){a(d._region).replaceWith(c);b.runTemplateJS(e)})};h.prototype._callAndRefresh=function(b,e){var f="tool_lp/planactions:_callAndRefresh-"+Math.floor(Math.random()*Math.floor(1e3));M.util.js_pending(f);var g=this;b.push({methodname:g._contextMethod,args:g._getContextArgs(e)});return a.when.apply(a,c.call(b)).then(function(){return g._renderView(arguments[arguments.length-1])}).fail(d.exception).always(function(){return M.util.js_complete(f)})};h.prototype._doDelete=function(a){var b=this,c=[{methodname:"core_competency_delete_plan",args:{id:a.id}}];b._callAndRefresh(c,a)};h.prototype.deletePlan=function(a){var b=this,f;f=c.call([{methodname:"core_competency_read_plan",args:{id:a.id}}]);f[0].done(function(c){e.get_strings([{key:"confirm",component:"moodle"},{key:"deleteplan",component:"tool_lp",param:c.name},{key:"delete",component:"moodle"},{key:"cancel",component:"moodle"}]).done(function(c){d.confirm(c[0],c[1],c[2],c[3],function(){b._doDelete(a)})}).fail(d.exception)}).fail(d.exception)};h.prototype._doReopenPlan=function(a){var b=this,c=[{methodname:"core_competency_reopen_plan",args:{planid:a.id}}];b._callAndRefresh(c,a)};h.prototype.reopenPlan=function(a){var b=this,f=c.call([{methodname:"core_competency_read_plan",args:{id:a.id}}]);f[0].done(function(c){e.get_strings([{key:"confirm",component:"moodle"},{key:"reopenplanconfirm",component:"tool_lp",param:c.name},{key:"reopenplan",component:"tool_lp"},{key:"cancel",component:"moodle"}]).done(function(c){d.confirm(c[0],c[1],c[2],c[3],function(){b._doReopenPlan(a)})}).fail(d.exception)}).fail(d.exception)};h.prototype._doCompletePlan=function(a){var b=this,c=[{methodname:"core_competency_complete_plan",args:{planid:a.id}}];b._callAndRefresh(c,a)};h.prototype.completePlan=function(a){var b=this,f=c.call([{methodname:"core_competency_read_plan",args:{id:a.id}}]);f[0].done(function(c){e.get_strings([{key:"confirm",component:"moodle"},{key:"completeplanconfirm",component:"tool_lp",param:c.name},{key:"completeplan",component:"tool_lp"},{key:"cancel",component:"moodle"}]).done(function(c){d.confirm(c[0],c[1],c[2],c[3],function(){b._doCompletePlan(a)})}).fail(d.exception)}).fail(d.exception)};h.prototype._doUnlinkPlan=function(a){var b=this,c=[{methodname:"core_competency_unlink_plan_from_template",args:{planid:a.id}}];b._callAndRefresh(c,a)};h.prototype.unlinkPlan=function(a){var b=this,f=c.call([{methodname:"core_competency_read_plan",args:{id:a.id}}]);f[0].done(function(c){e.get_strings([{key:"confirm",component:"moodle"},{key:"unlinkplantemplateconfirm",component:"tool_lp",param:c.name},{key:"unlinkplantemplate",component:"tool_lp"},{key:"cancel",component:"moodle"}]).done(function(c){d.confirm(c[0],c[1],c[2],c[3],function(){b._doUnlinkPlan(a)})}).fail(d.exception)}).fail(d.exception)};h.prototype._doRequestReview=function(a){var b=[{methodname:"core_competency_plan_request_review",args:{id:a.id}}];this._callAndRefresh(b,a)};h.prototype.requestReview=function(a){this._doRequestReview(a)};h.prototype._doCancelReviewRequest=function(a){var b=[{methodname:"core_competency_plan_cancel_review_request",args:{id:a.id}}];this._callAndRefresh(b,a)};h.prototype.cancelReviewRequest=function(a){this._doCancelReviewRequest(a)};h.prototype._doStartReview=function(a){var b=[{methodname:"core_competency_plan_start_review",args:{id:a.id}}];this._callAndRefresh(b,a)};h.prototype.startReview=function(a){this._doStartReview(a)};h.prototype._doStopReview=function(a){var b=[{methodname:"core_competency_plan_stop_review",args:{id:a.id}}];this._callAndRefresh(b,a)};h.prototype.stopReview=function(a){this._doStopReview(a)};h.prototype._doApprove=function(a){var b=[{methodname:"core_competency_approve_plan",args:{id:a.id}}];this._callAndRefresh(b,a)};h.prototype.approve=function(a){this._doApprove(a)};h.prototype._doUnapprove=function(a){var b=[{methodname:"core_competency_unapprove_plan",args:{id:a.id}}];this._callAndRefresh(b,a)};h.prototype.unapprove=function(a){this._doUnapprove(a)};h.prototype._showLinkedCoursesHandler=function(f){f.preventDefault();var h=a(f.target).data("id"),i=c.call([{methodname:"tool_lp_list_courses_using_competency",args:{id:h}}]);i[0].done(function(a){b.render("tool_lp/linked_courses_summary",{courses:a}).done(function(a){e.get_string("linkedcourses","tool_lp").done(function(b){new g(b,a)}).fail(d.exception)}).fail(d.exception)}).fail(d.exception)};h.prototype._eventHandler=function(b,c){c.preventDefault();var d=this._findPlanData(a(c.target));this[b](d)};h.prototype._findPlanData=function(b){var c=b.parentsUntil(a(this._region).parent(),this._planNode),d;if(1!=c.length){throw new Error("The plan node was not located.")}d=c.data();if("undefined"==typeof d||"undefined"==typeof d.id){throw new Error("Plan data could not be found.")}return d};h.prototype.enhanceMenubar=function(a){f.enhance(a,{'[data-action="plan-delete"]':this._eventHandler.bind(this,"deletePlan"),'[data-action="plan-complete"]':this._eventHandler.bind(this,"completePlan"),'[data-action="plan-reopen"]':this._eventHandler.bind(this,"reopenPlan"),'[data-action="plan-unlink"]':this._eventHandler.bind(this,"unlinkPlan"),'[data-action="plan-request-review"]':this._eventHandler.bind(this,"requestReview"),'[data-action="plan-cancel-review-request"]':this._eventHandler.bind(this,"cancelReviewRequest"),'[data-action="plan-start-review"]':this._eventHandler.bind(this,"startReview"),'[data-action="plan-stop-review"]':this._eventHandler.bind(this,"stopReview"),'[data-action="plan-approve"]':this._eventHandler.bind(this,"approve"),'[data-action="plan-unapprove"]':this._eventHandler.bind(this,"unapprove")})};h.prototype.registerEvents=function(){var b=a(this._region);b.find("[data-action=\"plan-delete\"]").click(this._eventHandler.bind(this,"deletePlan"));b.find("[data-action=\"plan-complete\"]").click(this._eventHandler.bind(this,"completePlan"));b.find("[data-action=\"plan-reopen\"]").click(this._eventHandler.bind(this,"reopenPlan"));b.find("[data-action=\"plan-unlink\"]").click(this._eventHandler.bind(this,"unlinkPlan"));b.find("[data-action=\"plan-request-review\"]").click(this._eventHandler.bind(this,"requestReview"));b.find("[data-action=\"plan-cancel-review-request\"]").click(this._eventHandler.bind(this,"cancelReviewRequest"));b.find("[data-action=\"plan-start-review\"]").click(this._eventHandler.bind(this,"startReview"));b.find("[data-action=\"plan-stop-review\"]").click(this._eventHandler.bind(this,"stopReview"));b.find("[data-action=\"plan-approve\"]").click(this._eventHandler.bind(this,"approve"));b.find("[data-action=\"plan-unapprove\"]").click(this._eventHandler.bind(this,"unapprove"));b.find("[data-action=\"find-courses-link\"]").click(this._showLinkedCoursesHandler.bind(this))};return h});
-//# sourceMappingURL=planactions.min.js.map
+/**
+ * Plan actions via ajax.
+ *
+ * @module tool_lp/planactions
+ * @copyright 2015 David Monllao
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/planactions",["jquery","core/templates","core/ajax","core/notification","core/str","tool_lp/menubar","tool_lp/dialogue"],(function($,templates,ajax,notification,str,Menubar,Dialogue){var PlanActions=function(type){if(this._type=type,"plan"===type)this._region='[data-region="plan-page"]',this._planNode='[data-region="plan-page"]',this._template="tool_lp/plan_page",this._contextMethod="tool_lp_data_for_plan_page";else{if("plans"!==type)throw new TypeError("Unexpected type.");this._region='[data-region="plans"]',this._planNode='[data-region="plan-node"]',this._template="tool_lp/plans_page",this._contextMethod="tool_lp_data_for_plans_page"}};return PlanActions.prototype._contextMethod=null,PlanActions.prototype._planNode=null,PlanActions.prototype._region=null,PlanActions.prototype._template=null,PlanActions.prototype._type=null,PlanActions.prototype._getContextArgs=function(planData){var args={};return"plan"===this._type?args={planid:planData.id}:"plans"===this._type&&(args={userid:planData.userid}),args},PlanActions.prototype.refresh=function(selector){var planData=this._findPlanData($(selector));this._callAndRefresh([],planData)},PlanActions.prototype._renderView=function(context){var self=this;return templates.render(self._template,context).then((function(newhtml,newjs){$(self._region).replaceWith(newhtml),templates.runTemplateJS(newjs)}))},PlanActions.prototype._callAndRefresh=function(calls,planData){var callKey="tool_lp/planactions:_callAndRefresh-"+Math.floor(Math.random()*Math.floor(1e3));M.util.js_pending(callKey);var self=this;return calls.push({methodname:self._contextMethod,args:self._getContextArgs(planData)}),$.when.apply($,ajax.call(calls)).then((function(){return self._renderView(arguments[arguments.length-1])})).fail(notification.exception).always((function(){return M.util.js_complete(callKey)}))},PlanActions.prototype._doDelete=function(planData){var calls=[{methodname:"core_competency_delete_plan",args:{id:planData.id}}];this._callAndRefresh(calls,planData)},PlanActions.prototype.deletePlan=function(planData){var self=this;ajax.call([{methodname:"core_competency_read_plan",args:{id:planData.id}}])[0].done((function(plan){str.get_strings([{key:"confirm",component:"moodle"},{key:"deleteplan",component:"tool_lp",param:plan.name},{key:"delete",component:"moodle"},{key:"cancel",component:"moodle"}]).done((function(strings){notification.confirm(strings[0],strings[1],strings[2],strings[3],(function(){self._doDelete(planData)}))})).fail(notification.exception)})).fail(notification.exception)},PlanActions.prototype._doReopenPlan=function(planData){var calls=[{methodname:"core_competency_reopen_plan",args:{planid:planData.id}}];this._callAndRefresh(calls,planData)},PlanActions.prototype.reopenPlan=function(planData){var self=this;ajax.call([{methodname:"core_competency_read_plan",args:{id:planData.id}}])[0].done((function(plan){str.get_strings([{key:"confirm",component:"moodle"},{key:"reopenplanconfirm",component:"tool_lp",param:plan.name},{key:"reopenplan",component:"tool_lp"},{key:"cancel",component:"moodle"}]).done((function(strings){notification.confirm(strings[0],strings[1],strings[2],strings[3],(function(){self._doReopenPlan(planData)}))})).fail(notification.exception)})).fail(notification.exception)},PlanActions.prototype._doCompletePlan=function(planData){var calls=[{methodname:"core_competency_complete_plan",args:{planid:planData.id}}];this._callAndRefresh(calls,planData)},PlanActions.prototype.completePlan=function(planData){var self=this;ajax.call([{methodname:"core_competency_read_plan",args:{id:planData.id}}])[0].done((function(plan){str.get_strings([{key:"confirm",component:"moodle"},{key:"completeplanconfirm",component:"tool_lp",param:plan.name},{key:"completeplan",component:"tool_lp"},{key:"cancel",component:"moodle"}]).done((function(strings){notification.confirm(strings[0],strings[1],strings[2],strings[3],(function(){self._doCompletePlan(planData)}))})).fail(notification.exception)})).fail(notification.exception)},PlanActions.prototype._doUnlinkPlan=function(planData){var calls=[{methodname:"core_competency_unlink_plan_from_template",args:{planid:planData.id}}];this._callAndRefresh(calls,planData)},PlanActions.prototype.unlinkPlan=function(planData){var self=this;ajax.call([{methodname:"core_competency_read_plan",args:{id:planData.id}}])[0].done((function(plan){str.get_strings([{key:"confirm",component:"moodle"},{key:"unlinkplantemplateconfirm",component:"tool_lp",param:plan.name},{key:"unlinkplantemplate",component:"tool_lp"},{key:"cancel",component:"moodle"}]).done((function(strings){notification.confirm(strings[0],strings[1],strings[2],strings[3],(function(){self._doUnlinkPlan(planData)}))})).fail(notification.exception)})).fail(notification.exception)},PlanActions.prototype._doRequestReview=function(planData){var calls=[{methodname:"core_competency_plan_request_review",args:{id:planData.id}}];this._callAndRefresh(calls,planData)},PlanActions.prototype.requestReview=function(planData){this._doRequestReview(planData)},PlanActions.prototype._doCancelReviewRequest=function(planData){var calls=[{methodname:"core_competency_plan_cancel_review_request",args:{id:planData.id}}];this._callAndRefresh(calls,planData)},PlanActions.prototype.cancelReviewRequest=function(planData){this._doCancelReviewRequest(planData)},PlanActions.prototype._doStartReview=function(planData){var calls=[{methodname:"core_competency_plan_start_review",args:{id:planData.id}}];this._callAndRefresh(calls,planData)},PlanActions.prototype.startReview=function(planData){this._doStartReview(planData)},PlanActions.prototype._doStopReview=function(planData){var calls=[{methodname:"core_competency_plan_stop_review",args:{id:planData.id}}];this._callAndRefresh(calls,planData)},PlanActions.prototype.stopReview=function(planData){this._doStopReview(planData)},PlanActions.prototype._doApprove=function(planData){var calls=[{methodname:"core_competency_approve_plan",args:{id:planData.id}}];this._callAndRefresh(calls,planData)},PlanActions.prototype.approve=function(planData){this._doApprove(planData)},PlanActions.prototype._doUnapprove=function(planData){var calls=[{methodname:"core_competency_unapprove_plan",args:{id:planData.id}}];this._callAndRefresh(calls,planData)},PlanActions.prototype.unapprove=function(planData){this._doUnapprove(planData)},PlanActions.prototype._showLinkedCoursesHandler=function(e){e.preventDefault();var competencyid=$(e.target).data("id");ajax.call([{methodname:"tool_lp_list_courses_using_competency",args:{id:competencyid}}])[0].done((function(courses){var context={courses:courses};templates.render("tool_lp/linked_courses_summary",context).done((function(html){str.get_string("linkedcourses","tool_lp").done((function(linkedcourses){new Dialogue(linkedcourses,html)})).fail(notification.exception)})).fail(notification.exception)})).fail(notification.exception)},PlanActions.prototype._eventHandler=function(method,e){e.preventDefault();var data=this._findPlanData($(e.target));this[method](data)},PlanActions.prototype._findPlanData=function(node){var data,parent=node.parentsUntil($(this._region).parent(),this._planNode);if(1!=parent.length)throw new Error("The plan node was not located.");if(void 0===(data=parent.data())||void 0===data.id)throw new Error("Plan data could not be found.");return data},PlanActions.prototype.enhanceMenubar=function(selector){Menubar.enhance(selector,{'[data-action="plan-delete"]':this._eventHandler.bind(this,"deletePlan"),'[data-action="plan-complete"]':this._eventHandler.bind(this,"completePlan"),'[data-action="plan-reopen"]':this._eventHandler.bind(this,"reopenPlan"),'[data-action="plan-unlink"]':this._eventHandler.bind(this,"unlinkPlan"),'[data-action="plan-request-review"]':this._eventHandler.bind(this,"requestReview"),'[data-action="plan-cancel-review-request"]':this._eventHandler.bind(this,"cancelReviewRequest"),'[data-action="plan-start-review"]':this._eventHandler.bind(this,"startReview"),'[data-action="plan-stop-review"]':this._eventHandler.bind(this,"stopReview"),'[data-action="plan-approve"]':this._eventHandler.bind(this,"approve"),'[data-action="plan-unapprove"]':this._eventHandler.bind(this,"unapprove")})},PlanActions.prototype.registerEvents=function(){var wrapper=$(this._region);wrapper.find('[data-action="plan-delete"]').click(this._eventHandler.bind(this,"deletePlan")),wrapper.find('[data-action="plan-complete"]').click(this._eventHandler.bind(this,"completePlan")),wrapper.find('[data-action="plan-reopen"]').click(this._eventHandler.bind(this,"reopenPlan")),wrapper.find('[data-action="plan-unlink"]').click(this._eventHandler.bind(this,"unlinkPlan")),wrapper.find('[data-action="plan-request-review"]').click(this._eventHandler.bind(this,"requestReview")),wrapper.find('[data-action="plan-cancel-review-request"]').click(this._eventHandler.bind(this,"cancelReviewRequest")),wrapper.find('[data-action="plan-start-review"]').click(this._eventHandler.bind(this,"startReview")),wrapper.find('[data-action="plan-stop-review"]').click(this._eventHandler.bind(this,"stopReview")),wrapper.find('[data-action="plan-approve"]').click(this._eventHandler.bind(this,"approve")),wrapper.find('[data-action="plan-unapprove"]').click(this._eventHandler.bind(this,"unapprove")),wrapper.find('[data-action="find-courses-link"]').click(this._showLinkedCoursesHandler.bind(this))},PlanActions}));
+
+//# sourceMappingURL=planactions.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/planactions.min.js.map b/admin/tool/lp/amd/build/planactions.min.js.map
index 5d24458ce4f..9ef56027339 100644
--- a/admin/tool/lp/amd/build/planactions.min.js.map
+++ b/admin/tool/lp/amd/build/planactions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/planactions.js"],"names":["define","$","templates","ajax","notification","str","Menubar","Dialogue","PlanActions","type","_type","_region","_planNode","_template","_contextMethod","TypeError","prototype","_getContextArgs","planData","self","args","planid","id","userid","refresh","selector","_findPlanData","_callAndRefresh","_renderView","context","render","then","newhtml","newjs","replaceWith","runTemplateJS","calls","callKey","Math","floor","random","M","util","js_pending","push","methodname","when","apply","call","arguments","length","fail","exception","always","js_complete","_doDelete","deletePlan","requests","done","plan","get_strings","key","component","param","name","strings","confirm","_doReopenPlan","reopenPlan","_doCompletePlan","completePlan","_doUnlinkPlan","unlinkPlan","_doRequestReview","requestReview","_doCancelReviewRequest","cancelReviewRequest","_doStartReview","startReview","_doStopReview","stopReview","_doApprove","approve","_doUnapprove","unapprove","_showLinkedCoursesHandler","e","preventDefault","competencyid","target","data","courses","html","get_string","linkedcourses","_eventHandler","method","node","parent","parentsUntil","Error","enhanceMenubar","enhance","bind","registerEvents","wrapper","find","click"],"mappings":"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","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 .\n\n/**\n * Plan actions via ajax.\n *\n * @module tool_lp/planactions\n * @copyright 2015 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/templates',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'tool_lp/menubar',\n 'tool_lp/dialogue'],\n function($, templates, ajax, notification, str, Menubar, Dialogue) {\n\n /**\n * PlanActions class.\n *\n * Note that presently this cannot be instantiated more than once per page.\n *\n * @param {String} type The type of page we're in.\n */\n var PlanActions = function(type) {\n this._type = type;\n\n if (type === 'plan') {\n // This is the page to view one plan.\n this._region = '[data-region=\"plan-page\"]';\n this._planNode = '[data-region=\"plan-page\"]';\n this._template = 'tool_lp/plan_page';\n this._contextMethod = 'tool_lp_data_for_plan_page';\n\n } else if (type === 'plans') {\n // This is the page to view a list of plans.\n this._region = '[data-region=\"plans\"]';\n this._planNode = '[data-region=\"plan-node\"]';\n this._template = 'tool_lp/plans_page';\n this._contextMethod = 'tool_lp_data_for_plans_page';\n\n } else {\n throw new TypeError('Unexpected type.');\n }\n };\n\n /** @property {String} Ajax method to fetch the page data from. */\n PlanActions.prototype._contextMethod = null;\n /** @property {String} Selector to find the node describing the plan. */\n PlanActions.prototype._planNode = null;\n /** @property {String} Selector mapping to the region to update. Usually similar to wrapper. */\n PlanActions.prototype._region = null;\n /** @property {String} Name of the template used to render the region. */\n PlanActions.prototype._template = null;\n /** @property {String} Type of page/region we're in. */\n PlanActions.prototype._type = null;\n\n /**\n * Resolve the arguments to refresh the region.\n *\n * @param {Object} planData Plan data from plan node.\n * @return {Object} List of arguments.\n */\n PlanActions.prototype._getContextArgs = function(planData) {\n var self = this,\n args = {};\n\n if (self._type === 'plan') {\n args = {\n planid: planData.id\n };\n\n } else if (self._type === 'plans') {\n args = {\n userid: planData.userid\n };\n }\n\n return args;\n };\n\n /**\n * Refresh the plan view.\n *\n * This is useful when you only want to refresh the view.\n *\n * @param {String} selector The node to search the plan data from.\n */\n PlanActions.prototype.refresh = function(selector) {\n var planData = this._findPlanData($(selector));\n this._callAndRefresh([], planData);\n };\n\n /**\n * Callback to render the region template.\n *\n * @param {Object} context The context for the template.\n * @return {Promise}\n */\n PlanActions.prototype._renderView = function(context) {\n var self = this;\n return templates.render(self._template, context)\n .then(function(newhtml, newjs) {\n $(self._region).replaceWith(newhtml);\n templates.runTemplateJS(newjs);\n return;\n });\n };\n\n /**\n * Call multiple ajax methods, and refresh.\n *\n * @param {Array} calls List of Ajax calls.\n * @param {Object} planData Plan data from plan node.\n * @return {Promise}\n */\n PlanActions.prototype._callAndRefresh = function(calls, planData) {\n // Because this function causes a refresh, we must track the JS completion from start to finish to prevent\n // stale reference issues in Behat.\n var callKey = 'tool_lp/planactions:_callAndRefresh-' + Math.floor(Math.random() * Math.floor(1000));\n M.util.js_pending(callKey);\n\n var self = this;\n calls.push({\n methodname: self._contextMethod,\n args: self._getContextArgs(planData)\n });\n\n // Apply all the promises, and refresh when the last one is resolved.\n return $.when.apply($, ajax.call(calls))\n .then(function() {\n return self._renderView(arguments[arguments.length - 1]);\n })\n .fail(notification.exception)\n .always(function() {\n return M.util.js_complete(callKey);\n });\n };\n\n /**\n * Delete a plan and reload the region.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype._doDelete = function(planData) {\n var self = this,\n calls = [{\n methodname: 'core_competency_delete_plan',\n args: {id: planData.id}\n }];\n self._callAndRefresh(calls, planData);\n };\n\n /**\n * Delete a plan.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype.deletePlan = function(planData) {\n var self = this,\n requests;\n\n requests = ajax.call([{\n methodname: 'core_competency_read_plan',\n args: {id: planData.id}\n }]);\n\n requests[0].done(function(plan) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'deleteplan', component: 'tool_lp', param: plan.name},\n {key: 'delete', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Delete plan X?\n strings[2], // Delete.\n strings[3], // Cancel.\n function() {\n self._doDelete(planData);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n /**\n * Reopen plan and reload the region.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype._doReopenPlan = function(planData) {\n var self = this,\n calls = [{\n methodname: 'core_competency_reopen_plan',\n args: {planid: planData.id}\n }];\n self._callAndRefresh(calls, planData);\n };\n\n /**\n * Reopen a plan.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype.reopenPlan = function(planData) {\n var self = this,\n requests = ajax.call([{\n methodname: 'core_competency_read_plan',\n args: {id: planData.id}\n }]);\n\n requests[0].done(function(plan) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'reopenplanconfirm', component: 'tool_lp', param: plan.name},\n {key: 'reopenplan', component: 'tool_lp'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Reopen plan X?\n strings[2], // Reopen.\n strings[3], // Cancel.\n function() {\n self._doReopenPlan(planData);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n /**\n * Complete plan and reload the region.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype._doCompletePlan = function(planData) {\n var self = this,\n calls = [{\n methodname: 'core_competency_complete_plan',\n args: {planid: planData.id}\n }];\n self._callAndRefresh(calls, planData);\n };\n\n /**\n * Complete a plan process.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype.completePlan = function(planData) {\n var self = this,\n requests = ajax.call([{\n methodname: 'core_competency_read_plan',\n args: {id: planData.id}\n }]);\n\n requests[0].done(function(plan) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'completeplanconfirm', component: 'tool_lp', param: plan.name},\n {key: 'completeplan', component: 'tool_lp'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Complete plan X?\n strings[2], // Complete.\n strings[3], // Cancel.\n function() {\n self._doCompletePlan(planData);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Unlink plan and reload the region.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype._doUnlinkPlan = function(planData) {\n var self = this,\n calls = [{\n methodname: 'core_competency_unlink_plan_from_template',\n args: {planid: planData.id}\n }];\n self._callAndRefresh(calls, planData);\n };\n\n /**\n * Unlink a plan process.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype.unlinkPlan = function(planData) {\n var self = this,\n requests = ajax.call([{\n methodname: 'core_competency_read_plan',\n args: {id: planData.id}\n }]);\n\n requests[0].done(function(plan) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'unlinkplantemplateconfirm', component: 'tool_lp', param: plan.name},\n {key: 'unlinkplantemplate', component: 'tool_lp'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Unlink plan X?\n strings[2], // Unlink.\n strings[3], // Cancel.\n function() {\n self._doUnlinkPlan(planData);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Request review of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method _doRequestReview\n */\n PlanActions.prototype._doRequestReview = function(planData) {\n var calls = [{\n methodname: 'core_competency_plan_request_review',\n args: {\n id: planData.id\n }\n }];\n this._callAndRefresh(calls, planData);\n };\n\n /**\n * Request review of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method requestReview\n */\n PlanActions.prototype.requestReview = function(planData) {\n this._doRequestReview(planData);\n };\n\n /**\n * Cancel review request of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method _doCancelReviewRequest\n */\n PlanActions.prototype._doCancelReviewRequest = function(planData) {\n var calls = [{\n methodname: 'core_competency_plan_cancel_review_request',\n args: {\n id: planData.id\n }\n }];\n this._callAndRefresh(calls, planData);\n };\n\n /**\n * Cancel review request of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method cancelReviewRequest\n */\n PlanActions.prototype.cancelReviewRequest = function(planData) {\n this._doCancelReviewRequest(planData);\n };\n\n /**\n * Start review of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method _doStartReview\n */\n PlanActions.prototype._doStartReview = function(planData) {\n var calls = [{\n methodname: 'core_competency_plan_start_review',\n args: {\n id: planData.id\n }\n }];\n this._callAndRefresh(calls, planData);\n };\n\n /**\n * Start review of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method startReview\n */\n PlanActions.prototype.startReview = function(planData) {\n this._doStartReview(planData);\n };\n\n /**\n * Stop review of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method _doStopReview\n */\n PlanActions.prototype._doStopReview = function(planData) {\n var calls = [{\n methodname: 'core_competency_plan_stop_review',\n args: {\n id: planData.id\n }\n }];\n this._callAndRefresh(calls, planData);\n };\n\n /**\n * Stop review of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method stopReview\n */\n PlanActions.prototype.stopReview = function(planData) {\n this._doStopReview(planData);\n };\n\n /**\n * Approve a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method _doApprove\n */\n PlanActions.prototype._doApprove = function(planData) {\n var calls = [{\n methodname: 'core_competency_approve_plan',\n args: {\n id: planData.id\n }\n }];\n this._callAndRefresh(calls, planData);\n };\n\n /**\n * Approve a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method approve\n */\n PlanActions.prototype.approve = function(planData) {\n this._doApprove(planData);\n };\n\n /**\n * Unapprove a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method _doUnapprove\n */\n PlanActions.prototype._doUnapprove = function(planData) {\n var calls = [{\n methodname: 'core_competency_unapprove_plan',\n args: {\n id: planData.id\n }\n }];\n this._callAndRefresh(calls, planData);\n };\n\n /**\n * Unapprove a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method unapprove\n */\n PlanActions.prototype.unapprove = function(planData) {\n this._doUnapprove(planData);\n };\n\n /**\n * Display list of linked courses on a modal dialogue.\n *\n * @param {Event} e The event.\n */\n PlanActions.prototype._showLinkedCoursesHandler = function(e) {\n e.preventDefault();\n\n var competencyid = $(e.target).data('id');\n var requests = ajax.call([{\n methodname: 'tool_lp_list_courses_using_competency',\n args: {id: competencyid}\n }]);\n\n requests[0].done(function(courses) {\n var context = {\n courses: courses\n };\n templates.render('tool_lp/linked_courses_summary', context).done(function(html) {\n str.get_string('linkedcourses', 'tool_lp').done(function(linkedcourses) {\n new Dialogue(\n linkedcourses, // Title.\n html // The linked courses.\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Plan event handler.\n *\n * @param {String} method The method to call.\n * @param {Event} e The event.\n * @method _eventHandler\n */\n PlanActions.prototype._eventHandler = function(method, e) {\n e.preventDefault();\n var data = this._findPlanData($(e.target));\n this[method](data);\n };\n\n /**\n * Find the plan data from the plan node.\n *\n * @param {Node} node The node to search from.\n * @return {Object} Plan data.\n */\n PlanActions.prototype._findPlanData = function(node) {\n var parent = node.parentsUntil($(this._region).parent(), this._planNode),\n data;\n\n if (parent.length != 1) {\n throw new Error('The plan node was not located.');\n }\n\n data = parent.data();\n if (typeof data === 'undefined' || typeof data.id === 'undefined') {\n throw new Error('Plan data could not be found.');\n }\n\n return data;\n };\n\n /**\n * Enhance a menu bar.\n *\n * @param {String} selector Menubar selector.\n */\n PlanActions.prototype.enhanceMenubar = function(selector) {\n Menubar.enhance(selector, {\n '[data-action=\"plan-delete\"]': this._eventHandler.bind(this, 'deletePlan'),\n '[data-action=\"plan-complete\"]': this._eventHandler.bind(this, 'completePlan'),\n '[data-action=\"plan-reopen\"]': this._eventHandler.bind(this, 'reopenPlan'),\n '[data-action=\"plan-unlink\"]': this._eventHandler.bind(this, 'unlinkPlan'),\n '[data-action=\"plan-request-review\"]': this._eventHandler.bind(this, 'requestReview'),\n '[data-action=\"plan-cancel-review-request\"]': this._eventHandler.bind(this, 'cancelReviewRequest'),\n '[data-action=\"plan-start-review\"]': this._eventHandler.bind(this, 'startReview'),\n '[data-action=\"plan-stop-review\"]': this._eventHandler.bind(this, 'stopReview'),\n '[data-action=\"plan-approve\"]': this._eventHandler.bind(this, 'approve'),\n '[data-action=\"plan-unapprove\"]': this._eventHandler.bind(this, 'unapprove'),\n });\n };\n\n /**\n * Register the events in the region.\n *\n * At this stage this cannot be used with enhanceMenubar or multiple handlers\n * will be added to the same node.\n */\n PlanActions.prototype.registerEvents = function() {\n var wrapper = $(this._region);\n\n wrapper.find('[data-action=\"plan-delete\"]').click(this._eventHandler.bind(this, 'deletePlan'));\n wrapper.find('[data-action=\"plan-complete\"]').click(this._eventHandler.bind(this, 'completePlan'));\n wrapper.find('[data-action=\"plan-reopen\"]').click(this._eventHandler.bind(this, 'reopenPlan'));\n wrapper.find('[data-action=\"plan-unlink\"]').click(this._eventHandler.bind(this, 'unlinkPlan'));\n\n wrapper.find('[data-action=\"plan-request-review\"]').click(this._eventHandler.bind(this, 'requestReview'));\n wrapper.find('[data-action=\"plan-cancel-review-request\"]').click(this._eventHandler.bind(this, 'cancelReviewRequest'));\n wrapper.find('[data-action=\"plan-start-review\"]').click(this._eventHandler.bind(this, 'startReview'));\n wrapper.find('[data-action=\"plan-stop-review\"]').click(this._eventHandler.bind(this, 'stopReview'));\n wrapper.find('[data-action=\"plan-approve\"]').click(this._eventHandler.bind(this, 'approve'));\n wrapper.find('[data-action=\"plan-unapprove\"]').click(this._eventHandler.bind(this, 'unapprove'));\n\n wrapper.find('[data-action=\"find-courses-link\"]').click(this._showLinkedCoursesHandler.bind(this));\n };\n\n return PlanActions;\n});\n"],"file":"planactions.min.js"}
\ No newline at end of file
+{"version":3,"file":"planactions.min.js","sources":["../src/planactions.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 .\n\n/**\n * Plan actions via ajax.\n *\n * @module tool_lp/planactions\n * @copyright 2015 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/templates',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'tool_lp/menubar',\n 'tool_lp/dialogue'],\n function($, templates, ajax, notification, str, Menubar, Dialogue) {\n\n /**\n * PlanActions class.\n *\n * Note that presently this cannot be instantiated more than once per page.\n *\n * @param {String} type The type of page we're in.\n */\n var PlanActions = function(type) {\n this._type = type;\n\n if (type === 'plan') {\n // This is the page to view one plan.\n this._region = '[data-region=\"plan-page\"]';\n this._planNode = '[data-region=\"plan-page\"]';\n this._template = 'tool_lp/plan_page';\n this._contextMethod = 'tool_lp_data_for_plan_page';\n\n } else if (type === 'plans') {\n // This is the page to view a list of plans.\n this._region = '[data-region=\"plans\"]';\n this._planNode = '[data-region=\"plan-node\"]';\n this._template = 'tool_lp/plans_page';\n this._contextMethod = 'tool_lp_data_for_plans_page';\n\n } else {\n throw new TypeError('Unexpected type.');\n }\n };\n\n /** @property {String} Ajax method to fetch the page data from. */\n PlanActions.prototype._contextMethod = null;\n /** @property {String} Selector to find the node describing the plan. */\n PlanActions.prototype._planNode = null;\n /** @property {String} Selector mapping to the region to update. Usually similar to wrapper. */\n PlanActions.prototype._region = null;\n /** @property {String} Name of the template used to render the region. */\n PlanActions.prototype._template = null;\n /** @property {String} Type of page/region we're in. */\n PlanActions.prototype._type = null;\n\n /**\n * Resolve the arguments to refresh the region.\n *\n * @param {Object} planData Plan data from plan node.\n * @return {Object} List of arguments.\n */\n PlanActions.prototype._getContextArgs = function(planData) {\n var self = this,\n args = {};\n\n if (self._type === 'plan') {\n args = {\n planid: planData.id\n };\n\n } else if (self._type === 'plans') {\n args = {\n userid: planData.userid\n };\n }\n\n return args;\n };\n\n /**\n * Refresh the plan view.\n *\n * This is useful when you only want to refresh the view.\n *\n * @param {String} selector The node to search the plan data from.\n */\n PlanActions.prototype.refresh = function(selector) {\n var planData = this._findPlanData($(selector));\n this._callAndRefresh([], planData);\n };\n\n /**\n * Callback to render the region template.\n *\n * @param {Object} context The context for the template.\n * @return {Promise}\n */\n PlanActions.prototype._renderView = function(context) {\n var self = this;\n return templates.render(self._template, context)\n .then(function(newhtml, newjs) {\n $(self._region).replaceWith(newhtml);\n templates.runTemplateJS(newjs);\n return;\n });\n };\n\n /**\n * Call multiple ajax methods, and refresh.\n *\n * @param {Array} calls List of Ajax calls.\n * @param {Object} planData Plan data from plan node.\n * @return {Promise}\n */\n PlanActions.prototype._callAndRefresh = function(calls, planData) {\n // Because this function causes a refresh, we must track the JS completion from start to finish to prevent\n // stale reference issues in Behat.\n var callKey = 'tool_lp/planactions:_callAndRefresh-' + Math.floor(Math.random() * Math.floor(1000));\n M.util.js_pending(callKey);\n\n var self = this;\n calls.push({\n methodname: self._contextMethod,\n args: self._getContextArgs(planData)\n });\n\n // Apply all the promises, and refresh when the last one is resolved.\n return $.when.apply($, ajax.call(calls))\n .then(function() {\n return self._renderView(arguments[arguments.length - 1]);\n })\n .fail(notification.exception)\n .always(function() {\n return M.util.js_complete(callKey);\n });\n };\n\n /**\n * Delete a plan and reload the region.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype._doDelete = function(planData) {\n var self = this,\n calls = [{\n methodname: 'core_competency_delete_plan',\n args: {id: planData.id}\n }];\n self._callAndRefresh(calls, planData);\n };\n\n /**\n * Delete a plan.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype.deletePlan = function(planData) {\n var self = this,\n requests;\n\n requests = ajax.call([{\n methodname: 'core_competency_read_plan',\n args: {id: planData.id}\n }]);\n\n requests[0].done(function(plan) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'deleteplan', component: 'tool_lp', param: plan.name},\n {key: 'delete', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Delete plan X?\n strings[2], // Delete.\n strings[3], // Cancel.\n function() {\n self._doDelete(planData);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n /**\n * Reopen plan and reload the region.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype._doReopenPlan = function(planData) {\n var self = this,\n calls = [{\n methodname: 'core_competency_reopen_plan',\n args: {planid: planData.id}\n }];\n self._callAndRefresh(calls, planData);\n };\n\n /**\n * Reopen a plan.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype.reopenPlan = function(planData) {\n var self = this,\n requests = ajax.call([{\n methodname: 'core_competency_read_plan',\n args: {id: planData.id}\n }]);\n\n requests[0].done(function(plan) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'reopenplanconfirm', component: 'tool_lp', param: plan.name},\n {key: 'reopenplan', component: 'tool_lp'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Reopen plan X?\n strings[2], // Reopen.\n strings[3], // Cancel.\n function() {\n self._doReopenPlan(planData);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n /**\n * Complete plan and reload the region.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype._doCompletePlan = function(planData) {\n var self = this,\n calls = [{\n methodname: 'core_competency_complete_plan',\n args: {planid: planData.id}\n }];\n self._callAndRefresh(calls, planData);\n };\n\n /**\n * Complete a plan process.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype.completePlan = function(planData) {\n var self = this,\n requests = ajax.call([{\n methodname: 'core_competency_read_plan',\n args: {id: planData.id}\n }]);\n\n requests[0].done(function(plan) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'completeplanconfirm', component: 'tool_lp', param: plan.name},\n {key: 'completeplan', component: 'tool_lp'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Complete plan X?\n strings[2], // Complete.\n strings[3], // Cancel.\n function() {\n self._doCompletePlan(planData);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Unlink plan and reload the region.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype._doUnlinkPlan = function(planData) {\n var self = this,\n calls = [{\n methodname: 'core_competency_unlink_plan_from_template',\n args: {planid: planData.id}\n }];\n self._callAndRefresh(calls, planData);\n };\n\n /**\n * Unlink a plan process.\n *\n * @param {Object} planData Plan data from plan node.\n */\n PlanActions.prototype.unlinkPlan = function(planData) {\n var self = this,\n requests = ajax.call([{\n methodname: 'core_competency_read_plan',\n args: {id: planData.id}\n }]);\n\n requests[0].done(function(plan) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'unlinkplantemplateconfirm', component: 'tool_lp', param: plan.name},\n {key: 'unlinkplantemplate', component: 'tool_lp'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Unlink plan X?\n strings[2], // Unlink.\n strings[3], // Cancel.\n function() {\n self._doUnlinkPlan(planData);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Request review of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method _doRequestReview\n */\n PlanActions.prototype._doRequestReview = function(planData) {\n var calls = [{\n methodname: 'core_competency_plan_request_review',\n args: {\n id: planData.id\n }\n }];\n this._callAndRefresh(calls, planData);\n };\n\n /**\n * Request review of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method requestReview\n */\n PlanActions.prototype.requestReview = function(planData) {\n this._doRequestReview(planData);\n };\n\n /**\n * Cancel review request of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method _doCancelReviewRequest\n */\n PlanActions.prototype._doCancelReviewRequest = function(planData) {\n var calls = [{\n methodname: 'core_competency_plan_cancel_review_request',\n args: {\n id: planData.id\n }\n }];\n this._callAndRefresh(calls, planData);\n };\n\n /**\n * Cancel review request of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method cancelReviewRequest\n */\n PlanActions.prototype.cancelReviewRequest = function(planData) {\n this._doCancelReviewRequest(planData);\n };\n\n /**\n * Start review of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method _doStartReview\n */\n PlanActions.prototype._doStartReview = function(planData) {\n var calls = [{\n methodname: 'core_competency_plan_start_review',\n args: {\n id: planData.id\n }\n }];\n this._callAndRefresh(calls, planData);\n };\n\n /**\n * Start review of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method startReview\n */\n PlanActions.prototype.startReview = function(planData) {\n this._doStartReview(planData);\n };\n\n /**\n * Stop review of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method _doStopReview\n */\n PlanActions.prototype._doStopReview = function(planData) {\n var calls = [{\n methodname: 'core_competency_plan_stop_review',\n args: {\n id: planData.id\n }\n }];\n this._callAndRefresh(calls, planData);\n };\n\n /**\n * Stop review of a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method stopReview\n */\n PlanActions.prototype.stopReview = function(planData) {\n this._doStopReview(planData);\n };\n\n /**\n * Approve a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method _doApprove\n */\n PlanActions.prototype._doApprove = function(planData) {\n var calls = [{\n methodname: 'core_competency_approve_plan',\n args: {\n id: planData.id\n }\n }];\n this._callAndRefresh(calls, planData);\n };\n\n /**\n * Approve a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method approve\n */\n PlanActions.prototype.approve = function(planData) {\n this._doApprove(planData);\n };\n\n /**\n * Unapprove a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method _doUnapprove\n */\n PlanActions.prototype._doUnapprove = function(planData) {\n var calls = [{\n methodname: 'core_competency_unapprove_plan',\n args: {\n id: planData.id\n }\n }];\n this._callAndRefresh(calls, planData);\n };\n\n /**\n * Unapprove a plan.\n *\n * @param {Object} planData Plan data from plan node.\n * @method unapprove\n */\n PlanActions.prototype.unapprove = function(planData) {\n this._doUnapprove(planData);\n };\n\n /**\n * Display list of linked courses on a modal dialogue.\n *\n * @param {Event} e The event.\n */\n PlanActions.prototype._showLinkedCoursesHandler = function(e) {\n e.preventDefault();\n\n var competencyid = $(e.target).data('id');\n var requests = ajax.call([{\n methodname: 'tool_lp_list_courses_using_competency',\n args: {id: competencyid}\n }]);\n\n requests[0].done(function(courses) {\n var context = {\n courses: courses\n };\n templates.render('tool_lp/linked_courses_summary', context).done(function(html) {\n str.get_string('linkedcourses', 'tool_lp').done(function(linkedcourses) {\n new Dialogue(\n linkedcourses, // Title.\n html // The linked courses.\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Plan event handler.\n *\n * @param {String} method The method to call.\n * @param {Event} e The event.\n * @method _eventHandler\n */\n PlanActions.prototype._eventHandler = function(method, e) {\n e.preventDefault();\n var data = this._findPlanData($(e.target));\n this[method](data);\n };\n\n /**\n * Find the plan data from the plan node.\n *\n * @param {Node} node The node to search from.\n * @return {Object} Plan data.\n */\n PlanActions.prototype._findPlanData = function(node) {\n var parent = node.parentsUntil($(this._region).parent(), this._planNode),\n data;\n\n if (parent.length != 1) {\n throw new Error('The plan node was not located.');\n }\n\n data = parent.data();\n if (typeof data === 'undefined' || typeof data.id === 'undefined') {\n throw new Error('Plan data could not be found.');\n }\n\n return data;\n };\n\n /**\n * Enhance a menu bar.\n *\n * @param {String} selector Menubar selector.\n */\n PlanActions.prototype.enhanceMenubar = function(selector) {\n Menubar.enhance(selector, {\n '[data-action=\"plan-delete\"]': this._eventHandler.bind(this, 'deletePlan'),\n '[data-action=\"plan-complete\"]': this._eventHandler.bind(this, 'completePlan'),\n '[data-action=\"plan-reopen\"]': this._eventHandler.bind(this, 'reopenPlan'),\n '[data-action=\"plan-unlink\"]': this._eventHandler.bind(this, 'unlinkPlan'),\n '[data-action=\"plan-request-review\"]': this._eventHandler.bind(this, 'requestReview'),\n '[data-action=\"plan-cancel-review-request\"]': this._eventHandler.bind(this, 'cancelReviewRequest'),\n '[data-action=\"plan-start-review\"]': this._eventHandler.bind(this, 'startReview'),\n '[data-action=\"plan-stop-review\"]': this._eventHandler.bind(this, 'stopReview'),\n '[data-action=\"plan-approve\"]': this._eventHandler.bind(this, 'approve'),\n '[data-action=\"plan-unapprove\"]': this._eventHandler.bind(this, 'unapprove'),\n });\n };\n\n /**\n * Register the events in the region.\n *\n * At this stage this cannot be used with enhanceMenubar or multiple handlers\n * will be added to the same node.\n */\n PlanActions.prototype.registerEvents = function() {\n var wrapper = $(this._region);\n\n wrapper.find('[data-action=\"plan-delete\"]').click(this._eventHandler.bind(this, 'deletePlan'));\n wrapper.find('[data-action=\"plan-complete\"]').click(this._eventHandler.bind(this, 'completePlan'));\n wrapper.find('[data-action=\"plan-reopen\"]').click(this._eventHandler.bind(this, 'reopenPlan'));\n wrapper.find('[data-action=\"plan-unlink\"]').click(this._eventHandler.bind(this, 'unlinkPlan'));\n\n wrapper.find('[data-action=\"plan-request-review\"]').click(this._eventHandler.bind(this, 'requestReview'));\n wrapper.find('[data-action=\"plan-cancel-review-request\"]').click(this._eventHandler.bind(this, 'cancelReviewRequest'));\n wrapper.find('[data-action=\"plan-start-review\"]').click(this._eventHandler.bind(this, 'startReview'));\n wrapper.find('[data-action=\"plan-stop-review\"]').click(this._eventHandler.bind(this, 'stopReview'));\n wrapper.find('[data-action=\"plan-approve\"]').click(this._eventHandler.bind(this, 'approve'));\n wrapper.find('[data-action=\"plan-unapprove\"]').click(this._eventHandler.bind(this, 'unapprove'));\n\n wrapper.find('[data-action=\"find-courses-link\"]').click(this._showLinkedCoursesHandler.bind(this));\n };\n\n return PlanActions;\n});\n"],"names":["define","$","templates","ajax","notification","str","Menubar","Dialogue","PlanActions","type","_type","_region","_planNode","_template","_contextMethod","TypeError","prototype","_getContextArgs","planData","args","this","planid","id","userid","refresh","selector","_findPlanData","_callAndRefresh","_renderView","context","self","render","then","newhtml","newjs","replaceWith","runTemplateJS","calls","callKey","Math","floor","random","M","util","js_pending","push","methodname","when","apply","call","arguments","length","fail","exception","always","js_complete","_doDelete","deletePlan","done","plan","get_strings","key","component","param","name","strings","confirm","_doReopenPlan","reopenPlan","_doCompletePlan","completePlan","_doUnlinkPlan","unlinkPlan","_doRequestReview","requestReview","_doCancelReviewRequest","cancelReviewRequest","_doStartReview","startReview","_doStopReview","stopReview","_doApprove","approve","_doUnapprove","unapprove","_showLinkedCoursesHandler","e","preventDefault","competencyid","target","data","courses","html","get_string","linkedcourses","_eventHandler","method","node","parent","parentsUntil","Error","enhanceMenubar","enhance","bind","registerEvents","wrapper","find","click"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/scaleconfig.min.js b/admin/tool/lp/amd/build/scaleconfig.min.js
index 3e275c29b91..12a49195596 100644
--- a/admin/tool/lp/amd/build/scaleconfig.min.js
+++ b/admin/tool/lp/amd/build/scaleconfig.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/scaleconfig",["jquery","core/notification","core/templates","core/ajax","tool_lp/dialogue","tool_lp/scalevalues"],function(a,b,c,d,e,f){var g=function(b,c,d){this.selectSelector=b;this.inputSelector=c;this.triggerSelector=d;this.originalscaleid=a(b).val();a(b).on("change",this.scaleChangeHandler.bind(this)).change();a(d).click(this.showConfig.bind(this))};g.prototype.selectSelector=null;g.prototype.inputSelector=null;g.prototype.triggerSelector=null;g.prototype.scalevalues=null;g.prototype.originalscaleid=0;g.prototype.scaleid=0;g.prototype.popup=null;g.prototype.showConfig=function(){var d=this;this.scaleid=a(this.selectSelector).val();if(0>=this.scaleid){return}var f=a(this.selectSelector).find("option:selected").text();this.getScaleValues(this.scaleid).done(function(){var a={scalename:f,scales:d.scalevalues};c.render("tool_lp/scale_configuration_page",a).done(function(a){new e(f,a,d.initScaleConfig.bind(d))}).fail(b.exception)}).fail(b.exception)};g.prototype.retrieveOriginalScaleConfig=function(){var b=a(this.inputSelector).val();if(""!==b){var c=a.parseJSON(b),d=c.shift();if(d.scaleid===this.originalscaleid){return c}}return""};g.prototype.initScaleConfig=function(b){this.popup=b;var c=a(b.getContent());if(this.originalscaleid===this.scaleid){var d=this.retrieveOriginalScaleConfig();if(""!==d){d.forEach(function(a){if(1===a.scaledefault){c.find("[data-field=\"tool_lp_scale_default_"+a.id+"\"]").attr("checked",!0)}if(1===a.proficient){c.find("[data-field=\"tool_lp_scale_proficient_"+a.id+"\"]").attr("checked",!0)}})}}c.on("click","[data-action=\"close\"]",function(){this.setScaleConfig();b.close()}.bind(this));c.on("click","[data-action=\"cancel\"]",function(){b.close()})};g.prototype.setScaleConfig=function(){var b=a(this.popup.getContent()),c=[{scaleid:this.scaleid}];this.scalevalues.forEach(function(a){var d=0,e=0;if(b.find("[data-field=\"tool_lp_scale_default_"+a.id+"\"]").is(":checked")){d=1}if(b.find("[data-field=\"tool_lp_scale_proficient_"+a.id+"\"]").is(":checked")){e=1}if(!d&&!e){return}c.push({id:a.id,scaledefault:d,proficient:e})});var d=JSON.stringify(c);a(this.inputSelector).val(d);this.originalscaleid=this.scaleid};g.prototype.getScaleValues=function(a){return f.get_values(a).then(function(a){this.scalevalues=a;return a}.bind(this))};g.prototype.scaleChangeHandler=function(b){if(0>=a(b.target).val()){a(this.triggerSelector).prop("disabled",!0)}else{a(this.triggerSelector).prop("disabled",!1)}};return{init:function init(a,b,c){return new g(a,b,c)}}});
-//# sourceMappingURL=scaleconfig.min.js.map
+/**
+ * Handle opening a dialogue to configure scale data.
+ *
+ * @module tool_lp/scaleconfig
+ * @copyright 2015 Adrian Greeve
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/scaleconfig",["jquery","core/notification","core/templates","core/ajax","tool_lp/dialogue","tool_lp/scalevalues"],(function($,notification,templates,ajax,Dialogue,ModScaleValues){var ScaleConfig=function(selectSelector,inputSelector,triggerSelector){this.selectSelector=selectSelector,this.inputSelector=inputSelector,this.triggerSelector=triggerSelector,this.originalscaleid=$(selectSelector).val(),$(selectSelector).on("change",this.scaleChangeHandler.bind(this)).change(),$(triggerSelector).click(this.showConfig.bind(this))};return ScaleConfig.prototype.selectSelector=null,ScaleConfig.prototype.inputSelector=null,ScaleConfig.prototype.triggerSelector=null,ScaleConfig.prototype.scalevalues=null,ScaleConfig.prototype.originalscaleid=0,ScaleConfig.prototype.scaleid=0,ScaleConfig.prototype.popup=null,ScaleConfig.prototype.showConfig=function(){var self=this;if(this.scaleid=$(this.selectSelector).val(),!(this.scaleid<=0)){var scalename=$(this.selectSelector).find("option:selected").text();this.getScaleValues(this.scaleid).done((function(){var context={scalename:scalename,scales:self.scalevalues};templates.render("tool_lp/scale_configuration_page",context).done((function(html){new Dialogue(scalename,html,self.initScaleConfig.bind(self))})).fail(notification.exception)})).fail(notification.exception)}},ScaleConfig.prototype.retrieveOriginalScaleConfig=function(){var jsonstring=$(this.inputSelector).val();if(""!==jsonstring){var scaleconfiguration=$.parseJSON(jsonstring);if(scaleconfiguration.shift().scaleid===this.originalscaleid)return scaleconfiguration}return""},ScaleConfig.prototype.initScaleConfig=function(popup){this.popup=popup;var body=$(popup.getContent());if(this.originalscaleid===this.scaleid){var currentconfig=this.retrieveOriginalScaleConfig();""!==currentconfig&¤tconfig.forEach((function(value){1===value.scaledefault&&body.find('[data-field="tool_lp_scale_default_'+value.id+'"]').attr("checked",!0),1===value.proficient&&body.find('[data-field="tool_lp_scale_proficient_'+value.id+'"]').attr("checked",!0)}))}body.on("click",'[data-action="close"]',function(){this.setScaleConfig(),popup.close()}.bind(this)),body.on("click",'[data-action="cancel"]',(function(){popup.close()}))},ScaleConfig.prototype.setScaleConfig=function(){var body=$(this.popup.getContent()),data=[{scaleid:this.scaleid}];this.scalevalues.forEach((function(value){var scaledefault=0,proficient=0;body.find('[data-field="tool_lp_scale_default_'+value.id+'"]').is(":checked")&&(scaledefault=1),body.find('[data-field="tool_lp_scale_proficient_'+value.id+'"]').is(":checked")&&(proficient=1),(scaledefault||proficient)&&data.push({id:value.id,scaledefault:scaledefault,proficient:proficient})}));var datastring=JSON.stringify(data);$(this.inputSelector).val(datastring),this.originalscaleid=this.scaleid},ScaleConfig.prototype.getScaleValues=function(scaleid){return ModScaleValues.get_values(scaleid).then(function(values){return this.scalevalues=values,values}.bind(this))},ScaleConfig.prototype.scaleChangeHandler=function(e){$(e.target).val()<=0?$(this.triggerSelector).prop("disabled",!0):$(this.triggerSelector).prop("disabled",!1)},{init:function(selectSelector,inputSelector,triggerSelector){return new ScaleConfig(selectSelector,inputSelector,triggerSelector)}}}));
+
+//# sourceMappingURL=scaleconfig.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/scaleconfig.min.js.map b/admin/tool/lp/amd/build/scaleconfig.min.js.map
index 73df75a279d..3a709b50add 100644
--- a/admin/tool/lp/amd/build/scaleconfig.min.js.map
+++ b/admin/tool/lp/amd/build/scaleconfig.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/scaleconfig.js"],"names":["define","$","notification","templates","ajax","Dialogue","ModScaleValues","ScaleConfig","selectSelector","inputSelector","triggerSelector","originalscaleid","val","on","scaleChangeHandler","bind","change","click","showConfig","prototype","scalevalues","scaleid","popup","self","scalename","find","text","getScaleValues","done","context","scales","render","html","initScaleConfig","fail","exception","retrieveOriginalScaleConfig","jsonstring","scaleconfiguration","parseJSON","scaledetail","shift","body","getContent","currentconfig","forEach","value","scaledefault","id","attr","proficient","setScaleConfig","close","data","is","push","datastring","JSON","stringify","get_values","then","values","e","target","prop","init"],"mappings":"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","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 .\n\n/**\n * Handle opening a dialogue to configure scale data.\n *\n * @module tool_lp/scaleconfig\n * @copyright 2015 Adrian Greeve \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/notification', 'core/templates', 'core/ajax', 'tool_lp/dialogue', 'tool_lp/scalevalues'],\n function($, notification, templates, ajax, Dialogue, ModScaleValues) {\n\n /**\n * Scale config object.\n * @param {String} selectSelector The select box selector.\n * @param {String} inputSelector The hidden input field selector.\n * @param {String} triggerSelector The trigger selector.\n */\n var ScaleConfig = function(selectSelector, inputSelector, triggerSelector) {\n this.selectSelector = selectSelector;\n this.inputSelector = inputSelector;\n this.triggerSelector = triggerSelector;\n\n // Get the current scale ID.\n this.originalscaleid = $(selectSelector).val();\n $(selectSelector).on('change', this.scaleChangeHandler.bind(this)).change();\n $(triggerSelector).click(this.showConfig.bind(this));\n };\n\n /** @var {String} The select box selector. */\n ScaleConfig.prototype.selectSelector = null;\n /** @var {String} The hidden field selector. */\n ScaleConfig.prototype.inputSelector = null;\n /** @var {String} The trigger selector. */\n ScaleConfig.prototype.triggerSelector = null;\n /** @var {Array} scalevalues ID and name of the scales. */\n ScaleConfig.prototype.scalevalues = null;\n /** @var {Number) originalscaleid Original scale ID when the page loads. */\n ScaleConfig.prototype.originalscaleid = 0;\n /** @var {Number} scaleid Current scale ID. */\n ScaleConfig.prototype.scaleid = 0;\n /** @var {Dialogue} Reference to the popup. */\n ScaleConfig.prototype.popup = null;\n\n /**\n * Displays the scale configuration dialogue.\n *\n * @method showConfig\n */\n ScaleConfig.prototype.showConfig = function() {\n var self = this;\n\n this.scaleid = $(this.selectSelector).val();\n if (this.scaleid <= 0) {\n // This should not happen.\n return;\n }\n\n var scalename = $(this.selectSelector).find(\"option:selected\").text();\n this.getScaleValues(this.scaleid).done(function() {\n\n var context = {\n scalename: scalename,\n scales: self.scalevalues\n };\n\n // Dish up the form.\n templates.render('tool_lp/scale_configuration_page', context)\n .done(function(html) {\n new Dialogue(\n scalename,\n html,\n self.initScaleConfig.bind(self)\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Gets the original scale configuration if it was set.\n *\n * @method retrieveOriginalScaleConfig\n * @return {Object|String} scale configuration or empty string.\n */\n ScaleConfig.prototype.retrieveOriginalScaleConfig = function() {\n var jsonstring = $(this.inputSelector).val();\n if (jsonstring !== '') {\n var scaleconfiguration = $.parseJSON(jsonstring);\n // The first object should contain the scale ID for the configuration.\n var scaledetail = scaleconfiguration.shift();\n // Check that this scale id matches the one from the page before returning the configuration.\n if (scaledetail.scaleid === this.originalscaleid) {\n return scaleconfiguration;\n }\n }\n return '';\n };\n\n /**\n * Initialises the scale configuration dialogue.\n *\n * @method initScaleConfig\n * @param {Dialogue} popup Dialogue object to initialise.\n */\n ScaleConfig.prototype.initScaleConfig = function(popup) {\n this.popup = popup;\n var body = $(popup.getContent());\n if (this.originalscaleid === this.scaleid) {\n // Set up the popup to show the current configuration.\n var currentconfig = this.retrieveOriginalScaleConfig();\n // Set up the form only if there is configuration settings to set.\n if (currentconfig !== '') {\n currentconfig.forEach(function(value) {\n if (value.scaledefault === 1) {\n body.find('[data-field=\"tool_lp_scale_default_' + value.id + '\"]').attr('checked', true);\n }\n if (value.proficient === 1) {\n body.find('[data-field=\"tool_lp_scale_proficient_' + value.id + '\"]').attr('checked', true);\n }\n });\n }\n }\n body.on('click', '[data-action=\"close\"]', function() {\n this.setScaleConfig();\n popup.close();\n }.bind(this));\n body.on('click', '[data-action=\"cancel\"]', function() {\n popup.close();\n });\n };\n\n /**\n * Set the scale configuration back into a JSON string in the hidden element.\n *\n * @method setScaleConfig\n */\n ScaleConfig.prototype.setScaleConfig = function() {\n var body = $(this.popup.getContent());\n // Get the data.\n var data = [{scaleid: this.scaleid}];\n this.scalevalues.forEach(function(value) {\n var scaledefault = 0;\n var proficient = 0;\n if (body.find('[data-field=\"tool_lp_scale_default_' + value.id + '\"]').is(':checked')) {\n scaledefault = 1;\n }\n if (body.find('[data-field=\"tool_lp_scale_proficient_' + value.id + '\"]').is(':checked')) {\n proficient = 1;\n }\n\n if (!scaledefault && !proficient) {\n return;\n }\n\n data.push({\n id: value.id,\n scaledefault: scaledefault,\n proficient: proficient\n });\n });\n var datastring = JSON.stringify(data);\n // Send to the hidden field on the form.\n $(this.inputSelector).val(datastring);\n // Once the configuration has been saved then the original scale ID is set to the current scale ID.\n this.originalscaleid = this.scaleid;\n };\n\n /**\n * Get the scale values for the selected scale.\n *\n * @method getScaleValues\n * @param {Number} scaleid The scale ID of the selected scale.\n * @return {Promise} A deffered object with the scale values.\n */\n ScaleConfig.prototype.getScaleValues = function(scaleid) {\n return ModScaleValues.get_values(scaleid).then(function(values) {\n this.scalevalues = values;\n return values;\n }.bind(this));\n };\n\n /**\n * Triggered when a scale is selected.\n *\n * @name scaleChangeHandler\n * @param {Event} e\n * @function\n */\n ScaleConfig.prototype.scaleChangeHandler = function(e) {\n if ($(e.target).val() <= 0) {\n $(this.triggerSelector).prop('disabled', true);\n } else {\n $(this.triggerSelector).prop('disabled', false);\n }\n\n };\n\n return {\n\n /**\n * Main initialisation.\n *\n * @param {String} selectSelector The select box selector.\n * @param {String} inputSelector The hidden input field selector.\n * @param {String} triggerSelector The trigger selector.\n * @return {ScaleConfig} A new instance of ScaleConfig.\n * @method init\n */\n init: function(selectSelector, inputSelector, triggerSelector) {\n return new ScaleConfig(selectSelector, inputSelector, triggerSelector);\n }\n };\n});\n"],"file":"scaleconfig.min.js"}
\ No newline at end of file
+{"version":3,"file":"scaleconfig.min.js","sources":["../src/scaleconfig.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 .\n\n/**\n * Handle opening a dialogue to configure scale data.\n *\n * @module tool_lp/scaleconfig\n * @copyright 2015 Adrian Greeve \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/notification', 'core/templates', 'core/ajax', 'tool_lp/dialogue', 'tool_lp/scalevalues'],\n function($, notification, templates, ajax, Dialogue, ModScaleValues) {\n\n /**\n * Scale config object.\n * @param {String} selectSelector The select box selector.\n * @param {String} inputSelector The hidden input field selector.\n * @param {String} triggerSelector The trigger selector.\n */\n var ScaleConfig = function(selectSelector, inputSelector, triggerSelector) {\n this.selectSelector = selectSelector;\n this.inputSelector = inputSelector;\n this.triggerSelector = triggerSelector;\n\n // Get the current scale ID.\n this.originalscaleid = $(selectSelector).val();\n $(selectSelector).on('change', this.scaleChangeHandler.bind(this)).change();\n $(triggerSelector).click(this.showConfig.bind(this));\n };\n\n /** @var {String} The select box selector. */\n ScaleConfig.prototype.selectSelector = null;\n /** @var {String} The hidden field selector. */\n ScaleConfig.prototype.inputSelector = null;\n /** @var {String} The trigger selector. */\n ScaleConfig.prototype.triggerSelector = null;\n /** @var {Array} scalevalues ID and name of the scales. */\n ScaleConfig.prototype.scalevalues = null;\n /** @var {Number) originalscaleid Original scale ID when the page loads. */\n ScaleConfig.prototype.originalscaleid = 0;\n /** @var {Number} scaleid Current scale ID. */\n ScaleConfig.prototype.scaleid = 0;\n /** @var {Dialogue} Reference to the popup. */\n ScaleConfig.prototype.popup = null;\n\n /**\n * Displays the scale configuration dialogue.\n *\n * @method showConfig\n */\n ScaleConfig.prototype.showConfig = function() {\n var self = this;\n\n this.scaleid = $(this.selectSelector).val();\n if (this.scaleid <= 0) {\n // This should not happen.\n return;\n }\n\n var scalename = $(this.selectSelector).find(\"option:selected\").text();\n this.getScaleValues(this.scaleid).done(function() {\n\n var context = {\n scalename: scalename,\n scales: self.scalevalues\n };\n\n // Dish up the form.\n templates.render('tool_lp/scale_configuration_page', context)\n .done(function(html) {\n new Dialogue(\n scalename,\n html,\n self.initScaleConfig.bind(self)\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Gets the original scale configuration if it was set.\n *\n * @method retrieveOriginalScaleConfig\n * @return {Object|String} scale configuration or empty string.\n */\n ScaleConfig.prototype.retrieveOriginalScaleConfig = function() {\n var jsonstring = $(this.inputSelector).val();\n if (jsonstring !== '') {\n var scaleconfiguration = $.parseJSON(jsonstring);\n // The first object should contain the scale ID for the configuration.\n var scaledetail = scaleconfiguration.shift();\n // Check that this scale id matches the one from the page before returning the configuration.\n if (scaledetail.scaleid === this.originalscaleid) {\n return scaleconfiguration;\n }\n }\n return '';\n };\n\n /**\n * Initialises the scale configuration dialogue.\n *\n * @method initScaleConfig\n * @param {Dialogue} popup Dialogue object to initialise.\n */\n ScaleConfig.prototype.initScaleConfig = function(popup) {\n this.popup = popup;\n var body = $(popup.getContent());\n if (this.originalscaleid === this.scaleid) {\n // Set up the popup to show the current configuration.\n var currentconfig = this.retrieveOriginalScaleConfig();\n // Set up the form only if there is configuration settings to set.\n if (currentconfig !== '') {\n currentconfig.forEach(function(value) {\n if (value.scaledefault === 1) {\n body.find('[data-field=\"tool_lp_scale_default_' + value.id + '\"]').attr('checked', true);\n }\n if (value.proficient === 1) {\n body.find('[data-field=\"tool_lp_scale_proficient_' + value.id + '\"]').attr('checked', true);\n }\n });\n }\n }\n body.on('click', '[data-action=\"close\"]', function() {\n this.setScaleConfig();\n popup.close();\n }.bind(this));\n body.on('click', '[data-action=\"cancel\"]', function() {\n popup.close();\n });\n };\n\n /**\n * Set the scale configuration back into a JSON string in the hidden element.\n *\n * @method setScaleConfig\n */\n ScaleConfig.prototype.setScaleConfig = function() {\n var body = $(this.popup.getContent());\n // Get the data.\n var data = [{scaleid: this.scaleid}];\n this.scalevalues.forEach(function(value) {\n var scaledefault = 0;\n var proficient = 0;\n if (body.find('[data-field=\"tool_lp_scale_default_' + value.id + '\"]').is(':checked')) {\n scaledefault = 1;\n }\n if (body.find('[data-field=\"tool_lp_scale_proficient_' + value.id + '\"]').is(':checked')) {\n proficient = 1;\n }\n\n if (!scaledefault && !proficient) {\n return;\n }\n\n data.push({\n id: value.id,\n scaledefault: scaledefault,\n proficient: proficient\n });\n });\n var datastring = JSON.stringify(data);\n // Send to the hidden field on the form.\n $(this.inputSelector).val(datastring);\n // Once the configuration has been saved then the original scale ID is set to the current scale ID.\n this.originalscaleid = this.scaleid;\n };\n\n /**\n * Get the scale values for the selected scale.\n *\n * @method getScaleValues\n * @param {Number} scaleid The scale ID of the selected scale.\n * @return {Promise} A deffered object with the scale values.\n */\n ScaleConfig.prototype.getScaleValues = function(scaleid) {\n return ModScaleValues.get_values(scaleid).then(function(values) {\n this.scalevalues = values;\n return values;\n }.bind(this));\n };\n\n /**\n * Triggered when a scale is selected.\n *\n * @name scaleChangeHandler\n * @param {Event} e\n * @function\n */\n ScaleConfig.prototype.scaleChangeHandler = function(e) {\n if ($(e.target).val() <= 0) {\n $(this.triggerSelector).prop('disabled', true);\n } else {\n $(this.triggerSelector).prop('disabled', false);\n }\n\n };\n\n return {\n\n /**\n * Main initialisation.\n *\n * @param {String} selectSelector The select box selector.\n * @param {String} inputSelector The hidden input field selector.\n * @param {String} triggerSelector The trigger selector.\n * @return {ScaleConfig} A new instance of ScaleConfig.\n * @method init\n */\n init: function(selectSelector, inputSelector, triggerSelector) {\n return new ScaleConfig(selectSelector, inputSelector, triggerSelector);\n }\n };\n});\n"],"names":["define","$","notification","templates","ajax","Dialogue","ModScaleValues","ScaleConfig","selectSelector","inputSelector","triggerSelector","originalscaleid","val","on","this","scaleChangeHandler","bind","change","click","showConfig","prototype","scalevalues","scaleid","popup","self","scalename","find","text","getScaleValues","done","context","scales","render","html","initScaleConfig","fail","exception","retrieveOriginalScaleConfig","jsonstring","scaleconfiguration","parseJSON","shift","body","getContent","currentconfig","forEach","value","scaledefault","id","attr","proficient","setScaleConfig","close","data","is","push","datastring","JSON","stringify","get_values","then","values","e","target","prop","init"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/scalevalues.min.js b/admin/tool/lp/amd/build/scalevalues.min.js
index 637c17fb289..dd1d78ea291 100644
--- a/admin/tool/lp/amd/build/scalevalues.min.js
+++ b/admin/tool/lp/amd/build/scalevalues.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/scalevalues",["jquery","core/ajax"],function(a,b){var c=[];return{get_values:function get_values(d){var e=a.Deferred();if("undefined"==typeof c[d]){b.call([{methodname:"core_competency_get_scale_values",args:{scaleid:d},done:function done(a){c[d]=a;e.resolve(a)},fail:e.reject}])}else{e.resolve(c[d])}return e.promise()}}});
-//# sourceMappingURL=scalevalues.min.js.map
+/**
+ * Module to get the scale values.
+ *
+ * @module tool_lp/scalevalues
+ * @copyright 2016 Serge Gauthier
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/scalevalues",["jquery","core/ajax"],(function($,ajax){var localCache=[];return{get_values:function(scaleid){var deferred=$.Deferred();return void 0===localCache[scaleid]?ajax.call([{methodname:"core_competency_get_scale_values",args:{scaleid:scaleid},done:function(scaleinfo){localCache[scaleid]=scaleinfo,deferred.resolve(scaleinfo)},fail:deferred.reject}]):deferred.resolve(localCache[scaleid]),deferred.promise()}}}));
+
+//# sourceMappingURL=scalevalues.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/scalevalues.min.js.map b/admin/tool/lp/amd/build/scalevalues.min.js.map
index d652b9fb38d..f15ca392296 100644
--- a/admin/tool/lp/amd/build/scalevalues.min.js.map
+++ b/admin/tool/lp/amd/build/scalevalues.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/scalevalues.js"],"names":["define","$","ajax","localCache","get_values","scaleid","deferred","Deferred","call","methodname","args","done","scaleinfo","resolve","fail","reject","promise"],"mappings":"AAsBAA,OAAM,uBAAC,CAAC,QAAD,CAAW,WAAX,CAAD,CAA0B,SAASC,CAAT,CAAYC,CAAZ,CAAkB,CAC9C,GAAIC,CAAAA,CAAU,CAAG,EAAjB,CAEA,MAAO,CAUHC,UAAU,CAAE,oBAASC,CAAT,CAAkB,CAE1B,GAAIC,CAAAA,CAAQ,CAAGL,CAAC,CAACM,QAAF,EAAf,CAEA,GAAmC,WAA/B,QAAOJ,CAAAA,CAAU,CAACE,CAAD,CAArB,CAAgD,CAC5CH,CAAI,CAACM,IAAL,CAAU,CAAC,CACPC,UAAU,CAAE,kCADL,CAEPC,IAAI,CAAE,CAACL,OAAO,CAAEA,CAAV,CAFC,CAGPM,IAAI,CAAE,cAASC,CAAT,CAAoB,CACtBT,CAAU,CAACE,CAAD,CAAV,CAAsBO,CAAtB,CACAN,CAAQ,CAACO,OAAT,CAAiBD,CAAjB,CACH,CANM,CAOPE,IAAI,CAAGR,CAAQ,CAACS,MAPT,CAAD,CAAV,CASH,CAVD,IAUO,CACHT,CAAQ,CAACO,OAAT,CAAiBV,CAAU,CAACE,CAAD,CAA3B,CACH,CAED,MAAOC,CAAAA,CAAQ,CAACU,OAAT,EACV,CA7BE,CA+BV,CAlCK,CAAN","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 .\n\n/**\n * Module to get the scale values.\n *\n * @module tool_lp/scalevalues\n * @copyright 2016 Serge Gauthier\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax'], function($, ajax) {\n var localCache = [];\n\n return {\n\n /**\n * Return a promise object that will be resolved into a string eventually (maybe immediately).\n *\n * @method get_values\n * @param {Number} scaleid The scale id\n * @return [] {Promise}\n */\n // eslint-disable-next-line camelcase\n get_values: function(scaleid) {\n\n var deferred = $.Deferred();\n\n if (typeof localCache[scaleid] === 'undefined') {\n ajax.call([{\n methodname: 'core_competency_get_scale_values',\n args: {scaleid: scaleid},\n done: function(scaleinfo) {\n localCache[scaleid] = scaleinfo;\n deferred.resolve(scaleinfo);\n },\n fail: (deferred.reject)\n }]);\n } else {\n deferred.resolve(localCache[scaleid]);\n }\n\n return deferred.promise();\n }\n };\n});\n"],"file":"scalevalues.min.js"}
\ No newline at end of file
+{"version":3,"file":"scalevalues.min.js","sources":["../src/scalevalues.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 .\n\n/**\n * Module to get the scale values.\n *\n * @module tool_lp/scalevalues\n * @copyright 2016 Serge Gauthier\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax'], function($, ajax) {\n var localCache = [];\n\n return {\n\n /**\n * Return a promise object that will be resolved into a string eventually (maybe immediately).\n *\n * @method get_values\n * @param {Number} scaleid The scale id\n * @return [] {Promise}\n */\n // eslint-disable-next-line camelcase\n get_values: function(scaleid) {\n\n var deferred = $.Deferred();\n\n if (typeof localCache[scaleid] === 'undefined') {\n ajax.call([{\n methodname: 'core_competency_get_scale_values',\n args: {scaleid: scaleid},\n done: function(scaleinfo) {\n localCache[scaleid] = scaleinfo;\n deferred.resolve(scaleinfo);\n },\n fail: (deferred.reject)\n }]);\n } else {\n deferred.resolve(localCache[scaleid]);\n }\n\n return deferred.promise();\n }\n };\n});\n"],"names":["define","$","ajax","localCache","get_values","scaleid","deferred","Deferred","call","methodname","args","done","scaleinfo","resolve","fail","reject","promise"],"mappings":";;;;;;;AAsBAA,6BAAO,CAAC,SAAU,cAAc,SAASC,EAAGC,UACpCC,WAAa,SAEV,CAUHC,WAAY,SAASC,aAEbC,SAAWL,EAAEM,uBAEkB,IAAxBJ,WAAWE,SAClBH,KAAKM,KAAK,CAAC,CACPC,WAAY,mCACZC,KAAM,CAACL,QAASA,SAChBM,KAAM,SAASC,WACXT,WAAWE,SAAWO,UACtBN,SAASO,QAAQD,YAErBE,KAAOR,SAASS,UAGpBT,SAASO,QAAQV,WAAWE,UAGzBC,SAASU"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/templateactions.min.js b/admin/tool/lp/amd/build/templateactions.min.js
index e57f9618e1c..1c72cff04d6 100644
--- a/admin/tool/lp/amd/build/templateactions.min.js
+++ b/admin/tool/lp/amd/build/templateactions.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/templateactions",["jquery","core/templates","core/ajax","core/notification","core/str","tool_lp/actionselector"],function(a,b,c,d,e,f){var g=0,h=0,i=!0,j=function(c,d){a("[data-region=\"managetemplates\"]").replaceWith(c);b.runTemplateJS(d)},k=function(a){b.render("tool_lp/manage_templates_page",a).done(j).fail(d.exception)},l=function(){var a=c.call([{methodname:"core_competency_delete_template",args:{id:h,deleteplans:i}},{methodname:"tool_lp_data_for_templates_manage_page",args:{pagecontext:{contextid:g}}}]);a[1].done(k).fail(d.exception)},m=function(b){b.preventDefault();h=a(this).attr("data-templateid");var e=c.call([{methodname:"core_competency_duplicate_template",args:{id:h}},{methodname:"tool_lp_data_for_templates_manage_page",args:{pagecontext:{contextid:g}}}]);e[1].done(k).fail(d.exception)},n=function(b){b.preventDefault();var g=a(this).attr("data-templateid");h=g;i=!0;var j=c.call([{methodname:"core_competency_read_template",args:{id:h}},{methodname:"core_competency_template_has_related_data",args:{id:h}}]);j[0].done(function(a){j[1].done(function(b){if(b){e.get_strings([{key:"deletetemplate",component:"tool_lp",param:a.shortname},{key:"deletetemplatewithplans",component:"tool_lp"},{key:"deleteplans",component:"tool_lp"},{key:"unlinkplanstemplate",component:"tool_lp"},{key:"confirm",component:"moodle"},{key:"cancel",component:"moodle"}]).done(function(a){var b=[{text:a[2],value:"delete"},{text:a[3],value:"unlink"}],c=new f(a[0],a[1],b,a[4],a[5]);c.display();c.on("save",function(a,b){if("delete"!=b.action){i=!1}l()})}).fail(d.exception)}else{e.get_strings([{key:"confirm",component:"moodle"},{key:"deletetemplate",component:"tool_lp",param:a.shortname},{key:"delete",component:"moodle"},{key:"cancel",component:"moodle"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],l)}).fail(d.exception)}}).fail(d.exception)}).fail(d.exception)};return{deleteHandler:n,duplicateHandler:m,init:function init(a){g=a}}});
-//# sourceMappingURL=templateactions.min.js.map
+/**
+ * Handle actions on learning plan templates via ajax.
+ *
+ * @module tool_lp/templateactions
+ * @copyright 2015 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/templateactions",["jquery","core/templates","core/ajax","core/notification","core/str","tool_lp/actionselector"],(function($,templates,ajax,notification,str,Actionselector){var pagecontextid=0,templateid=0,deleteplans=!0,updatePage=function(newhtml,newjs){$('[data-region="managetemplates"]').replaceWith(newhtml),templates.runTemplateJS(newjs)},reloadList=function(context){templates.render("tool_lp/manage_templates_page",context).done(updatePage).fail(notification.exception)},doDelete=function(){ajax.call([{methodname:"core_competency_delete_template",args:{id:templateid,deleteplans:deleteplans}},{methodname:"tool_lp_data_for_templates_manage_page",args:{pagecontext:{contextid:pagecontextid}}}])[1].done(reloadList).fail(notification.exception)};return{deleteHandler:function(e){e.preventDefault();var id=$(this).attr("data-templateid");templateid=id,deleteplans=!0;var requests=ajax.call([{methodname:"core_competency_read_template",args:{id:templateid}},{methodname:"core_competency_template_has_related_data",args:{id:templateid}}]);requests[0].done((function(template){requests[1].done((function(templatehasrelateddata){templatehasrelateddata?str.get_strings([{key:"deletetemplate",component:"tool_lp",param:template.shortname},{key:"deletetemplatewithplans",component:"tool_lp"},{key:"deleteplans",component:"tool_lp"},{key:"unlinkplanstemplate",component:"tool_lp"},{key:"confirm",component:"moodle"},{key:"cancel",component:"moodle"}]).done((function(strings){var actions=[{text:strings[2],value:"delete"},{text:strings[3],value:"unlink"}],actionselector=new Actionselector(strings[0],strings[1],actions,strings[4],strings[5]);actionselector.display(),actionselector.on("save",(function(e,data){"delete"!=data.action&&(deleteplans=!1),doDelete()}))})).fail(notification.exception):str.get_strings([{key:"confirm",component:"moodle"},{key:"deletetemplate",component:"tool_lp",param:template.shortname},{key:"delete",component:"moodle"},{key:"cancel",component:"moodle"}]).done((function(strings){notification.confirm(strings[0],strings[1],strings[2],strings[3],doDelete)})).fail(notification.exception)})).fail(notification.exception)})).fail(notification.exception)},duplicateHandler:function(e){e.preventDefault(),templateid=$(this).attr("data-templateid"),ajax.call([{methodname:"core_competency_duplicate_template",args:{id:templateid}},{methodname:"tool_lp_data_for_templates_manage_page",args:{pagecontext:{contextid:pagecontextid}}}])[1].done(reloadList).fail(notification.exception)},init:function(contextid){pagecontextid=contextid}}}));
+
+//# sourceMappingURL=templateactions.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/templateactions.min.js.map b/admin/tool/lp/amd/build/templateactions.min.js.map
index cbcfd077d8d..6c72d2794ca 100644
--- a/admin/tool/lp/amd/build/templateactions.min.js.map
+++ b/admin/tool/lp/amd/build/templateactions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/templateactions.js"],"names":["define","$","templates","ajax","notification","str","Actionselector","pagecontextid","templateid","deleteplans","updatePage","newhtml","newjs","replaceWith","runTemplateJS","reloadList","context","render","done","fail","exception","doDelete","requests","call","methodname","args","id","pagecontext","contextid","doDuplicate","e","preventDefault","attr","confirmDelete","template","templatehasrelateddata","get_strings","key","component","param","shortname","strings","actions","actionselector","display","on","data","action","confirm","deleteHandler","duplicateHandler","init"],"mappings":"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","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 .\n\n/**\n * Handle actions on learning plan templates via ajax.\n *\n * @module tool_lp/templateactions\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str', 'tool_lp/actionselector'],\n function($, templates, ajax, notification, str, Actionselector) {\n // Private variables and functions.\n\n /** @var {Number} pagecontextid The id of the context */\n var pagecontextid = 0;\n\n /** @var {Number} templateid The id of the template */\n var templateid = 0;\n\n /** @var {Boolean} Action to apply to plans when deleting a template */\n var deleteplans = true;\n\n /**\n * Callback to replace the dom element with the rendered template.\n *\n * @method updatePage\n * @param {String} newhtml The new html to insert.\n * @param {String} newjs The new js to run.\n */\n var updatePage = function(newhtml, newjs) {\n $('[data-region=\"managetemplates\"]').replaceWith(newhtml);\n templates.runTemplateJS(newjs);\n };\n\n /**\n * Callback to render the page template again and update the page.\n *\n * @method reloadList\n * @param {Object} context The context for the template.\n */\n var reloadList = function(context) {\n templates.render('tool_lp/manage_templates_page', context)\n .done(updatePage)\n .fail(notification.exception);\n };\n\n /**\n * Delete a template and reload the page.\n * @method doDelete\n */\n var doDelete = function() {\n\n // We are chaining ajax requests here.\n var requests = ajax.call([{\n methodname: 'core_competency_delete_template',\n args: {id: templateid,\n deleteplans: deleteplans}\n }, {\n methodname: 'tool_lp_data_for_templates_manage_page',\n args: {\n pagecontext: {\n contextid: pagecontextid\n }\n }\n }]);\n requests[1].done(reloadList).fail(notification.exception);\n };\n\n /**\n * Duplicate a template and reload the page.\n * @method doDuplicate\n * @param {Event} e\n */\n var doDuplicate = function(e) {\n e.preventDefault();\n\n templateid = $(this).attr('data-templateid');\n\n // We are chaining ajax requests here.\n var requests = ajax.call([{\n methodname: 'core_competency_duplicate_template',\n args: {id: templateid}\n }, {\n methodname: 'tool_lp_data_for_templates_manage_page',\n args: {\n pagecontext: {\n contextid: pagecontextid\n }\n }\n }]);\n requests[1].done(reloadList).fail(notification.exception);\n };\n\n /**\n * Handler for \"Delete learning plan template\" actions.\n * @method confirmDelete\n * @param {Event} e\n */\n var confirmDelete = function(e) {\n e.preventDefault();\n\n var id = $(this).attr('data-templateid');\n templateid = id;\n deleteplans = true;\n\n var requests = ajax.call([{\n methodname: 'core_competency_read_template',\n args: {id: templateid}\n }, {\n methodname: 'core_competency_template_has_related_data',\n args: {id: templateid}\n }]);\n\n requests[0].done(function(template) {\n requests[1].done(function(templatehasrelateddata) {\n if (templatehasrelateddata) {\n str.get_strings([\n {key: 'deletetemplate', component: 'tool_lp', param: template.shortname},\n {key: 'deletetemplatewithplans', component: 'tool_lp'},\n {key: 'deleteplans', component: 'tool_lp'},\n {key: 'unlinkplanstemplate', component: 'tool_lp'},\n {key: 'confirm', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n var actions = [{'text': strings[2], 'value': 'delete'},\n {'text': strings[3], 'value': 'unlink'}];\n var actionselector = new Actionselector(\n strings[0], // Title.\n strings[1], // Message\n actions, // Radio button options.\n strings[4], // Confirm.\n strings[5]); // Cancel.\n actionselector.display();\n actionselector.on('save', function(e, data) {\n if (data.action != 'delete') {\n deleteplans = false;\n }\n doDelete();\n });\n }).fail(notification.exception);\n } else {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'deletetemplate', component: 'tool_lp', param: template.shortname},\n {key: 'delete', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Delete learning plan template X?\n strings[2], // Delete.\n strings[3], // Cancel.\n doDelete\n );\n }).fail(notification.exception);\n }\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n return /** @alias module:tool_lp/templateactions */ {\n // Public variables and functions.\n /**\n * Expose the event handler for the delete.\n * @method deleteHandler\n * @param {Event} e\n */\n deleteHandler: confirmDelete,\n\n /**\n * Expose the event handler for the duplicate.\n * @method duplicateHandler\n * @param {Event} e\n */\n duplicateHandler: doDuplicate,\n\n /**\n * Initialise the module.\n * @method init\n * @param {Number} contextid The context id of the page.\n */\n init: function(contextid) {\n pagecontextid = contextid;\n }\n };\n});\n"],"file":"templateactions.min.js"}
\ No newline at end of file
+{"version":3,"file":"templateactions.min.js","sources":["../src/templateactions.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 .\n\n/**\n * Handle actions on learning plan templates via ajax.\n *\n * @module tool_lp/templateactions\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str', 'tool_lp/actionselector'],\n function($, templates, ajax, notification, str, Actionselector) {\n // Private variables and functions.\n\n /** @var {Number} pagecontextid The id of the context */\n var pagecontextid = 0;\n\n /** @var {Number} templateid The id of the template */\n var templateid = 0;\n\n /** @var {Boolean} Action to apply to plans when deleting a template */\n var deleteplans = true;\n\n /**\n * Callback to replace the dom element with the rendered template.\n *\n * @method updatePage\n * @param {String} newhtml The new html to insert.\n * @param {String} newjs The new js to run.\n */\n var updatePage = function(newhtml, newjs) {\n $('[data-region=\"managetemplates\"]').replaceWith(newhtml);\n templates.runTemplateJS(newjs);\n };\n\n /**\n * Callback to render the page template again and update the page.\n *\n * @method reloadList\n * @param {Object} context The context for the template.\n */\n var reloadList = function(context) {\n templates.render('tool_lp/manage_templates_page', context)\n .done(updatePage)\n .fail(notification.exception);\n };\n\n /**\n * Delete a template and reload the page.\n * @method doDelete\n */\n var doDelete = function() {\n\n // We are chaining ajax requests here.\n var requests = ajax.call([{\n methodname: 'core_competency_delete_template',\n args: {id: templateid,\n deleteplans: deleteplans}\n }, {\n methodname: 'tool_lp_data_for_templates_manage_page',\n args: {\n pagecontext: {\n contextid: pagecontextid\n }\n }\n }]);\n requests[1].done(reloadList).fail(notification.exception);\n };\n\n /**\n * Duplicate a template and reload the page.\n * @method doDuplicate\n * @param {Event} e\n */\n var doDuplicate = function(e) {\n e.preventDefault();\n\n templateid = $(this).attr('data-templateid');\n\n // We are chaining ajax requests here.\n var requests = ajax.call([{\n methodname: 'core_competency_duplicate_template',\n args: {id: templateid}\n }, {\n methodname: 'tool_lp_data_for_templates_manage_page',\n args: {\n pagecontext: {\n contextid: pagecontextid\n }\n }\n }]);\n requests[1].done(reloadList).fail(notification.exception);\n };\n\n /**\n * Handler for \"Delete learning plan template\" actions.\n * @method confirmDelete\n * @param {Event} e\n */\n var confirmDelete = function(e) {\n e.preventDefault();\n\n var id = $(this).attr('data-templateid');\n templateid = id;\n deleteplans = true;\n\n var requests = ajax.call([{\n methodname: 'core_competency_read_template',\n args: {id: templateid}\n }, {\n methodname: 'core_competency_template_has_related_data',\n args: {id: templateid}\n }]);\n\n requests[0].done(function(template) {\n requests[1].done(function(templatehasrelateddata) {\n if (templatehasrelateddata) {\n str.get_strings([\n {key: 'deletetemplate', component: 'tool_lp', param: template.shortname},\n {key: 'deletetemplatewithplans', component: 'tool_lp'},\n {key: 'deleteplans', component: 'tool_lp'},\n {key: 'unlinkplanstemplate', component: 'tool_lp'},\n {key: 'confirm', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n var actions = [{'text': strings[2], 'value': 'delete'},\n {'text': strings[3], 'value': 'unlink'}];\n var actionselector = new Actionselector(\n strings[0], // Title.\n strings[1], // Message\n actions, // Radio button options.\n strings[4], // Confirm.\n strings[5]); // Cancel.\n actionselector.display();\n actionselector.on('save', function(e, data) {\n if (data.action != 'delete') {\n deleteplans = false;\n }\n doDelete();\n });\n }).fail(notification.exception);\n } else {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'deletetemplate', component: 'tool_lp', param: template.shortname},\n {key: 'delete', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Delete learning plan template X?\n strings[2], // Delete.\n strings[3], // Cancel.\n doDelete\n );\n }).fail(notification.exception);\n }\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n return /** @alias module:tool_lp/templateactions */ {\n // Public variables and functions.\n /**\n * Expose the event handler for the delete.\n * @method deleteHandler\n * @param {Event} e\n */\n deleteHandler: confirmDelete,\n\n /**\n * Expose the event handler for the duplicate.\n * @method duplicateHandler\n * @param {Event} e\n */\n duplicateHandler: doDuplicate,\n\n /**\n * Initialise the module.\n * @method init\n * @param {Number} contextid The context id of the page.\n */\n init: function(contextid) {\n pagecontextid = contextid;\n }\n };\n});\n"],"names":["define","$","templates","ajax","notification","str","Actionselector","pagecontextid","templateid","deleteplans","updatePage","newhtml","newjs","replaceWith","runTemplateJS","reloadList","context","render","done","fail","exception","doDelete","call","methodname","args","id","pagecontext","contextid","deleteHandler","e","preventDefault","this","attr","requests","template","templatehasrelateddata","get_strings","key","component","param","shortname","strings","actions","actionselector","display","on","data","action","confirm","duplicateHandler","init"],"mappings":";;;;;;;AAsBAA,iCAAO,CAAC,SAAU,iBAAkB,YAAa,oBAAqB,WAAY,2BAC3E,SAASC,EAAGC,UAAWC,KAAMC,aAAcC,IAAKC,oBAI/CC,cAAgB,EAGhBC,WAAa,EAGbC,aAAc,EASdC,WAAa,SAASC,QAASC,OAC/BX,EAAE,mCAAmCY,YAAYF,SACjDT,UAAUY,cAAcF,QASxBG,WAAa,SAASC,SACtBd,UAAUe,OAAO,gCAAiCD,SAC7CE,KAAKR,YACLS,KAAKf,aAAagB,YAOvBC,SAAW,WAGIlB,KAAKmB,KAAK,CAAC,CACtBC,WAAY,kCACZC,KAAM,CAACC,GAAIjB,WACHC,YAAaA,cACtB,CACCc,WAAY,yCACZC,KAAM,CACFE,YAAa,CACTC,UAAWpB,mBAId,GAAGW,KAAKH,YAAYI,KAAKf,aAAagB,kBAgGC,CAOhDQ,cAtEgB,SAASC,GACzBA,EAAEC,qBAEEL,GAAKxB,EAAE8B,MAAMC,KAAK,mBACtBxB,WAAaiB,GACbhB,aAAc,MAEVwB,SAAW9B,KAAKmB,KAAK,CAAC,CACtBC,WAAY,gCACZC,KAAM,CAACC,GAAIjB,aACZ,CACCe,WAAY,4CACZC,KAAM,CAACC,GAAIjB,eAGfyB,SAAS,GAAGf,MAAK,SAASgB,UACtBD,SAAS,GAAGf,MAAK,SAASiB,wBAClBA,uBACA9B,IAAI+B,YAAY,CACZ,CAACC,IAAK,iBAAkBC,UAAW,UAAWC,MAAOL,SAASM,WAC9D,CAACH,IAAK,0BAA2BC,UAAW,WAC5C,CAACD,IAAK,cAAeC,UAAW,WAChC,CAACD,IAAK,sBAAuBC,UAAW,WACxC,CAACD,IAAK,UAAWC,UAAW,UAC5B,CAACD,IAAK,SAAUC,UAAW,YAC5BpB,MAAK,SAASuB,aACTC,QAAU,CAAC,MAASD,QAAQ,SAAa,UAC9B,MAASA,QAAQ,SAAa,WACzCE,eAAiB,IAAIrC,eACjBmC,QAAQ,GACRA,QAAQ,GACRC,QACAD,QAAQ,GACRA,QAAQ,IAChBE,eAAeC,UACfD,eAAeE,GAAG,QAAQ,SAAShB,EAAGiB,MACf,UAAfA,KAAKC,SACLtC,aAAc,GAElBY,iBAELF,KAAKf,aAAagB,WAErBf,IAAI+B,YAAY,CACZ,CAACC,IAAK,UAAWC,UAAW,UAC5B,CAACD,IAAK,iBAAkBC,UAAW,UAAWC,MAAOL,SAASM,WAC9D,CAACH,IAAK,SAAUC,UAAW,UAC3B,CAACD,IAAK,SAAUC,UAAW,YAC5BpB,MAAK,SAASuB,SACbrC,aAAa4C,QACbP,QAAQ,GACRA,QAAQ,GACRA,QAAQ,GACRA,QAAQ,GACRpB,aAEDF,KAAKf,aAAagB,cAE1BD,KAAKf,aAAagB,cACtBD,KAAKf,aAAagB,YAkBrB6B,iBAtGc,SAASpB,GACvBA,EAAEC,iBAEFtB,WAAaP,EAAE8B,MAAMC,KAAK,mBAGX7B,KAAKmB,KAAK,CAAC,CACtBC,WAAY,qCACZC,KAAM,CAACC,GAAIjB,aACZ,CACCe,WAAY,yCACZC,KAAM,CACFE,YAAa,CACTC,UAAWpB,mBAId,GAAGW,KAAKH,YAAYI,KAAKf,aAAagB,YA4F/C8B,KAAM,SAASvB,WACXpB,cAAgBoB"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/tree.min.js b/admin/tool/lp/amd/build/tree.min.js
index a5a4ecd4449..d6d373a1320 100644
--- a/admin/tool/lp/amd/build/tree.min.js
+++ b/admin/tool/lp/amd/build/tree.min.js
@@ -1,2 +1,15 @@
-define ("tool_lp/tree",["jquery","core/url","core/log"],function(a,b,c){var d=a(""),e=a(""),f=function(b,c){this.treeRoot=a(b);this.multiSelect="undefined"==typeof c||!0===c;this.items=this.treeRoot.find("li");this.expandAll=20>this.items.length;this.parents=this.treeRoot.find("li:has(ul)");if(c){this.treeRoot.attr("aria-multiselectable","true")}this.items.attr("aria-selected","false");this.visibleItems=null;this.activeItem=null;this.lastActiveItem=null;this.keys={tab:9,enter:13,space:32,pageup:33,pagedown:34,end:35,home:36,left:37,up:38,right:39,down:40,eight:56,asterisk:106};this.init();this.bindEventHandlers()};f.prototype.init=function(){this.parents.attr("aria-expanded","true");this.parents.prepend(d.clone());this.items.attr("role","tree-item");this.items.attr("tabindex","-1");this.parents.attr("role","group");this.treeRoot.attr("role","tree");this.visibleItems=this.treeRoot.find("li");var b=this;if(!this.expandAll){this.parents.each(function(){b.collapseGroup(a(this))});this.expandGroup(this.parents.first())}};f.prototype.expandGroup=function(a){var b=a.children("ul");b.show().attr("aria-hidden","false");a.attr("aria-expanded","true");a.children("img").attr("src",d.attr("src"));this.visibleItems=this.treeRoot.find("li:visible")};f.prototype.collapseGroup=function(a){var b=a.children("ul");b.hide().attr("aria-hidden","true");a.attr("aria-expanded","false");a.children("img").attr("src",e.attr("src"));this.visibleItems=this.treeRoot.find("li:visible")};f.prototype.toggleGroup=function(a){if("true"==a.attr("aria-expanded")){this.collapseGroup(a)}else{this.expandGroup(a)}};f.prototype.triggerChange=function(){var a=this.items.filter("[aria-selected=true]");if(!this.multiSelect){a=a.first()}this.treeRoot.trigger("selectionchanged",{selected:a})};f.prototype.multiSelectItem=function(b){if(!this.multiSelect){this.items.attr("aria-selected","false")}else if(null!==this.lastActiveItem){var c=this.visibleItems.index(this.lastActiveItem),d=this.visibleItems.index(this.activeItem),e=null;while(cd){e=a(this.visibleItems.get(c));e.attr("aria-selected","true");c--}}b.attr("aria-selected","true");this.triggerChange()};f.prototype.selectItem=function(a){var b=a.parent();while("tree"!=b.attr("role")){b=b.parent();if("false"==b.attr("aria-expanded")){this.expandGroup(b)}b=b.parent()}this.items.attr("aria-selected","false");a.attr("aria-selected","true");this.triggerChange()};f.prototype.toggleItem=function(a){if(!this.multiSelect){this.selectItem(a);return}var b=a.attr("aria-selected");if("true"===b){b="false"}else{b="true"}a.attr("aria-selected",b);this.triggerChange()};f.prototype.updateFocus=function(a){this.lastActiveItem=this.activeItem;this.activeItem=a;var b=a.parent();while("tree"!=b.attr("role")){b=b.parent();if("false"==b.attr("aria-expanded")){this.expandGroup(b)}b=b.parent()}this.items.attr("tabindex","-1");a.attr("tabindex",0)};f.prototype.handleKeyDown=function(b,c){var d=this.visibleItems.index(b),e=null,f=c.shiftKey||c.ctrlKey||c.metaKey||c.altKey,g=this;switch(c.keyCode){case this.keys.home:{e=this.parents.first();e.focus();if(c.shiftKey){this.multiSelectItem(e)}else if(!f){this.selectItem(e)}c.stopPropagation();return!1}case this.keys.end:{e=this.visibleItems.last();e.focus();if(c.shiftKey){this.multiSelectItem(e)}else if(!f){this.selectItem(e)}c.stopPropagation();return!1}case this.keys.enter:case this.keys.space:{if(c.shiftKey){this.multiSelectItem(b)}else if(c.metaKey||c.ctrlKey){this.toggleItem(b)}else{this.selectItem(b)}c.stopPropagation();return!1}case this.keys.left:{if(b.has("ul")&&"true"==b.attr("aria-expanded")){this.collapseGroup(b)}else{var h=b.parent(),i=h.parent();if(i.is("li")){i.focus();if(c.shiftKey){this.multiSelectItem(i)}else if(!f){this.selectItem(i)}}}c.stopPropagation();return!1}case this.keys.right:{if(b.has("ul")&&"false"==b.attr("aria-expanded")){this.expandGroup(b)}else{e=b.children("ul").children("li").first();if(0
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/tree",["jquery","core/url","core/log"],(function($,url,log){var expandedImage=$(''),collapsedImage=$(''),Tree=function(selector,multiSelect){this.treeRoot=$(selector),this.multiSelect=void 0===multiSelect||!0===multiSelect,this.items=this.treeRoot.find("li"),this.expandAll=this.items.length<20,this.parents=this.treeRoot.find("li:has(ul)"),multiSelect&&this.treeRoot.attr("aria-multiselectable","true"),this.items.attr("aria-selected","false"),this.visibleItems=null,this.activeItem=null,this.lastActiveItem=null,this.keys={tab:9,enter:13,space:32,pageup:33,pagedown:34,end:35,home:36,left:37,up:38,right:39,down:40,eight:56,asterisk:106},this.init(),this.bindEventHandlers()};return Tree.prototype.init=function(){this.parents.attr("aria-expanded","true"),this.parents.prepend(expandedImage.clone()),this.items.attr("role","tree-item"),this.items.attr("tabindex","-1"),this.parents.attr("role","group"),this.treeRoot.attr("role","tree"),this.visibleItems=this.treeRoot.find("li");var thisObj=this;this.expandAll||(this.parents.each((function(){thisObj.collapseGroup($(this))})),this.expandGroup(this.parents.first()))},Tree.prototype.expandGroup=function(item){item.children("ul").show().attr("aria-hidden","false"),item.attr("aria-expanded","true"),item.children("img").attr("src",expandedImage.attr("src")),this.visibleItems=this.treeRoot.find("li:visible")},Tree.prototype.collapseGroup=function(item){item.children("ul").hide().attr("aria-hidden","true"),item.attr("aria-expanded","false"),item.children("img").attr("src",collapsedImage.attr("src")),this.visibleItems=this.treeRoot.find("li:visible")},Tree.prototype.toggleGroup=function(item){"true"==item.attr("aria-expanded")?this.collapseGroup(item):this.expandGroup(item)},Tree.prototype.triggerChange=function(){var allSelected=this.items.filter("[aria-selected=true]");this.multiSelect||(allSelected=allSelected.first()),this.treeRoot.trigger("selectionchanged",{selected:allSelected})},Tree.prototype.multiSelectItem=function(item){if(this.multiSelect){if(null!==this.lastActiveItem){for(var lastIndex=this.visibleItems.index(this.lastActiveItem),currentIndex=this.visibleItems.index(this.activeItem);lastIndexcurrentIndex;)$(this.visibleItems.get(lastIndex)).attr("aria-selected","true"),lastIndex--}}else this.items.attr("aria-selected","false");item.attr("aria-selected","true"),this.triggerChange()},Tree.prototype.selectItem=function(item){for(var walk=item.parent();"tree"!=walk.attr("role");)"false"==(walk=walk.parent()).attr("aria-expanded")&&this.expandGroup(walk),walk=walk.parent();this.items.attr("aria-selected","false"),item.attr("aria-selected","true"),this.triggerChange()},Tree.prototype.toggleItem=function(item){if(this.multiSelect){var current=item.attr("aria-selected");current="true"===current?"false":"true",item.attr("aria-selected",current),this.triggerChange()}else this.selectItem(item)},Tree.prototype.updateFocus=function(item){this.lastActiveItem=this.activeItem,this.activeItem=item;for(var walk=item.parent();"tree"!=walk.attr("role");)"false"==(walk=walk.parent()).attr("aria-expanded")&&this.expandGroup(walk),walk=walk.parent();this.items.attr("tabindex","-1"),item.attr("tabindex",0)},Tree.prototype.handleKeyDown=function(item,e){var currentIndex=this.visibleItems.index(item),newItem=null,hasKeyModifier=e.shiftKey||e.ctrlKey||e.metaKey||e.altKey,thisObj=this;switch(e.keyCode){case this.keys.home:return(newItem=this.parents.first()).focus(),e.shiftKey?this.multiSelectItem(newItem):hasKeyModifier||this.selectItem(newItem),e.stopPropagation(),!1;case this.keys.end:return(newItem=this.visibleItems.last()).focus(),e.shiftKey?this.multiSelectItem(newItem):hasKeyModifier||this.selectItem(newItem),e.stopPropagation(),!1;case this.keys.enter:case this.keys.space:return e.shiftKey?this.multiSelectItem(item):e.metaKey||e.ctrlKey?this.toggleItem(item):this.selectItem(item),e.stopPropagation(),!1;case this.keys.left:if(item.has("ul")&&"true"==item.attr("aria-expanded"))this.collapseGroup(item);else{var itemParent=item.parent().parent();itemParent.is("li")&&(itemParent.focus(),e.shiftKey?this.multiSelectItem(itemParent):hasKeyModifier||this.selectItem(itemParent))}return e.stopPropagation(),!1;case this.keys.right:return item.has("ul")&&"false"==item.attr("aria-expanded")?this.expandGroup(item):(newItem=item.children("ul").children("li").first()).length>0&&(newItem.focus(),e.shiftKey?this.multiSelectItem(newItem):hasKeyModifier||this.selectItem(newItem)),e.stopPropagation(),!1;case this.keys.up:if(currentIndex>0){var prev=this.visibleItems.eq(currentIndex-1);prev.focus(),e.shiftKey?this.multiSelectItem(prev):hasKeyModifier||this.selectItem(prev)}return e.stopPropagation(),!1;case this.keys.down:if(currentIndex.\n\n/**\n * Implement an accessible aria tree widget, from a nested unordered list.\n * Based on http://oaa-accessibility.org/example/41/\n *\n * To respond to selection changed events - use tree.on(\"selectionchanged\", handler).\n * The handler will receive an array of nodes, which are the list items that are currently\n * selected. (Or a single node if multiselect is disabled).\n *\n * @module tool_lp/tree\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/url', 'core/log'], function($, url, log) {\n // Private variables and functions.\n /** @var {String} expandedImage The html for an expanded tree node twistie. */\n var expandedImage = $('');\n /** @var {String} collapsedImage The html for a collapsed tree node twistie. */\n var collapsedImage = $('');\n\n /**\n * Constructor\n *\n * @param {String} selector\n * @param {Boolean} multiSelect\n */\n var Tree = function(selector, multiSelect) {\n this.treeRoot = $(selector);\n this.multiSelect = (typeof multiSelect === 'undefined' || multiSelect === true);\n\n this.items = this.treeRoot.find('li');\n this.expandAll = this.items.length < 20;\n this.parents = this.treeRoot.find('li:has(ul)');\n\n if (multiSelect) {\n this.treeRoot.attr('aria-multiselectable', 'true');\n }\n\n this.items.attr('aria-selected', 'false');\n\n this.visibleItems = null;\n this.activeItem = null;\n this.lastActiveItem = null;\n\n this.keys = {\n tab: 9,\n enter: 13,\n space: 32,\n pageup: 33,\n pagedown: 34,\n end: 35,\n home: 36,\n left: 37,\n up: 38,\n right: 39,\n down: 40,\n eight: 56,\n asterisk: 106\n };\n\n this.init();\n\n this.bindEventHandlers();\n };\n // Public variables and functions.\n\n /**\n * Init this tree\n * @method init\n */\n Tree.prototype.init = function() {\n this.parents.attr('aria-expanded', 'true');\n this.parents.prepend(expandedImage.clone());\n\n this.items.attr('role', 'tree-item');\n this.items.attr('tabindex', '-1');\n this.parents.attr('role', 'group');\n this.treeRoot.attr('role', 'tree');\n\n this.visibleItems = this.treeRoot.find('li');\n\n var thisObj = this;\n if (!this.expandAll) {\n this.parents.each(function() {\n thisObj.collapseGroup($(this));\n });\n this.expandGroup(this.parents.first());\n }\n };\n\n /**\n * Expand a collapsed group.\n *\n * @method expandGroup\n * @param {Object} item is the jquery id of the parent item of the group\n */\n Tree.prototype.expandGroup = function(item) {\n // Find the first child ul node.\n var group = item.children('ul');\n\n // Expand the group.\n group.show().attr('aria-hidden', 'false');\n\n item.attr('aria-expanded', 'true');\n\n item.children('img').attr('src', expandedImage.attr('src'));\n\n // Update the list of visible items.\n this.visibleItems = this.treeRoot.find('li:visible');\n };\n\n /**\n * Collapse an expanded group.\n *\n * @method collapseGroup\n * @param {Object} item is the jquery id of the parent item of the group\n */\n Tree.prototype.collapseGroup = function(item) {\n var group = item.children('ul');\n\n // Collapse the group.\n group.hide().attr('aria-hidden', 'true');\n\n item.attr('aria-expanded', 'false');\n\n item.children('img').attr('src', collapsedImage.attr('src'));\n\n // Update the list of visible items.\n this.visibleItems = this.treeRoot.find('li:visible');\n };\n\n /**\n * Expand or collapse a group.\n *\n * @method toggleGroup\n * @param {Object} item is the jquery id of the parent item of the group\n */\n Tree.prototype.toggleGroup = function(item) {\n if (item.attr('aria-expanded') == 'true') {\n this.collapseGroup(item);\n } else {\n this.expandGroup(item);\n }\n };\n\n /**\n * Whenever the currently selected node has changed, trigger an event using this function.\n *\n * @method triggerChange\n */\n Tree.prototype.triggerChange = function() {\n var allSelected = this.items.filter('[aria-selected=true]');\n if (!this.multiSelect) {\n allSelected = allSelected.first();\n }\n this.treeRoot.trigger('selectionchanged', {selected: allSelected});\n };\n\n /**\n * Select all the items between the last focused item and this currently focused item.\n *\n * @method multiSelectItem\n * @param {Object} item is the jquery id of the newly selected item.\n */\n Tree.prototype.multiSelectItem = function(item) {\n if (!this.multiSelect) {\n this.items.attr('aria-selected', 'false');\n } else if (this.lastActiveItem !== null) {\n var lastIndex = this.visibleItems.index(this.lastActiveItem);\n var currentIndex = this.visibleItems.index(this.activeItem);\n var oneItem = null;\n\n while (lastIndex < currentIndex) {\n oneItem = $(this.visibleItems.get(lastIndex));\n oneItem.attr('aria-selected', 'true');\n lastIndex++;\n }\n while (lastIndex > currentIndex) {\n oneItem = $(this.visibleItems.get(lastIndex));\n oneItem.attr('aria-selected', 'true');\n lastIndex--;\n }\n }\n\n item.attr('aria-selected', 'true');\n this.triggerChange();\n };\n\n /**\n * Select a single item. Make sure all the parents are expanded. De-select all other items.\n *\n * @method selectItem\n * @param {Object} item is the jquery id of the newly selected item.\n */\n Tree.prototype.selectItem = function(item) {\n // Expand all nodes up the tree.\n var walk = item.parent();\n while (walk.attr('role') != 'tree') {\n walk = walk.parent();\n if (walk.attr('aria-expanded') == 'false') {\n this.expandGroup(walk);\n }\n walk = walk.parent();\n }\n this.items.attr('aria-selected', 'false');\n item.attr('aria-selected', 'true');\n this.triggerChange();\n };\n\n /**\n * Toggle the selected state for an item back and forth.\n *\n * @method toggleItem\n * @param {Object} item is the jquery id of the item to toggle.\n */\n Tree.prototype.toggleItem = function(item) {\n if (!this.multiSelect) {\n this.selectItem(item);\n return;\n }\n\n var current = item.attr('aria-selected');\n if (current === 'true') {\n current = 'false';\n } else {\n current = 'true';\n }\n item.attr('aria-selected', current);\n this.triggerChange();\n };\n\n /**\n * Set the focus to this item.\n *\n * @method updateFocus\n * @param {Object} item is the jquery id of the parent item of the group\n */\n Tree.prototype.updateFocus = function(item) {\n this.lastActiveItem = this.activeItem;\n this.activeItem = item;\n // Expand all nodes up the tree.\n var walk = item.parent();\n while (walk.attr('role') != 'tree') {\n walk = walk.parent();\n if (walk.attr('aria-expanded') == 'false') {\n this.expandGroup(walk);\n }\n walk = walk.parent();\n }\n this.items.attr('tabindex', '-1');\n item.attr('tabindex', 0);\n };\n\n /**\n * Handle a key down event - ie navigate the tree.\n *\n * @method handleKeyDown\n * @param {Object} item is the jquery id of the parent item of the group\n * @param {Event} e The event.\n * @return {Boolean}\n */\n // This function should be simplified. In the meantime..\n // eslint-disable-next-line complexity\n Tree.prototype.handleKeyDown = function(item, e) {\n var currentIndex = this.visibleItems.index(item);\n var newItem = null;\n var hasKeyModifier = e.shiftKey || e.ctrlKey || e.metaKey || e.altKey;\n var thisObj = this;\n\n switch (e.keyCode) {\n case this.keys.home: {\n // Jump to first item in tree.\n newItem = this.parents.first();\n newItem.focus();\n if (e.shiftKey) {\n this.multiSelectItem(newItem);\n } else if (!hasKeyModifier) {\n this.selectItem(newItem);\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.end: {\n // Jump to last visible item.\n newItem = this.visibleItems.last();\n newItem.focus();\n if (e.shiftKey) {\n this.multiSelectItem(newItem);\n } else if (!hasKeyModifier) {\n this.selectItem(newItem);\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.enter:\n case this.keys.space: {\n\n if (e.shiftKey) {\n this.multiSelectItem(item);\n } else if (e.metaKey || e.ctrlKey) {\n this.toggleItem(item);\n } else {\n this.selectItem(item);\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.left: {\n if (item.has('ul') && item.attr('aria-expanded') == 'true') {\n this.collapseGroup(item);\n } else {\n // Move up to the parent.\n var itemUL = item.parent();\n var itemParent = itemUL.parent();\n if (itemParent.is('li')) {\n itemParent.focus();\n if (e.shiftKey) {\n this.multiSelectItem(itemParent);\n } else if (!hasKeyModifier) {\n this.selectItem(itemParent);\n }\n }\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.right: {\n if (item.has('ul') && item.attr('aria-expanded') == 'false') {\n this.expandGroup(item);\n } else {\n // Move to the first item in the child group.\n newItem = item.children('ul').children('li').first();\n if (newItem.length > 0) {\n newItem.focus();\n if (e.shiftKey) {\n this.multiSelectItem(newItem);\n } else if (!hasKeyModifier) {\n this.selectItem(newItem);\n }\n }\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.up: {\n\n if (currentIndex > 0) {\n var prev = this.visibleItems.eq(currentIndex - 1);\n prev.focus();\n if (e.shiftKey) {\n this.multiSelectItem(prev);\n } else if (!hasKeyModifier) {\n this.selectItem(prev);\n }\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.down: {\n\n if (currentIndex < this.visibleItems.length - 1) {\n var next = this.visibleItems.eq(currentIndex + 1);\n next.focus();\n if (e.shiftKey) {\n this.multiSelectItem(next);\n } else if (!hasKeyModifier) {\n this.selectItem(next);\n }\n }\n e.stopPropagation();\n return false;\n }\n case this.keys.asterisk: {\n // Expand all groups.\n this.parents.each(function() {\n thisObj.expandGroup($(this));\n });\n\n e.stopPropagation();\n return false;\n }\n case this.keys.eight: {\n if (e.shiftKey) {\n // Expand all groups.\n this.parents.each(function() {\n thisObj.expandGroup($(this));\n });\n\n e.stopPropagation();\n }\n\n return false;\n }\n }\n\n return true;\n };\n\n /**\n * Handle a key press event - ie navigate the tree.\n *\n * @method handleKeyPress\n * @param {Object} item is the jquery id of the parent item of the group\n * @param {Event} e The event.\n * @return {Boolean}\n */\n Tree.prototype.handleKeyPress = function(item, e) {\n if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {\n // Do nothing.\n return true;\n }\n\n switch (e.keyCode) {\n case this.keys.tab: {\n return true;\n }\n case this.keys.enter:\n case this.keys.home:\n case this.keys.end:\n case this.keys.left:\n case this.keys.right:\n case this.keys.up:\n case this.keys.down: {\n e.stopPropagation();\n return false;\n }\n default : {\n var chr = String.fromCharCode(e.which);\n var match = false;\n var itemIndex = this.visibleItems.index(item);\n var itemCount = this.visibleItems.length;\n var currentIndex = itemIndex + 1;\n\n // Check if the active item was the last one on the list.\n if (currentIndex == itemCount) {\n currentIndex = 0;\n }\n\n // Iterate through the menu items (starting from the current item and wrapping) until a match is found\n // or the loop returns to the current menu item.\n while (currentIndex != itemIndex) {\n\n var currentItem = this.visibleItems.eq(currentIndex);\n var titleChr = currentItem.text().charAt(0);\n\n if (currentItem.has('ul')) {\n titleChr = currentItem.find('span').text().charAt(0);\n }\n\n if (titleChr.toLowerCase() == chr) {\n match = true;\n break;\n }\n\n currentIndex = currentIndex + 1;\n if (currentIndex == itemCount) {\n // Reached the end of the list, start again at the beginning.\n currentIndex = 0;\n }\n }\n\n if (match === true) {\n this.updateFocus(this.visibleItems.eq(currentIndex));\n }\n e.stopPropagation();\n return false;\n }\n }\n\n // eslint-disable-next-line no-unreachable\n return true;\n };\n\n /**\n * Attach an event listener to the tree.\n *\n * @method on\n * @param {String} eventname This is the name of the event to listen for. Only 'selectionchanged' is supported for now.\n * @param {Function} handler The function to call when the event is triggered.\n */\n Tree.prototype.on = function(eventname, handler) {\n if (eventname !== 'selectionchanged') {\n log.warning('Invalid custom event name for tree. Only \"selectionchanged\" is supported.');\n } else {\n this.treeRoot.on(eventname, handler);\n }\n };\n\n /**\n * Handle a double click (expand/collapse).\n *\n * @method handleDblClick\n * @param {Object} item is the jquery id of the parent item of the group\n * @param {Event} e The event.\n * @return {Boolean}\n */\n Tree.prototype.handleDblClick = function(item, e) {\n\n if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {\n // Do nothing.\n return true;\n }\n\n // Apply the focus markup.\n this.updateFocus(item);\n\n // Expand or collapse the group.\n this.toggleGroup(item);\n\n e.stopPropagation();\n return false;\n };\n\n /**\n * Handle a click (select).\n *\n * @method handleExpandCollapseClick\n * @param {Object} item is the jquery id of the parent item of the group\n * @param {Event} e The event.\n * @return {Boolean}\n */\n Tree.prototype.handleExpandCollapseClick = function(item, e) {\n\n // Do not shift the focus.\n this.toggleGroup(item);\n e.stopPropagation();\n return false;\n };\n\n\n /**\n * Handle a click (select).\n *\n * @method handleClick\n * @param {Object} item is the jquery id of the parent item of the group\n * @param {Event} e The event.\n * @return {Boolean}\n */\n Tree.prototype.handleClick = function(item, e) {\n\n if (e.shiftKey) {\n this.multiSelectItem(item);\n } else if (e.metaKey || e.ctrlKey) {\n this.toggleItem(item);\n } else {\n this.selectItem(item);\n }\n this.updateFocus(item);\n e.stopPropagation();\n return false;\n };\n\n /**\n * Handle a blur event\n *\n * @method handleBlur\n * @return {Boolean}\n */\n Tree.prototype.handleBlur = function() {\n return true;\n };\n\n /**\n * Handle a focus event\n *\n * @method handleFocus\n * @param {Object} item item is the jquery id of the parent item of the group\n * @return {Boolean}\n */\n Tree.prototype.handleFocus = function(item) {\n\n this.updateFocus(item);\n\n return true;\n };\n\n /**\n * Bind the event listeners we require.\n *\n * @method bindEventHandlers\n */\n Tree.prototype.bindEventHandlers = function() {\n var thisObj = this;\n\n // Bind a dblclick handler to the parent items.\n this.parents.dblclick(function(e) {\n return thisObj.handleDblClick($(this), e);\n });\n\n // Bind a click handler.\n this.items.click(function(e) {\n return thisObj.handleClick($(this), e);\n });\n\n // Bind a toggle handler to the expand/collapse icons.\n this.items.children('img').click(function(e) {\n return thisObj.handleExpandCollapseClick($(this).parent(), e);\n });\n\n // Bind a keydown handler.\n this.items.keydown(function(e) {\n return thisObj.handleKeyDown($(this), e);\n });\n\n // Bind a keypress handler.\n this.items.keypress(function(e) {\n return thisObj.handleKeyPress($(this), e);\n });\n\n // Bind a focus handler.\n this.items.focus(function(e) {\n return thisObj.handleFocus($(this), e);\n });\n\n // Bind a blur handler.\n this.items.blur(function(e) {\n return thisObj.handleBlur($(this), e);\n });\n\n };\n\n return /** @alias module:tool_lp/tree */ Tree;\n});\n"],"file":"tree.min.js"}
\ No newline at end of file
+{"version":3,"file":"tree.min.js","sources":["../src/tree.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 .\n\n/**\n * Implement an accessible aria tree widget, from a nested unordered list.\n * Based on http://oaa-accessibility.org/example/41/\n *\n * To respond to selection changed events - use tree.on(\"selectionchanged\", handler).\n * The handler will receive an array of nodes, which are the list items that are currently\n * selected. (Or a single node if multiselect is disabled).\n *\n * @module tool_lp/tree\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/url', 'core/log'], function($, url, log) {\n // Private variables and functions.\n /** @var {String} expandedImage The html for an expanded tree node twistie. */\n var expandedImage = $('');\n /** @var {String} collapsedImage The html for a collapsed tree node twistie. */\n var collapsedImage = $('');\n\n /**\n * Constructor\n *\n * @param {String} selector\n * @param {Boolean} multiSelect\n */\n var Tree = function(selector, multiSelect) {\n this.treeRoot = $(selector);\n this.multiSelect = (typeof multiSelect === 'undefined' || multiSelect === true);\n\n this.items = this.treeRoot.find('li');\n this.expandAll = this.items.length < 20;\n this.parents = this.treeRoot.find('li:has(ul)');\n\n if (multiSelect) {\n this.treeRoot.attr('aria-multiselectable', 'true');\n }\n\n this.items.attr('aria-selected', 'false');\n\n this.visibleItems = null;\n this.activeItem = null;\n this.lastActiveItem = null;\n\n this.keys = {\n tab: 9,\n enter: 13,\n space: 32,\n pageup: 33,\n pagedown: 34,\n end: 35,\n home: 36,\n left: 37,\n up: 38,\n right: 39,\n down: 40,\n eight: 56,\n asterisk: 106\n };\n\n this.init();\n\n this.bindEventHandlers();\n };\n // Public variables and functions.\n\n /**\n * Init this tree\n * @method init\n */\n Tree.prototype.init = function() {\n this.parents.attr('aria-expanded', 'true');\n this.parents.prepend(expandedImage.clone());\n\n this.items.attr('role', 'tree-item');\n this.items.attr('tabindex', '-1');\n this.parents.attr('role', 'group');\n this.treeRoot.attr('role', 'tree');\n\n this.visibleItems = this.treeRoot.find('li');\n\n var thisObj = this;\n if (!this.expandAll) {\n this.parents.each(function() {\n thisObj.collapseGroup($(this));\n });\n this.expandGroup(this.parents.first());\n }\n };\n\n /**\n * Expand a collapsed group.\n *\n * @method expandGroup\n * @param {Object} item is the jquery id of the parent item of the group\n */\n Tree.prototype.expandGroup = function(item) {\n // Find the first child ul node.\n var group = item.children('ul');\n\n // Expand the group.\n group.show().attr('aria-hidden', 'false');\n\n item.attr('aria-expanded', 'true');\n\n item.children('img').attr('src', expandedImage.attr('src'));\n\n // Update the list of visible items.\n this.visibleItems = this.treeRoot.find('li:visible');\n };\n\n /**\n * Collapse an expanded group.\n *\n * @method collapseGroup\n * @param {Object} item is the jquery id of the parent item of the group\n */\n Tree.prototype.collapseGroup = function(item) {\n var group = item.children('ul');\n\n // Collapse the group.\n group.hide().attr('aria-hidden', 'true');\n\n item.attr('aria-expanded', 'false');\n\n item.children('img').attr('src', collapsedImage.attr('src'));\n\n // Update the list of visible items.\n this.visibleItems = this.treeRoot.find('li:visible');\n };\n\n /**\n * Expand or collapse a group.\n *\n * @method toggleGroup\n * @param {Object} item is the jquery id of the parent item of the group\n */\n Tree.prototype.toggleGroup = function(item) {\n if (item.attr('aria-expanded') == 'true') {\n this.collapseGroup(item);\n } else {\n this.expandGroup(item);\n }\n };\n\n /**\n * Whenever the currently selected node has changed, trigger an event using this function.\n *\n * @method triggerChange\n */\n Tree.prototype.triggerChange = function() {\n var allSelected = this.items.filter('[aria-selected=true]');\n if (!this.multiSelect) {\n allSelected = allSelected.first();\n }\n this.treeRoot.trigger('selectionchanged', {selected: allSelected});\n };\n\n /**\n * Select all the items between the last focused item and this currently focused item.\n *\n * @method multiSelectItem\n * @param {Object} item is the jquery id of the newly selected item.\n */\n Tree.prototype.multiSelectItem = function(item) {\n if (!this.multiSelect) {\n this.items.attr('aria-selected', 'false');\n } else if (this.lastActiveItem !== null) {\n var lastIndex = this.visibleItems.index(this.lastActiveItem);\n var currentIndex = this.visibleItems.index(this.activeItem);\n var oneItem = null;\n\n while (lastIndex < currentIndex) {\n oneItem = $(this.visibleItems.get(lastIndex));\n oneItem.attr('aria-selected', 'true');\n lastIndex++;\n }\n while (lastIndex > currentIndex) {\n oneItem = $(this.visibleItems.get(lastIndex));\n oneItem.attr('aria-selected', 'true');\n lastIndex--;\n }\n }\n\n item.attr('aria-selected', 'true');\n this.triggerChange();\n };\n\n /**\n * Select a single item. Make sure all the parents are expanded. De-select all other items.\n *\n * @method selectItem\n * @param {Object} item is the jquery id of the newly selected item.\n */\n Tree.prototype.selectItem = function(item) {\n // Expand all nodes up the tree.\n var walk = item.parent();\n while (walk.attr('role') != 'tree') {\n walk = walk.parent();\n if (walk.attr('aria-expanded') == 'false') {\n this.expandGroup(walk);\n }\n walk = walk.parent();\n }\n this.items.attr('aria-selected', 'false');\n item.attr('aria-selected', 'true');\n this.triggerChange();\n };\n\n /**\n * Toggle the selected state for an item back and forth.\n *\n * @method toggleItem\n * @param {Object} item is the jquery id of the item to toggle.\n */\n Tree.prototype.toggleItem = function(item) {\n if (!this.multiSelect) {\n this.selectItem(item);\n return;\n }\n\n var current = item.attr('aria-selected');\n if (current === 'true') {\n current = 'false';\n } else {\n current = 'true';\n }\n item.attr('aria-selected', current);\n this.triggerChange();\n };\n\n /**\n * Set the focus to this item.\n *\n * @method updateFocus\n * @param {Object} item is the jquery id of the parent item of the group\n */\n Tree.prototype.updateFocus = function(item) {\n this.lastActiveItem = this.activeItem;\n this.activeItem = item;\n // Expand all nodes up the tree.\n var walk = item.parent();\n while (walk.attr('role') != 'tree') {\n walk = walk.parent();\n if (walk.attr('aria-expanded') == 'false') {\n this.expandGroup(walk);\n }\n walk = walk.parent();\n }\n this.items.attr('tabindex', '-1');\n item.attr('tabindex', 0);\n };\n\n /**\n * Handle a key down event - ie navigate the tree.\n *\n * @method handleKeyDown\n * @param {Object} item is the jquery id of the parent item of the group\n * @param {Event} e The event.\n * @return {Boolean}\n */\n // This function should be simplified. In the meantime..\n // eslint-disable-next-line complexity\n Tree.prototype.handleKeyDown = function(item, e) {\n var currentIndex = this.visibleItems.index(item);\n var newItem = null;\n var hasKeyModifier = e.shiftKey || e.ctrlKey || e.metaKey || e.altKey;\n var thisObj = this;\n\n switch (e.keyCode) {\n case this.keys.home: {\n // Jump to first item in tree.\n newItem = this.parents.first();\n newItem.focus();\n if (e.shiftKey) {\n this.multiSelectItem(newItem);\n } else if (!hasKeyModifier) {\n this.selectItem(newItem);\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.end: {\n // Jump to last visible item.\n newItem = this.visibleItems.last();\n newItem.focus();\n if (e.shiftKey) {\n this.multiSelectItem(newItem);\n } else if (!hasKeyModifier) {\n this.selectItem(newItem);\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.enter:\n case this.keys.space: {\n\n if (e.shiftKey) {\n this.multiSelectItem(item);\n } else if (e.metaKey || e.ctrlKey) {\n this.toggleItem(item);\n } else {\n this.selectItem(item);\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.left: {\n if (item.has('ul') && item.attr('aria-expanded') == 'true') {\n this.collapseGroup(item);\n } else {\n // Move up to the parent.\n var itemUL = item.parent();\n var itemParent = itemUL.parent();\n if (itemParent.is('li')) {\n itemParent.focus();\n if (e.shiftKey) {\n this.multiSelectItem(itemParent);\n } else if (!hasKeyModifier) {\n this.selectItem(itemParent);\n }\n }\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.right: {\n if (item.has('ul') && item.attr('aria-expanded') == 'false') {\n this.expandGroup(item);\n } else {\n // Move to the first item in the child group.\n newItem = item.children('ul').children('li').first();\n if (newItem.length > 0) {\n newItem.focus();\n if (e.shiftKey) {\n this.multiSelectItem(newItem);\n } else if (!hasKeyModifier) {\n this.selectItem(newItem);\n }\n }\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.up: {\n\n if (currentIndex > 0) {\n var prev = this.visibleItems.eq(currentIndex - 1);\n prev.focus();\n if (e.shiftKey) {\n this.multiSelectItem(prev);\n } else if (!hasKeyModifier) {\n this.selectItem(prev);\n }\n }\n\n e.stopPropagation();\n return false;\n }\n case this.keys.down: {\n\n if (currentIndex < this.visibleItems.length - 1) {\n var next = this.visibleItems.eq(currentIndex + 1);\n next.focus();\n if (e.shiftKey) {\n this.multiSelectItem(next);\n } else if (!hasKeyModifier) {\n this.selectItem(next);\n }\n }\n e.stopPropagation();\n return false;\n }\n case this.keys.asterisk: {\n // Expand all groups.\n this.parents.each(function() {\n thisObj.expandGroup($(this));\n });\n\n e.stopPropagation();\n return false;\n }\n case this.keys.eight: {\n if (e.shiftKey) {\n // Expand all groups.\n this.parents.each(function() {\n thisObj.expandGroup($(this));\n });\n\n e.stopPropagation();\n }\n\n return false;\n }\n }\n\n return true;\n };\n\n /**\n * Handle a key press event - ie navigate the tree.\n *\n * @method handleKeyPress\n * @param {Object} item is the jquery id of the parent item of the group\n * @param {Event} e The event.\n * @return {Boolean}\n */\n Tree.prototype.handleKeyPress = function(item, e) {\n if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {\n // Do nothing.\n return true;\n }\n\n switch (e.keyCode) {\n case this.keys.tab: {\n return true;\n }\n case this.keys.enter:\n case this.keys.home:\n case this.keys.end:\n case this.keys.left:\n case this.keys.right:\n case this.keys.up:\n case this.keys.down: {\n e.stopPropagation();\n return false;\n }\n default : {\n var chr = String.fromCharCode(e.which);\n var match = false;\n var itemIndex = this.visibleItems.index(item);\n var itemCount = this.visibleItems.length;\n var currentIndex = itemIndex + 1;\n\n // Check if the active item was the last one on the list.\n if (currentIndex == itemCount) {\n currentIndex = 0;\n }\n\n // Iterate through the menu items (starting from the current item and wrapping) until a match is found\n // or the loop returns to the current menu item.\n while (currentIndex != itemIndex) {\n\n var currentItem = this.visibleItems.eq(currentIndex);\n var titleChr = currentItem.text().charAt(0);\n\n if (currentItem.has('ul')) {\n titleChr = currentItem.find('span').text().charAt(0);\n }\n\n if (titleChr.toLowerCase() == chr) {\n match = true;\n break;\n }\n\n currentIndex = currentIndex + 1;\n if (currentIndex == itemCount) {\n // Reached the end of the list, start again at the beginning.\n currentIndex = 0;\n }\n }\n\n if (match === true) {\n this.updateFocus(this.visibleItems.eq(currentIndex));\n }\n e.stopPropagation();\n return false;\n }\n }\n\n // eslint-disable-next-line no-unreachable\n return true;\n };\n\n /**\n * Attach an event listener to the tree.\n *\n * @method on\n * @param {String} eventname This is the name of the event to listen for. Only 'selectionchanged' is supported for now.\n * @param {Function} handler The function to call when the event is triggered.\n */\n Tree.prototype.on = function(eventname, handler) {\n if (eventname !== 'selectionchanged') {\n log.warning('Invalid custom event name for tree. Only \"selectionchanged\" is supported.');\n } else {\n this.treeRoot.on(eventname, handler);\n }\n };\n\n /**\n * Handle a double click (expand/collapse).\n *\n * @method handleDblClick\n * @param {Object} item is the jquery id of the parent item of the group\n * @param {Event} e The event.\n * @return {Boolean}\n */\n Tree.prototype.handleDblClick = function(item, e) {\n\n if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {\n // Do nothing.\n return true;\n }\n\n // Apply the focus markup.\n this.updateFocus(item);\n\n // Expand or collapse the group.\n this.toggleGroup(item);\n\n e.stopPropagation();\n return false;\n };\n\n /**\n * Handle a click (select).\n *\n * @method handleExpandCollapseClick\n * @param {Object} item is the jquery id of the parent item of the group\n * @param {Event} e The event.\n * @return {Boolean}\n */\n Tree.prototype.handleExpandCollapseClick = function(item, e) {\n\n // Do not shift the focus.\n this.toggleGroup(item);\n e.stopPropagation();\n return false;\n };\n\n\n /**\n * Handle a click (select).\n *\n * @method handleClick\n * @param {Object} item is the jquery id of the parent item of the group\n * @param {Event} e The event.\n * @return {Boolean}\n */\n Tree.prototype.handleClick = function(item, e) {\n\n if (e.shiftKey) {\n this.multiSelectItem(item);\n } else if (e.metaKey || e.ctrlKey) {\n this.toggleItem(item);\n } else {\n this.selectItem(item);\n }\n this.updateFocus(item);\n e.stopPropagation();\n return false;\n };\n\n /**\n * Handle a blur event\n *\n * @method handleBlur\n * @return {Boolean}\n */\n Tree.prototype.handleBlur = function() {\n return true;\n };\n\n /**\n * Handle a focus event\n *\n * @method handleFocus\n * @param {Object} item item is the jquery id of the parent item of the group\n * @return {Boolean}\n */\n Tree.prototype.handleFocus = function(item) {\n\n this.updateFocus(item);\n\n return true;\n };\n\n /**\n * Bind the event listeners we require.\n *\n * @method bindEventHandlers\n */\n Tree.prototype.bindEventHandlers = function() {\n var thisObj = this;\n\n // Bind a dblclick handler to the parent items.\n this.parents.dblclick(function(e) {\n return thisObj.handleDblClick($(this), e);\n });\n\n // Bind a click handler.\n this.items.click(function(e) {\n return thisObj.handleClick($(this), e);\n });\n\n // Bind a toggle handler to the expand/collapse icons.\n this.items.children('img').click(function(e) {\n return thisObj.handleExpandCollapseClick($(this).parent(), e);\n });\n\n // Bind a keydown handler.\n this.items.keydown(function(e) {\n return thisObj.handleKeyDown($(this), e);\n });\n\n // Bind a keypress handler.\n this.items.keypress(function(e) {\n return thisObj.handleKeyPress($(this), e);\n });\n\n // Bind a focus handler.\n this.items.focus(function(e) {\n return thisObj.handleFocus($(this), e);\n });\n\n // Bind a blur handler.\n this.items.blur(function(e) {\n return thisObj.handleBlur($(this), e);\n });\n\n };\n\n return /** @alias module:tool_lp/tree */ Tree;\n});\n"],"names":["define","$","url","log","expandedImage","imageUrl","collapsedImage","Tree","selector","multiSelect","treeRoot","items","this","find","expandAll","length","parents","attr","visibleItems","activeItem","lastActiveItem","keys","tab","enter","space","pageup","pagedown","end","home","left","up","right","down","eight","asterisk","init","bindEventHandlers","prototype","prepend","clone","thisObj","each","collapseGroup","expandGroup","first","item","children","show","hide","toggleGroup","triggerChange","allSelected","filter","trigger","selected","multiSelectItem","lastIndex","index","currentIndex","get","selectItem","walk","parent","toggleItem","current","updateFocus","handleKeyDown","e","newItem","hasKeyModifier","shiftKey","ctrlKey","metaKey","altKey","keyCode","focus","stopPropagation","last","has","itemParent","is","prev","eq","next","handleKeyPress","chr","String","fromCharCode","which","match","itemIndex","itemCount","currentItem","titleChr","text","charAt","toLowerCase","on","eventname","handler","warning","handleDblClick","handleExpandCollapseClick","handleClick","handleBlur","handleFocus","dblclick","click","keydown","keypress","blur"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/user_competency_course_navigation.min.js b/admin/tool/lp/amd/build/user_competency_course_navigation.min.js
index 6bf284959ce..928414d4e67 100644
--- a/admin/tool/lp/amd/build/user_competency_course_navigation.min.js
+++ b/admin/tool/lp/amd/build/user_competency_course_navigation.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/user_competency_course_navigation",["jquery"],function(a){var b=function(b,c,d,e,f,g){this._baseUrl=d;this._userId=e+"";this._competencyId=f+"";this._courseId=g;a(b).on("change",this._userChanged.bind(this));a(c).on("change",this._competencyChanged.bind(this))};b.prototype._userChanged=function(b){var c=a(b.target).val(),d="?userid="+c+"&courseid="+this._courseId+"&competencyid="+this._competencyId;document.location=this._baseUrl+d};b.prototype._competencyChanged=function(b){var c=a(b.target).val(),d="?userid="+this._userId+"&courseid="+this._courseId+"&competencyid="+c;document.location=this._baseUrl+d};b.prototype._competencyId=null;b.prototype._userId=null;b.prototype._courseId=null;b.prototype._baseUrl=null;b.prototype._ignoreFirstCompetency=null;return b});
-//# sourceMappingURL=user_competency_course_navigation.min.js.map
+/**
+ * Module to enable inline editing of a comptency grade.
+ *
+ * @module tool_lp/user_competency_course_navigation
+ * @copyright 2015 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/user_competency_course_navigation",["jquery"],(function($){var UserCompetencyCourseNavigation=function(userSelector,competencySelector,baseUrl,userId,competencyId,courseId){this._baseUrl=baseUrl,this._userId=userId+"",this._competencyId=competencyId+"",this._courseId=courseId,$(userSelector).on("change",this._userChanged.bind(this)),$(competencySelector).on("change",this._competencyChanged.bind(this))};return UserCompetencyCourseNavigation.prototype._userChanged=function(e){var queryStr="?userid="+$(e.target).val()+"&courseid="+this._courseId+"&competencyid="+this._competencyId;document.location=this._baseUrl+queryStr},UserCompetencyCourseNavigation.prototype._competencyChanged=function(e){var newCompetencyId=$(e.target).val(),queryStr="?userid="+this._userId+"&courseid="+this._courseId+"&competencyid="+newCompetencyId;document.location=this._baseUrl+queryStr},UserCompetencyCourseNavigation.prototype._competencyId=null,UserCompetencyCourseNavigation.prototype._userId=null,UserCompetencyCourseNavigation.prototype._courseId=null,UserCompetencyCourseNavigation.prototype._baseUrl=null,UserCompetencyCourseNavigation.prototype._ignoreFirstCompetency=null,UserCompetencyCourseNavigation}));
+
+//# sourceMappingURL=user_competency_course_navigation.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/user_competency_course_navigation.min.js.map b/admin/tool/lp/amd/build/user_competency_course_navigation.min.js.map
index 15007d6d46a..180e7138397 100644
--- a/admin/tool/lp/amd/build/user_competency_course_navigation.min.js.map
+++ b/admin/tool/lp/amd/build/user_competency_course_navigation.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/user_competency_course_navigation.js"],"names":["define","$","UserCompetencyCourseNavigation","userSelector","competencySelector","baseUrl","userId","competencyId","courseId","_baseUrl","_userId","_competencyId","_courseId","on","_userChanged","bind","_competencyChanged","prototype","e","newUserId","target","val","queryStr","document","location","newCompetencyId","_ignoreFirstCompetency"],"mappings":"AAuBAA,OAAM,6CAAC,CAAC,QAAD,CAAD,CAAa,SAASC,CAAT,CAAY,CAa3B,GAAIC,CAAAA,CAA8B,CAAG,SAASC,CAAT,CAAuBC,CAAvB,CAA2CC,CAA3C,CAAoDC,CAApD,CAA4DC,CAA5D,CAA0EC,CAA1E,CAAoF,CACrH,KAAKC,QAAL,CAAgBJ,CAAhB,CACA,KAAKK,OAAL,CAAeJ,CAAM,CAAG,EAAxB,CACA,KAAKK,aAAL,CAAqBJ,CAAY,CAAG,EAApC,CACA,KAAKK,SAAL,CAAiBJ,CAAjB,CAEAP,CAAC,CAACE,CAAD,CAAD,CAAgBU,EAAhB,CAAmB,QAAnB,CAA6B,KAAKC,YAAL,CAAkBC,IAAlB,CAAuB,IAAvB,CAA7B,EACAd,CAAC,CAACG,CAAD,CAAD,CAAsBS,EAAtB,CAAyB,QAAzB,CAAmC,KAAKG,kBAAL,CAAwBD,IAAxB,CAA6B,IAA7B,CAAnC,CACH,CARD,CAgBAb,CAA8B,CAACe,SAA/B,CAAyCH,YAAzC,CAAwD,SAASI,CAAT,CAAY,IAC5DC,CAAAA,CAAS,CAAGlB,CAAC,CAACiB,CAAC,CAACE,MAAH,CAAD,CAAYC,GAAZ,EADgD,CAE5DC,CAAQ,CAAG,WAAaH,CAAb,CAAyB,YAAzB,CAAwC,KAAKP,SAA7C,CAAyD,gBAAzD,CAA4E,KAAKD,aAFhC,CAGhEY,QAAQ,CAACC,QAAT,CAAoB,KAAKf,QAAL,CAAgBa,CACvC,CAJD,CAYApB,CAA8B,CAACe,SAA/B,CAAyCD,kBAAzC,CAA8D,SAASE,CAAT,CAAY,IAClEO,CAAAA,CAAe,CAAGxB,CAAC,CAACiB,CAAC,CAACE,MAAH,CAAD,CAAYC,GAAZ,EADgD,CAElEC,CAAQ,CAAG,WAAa,KAAKZ,OAAlB,CAA4B,YAA5B,CAA2C,KAAKE,SAAhD,CAA4D,gBAA5D,CAA+Ea,CAFxB,CAGtEF,QAAQ,CAACC,QAAT,CAAoB,KAAKf,QAAL,CAAgBa,CACvC,CAJD,CAOApB,CAA8B,CAACe,SAA/B,CAAyCN,aAAzC,CAAyD,IAAzD,CAEAT,CAA8B,CAACe,SAA/B,CAAyCP,OAAzC,CAAmD,IAAnD,CAEAR,CAA8B,CAACe,SAA/B,CAAyCL,SAAzC,CAAqD,IAArD,CAEAV,CAA8B,CAACe,SAA/B,CAAyCR,QAAzC,CAAoD,IAApD,CAEAP,CAA8B,CAACe,SAA/B,CAAyCS,sBAAzC,CAAkE,IAAlE,CAEA,MAAOxB,CAAAA,CACV,CA3DK,CAAN","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 .\n\n/**\n * Module to enable inline editing of a comptency grade.\n *\n * @module tool_lp/user_competency_course_navigation\n * @copyright 2015 Damyon Wiese\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function($) {\n\n /**\n * UserCompetencyCourseNavigation\n *\n * @class tool_lp/user_competency_course_navigation\n * @param {String} userSelector The selector of the user element.\n * @param {String} competencySelector The selector of the competency element.\n * @param {String} baseUrl The base url for the page (no params).\n * @param {Number} userId The user id\n * @param {Number} competencyId The competency id\n * @param {Number} courseId The course id\n */\n var UserCompetencyCourseNavigation = function(userSelector, competencySelector, baseUrl, userId, competencyId, courseId) {\n this._baseUrl = baseUrl;\n this._userId = userId + '';\n this._competencyId = competencyId + '';\n this._courseId = courseId;\n\n $(userSelector).on('change', this._userChanged.bind(this));\n $(competencySelector).on('change', this._competencyChanged.bind(this));\n };\n\n /**\n * The user was changed in the select list.\n *\n * @method _userChanged\n * @param {Event} e\n */\n UserCompetencyCourseNavigation.prototype._userChanged = function(e) {\n var newUserId = $(e.target).val();\n var queryStr = '?userid=' + newUserId + '&courseid=' + this._courseId + '&competencyid=' + this._competencyId;\n document.location = this._baseUrl + queryStr;\n };\n\n /**\n * The competency was changed in the select list.\n *\n * @method _competencyChanged\n * @param {Event} e\n */\n UserCompetencyCourseNavigation.prototype._competencyChanged = function(e) {\n var newCompetencyId = $(e.target).val();\n var queryStr = '?userid=' + this._userId + '&courseid=' + this._courseId + '&competencyid=' + newCompetencyId;\n document.location = this._baseUrl + queryStr;\n };\n\n /** @property {Number} The id of the competency. */\n UserCompetencyCourseNavigation.prototype._competencyId = null;\n /** @property {Number} The id of the user. */\n UserCompetencyCourseNavigation.prototype._userId = null;\n /** @property {Number} The id of the course. */\n UserCompetencyCourseNavigation.prototype._courseId = null;\n /** @property {String} Plugin base url. */\n UserCompetencyCourseNavigation.prototype._baseUrl = null;\n /** @property {Boolean} Ignore the first change event for competencies. */\n UserCompetencyCourseNavigation.prototype._ignoreFirstCompetency = null;\n\n return UserCompetencyCourseNavigation;\n});\n"],"file":"user_competency_course_navigation.min.js"}
\ No newline at end of file
+{"version":3,"file":"user_competency_course_navigation.min.js","sources":["../src/user_competency_course_navigation.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 .\n\n/**\n * Module to enable inline editing of a comptency grade.\n *\n * @module tool_lp/user_competency_course_navigation\n * @copyright 2015 Damyon Wiese\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function($) {\n\n /**\n * UserCompetencyCourseNavigation\n *\n * @class tool_lp/user_competency_course_navigation\n * @param {String} userSelector The selector of the user element.\n * @param {String} competencySelector The selector of the competency element.\n * @param {String} baseUrl The base url for the page (no params).\n * @param {Number} userId The user id\n * @param {Number} competencyId The competency id\n * @param {Number} courseId The course id\n */\n var UserCompetencyCourseNavigation = function(userSelector, competencySelector, baseUrl, userId, competencyId, courseId) {\n this._baseUrl = baseUrl;\n this._userId = userId + '';\n this._competencyId = competencyId + '';\n this._courseId = courseId;\n\n $(userSelector).on('change', this._userChanged.bind(this));\n $(competencySelector).on('change', this._competencyChanged.bind(this));\n };\n\n /**\n * The user was changed in the select list.\n *\n * @method _userChanged\n * @param {Event} e\n */\n UserCompetencyCourseNavigation.prototype._userChanged = function(e) {\n var newUserId = $(e.target).val();\n var queryStr = '?userid=' + newUserId + '&courseid=' + this._courseId + '&competencyid=' + this._competencyId;\n document.location = this._baseUrl + queryStr;\n };\n\n /**\n * The competency was changed in the select list.\n *\n * @method _competencyChanged\n * @param {Event} e\n */\n UserCompetencyCourseNavigation.prototype._competencyChanged = function(e) {\n var newCompetencyId = $(e.target).val();\n var queryStr = '?userid=' + this._userId + '&courseid=' + this._courseId + '&competencyid=' + newCompetencyId;\n document.location = this._baseUrl + queryStr;\n };\n\n /** @property {Number} The id of the competency. */\n UserCompetencyCourseNavigation.prototype._competencyId = null;\n /** @property {Number} The id of the user. */\n UserCompetencyCourseNavigation.prototype._userId = null;\n /** @property {Number} The id of the course. */\n UserCompetencyCourseNavigation.prototype._courseId = null;\n /** @property {String} Plugin base url. */\n UserCompetencyCourseNavigation.prototype._baseUrl = null;\n /** @property {Boolean} Ignore the first change event for competencies. */\n UserCompetencyCourseNavigation.prototype._ignoreFirstCompetency = null;\n\n return UserCompetencyCourseNavigation;\n});\n"],"names":["define","$","UserCompetencyCourseNavigation","userSelector","competencySelector","baseUrl","userId","competencyId","courseId","_baseUrl","_userId","_competencyId","_courseId","on","this","_userChanged","bind","_competencyChanged","prototype","e","queryStr","target","val","document","location","newCompetencyId","_ignoreFirstCompetency"],"mappings":";;;;;;;AAuBAA,mDAAO,CAAC,WAAW,SAASC,OAapBC,+BAAiC,SAASC,aAAcC,mBAAoBC,QAASC,OAAQC,aAAcC,eACtGC,SAAWJ,aACXK,QAAUJ,OAAS,QACnBK,cAAgBJ,aAAe,QAC/BK,UAAYJ,SAEjBP,EAAEE,cAAcU,GAAG,SAAUC,KAAKC,aAAaC,KAAKF,OACpDb,EAAEG,oBAAoBS,GAAG,SAAUC,KAAKG,mBAAmBD,KAAKF,eASpEZ,+BAA+BgB,UAAUH,aAAe,SAASI,OAEzDC,SAAW,WADCnB,EAAEkB,EAAEE,QAAQC,MACY,aAAeR,KAAKF,UAAY,iBAAmBE,KAAKH,cAChGY,SAASC,SAAWV,KAAKL,SAAWW,UASxClB,+BAA+BgB,UAAUD,mBAAqB,SAASE,OAC/DM,gBAAkBxB,EAAEkB,EAAEE,QAAQC,MAC9BF,SAAW,WAAaN,KAAKJ,QAAU,aAAeI,KAAKF,UAAY,iBAAmBa,gBAC9FF,SAASC,SAAWV,KAAKL,SAAWW,UAIxClB,+BAA+BgB,UAAUP,cAAgB,KAEzDT,+BAA+BgB,UAAUR,QAAU,KAEnDR,+BAA+BgB,UAAUN,UAAY,KAErDV,+BAA+BgB,UAAUT,SAAW,KAEpDP,+BAA+BgB,UAAUQ,uBAAyB,KAE3DxB"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/user_competency_info.min.js b/admin/tool/lp/amd/build/user_competency_info.min.js
index c4a3f727781..271a5f6e0e3 100644
--- a/admin/tool/lp/amd/build/user_competency_info.min.js
+++ b/admin/tool/lp/amd/build/user_competency_info.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/user_competency_info",["jquery","core/notification","core/ajax","core/templates"],function(a,b,c,d){var e=function(a,b,c,d,e,f){this._rootElement=a;this._competencyId=b;this._userId=c;this._planId=d;this._courseId=e;this._valid=!0;this._displayuser="undefined"!=typeof f?f:!1;if(this._planId){this._methodName="tool_lp_data_for_user_competency_summary_in_plan";this._args={competencyid:this._competencyId,planid:this._planId};this._templateName="tool_lp/user_competency_summary_in_plan"}else if(this._courseId){this._methodName="tool_lp_data_for_user_competency_summary_in_course";this._args={userid:this._userId,competencyid:this._competencyId,courseid:this._courseId};this._templateName="tool_lp/user_competency_summary_in_course"}else{this._methodName="tool_lp_data_for_user_competency_summary";this._args={userid:this._userId,competencyid:this._competencyId};this._templateName="tool_lp/user_competency_summary"}};e.prototype.reload=function(){var a=this,e=[];if(!this._valid){return}e=c.call([{methodname:this._methodName,args:this._args}]);e[0].done(function(c){if(a._displayuser){c.displayuser=!0}d.render(a._templateName,c).done(function(b,c){d.replaceNode(a._rootElement,b,c)}).fail(b.exception)}).fail(b.exception)};e.prototype._rootElement=null;e.prototype._courseId=null;e.prototype._valid=null;e.prototype._planId=null;e.prototype._competencyId=null;e.prototype._userId=null;e.prototype._methodName=null;e.prototype._args=null;e.prototype._templateName=null;e.prototype._displayuser=!1;return e});
-//# sourceMappingURL=user_competency_info.min.js.map
+/**
+ * Module to refresh a user competency summary in a page.
+ *
+ * @module tool_lp/user_competency_info
+ * @copyright 2015 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/user_competency_info",["jquery","core/notification","core/ajax","core/templates"],(function($,notification,ajax,templates){var Info=function(rootElement,competencyId,userId,planId,courseId,displayuser){this._rootElement=rootElement,this._competencyId=competencyId,this._userId=userId,this._planId=planId,this._courseId=courseId,this._valid=!0,this._displayuser=void 0!==displayuser&&displayuser,this._planId?(this._methodName="tool_lp_data_for_user_competency_summary_in_plan",this._args={competencyid:this._competencyId,planid:this._planId},this._templateName="tool_lp/user_competency_summary_in_plan"):this._courseId?(this._methodName="tool_lp_data_for_user_competency_summary_in_course",this._args={userid:this._userId,competencyid:this._competencyId,courseid:this._courseId},this._templateName="tool_lp/user_competency_summary_in_course"):(this._methodName="tool_lp_data_for_user_competency_summary",this._args={userid:this._userId,competencyid:this._competencyId},this._templateName="tool_lp/user_competency_summary")};return Info.prototype.reload=function(){var self=this;this._valid&&ajax.call([{methodname:this._methodName,args:this._args}])[0].done((function(context){self._displayuser&&(context.displayuser=!0),templates.render(self._templateName,context).done((function(html,js){templates.replaceNode(self._rootElement,html,js)})).fail(notification.exception)})).fail(notification.exception)},Info.prototype._rootElement=null,Info.prototype._courseId=null,Info.prototype._valid=null,Info.prototype._planId=null,Info.prototype._competencyId=null,Info.prototype._userId=null,Info.prototype._methodName=null,Info.prototype._args=null,Info.prototype._templateName=null,Info.prototype._displayuser=!1,Info}));
+
+//# sourceMappingURL=user_competency_info.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/user_competency_info.min.js.map b/admin/tool/lp/amd/build/user_competency_info.min.js.map
index 2d7caa901c0..6a86054a7a4 100644
--- a/admin/tool/lp/amd/build/user_competency_info.min.js.map
+++ b/admin/tool/lp/amd/build/user_competency_info.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/user_competency_info.js"],"names":["define","$","notification","ajax","templates","Info","rootElement","competencyId","userId","planId","courseId","displayuser","_rootElement","_competencyId","_userId","_planId","_courseId","_valid","_displayuser","_methodName","_args","competencyid","planid","_templateName","userid","courseid","prototype","reload","self","promises","call","methodname","args","done","context","render","html","js","replaceNode","fail","exception"],"mappings":"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","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 .\n\n/**\n * Module to refresh a user competency summary in a page.\n *\n * @module tool_lp/user_competency_info\n * @copyright 2015 Damyon Wiese\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/notification', 'core/ajax', 'core/templates'], function($, notification, ajax, templates) {\n\n /**\n * Info\n *\n * @param {JQuery} rootElement Selector to replace when the information needs updating.\n * @param {Number} competencyId The id of the competency.\n * @param {Number} userId The id of the user.\n * @param {Number} planId The id of the plan.\n * @param {Number} courseId The id of the course.\n * @param {Boolean} displayuser If we should display the user info.\n */\n var Info = function(rootElement, competencyId, userId, planId, courseId, displayuser) {\n this._rootElement = rootElement;\n this._competencyId = competencyId;\n this._userId = userId;\n this._planId = planId;\n this._courseId = courseId;\n this._valid = true;\n this._displayuser = (typeof displayuser !== 'undefined') ? displayuser : false;\n\n if (this._planId) {\n this._methodName = 'tool_lp_data_for_user_competency_summary_in_plan';\n this._args = {competencyid: this._competencyId, planid: this._planId};\n this._templateName = 'tool_lp/user_competency_summary_in_plan';\n } else if (this._courseId) {\n this._methodName = 'tool_lp_data_for_user_competency_summary_in_course';\n this._args = {userid: this._userId, competencyid: this._competencyId, courseid: this._courseId};\n this._templateName = 'tool_lp/user_competency_summary_in_course';\n } else {\n this._methodName = 'tool_lp_data_for_user_competency_summary';\n this._args = {userid: this._userId, competencyid: this._competencyId};\n this._templateName = 'tool_lp/user_competency_summary';\n }\n };\n\n /**\n * Reload the info for this user competency.\n *\n * @method reload\n */\n Info.prototype.reload = function() {\n var self = this,\n promises = [];\n\n if (!this._valid) {\n return;\n }\n\n promises = ajax.call([{\n methodname: this._methodName,\n args: this._args\n }]);\n\n promises[0].done(function(context) {\n // Check if we should also the user info.\n if (self._displayuser) {\n context.displayuser = true;\n }\n templates.render(self._templateName, context).done(function(html, js) {\n templates.replaceNode(self._rootElement, html, js);\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /** @property {JQuery} The root element to replace in the DOM. */\n Info.prototype._rootElement = null;\n /** @property {Number} The id of the course. */\n Info.prototype._courseId = null;\n /** @property {Boolean} Is this module valid? */\n Info.prototype._valid = null;\n /** @property {Number} The id of the plan. */\n Info.prototype._planId = null;\n /** @property {Number} The id of the competency. */\n Info.prototype._competencyId = null;\n /** @property {Number} The id of the user. */\n Info.prototype._userId = null;\n /** @property {String} The method name to load the data. */\n Info.prototype._methodName = null;\n /** @property {Object} The arguments to load the data. */\n Info.prototype._args = null;\n /** @property {String} The template to reload the fragment. */\n Info.prototype._templateName = null;\n /** @property {Boolean} If we should display the user info? */\n Info.prototype._displayuser = false;\n\n return /** @alias module:tool_lp/user_competency_info */ Info;\n\n});\n"],"file":"user_competency_info.min.js"}
\ No newline at end of file
+{"version":3,"file":"user_competency_info.min.js","sources":["../src/user_competency_info.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 .\n\n/**\n * Module to refresh a user competency summary in a page.\n *\n * @module tool_lp/user_competency_info\n * @copyright 2015 Damyon Wiese\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/notification', 'core/ajax', 'core/templates'], function($, notification, ajax, templates) {\n\n /**\n * Info\n *\n * @param {JQuery} rootElement Selector to replace when the information needs updating.\n * @param {Number} competencyId The id of the competency.\n * @param {Number} userId The id of the user.\n * @param {Number} planId The id of the plan.\n * @param {Number} courseId The id of the course.\n * @param {Boolean} displayuser If we should display the user info.\n */\n var Info = function(rootElement, competencyId, userId, planId, courseId, displayuser) {\n this._rootElement = rootElement;\n this._competencyId = competencyId;\n this._userId = userId;\n this._planId = planId;\n this._courseId = courseId;\n this._valid = true;\n this._displayuser = (typeof displayuser !== 'undefined') ? displayuser : false;\n\n if (this._planId) {\n this._methodName = 'tool_lp_data_for_user_competency_summary_in_plan';\n this._args = {competencyid: this._competencyId, planid: this._planId};\n this._templateName = 'tool_lp/user_competency_summary_in_plan';\n } else if (this._courseId) {\n this._methodName = 'tool_lp_data_for_user_competency_summary_in_course';\n this._args = {userid: this._userId, competencyid: this._competencyId, courseid: this._courseId};\n this._templateName = 'tool_lp/user_competency_summary_in_course';\n } else {\n this._methodName = 'tool_lp_data_for_user_competency_summary';\n this._args = {userid: this._userId, competencyid: this._competencyId};\n this._templateName = 'tool_lp/user_competency_summary';\n }\n };\n\n /**\n * Reload the info for this user competency.\n *\n * @method reload\n */\n Info.prototype.reload = function() {\n var self = this,\n promises = [];\n\n if (!this._valid) {\n return;\n }\n\n promises = ajax.call([{\n methodname: this._methodName,\n args: this._args\n }]);\n\n promises[0].done(function(context) {\n // Check if we should also the user info.\n if (self._displayuser) {\n context.displayuser = true;\n }\n templates.render(self._templateName, context).done(function(html, js) {\n templates.replaceNode(self._rootElement, html, js);\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /** @property {JQuery} The root element to replace in the DOM. */\n Info.prototype._rootElement = null;\n /** @property {Number} The id of the course. */\n Info.prototype._courseId = null;\n /** @property {Boolean} Is this module valid? */\n Info.prototype._valid = null;\n /** @property {Number} The id of the plan. */\n Info.prototype._planId = null;\n /** @property {Number} The id of the competency. */\n Info.prototype._competencyId = null;\n /** @property {Number} The id of the user. */\n Info.prototype._userId = null;\n /** @property {String} The method name to load the data. */\n Info.prototype._methodName = null;\n /** @property {Object} The arguments to load the data. */\n Info.prototype._args = null;\n /** @property {String} The template to reload the fragment. */\n Info.prototype._templateName = null;\n /** @property {Boolean} If we should display the user info? */\n Info.prototype._displayuser = false;\n\n return /** @alias module:tool_lp/user_competency_info */ Info;\n\n});\n"],"names":["define","$","notification","ajax","templates","Info","rootElement","competencyId","userId","planId","courseId","displayuser","_rootElement","_competencyId","_userId","_planId","_courseId","_valid","_displayuser","this","_methodName","_args","competencyid","planid","_templateName","userid","courseid","prototype","reload","self","call","methodname","args","done","context","render","html","js","replaceNode","fail","exception"],"mappings":";;;;;;;AAuBAA,sCAAO,CAAC,SAAU,oBAAqB,YAAa,mBAAmB,SAASC,EAAGC,aAAcC,KAAMC,eAY/FC,KAAO,SAASC,YAAaC,aAAcC,OAAQC,OAAQC,SAAUC,kBAChEC,aAAeN,iBACfO,cAAgBN,kBAChBO,QAAUN,YACVO,QAAUN,YACVO,UAAYN,cACZO,QAAS,OACTC,kBAAuC,IAAhBP,aAA+BA,YAEvDQ,KAAKJ,cACAK,YAAc,wDACdC,MAAQ,CAACC,aAAcH,KAAKN,cAAeU,OAAQJ,KAAKJ,cACxDS,cAAgB,2CACdL,KAAKH,gBACPI,YAAc,0DACdC,MAAQ,CAACI,OAAQN,KAAKL,QAASQ,aAAcH,KAAKN,cAAea,SAAUP,KAAKH,gBAChFQ,cAAgB,mDAEhBJ,YAAc,gDACdC,MAAQ,CAACI,OAAQN,KAAKL,QAASQ,aAAcH,KAAKN,oBAClDW,cAAgB,2CAS7BnB,KAAKsB,UAAUC,OAAS,eAChBC,KAAOV,KAGNA,KAAKF,QAICd,KAAK2B,KAAK,CAAC,CAClBC,WAAYZ,KAAKC,YACjBY,KAAMb,KAAKE,SAGN,GAAGY,MAAK,SAASC,SAElBL,KAAKX,eACLgB,QAAQvB,aAAc,GAE1BP,UAAU+B,OAAON,KAAKL,cAAeU,SAASD,MAAK,SAASG,KAAMC,IAC9DjC,UAAUkC,YAAYT,KAAKjB,aAAcwB,KAAMC,OAChDE,KAAKrC,aAAasC,cACtBD,KAAKrC,aAAasC,YAIzBnC,KAAKsB,UAAUf,aAAe,KAE9BP,KAAKsB,UAAUX,UAAY,KAE3BX,KAAKsB,UAAUV,OAAS,KAExBZ,KAAKsB,UAAUZ,QAAU,KAEzBV,KAAKsB,UAAUd,cAAgB,KAE/BR,KAAKsB,UAAUb,QAAU,KAEzBT,KAAKsB,UAAUP,YAAc,KAE7Bf,KAAKsB,UAAUN,MAAQ,KAEvBhB,KAAKsB,UAAUH,cAAgB,KAE/BnB,KAAKsB,UAAUT,cAAe,EAE2Bb"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/user_competency_plan_popup.min.js b/admin/tool/lp/amd/build/user_competency_plan_popup.min.js
index cda67b49907..f05a6e8b24d 100644
--- a/admin/tool/lp/amd/build/user_competency_plan_popup.min.js
+++ b/admin/tool/lp/amd/build/user_competency_plan_popup.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/user_competency_plan_popup",["jquery","core/notification","core/str","core/ajax","core/templates","tool_lp/dialogue"],function(a,b,c,d,e,f){var g=function(b,c,d){this._regionSelector=b;this._userCompetencySelector=c;this._planId=d;a(this._regionSelector).on("click",this._userCompetencySelector,this._handleClick.bind(this))};g.prototype._handleClick=function(c){c.preventDefault();var e=a(c.target).closest("tr"),f=a(e).data("competencyid"),g=a(e).data("userid"),h=this._planId,i=d.call([{methodname:"tool_lp_data_for_user_competency_summary_in_plan",args:{competencyid:f,planid:h},done:this._contextLoaded.bind(this),fail:b.exception}]);i[0].then(function(a){var b="core_competency_user_competency_viewed_in_plan";if(a.plan.iscompleted){b="core_competency_user_competency_plan_viewed"}return d.call([{methodname:b,args:{competencyid:f,userid:g,planid:h}}])[0]}).catch(b.exception)};g.prototype._contextLoaded=function(a){var d=this;e.render("tool_lp/user_competency_summary_in_plan",a).done(function(a,g){c.get_string("usercompetencysummary","report_competency").done(function(b){new f(b,a,e.runTemplateJS.bind(e,g),d._refresh.bind(d),!0)}).fail(b.exception)}).fail(b.exception)};g.prototype._refresh=function(){var a=this._planId;d.call([{methodname:"tool_lp_data_for_plan_page",args:{planid:a},done:this._pageContextLoaded.bind(this),fail:b.exception}])};g.prototype._pageContextLoaded=function(a){var c=this;e.render("tool_lp/plan_page",a).done(function(a,b){e.replaceNode(c._regionSelector,a,b)}).fail(b.exception)};g.prototype._regionSelector=null;g.prototype._userCompetencySelector=null;g.prototype._planId=null;return g});
-//# sourceMappingURL=user_competency_plan_popup.min.js.map
+/**
+ * Module to open user competency plan in popup
+ *
+ * @module tool_lp/user_competency_plan_popup
+ * @copyright 2016 Issam Taboubi
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/user_competency_plan_popup",["jquery","core/notification","core/str","core/ajax","core/templates","tool_lp/dialogue"],(function($,notification,str,ajax,templates,Dialogue){var UserCompetencyPopup=function(regionSelector,userCompetencySelector,planId){this._regionSelector=regionSelector,this._userCompetencySelector=userCompetencySelector,this._planId=planId,$(this._regionSelector).on("click",this._userCompetencySelector,this._handleClick.bind(this))};return UserCompetencyPopup.prototype._handleClick=function(e){e.preventDefault();var tr=$(e.target).closest("tr"),competencyId=$(tr).data("competencyid"),userId=$(tr).data("userid"),planId=this._planId;ajax.call([{methodname:"tool_lp_data_for_user_competency_summary_in_plan",args:{competencyid:competencyId,planid:planId},done:this._contextLoaded.bind(this),fail:notification.exception}])[0].then((function(result){var eventMethodName="core_competency_user_competency_viewed_in_plan";return result.plan.iscompleted&&(eventMethodName="core_competency_user_competency_plan_viewed"),ajax.call([{methodname:eventMethodName,args:{competencyid:competencyId,userid:userId,planid:planId}}])[0]})).catch(notification.exception)},UserCompetencyPopup.prototype._contextLoaded=function(context){var self=this;templates.render("tool_lp/user_competency_summary_in_plan",context).done((function(html,js){str.get_string("usercompetencysummary","report_competency").done((function(title){new Dialogue(title,html,templates.runTemplateJS.bind(templates,js),self._refresh.bind(self),!0)})).fail(notification.exception)})).fail(notification.exception)},UserCompetencyPopup.prototype._refresh=function(){var planId=this._planId;ajax.call([{methodname:"tool_lp_data_for_plan_page",args:{planid:planId},done:this._pageContextLoaded.bind(this),fail:notification.exception}])},UserCompetencyPopup.prototype._pageContextLoaded=function(context){var self=this;templates.render("tool_lp/plan_page",context).done((function(html,js){templates.replaceNode(self._regionSelector,html,js)})).fail(notification.exception)},UserCompetencyPopup.prototype._regionSelector=null,UserCompetencyPopup.prototype._userCompetencySelector=null,UserCompetencyPopup.prototype._planId=null,UserCompetencyPopup}));
+
+//# sourceMappingURL=user_competency_plan_popup.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/user_competency_plan_popup.min.js.map b/admin/tool/lp/amd/build/user_competency_plan_popup.min.js.map
index ec205079c83..14958c5e65c 100644
--- a/admin/tool/lp/amd/build/user_competency_plan_popup.min.js.map
+++ b/admin/tool/lp/amd/build/user_competency_plan_popup.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/user_competency_plan_popup.js"],"names":["define","$","notification","str","ajax","templates","Dialogue","UserCompetencyPopup","regionSelector","userCompetencySelector","planId","_regionSelector","_userCompetencySelector","_planId","on","_handleClick","bind","prototype","e","preventDefault","tr","target","closest","competencyId","data","userId","requests","call","methodname","args","competencyid","planid","done","_contextLoaded","fail","exception","then","result","eventMethodName","plan","iscompleted","userid","catch","context","self","render","html","js","get_string","title","runTemplateJS","_refresh","_pageContextLoaded","replaceNode"],"mappings":"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","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 .\n\n/**\n * Module to open user competency plan in popup\n *\n * @module tool_lp/user_competency_plan_popup\n * @copyright 2016 Issam Taboubi \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/notification', 'core/str', 'core/ajax', 'core/templates', 'tool_lp/dialogue'],\n function($, notification, str, ajax, templates, Dialogue) {\n\n /**\n * UserCompetencyPopup\n *\n * @param {String} regionSelector The regionSelector\n * @param {String} userCompetencySelector The userCompetencySelector\n * @param {Number} planId The plan ID\n */\n var UserCompetencyPopup = function(regionSelector, userCompetencySelector, planId) {\n this._regionSelector = regionSelector;\n this._userCompetencySelector = userCompetencySelector;\n this._planId = planId;\n\n $(this._regionSelector).on('click', this._userCompetencySelector, this._handleClick.bind(this));\n };\n\n /**\n * Get the data from the closest TR and open the popup.\n *\n * @method _handleClick\n * @param {Event} e\n */\n UserCompetencyPopup.prototype._handleClick = function(e) {\n e.preventDefault();\n var tr = $(e.target).closest('tr');\n var competencyId = $(tr).data('competencyid');\n var userId = $(tr).data('userid');\n var planId = this._planId;\n\n var requests = ajax.call([{\n methodname: 'tool_lp_data_for_user_competency_summary_in_plan',\n args: {competencyid: competencyId, planid: planId},\n done: this._contextLoaded.bind(this),\n fail: notification.exception\n }]);\n // Log the user competency viewed in plan event.\n requests[0].then(function(result) {\n var eventMethodName = 'core_competency_user_competency_viewed_in_plan';\n // Trigger core_competency_user_competency_plan_viewed event instead if plan is already completed.\n if (result.plan.iscompleted) {\n eventMethodName = 'core_competency_user_competency_plan_viewed';\n }\n return ajax.call([{\n methodname: eventMethodName,\n args: {competencyid: competencyId, userid: userId, planid: planId}\n }])[0];\n }).catch(notification.exception);\n };\n\n /**\n * We loaded the context, now render the template.\n *\n * @method _contextLoaded\n * @param {Object} context\n */\n UserCompetencyPopup.prototype._contextLoaded = function(context) {\n var self = this;\n templates.render('tool_lp/user_competency_summary_in_plan', context).done(function(html, js) {\n str.get_string('usercompetencysummary', 'report_competency').done(function(title) {\n (new Dialogue(title, html, templates.runTemplateJS.bind(templates, js), self._refresh.bind(self), true));\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Refresh the page.\n *\n * @method _refresh\n */\n UserCompetencyPopup.prototype._refresh = function() {\n var planId = this._planId;\n\n ajax.call([{\n methodname: 'tool_lp_data_for_plan_page',\n args: {planid: planId},\n done: this._pageContextLoaded.bind(this),\n fail: notification.exception\n }]);\n };\n\n /**\n * We loaded the context, now render the template.\n *\n * @method _pageContextLoaded\n * @param {Object} context\n */\n UserCompetencyPopup.prototype._pageContextLoaded = function(context) {\n var self = this;\n templates.render('tool_lp/plan_page', context).done(function(html, js) {\n templates.replaceNode(self._regionSelector, html, js);\n }).fail(notification.exception);\n };\n\n /** @property {String} The selector for the region with the user competencies */\n UserCompetencyPopup.prototype._regionSelector = null;\n /** @property {String} The selector for the region with a single user competencies */\n UserCompetencyPopup.prototype._userCompetencySelector = null;\n /** @property {Number} The plan Id */\n UserCompetencyPopup.prototype._planId = null;\n\n return /** @alias module:tool_lp/user_competency_plan_popup */ UserCompetencyPopup;\n\n});\n"],"file":"user_competency_plan_popup.min.js"}
\ No newline at end of file
+{"version":3,"file":"user_competency_plan_popup.min.js","sources":["../src/user_competency_plan_popup.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 .\n\n/**\n * Module to open user competency plan in popup\n *\n * @module tool_lp/user_competency_plan_popup\n * @copyright 2016 Issam Taboubi \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/notification', 'core/str', 'core/ajax', 'core/templates', 'tool_lp/dialogue'],\n function($, notification, str, ajax, templates, Dialogue) {\n\n /**\n * UserCompetencyPopup\n *\n * @param {String} regionSelector The regionSelector\n * @param {String} userCompetencySelector The userCompetencySelector\n * @param {Number} planId The plan ID\n */\n var UserCompetencyPopup = function(regionSelector, userCompetencySelector, planId) {\n this._regionSelector = regionSelector;\n this._userCompetencySelector = userCompetencySelector;\n this._planId = planId;\n\n $(this._regionSelector).on('click', this._userCompetencySelector, this._handleClick.bind(this));\n };\n\n /**\n * Get the data from the closest TR and open the popup.\n *\n * @method _handleClick\n * @param {Event} e\n */\n UserCompetencyPopup.prototype._handleClick = function(e) {\n e.preventDefault();\n var tr = $(e.target).closest('tr');\n var competencyId = $(tr).data('competencyid');\n var userId = $(tr).data('userid');\n var planId = this._planId;\n\n var requests = ajax.call([{\n methodname: 'tool_lp_data_for_user_competency_summary_in_plan',\n args: {competencyid: competencyId, planid: planId},\n done: this._contextLoaded.bind(this),\n fail: notification.exception\n }]);\n // Log the user competency viewed in plan event.\n requests[0].then(function(result) {\n var eventMethodName = 'core_competency_user_competency_viewed_in_plan';\n // Trigger core_competency_user_competency_plan_viewed event instead if plan is already completed.\n if (result.plan.iscompleted) {\n eventMethodName = 'core_competency_user_competency_plan_viewed';\n }\n return ajax.call([{\n methodname: eventMethodName,\n args: {competencyid: competencyId, userid: userId, planid: planId}\n }])[0];\n }).catch(notification.exception);\n };\n\n /**\n * We loaded the context, now render the template.\n *\n * @method _contextLoaded\n * @param {Object} context\n */\n UserCompetencyPopup.prototype._contextLoaded = function(context) {\n var self = this;\n templates.render('tool_lp/user_competency_summary_in_plan', context).done(function(html, js) {\n str.get_string('usercompetencysummary', 'report_competency').done(function(title) {\n (new Dialogue(title, html, templates.runTemplateJS.bind(templates, js), self._refresh.bind(self), true));\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Refresh the page.\n *\n * @method _refresh\n */\n UserCompetencyPopup.prototype._refresh = function() {\n var planId = this._planId;\n\n ajax.call([{\n methodname: 'tool_lp_data_for_plan_page',\n args: {planid: planId},\n done: this._pageContextLoaded.bind(this),\n fail: notification.exception\n }]);\n };\n\n /**\n * We loaded the context, now render the template.\n *\n * @method _pageContextLoaded\n * @param {Object} context\n */\n UserCompetencyPopup.prototype._pageContextLoaded = function(context) {\n var self = this;\n templates.render('tool_lp/plan_page', context).done(function(html, js) {\n templates.replaceNode(self._regionSelector, html, js);\n }).fail(notification.exception);\n };\n\n /** @property {String} The selector for the region with the user competencies */\n UserCompetencyPopup.prototype._regionSelector = null;\n /** @property {String} The selector for the region with a single user competencies */\n UserCompetencyPopup.prototype._userCompetencySelector = null;\n /** @property {Number} The plan Id */\n UserCompetencyPopup.prototype._planId = null;\n\n return /** @alias module:tool_lp/user_competency_plan_popup */ UserCompetencyPopup;\n\n});\n"],"names":["define","$","notification","str","ajax","templates","Dialogue","UserCompetencyPopup","regionSelector","userCompetencySelector","planId","_regionSelector","_userCompetencySelector","_planId","this","on","_handleClick","bind","prototype","e","preventDefault","tr","target","closest","competencyId","data","userId","call","methodname","args","competencyid","planid","done","_contextLoaded","fail","exception","then","result","eventMethodName","plan","iscompleted","userid","catch","context","self","render","html","js","get_string","title","runTemplateJS","_refresh","_pageContextLoaded","replaceNode"],"mappings":";;;;;;;AAuBAA,4CAAO,CAAC,SAAU,oBAAqB,WAAY,YAAa,iBAAkB,qBAC3E,SAASC,EAAGC,aAAcC,IAAKC,KAAMC,UAAWC,cAS/CC,oBAAsB,SAASC,eAAgBC,uBAAwBC,aAClEC,gBAAkBH,oBAClBI,wBAA0BH,4BAC1BI,QAAUH,OAEfT,EAAEa,KAAKH,iBAAiBI,GAAG,QAASD,KAAKF,wBAAyBE,KAAKE,aAAaC,KAAKH,eAS7FP,oBAAoBW,UAAUF,aAAe,SAASG,GAClDA,EAAEC,qBACEC,GAAKpB,EAAEkB,EAAEG,QAAQC,QAAQ,MACzBC,aAAevB,EAAEoB,IAAII,KAAK,gBAC1BC,OAASzB,EAAEoB,IAAII,KAAK,UACpBf,OAASI,KAAKD,QAEHT,KAAKuB,KAAK,CAAC,CACtBC,WAAY,mDACZC,KAAM,CAACC,aAAcN,aAAcO,OAAQrB,QAC3CsB,KAAMlB,KAAKmB,eAAehB,KAAKH,MAC/BoB,KAAMhC,aAAaiC,aAGd,GAAGC,MAAK,SAASC,YAClBC,gBAAkB,wDAElBD,OAAOE,KAAKC,cACZF,gBAAkB,+CAEflC,KAAKuB,KAAK,CAAC,CACdC,WAAYU,gBACZT,KAAM,CAACC,aAAcN,aAAciB,OAAQf,OAAQK,OAAQrB,WAC3D,MACLgC,MAAMxC,aAAaiC,YAS1B5B,oBAAoBW,UAAUe,eAAiB,SAASU,aAChDC,KAAO9B,KACXT,UAAUwC,OAAO,0CAA2CF,SAASX,MAAK,SAASc,KAAMC,IACrF5C,IAAI6C,WAAW,wBAAyB,qBAAqBhB,MAAK,SAASiB,WAClE3C,SAAS2C,MAAOH,KAAMzC,UAAU6C,cAAcjC,KAAKZ,UAAW0C,IAAKH,KAAKO,SAASlC,KAAK2B,OAAO,MACnGV,KAAKhC,aAAaiC,cACtBD,KAAKhC,aAAaiC,YAQzB5B,oBAAoBW,UAAUiC,SAAW,eACjCzC,OAASI,KAAKD,QAElBT,KAAKuB,KAAK,CAAC,CACPC,WAAY,6BACZC,KAAM,CAACE,OAAQrB,QACfsB,KAAMlB,KAAKsC,mBAAmBnC,KAAKH,MACnCoB,KAAMhC,aAAaiC,cAU3B5B,oBAAoBW,UAAUkC,mBAAqB,SAAST,aACpDC,KAAO9B,KACXT,UAAUwC,OAAO,oBAAqBF,SAASX,MAAK,SAASc,KAAMC,IAC/D1C,UAAUgD,YAAYT,KAAKjC,gBAAiBmC,KAAMC,OACnDb,KAAKhC,aAAaiC,YAIzB5B,oBAAoBW,UAAUP,gBAAkB,KAEhDJ,oBAAoBW,UAAUN,wBAA0B,KAExDL,oBAAoBW,UAAUL,QAAU,KAEuBN"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/user_competency_workflow.min.js b/admin/tool/lp/amd/build/user_competency_workflow.min.js
index b975a287e3b..e65a435128b 100644
--- a/admin/tool/lp/amd/build/user_competency_workflow.min.js
+++ b/admin/tool/lp/amd/build/user_competency_workflow.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/user_competency_workflow",["jquery","core/templates","core/ajax","core/notification","core/str","tool_lp/menubar","tool_lp/event_base"],function(a,b,c,d,e,f,g){var h=function(){g.prototype.constructor.apply(this,[])};h.prototype=Object.create(g.prototype);h.prototype._nodeSelector="[data-node=\"user-competency\"]";h.prototype._cancelReviewRequest=function(a){var b={methodname:"core_competency_user_competency_cancel_review_request",args:{userid:a.userid,competencyid:a.competencyid}};c.call([b])[0].then(function(){this._trigger("review-request-cancelled",a);this._trigger("status-changed",a)}.bind(this)).catch(function(){this._trigger("error-occured",a)}.bind(this))};h.prototype.cancelReviewRequest=function(a){this._cancelReviewRequest(a)};h.prototype._cancelReviewRequestHandler=function(b){b.preventDefault();var c=this._findUserCompetencyData(a(b.target));this.cancelReviewRequest(c)};h.prototype._requestReview=function(a){var b={methodname:"core_competency_user_competency_request_review",args:{userid:a.userid,competencyid:a.competencyid}};c.call([b])[0].then(function(){this._trigger("review-requested",a);this._trigger("status-changed",a)}.bind(this)).catch(function(){this._trigger("error-occured",a)}.bind(this))};h.prototype.requestReview=function(a){this._requestReview(a)};h.prototype._requestReviewHandler=function(b){b.preventDefault();var c=this._findUserCompetencyData(a(b.target));this.requestReview(c)};h.prototype._startReview=function(a){var b={methodname:"core_competency_user_competency_start_review",args:{userid:a.userid,competencyid:a.competencyid}};c.call([b])[0].then(function(){this._trigger("review-started",a);this._trigger("status-changed",a)}.bind(this)).catch(function(){this._trigger("error-occured",a)}.bind(this))};h.prototype.startReview=function(a){this._startReview(a)};h.prototype._startReviewHandler=function(b){b.preventDefault();var c=this._findUserCompetencyData(a(b.target));this.startReview(c)};h.prototype._stopReview=function(a){var b={methodname:"core_competency_user_competency_stop_review",args:{userid:a.userid,competencyid:a.competencyid}};c.call([b])[0].then(function(){this._trigger("review-stopped",a);this._trigger("status-changed",a)}.bind(this)).catch(function(){this._trigger("error-occured",a)}.bind(this))};h.prototype.stopReview=function(a){this._stopReview(a)};h.prototype._stopReviewHandler=function(b){b.preventDefault();var c=this._findUserCompetencyData(a(b.target));this.stopReview(c)};h.prototype.enhanceMenubar=function(a){f.enhance(a,{'[data-action="request-review"]':this._requestReviewHandler.bind(this),'[data-action="cancel-review-request"]':this._cancelReviewRequestHandler.bind(this)})};h.prototype._findUserCompetencyData=function(a){var b=a.parents(this._nodeSelector),c;if(1!=b.length){throw new Error("The evidence node was not located.")}c=b.data();if("undefined"==typeof c||"undefined"==typeof c.userid||"undefined"==typeof c.competencyid){throw new Error("User competency data could not be found.")}return c};h.prototype.enhanceMenubar=function(a){f.enhance(a,{'[data-action="request-review"]':this._requestReviewHandler.bind(this),'[data-action="cancel-review-request"]':this._cancelReviewRequestHandler.bind(this),'[data-action="start-review"]':this._startReviewHandler.bind(this),'[data-action="stop-review"]':this._stopReviewHandler.bind(this)})};h.prototype.registerEvents=function(b){var c=a(b);c.find("[data-action=\"request-review\"]").click(this._requestReviewHandler.bind(this));c.find("[data-action=\"cancel-review-request\"]").click(this._cancelReviewRequestHandler.bind(this));c.find("[data-action=\"start-review\"]").click(this._startReviewHandler.bind(this));c.find("[data-action=\"stop-review\"]").click(this._stopReviewHandler.bind(this))};return h});
-//# sourceMappingURL=user_competency_workflow.min.js.map
+/**
+ * User competency workflow.
+ *
+ * @module tool_lp/user_competency_workflow
+ * @copyright 2015 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/user_competency_workflow",["jquery","core/templates","core/ajax","core/notification","core/str","tool_lp/menubar","tool_lp/event_base"],(function($,Templates,Ajax,Notification,Str,Menubar,EventBase){var UserCompetencyWorkflow=function(){EventBase.prototype.constructor.apply(this,[])};return(UserCompetencyWorkflow.prototype=Object.create(EventBase.prototype))._nodeSelector='[data-node="user-competency"]',UserCompetencyWorkflow.prototype._cancelReviewRequest=function(data){var call={methodname:"core_competency_user_competency_cancel_review_request",args:{userid:data.userid,competencyid:data.competencyid}};Ajax.call([call])[0].then(function(){this._trigger("review-request-cancelled",data),this._trigger("status-changed",data)}.bind(this)).catch(function(){this._trigger("error-occured",data)}.bind(this))},UserCompetencyWorkflow.prototype.cancelReviewRequest=function(data){this._cancelReviewRequest(data)},UserCompetencyWorkflow.prototype._cancelReviewRequestHandler=function(e){e.preventDefault();var data=this._findUserCompetencyData($(e.target));this.cancelReviewRequest(data)},UserCompetencyWorkflow.prototype._requestReview=function(data){var call={methodname:"core_competency_user_competency_request_review",args:{userid:data.userid,competencyid:data.competencyid}};Ajax.call([call])[0].then(function(){this._trigger("review-requested",data),this._trigger("status-changed",data)}.bind(this)).catch(function(){this._trigger("error-occured",data)}.bind(this))},UserCompetencyWorkflow.prototype.requestReview=function(data){this._requestReview(data)},UserCompetencyWorkflow.prototype._requestReviewHandler=function(e){e.preventDefault();var data=this._findUserCompetencyData($(e.target));this.requestReview(data)},UserCompetencyWorkflow.prototype._startReview=function(data){var call={methodname:"core_competency_user_competency_start_review",args:{userid:data.userid,competencyid:data.competencyid}};Ajax.call([call])[0].then(function(){this._trigger("review-started",data),this._trigger("status-changed",data)}.bind(this)).catch(function(){this._trigger("error-occured",data)}.bind(this))},UserCompetencyWorkflow.prototype.startReview=function(data){this._startReview(data)},UserCompetencyWorkflow.prototype._startReviewHandler=function(e){e.preventDefault();var data=this._findUserCompetencyData($(e.target));this.startReview(data)},UserCompetencyWorkflow.prototype._stopReview=function(data){var call={methodname:"core_competency_user_competency_stop_review",args:{userid:data.userid,competencyid:data.competencyid}};Ajax.call([call])[0].then(function(){this._trigger("review-stopped",data),this._trigger("status-changed",data)}.bind(this)).catch(function(){this._trigger("error-occured",data)}.bind(this))},UserCompetencyWorkflow.prototype.stopReview=function(data){this._stopReview(data)},UserCompetencyWorkflow.prototype._stopReviewHandler=function(e){e.preventDefault();var data=this._findUserCompetencyData($(e.target));this.stopReview(data)},UserCompetencyWorkflow.prototype.enhanceMenubar=function(selector){Menubar.enhance(selector,{'[data-action="request-review"]':this._requestReviewHandler.bind(this),'[data-action="cancel-review-request"]':this._cancelReviewRequestHandler.bind(this)})},UserCompetencyWorkflow.prototype._findUserCompetencyData=function(node){var data,parent=node.parents(this._nodeSelector);if(1!=parent.length)throw new Error("The evidence node was not located.");if(void 0===(data=parent.data())||void 0===data.userid||void 0===data.competencyid)throw new Error("User competency data could not be found.");return data},UserCompetencyWorkflow.prototype.enhanceMenubar=function(selector){Menubar.enhance(selector,{'[data-action="request-review"]':this._requestReviewHandler.bind(this),'[data-action="cancel-review-request"]':this._cancelReviewRequestHandler.bind(this),'[data-action="start-review"]':this._startReviewHandler.bind(this),'[data-action="stop-review"]':this._stopReviewHandler.bind(this)})},UserCompetencyWorkflow.prototype.registerEvents=function(selector){var wrapper=$(selector);wrapper.find('[data-action="request-review"]').click(this._requestReviewHandler.bind(this)),wrapper.find('[data-action="cancel-review-request"]').click(this._cancelReviewRequestHandler.bind(this)),wrapper.find('[data-action="start-review"]').click(this._startReviewHandler.bind(this)),wrapper.find('[data-action="stop-review"]').click(this._stopReviewHandler.bind(this))},UserCompetencyWorkflow}));
+
+//# sourceMappingURL=user_competency_workflow.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/user_competency_workflow.min.js.map b/admin/tool/lp/amd/build/user_competency_workflow.min.js.map
index f843d5ce9e6..6828088a678 100644
--- a/admin/tool/lp/amd/build/user_competency_workflow.min.js.map
+++ b/admin/tool/lp/amd/build/user_competency_workflow.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/user_competency_workflow.js"],"names":["define","$","Templates","Ajax","Notification","Str","Menubar","EventBase","UserCompetencyWorkflow","prototype","constructor","apply","Object","create","_nodeSelector","_cancelReviewRequest","data","call","methodname","args","userid","competencyid","then","_trigger","bind","catch","cancelReviewRequest","_cancelReviewRequestHandler","e","preventDefault","_findUserCompetencyData","target","_requestReview","requestReview","_requestReviewHandler","_startReview","startReview","_startReviewHandler","_stopReview","stopReview","_stopReviewHandler","enhanceMenubar","selector","enhance","node","parent","parents","length","Error","registerEvents","wrapper","find","click"],"mappings":"AAsBAA,OAAM,oCAAC,CAAC,QAAD,CACC,gBADD,CAEC,WAFD,CAGC,mBAHD,CAIC,UAJD,CAKC,iBALD,CAMC,oBAND,CAAD,CAOE,SAASC,CAAT,CAAYC,CAAZ,CAAuBC,CAAvB,CAA6BC,CAA7B,CAA2CC,CAA3C,CAAgDC,CAAhD,CAAyDC,CAAzD,CAAoE,CAKxE,GAAIC,CAAAA,CAAsB,CAAG,UAAW,CACpCD,CAAS,CAACE,SAAV,CAAoBC,WAApB,CAAgCC,KAAhC,CAAsC,IAAtC,CAA4C,EAA5C,CACH,CAFD,CAGAH,CAAsB,CAACC,SAAvB,CAAmCG,MAAM,CAACC,MAAP,CAAcN,CAAS,CAACE,SAAxB,CAAnC,CAGAD,CAAsB,CAACC,SAAvB,CAAiCK,aAAjC,CAAiD,iCAAjD,CAQAN,CAAsB,CAACC,SAAvB,CAAiCM,oBAAjC,CAAwD,SAASC,CAAT,CAAe,CACnE,GAAIC,CAAAA,CAAI,CAAG,CACPC,UAAU,CAAE,uDADL,CAEPC,IAAI,CAAE,CACFC,MAAM,CAAEJ,CAAI,CAACI,MADX,CAEFC,YAAY,CAAEL,CAAI,CAACK,YAFjB,CAFC,CAAX,CAQAlB,CAAI,CAACc,IAAL,CAAU,CAACA,CAAD,CAAV,EAAkB,CAAlB,EAAqBK,IAArB,CAA0B,UAAW,CACjC,KAAKC,QAAL,CAAc,0BAAd,CAA0CP,CAA1C,EACA,KAAKO,QAAL,CAAc,gBAAd,CAAgCP,CAAhC,CACH,CAHyB,CAGxBQ,IAHwB,CAGnB,IAHmB,CAA1B,EAGcC,KAHd,CAGoB,UAAW,CAC3B,KAAKF,QAAL,CAAc,eAAd,CAA+BP,CAA/B,CACH,CAFmB,CAElBQ,IAFkB,CAEb,IAFa,CAHpB,CAMH,CAfD,CAuBAhB,CAAsB,CAACC,SAAvB,CAAiCiB,mBAAjC,CAAuD,SAASV,CAAT,CAAe,CAClE,KAAKD,oBAAL,CAA0BC,CAA1B,CACH,CAFD,CAUAR,CAAsB,CAACC,SAAvB,CAAiCkB,2BAAjC,CAA+D,SAASC,CAAT,CAAY,CACvEA,CAAC,CAACC,cAAF,GACA,GAAIb,CAAAA,CAAI,CAAG,KAAKc,uBAAL,CAA6B7B,CAAC,CAAC2B,CAAC,CAACG,MAAH,CAA9B,CAAX,CACA,KAAKL,mBAAL,CAAyBV,CAAzB,CACH,CAJD,CAYAR,CAAsB,CAACC,SAAvB,CAAiCuB,cAAjC,CAAkD,SAAShB,CAAT,CAAe,CAC7D,GAAIC,CAAAA,CAAI,CAAG,CACPC,UAAU,CAAE,gDADL,CAEPC,IAAI,CAAE,CACFC,MAAM,CAAEJ,CAAI,CAACI,MADX,CAEFC,YAAY,CAAEL,CAAI,CAACK,YAFjB,CAFC,CAAX,CAQAlB,CAAI,CAACc,IAAL,CAAU,CAACA,CAAD,CAAV,EAAkB,CAAlB,EAAqBK,IAArB,CAA0B,UAAW,CACjC,KAAKC,QAAL,CAAc,kBAAd,CAAkCP,CAAlC,EACA,KAAKO,QAAL,CAAc,gBAAd,CAAgCP,CAAhC,CACH,CAHyB,CAGxBQ,IAHwB,CAGnB,IAHmB,CAA1B,EAGcC,KAHd,CAGoB,UAAW,CAC3B,KAAKF,QAAL,CAAc,eAAd,CAA+BP,CAA/B,CACH,CAFmB,CAElBQ,IAFkB,CAEb,IAFa,CAHpB,CAMH,CAfD,CAuBAhB,CAAsB,CAACC,SAAvB,CAAiCwB,aAAjC,CAAiD,SAASjB,CAAT,CAAe,CAC5D,KAAKgB,cAAL,CAAoBhB,CAApB,CACH,CAFD,CAUAR,CAAsB,CAACC,SAAvB,CAAiCyB,qBAAjC,CAAyD,SAASN,CAAT,CAAY,CACjEA,CAAC,CAACC,cAAF,GACA,GAAIb,CAAAA,CAAI,CAAG,KAAKc,uBAAL,CAA6B7B,CAAC,CAAC2B,CAAC,CAACG,MAAH,CAA9B,CAAX,CACA,KAAKE,aAAL,CAAmBjB,CAAnB,CACH,CAJD,CAYAR,CAAsB,CAACC,SAAvB,CAAiC0B,YAAjC,CAAgD,SAASnB,CAAT,CAAe,CAC3D,GAAIC,CAAAA,CAAI,CAAG,CACPC,UAAU,CAAE,8CADL,CAEPC,IAAI,CAAE,CACFC,MAAM,CAAEJ,CAAI,CAACI,MADX,CAEFC,YAAY,CAAEL,CAAI,CAACK,YAFjB,CAFC,CAAX,CAOAlB,CAAI,CAACc,IAAL,CAAU,CAACA,CAAD,CAAV,EAAkB,CAAlB,EAAqBK,IAArB,CAA0B,UAAW,CACjC,KAAKC,QAAL,CAAc,gBAAd,CAAgCP,CAAhC,EACA,KAAKO,QAAL,CAAc,gBAAd,CAAgCP,CAAhC,CACH,CAHyB,CAGxBQ,IAHwB,CAGnB,IAHmB,CAA1B,EAGcC,KAHd,CAGoB,UAAW,CAC3B,KAAKF,QAAL,CAAc,eAAd,CAA+BP,CAA/B,CACH,CAFmB,CAElBQ,IAFkB,CAEb,IAFa,CAHpB,CAMH,CAdD,CAsBAhB,CAAsB,CAACC,SAAvB,CAAiC2B,WAAjC,CAA+C,SAASpB,CAAT,CAAe,CAC1D,KAAKmB,YAAL,CAAkBnB,CAAlB,CACH,CAFD,CAUAR,CAAsB,CAACC,SAAvB,CAAiC4B,mBAAjC,CAAuD,SAAST,CAAT,CAAY,CAC/DA,CAAC,CAACC,cAAF,GACA,GAAIb,CAAAA,CAAI,CAAG,KAAKc,uBAAL,CAA6B7B,CAAC,CAAC2B,CAAC,CAACG,MAAH,CAA9B,CAAX,CACA,KAAKK,WAAL,CAAiBpB,CAAjB,CACH,CAJD,CAYAR,CAAsB,CAACC,SAAvB,CAAiC6B,WAAjC,CAA+C,SAAStB,CAAT,CAAe,CAC1D,GAAIC,CAAAA,CAAI,CAAG,CACPC,UAAU,CAAE,6CADL,CAEPC,IAAI,CAAE,CACFC,MAAM,CAAEJ,CAAI,CAACI,MADX,CAEFC,YAAY,CAAEL,CAAI,CAACK,YAFjB,CAFC,CAAX,CAQAlB,CAAI,CAACc,IAAL,CAAU,CAACA,CAAD,CAAV,EAAkB,CAAlB,EAAqBK,IAArB,CAA0B,UAAW,CACjC,KAAKC,QAAL,CAAc,gBAAd,CAAgCP,CAAhC,EACA,KAAKO,QAAL,CAAc,gBAAd,CAAgCP,CAAhC,CACH,CAHyB,CAGxBQ,IAHwB,CAGnB,IAHmB,CAA1B,EAGcC,KAHd,CAGoB,UAAW,CAC3B,KAAKF,QAAL,CAAc,eAAd,CAA+BP,CAA/B,CACH,CAFmB,CAElBQ,IAFkB,CAEb,IAFa,CAHpB,CAMH,CAfD,CAuBAhB,CAAsB,CAACC,SAAvB,CAAiC8B,UAAjC,CAA8C,SAASvB,CAAT,CAAe,CACzD,KAAKsB,WAAL,CAAiBtB,CAAjB,CACH,CAFD,CAUAR,CAAsB,CAACC,SAAvB,CAAiC+B,kBAAjC,CAAsD,SAASZ,CAAT,CAAY,CAC9DA,CAAC,CAACC,cAAF,GACA,GAAIb,CAAAA,CAAI,CAAG,KAAKc,uBAAL,CAA6B7B,CAAC,CAAC2B,CAAC,CAACG,MAAH,CAA9B,CAAX,CACA,KAAKQ,UAAL,CAAgBvB,CAAhB,CACH,CAJD,CAWAR,CAAsB,CAACC,SAAvB,CAAiCgC,cAAjC,CAAkD,SAASC,CAAT,CAAmB,CACjEpC,CAAO,CAACqC,OAAR,CAAgBD,CAAhB,CAA0B,CACtB,iCAAkC,KAAKR,qBAAL,CAA2BV,IAA3B,CAAgC,IAAhC,CADZ,CAEtB,wCAAyC,KAAKG,2BAAL,CAAiCH,IAAjC,CAAsC,IAAtC,CAFnB,CAA1B,CAIH,CALD,CAaAhB,CAAsB,CAACC,SAAvB,CAAiCqB,uBAAjC,CAA2D,SAASc,CAAT,CAAe,CACtE,GAAIC,CAAAA,CAAM,CAAGD,CAAI,CAACE,OAAL,CAAa,KAAKhC,aAAlB,CAAb,CACIE,CADJ,CAGA,GAAqB,CAAjB,EAAA6B,CAAM,CAACE,MAAX,CAAwB,CACpB,KAAM,IAAIC,CAAAA,KAAJ,CAAU,oCAAV,CACT,CAEDhC,CAAI,CAAG6B,CAAM,CAAC7B,IAAP,EAAP,CACA,GAAoB,WAAhB,QAAOA,CAAAA,CAAP,EAAsD,WAAvB,QAAOA,CAAAA,CAAI,CAACI,MAA3C,EAAkG,WAA7B,QAAOJ,CAAAA,CAAI,CAACK,YAArF,CAAmH,CAC/G,KAAM,IAAI2B,CAAAA,KAAJ,CAAU,0CAAV,CACT,CAED,MAAOhC,CAAAA,CACV,CAdD,CAqBAR,CAAsB,CAACC,SAAvB,CAAiCgC,cAAjC,CAAkD,SAASC,CAAT,CAAmB,CACjEpC,CAAO,CAACqC,OAAR,CAAgBD,CAAhB,CAA0B,CACtB,iCAAkC,KAAKR,qBAAL,CAA2BV,IAA3B,CAAgC,IAAhC,CADZ,CAEtB,wCAAyC,KAAKG,2BAAL,CAAiCH,IAAjC,CAAsC,IAAtC,CAFnB,CAGtB,+BAAgC,KAAKa,mBAAL,CAAyBb,IAAzB,CAA8B,IAA9B,CAHV,CAItB,8BAA+B,KAAKgB,kBAAL,CAAwBhB,IAAxB,CAA6B,IAA7B,CAJT,CAA1B,CAMH,CAPD,CAcAhB,CAAsB,CAACC,SAAvB,CAAiCwC,cAAjC,CAAkD,SAASP,CAAT,CAAmB,CACjE,GAAIQ,CAAAA,CAAO,CAAGjD,CAAC,CAACyC,CAAD,CAAf,CAEAQ,CAAO,CAACC,IAAR,CAAa,kCAAb,EAA+CC,KAA/C,CAAqD,KAAKlB,qBAAL,CAA2BV,IAA3B,CAAgC,IAAhC,CAArD,EACA0B,CAAO,CAACC,IAAR,CAAa,yCAAb,EAAsDC,KAAtD,CAA4D,KAAKzB,2BAAL,CAAiCH,IAAjC,CAAsC,IAAtC,CAA5D,EACA0B,CAAO,CAACC,IAAR,CAAa,gCAAb,EAA6CC,KAA7C,CAAmD,KAAKf,mBAAL,CAAyBb,IAAzB,CAA8B,IAA9B,CAAnD,EACA0B,CAAO,CAACC,IAAR,CAAa,+BAAb,EAA4CC,KAA5C,CAAkD,KAAKZ,kBAAL,CAAwBhB,IAAxB,CAA6B,IAA7B,CAAlD,CACH,CAPD,CASA,MAA4DhB,CAAAA,CAC/D,CAtQK,CAAN","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 .\n\n/**\n * User competency workflow.\n *\n * @module tool_lp/user_competency_workflow\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/templates',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'tool_lp/menubar',\n 'tool_lp/event_base'],\n function($, Templates, Ajax, Notification, Str, Menubar, EventBase) {\n\n /**\n * UserCompetencyWorkflow class.\n */\n var UserCompetencyWorkflow = function() {\n EventBase.prototype.constructor.apply(this, []);\n };\n UserCompetencyWorkflow.prototype = Object.create(EventBase.prototype);\n\n /** @property {String} The selector to find the user competency data. */\n UserCompetencyWorkflow.prototype._nodeSelector = '[data-node=\"user-competency\"]';\n\n /**\n * Cancel a review request and refresh the view.\n *\n * @param {Object} data The user competency data.\n * @method _cancelReviewRequest\n */\n UserCompetencyWorkflow.prototype._cancelReviewRequest = function(data) {\n var call = {\n methodname: 'core_competency_user_competency_cancel_review_request',\n args: {\n userid: data.userid,\n competencyid: data.competencyid\n }\n };\n\n Ajax.call([call])[0].then(function() {\n this._trigger('review-request-cancelled', data);\n this._trigger('status-changed', data);\n }.bind(this)).catch(function() {\n this._trigger('error-occured', data);\n }.bind(this));\n };\n\n /**\n * Cancel a review request an refresh the view.\n *\n * @param {Object} data The user competency data.\n * @method cancelReviewRequest\n */\n UserCompetencyWorkflow.prototype.cancelReviewRequest = function(data) {\n this._cancelReviewRequest(data);\n };\n\n /**\n * Cancel a review request handler.\n *\n * @param {Event} e The event.\n * @method _cancelReviewRequestHandler\n */\n UserCompetencyWorkflow.prototype._cancelReviewRequestHandler = function(e) {\n e.preventDefault();\n var data = this._findUserCompetencyData($(e.target));\n this.cancelReviewRequest(data);\n };\n\n /**\n * Request a review and refresh the view.\n *\n * @param {Object} data The user competency data.\n * @method _requestReview\n */\n UserCompetencyWorkflow.prototype._requestReview = function(data) {\n var call = {\n methodname: 'core_competency_user_competency_request_review',\n args: {\n userid: data.userid,\n competencyid: data.competencyid\n }\n };\n\n Ajax.call([call])[0].then(function() {\n this._trigger('review-requested', data);\n this._trigger('status-changed', data);\n }.bind(this)).catch(function() {\n this._trigger('error-occured', data);\n }.bind(this));\n };\n\n /**\n * Request a review.\n *\n * @param {Object} data The user competency data.\n * @method requestReview\n */\n UserCompetencyWorkflow.prototype.requestReview = function(data) {\n this._requestReview(data);\n };\n\n /**\n * Request a review handler.\n *\n * @param {Event} e The event.\n * @method _requestReviewHandler\n */\n UserCompetencyWorkflow.prototype._requestReviewHandler = function(e) {\n e.preventDefault();\n var data = this._findUserCompetencyData($(e.target));\n this.requestReview(data);\n };\n\n /**\n * Start a review and refresh the view.\n *\n * @param {Object} data The user competency data.\n * @method _startReview\n */\n UserCompetencyWorkflow.prototype._startReview = function(data) {\n var call = {\n methodname: 'core_competency_user_competency_start_review',\n args: {\n userid: data.userid,\n competencyid: data.competencyid\n }\n };\n Ajax.call([call])[0].then(function() {\n this._trigger('review-started', data);\n this._trigger('status-changed', data);\n }.bind(this)).catch(function() {\n this._trigger('error-occured', data);\n }.bind(this));\n };\n\n /**\n * Start a review.\n *\n * @param {Object} data The user competency data.\n * @method startReview\n */\n UserCompetencyWorkflow.prototype.startReview = function(data) {\n this._startReview(data);\n };\n\n /**\n * Start a review handler.\n *\n * @param {Event} e The event.\n * @method _startReviewHandler\n */\n UserCompetencyWorkflow.prototype._startReviewHandler = function(e) {\n e.preventDefault();\n var data = this._findUserCompetencyData($(e.target));\n this.startReview(data);\n };\n\n /**\n * Stop a review and refresh the view.\n *\n * @param {Object} data The user competency data.\n * @method _stopReview\n */\n UserCompetencyWorkflow.prototype._stopReview = function(data) {\n var call = {\n methodname: 'core_competency_user_competency_stop_review',\n args: {\n userid: data.userid,\n competencyid: data.competencyid\n }\n };\n\n Ajax.call([call])[0].then(function() {\n this._trigger('review-stopped', data);\n this._trigger('status-changed', data);\n }.bind(this)).catch(function() {\n this._trigger('error-occured', data);\n }.bind(this));\n };\n\n /**\n * Stop a review.\n *\n * @param {Object} data The user competency data.\n * @method stopReview\n */\n UserCompetencyWorkflow.prototype.stopReview = function(data) {\n this._stopReview(data);\n };\n\n /**\n * Stop a review handler.\n *\n * @param {Event} e The event.\n * @method _stopReviewHandler\n */\n UserCompetencyWorkflow.prototype._stopReviewHandler = function(e) {\n e.preventDefault();\n var data = this._findUserCompetencyData($(e.target));\n this.stopReview(data);\n };\n\n /**\n * Enhance a menu bar.\n *\n * @param {String} selector Menubar selector.\n */\n UserCompetencyWorkflow.prototype.enhanceMenubar = function(selector) {\n Menubar.enhance(selector, {\n '[data-action=\"request-review\"]': this._requestReviewHandler.bind(this),\n '[data-action=\"cancel-review-request\"]': this._cancelReviewRequestHandler.bind(this),\n });\n };\n\n /**\n * Find the user competency data from a node.\n *\n * @param {Node} node The node to search from.\n * @return {Object} User competency data.\n */\n UserCompetencyWorkflow.prototype._findUserCompetencyData = function(node) {\n var parent = node.parents(this._nodeSelector),\n data;\n\n if (parent.length != 1) {\n throw new Error('The evidence node was not located.');\n }\n\n data = parent.data();\n if (typeof data === 'undefined' || typeof data.userid === 'undefined' || typeof data.competencyid === 'undefined') {\n throw new Error('User competency data could not be found.');\n }\n\n return data;\n };\n\n /**\n * Enhance a menu bar.\n *\n * @param {String} selector Menubar selector.\n */\n UserCompetencyWorkflow.prototype.enhanceMenubar = function(selector) {\n Menubar.enhance(selector, {\n '[data-action=\"request-review\"]': this._requestReviewHandler.bind(this),\n '[data-action=\"cancel-review-request\"]': this._cancelReviewRequestHandler.bind(this),\n '[data-action=\"start-review\"]': this._startReviewHandler.bind(this),\n '[data-action=\"stop-review\"]': this._stopReviewHandler.bind(this),\n });\n };\n\n /**\n * Register the events in the region.\n *\n * @param {String} selector The base selector to search nodes in and attach events.\n */\n UserCompetencyWorkflow.prototype.registerEvents = function(selector) {\n var wrapper = $(selector);\n\n wrapper.find('[data-action=\"request-review\"]').click(this._requestReviewHandler.bind(this));\n wrapper.find('[data-action=\"cancel-review-request\"]').click(this._cancelReviewRequestHandler.bind(this));\n wrapper.find('[data-action=\"start-review\"]').click(this._startReviewHandler.bind(this));\n wrapper.find('[data-action=\"stop-review\"]').click(this._stopReviewHandler.bind(this));\n };\n\n return /** @alias module:tool_lp/user_competency_actions */ UserCompetencyWorkflow;\n});\n"],"file":"user_competency_workflow.min.js"}
\ No newline at end of file
+{"version":3,"file":"user_competency_workflow.min.js","sources":["../src/user_competency_workflow.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 .\n\n/**\n * User competency workflow.\n *\n * @module tool_lp/user_competency_workflow\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/templates',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'tool_lp/menubar',\n 'tool_lp/event_base'],\n function($, Templates, Ajax, Notification, Str, Menubar, EventBase) {\n\n /**\n * UserCompetencyWorkflow class.\n */\n var UserCompetencyWorkflow = function() {\n EventBase.prototype.constructor.apply(this, []);\n };\n UserCompetencyWorkflow.prototype = Object.create(EventBase.prototype);\n\n /** @property {String} The selector to find the user competency data. */\n UserCompetencyWorkflow.prototype._nodeSelector = '[data-node=\"user-competency\"]';\n\n /**\n * Cancel a review request and refresh the view.\n *\n * @param {Object} data The user competency data.\n * @method _cancelReviewRequest\n */\n UserCompetencyWorkflow.prototype._cancelReviewRequest = function(data) {\n var call = {\n methodname: 'core_competency_user_competency_cancel_review_request',\n args: {\n userid: data.userid,\n competencyid: data.competencyid\n }\n };\n\n Ajax.call([call])[0].then(function() {\n this._trigger('review-request-cancelled', data);\n this._trigger('status-changed', data);\n }.bind(this)).catch(function() {\n this._trigger('error-occured', data);\n }.bind(this));\n };\n\n /**\n * Cancel a review request an refresh the view.\n *\n * @param {Object} data The user competency data.\n * @method cancelReviewRequest\n */\n UserCompetencyWorkflow.prototype.cancelReviewRequest = function(data) {\n this._cancelReviewRequest(data);\n };\n\n /**\n * Cancel a review request handler.\n *\n * @param {Event} e The event.\n * @method _cancelReviewRequestHandler\n */\n UserCompetencyWorkflow.prototype._cancelReviewRequestHandler = function(e) {\n e.preventDefault();\n var data = this._findUserCompetencyData($(e.target));\n this.cancelReviewRequest(data);\n };\n\n /**\n * Request a review and refresh the view.\n *\n * @param {Object} data The user competency data.\n * @method _requestReview\n */\n UserCompetencyWorkflow.prototype._requestReview = function(data) {\n var call = {\n methodname: 'core_competency_user_competency_request_review',\n args: {\n userid: data.userid,\n competencyid: data.competencyid\n }\n };\n\n Ajax.call([call])[0].then(function() {\n this._trigger('review-requested', data);\n this._trigger('status-changed', data);\n }.bind(this)).catch(function() {\n this._trigger('error-occured', data);\n }.bind(this));\n };\n\n /**\n * Request a review.\n *\n * @param {Object} data The user competency data.\n * @method requestReview\n */\n UserCompetencyWorkflow.prototype.requestReview = function(data) {\n this._requestReview(data);\n };\n\n /**\n * Request a review handler.\n *\n * @param {Event} e The event.\n * @method _requestReviewHandler\n */\n UserCompetencyWorkflow.prototype._requestReviewHandler = function(e) {\n e.preventDefault();\n var data = this._findUserCompetencyData($(e.target));\n this.requestReview(data);\n };\n\n /**\n * Start a review and refresh the view.\n *\n * @param {Object} data The user competency data.\n * @method _startReview\n */\n UserCompetencyWorkflow.prototype._startReview = function(data) {\n var call = {\n methodname: 'core_competency_user_competency_start_review',\n args: {\n userid: data.userid,\n competencyid: data.competencyid\n }\n };\n Ajax.call([call])[0].then(function() {\n this._trigger('review-started', data);\n this._trigger('status-changed', data);\n }.bind(this)).catch(function() {\n this._trigger('error-occured', data);\n }.bind(this));\n };\n\n /**\n * Start a review.\n *\n * @param {Object} data The user competency data.\n * @method startReview\n */\n UserCompetencyWorkflow.prototype.startReview = function(data) {\n this._startReview(data);\n };\n\n /**\n * Start a review handler.\n *\n * @param {Event} e The event.\n * @method _startReviewHandler\n */\n UserCompetencyWorkflow.prototype._startReviewHandler = function(e) {\n e.preventDefault();\n var data = this._findUserCompetencyData($(e.target));\n this.startReview(data);\n };\n\n /**\n * Stop a review and refresh the view.\n *\n * @param {Object} data The user competency data.\n * @method _stopReview\n */\n UserCompetencyWorkflow.prototype._stopReview = function(data) {\n var call = {\n methodname: 'core_competency_user_competency_stop_review',\n args: {\n userid: data.userid,\n competencyid: data.competencyid\n }\n };\n\n Ajax.call([call])[0].then(function() {\n this._trigger('review-stopped', data);\n this._trigger('status-changed', data);\n }.bind(this)).catch(function() {\n this._trigger('error-occured', data);\n }.bind(this));\n };\n\n /**\n * Stop a review.\n *\n * @param {Object} data The user competency data.\n * @method stopReview\n */\n UserCompetencyWorkflow.prototype.stopReview = function(data) {\n this._stopReview(data);\n };\n\n /**\n * Stop a review handler.\n *\n * @param {Event} e The event.\n * @method _stopReviewHandler\n */\n UserCompetencyWorkflow.prototype._stopReviewHandler = function(e) {\n e.preventDefault();\n var data = this._findUserCompetencyData($(e.target));\n this.stopReview(data);\n };\n\n /**\n * Enhance a menu bar.\n *\n * @param {String} selector Menubar selector.\n */\n UserCompetencyWorkflow.prototype.enhanceMenubar = function(selector) {\n Menubar.enhance(selector, {\n '[data-action=\"request-review\"]': this._requestReviewHandler.bind(this),\n '[data-action=\"cancel-review-request\"]': this._cancelReviewRequestHandler.bind(this),\n });\n };\n\n /**\n * Find the user competency data from a node.\n *\n * @param {Node} node The node to search from.\n * @return {Object} User competency data.\n */\n UserCompetencyWorkflow.prototype._findUserCompetencyData = function(node) {\n var parent = node.parents(this._nodeSelector),\n data;\n\n if (parent.length != 1) {\n throw new Error('The evidence node was not located.');\n }\n\n data = parent.data();\n if (typeof data === 'undefined' || typeof data.userid === 'undefined' || typeof data.competencyid === 'undefined') {\n throw new Error('User competency data could not be found.');\n }\n\n return data;\n };\n\n /**\n * Enhance a menu bar.\n *\n * @param {String} selector Menubar selector.\n */\n UserCompetencyWorkflow.prototype.enhanceMenubar = function(selector) {\n Menubar.enhance(selector, {\n '[data-action=\"request-review\"]': this._requestReviewHandler.bind(this),\n '[data-action=\"cancel-review-request\"]': this._cancelReviewRequestHandler.bind(this),\n '[data-action=\"start-review\"]': this._startReviewHandler.bind(this),\n '[data-action=\"stop-review\"]': this._stopReviewHandler.bind(this),\n });\n };\n\n /**\n * Register the events in the region.\n *\n * @param {String} selector The base selector to search nodes in and attach events.\n */\n UserCompetencyWorkflow.prototype.registerEvents = function(selector) {\n var wrapper = $(selector);\n\n wrapper.find('[data-action=\"request-review\"]').click(this._requestReviewHandler.bind(this));\n wrapper.find('[data-action=\"cancel-review-request\"]').click(this._cancelReviewRequestHandler.bind(this));\n wrapper.find('[data-action=\"start-review\"]').click(this._startReviewHandler.bind(this));\n wrapper.find('[data-action=\"stop-review\"]').click(this._stopReviewHandler.bind(this));\n };\n\n return /** @alias module:tool_lp/user_competency_actions */ UserCompetencyWorkflow;\n});\n"],"names":["define","$","Templates","Ajax","Notification","Str","Menubar","EventBase","UserCompetencyWorkflow","prototype","constructor","apply","this","Object","create","_nodeSelector","_cancelReviewRequest","data","call","methodname","args","userid","competencyid","then","_trigger","bind","catch","cancelReviewRequest","_cancelReviewRequestHandler","e","preventDefault","_findUserCompetencyData","target","_requestReview","requestReview","_requestReviewHandler","_startReview","startReview","_startReviewHandler","_stopReview","stopReview","_stopReviewHandler","enhanceMenubar","selector","enhance","node","parent","parents","length","Error","registerEvents","wrapper","find","click"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/user_evidence_actions.min.js b/admin/tool/lp/amd/build/user_evidence_actions.min.js
index d8c7b8efe08..9d0ec07c6da 100644
--- a/admin/tool/lp/amd/build/user_evidence_actions.min.js
+++ b/admin/tool/lp/amd/build/user_evidence_actions.min.js
@@ -1,2 +1,10 @@
-define ("tool_lp/user_evidence_actions",["jquery","core/templates","core/ajax","core/notification","core/str","tool_lp/menubar","tool_lp/competencypicker_user_plans"],function(a,b,c,d,e,f,g){var h=function(a){this._type=a;if("evidence"===a){this._region="[data-region=\"user-evidence-page\"]";this._evidenceNode="[data-region=\"user-evidence-page\"]";this._template="tool_lp/user_evidence_page";this._contextMethod="tool_lp_data_for_user_evidence_page"}else if("list"===a){this._region="[data-region=\"user-evidence-list\"]";this._evidenceNode="[data-region=\"user-evidence-node\"]";this._template="tool_lp/user_evidence_list_page";this._contextMethod="tool_lp_data_for_user_evidence_list_page"}else{throw new TypeError("Unexpected type.")}};h.prototype._contextMethod=null;h.prototype._evidenceNode=null;h.prototype._region=null;h.prototype._template=null;h.prototype._type=null;h.prototype._getContextArgs=function(a){var b=this,c={};if("evidence"===b._type){c={id:a.id}}else if("list"===b._type){c={userid:a.userid}}return c};h.prototype._renderView=function(c){var d=this;return b.render(d._template,c).then(function(c,e){b.replaceNode(a(d._region),c,e)})};h.prototype._callAndRefresh=function(b,e){var f=this;b.push({methodname:f._contextMethod,args:f._getContextArgs(e)});return a.when.apply(a.when,c.call(b)).then(function(){return f._renderView(arguments[arguments.length-1])}).fail(d.exception)};h.prototype._doDelete=function(a){var b=this,c=[{methodname:"core_competency_delete_user_evidence",args:{id:a.id}}];b._callAndRefresh(c,a)};h.prototype.deleteEvidence=function(a){var b=this,f;f=c.call([{methodname:"core_competency_read_user_evidence",args:{id:a.id}}]);f[0].done(function(c){e.get_strings([{key:"confirm",component:"moodle"},{key:"deleteuserevidence",component:"tool_lp",param:c.name},{key:"delete",component:"moodle"},{key:"cancel",component:"moodle"}]).done(function(c){d.confirm(c[0],c[1],c[2],c[3],function(){b._doDelete(a)})}).fail(d.exception)}).fail(d.exception)};h.prototype._deleteEvidenceHandler=function(b){b.preventDefault();var c=this._findEvidenceData(a(b.target));this.deleteEvidence(c)};h.prototype._doCreateUserEvidenceCompetency=function(b,c){var d=this,e=[];a.each(c,function(a,c){e.push({methodname:"core_competency_create_user_evidence_competency",args:{userevidenceid:b.id,competencyid:c}})});d._callAndRefresh(e,b)};h.prototype.createUserEvidenceCompetency=function(a){var b=this,c=new g(a.userid);c.on("save",function(c,d){var e=d.competencyIds;b._doCreateUserEvidenceCompetency(a,e,d.requestReview)});c.display()};h.prototype._createUserEvidenceCompetencyHandler=function(b){b.preventDefault();var c=this._findEvidenceData(a(b.target));this.createUserEvidenceCompetency(c)};h.prototype._doDeleteUserEvidenceCompetency=function(a,b){var c=this,d=[];d.push({methodname:"core_competency_delete_user_evidence_competency",args:{userevidenceid:a.id,competencyid:b}});c._callAndRefresh(d,a)};h.prototype.deleteUserEvidenceCompetency=function(a,b){this._doDeleteUserEvidenceCompetency(a,b)};h.prototype._deleteUserEvidenceCompetencyHandler=function(b){var c=this._findEvidenceData(a(b.currentTarget)),d=a(b.currentTarget).data("id");b.preventDefault();this.deleteUserEvidenceCompetency(c,d)};h.prototype._doReviewUserEvidenceCompetencies=function(a){var b=this,c=[{methodname:"core_competency_request_review_of_user_evidence_linked_competencies",args:{id:a.id}}];b._callAndRefresh(c,a)};h.prototype.reviewUserEvidenceCompetencies=function(a){var b=this,f;f=c.call([{methodname:"core_competency_read_user_evidence",args:{id:a.id}}]);f[0].done(function(c){e.get_strings([{key:"confirm",component:"moodle"},{key:"sendallcompetenciestoreview",component:"tool_lp",param:c.name},{key:"confirm",component:"moodle"},{key:"cancel",component:"moodle"}]).done(function(c){d.confirm(c[0],c[1],c[2],c[3],function(){b._doReviewUserEvidenceCompetencies(a)})}).fail(d.exception)}).fail(d.exception)};h.prototype._reviewUserEvidenceCompetenciesHandler=function(b){b.preventDefault();var c=this._findEvidenceData(a(b.target));this.reviewUserEvidenceCompetencies(c)};h.prototype._findEvidenceData=function(b){var c=b.parentsUntil(a(this._region).parent(),this._evidenceNode),d;if(1!=c.length){throw new Error("The evidence node was not located.")}d=c.data();if("undefined"==typeof d||"undefined"==typeof d.id){throw new Error("Evidence data could not be found.")}return d};h.prototype.enhanceMenubar=function(a){var b=this;f.enhance(a,{'[data-action="user-evidence-delete"]':b._deleteEvidenceHandler.bind(b),'[data-action="link-competency"]':b._createUserEvidenceCompetencyHandler.bind(b),'[data-action="send-competencies-review"]':b._reviewUserEvidenceCompetenciesHandler.bind(b)})};h.prototype.registerEvents=function(){var b=a(this._region),c=this;b.find("[data-action=\"user-evidence-delete\"]").click(c._deleteEvidenceHandler.bind(c));b.find("[data-action=\"link-competency\"]").click(c._createUserEvidenceCompetencyHandler.bind(c));b.find("[data-action=\"delete-competency-link\"]").click(c._deleteUserEvidenceCompetencyHandler.bind(c));b.find("[data-action=\"send-competencies-review\"]").click(c._reviewUserEvidenceCompetenciesHandler.bind(c))};return h});
-//# sourceMappingURL=user_evidence_actions.min.js.map
+/**
+ * User evidence actions.
+ *
+ * @module tool_lp/user_evidence_actions
+ * @copyright 2015 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_lp/user_evidence_actions",["jquery","core/templates","core/ajax","core/notification","core/str","tool_lp/menubar","tool_lp/competencypicker_user_plans"],(function($,templates,ajax,notification,str,Menubar,PickerUserPlans){var UserEvidenceActions=function(type){if(this._type=type,"evidence"===type)this._region='[data-region="user-evidence-page"]',this._evidenceNode='[data-region="user-evidence-page"]',this._template="tool_lp/user_evidence_page",this._contextMethod="tool_lp_data_for_user_evidence_page";else{if("list"!==type)throw new TypeError("Unexpected type.");this._region='[data-region="user-evidence-list"]',this._evidenceNode='[data-region="user-evidence-node"]',this._template="tool_lp/user_evidence_list_page",this._contextMethod="tool_lp_data_for_user_evidence_list_page"}};return UserEvidenceActions.prototype._contextMethod=null,UserEvidenceActions.prototype._evidenceNode=null,UserEvidenceActions.prototype._region=null,UserEvidenceActions.prototype._template=null,UserEvidenceActions.prototype._type=null,UserEvidenceActions.prototype._getContextArgs=function(evidenceData){var args={};return"evidence"===this._type?args={id:evidenceData.id}:"list"===this._type&&(args={userid:evidenceData.userid}),args},UserEvidenceActions.prototype._renderView=function(context){var self=this;return templates.render(self._template,context).then((function(newhtml,newjs){templates.replaceNode($(self._region),newhtml,newjs)}))},UserEvidenceActions.prototype._callAndRefresh=function(calls,evidenceData){var self=this;return calls.push({methodname:self._contextMethod,args:self._getContextArgs(evidenceData)}),$.when.apply($.when,ajax.call(calls)).then((function(){return self._renderView(arguments[arguments.length-1])})).fail(notification.exception)},UserEvidenceActions.prototype._doDelete=function(evidenceData){var calls=[{methodname:"core_competency_delete_user_evidence",args:{id:evidenceData.id}}];this._callAndRefresh(calls,evidenceData)},UserEvidenceActions.prototype.deleteEvidence=function(evidenceData){var self=this;ajax.call([{methodname:"core_competency_read_user_evidence",args:{id:evidenceData.id}}])[0].done((function(evidence){str.get_strings([{key:"confirm",component:"moodle"},{key:"deleteuserevidence",component:"tool_lp",param:evidence.name},{key:"delete",component:"moodle"},{key:"cancel",component:"moodle"}]).done((function(strings){notification.confirm(strings[0],strings[1],strings[2],strings[3],(function(){self._doDelete(evidenceData)}))})).fail(notification.exception)})).fail(notification.exception)},UserEvidenceActions.prototype._deleteEvidenceHandler=function(e){e.preventDefault();var data=this._findEvidenceData($(e.target));this.deleteEvidence(data)},UserEvidenceActions.prototype._doCreateUserEvidenceCompetency=function(evidenceData,competencyIds){var calls=[];$.each(competencyIds,(function(index,competencyId){calls.push({methodname:"core_competency_create_user_evidence_competency",args:{userevidenceid:evidenceData.id,competencyid:competencyId}})})),this._callAndRefresh(calls,evidenceData)},UserEvidenceActions.prototype.createUserEvidenceCompetency=function(evidenceData){var self=this,picker=new PickerUserPlans(evidenceData.userid);picker.on("save",(function(e,data){var competencyIds=data.competencyIds;self._doCreateUserEvidenceCompetency(evidenceData,competencyIds,data.requestReview)})),picker.display()},UserEvidenceActions.prototype._createUserEvidenceCompetencyHandler=function(e){e.preventDefault();var data=this._findEvidenceData($(e.target));this.createUserEvidenceCompetency(data)},UserEvidenceActions.prototype._doDeleteUserEvidenceCompetency=function(evidenceData,competencyId){var calls=[];calls.push({methodname:"core_competency_delete_user_evidence_competency",args:{userevidenceid:evidenceData.id,competencyid:competencyId}}),this._callAndRefresh(calls,evidenceData)},UserEvidenceActions.prototype.deleteUserEvidenceCompetency=function(evidenceData,competencyId){this._doDeleteUserEvidenceCompetency(evidenceData,competencyId)},UserEvidenceActions.prototype._deleteUserEvidenceCompetencyHandler=function(e){var data=this._findEvidenceData($(e.currentTarget)),competencyId=$(e.currentTarget).data("id");e.preventDefault(),this.deleteUserEvidenceCompetency(data,competencyId)},UserEvidenceActions.prototype._doReviewUserEvidenceCompetencies=function(evidenceData){var calls=[{methodname:"core_competency_request_review_of_user_evidence_linked_competencies",args:{id:evidenceData.id}}];this._callAndRefresh(calls,evidenceData)},UserEvidenceActions.prototype.reviewUserEvidenceCompetencies=function(evidenceData){var self=this;ajax.call([{methodname:"core_competency_read_user_evidence",args:{id:evidenceData.id}}])[0].done((function(evidence){str.get_strings([{key:"confirm",component:"moodle"},{key:"sendallcompetenciestoreview",component:"tool_lp",param:evidence.name},{key:"confirm",component:"moodle"},{key:"cancel",component:"moodle"}]).done((function(strings){notification.confirm(strings[0],strings[1],strings[2],strings[3],(function(){self._doReviewUserEvidenceCompetencies(evidenceData)}))})).fail(notification.exception)})).fail(notification.exception)},UserEvidenceActions.prototype._reviewUserEvidenceCompetenciesHandler=function(e){e.preventDefault();var data=this._findEvidenceData($(e.target));this.reviewUserEvidenceCompetencies(data)},UserEvidenceActions.prototype._findEvidenceData=function(node){var data,parent=node.parentsUntil($(this._region).parent(),this._evidenceNode);if(1!=parent.length)throw new Error("The evidence node was not located.");if(void 0===(data=parent.data())||void 0===data.id)throw new Error("Evidence data could not be found.");return data},UserEvidenceActions.prototype.enhanceMenubar=function(selector){Menubar.enhance(selector,{'[data-action="user-evidence-delete"]':this._deleteEvidenceHandler.bind(this),'[data-action="link-competency"]':this._createUserEvidenceCompetencyHandler.bind(this),'[data-action="send-competencies-review"]':this._reviewUserEvidenceCompetenciesHandler.bind(this)})},UserEvidenceActions.prototype.registerEvents=function(){var wrapper=$(this._region);wrapper.find('[data-action="user-evidence-delete"]').click(this._deleteEvidenceHandler.bind(this)),wrapper.find('[data-action="link-competency"]').click(this._createUserEvidenceCompetencyHandler.bind(this)),wrapper.find('[data-action="delete-competency-link"]').click(this._deleteUserEvidenceCompetencyHandler.bind(this)),wrapper.find('[data-action="send-competencies-review"]').click(this._reviewUserEvidenceCompetenciesHandler.bind(this))},UserEvidenceActions}));
+
+//# sourceMappingURL=user_evidence_actions.min.js.map
\ No newline at end of file
diff --git a/admin/tool/lp/amd/build/user_evidence_actions.min.js.map b/admin/tool/lp/amd/build/user_evidence_actions.min.js.map
index e4ce2adbb68..719e3f31120 100644
--- a/admin/tool/lp/amd/build/user_evidence_actions.min.js.map
+++ b/admin/tool/lp/amd/build/user_evidence_actions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/user_evidence_actions.js"],"names":["define","$","templates","ajax","notification","str","Menubar","PickerUserPlans","UserEvidenceActions","type","_type","_region","_evidenceNode","_template","_contextMethod","TypeError","prototype","_getContextArgs","evidenceData","self","args","id","userid","_renderView","context","render","then","newhtml","newjs","replaceNode","_callAndRefresh","calls","push","methodname","when","apply","call","arguments","length","fail","exception","_doDelete","deleteEvidence","requests","done","evidence","get_strings","key","component","param","name","strings","confirm","_deleteEvidenceHandler","e","preventDefault","data","_findEvidenceData","target","_doCreateUserEvidenceCompetency","competencyIds","each","index","competencyId","userevidenceid","competencyid","createUserEvidenceCompetency","picker","on","requestReview","display","_createUserEvidenceCompetencyHandler","_doDeleteUserEvidenceCompetency","deleteUserEvidenceCompetency","_deleteUserEvidenceCompetencyHandler","currentTarget","_doReviewUserEvidenceCompetencies","reviewUserEvidenceCompetencies","_reviewUserEvidenceCompetenciesHandler","node","parent","parentsUntil","Error","enhanceMenubar","selector","enhance","bind","registerEvents","wrapper","find","click"],"mappings":"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","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 .\n\n/**\n * User evidence actions.\n *\n * @module tool_lp/user_evidence_actions\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/templates',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'tool_lp/menubar',\n 'tool_lp/competencypicker_user_plans'],\n function($, templates, ajax, notification, str, Menubar, PickerUserPlans) {\n\n /**\n * UserEvidenceActions class.\n *\n * Note that presently this cannot be instantiated more than once per page.\n *\n * @param {String} type The type of page we're in.\n */\n var UserEvidenceActions = function(type) {\n this._type = type;\n\n if (type === 'evidence') {\n // This is the page to view one evidence.\n this._region = '[data-region=\"user-evidence-page\"]';\n this._evidenceNode = '[data-region=\"user-evidence-page\"]';\n this._template = 'tool_lp/user_evidence_page';\n this._contextMethod = 'tool_lp_data_for_user_evidence_page';\n\n } else if (type === 'list') {\n // This is the page to view a list of evidence.\n this._region = '[data-region=\"user-evidence-list\"]';\n this._evidenceNode = '[data-region=\"user-evidence-node\"]';\n this._template = 'tool_lp/user_evidence_list_page';\n this._contextMethod = 'tool_lp_data_for_user_evidence_list_page';\n\n } else {\n throw new TypeError('Unexpected type.');\n }\n };\n\n /** @property {String} Ajax method to fetch the page data from. */\n UserEvidenceActions.prototype._contextMethod = null;\n /** @property {String} Selector to find the node describing the evidence. */\n UserEvidenceActions.prototype._evidenceNode = null;\n /** @property {String} Selector mapping to the region to update. Usually similar to wrapper. */\n UserEvidenceActions.prototype._region = null;\n /** @property {String} Name of the template used to render the region. */\n UserEvidenceActions.prototype._template = null;\n /** @property {String} Type of page/region we're in. */\n UserEvidenceActions.prototype._type = null;\n\n /**\n * Resolve the arguments to refresh the region.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n * @return {Object} List of arguments.\n */\n UserEvidenceActions.prototype._getContextArgs = function(evidenceData) {\n var self = this,\n args = {};\n\n if (self._type === 'evidence') {\n args = {\n id: evidenceData.id\n };\n\n } else if (self._type === 'list') {\n args = {\n userid: evidenceData.userid\n };\n }\n\n return args;\n };\n\n /**\n * Callback to render the region template.\n *\n * @param {Object} context The context for the template.\n * @return {Promise}\n */\n UserEvidenceActions.prototype._renderView = function(context) {\n var self = this;\n return templates.render(self._template, context)\n .then(function(newhtml, newjs) {\n templates.replaceNode($(self._region), newhtml, newjs);\n return;\n });\n };\n\n /**\n * Call multiple ajax methods, and refresh.\n *\n * @param {Array} calls List of Ajax calls.\n * @param {Object} evidenceData Evidence data from evidence node.\n * @return {Promise}\n */\n UserEvidenceActions.prototype._callAndRefresh = function(calls, evidenceData) {\n var self = this;\n calls.push({\n methodname: self._contextMethod,\n args: self._getContextArgs(evidenceData)\n });\n\n // Apply all the promises, and refresh when the last one is resolved.\n return $.when.apply($.when, ajax.call(calls))\n .then(function() {\n return self._renderView(arguments[arguments.length - 1]);\n })\n .fail(notification.exception);\n };\n\n /**\n * Delete a plan and reload the region.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n */\n UserEvidenceActions.prototype._doDelete = function(evidenceData) {\n var self = this,\n calls = [{\n methodname: 'core_competency_delete_user_evidence',\n args: {id: evidenceData.id}\n }];\n self._callAndRefresh(calls, evidenceData);\n };\n\n /**\n * Delete a plan.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n */\n UserEvidenceActions.prototype.deleteEvidence = function(evidenceData) {\n var self = this,\n requests;\n\n requests = ajax.call([{\n methodname: 'core_competency_read_user_evidence',\n args: {id: evidenceData.id}\n }]);\n\n requests[0].done(function(evidence) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'deleteuserevidence', component: 'tool_lp', param: evidence.name},\n {key: 'delete', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Delete evidence X?\n strings[2], // Delete.\n strings[3], // Cancel.\n function() {\n self._doDelete(evidenceData);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n /**\n * Delete evidence handler.\n *\n * @param {Event} e The event.\n */\n UserEvidenceActions.prototype._deleteEvidenceHandler = function(e) {\n e.preventDefault();\n var data = this._findEvidenceData($(e.target));\n this.deleteEvidence(data);\n };\n\n /**\n * Link a competency and reload.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n * @param {Number} competencyIds The competency IDs.\n */\n UserEvidenceActions.prototype._doCreateUserEvidenceCompetency = function(evidenceData, competencyIds) {\n var self = this,\n calls = [];\n\n $.each(competencyIds, function(index, competencyId) {\n calls.push({\n methodname: 'core_competency_create_user_evidence_competency',\n args: {\n userevidenceid: evidenceData.id,\n competencyid: competencyId,\n }\n });\n });\n\n self._callAndRefresh(calls, evidenceData);\n };\n\n /**\n * Create a user evidence competency.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n */\n UserEvidenceActions.prototype.createUserEvidenceCompetency = function(evidenceData) {\n var self = this,\n picker = new PickerUserPlans(evidenceData.userid);\n\n picker.on('save', function(e, data) {\n var competencyIds = data.competencyIds;\n self._doCreateUserEvidenceCompetency(evidenceData, competencyIds, data.requestReview);\n });\n\n picker.display();\n };\n\n /**\n * Create user evidence competency handler.\n *\n * @param {Event} e The event.\n */\n UserEvidenceActions.prototype._createUserEvidenceCompetencyHandler = function(e) {\n e.preventDefault();\n var data = this._findEvidenceData($(e.target));\n this.createUserEvidenceCompetency(data);\n };\n\n /**\n * Remove a linked competency and reload.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n * @param {Number} competencyId The competency ID.\n */\n UserEvidenceActions.prototype._doDeleteUserEvidenceCompetency = function(evidenceData, competencyId) {\n var self = this,\n calls = [];\n\n calls.push({\n methodname: 'core_competency_delete_user_evidence_competency',\n args: {\n userevidenceid: evidenceData.id,\n competencyid: competencyId,\n }\n });\n\n self._callAndRefresh(calls, evidenceData);\n };\n\n /**\n * Delete a user evidence competency.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n * @param {Number} competencyId The competency ID.\n */\n UserEvidenceActions.prototype.deleteUserEvidenceCompetency = function(evidenceData, competencyId) {\n this._doDeleteUserEvidenceCompetency(evidenceData, competencyId);\n };\n\n /**\n * Delete user evidence competency handler.\n *\n * @param {Event} e The event.\n */\n UserEvidenceActions.prototype._deleteUserEvidenceCompetencyHandler = function(e) {\n var data = this._findEvidenceData($(e.currentTarget)),\n competencyId = $(e.currentTarget).data('id');\n e.preventDefault();\n this.deleteUserEvidenceCompetency(data, competencyId);\n };\n\n /**\n * Send request review for user evidence competencies and reload the region.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n */\n UserEvidenceActions.prototype._doReviewUserEvidenceCompetencies = function(evidenceData) {\n var self = this,\n calls = [{\n methodname: 'core_competency_request_review_of_user_evidence_linked_competencies',\n args: {id: evidenceData.id}\n }];\n self._callAndRefresh(calls, evidenceData);\n };\n\n /**\n * Send request review for user evidence competencies.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n */\n UserEvidenceActions.prototype.reviewUserEvidenceCompetencies = function(evidenceData) {\n var self = this,\n requests;\n\n requests = ajax.call([{\n methodname: 'core_competency_read_user_evidence',\n args: {id: evidenceData.id}\n }]);\n\n requests[0].done(function(evidence) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'sendallcompetenciestoreview', component: 'tool_lp', param: evidence.name},\n {key: 'confirm', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Send all competencies in review for X?\n strings[2], // Confirm.\n strings[3], // Cancel.\n function() {\n self._doReviewUserEvidenceCompetencies(evidenceData);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n /**\n * Send request review for user evidence competencies handler.\n *\n * @param {Event} e The event.\n */\n UserEvidenceActions.prototype._reviewUserEvidenceCompetenciesHandler = function(e) {\n e.preventDefault();\n var data = this._findEvidenceData($(e.target));\n this.reviewUserEvidenceCompetencies(data);\n };\n\n /**\n * Find the evidence data from the evidence node.\n *\n * @param {Node} node The node to search from.\n * @return {Object} Evidence data.\n */\n UserEvidenceActions.prototype._findEvidenceData = function(node) {\n var parent = node.parentsUntil($(this._region).parent(), this._evidenceNode),\n data;\n\n if (parent.length != 1) {\n throw new Error('The evidence node was not located.');\n }\n\n data = parent.data();\n if (typeof data === 'undefined' || typeof data.id === 'undefined') {\n throw new Error('Evidence data could not be found.');\n }\n\n return data;\n };\n\n /**\n * Enhance a menu bar.\n *\n * @param {String} selector Menubar selector.\n */\n UserEvidenceActions.prototype.enhanceMenubar = function(selector) {\n var self = this;\n Menubar.enhance(selector, {\n '[data-action=\"user-evidence-delete\"]': self._deleteEvidenceHandler.bind(self),\n '[data-action=\"link-competency\"]': self._createUserEvidenceCompetencyHandler.bind(self),\n '[data-action=\"send-competencies-review\"]': self._reviewUserEvidenceCompetenciesHandler.bind(self),\n });\n };\n\n /**\n * Register the events in the region.\n *\n * At this stage this cannot be used with enhanceMenubar or multiple handlers\n * will be added to the same node.\n */\n UserEvidenceActions.prototype.registerEvents = function() {\n var wrapper = $(this._region),\n self = this;\n\n wrapper.find('[data-action=\"user-evidence-delete\"]').click(self._deleteEvidenceHandler.bind(self));\n wrapper.find('[data-action=\"link-competency\"]').click(self._createUserEvidenceCompetencyHandler.bind(self));\n wrapper.find('[data-action=\"delete-competency-link\"]').click(self._deleteUserEvidenceCompetencyHandler.bind(self));\n wrapper.find('[data-action=\"send-competencies-review\"]').click(self._reviewUserEvidenceCompetenciesHandler.bind(self));\n };\n\n return /** @alias module:tool_lp/user_evidence_actions */ UserEvidenceActions;\n});\n"],"file":"user_evidence_actions.min.js"}
\ No newline at end of file
+{"version":3,"file":"user_evidence_actions.min.js","sources":["../src/user_evidence_actions.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 .\n\n/**\n * User evidence actions.\n *\n * @module tool_lp/user_evidence_actions\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/templates',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'tool_lp/menubar',\n 'tool_lp/competencypicker_user_plans'],\n function($, templates, ajax, notification, str, Menubar, PickerUserPlans) {\n\n /**\n * UserEvidenceActions class.\n *\n * Note that presently this cannot be instantiated more than once per page.\n *\n * @param {String} type The type of page we're in.\n */\n var UserEvidenceActions = function(type) {\n this._type = type;\n\n if (type === 'evidence') {\n // This is the page to view one evidence.\n this._region = '[data-region=\"user-evidence-page\"]';\n this._evidenceNode = '[data-region=\"user-evidence-page\"]';\n this._template = 'tool_lp/user_evidence_page';\n this._contextMethod = 'tool_lp_data_for_user_evidence_page';\n\n } else if (type === 'list') {\n // This is the page to view a list of evidence.\n this._region = '[data-region=\"user-evidence-list\"]';\n this._evidenceNode = '[data-region=\"user-evidence-node\"]';\n this._template = 'tool_lp/user_evidence_list_page';\n this._contextMethod = 'tool_lp_data_for_user_evidence_list_page';\n\n } else {\n throw new TypeError('Unexpected type.');\n }\n };\n\n /** @property {String} Ajax method to fetch the page data from. */\n UserEvidenceActions.prototype._contextMethod = null;\n /** @property {String} Selector to find the node describing the evidence. */\n UserEvidenceActions.prototype._evidenceNode = null;\n /** @property {String} Selector mapping to the region to update. Usually similar to wrapper. */\n UserEvidenceActions.prototype._region = null;\n /** @property {String} Name of the template used to render the region. */\n UserEvidenceActions.prototype._template = null;\n /** @property {String} Type of page/region we're in. */\n UserEvidenceActions.prototype._type = null;\n\n /**\n * Resolve the arguments to refresh the region.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n * @return {Object} List of arguments.\n */\n UserEvidenceActions.prototype._getContextArgs = function(evidenceData) {\n var self = this,\n args = {};\n\n if (self._type === 'evidence') {\n args = {\n id: evidenceData.id\n };\n\n } else if (self._type === 'list') {\n args = {\n userid: evidenceData.userid\n };\n }\n\n return args;\n };\n\n /**\n * Callback to render the region template.\n *\n * @param {Object} context The context for the template.\n * @return {Promise}\n */\n UserEvidenceActions.prototype._renderView = function(context) {\n var self = this;\n return templates.render(self._template, context)\n .then(function(newhtml, newjs) {\n templates.replaceNode($(self._region), newhtml, newjs);\n return;\n });\n };\n\n /**\n * Call multiple ajax methods, and refresh.\n *\n * @param {Array} calls List of Ajax calls.\n * @param {Object} evidenceData Evidence data from evidence node.\n * @return {Promise}\n */\n UserEvidenceActions.prototype._callAndRefresh = function(calls, evidenceData) {\n var self = this;\n calls.push({\n methodname: self._contextMethod,\n args: self._getContextArgs(evidenceData)\n });\n\n // Apply all the promises, and refresh when the last one is resolved.\n return $.when.apply($.when, ajax.call(calls))\n .then(function() {\n return self._renderView(arguments[arguments.length - 1]);\n })\n .fail(notification.exception);\n };\n\n /**\n * Delete a plan and reload the region.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n */\n UserEvidenceActions.prototype._doDelete = function(evidenceData) {\n var self = this,\n calls = [{\n methodname: 'core_competency_delete_user_evidence',\n args: {id: evidenceData.id}\n }];\n self._callAndRefresh(calls, evidenceData);\n };\n\n /**\n * Delete a plan.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n */\n UserEvidenceActions.prototype.deleteEvidence = function(evidenceData) {\n var self = this,\n requests;\n\n requests = ajax.call([{\n methodname: 'core_competency_read_user_evidence',\n args: {id: evidenceData.id}\n }]);\n\n requests[0].done(function(evidence) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'deleteuserevidence', component: 'tool_lp', param: evidence.name},\n {key: 'delete', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Delete evidence X?\n strings[2], // Delete.\n strings[3], // Cancel.\n function() {\n self._doDelete(evidenceData);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n /**\n * Delete evidence handler.\n *\n * @param {Event} e The event.\n */\n UserEvidenceActions.prototype._deleteEvidenceHandler = function(e) {\n e.preventDefault();\n var data = this._findEvidenceData($(e.target));\n this.deleteEvidence(data);\n };\n\n /**\n * Link a competency and reload.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n * @param {Number} competencyIds The competency IDs.\n */\n UserEvidenceActions.prototype._doCreateUserEvidenceCompetency = function(evidenceData, competencyIds) {\n var self = this,\n calls = [];\n\n $.each(competencyIds, function(index, competencyId) {\n calls.push({\n methodname: 'core_competency_create_user_evidence_competency',\n args: {\n userevidenceid: evidenceData.id,\n competencyid: competencyId,\n }\n });\n });\n\n self._callAndRefresh(calls, evidenceData);\n };\n\n /**\n * Create a user evidence competency.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n */\n UserEvidenceActions.prototype.createUserEvidenceCompetency = function(evidenceData) {\n var self = this,\n picker = new PickerUserPlans(evidenceData.userid);\n\n picker.on('save', function(e, data) {\n var competencyIds = data.competencyIds;\n self._doCreateUserEvidenceCompetency(evidenceData, competencyIds, data.requestReview);\n });\n\n picker.display();\n };\n\n /**\n * Create user evidence competency handler.\n *\n * @param {Event} e The event.\n */\n UserEvidenceActions.prototype._createUserEvidenceCompetencyHandler = function(e) {\n e.preventDefault();\n var data = this._findEvidenceData($(e.target));\n this.createUserEvidenceCompetency(data);\n };\n\n /**\n * Remove a linked competency and reload.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n * @param {Number} competencyId The competency ID.\n */\n UserEvidenceActions.prototype._doDeleteUserEvidenceCompetency = function(evidenceData, competencyId) {\n var self = this,\n calls = [];\n\n calls.push({\n methodname: 'core_competency_delete_user_evidence_competency',\n args: {\n userevidenceid: evidenceData.id,\n competencyid: competencyId,\n }\n });\n\n self._callAndRefresh(calls, evidenceData);\n };\n\n /**\n * Delete a user evidence competency.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n * @param {Number} competencyId The competency ID.\n */\n UserEvidenceActions.prototype.deleteUserEvidenceCompetency = function(evidenceData, competencyId) {\n this._doDeleteUserEvidenceCompetency(evidenceData, competencyId);\n };\n\n /**\n * Delete user evidence competency handler.\n *\n * @param {Event} e The event.\n */\n UserEvidenceActions.prototype._deleteUserEvidenceCompetencyHandler = function(e) {\n var data = this._findEvidenceData($(e.currentTarget)),\n competencyId = $(e.currentTarget).data('id');\n e.preventDefault();\n this.deleteUserEvidenceCompetency(data, competencyId);\n };\n\n /**\n * Send request review for user evidence competencies and reload the region.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n */\n UserEvidenceActions.prototype._doReviewUserEvidenceCompetencies = function(evidenceData) {\n var self = this,\n calls = [{\n methodname: 'core_competency_request_review_of_user_evidence_linked_competencies',\n args: {id: evidenceData.id}\n }];\n self._callAndRefresh(calls, evidenceData);\n };\n\n /**\n * Send request review for user evidence competencies.\n *\n * @param {Object} evidenceData Evidence data from evidence node.\n */\n UserEvidenceActions.prototype.reviewUserEvidenceCompetencies = function(evidenceData) {\n var self = this,\n requests;\n\n requests = ajax.call([{\n methodname: 'core_competency_read_user_evidence',\n args: {id: evidenceData.id}\n }]);\n\n requests[0].done(function(evidence) {\n str.get_strings([\n {key: 'confirm', component: 'moodle'},\n {key: 'sendallcompetenciestoreview', component: 'tool_lp', param: evidence.name},\n {key: 'confirm', component: 'moodle'},\n {key: 'cancel', component: 'moodle'}\n ]).done(function(strings) {\n notification.confirm(\n strings[0], // Confirm.\n strings[1], // Send all competencies in review for X?\n strings[2], // Confirm.\n strings[3], // Cancel.\n function() {\n self._doReviewUserEvidenceCompetencies(evidenceData);\n }\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n\n };\n\n /**\n * Send request review for user evidence competencies handler.\n *\n * @param {Event} e The event.\n */\n UserEvidenceActions.prototype._reviewUserEvidenceCompetenciesHandler = function(e) {\n e.preventDefault();\n var data = this._findEvidenceData($(e.target));\n this.reviewUserEvidenceCompetencies(data);\n };\n\n /**\n * Find the evidence data from the evidence node.\n *\n * @param {Node} node The node to search from.\n * @return {Object} Evidence data.\n */\n UserEvidenceActions.prototype._findEvidenceData = function(node) {\n var parent = node.parentsUntil($(this._region).parent(), this._evidenceNode),\n data;\n\n if (parent.length != 1) {\n throw new Error('The evidence node was not located.');\n }\n\n data = parent.data();\n if (typeof data === 'undefined' || typeof data.id === 'undefined') {\n throw new Error('Evidence data could not be found.');\n }\n\n return data;\n };\n\n /**\n * Enhance a menu bar.\n *\n * @param {String} selector Menubar selector.\n */\n UserEvidenceActions.prototype.enhanceMenubar = function(selector) {\n var self = this;\n Menubar.enhance(selector, {\n '[data-action=\"user-evidence-delete\"]': self._deleteEvidenceHandler.bind(self),\n '[data-action=\"link-competency\"]': self._createUserEvidenceCompetencyHandler.bind(self),\n '[data-action=\"send-competencies-review\"]': self._reviewUserEvidenceCompetenciesHandler.bind(self),\n });\n };\n\n /**\n * Register the events in the region.\n *\n * At this stage this cannot be used with enhanceMenubar or multiple handlers\n * will be added to the same node.\n */\n UserEvidenceActions.prototype.registerEvents = function() {\n var wrapper = $(this._region),\n self = this;\n\n wrapper.find('[data-action=\"user-evidence-delete\"]').click(self._deleteEvidenceHandler.bind(self));\n wrapper.find('[data-action=\"link-competency\"]').click(self._createUserEvidenceCompetencyHandler.bind(self));\n wrapper.find('[data-action=\"delete-competency-link\"]').click(self._deleteUserEvidenceCompetencyHandler.bind(self));\n wrapper.find('[data-action=\"send-competencies-review\"]').click(self._reviewUserEvidenceCompetenciesHandler.bind(self));\n };\n\n return /** @alias module:tool_lp/user_evidence_actions */ UserEvidenceActions;\n});\n"],"names":["define","$","templates","ajax","notification","str","Menubar","PickerUserPlans","UserEvidenceActions","type","_type","_region","_evidenceNode","_template","_contextMethod","TypeError","prototype","_getContextArgs","evidenceData","args","this","id","userid","_renderView","context","self","render","then","newhtml","newjs","replaceNode","_callAndRefresh","calls","push","methodname","when","apply","call","arguments","length","fail","exception","_doDelete","deleteEvidence","done","evidence","get_strings","key","component","param","name","strings","confirm","_deleteEvidenceHandler","e","preventDefault","data","_findEvidenceData","target","_doCreateUserEvidenceCompetency","competencyIds","each","index","competencyId","userevidenceid","competencyid","createUserEvidenceCompetency","picker","on","requestReview","display","_createUserEvidenceCompetencyHandler","_doDeleteUserEvidenceCompetency","deleteUserEvidenceCompetency","_deleteUserEvidenceCompetencyHandler","currentTarget","_doReviewUserEvidenceCompetencies","reviewUserEvidenceCompetencies","_reviewUserEvidenceCompetenciesHandler","node","parent","parentsUntil","Error","enhanceMenubar","selector","enhance","bind","registerEvents","wrapper","find","click"],"mappings":";;;;;;;AAsBAA,uCAAO,CAAC,SACA,iBACA,YACA,oBACA,WACA,kBACA,wCACA,SAASC,EAAGC,UAAWC,KAAMC,aAAcC,IAAKC,QAASC,qBASzDC,oBAAsB,SAASC,cAC1BC,MAAQD,KAEA,aAATA,UAEKE,QAAU,0CACVC,cAAgB,0CAChBC,UAAY,kCACZC,eAAiB,0CAEnB,CAAA,GAAa,SAATL,WAQD,IAAIM,UAAU,yBANfJ,QAAU,0CACVC,cAAgB,0CAChBC,UAAY,uCACZC,eAAiB,oDAQ9BN,oBAAoBQ,UAAUF,eAAiB,KAE/CN,oBAAoBQ,UAAUJ,cAAgB,KAE9CJ,oBAAoBQ,UAAUL,QAAU,KAExCH,oBAAoBQ,UAAUH,UAAY,KAE1CL,oBAAoBQ,UAAUN,MAAQ,KAQtCF,oBAAoBQ,UAAUC,gBAAkB,SAASC,kBAEjDC,KAAO,SAEQ,aAHRC,KAGFV,MACLS,KAAO,CACHE,GAAIH,aAAaG,IAGC,SARfD,KAQKV,QACZS,KAAO,CACHG,OAAQJ,aAAaI,SAItBH,MASXX,oBAAoBQ,UAAUO,YAAc,SAASC,aAC7CC,KAAOL,YACJlB,UAAUwB,OAAOD,KAAKZ,UAAWW,SACnCG,MAAK,SAASC,QAASC,OACpB3B,UAAU4B,YAAY7B,EAAEwB,KAAKd,SAAUiB,QAASC,WAY5DrB,oBAAoBQ,UAAUe,gBAAkB,SAASC,MAAOd,kBACxDO,KAAOL,YACXY,MAAMC,KAAK,CACPC,WAAYT,KAAKX,eACjBK,KAAMM,KAAKR,gBAAgBC,gBAIxBjB,EAAEkC,KAAKC,MAAMnC,EAAEkC,KAAMhC,KAAKkC,KAAKL,QACjCL,MAAK,kBACKF,KAAKF,YAAYe,UAAUA,UAAUC,OAAS,OAExDC,KAAKpC,aAAaqC,YAQ3BjC,oBAAoBQ,UAAU0B,UAAY,SAASxB,kBAE3Cc,MAAQ,CAAC,CACLE,WAAY,uCACZf,KAAM,CAACE,GAAIH,aAAaG,MAHrBD,KAKNW,gBAAgBC,MAAOd,eAQhCV,oBAAoBQ,UAAU2B,eAAiB,SAASzB,kBAChDO,KAAOL,KAGAjB,KAAKkC,KAAK,CAAC,CAClBH,WAAY,qCACZf,KAAM,CAACE,GAAIH,aAAaG,OAGnB,GAAGuB,MAAK,SAASC,UACtBxC,IAAIyC,YAAY,CACZ,CAACC,IAAK,UAAWC,UAAW,UAC5B,CAACD,IAAK,qBAAsBC,UAAW,UAAWC,MAAOJ,SAASK,MAClE,CAACH,IAAK,SAAUC,UAAW,UAC3B,CAACD,IAAK,SAAUC,UAAW,YAC5BJ,MAAK,SAASO,SACb/C,aAAagD,QACTD,QAAQ,GACRA,QAAQ,GACRA,QAAQ,GACRA,QAAQ,IACR,WACI1B,KAAKiB,UAAUxB,oBAGxBsB,KAAKpC,aAAaqC,cACtBD,KAAKpC,aAAaqC,YASzBjC,oBAAoBQ,UAAUqC,uBAAyB,SAASC,GAC5DA,EAAEC,qBACEC,KAAOpC,KAAKqC,kBAAkBxD,EAAEqD,EAAEI,cACjCf,eAAea,OASxBhD,oBAAoBQ,UAAU2C,gCAAkC,SAASzC,aAAc0C,mBAE/E5B,MAAQ,GAEZ/B,EAAE4D,KAAKD,eAAe,SAASE,MAAOC,cAClC/B,MAAMC,KAAK,CACPC,WAAY,kDACZf,KAAM,CACF6C,eAAgB9C,aAAaG,GAC7B4C,aAAcF,mBARf3C,KAaNW,gBAAgBC,MAAOd,eAQhCV,oBAAoBQ,UAAUkD,6BAA+B,SAAShD,kBAC9DO,KAAOL,KACP+C,OAAS,IAAI5D,gBAAgBW,aAAaI,QAE9C6C,OAAOC,GAAG,QAAQ,SAASd,EAAGE,UACtBI,cAAgBJ,KAAKI,cACzBnC,KAAKkC,gCAAgCzC,aAAc0C,cAAeJ,KAAKa,kBAG3EF,OAAOG,WAQX9D,oBAAoBQ,UAAUuD,qCAAuC,SAASjB,GAC1EA,EAAEC,qBACEC,KAAOpC,KAAKqC,kBAAkBxD,EAAEqD,EAAEI,cACjCQ,6BAA6BV,OAStChD,oBAAoBQ,UAAUwD,gCAAkC,SAAStD,aAAc6C,kBAE/E/B,MAAQ,GAEZA,MAAMC,KAAK,CACPC,WAAY,kDACZf,KAAM,CACF6C,eAAgB9C,aAAaG,GAC7B4C,aAAcF,gBAPX3C,KAWNW,gBAAgBC,MAAOd,eAShCV,oBAAoBQ,UAAUyD,6BAA+B,SAASvD,aAAc6C,mBAC3ES,gCAAgCtD,aAAc6C,eAQvDvD,oBAAoBQ,UAAU0D,qCAAuC,SAASpB,OACtEE,KAAOpC,KAAKqC,kBAAkBxD,EAAEqD,EAAEqB,gBAClCZ,aAAe9D,EAAEqD,EAAEqB,eAAenB,KAAK,MAC3CF,EAAEC,sBACGkB,6BAA6BjB,KAAMO,eAQ5CvD,oBAAoBQ,UAAU4D,kCAAoC,SAAS1D,kBAEnEc,MAAQ,CAAC,CACLE,WAAY,sEACZf,KAAM,CAACE,GAAIH,aAAaG,MAHrBD,KAKNW,gBAAgBC,MAAOd,eAQhCV,oBAAoBQ,UAAU6D,+BAAiC,SAAS3D,kBAChEO,KAAOL,KAGAjB,KAAKkC,KAAK,CAAC,CAClBH,WAAY,qCACZf,KAAM,CAACE,GAAIH,aAAaG,OAGnB,GAAGuB,MAAK,SAASC,UACtBxC,IAAIyC,YAAY,CACZ,CAACC,IAAK,UAAWC,UAAW,UAC5B,CAACD,IAAK,8BAA+BC,UAAW,UAAWC,MAAOJ,SAASK,MAC3E,CAACH,IAAK,UAAWC,UAAW,UAC5B,CAACD,IAAK,SAAUC,UAAW,YAC5BJ,MAAK,SAASO,SACb/C,aAAagD,QACTD,QAAQ,GACRA,QAAQ,GACRA,QAAQ,GACRA,QAAQ,IACR,WACI1B,KAAKmD,kCAAkC1D,oBAGhDsB,KAAKpC,aAAaqC,cACtBD,KAAKpC,aAAaqC,YASzBjC,oBAAoBQ,UAAU8D,uCAAyC,SAASxB,GAC5EA,EAAEC,qBACEC,KAAOpC,KAAKqC,kBAAkBxD,EAAEqD,EAAEI,cACjCmB,+BAA+BrB,OASxChD,oBAAoBQ,UAAUyC,kBAAoB,SAASsB,UAEnDvB,KADAwB,OAASD,KAAKE,aAAahF,EAAEmB,KAAKT,SAASqE,SAAU5D,KAAKR,kBAGzC,GAAjBoE,OAAOzC,aACD,IAAI2C,MAAM,8CAIA,KADpB1B,KAAOwB,OAAOxB,cACwC,IAAZA,KAAKnC,SACrC,IAAI6D,MAAM,4CAGb1B,MAQXhD,oBAAoBQ,UAAUmE,eAAiB,SAASC,UAEpD9E,QAAQ+E,QAAQD,SAAU,wCADfhE,KAEsCiC,uBAAuBiC,KAF7DlE,wCAAAA,KAGiCmD,qCAAqCe,KAHtElE,iDAAAA,KAI0C0D,uCAAuCQ,KAJjFlE,SAcfZ,oBAAoBQ,UAAUuE,eAAiB,eACvCC,QAAUvF,EAAEmB,KAAKT,SAGrB6E,QAAQC,KAAK,wCAAwCC,MAF1CtE,KAEqDiC,uBAAuBiC,KAF5ElE,OAGXoE,QAAQC,KAAK,mCAAmCC,MAHrCtE,KAGgDmD,qCAAqCe,KAHrFlE,OAIXoE,QAAQC,KAAK,0CAA0CC,MAJ5CtE,KAIuDsD,qCAAqCY,KAJ5FlE,OAKXoE,QAAQC,KAAK,4CAA4CC,MAL9CtE,KAKyD0D,uCAAuCQ,KALhGlE,QAQ2CZ"}
\ No newline at end of file
diff --git a/admin/tool/monitor/yui/build/moodle-tool_monitor-dropdown/moodle-tool_monitor-dropdown-min.js b/admin/tool/monitor/yui/build/moodle-tool_monitor-dropdown/moodle-tool_monitor-dropdown-min.js
index 2e8537e4ccb..d30bd3f47fd 100644
--- a/admin/tool/monitor/yui/build/moodle-tool_monitor-dropdown/moodle-tool_monitor-dropdown-min.js
+++ b/admin/tool/monitor/yui/build/moodle-tool_monitor-dropdown/moodle-tool_monitor-dropdown-min.js
@@ -1 +1 @@
-YUI.add("moodle-tool_monitor-dropdown",function(s,e){function t(){t.superclass.constructor.apply(this,arguments)}var n="#id_plugin",i="#id_eventname",a="option";s.extend(t,s.Base,{plugin:null,eventname:null,initializer:function(){this.plugin=s.one(n),this.eventname=s.one(i);var e=this.eventname.get("value");this.updateEventsList(),this.updateSelection(e),this.plugin.on("change",this.updateEventsList,this)},updateEventsList:function(){var n,e,t,i=this.plugin.get("value"),o="\\"+i+"\\";this.eventname.all(a).remove(!0),e=this.get("eventlist"),(t=s.Node.create('")).set("selected","selected"),this.eventname.appendChild(t),s.Object.each(e,function(e,t){t.substring(0,o.length)===o&&(n=s.Node.create('"),this.eventname.appendChild(n))},this)},updateSelection:function(t){this.eventname.get("options").each(function(e){e.get("value")===t&&e.set("selected","selected")},this)}},{NAME:"dropDown",ATTRS:{eventlist:null}}),s.namespace("M.tool_monitor.DropDown").init=function(e){return new t(e)}},"@VERSION@",{requires:["base","event","node"]});
\ No newline at end of file
+YUI.add("moodle-tool_monitor-dropdown",function(o,e){function t(){t.superclass.constructor.apply(this,arguments)}var n="#id_plugin",i="#id_eventname",s="option";o.extend(t,o.Base,{plugin:null,eventname:null,initializer:function(){this.plugin=o.one(n),this.eventname=o.one(i);var e=this.eventname.get("value");this.updateEventsList(),this.updateSelection(e),this.plugin.on("change",this.updateEventsList,this)},updateEventsList:function(){var n,e,t=this.plugin.get("value"),i="\\"+t+"\\";this.eventname.all(s).remove(!0),t=this.get("eventlist"),(e=o.Node.create('")).set("selected","selected"),this.eventname.appendChild(e),o.Object.each(t,function(e,t){t.substring(0,i.length)===i&&(n=o.Node.create('"),this.eventname.appendChild(n))},this)},updateSelection:function(t){this.eventname.get("options").each(function(e){e.get("value")===t&&e.set("selected","selected")},this)}},{NAME:"dropDown",ATTRS:{eventlist:null}}),o.namespace("M.tool_monitor.DropDown").init=function(e){return new t(e)}},"@VERSION@",{requires:["base","event","node"]});
\ No newline at end of file
diff --git a/admin/tool/moodlenet/amd/build/instance_form.min.js b/admin/tool/moodlenet/amd/build/instance_form.min.js
index 70d692bc592..6b6ebb2ff29 100644
--- a/admin/tool/moodlenet/amd/build/instance_form.min.js
+++ b/admin/tool/moodlenet/amd/build/instance_form.min.js
@@ -1,2 +1,17 @@
-define ("tool_moodlenet/instance_form",["tool_moodlenet/validator","tool_moodlenet/selectors","core/loadingicon","core/templates","core/notification","jquery"],function(a,b,c,d,e,f){var g=function(d){d.addEventListener("click",function(f){if(f.target.matches(b.action.submit)){var e=d.querySelector("[data-var=\"mnet-link\"]"),g=d.querySelector(b.region.spinner),h=document.querySelector(b.region.validationArea);g.classList.remove("d-none");var i=c.addIconToContainerWithPromise(g);a.validation(e).then(function(a){i.resolve();g.classList.add("d-none");if(a.result){e.classList.remove("is-invalid");e.classList.add("is-valid");h.innerText=a.message;h.classList.remove("text-danger");h.classList.add("text-success");setTimeout(function(){window.location=a.domain},1e3)}else{e.classList.add("is-invalid");h.innerText=a.message;h.classList.add("text-danger")}}).catch()}})},h=function(a,b,h,i){a.innerHTML="";var j=c.addIconToContainer(a),k=null,l=new Promise(function(a){k=a});f.when(j,l).then(function(){d.replaceNodeContents(a,b.customcarouseltemplate,"")}).catch(e.exception);g(a);h.one("slid.bs.carousel",function(){k()});h.carousel(2);i.setFooter(d.render("tool_moodlenet/chooser_footer_close_mnet",{}))},i=function(a,b,c){a.carousel(0);b.setFooter(c.customfootertemplate)};return{footerClickListener:function footerClickListener(a,c,d){if(a.target.matches(b.action.showMoodleNet)||a.target.closest(b.action.showMoodleNet)){a.preventDefault();var e=f(d.getBody()[0].querySelector(b.region.carousel)),g=e.find(b.region.moodleNet)[0];h(g,c,e,d)}if(a.target.matches(b.action.closeOption)){var j=f(d.getBody()[0].querySelector(b.region.carousel));i(j,d,c)}}}});
-//# sourceMappingURL=instance_form.min.js.map
+/**
+ * Our basic form manager for when a user either enters
+ * their profile url or just wants to browse.
+ *
+ * This file is a mishmash of JS functions we need for both the standalone (M3.7, M3.8)
+ * plugin & Moodle 3.9 functions. The 3.9 Functions have a base understanding that certain
+ * things exist i.e. directory structures for templates. When this feature goes 3.9+ only
+ * The goal is that we can quickly gut all AMD modules into bare JS files and use ES6 guidelines.
+ * Till then this will have to do.
+ *
+ * @module tool_moodlenet/instance_form
+ * @copyright 2020 Mathew May
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_moodlenet/instance_form",["tool_moodlenet/validator","tool_moodlenet/selectors","core/loadingicon","core/templates","core/notification","jquery"],(function(Validator,Selectors,LoadingIcon,Templates,Notification,$){var chooserNavigateToMnet=function(showMoodleNet,footerData,carousel,modal){showMoodleNet.innerHTML="";var page,spinnerPromise=LoadingIcon.addIconToContainer(showMoodleNet),transitionPromiseResolver=null,transitionPromise=new Promise((resolve=>{transitionPromiseResolver=resolve}));$.when(spinnerPromise,transitionPromise).then((function(){Templates.replaceNodeContents(showMoodleNet,footerData.customcarouseltemplate,"")})).catch(Notification.exception),(page=showMoodleNet).addEventListener("click",(function(e){if(e.target.matches(Selectors.action.submit)){var input=page.querySelector('[data-var="mnet-link"]'),overlay=page.querySelector(Selectors.region.spinner),validationArea=document.querySelector(Selectors.region.validationArea);overlay.classList.remove("d-none");var spinner=LoadingIcon.addIconToContainerWithPromise(overlay);Validator.validation(input).then((function(result){spinner.resolve(),overlay.classList.add("d-none"),result.result?(input.classList.remove("is-invalid"),input.classList.add("is-valid"),validationArea.innerText=result.message,validationArea.classList.remove("text-danger"),validationArea.classList.add("text-success"),setTimeout((function(){window.location=result.domain}),1e3)):(input.classList.add("is-invalid"),validationArea.innerText=result.message,validationArea.classList.add("text-danger"))})).catch()}})),carousel.one("slid.bs.carousel",(function(){transitionPromiseResolver()})),carousel.carousel(2),modal.setFooter(Templates.render("tool_moodlenet/chooser_footer_close_mnet",{}))};return{footerClickListener:function(e,footerData,modal){if(e.target.matches(Selectors.action.showMoodleNet)||e.target.closest(Selectors.action.showMoodleNet)){e.preventDefault();const carousel=$(modal.getBody()[0].querySelector(Selectors.region.carousel)),showMoodleNet=carousel.find(Selectors.region.moodleNet)[0];chooserNavigateToMnet(showMoodleNet,footerData,carousel,modal)}if(e.target.matches(Selectors.action.closeOption)){!function(carousel,modal,footerData){carousel.carousel(0),modal.setFooter(footerData.customfootertemplate)}($(modal.getBody()[0].querySelector(Selectors.region.carousel)),modal,footerData)}}}}));
+
+//# sourceMappingURL=instance_form.min.js.map
\ No newline at end of file
diff --git a/admin/tool/moodlenet/amd/build/instance_form.min.js.map b/admin/tool/moodlenet/amd/build/instance_form.min.js.map
index 0faff890d64..4d3ccc56ff7 100644
--- a/admin/tool/moodlenet/amd/build/instance_form.min.js.map
+++ b/admin/tool/moodlenet/amd/build/instance_form.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/instance_form.js"],"names":["define","Validator","Selectors","LoadingIcon","Templates","Notification","$","registerListenerEvents","page","addEventListener","e","target","matches","action","submit","input","querySelector","overlay","region","spinner","validationArea","document","classList","remove","addIconToContainerWithPromise","validation","then","result","resolve","add","innerText","message","setTimeout","window","location","domain","catch","chooserNavigateToMnet","showMoodleNet","footerData","carousel","modal","innerHTML","spinnerPromise","addIconToContainer","transitionPromiseResolver","transitionPromise","Promise","when","replaceNodeContents","customcarouseltemplate","exception","one","setFooter","render","chooserNavigateFromMnet","customfootertemplate","footerClickListener","closest","preventDefault","getBody","find","moodleNet","closeOption"],"mappings":"AA8BAA,OAAM,gCAAC,CAAC,0BAAD,CACC,0BADD,CAEC,kBAFD,CAGC,gBAHD,CAIC,mBAJD,CAKC,QALD,CAAD,CAMF,SAASC,CAAT,CACSC,CADT,CAESC,CAFT,CAGSC,CAHT,CAISC,CAJT,CAKSC,CALT,CAKY,IAQRC,CAAAA,CAAsB,CAAG,SAAgCC,CAAhC,CAAsC,CAC/DA,CAAI,CAACC,gBAAL,CAAsB,OAAtB,CAA+B,SAASC,CAAT,CAAY,CAGvC,GAAIA,CAAC,CAACC,MAAF,CAASC,OAAT,CAAiBV,CAAS,CAACW,MAAV,CAAiBC,MAAlC,CAAJ,CAA+C,IACvCC,CAAAA,CAAK,CAAGP,CAAI,CAACQ,aAAL,CAAmB,0BAAnB,CAD+B,CAEvCC,CAAO,CAAGT,CAAI,CAACQ,aAAL,CAAmBd,CAAS,CAACgB,MAAV,CAAiBC,OAApC,CAF6B,CAGvCC,CAAc,CAAGC,QAAQ,CAACL,aAAT,CAAuBd,CAAS,CAACgB,MAAV,CAAiBE,cAAxC,CAHsB,CAK3CH,CAAO,CAACK,SAAR,CAAkBC,MAAlB,CAAyB,QAAzB,EACA,GAAIJ,CAAAA,CAAO,CAAGhB,CAAW,CAACqB,6BAAZ,CAA0CP,CAA1C,CAAd,CACAhB,CAAS,CAACwB,UAAV,CAAqBV,CAArB,EACKW,IADL,CACU,SAASC,CAAT,CAAiB,CACnBR,CAAO,CAACS,OAAR,GACAX,CAAO,CAACK,SAAR,CAAkBO,GAAlB,CAAsB,QAAtB,EACA,GAAIF,CAAM,CAACA,MAAX,CAAmB,CACfZ,CAAK,CAACO,SAAN,CAAgBC,MAAhB,CAAuB,YAAvB,EACAR,CAAK,CAACO,SAAN,CAAgBO,GAAhB,CAAoB,UAApB,EACAT,CAAc,CAACU,SAAf,CAA2BH,CAAM,CAACI,OAAlC,CACAX,CAAc,CAACE,SAAf,CAAyBC,MAAzB,CAAgC,aAAhC,EACAH,CAAc,CAACE,SAAf,CAAyBO,GAAzB,CAA6B,cAA7B,EAEAG,UAAU,CAAC,UAAW,CAClBC,MAAM,CAACC,QAAP,CAAkBP,CAAM,CAACQ,MAC5B,CAFS,CAEP,GAFO,CAGb,CAVD,IAUO,CACHpB,CAAK,CAACO,SAAN,CAAgBO,GAAhB,CAAoB,YAApB,EACAT,CAAc,CAACU,SAAf,CAA2BH,CAAM,CAACI,OAAlC,CACAX,CAAc,CAACE,SAAf,CAAyBO,GAAzB,CAA6B,aAA7B,CACH,CAER,CApBD,EAoBGO,KApBH,EAqBH,CACJ,CAhCD,CAiCH,CA1CW,CAqDRC,CAAqB,CAAG,SAASC,CAAT,CAAwBC,CAAxB,CAAoCC,CAApC,CAA8CC,CAA9C,CAAqD,CAC7EH,CAAa,CAACI,SAAd,CAA0B,EAA1B,CAD6E,GAIzEC,CAAAA,CAAc,CAAGxC,CAAW,CAACyC,kBAAZ,CAA+BN,CAA/B,CAJwD,CAOzEO,CAAyB,CAAG,IAP6C,CAQzEC,CAAiB,CAAG,GAAIC,CAAAA,OAAJ,CAAY,SAAAnB,CAAO,CAAI,CAC3CiB,CAAyB,CAAGjB,CAC/B,CAFuB,CARqD,CAY7EtB,CAAC,CAAC0C,IAAF,CACIL,CADJ,CAEIG,CAFJ,EAGEpB,IAHF,CAGO,UAAW,CACVtB,CAAS,CAAC6C,mBAAV,CAA8BX,CAA9B,CAA6CC,CAAU,CAACW,sBAAxD,CAAgF,EAAhF,CAEP,CAND,EAMGd,KANH,CAMS/B,CAAY,CAAC8C,SANtB,EASA5C,CAAsB,CAAC+B,CAAD,CAAtB,CAGAE,CAAQ,CAACY,GAAT,CAAa,kBAAb,CAAiC,UAAW,CACxCP,CAAyB,EAC5B,CAFD,EAIAL,CAAQ,CAACA,QAAT,CAAkB,CAAlB,EAEAC,CAAK,CAACY,SAAN,CAAgBjD,CAAS,CAACkD,MAAV,CAAiB,0CAAjB,CAA6D,EAA7D,CAAhB,CACH,CApFW,CA8FRC,CAAuB,CAAG,SAASf,CAAT,CAAmBC,CAAnB,CAA0BF,CAA1B,CAAsC,CAEhEC,CAAQ,CAACA,QAAT,CAAkB,CAAlB,EACAC,CAAK,CAACY,SAAN,CAAgBd,CAAU,CAACiB,oBAA3B,CACH,CAlGW,CA2HZ,MAAO,CACHC,mBAAmB,CAjBG,QAAtBA,CAAAA,mBAAsB,CAAS/C,CAAT,CAAY6B,CAAZ,CAAwBE,CAAxB,CAA+B,CACrD,GAAI/B,CAAC,CAACC,MAAF,CAASC,OAAT,CAAiBV,CAAS,CAACW,MAAV,CAAiByB,aAAlC,GAAoD5B,CAAC,CAACC,MAAF,CAAS+C,OAAT,CAAiBxD,CAAS,CAACW,MAAV,CAAiByB,aAAlC,CAAxD,CAA0G,CACtG5B,CAAC,CAACiD,cAAF,GADsG,GAEhGnB,CAAAA,CAAQ,CAAGlC,CAAC,CAACmC,CAAK,CAACmB,OAAN,GAAgB,CAAhB,EAAmB5C,aAAnB,CAAiCd,CAAS,CAACgB,MAAV,CAAiBsB,QAAlD,CAAD,CAFoF,CAGhGF,CAAa,CAAGE,CAAQ,CAACqB,IAAT,CAAc3D,CAAS,CAACgB,MAAV,CAAiB4C,SAA/B,EAA0C,CAA1C,CAHgF,CAKtGzB,CAAqB,CAACC,CAAD,CAAgBC,CAAhB,CAA4BC,CAA5B,CAAsCC,CAAtC,CACxB,CAED,GAAI/B,CAAC,CAACC,MAAF,CAASC,OAAT,CAAiBV,CAAS,CAACW,MAAV,CAAiBkD,WAAlC,CAAJ,CAAoD,CAChD,GAAMvB,CAAAA,CAAQ,CAAGlC,CAAC,CAACmC,CAAK,CAACmB,OAAN,GAAgB,CAAhB,EAAmB5C,aAAnB,CAAiCd,CAAS,CAACgB,MAAV,CAAiBsB,QAAlD,CAAD,CAAlB,CAEAe,CAAuB,CAACf,CAAD,CAAWC,CAAX,CAAkBF,CAAlB,CAC1B,CACJ,CAEM,CAGV,CAzIK,CAAN","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 .\n\n/**\n * Our basic form manager for when a user either enters\n * their profile url or just wants to browse.\n *\n * This file is a mishmash of JS functions we need for both the standalone (M3.7, M3.8)\n * plugin & Moodle 3.9 functions. The 3.9 Functions have a base understanding that certain\n * things exist i.e. directory structures for templates. When this feature goes 3.9+ only\n * The goal is that we can quickly gut all AMD modules into bare JS files and use ES6 guidelines.\n * Till then this will have to do.\n *\n * @module tool_moodlenet/instance_form\n * @copyright 2020 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['tool_moodlenet/validator',\n 'tool_moodlenet/selectors',\n 'core/loadingicon',\n 'core/templates',\n 'core/notification',\n 'jquery'],\n function(Validator,\n Selectors,\n LoadingIcon,\n Templates,\n Notification,\n $) {\n\n /**\n * Add the event listeners to our form.\n *\n * @method registerListenerEvents\n * @param {HTMLElement} page The whole page element for our form area\n */\n var registerListenerEvents = function registerListenerEvents(page) {\n page.addEventListener('click', function(e) {\n\n // Our fake submit button / browse button.\n if (e.target.matches(Selectors.action.submit)) {\n var input = page.querySelector('[data-var=\"mnet-link\"]');\n var overlay = page.querySelector(Selectors.region.spinner);\n var validationArea = document.querySelector(Selectors.region.validationArea);\n\n overlay.classList.remove('d-none');\n var spinner = LoadingIcon.addIconToContainerWithPromise(overlay);\n Validator.validation(input)\n .then(function(result) {\n spinner.resolve();\n overlay.classList.add('d-none');\n if (result.result) {\n input.classList.remove('is-invalid'); // Just in case the class has been applied already.\n input.classList.add('is-valid');\n validationArea.innerText = result.message;\n validationArea.classList.remove('text-danger');\n validationArea.classList.add('text-success');\n // Give the user some time to see their input is valid.\n setTimeout(function() {\n window.location = result.domain;\n }, 1000);\n } else {\n input.classList.add('is-invalid');\n validationArea.innerText = result.message;\n validationArea.classList.add('text-danger');\n }\n return;\n }).catch();\n }\n });\n };\n\n /**\n * Given a user wishes to see the MoodleNet profile url form transition them there.\n *\n * @method chooserNavigateToMnet\n * @param {HTMLElement} showMoodleNet The chooser's area for ment\n * @param {Object} footerData Our footer object to render out\n * @param {jQuery} carousel Our carousel instance to manage\n * @param {jQuery} modal Our modal instance to manage\n */\n var chooserNavigateToMnet = function(showMoodleNet, footerData, carousel, modal) {\n showMoodleNet.innerHTML = '';\n\n // Add a spinner.\n var spinnerPromise = LoadingIcon.addIconToContainer(showMoodleNet);\n\n // Used later...\n var transitionPromiseResolver = null;\n var transitionPromise = new Promise(resolve => {\n transitionPromiseResolver = resolve;\n });\n\n $.when(\n spinnerPromise,\n transitionPromise\n ).then(function() {\n Templates.replaceNodeContents(showMoodleNet, footerData.customcarouseltemplate, '');\n return;\n }).catch(Notification.exception);\n\n // We apply our handlers in here to minimise plugin dependency in the Chooser.\n registerListenerEvents(showMoodleNet);\n\n // Move to the next slide, and resolve the transition promise when it's done.\n carousel.one('slid.bs.carousel', function() {\n transitionPromiseResolver();\n });\n // Trigger the transition between 'pages'.\n carousel.carousel(2);\n // eslint-disable-next-line max-len\n modal.setFooter(Templates.render('tool_moodlenet/chooser_footer_close_mnet', {}));\n };\n\n /**\n * Given a user no longer wishes to see the MoodleNet profile url form transition them from there.\n *\n * @method chooserNavigateFromMnet\n * @param {jQuery} carousel Our carousel instance to manage\n * @param {jQuery} modal Our modal instance to manage\n * @param {Object} footerData Our footer object to render out\n */\n var chooserNavigateFromMnet = function(carousel, modal, footerData) {\n // Trigger the transition between 'pages'.\n carousel.carousel(0);\n modal.setFooter(footerData.customfootertemplate);\n };\n\n /**\n * Create the custom listener that would handle anything in the footer.\n *\n * @param {Event} e The event being triggered.\n * @param {Object} footerData The data generated from the exporter.\n * @param {Object} modal The chooser modal.\n */\n var footerClickListener = function(e, footerData, modal) {\n if (e.target.matches(Selectors.action.showMoodleNet) || e.target.closest(Selectors.action.showMoodleNet)) {\n e.preventDefault();\n const carousel = $(modal.getBody()[0].querySelector(Selectors.region.carousel));\n const showMoodleNet = carousel.find(Selectors.region.moodleNet)[0];\n\n chooserNavigateToMnet(showMoodleNet, footerData, carousel, modal);\n }\n // From the help screen go back to the module overview.\n if (e.target.matches(Selectors.action.closeOption)) {\n const carousel = $(modal.getBody()[0].querySelector(Selectors.region.carousel));\n\n chooserNavigateFromMnet(carousel, modal, footerData);\n }\n };\n\n return {\n footerClickListener: footerClickListener\n };\n});\n"],"file":"instance_form.min.js"}
\ No newline at end of file
+{"version":3,"file":"instance_form.min.js","sources":["../src/instance_form.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 .\n\n/**\n * Our basic form manager for when a user either enters\n * their profile url or just wants to browse.\n *\n * This file is a mishmash of JS functions we need for both the standalone (M3.7, M3.8)\n * plugin & Moodle 3.9 functions. The 3.9 Functions have a base understanding that certain\n * things exist i.e. directory structures for templates. When this feature goes 3.9+ only\n * The goal is that we can quickly gut all AMD modules into bare JS files and use ES6 guidelines.\n * Till then this will have to do.\n *\n * @module tool_moodlenet/instance_form\n * @copyright 2020 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['tool_moodlenet/validator',\n 'tool_moodlenet/selectors',\n 'core/loadingicon',\n 'core/templates',\n 'core/notification',\n 'jquery'],\n function(Validator,\n Selectors,\n LoadingIcon,\n Templates,\n Notification,\n $) {\n\n /**\n * Add the event listeners to our form.\n *\n * @method registerListenerEvents\n * @param {HTMLElement} page The whole page element for our form area\n */\n var registerListenerEvents = function registerListenerEvents(page) {\n page.addEventListener('click', function(e) {\n\n // Our fake submit button / browse button.\n if (e.target.matches(Selectors.action.submit)) {\n var input = page.querySelector('[data-var=\"mnet-link\"]');\n var overlay = page.querySelector(Selectors.region.spinner);\n var validationArea = document.querySelector(Selectors.region.validationArea);\n\n overlay.classList.remove('d-none');\n var spinner = LoadingIcon.addIconToContainerWithPromise(overlay);\n Validator.validation(input)\n .then(function(result) {\n spinner.resolve();\n overlay.classList.add('d-none');\n if (result.result) {\n input.classList.remove('is-invalid'); // Just in case the class has been applied already.\n input.classList.add('is-valid');\n validationArea.innerText = result.message;\n validationArea.classList.remove('text-danger');\n validationArea.classList.add('text-success');\n // Give the user some time to see their input is valid.\n setTimeout(function() {\n window.location = result.domain;\n }, 1000);\n } else {\n input.classList.add('is-invalid');\n validationArea.innerText = result.message;\n validationArea.classList.add('text-danger');\n }\n return;\n }).catch();\n }\n });\n };\n\n /**\n * Given a user wishes to see the MoodleNet profile url form transition them there.\n *\n * @method chooserNavigateToMnet\n * @param {HTMLElement} showMoodleNet The chooser's area for ment\n * @param {Object} footerData Our footer object to render out\n * @param {jQuery} carousel Our carousel instance to manage\n * @param {jQuery} modal Our modal instance to manage\n */\n var chooserNavigateToMnet = function(showMoodleNet, footerData, carousel, modal) {\n showMoodleNet.innerHTML = '';\n\n // Add a spinner.\n var spinnerPromise = LoadingIcon.addIconToContainer(showMoodleNet);\n\n // Used later...\n var transitionPromiseResolver = null;\n var transitionPromise = new Promise(resolve => {\n transitionPromiseResolver = resolve;\n });\n\n $.when(\n spinnerPromise,\n transitionPromise\n ).then(function() {\n Templates.replaceNodeContents(showMoodleNet, footerData.customcarouseltemplate, '');\n return;\n }).catch(Notification.exception);\n\n // We apply our handlers in here to minimise plugin dependency in the Chooser.\n registerListenerEvents(showMoodleNet);\n\n // Move to the next slide, and resolve the transition promise when it's done.\n carousel.one('slid.bs.carousel', function() {\n transitionPromiseResolver();\n });\n // Trigger the transition between 'pages'.\n carousel.carousel(2);\n // eslint-disable-next-line max-len\n modal.setFooter(Templates.render('tool_moodlenet/chooser_footer_close_mnet', {}));\n };\n\n /**\n * Given a user no longer wishes to see the MoodleNet profile url form transition them from there.\n *\n * @method chooserNavigateFromMnet\n * @param {jQuery} carousel Our carousel instance to manage\n * @param {jQuery} modal Our modal instance to manage\n * @param {Object} footerData Our footer object to render out\n */\n var chooserNavigateFromMnet = function(carousel, modal, footerData) {\n // Trigger the transition between 'pages'.\n carousel.carousel(0);\n modal.setFooter(footerData.customfootertemplate);\n };\n\n /**\n * Create the custom listener that would handle anything in the footer.\n *\n * @param {Event} e The event being triggered.\n * @param {Object} footerData The data generated from the exporter.\n * @param {Object} modal The chooser modal.\n */\n var footerClickListener = function(e, footerData, modal) {\n if (e.target.matches(Selectors.action.showMoodleNet) || e.target.closest(Selectors.action.showMoodleNet)) {\n e.preventDefault();\n const carousel = $(modal.getBody()[0].querySelector(Selectors.region.carousel));\n const showMoodleNet = carousel.find(Selectors.region.moodleNet)[0];\n\n chooserNavigateToMnet(showMoodleNet, footerData, carousel, modal);\n }\n // From the help screen go back to the module overview.\n if (e.target.matches(Selectors.action.closeOption)) {\n const carousel = $(modal.getBody()[0].querySelector(Selectors.region.carousel));\n\n chooserNavigateFromMnet(carousel, modal, footerData);\n }\n };\n\n return {\n footerClickListener: footerClickListener\n };\n});\n"],"names":["define","Validator","Selectors","LoadingIcon","Templates","Notification","$","chooserNavigateToMnet","showMoodleNet","footerData","carousel","modal","innerHTML","page","spinnerPromise","addIconToContainer","transitionPromiseResolver","transitionPromise","Promise","resolve","when","then","replaceNodeContents","customcarouseltemplate","catch","exception","addEventListener","e","target","matches","action","submit","input","querySelector","overlay","region","spinner","validationArea","document","classList","remove","addIconToContainerWithPromise","validation","result","add","innerText","message","setTimeout","window","location","domain","one","setFooter","render","footerClickListener","closest","preventDefault","getBody","find","moodleNet","closeOption","customfootertemplate","chooserNavigateFromMnet"],"mappings":";;;;;;;;;;;;;;AA8BAA,sCAAO,CAAC,2BACA,2BACA,mBACA,iBACA,oBACA,WACJ,SAASC,UACAC,UACAC,YACAC,UACAC,aACAC,OAqDLC,sBAAwB,SAASC,cAAeC,WAAYC,SAAUC,OACtEH,cAAcI,UAAY,OA9C+BC,KAiDrDC,eAAiBX,YAAYY,mBAAmBP,eAGhDQ,0BAA4B,KAC5BC,kBAAoB,IAAIC,SAAQC,UAChCH,0BAA4BG,WAGhCb,EAAEc,KACEN,eACAG,mBACFI,MAAK,WACCjB,UAAUkB,oBAAoBd,cAAeC,WAAWc,uBAAwB,OAErFC,MAAMnB,aAAaoB,YA/DmCZ,KAkElCL,eAjElBkB,iBAAiB,SAAS,SAASC,MAGhCA,EAAEC,OAAOC,QAAQ3B,UAAU4B,OAAOC,QAAS,KACvCC,MAAQnB,KAAKoB,cAAc,0BAC3BC,QAAUrB,KAAKoB,cAAc/B,UAAUiC,OAAOC,SAC9CC,eAAiBC,SAASL,cAAc/B,UAAUiC,OAAOE,gBAE7DH,QAAQK,UAAUC,OAAO,cACrBJ,QAAUjC,YAAYsC,8BAA8BP,SACxDjC,UAAUyC,WAAWV,OAChBX,MAAK,SAASsB,QACXP,QAAQjB,UACRe,QAAQK,UAAUK,IAAI,UAClBD,OAAOA,QACPX,MAAMO,UAAUC,OAAO,cACvBR,MAAMO,UAAUK,IAAI,YACpBP,eAAeQ,UAAYF,OAAOG,QAClCT,eAAeE,UAAUC,OAAO,eAChCH,eAAeE,UAAUK,IAAI,gBAE7BG,YAAW,WACPC,OAAOC,SAAWN,OAAOO,SAC1B,OAEHlB,MAAMO,UAAUK,IAAI,cACpBP,eAAeQ,UAAYF,OAAOG,QAClCT,eAAeE,UAAUK,IAAI,mBAGtCpB,YAsCXd,SAASyC,IAAI,oBAAoB,WAC7BnC,+BAGJN,SAASA,SAAS,GAElBC,MAAMyC,UAAUhD,UAAUiD,OAAO,2CAA4C,YAwC1E,CACHC,oBAjBsB,SAAS3B,EAAGlB,WAAYE,UAC1CgB,EAAEC,OAAOC,QAAQ3B,UAAU4B,OAAOtB,gBAAkBmB,EAAEC,OAAO2B,QAAQrD,UAAU4B,OAAOtB,eAAgB,CACtGmB,EAAE6B,uBACI9C,SAAWJ,EAAEK,MAAM8C,UAAU,GAAGxB,cAAc/B,UAAUiC,OAAOzB,WAC/DF,cAAgBE,SAASgD,KAAKxD,UAAUiC,OAAOwB,WAAW,GAEhEpD,sBAAsBC,cAAeC,WAAYC,SAAUC,UAG3DgB,EAAEC,OAAOC,QAAQ3B,UAAU4B,OAAO8B,aAAc,EAtB1B,SAASlD,SAAUC,MAAOF,YAEpDC,SAASA,SAAS,GAClBC,MAAMyC,UAAU3C,WAAWoD,sBAsBvBC,CAFiBxD,EAAEK,MAAM8C,UAAU,GAAGxB,cAAc/B,UAAUiC,OAAOzB,WAEnCC,MAAOF"}
\ No newline at end of file
diff --git a/admin/tool/moodlenet/amd/build/select_page.min.js b/admin/tool/moodlenet/amd/build/select_page.min.js
index 558896069b9..a74d396a408 100644
--- a/admin/tool/moodlenet/amd/build/select_page.min.js
+++ b/admin/tool/moodlenet/amd/build/select_page.min.js
@@ -1,2 +1,10 @@
-define ("tool_moodlenet/select_page",["core/ajax","core/templates","tool_moodlenet/selectors","core/notification"],function(a,b,c,d){var e,f=function(a){return b.renderPix("courses","tool_moodlenet").then(function(a){return a}).then(function(a){var c=document.createElement("div");c.innerHTML=a.trim();return b.render("core_course/no-courses",{nocoursesimg:c.firstChild.src})}).then(function(c,d){b.replaceNodeContents(a,c,d);a.classList.add("mx-auto");a.classList.add("w-25")})},g=function(a,c){return b.render("tool_moodlenet/view-cards",{courses:c}).then(function(c,d){b.replaceNodeContents(a,c,d);a.classList.remove("mx-auto");a.classList.remove("w-25")})},h=function(b,h,i){var j=h.querySelector(c.region.searchIcon),k=h.querySelector(c.region.clearIcon);if(""!==b){j.classList.add("d-none");k.parentElement.classList.remove("d-none")}else{j.classList.remove("d-none");k.parentElement.classList.add("d-none")}a.call([{methodname:"tool_moodlenet_search_courses",args:{searchvalue:b}}])[0].then(function(a){if(0===a.courses.length){return f(i)}else{a.courses.forEach(function(a){a.viewurl+="&id="+e});return g(i,a.courses)}}).catch(d.exception)},i=function(a){var b=a.querySelector(c.region.searchInput),d=a.querySelector(c.region.courses),e=a.querySelector(c.region.clearIcon);e.addEventListener("click",function(){b.value="";h("",a,d)});b.addEventListener("input",k(function(){h(b.value,a,d)},300))},j=function(a){var b=a.querySelector(c.region.courses);h("",a,b)},k=function(a,b,c){var d;return function(){var e=this,f=arguments,g=c&&!d;clearTimeout(d);d=setTimeout(function later(){d=null;if(!c){a.apply(e,f)}},b);if(g){a.apply(e,f)}}};return{init:function init(a){e=a;var b=document.querySelector(c.region.selectPage);i(b);j(b)}}});
-//# sourceMappingURL=select_page.min.js.map
+/**
+ * When returning to Moodle let the user select which course to add the resource to.
+ *
+ * @module tool_moodlenet/select_page
+ * @copyright 2020 Mathew May
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_moodlenet/select_page",["core/ajax","core/templates","tool_moodlenet/selectors","core/notification"],(function(Ajax,Templates,Selectors,Notification){var importId,searchCourses=function(inputValue,page,areaReplace){var searchIcon=page.querySelector(Selectors.region.searchIcon),clearIcon=page.querySelector(Selectors.region.clearIcon);""!==inputValue?(searchIcon.classList.add("d-none"),clearIcon.parentElement.classList.remove("d-none")):(searchIcon.classList.remove("d-none"),clearIcon.parentElement.classList.add("d-none"));var args={searchvalue:inputValue};Ajax.call([{methodname:"tool_moodlenet_search_courses",args:args}])[0].then((function(result){return 0===result.courses.length?function(areaReplace){return Templates.renderPix("courses","tool_moodlenet").then((function(img){return img})).then((function(img){var temp=document.createElement("div");return temp.innerHTML=img.trim(),Templates.render("core_course/no-courses",{nocoursesimg:temp.firstChild.src})})).then((function(html,js){Templates.replaceNodeContents(areaReplace,html,js),areaReplace.classList.add("mx-auto"),areaReplace.classList.add("w-25")}))}(areaReplace):(result.courses.forEach((function(course){course.viewurl+="&id="+importId})),function(areaReplace,courses){return Templates.render("tool_moodlenet/view-cards",{courses:courses}).then((function(html,js){Templates.replaceNodeContents(areaReplace,html,js),areaReplace.classList.remove("mx-auto"),areaReplace.classList.remove("w-25")}))}(areaReplace,result.courses))})).catch(Notification.exception)},registerListenerEvents=function(page){var input=page.querySelector(Selectors.region.searchInput),courseArea=page.querySelector(Selectors.region.courses);page.querySelector(Selectors.region.clearIcon).addEventListener("click",(function(){input.value="",searchCourses("",page,courseArea)})),input.addEventListener("input",debounce((function(){searchCourses(input.value,page,courseArea)}),300))},addCourses=function(page){var courseArea=page.querySelector(Selectors.region.courses);searchCourses("",page,courseArea)},debounce=function(func,wait,immediate){var timeout;return function(){var context=this,args=arguments,later=function(){timeout=null,immediate||func.apply(context,args)},callNow=immediate&&!timeout;clearTimeout(timeout),timeout=setTimeout(later,wait),callNow&&func.apply(context,args)}};return{init:function(importIdString){importId=importIdString;var page=document.querySelector(Selectors.region.selectPage);registerListenerEvents(page),addCourses(page)}}}));
+
+//# sourceMappingURL=select_page.min.js.map
\ No newline at end of file
diff --git a/admin/tool/moodlenet/amd/build/select_page.min.js.map b/admin/tool/moodlenet/amd/build/select_page.min.js.map
index a170f8b0a08..bc80e534253 100644
--- a/admin/tool/moodlenet/amd/build/select_page.min.js.map
+++ b/admin/tool/moodlenet/amd/build/select_page.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/select_page.js"],"names":["define","Ajax","Templates","Selectors","Notification","importId","renderNoCourses","areaReplace","renderPix","then","img","temp","document","createElement","innerHTML","trim","render","nocoursesimg","firstChild","src","html","js","replaceNodeContents","classList","add","renderCourses","courses","remove","searchCourses","inputValue","page","searchIcon","querySelector","region","clearIcon","parentElement","call","methodname","args","searchvalue","result","length","forEach","course","viewurl","catch","exception","registerListenerEvents","input","searchInput","courseArea","addEventListener","value","debounce","addCourses","func","wait","immediate","timeout","context","arguments","callNow","clearTimeout","setTimeout","later","apply","init","importIdString","selectPage"],"mappings":"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","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 .\n\n/**\n * When returning to Moodle let the user select which course to add the resource to.\n *\n * @module tool_moodlenet/select_page\n * @copyright 2020 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine([\n 'core/ajax',\n 'core/templates',\n 'tool_moodlenet/selectors',\n 'core/notification'\n], function(\n Ajax,\n Templates,\n Selectors,\n Notification\n) {\n /**\n * @var {string} The id corresponding to the import.\n */\n var importId;\n\n /**\n * Set up the page.\n *\n * @method init\n * @param {string} importIdString the string ID of the import.\n */\n var init = function(importIdString) {\n importId = importIdString;\n var page = document.querySelector(Selectors.region.selectPage);\n registerListenerEvents(page);\n addCourses(page);\n };\n\n /**\n * Renders the 'no-courses' template.\n *\n * @param {HTMLElement} areaReplace the DOM node to replace.\n * @returns {Promise}\n */\n var renderNoCourses = function(areaReplace) {\n return Templates.renderPix('courses', 'tool_moodlenet').then(function(img) {\n return img;\n }).then(function(img) {\n var temp = document.createElement('div');\n temp.innerHTML = img.trim();\n return Templates.render('core_course/no-courses', {\n nocoursesimg: temp.firstChild.src\n });\n }).then(function(html, js) {\n Templates.replaceNodeContents(areaReplace, html, js);\n areaReplace.classList.add('mx-auto');\n areaReplace.classList.add('w-25');\n return;\n });\n };\n\n /**\n * Render the course cards for those supplied courses.\n *\n * @param {HTMLElement} areaReplace the DOM node to replace.\n * @param {Array} courses the courses to render.\n * @returns {Promise}\n */\n var renderCourses = function(areaReplace, courses) {\n return Templates.render('tool_moodlenet/view-cards', {\n courses: courses\n }).then(function(html, js) {\n Templates.replaceNodeContents(areaReplace, html, js);\n areaReplace.classList.remove('mx-auto');\n areaReplace.classList.remove('w-25');\n return;\n });\n };\n\n /**\n * For a given input, the page & what to replace fetch courses and manage icons too.\n *\n * @method searchCourses\n * @param {string} inputValue What to search for\n * @param {HTMLElement} page The whole page element for our page\n * @param {HTMLElement} areaReplace The Element to replace the contents of\n */\n var searchCourses = function(inputValue, page, areaReplace) {\n var searchIcon = page.querySelector(Selectors.region.searchIcon);\n var clearIcon = page.querySelector(Selectors.region.clearIcon);\n\n if (inputValue !== '') {\n searchIcon.classList.add('d-none');\n clearIcon.parentElement.classList.remove('d-none');\n } else {\n searchIcon.classList.remove('d-none');\n clearIcon.parentElement.classList.add('d-none');\n }\n var args = {\n searchvalue: inputValue,\n };\n Ajax.call([{\n methodname: 'tool_moodlenet_search_courses',\n args: args\n }])[0].then(function(result) {\n if (result.courses.length === 0) {\n return renderNoCourses(areaReplace);\n } else {\n // Add the importId to the course link\n result.courses.forEach(function(course) {\n course.viewurl += '&id=' + importId;\n });\n return renderCourses(areaReplace, result.courses);\n }\n }).catch(Notification.exception);\n };\n\n /**\n * Add the event listeners to our page.\n *\n * @method registerListenerEvents\n * @param {HTMLElement} page The whole page element for our page\n */\n var registerListenerEvents = function(page) {\n var input = page.querySelector(Selectors.region.searchInput);\n var courseArea = page.querySelector(Selectors.region.courses);\n var clearIcon = page.querySelector(Selectors.region.clearIcon);\n clearIcon.addEventListener('click', function() {\n input.value = '';\n searchCourses('', page, courseArea);\n });\n\n input.addEventListener('input', debounce(function() {\n searchCourses(input.value, page, courseArea);\n }, 300));\n };\n\n /**\n * Fetch the courses to show the user. We use the same WS structure & template as the search for consistency.\n *\n * @method addCourses\n * @param {HTMLElement} page The whole page element for our course page\n */\n var addCourses = function(page) {\n var courseArea = page.querySelector(Selectors.region.courses);\n searchCourses('', page, courseArea);\n };\n\n /**\n * Define our own debounce function as Moodle 3.7 does not have it.\n *\n * @method debounce\n * @from underscore.js\n * @copyright 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * @licence MIT\n * @param {function} func The function we want to keep calling\n * @param {number} wait Our timeout\n * @param {boolean} immediate Do we want to apply the function immediately\n * @return {function}\n */\n var debounce = function(func, wait, immediate) {\n var timeout;\n return function() {\n var context = this;\n var args = arguments;\n var later = function() {\n timeout = null;\n if (!immediate) {\n func.apply(context, args);\n }\n };\n var callNow = immediate && !timeout;\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n if (callNow) {\n func.apply(context, args);\n }\n };\n };\n return {\n init: init,\n };\n});\n"],"file":"select_page.min.js"}
\ No newline at end of file
+{"version":3,"file":"select_page.min.js","sources":["../src/select_page.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 .\n\n/**\n * When returning to Moodle let the user select which course to add the resource to.\n *\n * @module tool_moodlenet/select_page\n * @copyright 2020 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine([\n 'core/ajax',\n 'core/templates',\n 'tool_moodlenet/selectors',\n 'core/notification'\n], function(\n Ajax,\n Templates,\n Selectors,\n Notification\n) {\n /**\n * @var {string} The id corresponding to the import.\n */\n var importId;\n\n /**\n * Set up the page.\n *\n * @method init\n * @param {string} importIdString the string ID of the import.\n */\n var init = function(importIdString) {\n importId = importIdString;\n var page = document.querySelector(Selectors.region.selectPage);\n registerListenerEvents(page);\n addCourses(page);\n };\n\n /**\n * Renders the 'no-courses' template.\n *\n * @param {HTMLElement} areaReplace the DOM node to replace.\n * @returns {Promise}\n */\n var renderNoCourses = function(areaReplace) {\n return Templates.renderPix('courses', 'tool_moodlenet').then(function(img) {\n return img;\n }).then(function(img) {\n var temp = document.createElement('div');\n temp.innerHTML = img.trim();\n return Templates.render('core_course/no-courses', {\n nocoursesimg: temp.firstChild.src\n });\n }).then(function(html, js) {\n Templates.replaceNodeContents(areaReplace, html, js);\n areaReplace.classList.add('mx-auto');\n areaReplace.classList.add('w-25');\n return;\n });\n };\n\n /**\n * Render the course cards for those supplied courses.\n *\n * @param {HTMLElement} areaReplace the DOM node to replace.\n * @param {Array} courses the courses to render.\n * @returns {Promise}\n */\n var renderCourses = function(areaReplace, courses) {\n return Templates.render('tool_moodlenet/view-cards', {\n courses: courses\n }).then(function(html, js) {\n Templates.replaceNodeContents(areaReplace, html, js);\n areaReplace.classList.remove('mx-auto');\n areaReplace.classList.remove('w-25');\n return;\n });\n };\n\n /**\n * For a given input, the page & what to replace fetch courses and manage icons too.\n *\n * @method searchCourses\n * @param {string} inputValue What to search for\n * @param {HTMLElement} page The whole page element for our page\n * @param {HTMLElement} areaReplace The Element to replace the contents of\n */\n var searchCourses = function(inputValue, page, areaReplace) {\n var searchIcon = page.querySelector(Selectors.region.searchIcon);\n var clearIcon = page.querySelector(Selectors.region.clearIcon);\n\n if (inputValue !== '') {\n searchIcon.classList.add('d-none');\n clearIcon.parentElement.classList.remove('d-none');\n } else {\n searchIcon.classList.remove('d-none');\n clearIcon.parentElement.classList.add('d-none');\n }\n var args = {\n searchvalue: inputValue,\n };\n Ajax.call([{\n methodname: 'tool_moodlenet_search_courses',\n args: args\n }])[0].then(function(result) {\n if (result.courses.length === 0) {\n return renderNoCourses(areaReplace);\n } else {\n // Add the importId to the course link\n result.courses.forEach(function(course) {\n course.viewurl += '&id=' + importId;\n });\n return renderCourses(areaReplace, result.courses);\n }\n }).catch(Notification.exception);\n };\n\n /**\n * Add the event listeners to our page.\n *\n * @method registerListenerEvents\n * @param {HTMLElement} page The whole page element for our page\n */\n var registerListenerEvents = function(page) {\n var input = page.querySelector(Selectors.region.searchInput);\n var courseArea = page.querySelector(Selectors.region.courses);\n var clearIcon = page.querySelector(Selectors.region.clearIcon);\n clearIcon.addEventListener('click', function() {\n input.value = '';\n searchCourses('', page, courseArea);\n });\n\n input.addEventListener('input', debounce(function() {\n searchCourses(input.value, page, courseArea);\n }, 300));\n };\n\n /**\n * Fetch the courses to show the user. We use the same WS structure & template as the search for consistency.\n *\n * @method addCourses\n * @param {HTMLElement} page The whole page element for our course page\n */\n var addCourses = function(page) {\n var courseArea = page.querySelector(Selectors.region.courses);\n searchCourses('', page, courseArea);\n };\n\n /**\n * Define our own debounce function as Moodle 3.7 does not have it.\n *\n * @method debounce\n * @from underscore.js\n * @copyright 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * @licence MIT\n * @param {function} func The function we want to keep calling\n * @param {number} wait Our timeout\n * @param {boolean} immediate Do we want to apply the function immediately\n * @return {function}\n */\n var debounce = function(func, wait, immediate) {\n var timeout;\n return function() {\n var context = this;\n var args = arguments;\n var later = function() {\n timeout = null;\n if (!immediate) {\n func.apply(context, args);\n }\n };\n var callNow = immediate && !timeout;\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n if (callNow) {\n func.apply(context, args);\n }\n };\n };\n return {\n init: init,\n };\n});\n"],"names":["define","Ajax","Templates","Selectors","Notification","importId","searchCourses","inputValue","page","areaReplace","searchIcon","querySelector","region","clearIcon","classList","add","parentElement","remove","args","searchvalue","call","methodname","then","result","courses","length","renderPix","img","temp","document","createElement","innerHTML","trim","render","nocoursesimg","firstChild","src","html","js","replaceNodeContents","renderNoCourses","forEach","course","viewurl","renderCourses","catch","exception","registerListenerEvents","input","searchInput","courseArea","addEventListener","value","debounce","addCourses","func","wait","immediate","timeout","context","this","arguments","later","apply","callNow","clearTimeout","setTimeout","init","importIdString","selectPage"],"mappings":";;;;;;;AAuBAA,oCAAO,CACH,YACA,iBACA,2BACA,sBACD,SACCC,KACAC,UACAC,UACAC,kBAKIC,SAgEAC,cAAgB,SAASC,WAAYC,KAAMC,iBACvCC,WAAaF,KAAKG,cAAcR,UAAUS,OAAOF,YACjDG,UAAYL,KAAKG,cAAcR,UAAUS,OAAOC,WAEjC,KAAfN,YACAG,WAAWI,UAAUC,IAAI,UACzBF,UAAUG,cAAcF,UAAUG,OAAO,YAEzCP,WAAWI,UAAUG,OAAO,UAC5BJ,UAAUG,cAAcF,UAAUC,IAAI,eAEtCG,KAAO,CACPC,YAAaZ,YAEjBN,KAAKmB,KAAK,CAAC,CACPC,WAAY,gCACZH,KAAMA,QACN,GAAGI,MAAK,SAASC,eACa,IAA1BA,OAAOC,QAAQC,OA7DL,SAAShB,oBACpBP,UAAUwB,UAAU,UAAW,kBAAkBJ,MAAK,SAASK,YAC3DA,OACRL,MAAK,SAASK,SACTC,KAAOC,SAASC,cAAc,cAClCF,KAAKG,UAAYJ,IAAIK,OACd9B,UAAU+B,OAAO,yBAA0B,CAC9CC,aAAcN,KAAKO,WAAWC,SAEnCd,MAAK,SAASe,KAAMC,IACnBpC,UAAUqC,oBAAoB9B,YAAa4B,KAAMC,IACjD7B,YAAYK,UAAUC,IAAI,WAC1BN,YAAYK,UAAUC,IAAI,WAkDfyB,CAAgB/B,cAGvBc,OAAOC,QAAQiB,SAAQ,SAASC,QAC5BA,OAAOC,SAAW,OAAStC,YA1CvB,SAASI,YAAae,gBAC/BtB,UAAU+B,OAAO,4BAA6B,CACjDT,QAASA,UACVF,MAAK,SAASe,KAAMC,IACnBpC,UAAUqC,oBAAoB9B,YAAa4B,KAAMC,IACjD7B,YAAYK,UAAUG,OAAO,WAC7BR,YAAYK,UAAUG,OAAO,WAsClB2B,CAAcnC,YAAac,OAAOC,aAE9CqB,MAAMzC,aAAa0C,YAStBC,uBAAyB,SAASvC,UAC9BwC,MAAQxC,KAAKG,cAAcR,UAAUS,OAAOqC,aAC5CC,WAAa1C,KAAKG,cAAcR,UAAUS,OAAOY,SACrChB,KAAKG,cAAcR,UAAUS,OAAOC,WAC1CsC,iBAAiB,SAAS,WAChCH,MAAMI,MAAQ,GACd9C,cAAc,GAAIE,KAAM0C,eAG5BF,MAAMG,iBAAiB,QAASE,UAAS,WACrC/C,cAAc0C,MAAMI,MAAO5C,KAAM0C,cAClC,OASHI,WAAa,SAAS9C,UAClB0C,WAAa1C,KAAKG,cAAcR,UAAUS,OAAOY,SACrDlB,cAAc,GAAIE,KAAM0C,aAexBG,SAAW,SAASE,KAAMC,KAAMC,eAC5BC,eACG,eACCC,QAAUC,KACV1C,KAAO2C,UACPC,MAAQ,WACRJ,QAAU,KACLD,WACDF,KAAKQ,MAAMJ,QAASzC,OAGxB8C,QAAUP,YAAcC,QAC5BO,aAAaP,SACbA,QAAUQ,WAAWJ,MAAON,MACxBQ,SACAT,KAAKQ,MAAMJ,QAASzC,cAIzB,CACHiD,KArJO,SAASC,gBAChB/D,SAAW+D,mBACP5D,KAAOqB,SAASlB,cAAcR,UAAUS,OAAOyD,YACnDtB,uBAAuBvC,MACvB8C,WAAW9C"}
\ No newline at end of file
diff --git a/admin/tool/moodlenet/amd/build/selectors.min.js b/admin/tool/moodlenet/amd/build/selectors.min.js
index b1db64f13e2..75de02c08db 100644
--- a/admin/tool/moodlenet/amd/build/selectors.min.js
+++ b/admin/tool/moodlenet/amd/build/selectors.min.js
@@ -1,2 +1,10 @@
-define ("tool_moodlenet/selectors",[],function(){return{action:{browse:"[data-action=\"browse\"]",submit:"[data-action=\"submit\"]",showMoodleNet:"[data-action=\"show-moodlenet\"]",closeOption:"[data-action=\"close-chooser-option-summary\"]"},region:{clearIcon:"[data-region=\"clear-icon\"]",courses:"[data-region=\"mnet-courses\"]",instancePage:"[data-region=\"moodle-net\"]",searchInput:"[data-region=\"search-input\"]",searchIcon:"[data-region=\"search-icon\"]",selectPage:"[data-region=\"moodle-net-select\"]",spinner:"[data-region=\"spinner\"]",validationArea:"[data-region=\"validation-area\"]",carousel:"[data-region=\"carousel\"]",moodleNet:"[data-region=\"pluginCarousel\"]"}}});
-//# sourceMappingURL=selectors.min.js.map
+/**
+ * Define all of the selectors we will be using within MoodleNet plugin.
+ *
+ * @module tool_moodlenet/selectors
+ * @copyright 2020 Mathew May
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_moodlenet/selectors",[],(function(){return{action:{browse:'[data-action="browse"]',submit:'[data-action="submit"]',showMoodleNet:'[data-action="show-moodlenet"]',closeOption:'[data-action="close-chooser-option-summary"]'},region:{clearIcon:'[data-region="clear-icon"]',courses:'[data-region="mnet-courses"]',instancePage:'[data-region="moodle-net"]',searchInput:'[data-region="search-input"]',searchIcon:'[data-region="search-icon"]',selectPage:'[data-region="moodle-net-select"]',spinner:'[data-region="spinner"]',validationArea:'[data-region="validation-area"]',carousel:'[data-region="carousel"]',moodleNet:'[data-region="pluginCarousel"]'}}}));
+
+//# sourceMappingURL=selectors.min.js.map
\ No newline at end of file
diff --git a/admin/tool/moodlenet/amd/build/selectors.min.js.map b/admin/tool/moodlenet/amd/build/selectors.min.js.map
index 045ac3b471f..4adbf8d872f 100644
--- a/admin/tool/moodlenet/amd/build/selectors.min.js.map
+++ b/admin/tool/moodlenet/amd/build/selectors.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/selectors.js"],"names":["define","action","browse","submit","showMoodleNet","closeOption","region","clearIcon","courses","instancePage","searchInput","searchIcon","selectPage","spinner","validationArea","carousel","moodleNet"],"mappings":"AAsBAA,OAAM,4BAAC,EAAD,CAAK,UAAW,CAClB,MAAO,CACHC,MAAM,CAAE,CACJC,MAAM,CAAE,0BADJ,CAEJC,MAAM,CAAE,0BAFJ,CAGJC,aAAa,CAAE,kCAHX,CAIJC,WAAW,CAAE,gDAJT,CADL,CAOHC,MAAM,CAAE,CACJC,SAAS,CAAE,8BADP,CAEJC,OAAO,CAAE,gCAFL,CAGJC,YAAY,CAAE,8BAHV,CAIJC,WAAW,CAAE,gCAJT,CAKJC,UAAU,CAAE,+BALR,CAMJC,UAAU,CAAE,qCANR,CAOJC,OAAO,CAAE,2BAPL,CAQJC,cAAc,CAAE,mCARZ,CASJC,QAAQ,CAAE,4BATN,CAUJC,SAAS,CAAE,kCAVP,CAPL,CAoBV,CArBK,CAAN","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 .\n\n/**\n * Define all of the selectors we will be using within MoodleNet plugin.\n *\n * @module tool_moodlenet/selectors\n * @copyright 2020 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n action: {\n browse: '[data-action=\"browse\"]',\n submit: '[data-action=\"submit\"]',\n showMoodleNet: '[data-action=\"show-moodlenet\"]',\n closeOption: '[data-action=\"close-chooser-option-summary\"]',\n },\n region: {\n clearIcon: '[data-region=\"clear-icon\"]',\n courses: '[data-region=\"mnet-courses\"]',\n instancePage: '[data-region=\"moodle-net\"]',\n searchInput: '[data-region=\"search-input\"]',\n searchIcon: '[data-region=\"search-icon\"]',\n selectPage: '[data-region=\"moodle-net-select\"]',\n spinner: '[data-region=\"spinner\"]',\n validationArea: '[data-region=\"validation-area\"]',\n carousel: '[data-region=\"carousel\"]',\n moodleNet: '[data-region=\"pluginCarousel\"]',\n },\n };\n});\n"],"file":"selectors.min.js"}
\ No newline at end of file
+{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 .\n\n/**\n * Define all of the selectors we will be using within MoodleNet plugin.\n *\n * @module tool_moodlenet/selectors\n * @copyright 2020 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n action: {\n browse: '[data-action=\"browse\"]',\n submit: '[data-action=\"submit\"]',\n showMoodleNet: '[data-action=\"show-moodlenet\"]',\n closeOption: '[data-action=\"close-chooser-option-summary\"]',\n },\n region: {\n clearIcon: '[data-region=\"clear-icon\"]',\n courses: '[data-region=\"mnet-courses\"]',\n instancePage: '[data-region=\"moodle-net\"]',\n searchInput: '[data-region=\"search-input\"]',\n searchIcon: '[data-region=\"search-icon\"]',\n selectPage: '[data-region=\"moodle-net-select\"]',\n spinner: '[data-region=\"spinner\"]',\n validationArea: '[data-region=\"validation-area\"]',\n carousel: '[data-region=\"carousel\"]',\n moodleNet: '[data-region=\"pluginCarousel\"]',\n },\n };\n});\n"],"names":["define","action","browse","submit","showMoodleNet","closeOption","region","clearIcon","courses","instancePage","searchInput","searchIcon","selectPage","spinner","validationArea","carousel","moodleNet"],"mappings":";;;;;;;AAsBAA,kCAAO,IAAI,iBACA,CACHC,OAAQ,CACJC,OAAQ,yBACRC,OAAQ,yBACRC,cAAe,iCACfC,YAAa,gDAEjBC,OAAQ,CACJC,UAAW,6BACXC,QAAS,+BACTC,aAAc,6BACdC,YAAa,+BACbC,WAAY,8BACZC,WAAY,oCACZC,QAAS,0BACTC,eAAgB,kCAChBC,SAAU,2BACVC,UAAW"}
\ No newline at end of file
diff --git a/admin/tool/moodlenet/amd/build/validator.min.js b/admin/tool/moodlenet/amd/build/validator.min.js
index 1c4d02ae503..7cf1287e5cc 100644
--- a/admin/tool/moodlenet/amd/build/validator.min.js
+++ b/admin/tool/moodlenet/amd/build/validator.min.js
@@ -1,2 +1,10 @@
-define ("tool_moodlenet/validator",["jquery","core/ajax","core/str","core/notification"],function(a,b,c,d){return{validation:function(e){var f=e.value;if(""===f||!f.includes("@")){a.when(c.get_string("profilevalidationerror","tool_moodlenet")).then(function(a){return Promise.reject().catch(function(){return{result:!1,message:a[0]}})}).fail(d.exception)}return b.call([{methodname:"tool_moodlenet_verify_webfinger",args:{profileurl:f,course:e.dataset.courseid,section:e.dataset.sectionid}}])[0].then(function(a){return a}).catch()}}});
-//# sourceMappingURL=validator.min.js.map
+/**
+ * Our validator that splits the user's input then fires off to a webservice
+ *
+ * @module tool_moodlenet/validator
+ * @copyright 2020 Mathew May
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_moodlenet/validator",["jquery","core/ajax","core/str","core/notification"],(function($,Ajax,Str,Notification){return{validation:function(inputElement){var inputValue=inputElement.value;return""!==inputValue&&inputValue.includes("@")||$.when(Str.get_string("profilevalidationerror","tool_moodlenet")).then((function(strings){return Promise.reject().catch((function(){return{result:!1,message:strings[0]}}))})).fail(Notification.exception),Ajax.call([{methodname:"tool_moodlenet_verify_webfinger",args:{profileurl:inputValue,course:inputElement.dataset.courseid,section:inputElement.dataset.sectionid}}])[0].then((function(result){return result})).catch()}}}));
+
+//# sourceMappingURL=validator.min.js.map
\ No newline at end of file
diff --git a/admin/tool/moodlenet/amd/build/validator.min.js.map b/admin/tool/moodlenet/amd/build/validator.min.js.map
index e0ccd035c88..7d0a9ae7781 100644
--- a/admin/tool/moodlenet/amd/build/validator.min.js.map
+++ b/admin/tool/moodlenet/amd/build/validator.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/validator.js"],"names":["define","$","Ajax","Str","Notification","validation","inputElement","inputValue","value","includes","when","get_string","then","strings","Promise","reject","catch","result","message","fail","exception","call","methodname","args","profileurl","course","dataset","courseid","section","sectionid"],"mappings":"AAsBAA,OAAM,4BAAC,CAAC,QAAD,CAAW,WAAX,CAAwB,UAAxB,CAAoC,mBAApC,CAAD,CAA2D,SAASC,CAAT,CAAYC,CAAZ,CAAkBC,CAAlB,CAAuBC,CAAvB,CAAqC,CAgClG,MAAO,CACHC,UAAU,CAzBG,SAAoBC,CAApB,CAAkC,CAC/C,GAAIC,CAAAA,CAAU,CAAGD,CAAY,CAACE,KAA9B,CAGA,GAAmB,EAAf,GAAAD,CAAU,EAAW,CAACA,CAAU,CAACE,QAAX,CAAoB,GAApB,CAA1B,CAAoD,CAEhDR,CAAC,CAACS,IAAF,CAAOP,CAAG,CAACQ,UAAJ,CAAe,wBAAf,CAAyC,gBAAzC,CAAP,EAAmEC,IAAnE,CAAwE,SAASC,CAAT,CAAkB,CACtF,MAAOC,CAAAA,OAAO,CAACC,MAAR,GAAiBC,KAAjB,CAAuB,UAAW,CACrC,MAAO,CAACC,MAAM,GAAP,CAAgBC,OAAO,CAAEL,CAAO,CAAC,CAAD,CAAhC,CACV,CAFM,CAGV,CAJD,EAIGM,IAJH,CAIQf,CAAY,CAACgB,SAJrB,CAKH,CAED,MAAOlB,CAAAA,CAAI,CAACmB,IAAL,CAAU,CAAC,CACdC,UAAU,CAAE,iCADE,CAEdC,IAAI,CAAE,CACFC,UAAU,CAAEjB,CADV,CAEFkB,MAAM,CAAEnB,CAAY,CAACoB,OAAb,CAAqBC,QAF3B,CAGFC,OAAO,CAAEtB,CAAY,CAACoB,OAAb,CAAqBG,SAH5B,CAFQ,CAAD,CAAV,EAOH,CAPG,EAOAjB,IAPA,CAOK,SAASK,CAAT,CAAiB,CACzB,MAAOA,CAAAA,CACV,CATM,EASJD,KATI,EAUV,CACM,CAGV,CAnCK,CAAN","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 .\n\n/**\n * Our validator that splits the user's input then fires off to a webservice\n *\n * @module tool_moodlenet/validator\n * @copyright 2020 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/str', 'core/notification'], function($, Ajax, Str, Notification) {\n /**\n * Handle form validation\n *\n * @method validation\n * @param {HTMLElement} inputElement The element the user entered text into.\n * @return {Promise} Was the users' entry a valid profile URL?\n */\n var validation = function validation(inputElement) {\n var inputValue = inputElement.value;\n\n // They didn't submit anything or they gave us a simple string that we can't do anything with.\n if (inputValue === \"\" || !inputValue.includes(\"@\")) {\n // Create a promise and immediately reject it.\n $.when(Str.get_string('profilevalidationerror', 'tool_moodlenet')).then(function(strings) {\n return Promise.reject().catch(function() {\n return {result: false, message: strings[0]};\n });\n }).fail(Notification.exception);\n }\n\n return Ajax.call([{\n methodname: 'tool_moodlenet_verify_webfinger',\n args: {\n profileurl: inputValue,\n course: inputElement.dataset.courseid,\n section: inputElement.dataset.sectionid\n }\n }])[0].then(function(result) {\n return result;\n }).catch();\n };\n return {\n validation: validation,\n };\n});\n"],"file":"validator.min.js"}
\ No newline at end of file
+{"version":3,"file":"validator.min.js","sources":["../src/validator.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 .\n\n/**\n * Our validator that splits the user's input then fires off to a webservice\n *\n * @module tool_moodlenet/validator\n * @copyright 2020 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/str', 'core/notification'], function($, Ajax, Str, Notification) {\n /**\n * Handle form validation\n *\n * @method validation\n * @param {HTMLElement} inputElement The element the user entered text into.\n * @return {Promise} Was the users' entry a valid profile URL?\n */\n var validation = function validation(inputElement) {\n var inputValue = inputElement.value;\n\n // They didn't submit anything or they gave us a simple string that we can't do anything with.\n if (inputValue === \"\" || !inputValue.includes(\"@\")) {\n // Create a promise and immediately reject it.\n $.when(Str.get_string('profilevalidationerror', 'tool_moodlenet')).then(function(strings) {\n return Promise.reject().catch(function() {\n return {result: false, message: strings[0]};\n });\n }).fail(Notification.exception);\n }\n\n return Ajax.call([{\n methodname: 'tool_moodlenet_verify_webfinger',\n args: {\n profileurl: inputValue,\n course: inputElement.dataset.courseid,\n section: inputElement.dataset.sectionid\n }\n }])[0].then(function(result) {\n return result;\n }).catch();\n };\n return {\n validation: validation,\n };\n});\n"],"names":["define","$","Ajax","Str","Notification","validation","inputElement","inputValue","value","includes","when","get_string","then","strings","Promise","reject","catch","result","message","fail","exception","call","methodname","args","profileurl","course","dataset","courseid","section","sectionid"],"mappings":";;;;;;;AAsBAA,kCAAO,CAAC,SAAU,YAAa,WAAY,sBAAsB,SAASC,EAAGC,KAAMC,IAAKC,oBAgC7E,CACHC,WAzBa,SAAoBC,kBAC7BC,WAAaD,aAAaE,YAGX,KAAfD,YAAsBA,WAAWE,SAAS,MAE1CR,EAAES,KAAKP,IAAIQ,WAAW,yBAA0B,mBAAmBC,MAAK,SAASC,gBACtEC,QAAQC,SAASC,OAAM,iBACnB,CAACC,QAAQ,EAAOC,QAASL,QAAQ,UAE7CM,KAAKf,aAAagB,WAGlBlB,KAAKmB,KAAK,CAAC,CACdC,WAAY,kCACZC,KAAM,CACFC,WAAYjB,WACZkB,OAAQnB,aAAaoB,QAAQC,SAC7BC,QAAStB,aAAaoB,QAAQG,cAElC,GAAGjB,MAAK,SAASK,eACVA,UACRD"}
\ No newline at end of file
diff --git a/admin/tool/policy/amd/build/acceptances_filter.min.js b/admin/tool/policy/amd/build/acceptances_filter.min.js
index 0cb2282aecf..9bd16c757bc 100644
--- a/admin/tool/policy/amd/build/acceptances_filter.min.js
+++ b/admin/tool/policy/amd/build/acceptances_filter.min.js
@@ -1,2 +1,10 @@
-define ("tool_policy/acceptances_filter",["jquery","core/form-autocomplete","core/str","core/notification"],function(a,b,c,d){var e={UNIFIED_FILTERS:"#unified-filters"},f=function init(){M.util.js_pending("acceptances_filter_datasource");c.get_strings([{key:"filterplaceholder",component:"tool_policy"},{key:"nofiltersapplied",component:"tool_policy"}]).done(function(a){var c=a[0],f=a[1];b.enhance(e.UNIFIED_FILTERS,!0,"tool_policy/acceptances_filter_datasource",c,!1,!0,f,!0).then(function(){M.util.js_complete("acceptances_filter_datasource")}).fail(d.exception)}).fail(d.exception);var f=a(e.UNIFIED_FILTERS).val();a(e.UNIFIED_FILTERS).on("change",function(){var b=a(this).val(),c=[],d=[],e=!1;a.each(b,function(a,b){var f=b.split(":",2);if(2!==f.length){d.push(b);return!0}var g=f[0],h=f[1];if("undefined"!=typeof c[g]){e=!0}c[g]=h;return!0});if(e){var g=[];for(var h in c){g.push(h+":"+c[h])}g=g.concat(d);a(this).val(g)}if(f.join(",")!=b.join(",")){this.form.submit()}})},g=function getForm(){return a(e.UNIFIED_FILTERS).closest("form")};return{init:function init(){f()},getForm:function getForm(){return g()}}});
-//# sourceMappingURL=acceptances_filter.min.js.map
+/**
+ * Unified filter page JS module for the course participants page.
+ *
+ * @module tool_policy/acceptances_filter
+ * @copyright 2017 Jun Pataleta
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_policy/acceptances_filter",["jquery","core/form-autocomplete","core/str","core/notification"],(function($,Autocomplete,Str,Notification){var SELECTORS_UNIFIED_FILTERS="#unified-filters";return{init:function(){!function(){M.util.js_pending("acceptances_filter_datasource"),Str.get_strings([{key:"filterplaceholder",component:"tool_policy"},{key:"nofiltersapplied",component:"tool_policy"}]).done((function(langstrings){var placeholder=langstrings[0],noSelectionString=langstrings[1];Autocomplete.enhance(SELECTORS_UNIFIED_FILTERS,!0,"tool_policy/acceptances_filter_datasource",placeholder,!1,!0,noSelectionString,!0).then((function(){M.util.js_complete("acceptances_filter_datasource")})).fail(Notification.exception)})).fail(Notification.exception);var last=$(SELECTORS_UNIFIED_FILTERS).val();$(SELECTORS_UNIFIED_FILTERS).on("change",(function(){var current=$(this).val(),listoffilters=[],textfilters=[],updatedselectedfilters=!1;if($.each(current,(function(index,catoption){var catandoption=catoption.split(":",2);if(2!==catandoption.length)return textfilters.push(catoption),!0;var category=catandoption[0],option=catandoption[1];return void 0!==listoffilters[category]&&(updatedselectedfilters=!0),listoffilters[category]=option,!0})),updatedselectedfilters){var updatefilters=[];for(var category in listoffilters)updatefilters.push(category+":"+listoffilters[category]);updatefilters=updatefilters.concat(textfilters),$(this).val(updatefilters)}last.join(",")!=current.join(",")&&this.form.submit()}))}()},getForm:function(){return $(SELECTORS_UNIFIED_FILTERS).closest("form")}}}));
+
+//# sourceMappingURL=acceptances_filter.min.js.map
\ No newline at end of file
diff --git a/admin/tool/policy/amd/build/acceptances_filter.min.js.map b/admin/tool/policy/amd/build/acceptances_filter.min.js.map
index 9d3a54d842f..360aa9aa9b6 100644
--- a/admin/tool/policy/amd/build/acceptances_filter.min.js.map
+++ b/admin/tool/policy/amd/build/acceptances_filter.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/acceptances_filter.js"],"names":["define","$","Autocomplete","Str","Notification","SELECTORS","UNIFIED_FILTERS","init","M","util","js_pending","get_strings","key","component","done","langstrings","placeholder","noSelectionString","enhance","then","js_complete","fail","exception","last","val","on","current","listoffilters","textfilters","updatedselectedfilters","each","index","catoption","catandoption","split","length","push","category","option","updatefilters","concat","join","form","submit","getForm","closest"],"mappings":"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","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 .\n\n/**\n * Unified filter page JS module for the course participants page.\n *\n * @module tool_policy/acceptances_filter\n * @copyright 2017 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/form-autocomplete', 'core/str', 'core/notification'],\n function($, Autocomplete, Str, Notification) {\n\n /**\n * Selectors.\n *\n * @access private\n * @type {{UNIFIED_FILTERS: string}}\n */\n var SELECTORS = {\n UNIFIED_FILTERS: '#unified-filters'\n };\n\n /**\n * Init function.\n *\n * @method init\n * @private\n */\n var init = function() {\n var stringkeys = [{\n key: 'filterplaceholder',\n component: 'tool_policy'\n }, {\n key: 'nofiltersapplied',\n component: 'tool_policy'\n }];\n\n M.util.js_pending('acceptances_filter_datasource');\n Str.get_strings(stringkeys).done(function(langstrings) {\n var placeholder = langstrings[0];\n var noSelectionString = langstrings[1];\n Autocomplete.enhance(SELECTORS.UNIFIED_FILTERS, true, 'tool_policy/acceptances_filter_datasource', placeholder,\n false, true, noSelectionString, true)\n .then(function() {\n M.util.js_complete('acceptances_filter_datasource');\n\n return;\n })\n .fail(Notification.exception);\n }).fail(Notification.exception);\n\n var last = $(SELECTORS.UNIFIED_FILTERS).val();\n $(SELECTORS.UNIFIED_FILTERS).on('change', function() {\n var current = $(this).val();\n var listoffilters = [];\n var textfilters = [];\n var updatedselectedfilters = false;\n\n $.each(current, function(index, catoption) {\n var catandoption = catoption.split(':', 2);\n if (catandoption.length !== 2) {\n textfilters.push(catoption);\n return true; // Text search filter.\n }\n\n var category = catandoption[0];\n var option = catandoption[1];\n\n // The last option (eg. 'Teacher') out of a category (eg. 'Role') in this loop is the one that was last\n // selected, so we want to use that if there are multiple options from the same category. Eg. The user\n // may have chosen to filter by the 'Student' role, then wanted to filter by the 'Teacher' role - the\n // last option in the category to be selected (in this case 'Teacher') will come last, so will overwrite\n // 'Student' (after this if). We want to let the JS know that the filters have been updated.\n if (typeof listoffilters[category] !== 'undefined') {\n updatedselectedfilters = true;\n }\n\n listoffilters[category] = option;\n return true;\n });\n\n // Check if we have something to remove from the list of filters.\n if (updatedselectedfilters) {\n // Go through and put the list into something we can use to update the list of filters.\n var updatefilters = [];\n for (var category in listoffilters) {\n updatefilters.push(category + \":\" + listoffilters[category]);\n }\n updatefilters = updatefilters.concat(textfilters);\n $(this).val(updatefilters);\n }\n\n // Prevent form from submitting unnecessarily, eg. on blur when no filter is selected.\n if (last.join(',') != current.join(',')) {\n this.form.submit();\n }\n });\n };\n\n /**\n * Return the unified user filter form.\n *\n * @method getForm\n * @return {DOMElement}\n */\n var getForm = function() {\n return $(SELECTORS.UNIFIED_FILTERS).closest('form');\n };\n\n return /** @alias module:core/form-autocomplete */ {\n /**\n * Initialise the unified user filter.\n *\n * @method init\n */\n init: function() {\n init();\n },\n\n /**\n * Return the unified user filter form.\n *\n * @method getForm\n * @return {DOMElement}\n */\n getForm: function() {\n return getForm();\n }\n };\n });\n"],"file":"acceptances_filter.min.js"}
\ No newline at end of file
+{"version":3,"file":"acceptances_filter.min.js","sources":["../src/acceptances_filter.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 .\n\n/**\n * Unified filter page JS module for the course participants page.\n *\n * @module tool_policy/acceptances_filter\n * @copyright 2017 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/form-autocomplete', 'core/str', 'core/notification'],\n function($, Autocomplete, Str, Notification) {\n\n /**\n * Selectors.\n *\n * @access private\n * @type {{UNIFIED_FILTERS: string}}\n */\n var SELECTORS = {\n UNIFIED_FILTERS: '#unified-filters'\n };\n\n /**\n * Init function.\n *\n * @method init\n * @private\n */\n var init = function() {\n var stringkeys = [{\n key: 'filterplaceholder',\n component: 'tool_policy'\n }, {\n key: 'nofiltersapplied',\n component: 'tool_policy'\n }];\n\n M.util.js_pending('acceptances_filter_datasource');\n Str.get_strings(stringkeys).done(function(langstrings) {\n var placeholder = langstrings[0];\n var noSelectionString = langstrings[1];\n Autocomplete.enhance(SELECTORS.UNIFIED_FILTERS, true, 'tool_policy/acceptances_filter_datasource', placeholder,\n false, true, noSelectionString, true)\n .then(function() {\n M.util.js_complete('acceptances_filter_datasource');\n\n return;\n })\n .fail(Notification.exception);\n }).fail(Notification.exception);\n\n var last = $(SELECTORS.UNIFIED_FILTERS).val();\n $(SELECTORS.UNIFIED_FILTERS).on('change', function() {\n var current = $(this).val();\n var listoffilters = [];\n var textfilters = [];\n var updatedselectedfilters = false;\n\n $.each(current, function(index, catoption) {\n var catandoption = catoption.split(':', 2);\n if (catandoption.length !== 2) {\n textfilters.push(catoption);\n return true; // Text search filter.\n }\n\n var category = catandoption[0];\n var option = catandoption[1];\n\n // The last option (eg. 'Teacher') out of a category (eg. 'Role') in this loop is the one that was last\n // selected, so we want to use that if there are multiple options from the same category. Eg. The user\n // may have chosen to filter by the 'Student' role, then wanted to filter by the 'Teacher' role - the\n // last option in the category to be selected (in this case 'Teacher') will come last, so will overwrite\n // 'Student' (after this if). We want to let the JS know that the filters have been updated.\n if (typeof listoffilters[category] !== 'undefined') {\n updatedselectedfilters = true;\n }\n\n listoffilters[category] = option;\n return true;\n });\n\n // Check if we have something to remove from the list of filters.\n if (updatedselectedfilters) {\n // Go through and put the list into something we can use to update the list of filters.\n var updatefilters = [];\n for (var category in listoffilters) {\n updatefilters.push(category + \":\" + listoffilters[category]);\n }\n updatefilters = updatefilters.concat(textfilters);\n $(this).val(updatefilters);\n }\n\n // Prevent form from submitting unnecessarily, eg. on blur when no filter is selected.\n if (last.join(',') != current.join(',')) {\n this.form.submit();\n }\n });\n };\n\n /**\n * Return the unified user filter form.\n *\n * @method getForm\n * @return {DOMElement}\n */\n var getForm = function() {\n return $(SELECTORS.UNIFIED_FILTERS).closest('form');\n };\n\n return /** @alias module:core/form-autocomplete */ {\n /**\n * Initialise the unified user filter.\n *\n * @method init\n */\n init: function() {\n init();\n },\n\n /**\n * Return the unified user filter form.\n *\n * @method getForm\n * @return {DOMElement}\n */\n getForm: function() {\n return getForm();\n }\n };\n });\n"],"names":["define","$","Autocomplete","Str","Notification","SELECTORS","init","M","util","js_pending","get_strings","key","component","done","langstrings","placeholder","noSelectionString","enhance","then","js_complete","fail","exception","last","val","on","current","this","listoffilters","textfilters","updatedselectedfilters","each","index","catoption","catandoption","split","length","push","category","option","updatefilters","concat","join","form","submit","getForm","closest"],"mappings":";;;;;;;AAsBAA,wCAAO,CAAC,SAAU,yBAA0B,WAAY,sBACpD,SAASC,EAAGC,aAAcC,IAAKC,kBAQvBC,0BACiB,yBA0F8B,CAM/CC,KAAM,YAvFC,WASPC,EAAEC,KAAKC,WAAW,iCAClBN,IAAIO,YATa,CAAC,CACdC,IAAK,oBACLC,UAAW,eACZ,CACCD,IAAK,mBACLC,UAAW,iBAIaC,MAAK,SAASC,iBAClCC,YAAcD,YAAY,GAC1BE,kBAAoBF,YAAY,GACpCZ,aAAae,QAAQZ,2BAA2B,EAAM,4CAA6CU,aAC/F,GAAO,EAAMC,mBAAmB,GAC/BE,MAAK,WACFX,EAAEC,KAAKW,YAAY,oCAItBC,KAAKhB,aAAaiB,cACxBD,KAAKhB,aAAaiB,eAEjBC,KAAOrB,EAAEI,2BAA2BkB,MACxCtB,EAAEI,2BAA2BmB,GAAG,UAAU,eAClCC,QAAUxB,EAAEyB,MAAMH,MAClBI,cAAgB,GAChBC,YAAc,GACdC,wBAAyB,KAE7B5B,EAAE6B,KAAKL,SAAS,SAASM,MAAOC,eACxBC,aAAeD,UAAUE,MAAM,IAAK,MACZ,IAAxBD,aAAaE,cACbP,YAAYQ,KAAKJ,YACV,MAGPK,SAAWJ,aAAa,GACxBK,OAASL,aAAa,eAOa,IAA5BN,cAAcU,YACrBR,wBAAyB,GAG7BF,cAAcU,UAAYC,QACnB,KAIPT,uBAAwB,KAEpBU,cAAgB,OACf,IAAIF,YAAYV,cACjBY,cAAcH,KAAKC,SAAW,IAAMV,cAAcU,WAEtDE,cAAgBA,cAAcC,OAAOZ,aACrC3B,EAAEyB,MAAMH,IAAIgB,eAIZjB,KAAKmB,KAAK,MAAQhB,QAAQgB,KAAK,WAC1BC,KAAKC,YAsBdrC,IASJsC,QAAS,kBAnBF3C,EAAEI,2BAA2BwC,QAAQ"}
\ No newline at end of file
diff --git a/admin/tool/policy/amd/build/acceptances_filter_datasource.min.js b/admin/tool/policy/amd/build/acceptances_filter_datasource.min.js
index 0a642f0c6b4..b76e74e00b1 100644
--- a/admin/tool/policy/amd/build/acceptances_filter_datasource.min.js
+++ b/admin/tool/policy/amd/build/acceptances_filter_datasource.min.js
@@ -1,2 +1,11 @@
-define ("tool_policy/acceptances_filter_datasource",["jquery","core/ajax","core/notification"],function(a,b,c){return{list:function list(b,c){var d=[],e=a(b),f=a(b).data("originaloptionsjson"),g=e.val();a.each(f,function(b,e){if(""!==c.trim()&&-1===e.label.toLocaleLowerCase().indexOf(c.toLocaleLowerCase())){return!0}if(-1-1||filteredOptions.push(option),!0}));var deferred=new $.Deferred;return deferred.resolve(filteredOptions),deferred.promise()},processResults:function(selector,results){var options=[];return $.each(results,(function(index,data){options.push({value:data.value,label:data.label})})),options},transport:function(selector,query,callback){this.list(selector,query).then(callback).catch(Notification.exception)}}}));
+
+//# sourceMappingURL=acceptances_filter_datasource.min.js.map
\ No newline at end of file
diff --git a/admin/tool/policy/amd/build/acceptances_filter_datasource.min.js.map b/admin/tool/policy/amd/build/acceptances_filter_datasource.min.js.map
index 3132f75f920..2d37ce4cd38 100644
--- a/admin/tool/policy/amd/build/acceptances_filter_datasource.min.js.map
+++ b/admin/tool/policy/amd/build/acceptances_filter_datasource.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/acceptances_filter_datasource.js"],"names":["define","$","Ajax","Notification","list","selector","query","filteredOptions","el","originalOptions","data","selectedFilters","val","each","index","option","trim","label","toLocaleLowerCase","indexOf","inArray","value","push","deferred","Deferred","resolve","promise","processResults","results","options","transport","callback","then","catch","exception"],"mappings":"AAwBAA,OAAM,6CAAC,CAAC,QAAD,CAAW,WAAX,CAAwB,mBAAxB,CAAD,CAA+C,SAASC,CAAT,CAAYC,CAAZ,CAAkBC,CAAlB,CAAgC,CAEjF,MAAsE,CAQlEC,IAAI,CAAE,cAASC,CAAT,CAAmBC,CAAnB,CAA0B,IACxBC,CAAAA,CAAe,CAAG,EADM,CAGxBC,CAAE,CAAGP,CAAC,CAACI,CAAD,CAHkB,CAIxBI,CAAe,CAAGR,CAAC,CAACI,CAAD,CAAD,CAAYK,IAAZ,CAAiB,qBAAjB,CAJM,CAKxBC,CAAe,CAAGH,CAAE,CAACI,GAAH,EALM,CAM5BX,CAAC,CAACY,IAAF,CAAOJ,CAAP,CAAwB,SAASK,CAAT,CAAgBC,CAAhB,CAAwB,CAE5C,GAAqB,EAAjB,GAAAT,CAAK,CAACU,IAAN,IAA+F,CAAC,CAAzE,GAAAD,CAAM,CAACE,KAAP,CAAaC,iBAAb,GAAiCC,OAAjC,CAAyCb,CAAK,CAACY,iBAAN,EAAzC,CAA3B,CAAuG,CACnG,QACH,CAED,GAA+C,CAAC,CAA5C,CAAAjB,CAAC,CAACmB,OAAF,CAAUL,CAAM,CAACM,KAAjB,CAAwBV,CAAxB,CAAJ,CAAmD,CAC/C,QACH,CAEDJ,CAAe,CAACe,IAAhB,CAAqBP,CAArB,EACA,QACH,CAZD,EAcA,GAAIQ,CAAAA,CAAQ,CAAG,GAAItB,CAAAA,CAAC,CAACuB,QAArB,CACAD,CAAQ,CAACE,OAAT,CAAiBlB,CAAjB,EAEA,MAAOgB,CAAAA,CAAQ,CAACG,OAAT,EACV,CAhCiE,CAyClEC,cAAc,CAAE,wBAAStB,CAAT,CAAmBuB,CAAnB,CAA4B,CACxC,GAAIC,CAAAA,CAAO,CAAG,EAAd,CACA5B,CAAC,CAACY,IAAF,CAAOe,CAAP,CAAgB,SAASd,CAAT,CAAgBJ,CAAhB,CAAsB,CAClCmB,CAAO,CAACP,IAAR,CAAa,CACTD,KAAK,CAAEX,CAAI,CAACW,KADH,CAETJ,KAAK,CAAEP,CAAI,CAACO,KAFH,CAAb,CAIH,CALD,EAMA,MAAOY,CAAAA,CACV,CAlDiE,CA4DlEC,SAAS,CAAE,mBAASzB,CAAT,CAAmBC,CAAnB,CAA0ByB,CAA1B,CAAoC,CAC3C,KAAK3B,IAAL,CAAUC,CAAV,CAAoBC,CAApB,EAA2B0B,IAA3B,CAAgCD,CAAhC,EAA0CE,KAA1C,CAAgD9B,CAAY,CAAC+B,SAA7D,CACH,CA9DiE,CAiEzE,CAnEK,CAAN","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 .\n\n/**\n * Datasource for the tool_policy/acceptances_filter.\n *\n * This module is compatible with core/form-autocomplete.\n *\n * @copyright 2017 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notification) {\n\n return /** @alias module:tool_policy/acceptances_filter_datasource */ {\n /**\n * List filter options.\n *\n * @param {String} selector The select element selector.\n * @param {String} query The query string.\n * @return {Promise}\n */\n list: function(selector, query) {\n var filteredOptions = [];\n\n var el = $(selector);\n var originalOptions = $(selector).data('originaloptionsjson');\n var selectedFilters = el.val();\n $.each(originalOptions, function(index, option) {\n // Skip option if it does not contain the query string.\n if (query.trim() !== '' && option.label.toLocaleLowerCase().indexOf(query.toLocaleLowerCase()) === -1) {\n return true;\n }\n // Skip filters that have already been selected.\n if ($.inArray(option.value, selectedFilters) > -1) {\n return true;\n }\n\n filteredOptions.push(option);\n return true;\n });\n\n var deferred = new $.Deferred();\n deferred.resolve(filteredOptions);\n\n return deferred.promise();\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.\n * @return {Array} New array of results.\n */\n processResults: function(selector, results) {\n var options = [];\n $.each(results, function(index, data) {\n options.push({\n value: data.value,\n label: data.label\n });\n });\n return options;\n },\n\n /**\n * Source of data for Ajax element.\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 */\n /* eslint-disable promise/no-callback-in-promise */\n transport: function(selector, query, callback) {\n this.list(selector, query).then(callback).catch(Notification.exception);\n }\n };\n\n});\n"],"file":"acceptances_filter_datasource.min.js"}
\ No newline at end of file
+{"version":3,"file":"acceptances_filter_datasource.min.js","sources":["../src/acceptances_filter_datasource.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 .\n\n/**\n * Datasource for the tool_policy/acceptances_filter.\n *\n * This module is compatible with core/form-autocomplete.\n *\n * @copyright 2017 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notification) {\n\n return /** @alias module:tool_policy/acceptances_filter_datasource */ {\n /**\n * List filter options.\n *\n * @param {String} selector The select element selector.\n * @param {String} query The query string.\n * @return {Promise}\n */\n list: function(selector, query) {\n var filteredOptions = [];\n\n var el = $(selector);\n var originalOptions = $(selector).data('originaloptionsjson');\n var selectedFilters = el.val();\n $.each(originalOptions, function(index, option) {\n // Skip option if it does not contain the query string.\n if (query.trim() !== '' && option.label.toLocaleLowerCase().indexOf(query.toLocaleLowerCase()) === -1) {\n return true;\n }\n // Skip filters that have already been selected.\n if ($.inArray(option.value, selectedFilters) > -1) {\n return true;\n }\n\n filteredOptions.push(option);\n return true;\n });\n\n var deferred = new $.Deferred();\n deferred.resolve(filteredOptions);\n\n return deferred.promise();\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.\n * @return {Array} New array of results.\n */\n processResults: function(selector, results) {\n var options = [];\n $.each(results, function(index, data) {\n options.push({\n value: data.value,\n label: data.label\n });\n });\n return options;\n },\n\n /**\n * Source of data for Ajax element.\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 */\n /* eslint-disable promise/no-callback-in-promise */\n transport: function(selector, query, callback) {\n this.list(selector, query).then(callback).catch(Notification.exception);\n }\n };\n\n});\n"],"names":["define","$","Ajax","Notification","list","selector","query","filteredOptions","el","originalOptions","data","selectedFilters","val","each","index","option","trim","label","toLocaleLowerCase","indexOf","inArray","value","push","deferred","Deferred","resolve","promise","processResults","results","options","transport","callback","then","catch","exception"],"mappings":";;;;;;;;AAwBAA,mDAAO,CAAC,SAAU,YAAa,sBAAsB,SAASC,EAAGC,KAAMC,oBAEG,CAQlEC,KAAM,SAASC,SAAUC,WACjBC,gBAAkB,GAElBC,GAAKP,EAAEI,UACPI,gBAAkBR,EAAEI,UAAUK,KAAK,uBACnCC,gBAAkBH,GAAGI,MACzBX,EAAEY,KAAKJ,iBAAiB,SAASK,MAAOC,cAEf,KAAjBT,MAAMU,SAA0F,IAAzED,OAAOE,MAAMC,oBAAoBC,QAAQb,MAAMY,sBAItEjB,EAAEmB,QAAQL,OAAOM,MAAOV,kBAAoB,GAIhDJ,gBAAgBe,KAAKP,SAPV,SAWXQ,SAAW,IAAItB,EAAEuB,gBACrBD,SAASE,QAAQlB,iBAEVgB,SAASG,WAUpBC,eAAgB,SAAStB,SAAUuB,aAC3BC,QAAU,UACd5B,EAAEY,KAAKe,SAAS,SAASd,MAAOJ,MAC5BmB,QAAQP,KAAK,CACTD,MAAOX,KAAKW,MACZJ,MAAOP,KAAKO,WAGbY,SAWXC,UAAW,SAASzB,SAAUC,MAAOyB,eAC5B3B,KAAKC,SAAUC,OAAO0B,KAAKD,UAAUE,MAAM9B,aAAa+B"}
\ No newline at end of file
diff --git a/admin/tool/policy/amd/build/acceptmodal.min.js b/admin/tool/policy/amd/build/acceptmodal.min.js
index b1c6edfaeb7..2c1c4f907a9 100644
--- a/admin/tool/policy/amd/build/acceptmodal.min.js
+++ b/admin/tool/policy/amd/build/acceptmodal.min.js
@@ -1,2 +1,10 @@
-define ("tool_policy/acceptmodal",["jquery","core/str","core/modal_factory","core/modal_events","core/notification","core/fragment","core/ajax","core_form/changechecker"],function(a,b,c,d,f,g,h,i){"use strict";var j=function(a){this.contextid=a;this.init()};j.prototype.modal=null;j.prototype.contextid=-1;j.prototype.currentTrigger=null;j.prototype.triggers={SINGLE:"a[data-action=acceptmodal]",BULK:"input[data-action=acceptmodal]"};j.prototype.init=function(){a(this.triggers.SINGLE).on("click",function(b){b.preventDefault();this.currentTrigger=a(b.currentTarget);var c=a(b.currentTarget).attr("href"),d=c.slice(c.indexOf("?")+1);this.showFormModal(d)}.bind(this));a(this.triggers.BULK).on("click",function(c){c.preventDefault();this.currentTrigger=a(c.currentTarget);var d=a(c.currentTarget).closest("form");if(d.find("input[type=checkbox][name=\"userids[]\"]:checked").length){var e=d.serialize();this.showFormModal(e)}else{b.get_strings([{key:"notice"},{key:"selectusersforconsent",component:"tool_policy"},{key:"ok"}]).then(function(a){f.alert(a[0],a[1],a[2])}).fail(f.exception)}}.bind(this))};j.prototype.showFormModal=function(a){for(var d,e=a.split("&"),g=0,h;g.\n\n/**\n * Add policy consent modal to the page\n *\n * @module tool_policy/acceptmodal\n * @copyright 2018 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/notification',\n 'core/fragment',\n 'core/ajax',\n 'core_form/changechecker',\n], function(\n $,\n Str,\n ModalFactory,\n ModalEvents,\n Notification,\n Fragment,\n Ajax,\n FormChangeChecker\n) {\n\n \"use strict\";\n\n /**\n * Constructor\n *\n * @param {int} contextid\n *\n * Each call to init gets it's own instance of this class.\n */\n var AcceptOnBehalf = function(contextid) {\n this.contextid = contextid;\n this.init();\n };\n\n /**\n * @var {Modal} modal\n * @private\n */\n AcceptOnBehalf.prototype.modal = null;\n\n /**\n * @var {int} contextid\n * @private\n */\n AcceptOnBehalf.prototype.contextid = -1;\n\n /**\n * @var {object} currentTrigger The triggered HTML jQuery object\n * @private\n */\n AcceptOnBehalf.prototype.currentTrigger = null;\n\n /**\n * @var {object} triggers The trigger selectors\n * @private\n */\n AcceptOnBehalf.prototype.triggers = {\n SINGLE: 'a[data-action=acceptmodal]',\n BULK: 'input[data-action=acceptmodal]'\n };\n\n /**\n * Initialise the class.\n *\n * @private\n */\n AcceptOnBehalf.prototype.init = function() {\n // Initialise for links accepting policies for individual users.\n $(this.triggers.SINGLE).on('click', function(e) {\n e.preventDefault();\n this.currentTrigger = $(e.currentTarget);\n var href = $(e.currentTarget).attr('href'),\n formData = href.slice(href.indexOf('?') + 1);\n this.showFormModal(formData);\n }.bind(this));\n\n // Initialise for multiple users acceptance form.\n $(this.triggers.BULK).on('click', function(e) {\n e.preventDefault();\n this.currentTrigger = $(e.currentTarget);\n var form = $(e.currentTarget).closest('form');\n if (form.find('input[type=checkbox][name=\"userids[]\"]:checked').length) {\n var formData = form.serialize();\n this.showFormModal(formData);\n } else {\n Str.get_strings([\n {key: 'notice'},\n {key: 'selectusersforconsent', component: 'tool_policy'},\n {key: 'ok'}\n ]).then(function(strings) {\n Notification.alert(strings[0], strings[1], strings[2]);\n return;\n }).fail(Notification.exception);\n }\n }.bind(this));\n };\n\n /**\n * Show modal with a form\n *\n * @param {String} formData\n */\n AcceptOnBehalf.prototype.showFormModal = function(formData) {\n var action;\n var params = formData.split('&');\n for (var i = 0; i < params.length; i++) {\n var pair = params[i].split('=');\n if (pair[0] == 'action') {\n action = pair[1];\n }\n }\n // Fetch the title string.\n Str.get_strings([\n {key: 'statusformtitleaccept', component: 'tool_policy'},\n {key: 'iagreetothepolicy', component: 'tool_policy'},\n {key: 'statusformtitlerevoke', component: 'tool_policy'},\n {key: 'irevokethepolicy', component: 'tool_policy'},\n {key: 'statusformtitledecline', component: 'tool_policy'},\n {key: 'declinethepolicy', component: 'tool_policy'}\n ]).then(function(strings) {\n var title;\n var saveText;\n if (action == 'accept') {\n title = strings[0];\n saveText = strings[1];\n } else if (action == 'revoke') {\n title = strings[2];\n saveText = strings[3];\n } else if (action == 'decline') {\n title = strings[4];\n saveText = strings[5];\n }\n // Create the modal.\n return ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: title,\n body: ''\n }).done(function(modal) {\n this.modal = modal;\n this.setupFormModal(formData, saveText);\n }.bind(this));\n }.bind(this))\n .catch(Notification.exception);\n };\n\n /**\n * Setup form inside a modal\n *\n * @param {String} formData\n * @param {String} saveText\n */\n AcceptOnBehalf.prototype.setupFormModal = function(formData, saveText) {\n var modal = this.modal;\n\n modal.setLarge();\n\n modal.setSaveButtonText(saveText);\n\n // We want to reset the form every time it is opened.\n modal.getRoot().on(ModalEvents.hidden, this.destroy.bind(this));\n\n modal.setBody(this.getBody(formData));\n\n // We catch the modal save event, and use it to submit the form inside the modal.\n // Triggering a form submission will give JS validation scripts a chance to check for errors.\n modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));\n // We also catch the form submit event and use it to submit the form with ajax.\n modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));\n\n modal.show();\n };\n\n /**\n * Load the body of the modal (contains the form)\n *\n * @method getBody\n * @private\n * @param {String} formData\n * @return {Promise}\n */\n AcceptOnBehalf.prototype.getBody = function(formData) {\n if (typeof formData === \"undefined\") {\n formData = {};\n }\n // Get the content of the modal.\n var params = {jsonformdata: JSON.stringify(formData)};\n return Fragment.loadFragment('tool_policy', 'accept_on_behalf', this.contextid, params);\n };\n\n /**\n * Submit the form inside the modal via AJAX request\n *\n * @method submitFormAjax\n * @private\n * @param {Event} e Form submission event.\n */\n AcceptOnBehalf.prototype.submitFormAjax = function(e) {\n // We don't want to do a real form submission.\n e.preventDefault();\n\n // Convert all the form elements values to a serialised string.\n var formData = this.modal.getRoot().find('form').serialize();\n\n var requests = Ajax.call([{\n methodname: 'tool_policy_submit_accept_on_behalf',\n args: {jsonformdata: JSON.stringify(formData)}\n }]);\n requests[0].done(function(data) {\n if (data.validationerrors) {\n this.modal.setBody(this.getBody(formData));\n } else {\n this.close();\n }\n }.bind(this)).fail(Notification.exception);\n };\n\n /**\n * This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.\n *\n * @method submitForm\n * @param {Event} e Form submission event.\n * @private\n */\n AcceptOnBehalf.prototype.submitForm = function(e) {\n e.preventDefault();\n this.modal.getRoot().find('form').submit();\n };\n\n /**\n * Close the modal\n */\n AcceptOnBehalf.prototype.close = function() {\n this.destroy();\n document.location.reload();\n };\n\n /**\n * Destroy the modal\n */\n AcceptOnBehalf.prototype.destroy = function() {\n FormChangeChecker.resetAllFormDirtyStates();\n this.modal.destroy();\n this.currentTrigger.focus();\n };\n\n return /** @alias module:tool_policy/acceptmodal */ {\n // Public variables and functions.\n /**\n * Attach event listeners to initialise this module.\n *\n * @method init\n * @param {int} contextid The contextid for the course.\n * @return {AcceptOnBehalf}\n */\n getInstance: function(contextid) {\n return new AcceptOnBehalf(contextid);\n }\n };\n });\n"],"file":"acceptmodal.min.js"}
\ No newline at end of file
+{"version":3,"file":"acceptmodal.min.js","sources":["../src/acceptmodal.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 .\n\n/**\n * Add policy consent modal to the page\n *\n * @module tool_policy/acceptmodal\n * @copyright 2018 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/notification',\n 'core/fragment',\n 'core/ajax',\n 'core_form/changechecker',\n], function(\n $,\n Str,\n ModalFactory,\n ModalEvents,\n Notification,\n Fragment,\n Ajax,\n FormChangeChecker\n) {\n\n \"use strict\";\n\n /**\n * Constructor\n *\n * @param {int} contextid\n *\n * Each call to init gets it's own instance of this class.\n */\n var AcceptOnBehalf = function(contextid) {\n this.contextid = contextid;\n this.init();\n };\n\n /**\n * @var {Modal} modal\n * @private\n */\n AcceptOnBehalf.prototype.modal = null;\n\n /**\n * @var {int} contextid\n * @private\n */\n AcceptOnBehalf.prototype.contextid = -1;\n\n /**\n * @var {object} currentTrigger The triggered HTML jQuery object\n * @private\n */\n AcceptOnBehalf.prototype.currentTrigger = null;\n\n /**\n * @var {object} triggers The trigger selectors\n * @private\n */\n AcceptOnBehalf.prototype.triggers = {\n SINGLE: 'a[data-action=acceptmodal]',\n BULK: 'input[data-action=acceptmodal]'\n };\n\n /**\n * Initialise the class.\n *\n * @private\n */\n AcceptOnBehalf.prototype.init = function() {\n // Initialise for links accepting policies for individual users.\n $(this.triggers.SINGLE).on('click', function(e) {\n e.preventDefault();\n this.currentTrigger = $(e.currentTarget);\n var href = $(e.currentTarget).attr('href'),\n formData = href.slice(href.indexOf('?') + 1);\n this.showFormModal(formData);\n }.bind(this));\n\n // Initialise for multiple users acceptance form.\n $(this.triggers.BULK).on('click', function(e) {\n e.preventDefault();\n this.currentTrigger = $(e.currentTarget);\n var form = $(e.currentTarget).closest('form');\n if (form.find('input[type=checkbox][name=\"userids[]\"]:checked').length) {\n var formData = form.serialize();\n this.showFormModal(formData);\n } else {\n Str.get_strings([\n {key: 'notice'},\n {key: 'selectusersforconsent', component: 'tool_policy'},\n {key: 'ok'}\n ]).then(function(strings) {\n Notification.alert(strings[0], strings[1], strings[2]);\n return;\n }).fail(Notification.exception);\n }\n }.bind(this));\n };\n\n /**\n * Show modal with a form\n *\n * @param {String} formData\n */\n AcceptOnBehalf.prototype.showFormModal = function(formData) {\n var action;\n var params = formData.split('&');\n for (var i = 0; i < params.length; i++) {\n var pair = params[i].split('=');\n if (pair[0] == 'action') {\n action = pair[1];\n }\n }\n // Fetch the title string.\n Str.get_strings([\n {key: 'statusformtitleaccept', component: 'tool_policy'},\n {key: 'iagreetothepolicy', component: 'tool_policy'},\n {key: 'statusformtitlerevoke', component: 'tool_policy'},\n {key: 'irevokethepolicy', component: 'tool_policy'},\n {key: 'statusformtitledecline', component: 'tool_policy'},\n {key: 'declinethepolicy', component: 'tool_policy'}\n ]).then(function(strings) {\n var title;\n var saveText;\n if (action == 'accept') {\n title = strings[0];\n saveText = strings[1];\n } else if (action == 'revoke') {\n title = strings[2];\n saveText = strings[3];\n } else if (action == 'decline') {\n title = strings[4];\n saveText = strings[5];\n }\n // Create the modal.\n return ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: title,\n body: ''\n }).done(function(modal) {\n this.modal = modal;\n this.setupFormModal(formData, saveText);\n }.bind(this));\n }.bind(this))\n .catch(Notification.exception);\n };\n\n /**\n * Setup form inside a modal\n *\n * @param {String} formData\n * @param {String} saveText\n */\n AcceptOnBehalf.prototype.setupFormModal = function(formData, saveText) {\n var modal = this.modal;\n\n modal.setLarge();\n\n modal.setSaveButtonText(saveText);\n\n // We want to reset the form every time it is opened.\n modal.getRoot().on(ModalEvents.hidden, this.destroy.bind(this));\n\n modal.setBody(this.getBody(formData));\n\n // We catch the modal save event, and use it to submit the form inside the modal.\n // Triggering a form submission will give JS validation scripts a chance to check for errors.\n modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));\n // We also catch the form submit event and use it to submit the form with ajax.\n modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));\n\n modal.show();\n };\n\n /**\n * Load the body of the modal (contains the form)\n *\n * @method getBody\n * @private\n * @param {String} formData\n * @return {Promise}\n */\n AcceptOnBehalf.prototype.getBody = function(formData) {\n if (typeof formData === \"undefined\") {\n formData = {};\n }\n // Get the content of the modal.\n var params = {jsonformdata: JSON.stringify(formData)};\n return Fragment.loadFragment('tool_policy', 'accept_on_behalf', this.contextid, params);\n };\n\n /**\n * Submit the form inside the modal via AJAX request\n *\n * @method submitFormAjax\n * @private\n * @param {Event} e Form submission event.\n */\n AcceptOnBehalf.prototype.submitFormAjax = function(e) {\n // We don't want to do a real form submission.\n e.preventDefault();\n\n // Convert all the form elements values to a serialised string.\n var formData = this.modal.getRoot().find('form').serialize();\n\n var requests = Ajax.call([{\n methodname: 'tool_policy_submit_accept_on_behalf',\n args: {jsonformdata: JSON.stringify(formData)}\n }]);\n requests[0].done(function(data) {\n if (data.validationerrors) {\n this.modal.setBody(this.getBody(formData));\n } else {\n this.close();\n }\n }.bind(this)).fail(Notification.exception);\n };\n\n /**\n * This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.\n *\n * @method submitForm\n * @param {Event} e Form submission event.\n * @private\n */\n AcceptOnBehalf.prototype.submitForm = function(e) {\n e.preventDefault();\n this.modal.getRoot().find('form').submit();\n };\n\n /**\n * Close the modal\n */\n AcceptOnBehalf.prototype.close = function() {\n this.destroy();\n document.location.reload();\n };\n\n /**\n * Destroy the modal\n */\n AcceptOnBehalf.prototype.destroy = function() {\n FormChangeChecker.resetAllFormDirtyStates();\n this.modal.destroy();\n this.currentTrigger.focus();\n };\n\n return /** @alias module:tool_policy/acceptmodal */ {\n // Public variables and functions.\n /**\n * Attach event listeners to initialise this module.\n *\n * @method init\n * @param {int} contextid The contextid for the course.\n * @return {AcceptOnBehalf}\n */\n getInstance: function(contextid) {\n return new AcceptOnBehalf(contextid);\n }\n };\n });\n"],"names":["define","$","Str","ModalFactory","ModalEvents","Notification","Fragment","Ajax","FormChangeChecker","AcceptOnBehalf","contextid","init","prototype","modal","currentTrigger","triggers","SINGLE","BULK","this","on","e","preventDefault","currentTarget","href","attr","formData","slice","indexOf","showFormModal","bind","form","closest","find","length","serialize","get_strings","key","component","then","strings","alert","fail","exception","action","params","split","i","pair","title","saveText","create","type","types","SAVE_CANCEL","body","done","setupFormModal","catch","setLarge","setSaveButtonText","getRoot","hidden","destroy","setBody","getBody","save","submitForm","submitFormAjax","show","jsonformdata","JSON","stringify","loadFragment","call","methodname","args","data","validationerrors","close","submit","document","location","reload","resetAllFormDirtyStates","focus","getInstance"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/policy/amd/build/jquery-eu-cookie-law-popup.min.js b/admin/tool/policy/amd/build/jquery-eu-cookie-law-popup.min.js
index 37744652a39..6dc7ef9edf3 100644
--- a/admin/tool/policy/amd/build/jquery-eu-cookie-law-popup.min.js
+++ b/admin/tool/policy/amd/build/jquery-eu-cookie-law-popup.min.js
@@ -1,2 +1,3 @@
-define ("tool_policy/jquery-eu-cookie-law-popup",["jquery"],function(a){if(!window.console)window.console={};if(!window.console.log)window.console.log=function(){};a.fn.euCookieLawPopup=function(){var b=this;b.params={cookiePolicyUrl:"/?cookie-policy",popupPosition:"top",colorStyle:"default",compactStyle:!1,popupTitle:"This website is using cookies",popupText:"We use cookies to ensure that we give you the best experience on our website. If you continue without changing your settings, we'll assume that you are happy to receive all cookies on this website.",buttonContinueTitle:"Continue",buttonLearnmoreTitle:"Learn more",buttonLearnmoreOpenInNewWindow:!0,agreementExpiresInDays:30,autoAcceptCookiePolicy:!1,htmlMarkup:null};b.vars={INITIALISED:!1,HTML_MARKUP:null,COOKIE_NAME:"EU_COOKIE_LAW_CONSENT"};var c=function(c,d,e){if(c){var f=a(c).attr("class")?a(c).attr("class"):"";if(-1
';\r\n\r\n\t\treturn html;\r\n\t};\r\n\r\n\t// Storing the consent in a cookie\r\n\tvar setUserAcceptsCookies = function(consent) {\r\n\t\tvar d = new Date();\r\n\t\tvar expiresInDays = _self.params.agreementExpiresInDays * 24 * 60 * 60 * 1000;\r\n\t\td.setTime( d.getTime() + expiresInDays );\r\n\t\tvar expires = \"expires=\" + d.toGMTString();\r\n\t\tdocument.cookie = _self.vars.COOKIE_NAME + '=' + consent + \"; \" + expires + \";path=/\";\r\n\r\n\t\t$(document).trigger(\"user_cookie_consent_changed\", {'consent' : consent});\r\n\t};\r\n\r\n\t// Let's see if we have a consent cookie already\r\n\tvar userAlreadyAcceptedCookies = function() {\r\n\t\tvar userAcceptedCookies = false;\r\n\t\tvar cookies = document.cookie.split(\";\");\r\n\t\tfor (var i = 0; i < cookies.length; i++) {\r\n\t\t\tvar c = cookies[i].trim();\r\n\t\t\tif (c.indexOf(_self.vars.COOKIE_NAME) !== -1) {\r\n\t\t\t\tuserAcceptedCookies = c.substring(_self.vars.COOKIE_NAME.length + 1, c.length);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn userAcceptedCookies;\r\n\t};\r\n\r\n\tvar hideContainer = function() {\r\n\t\t// $('.eupopup-container').slideUp(200);\r\n\t\t$('.eupopup-container').animate({\r\n\t\t\topacity: 0,\r\n\t\t\theight: 0\r\n\t\t}, 200, function() {\r\n\t\t\t$('.eupopup-container').hide(0);\r\n\t\t});\r\n\t};\r\n\r\n\t///////////////////////////////////////////////////////////////////////////////////////////////\r\n\t// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////\r\n\tvar publicfunc = {\r\n\r\n\t\t// INITIALIZE EU COOKIE LAW POPUP /////////////////////////////////////////////////////////\r\n\t\tinit : function(settings) {\r\n\r\n\t\t\tparseParameters(\r\n\t\t\t\t$(\".eupopup\").first(),\r\n\t\t\t\t$(\".eupopup-markup\").html(),\r\n\t\t\t\tsettings);\r\n\r\n\t\t\t// No need to display this if user already accepted the policy\r\n\t\t\tif (userAlreadyAcceptedCookies()) {\r\n $(document).trigger(\"user_cookie_already_accepted\", {'consent': true});\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// We should initialise only once\r\n\t\t\tif (_self.vars.INITIALISED) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\t_self.vars.INITIALISED = true;\r\n\r\n\t\t\t// Markup and event listeners >>>\r\n\t\t\t_self.vars.HTML_MARKUP = createHtmlMarkup();\r\n\r\n\t\t\tif ($('.eupopup-block').length > 0) {\r\n\t\t\t\t$('.eupopup-block').append(_self.vars.HTML_MARKUP);\r\n\t\t\t} else {\r\n\t\t\t\t$('BODY').append(_self.vars.HTML_MARKUP);\r\n\t\t\t}\r\n\r\n\t\t\t$('.eupopup-button_1').click(function() {\r\n\t\t\t\tsetUserAcceptsCookies(true);\r\n\t\t\t\thideContainer();\r\n\t\t\t\treturn false;\r\n\t\t\t});\r\n\t\t\t$('.eupopup-closebutton').click(function() {\r\n\t\t\t\tsetUserAcceptsCookies(true);\r\n\t\t\t\thideContainer();\r\n\t\t\t\treturn false;\r\n\t\t\t});\r\n\t\t\t// ^^^ Markup and event listeners\r\n\r\n\t\t\t// Ready to start!\r\n\t\t\t$('.eupopup-container').show();\r\n\r\n\t\t\t// In case it's alright to just display the message once\r\n\t\t\tif (_self.params.autoAcceptCookiePolicy) {\r\n\t\t\t\tsetUserAcceptsCookies(true);\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\treturn publicfunc;\r\n});\r\n});\r\n"],"names":["define","$","window","console","log","fn","euCookieLawPopup","_self","this","params","cookiePolicyUrl","popupPosition","colorStyle","compactStyle","popupTitle","popupText","buttonContinueTitle","buttonLearnmoreTitle","buttonLearnmoreOpenInNewWindow","agreementExpiresInDays","autoAcceptCookiePolicy","htmlMarkup","vars","INITIALISED","HTML_MARKUP","COOKIE_NAME","setUserAcceptsCookies","consent","d","Date","expiresInDays","setTime","getTime","expires","toGMTString","document","cookie","trigger","hideContainer","animate","opacity","height","hide","init","settings","object","markup","className","attr","indexOf","parseParameters","first","html","userAcceptedCookies","cookies","split","i","length","c","trim","substring","userAlreadyAcceptedCookies","append","click","show"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/policy/amd/build/managedocsactions.min.js b/admin/tool/policy/amd/build/managedocsactions.min.js
index e5a1692f384..fb447ea00ea 100644
--- a/admin/tool/policy/amd/build/managedocsactions.min.js
+++ b/admin/tool/policy/amd/build/managedocsactions.min.js
@@ -1,2 +1,10 @@
-define ("tool_policy/managedocsactions",["jquery","core/log","core/config","core/str","core/modal_factory","core/modal_events"],function(a,b,c,d,e,f){"use strict";var h={LINKS:"[data-action]",MAKE_CURRENT:"[data-action=\"makecurrent\"]",INACTIVATE:"[data-action=\"inactivate\"]",DELETE:"[data-action=\"delete\"]"};function g(a){this.base=a;this.initEvents()}g.prototype.initEvents=function(){var g=this;g.base.on("click",h.LINKS,function(g){g.stopPropagation();var i=a(g.currentTarget),j,k;if(i.is(h.MAKE_CURRENT)){j=d.get_strings([{key:"activating",component:"tool_policy"},{key:"activateconfirm",component:"tool_policy",param:{name:i.closest("[data-policy-name]").attr("data-policy-name"),revision:i.closest("[data-policy-revision]").attr("data-policy-revision")}},{key:"activateconfirmyes",component:"tool_policy"}])}else if(i.is(h.INACTIVATE)){j=d.get_strings([{key:"inactivating",component:"tool_policy"},{key:"inactivatingconfirm",component:"tool_policy",param:{name:i.closest("[data-policy-name]").attr("data-policy-name"),revision:i.closest("[data-policy-revision]").attr("data-policy-revision")}},{key:"inactivatingconfirmyes",component:"tool_policy"}])}else if(i.is(h.DELETE)){j=d.get_strings([{key:"deleting",component:"tool_policy"},{key:"deleteconfirm",component:"tool_policy",param:{name:i.closest("[data-policy-name]").attr("data-policy-name"),revision:i.closest("[data-policy-revision]").attr("data-policy-revision")}},{key:"delete",component:"core"}])}else{b.error("unknown action type detected","tool_policy/managedocsactions");return}g.preventDefault();j.then(function(a){k=a;return e.create({title:k[0],body:k[1],type:e.types.SAVE_CANCEL})}).then(function(a){a.setSaveButtonText(k[2]);a.getRoot().on(f.save,function(){window.location.href=i.attr("href")+"&sesskey="+c.sesskey+"&confirm=1"});a.getRoot().on(f.hidden,function(){a.destroy()});a.show();return!0}).catch(function(a){b.error(a);return!1})})};return{init:function init(b){var c=a(document.getElementById(b));if(c.length){return new g(c)}else{throw new Error("managedocsactions: Invalid base element identifier")}}}});
-//# sourceMappingURL=managedocsactions.min.js.map
+/**
+ * Adds support for confirmation via JS modal for some management actions at the Manage policies page.
+ *
+ * @module tool_policy/managedocsactions
+ * @copyright 2018 David Mudrák
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_policy/managedocsactions",["jquery","core/log","core/config","core/str","core/modal_factory","core/modal_events"],(function($,Log,Config,Str,ModalFactory,ModalEvents){var ACTION_LINKS="[data-action]",ACTION_MAKE_CURRENT='[data-action="makecurrent"]',ACTION_INACTIVATE='[data-action="inactivate"]',ACTION_DELETE='[data-action="delete"]';function ManageDocsActions(base){this.base=base,this.initEvents()}return ManageDocsActions.prototype.initEvents=function(){this.base.on("click",ACTION_LINKS,(function(e){e.stopPropagation();var promise,strings,link=$(e.currentTarget);if(link.is(ACTION_MAKE_CURRENT))promise=Str.get_strings([{key:"activating",component:"tool_policy"},{key:"activateconfirm",component:"tool_policy",param:{name:link.closest("[data-policy-name]").attr("data-policy-name"),revision:link.closest("[data-policy-revision]").attr("data-policy-revision")}},{key:"activateconfirmyes",component:"tool_policy"}]);else if(link.is(ACTION_INACTIVATE))promise=Str.get_strings([{key:"inactivating",component:"tool_policy"},{key:"inactivatingconfirm",component:"tool_policy",param:{name:link.closest("[data-policy-name]").attr("data-policy-name"),revision:link.closest("[data-policy-revision]").attr("data-policy-revision")}},{key:"inactivatingconfirmyes",component:"tool_policy"}]);else{if(!link.is(ACTION_DELETE))return void Log.error("unknown action type detected","tool_policy/managedocsactions");promise=Str.get_strings([{key:"deleting",component:"tool_policy"},{key:"deleteconfirm",component:"tool_policy",param:{name:link.closest("[data-policy-name]").attr("data-policy-name"),revision:link.closest("[data-policy-revision]").attr("data-policy-revision")}},{key:"delete",component:"core"}])}e.preventDefault(),promise.then((function(strs){return strings=strs,ModalFactory.create({title:strings[0],body:strings[1],type:ModalFactory.types.SAVE_CANCEL})})).then((function(modal){return modal.setSaveButtonText(strings[2]),modal.getRoot().on(ModalEvents.save,(function(){window.location.href=link.attr("href")+"&sesskey="+Config.sesskey+"&confirm=1"})),modal.getRoot().on(ModalEvents.hidden,(function(){modal.destroy()})),modal.show(),!0})).catch((function(e){return Log.error(e),!1}))}))},{init:function(baseid){var base=$(document.getElementById(baseid));if(base.length)return new ManageDocsActions(base);throw new Error("managedocsactions: Invalid base element identifier")}}}));
+
+//# sourceMappingURL=managedocsactions.min.js.map
\ No newline at end of file
diff --git a/admin/tool/policy/amd/build/managedocsactions.min.js.map b/admin/tool/policy/amd/build/managedocsactions.min.js.map
index 0c08443570d..d2962520b4e 100644
--- a/admin/tool/policy/amd/build/managedocsactions.min.js.map
+++ b/admin/tool/policy/amd/build/managedocsactions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/managedocsactions.js"],"names":["define","$","Log","Config","Str","ModalFactory","ModalEvents","ACTION","LINKS","MAKE_CURRENT","INACTIVATE","DELETE","ManageDocsActions","base","initEvents","prototype","self","on","e","stopPropagation","link","currentTarget","promise","strings","is","get_strings","key","component","param","name","closest","attr","revision","error","preventDefault","then","strs","create","title","body","type","types","SAVE_CANCEL","modal","setSaveButtonText","getRoot","save","window","location","href","sesskey","hidden","destroy","show","catch","init","baseid","document","getElementById","length","Error"],"mappings":"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","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 .\n\n/**\n * Adds support for confirmation via JS modal for some management actions at the Manage policies page.\n *\n * @module tool_policy/managedocsactions\n * @copyright 2018 David Mudrák \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/log',\n 'core/config',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events'\n], function($, Log, Config, Str, ModalFactory, ModalEvents) {\n\n \"use strict\";\n\n /**\n * List of action selectors.\n *\n * @property {string} LINKS - Selector for all action links\n * @property {string} MAKE_CURRENT\n */\n var ACTION = {\n LINKS: '[data-action]',\n MAKE_CURRENT: '[data-action=\"makecurrent\"]',\n INACTIVATE: '[data-action=\"inactivate\"]',\n DELETE: '[data-action=\"delete\"]'\n };\n\n /**\n * @constructor\n * @param {Element} base - Management area wrapping element\n */\n function ManageDocsActions(base) {\n this.base = base;\n\n this.initEvents();\n }\n\n /**\n * Register event listeners.\n */\n ManageDocsActions.prototype.initEvents = function() {\n var self = this;\n\n self.base.on('click', ACTION.LINKS, function(e) {\n e.stopPropagation();\n\n var link = $(e.currentTarget);\n var promise;\n var strings;\n\n if (link.is(ACTION.MAKE_CURRENT)) {\n promise = Str.get_strings([\n {key: 'activating', component: 'tool_policy'},\n {key: 'activateconfirm', component: 'tool_policy', param: {\n name: link.closest('[data-policy-name]').attr('data-policy-name'),\n revision: link.closest('[data-policy-revision]').attr('data-policy-revision')\n }},\n {key: 'activateconfirmyes', component: 'tool_policy'}\n ]);\n\n } else if (link.is(ACTION.INACTIVATE)) {\n promise = Str.get_strings([\n {key: 'inactivating', component: 'tool_policy'},\n {key: 'inactivatingconfirm', component: 'tool_policy', param: {\n name: link.closest('[data-policy-name]').attr('data-policy-name'),\n revision: link.closest('[data-policy-revision]').attr('data-policy-revision')\n }},\n {key: 'inactivatingconfirmyes', component: 'tool_policy'}\n ]);\n\n } else if (link.is(ACTION.DELETE)) {\n promise = Str.get_strings([\n {key: 'deleting', component: 'tool_policy'},\n {key: 'deleteconfirm', component: 'tool_policy', param: {\n name: link.closest('[data-policy-name]').attr('data-policy-name'),\n revision: link.closest('[data-policy-revision]').attr('data-policy-revision')\n }},\n {key: 'delete', component: 'core'}\n ]);\n\n } else {\n Log.error('unknown action type detected', 'tool_policy/managedocsactions');\n return;\n }\n\n e.preventDefault();\n\n promise.then(function(strs) {\n strings = strs;\n return ModalFactory.create({\n title: strings[0],\n body: strings[1],\n type: ModalFactory.types.SAVE_CANCEL\n });\n\n }).then(function(modal) {\n modal.setSaveButtonText(strings[2]);\n modal.getRoot().on(ModalEvents.save, function() {\n window.location.href = link.attr('href') + '&sesskey=' + Config.sesskey + '&confirm=1';\n });\n\n modal.getRoot().on(ModalEvents.hidden, function() {\n modal.destroy();\n });\n\n modal.show();\n return true;\n\n }).catch(function(e) {\n Log.error(e);\n return false;\n });\n });\n };\n\n return {\n /**\n * Factory method returning instance of the ManageDocsActions\n *\n * @param {String} baseid - ID of the management area wrapping element\n * @return {ManageDocsActions}\n */\n init: function(baseid) {\n var base = $(document.getElementById(baseid));\n\n if (base.length) {\n return new ManageDocsActions(base);\n\n } else {\n throw new Error(\"managedocsactions: Invalid base element identifier\");\n }\n }\n };\n});\n"],"file":"managedocsactions.min.js"}
\ No newline at end of file
+{"version":3,"file":"managedocsactions.min.js","sources":["../src/managedocsactions.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 .\n\n/**\n * Adds support for confirmation via JS modal for some management actions at the Manage policies page.\n *\n * @module tool_policy/managedocsactions\n * @copyright 2018 David Mudrák \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/log',\n 'core/config',\n 'core/str',\n 'core/modal_factory',\n 'core/modal_events'\n], function($, Log, Config, Str, ModalFactory, ModalEvents) {\n\n \"use strict\";\n\n /**\n * List of action selectors.\n *\n * @property {string} LINKS - Selector for all action links\n * @property {string} MAKE_CURRENT\n */\n var ACTION = {\n LINKS: '[data-action]',\n MAKE_CURRENT: '[data-action=\"makecurrent\"]',\n INACTIVATE: '[data-action=\"inactivate\"]',\n DELETE: '[data-action=\"delete\"]'\n };\n\n /**\n * @constructor\n * @param {Element} base - Management area wrapping element\n */\n function ManageDocsActions(base) {\n this.base = base;\n\n this.initEvents();\n }\n\n /**\n * Register event listeners.\n */\n ManageDocsActions.prototype.initEvents = function() {\n var self = this;\n\n self.base.on('click', ACTION.LINKS, function(e) {\n e.stopPropagation();\n\n var link = $(e.currentTarget);\n var promise;\n var strings;\n\n if (link.is(ACTION.MAKE_CURRENT)) {\n promise = Str.get_strings([\n {key: 'activating', component: 'tool_policy'},\n {key: 'activateconfirm', component: 'tool_policy', param: {\n name: link.closest('[data-policy-name]').attr('data-policy-name'),\n revision: link.closest('[data-policy-revision]').attr('data-policy-revision')\n }},\n {key: 'activateconfirmyes', component: 'tool_policy'}\n ]);\n\n } else if (link.is(ACTION.INACTIVATE)) {\n promise = Str.get_strings([\n {key: 'inactivating', component: 'tool_policy'},\n {key: 'inactivatingconfirm', component: 'tool_policy', param: {\n name: link.closest('[data-policy-name]').attr('data-policy-name'),\n revision: link.closest('[data-policy-revision]').attr('data-policy-revision')\n }},\n {key: 'inactivatingconfirmyes', component: 'tool_policy'}\n ]);\n\n } else if (link.is(ACTION.DELETE)) {\n promise = Str.get_strings([\n {key: 'deleting', component: 'tool_policy'},\n {key: 'deleteconfirm', component: 'tool_policy', param: {\n name: link.closest('[data-policy-name]').attr('data-policy-name'),\n revision: link.closest('[data-policy-revision]').attr('data-policy-revision')\n }},\n {key: 'delete', component: 'core'}\n ]);\n\n } else {\n Log.error('unknown action type detected', 'tool_policy/managedocsactions');\n return;\n }\n\n e.preventDefault();\n\n promise.then(function(strs) {\n strings = strs;\n return ModalFactory.create({\n title: strings[0],\n body: strings[1],\n type: ModalFactory.types.SAVE_CANCEL\n });\n\n }).then(function(modal) {\n modal.setSaveButtonText(strings[2]);\n modal.getRoot().on(ModalEvents.save, function() {\n window.location.href = link.attr('href') + '&sesskey=' + Config.sesskey + '&confirm=1';\n });\n\n modal.getRoot().on(ModalEvents.hidden, function() {\n modal.destroy();\n });\n\n modal.show();\n return true;\n\n }).catch(function(e) {\n Log.error(e);\n return false;\n });\n });\n };\n\n return {\n /**\n * Factory method returning instance of the ManageDocsActions\n *\n * @param {String} baseid - ID of the management area wrapping element\n * @return {ManageDocsActions}\n */\n init: function(baseid) {\n var base = $(document.getElementById(baseid));\n\n if (base.length) {\n return new ManageDocsActions(base);\n\n } else {\n throw new Error(\"managedocsactions: Invalid base element identifier\");\n }\n }\n };\n});\n"],"names":["define","$","Log","Config","Str","ModalFactory","ModalEvents","ACTION","ManageDocsActions","base","initEvents","prototype","this","on","e","stopPropagation","promise","strings","link","currentTarget","is","get_strings","key","component","param","name","closest","attr","revision","error","preventDefault","then","strs","create","title","body","type","types","SAVE_CANCEL","modal","setSaveButtonText","getRoot","save","window","location","href","sesskey","hidden","destroy","show","catch","init","baseid","document","getElementById","length","Error"],"mappings":";;;;;;;AAsBAA,uCAAO,CACH,SACA,WACA,cACA,WACA,qBACA,sBACD,SAASC,EAAGC,IAAKC,OAAQC,IAAKC,aAAcC,iBAUvCC,aACO,gBADPA,oBAEc,8BAFdA,kBAGY,6BAHZA,cAIQ,kCAOHC,kBAAkBC,WAClBA,KAAOA,UAEPC,oBAMTF,kBAAkBG,UAAUD,WAAa,WAC1BE,KAENH,KAAKI,GAAG,QAASN,cAAc,SAASO,GACzCA,EAAEC,sBAGEC,QACAC,QAFAC,KAAOjB,EAAEa,EAAEK,kBAIXD,KAAKE,GAAGb,qBACRS,QAAUZ,IAAIiB,YAAY,CACtB,CAACC,IAAK,aAAcC,UAAW,eAC/B,CAACD,IAAK,kBAAmBC,UAAW,cAAeC,MAAO,CACtDC,KAAMP,KAAKQ,QAAQ,sBAAsBC,KAAK,oBAC9CC,SAAUV,KAAKQ,QAAQ,0BAA0BC,KAAK,0BAE1D,CAACL,IAAK,qBAAsBC,UAAW,sBAGxC,GAAIL,KAAKE,GAAGb,mBACfS,QAAUZ,IAAIiB,YAAY,CACtB,CAACC,IAAK,eAAgBC,UAAW,eACjC,CAACD,IAAK,sBAAuBC,UAAW,cAAeC,MAAO,CAC1DC,KAAMP,KAAKQ,QAAQ,sBAAsBC,KAAK,oBAC9CC,SAAUV,KAAKQ,QAAQ,0BAA0BC,KAAK,0BAE1D,CAACL,IAAK,yBAA0BC,UAAW,qBAG5C,CAAA,IAAIL,KAAKE,GAAGb,2BAWfL,IAAI2B,MAAM,+BAAgC,iCAV1Cb,QAAUZ,IAAIiB,YAAY,CACtB,CAACC,IAAK,WAAYC,UAAW,eAC7B,CAACD,IAAK,gBAAiBC,UAAW,cAAeC,MAAO,CACpDC,KAAMP,KAAKQ,QAAQ,sBAAsBC,KAAK,oBAC9CC,SAAUV,KAAKQ,QAAQ,0BAA0BC,KAAK,0BAE1D,CAACL,IAAK,SAAUC,UAAW,UAQnCT,EAAEgB,iBAEFd,QAAQe,MAAK,SAASC,aAClBf,QAAUe,KACH3B,aAAa4B,OAAO,CACvBC,MAAOjB,QAAQ,GACfkB,KAAMlB,QAAQ,GACdmB,KAAM/B,aAAagC,MAAMC,iBAG9BP,MAAK,SAASQ,cACbA,MAAMC,kBAAkBvB,QAAQ,IAChCsB,MAAME,UAAU5B,GAAGP,YAAYoC,MAAM,WACjCC,OAAOC,SAASC,KAAO3B,KAAKS,KAAK,QAAU,YAAcxB,OAAO2C,QAAU,gBAG9EP,MAAME,UAAU5B,GAAGP,YAAYyC,QAAQ,WACnCR,MAAMS,aAGVT,MAAMU,QACC,KAERC,OAAM,SAASpC,UACdZ,IAAI2B,MAAMf,IACH,SAKZ,CAOHqC,KAAM,SAASC,YACP3C,KAAOR,EAAEoD,SAASC,eAAeF,YAEjC3C,KAAK8C,cACE,IAAI/C,kBAAkBC,YAGvB,IAAI+C,MAAM"}
\ No newline at end of file
diff --git a/admin/tool/policy/amd/build/policyactions.min.js b/admin/tool/policy/amd/build/policyactions.min.js
index 80d26882b60..ec338571b8e 100644
--- a/admin/tool/policy/amd/build/policyactions.min.js
+++ b/admin/tool/policy/amd/build/policyactions.min.js
@@ -1,2 +1,10 @@
-define ("tool_policy/policyactions",["jquery","core/ajax","core/notification","core/modal_factory","core/modal_events"],function(a,b,c,d,e){var f=function(a){this.registerEvents(a)};f.prototype.registerEvents=function(f){f.on("click",function(f){f.preventDefault();var g=a(this).data("versionid"),h=a(this).data("behalfid"),i=a.Deferred(),j=a.Deferred(),k=d.create({title:i,body:j,large:!0}).then(function(a){a.getRoot().on(e.hidden,function(){a.destroy()});return a}).then(function(a){a.show();return a}).catch(c.exception),l=b.call([{methodname:"tool_policy_get_policy_version",args:{versionid:g,behalfid:h}}]);a.when(l[0]).then(function(a){if(a.result.policy){i.resolve(a.result.policy.name);j.resolve(a.result.policy.content);return a}else{throw new Error(a.warnings[0].message)}}).catch(function(a){k.then(function(a){a.hide();a.destroy();return a}).catch(c.exception);return c.addNotification({message:a,type:"error"})})})};return{init:function init(b){b=a(b);return new f(b)}}});
-//# sourceMappingURL=policyactions.min.js.map
+/**
+ * Policy actions.
+ *
+ * @module tool_policy/policyactions
+ * @copyright 2018 Sara Arjona (sara@moodle.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_policy/policyactions",["jquery","core/ajax","core/notification","core/modal_factory","core/modal_events"],(function($,Ajax,Notification,ModalFactory,ModalEvents){var PolicyActions=function(root){this.registerEvents(root)};return PolicyActions.prototype.registerEvents=function(root){root.on("click",(function(e){e.preventDefault();var request={methodname:"tool_policy_get_policy_version",args:{versionid:$(this).data("versionid"),behalfid:$(this).data("behalfid")}},modalTitle=$.Deferred(),modalBody=$.Deferred(),modal=ModalFactory.create({title:modalTitle,body:modalBody,large:!0}).then((function(modal){return modal.getRoot().on(ModalEvents.hidden,(function(){modal.destroy()})),modal})).then((function(modal){return modal.show(),modal})).catch(Notification.exception),promises=Ajax.call([request]);$.when(promises[0]).then((function(data){if(data.result.policy)return modalTitle.resolve(data.result.policy.name),modalBody.resolve(data.result.policy.content),data;throw new Error(data.warnings[0].message)})).catch((function(message){return modal.then((function(modal){return modal.hide(),modal.destroy(),modal})).catch(Notification.exception),Notification.addNotification({message:message,type:"error"})}))}))},{init:function(root){return root=$(root),new PolicyActions(root)}}}));
+
+//# sourceMappingURL=policyactions.min.js.map
\ No newline at end of file
diff --git a/admin/tool/policy/amd/build/policyactions.min.js.map b/admin/tool/policy/amd/build/policyactions.min.js.map
index 6cfd15e5e92..fb97f1b84ae 100644
--- a/admin/tool/policy/amd/build/policyactions.min.js.map
+++ b/admin/tool/policy/amd/build/policyactions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/policyactions.js"],"names":["define","$","Ajax","Notification","ModalFactory","ModalEvents","PolicyActions","root","registerEvents","prototype","on","e","preventDefault","versionid","data","behalfid","modalTitle","Deferred","modalBody","modal","create","title","body","large","then","getRoot","hidden","destroy","show","catch","exception","promises","call","methodname","args","when","result","policy","resolve","name","content","Error","warnings","message","hide","addNotification","type"],"mappings":"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","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 .\n\n/**\n * Policy actions.\n *\n * @module tool_policy/policyactions\n * @copyright 2018 Sara Arjona (sara@moodle.com)\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/modal_factory',\n 'core/modal_events'],\nfunction($, Ajax, Notification, ModalFactory, ModalEvents) {\n\n /**\n * PolicyActions class.\n *\n * @param {jQuery} root\n */\n var PolicyActions = function(root) {\n this.registerEvents(root);\n };\n\n /**\n * Register event listeners.\n *\n * @param {jQuery} root\n */\n PolicyActions.prototype.registerEvents = function(root) {\n root.on(\"click\", function(e) {\n e.preventDefault();\n\n var versionid = $(this).data('versionid');\n var behalfid = $(this).data('behalfid');\n\n var params = {\n 'versionid': versionid,\n 'behalfid': behalfid\n };\n\n var request = {\n methodname: 'tool_policy_get_policy_version',\n args: params\n };\n\n var modalTitle = $.Deferred();\n var modalBody = $.Deferred();\n\n var modal = ModalFactory.create({\n title: modalTitle,\n body: modalBody,\n large: true\n })\n .then(function(modal) {\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n return modal;\n })\n .then(function(modal) {\n modal.show();\n\n return modal;\n })\n .catch(Notification.exception);\n\n // Make the request now that the modal is configured.\n var promises = Ajax.call([request]);\n $.when(promises[0]).then(function(data) {\n if (data.result.policy) {\n modalTitle.resolve(data.result.policy.name);\n modalBody.resolve(data.result.policy.content);\n\n return data;\n } else {\n throw new Error(data.warnings[0].message);\n }\n }).catch(function(message) {\n modal.then(function(modal) {\n modal.hide();\n modal.destroy();\n\n return modal;\n })\n .catch(Notification.exception);\n\n return Notification.addNotification({\n message: message,\n type: 'error'\n });\n });\n });\n\n };\n\n return /** @alias module:tool_policy/policyactions */ {\n // Public variables and functions.\n\n /**\n * Initialise the actions helper.\n *\n * @method init\n * @param {object} root\n * @return {PolicyActions}\n */\n 'init': function(root) {\n root = $(root);\n return new PolicyActions(root);\n }\n };\n});\n"],"file":"policyactions.min.js"}
\ No newline at end of file
+{"version":3,"file":"policyactions.min.js","sources":["../src/policyactions.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 .\n\n/**\n * Policy actions.\n *\n * @module tool_policy/policyactions\n * @copyright 2018 Sara Arjona (sara@moodle.com)\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/modal_factory',\n 'core/modal_events'],\nfunction($, Ajax, Notification, ModalFactory, ModalEvents) {\n\n /**\n * PolicyActions class.\n *\n * @param {jQuery} root\n */\n var PolicyActions = function(root) {\n this.registerEvents(root);\n };\n\n /**\n * Register event listeners.\n *\n * @param {jQuery} root\n */\n PolicyActions.prototype.registerEvents = function(root) {\n root.on(\"click\", function(e) {\n e.preventDefault();\n\n var versionid = $(this).data('versionid');\n var behalfid = $(this).data('behalfid');\n\n var params = {\n 'versionid': versionid,\n 'behalfid': behalfid\n };\n\n var request = {\n methodname: 'tool_policy_get_policy_version',\n args: params\n };\n\n var modalTitle = $.Deferred();\n var modalBody = $.Deferred();\n\n var modal = ModalFactory.create({\n title: modalTitle,\n body: modalBody,\n large: true\n })\n .then(function(modal) {\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n return modal;\n })\n .then(function(modal) {\n modal.show();\n\n return modal;\n })\n .catch(Notification.exception);\n\n // Make the request now that the modal is configured.\n var promises = Ajax.call([request]);\n $.when(promises[0]).then(function(data) {\n if (data.result.policy) {\n modalTitle.resolve(data.result.policy.name);\n modalBody.resolve(data.result.policy.content);\n\n return data;\n } else {\n throw new Error(data.warnings[0].message);\n }\n }).catch(function(message) {\n modal.then(function(modal) {\n modal.hide();\n modal.destroy();\n\n return modal;\n })\n .catch(Notification.exception);\n\n return Notification.addNotification({\n message: message,\n type: 'error'\n });\n });\n });\n\n };\n\n return /** @alias module:tool_policy/policyactions */ {\n // Public variables and functions.\n\n /**\n * Initialise the actions helper.\n *\n * @method init\n * @param {object} root\n * @return {PolicyActions}\n */\n 'init': function(root) {\n root = $(root);\n return new PolicyActions(root);\n }\n };\n});\n"],"names":["define","$","Ajax","Notification","ModalFactory","ModalEvents","PolicyActions","root","registerEvents","prototype","on","e","preventDefault","request","methodname","args","this","data","modalTitle","Deferred","modalBody","modal","create","title","body","large","then","getRoot","hidden","destroy","show","catch","exception","promises","call","when","result","policy","resolve","name","content","Error","warnings","message","hide","addNotification","type"],"mappings":";;;;;;;AAsBAA,mCAAO,CACH,SACA,YACA,oBACA,qBACA,sBACJ,SAASC,EAAGC,KAAMC,aAAcC,aAAcC,iBAOtCC,cAAgB,SAASC,WACpBC,eAAeD,cAQxBD,cAAcG,UAAUD,eAAiB,SAASD,MAC9CA,KAAKG,GAAG,SAAS,SAASC,GACtBA,EAAEC,qBAUEC,QAAU,CACVC,WAAY,iCACZC,KAPS,WAHGd,EAAEe,MAAMC,KAAK,sBACdhB,EAAEe,MAAMC,KAAK,cAYxBC,WAAajB,EAAEkB,WACfC,UAAYnB,EAAEkB,WAEdE,MAAQjB,aAAakB,OAAO,CAC5BC,MAAOL,WACPM,KAAMJ,UACNK,OAAO,IAEVC,MAAK,SAASL,cAEXA,MAAMM,UAAUjB,GAAGL,YAAYuB,QAAQ,WAEnCP,MAAMQ,aAGHR,SAEVK,MAAK,SAASL,cACXA,MAAMS,OAECT,SAEVU,MAAM5B,aAAa6B,WAGhBC,SAAW/B,KAAKgC,KAAK,CAACrB,UAC1BZ,EAAEkC,KAAKF,SAAS,IAAIP,MAAK,SAAST,SAC1BA,KAAKmB,OAAOC,cACZnB,WAAWoB,QAAQrB,KAAKmB,OAAOC,OAAOE,MACtCnB,UAAUkB,QAAQrB,KAAKmB,OAAOC,OAAOG,SAE9BvB,WAED,IAAIwB,MAAMxB,KAAKyB,SAAS,GAAGC,YAEtCZ,OAAM,SAASY,gBACdtB,MAAMK,MAAK,SAASL,cAChBA,MAAMuB,OACNvB,MAAMQ,UAECR,SAEVU,MAAM5B,aAAa6B,WAEb7B,aAAa0C,gBAAgB,CAChCF,QAASA,QACTG,KAAM,iBAOgC,MAU1C,SAASvC,aACbA,KAAON,EAAEM,MACF,IAAID,cAAcC"}
\ No newline at end of file
diff --git a/admin/tool/templatelibrary/amd/build/display.min.js b/admin/tool/templatelibrary/amd/build/display.min.js
index 9ac8f6ba001..a256e671bc9 100644
--- a/admin/tool/templatelibrary/amd/build/display.min.js
+++ b/admin/tool/templatelibrary/amd/build/display.min.js
@@ -1,2 +1,10 @@
-define ("tool_templatelibrary/display",["jquery","core/ajax","core/log","core/notification","core/templates","core/config","core/str"],function(a,b,c,d,e,f,g){var h=function(a,b){if(!a){return!1}var c="@template "+b,d=0,e=[];e=a.match(/{{!([\s\S]*?)}}/g);if(null!==e){for(d=0;d
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_templatelibrary/display",["jquery","core/ajax","core/log","core/notification","core/templates","core/config","core/str"],(function($,ajax,log,notification,templates,config,str){var findDocsSection=function(templateSource,templateName){if(!templateSource)return!1;var sections,marker="@template "+templateName,i=0;if(null!==(sections=templateSource.match(/{{!([\s\S]*?)}}/g)))for(i=0;i.\n\n/**\n * This module adds ajax display functions to the template library page.\n *\n * @module tool_templatelibrary/display\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates', 'core/config', 'core/str'],\n function($, ajax, log, notification, templates, config, str) {\n\n /**\n * Search through a template for a template docs comment.\n *\n * @param {String} templateSource The raw template\n * @param {String} templateName The name of the template used to search for docs tag\n * @return {String|boolean} the correct comment or false\n */\n var findDocsSection = function(templateSource, templateName) {\n\n if (!templateSource) {\n return false;\n }\n // Find the comment section marked with @template component/template.\n var marker = \"@template \" + templateName,\n i = 0,\n sections = [];\n\n sections = templateSource.match(/{{!([\\s\\S]*?)}}/g);\n\n // If no sections match - show the entire file.\n if (sections !== null) {\n for (i = 0; i < sections.length; i++) {\n var section = sections[i];\n var start = section.indexOf(marker);\n if (start !== -1) {\n // Remove {{! and }} from start and end.\n var offset = start + marker.length + 1;\n section = section.substr(offset, section.length - 2 - offset);\n return section;\n }\n }\n }\n // No matching comment.\n return false;\n };\n\n /**\n * Handle a template loaded response.\n *\n * @param {String} templateName The template name\n * @param {String} source The template source\n * @param {String} originalSource The original template source (not theme overridden)\n */\n var templateLoaded = function(templateName, source, originalSource) {\n str.get_string('templateselected', 'tool_templatelibrary', templateName).done(function(s) {\n $('[data-region=\"displaytemplateheader\"]').text(s);\n }).fail(notification.exception);\n\n // Find the comment section marked with @template component/template.\n var docs = findDocsSection(source, templateName);\n\n if (docs === false) {\n // Docs was not in theme template, try original.\n docs = findDocsSection(originalSource, templateName);\n }\n\n // If we found a docs section, limit the template library to showing this section.\n if (docs) {\n source = docs;\n }\n\n $('[data-region=\"displaytemplatesource\"]').text(source);\n\n // Now search the text for a json example.\n\n var example = source.match(/Example context \\(json\\):([\\s\\S]*)/);\n var context = false;\n if (example) {\n var rawJSON = example[1].trim();\n try {\n context = $.parseJSON(rawJSON);\n } catch (e) {\n log.debug('Could not parse json example context for template.');\n log.debug(e);\n }\n }\n if (context) {\n templates.render(templateName, context).done(function(html, js) {\n templates.replaceNodeContents($('[data-region=\"displaytemplateexample\"]'), html, js);\n }).fail(notification.exception);\n } else {\n str.get_string('templatehasnoexample', 'tool_templatelibrary').done(function(s) {\n $('[data-region=\"displaytemplateexample\"]').text(s);\n }).fail(notification.exception);\n }\n };\n\n /**\n * Load the a template source from Moodle.\n *\n * @param {String} templateName\n */\n var loadTemplate = function(templateName) {\n var parts = templateName.split('/');\n var component = parts.shift();\n var name = parts.join('/');\n\n var promises = ajax.call([{\n methodname: 'core_output_load_template',\n args: {\n component: component,\n template: name,\n themename: config.theme,\n includecomments: true\n }\n }, {\n methodname: 'tool_templatelibrary_load_canonical_template',\n args: {\n component: component,\n template: name\n }\n }], true, false);\n\n // When returns a new promise that is resolved when all the passed in promises are resolved.\n // The arguments to the done become the values of each resolved promise.\n $.when.apply($, promises)\n .done(function(source, originalSource) {\n templateLoaded(templateName, source, originalSource);\n })\n .fail(notification.exception);\n };\n\n // Add the event listeners.\n $('[data-region=\"list-templates\"]').on('click', '[data-templatename]', function(e) {\n var templatename = $(this).data('templatename');\n e.preventDefault();\n loadTemplate(templatename);\n });\n\n // This module does not expose anything.\n return {};\n});\n"],"file":"display.min.js"}
\ No newline at end of file
+{"version":3,"file":"display.min.js","sources":["../src/display.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 .\n\n/**\n * This module adds ajax display functions to the template library page.\n *\n * @module tool_templatelibrary/display\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates', 'core/config', 'core/str'],\n function($, ajax, log, notification, templates, config, str) {\n\n /**\n * Search through a template for a template docs comment.\n *\n * @param {String} templateSource The raw template\n * @param {String} templateName The name of the template used to search for docs tag\n * @return {String|boolean} the correct comment or false\n */\n var findDocsSection = function(templateSource, templateName) {\n\n if (!templateSource) {\n return false;\n }\n // Find the comment section marked with @template component/template.\n var marker = \"@template \" + templateName,\n i = 0,\n sections = [];\n\n sections = templateSource.match(/{{!([\\s\\S]*?)}}/g);\n\n // If no sections match - show the entire file.\n if (sections !== null) {\n for (i = 0; i < sections.length; i++) {\n var section = sections[i];\n var start = section.indexOf(marker);\n if (start !== -1) {\n // Remove {{! and }} from start and end.\n var offset = start + marker.length + 1;\n section = section.substr(offset, section.length - 2 - offset);\n return section;\n }\n }\n }\n // No matching comment.\n return false;\n };\n\n /**\n * Handle a template loaded response.\n *\n * @param {String} templateName The template name\n * @param {String} source The template source\n * @param {String} originalSource The original template source (not theme overridden)\n */\n var templateLoaded = function(templateName, source, originalSource) {\n str.get_string('templateselected', 'tool_templatelibrary', templateName).done(function(s) {\n $('[data-region=\"displaytemplateheader\"]').text(s);\n }).fail(notification.exception);\n\n // Find the comment section marked with @template component/template.\n var docs = findDocsSection(source, templateName);\n\n if (docs === false) {\n // Docs was not in theme template, try original.\n docs = findDocsSection(originalSource, templateName);\n }\n\n // If we found a docs section, limit the template library to showing this section.\n if (docs) {\n source = docs;\n }\n\n $('[data-region=\"displaytemplatesource\"]').text(source);\n\n // Now search the text for a json example.\n\n var example = source.match(/Example context \\(json\\):([\\s\\S]*)/);\n var context = false;\n if (example) {\n var rawJSON = example[1].trim();\n try {\n context = $.parseJSON(rawJSON);\n } catch (e) {\n log.debug('Could not parse json example context for template.');\n log.debug(e);\n }\n }\n if (context) {\n templates.render(templateName, context).done(function(html, js) {\n templates.replaceNodeContents($('[data-region=\"displaytemplateexample\"]'), html, js);\n }).fail(notification.exception);\n } else {\n str.get_string('templatehasnoexample', 'tool_templatelibrary').done(function(s) {\n $('[data-region=\"displaytemplateexample\"]').text(s);\n }).fail(notification.exception);\n }\n };\n\n /**\n * Load the a template source from Moodle.\n *\n * @param {String} templateName\n */\n var loadTemplate = function(templateName) {\n var parts = templateName.split('/');\n var component = parts.shift();\n var name = parts.join('/');\n\n var promises = ajax.call([{\n methodname: 'core_output_load_template',\n args: {\n component: component,\n template: name,\n themename: config.theme,\n includecomments: true\n }\n }, {\n methodname: 'tool_templatelibrary_load_canonical_template',\n args: {\n component: component,\n template: name\n }\n }], true, false);\n\n // When returns a new promise that is resolved when all the passed in promises are resolved.\n // The arguments to the done become the values of each resolved promise.\n $.when.apply($, promises)\n .done(function(source, originalSource) {\n templateLoaded(templateName, source, originalSource);\n })\n .fail(notification.exception);\n };\n\n // Add the event listeners.\n $('[data-region=\"list-templates\"]').on('click', '[data-templatename]', function(e) {\n var templatename = $(this).data('templatename');\n e.preventDefault();\n loadTemplate(templatename);\n });\n\n // This module does not expose anything.\n return {};\n});\n"],"names":["define","$","ajax","log","notification","templates","config","str","findDocsSection","templateSource","templateName","sections","marker","i","match","length","section","start","indexOf","offset","substr","loadTemplate","parts","split","component","shift","name","join","promises","call","methodname","args","template","themename","theme","includecomments","when","apply","done","source","originalSource","get_string","s","text","fail","exception","docs","example","context","rawJSON","trim","parseJSON","e","debug","render","html","js","replaceNodeContents","templateLoaded","on","templatename","this","data","preventDefault"],"mappings":";;;;;;;AAsBAA,sCAAO,CAAC,SAAU,YAAa,WAAY,oBAAqB,iBAAkB,cAAe,aAC1F,SAASC,EAAGC,KAAMC,IAAKC,aAAcC,UAAWC,OAAQC,SASvDC,gBAAkB,SAASC,eAAgBC,kBAEtCD,sBACM,MAKPE,SAFAC,OAAS,aAAeF,aACxBG,EAAI,KAMS,QAHjBF,SAAWF,eAAeK,MAAM,yBAIvBD,EAAI,EAAGA,EAAIF,SAASI,OAAQF,IAAK,KAC9BG,QAAUL,SAASE,GACnBI,MAAQD,QAAQE,QAAQN,YACb,IAAXK,MAAc,KAEVE,OAASF,MAAQL,OAAOG,OAAS,SACrCC,QAAUA,QAAQI,OAAOD,OAAQH,QAAQD,OAAS,EAAII,gBAM3D,GA2DPE,aAAe,SAASX,kBACpBY,MAAQZ,aAAaa,MAAM,KAC3BC,UAAYF,MAAMG,QAClBC,KAAOJ,MAAMK,KAAK,KAElBC,SAAW1B,KAAK2B,KAAK,CAAC,CACtBC,WAAY,4BACZC,KAAM,CACEP,UAAWA,UACXQ,SAAUN,KACVO,UAAW3B,OAAO4B,MAClBC,iBAAiB,IAE1B,CACCL,WAAY,+CACZC,KAAM,CACEP,UAAWA,UACXQ,SAAUN,SAElB,GAAM,GAIVzB,EAAEmC,KAAKC,MAAMpC,EAAG2B,UACXU,MAAK,SAASC,OAAQC,iBAzEV,SAAS9B,aAAc6B,OAAQC,gBAChDjC,IAAIkC,WAAW,mBAAoB,uBAAwB/B,cAAc4B,MAAK,SAASI,GACnFzC,EAAE,yCAAyC0C,KAAKD,MACjDE,KAAKxC,aAAayC,eAGjBC,KAAOtC,gBAAgB+B,OAAQ7B,eAEtB,IAAToC,OAEAA,KAAOtC,gBAAgBgC,eAAgB9B,eAIvCoC,OACAP,OAASO,MAGb7C,EAAE,yCAAyC0C,KAAKJ,YAI5CQ,QAAUR,OAAOzB,MAAM,sCACvBkC,SAAU,KACVD,QAAS,KACLE,QAAUF,QAAQ,GAAGG,WAErBF,QAAU/C,EAAEkD,UAAUF,SACxB,MAAOG,GACLjD,IAAIkD,MAAM,sDACVlD,IAAIkD,MAAMD,IAGdJ,QACA3C,UAAUiD,OAAO5C,aAAcsC,SAASV,MAAK,SAASiB,KAAMC,IACxDnD,UAAUoD,oBAAoBxD,EAAE,0CAA2CsD,KAAMC,OAClFZ,KAAKxC,aAAayC,WAErBtC,IAAIkC,WAAW,uBAAwB,wBAAwBH,MAAK,SAASI,GACzEzC,EAAE,0CAA0C0C,KAAKD,MAClDE,KAAKxC,aAAayC,WAkCnBa,CAAehD,aAAc6B,OAAQC,mBAEtCI,KAAKxC,aAAayC,mBAI3B5C,EAAE,kCAAkC0D,GAAG,QAAS,uBAAuB,SAASP,OACxEQ,aAAe3D,EAAE4D,MAAMC,KAAK,gBAChCV,EAAEW,iBACF1C,aAAauC,iBAIV"}
\ No newline at end of file
diff --git a/admin/tool/templatelibrary/amd/build/search.min.js b/admin/tool/templatelibrary/amd/build/search.min.js
index 9645fa6341e..74919611155 100644
--- a/admin/tool/templatelibrary/amd/build/search.min.js
+++ b/admin/tool/templatelibrary/amd/build/search.min.js
@@ -1,2 +1,10 @@
-define ("tool_templatelibrary/search",["jquery","core/ajax","core/log","core/notification","core/templates","core/config"],function(a,b,c,d,e,f){var g=function(b){e.render("tool_templatelibrary/search_results",{templates:b}).done(function(b,c){e.replaceNode(a("[data-region=\"searchresults\"]"),b,c)}).fail(d.exception)},h=function(c){var e=a("[data-field=\"component\"]").val(),f=a("[data-region=\"list-templates\"] [data-region=\"input\"]").val();if(""!==f){a("[data-region=\"list-templates\"] [data-action=\"clearsearch\"]").removeClass("d-none")}else{a("[data-region=\"list-templates\"] [data-action=\"clearsearch\"]").addClass("d-none")}b.call([{methodname:"tool_templatelibrary_list_templates",args:{component:e,search:f,themename:c},done:g,fail:d.exception}],!0,!1)},i=null,j=function(a,b){if(null!==i){window.clearTimeout(i)}i=window.setTimeout(function(){a();i=null},b)},k=function(){j(h.bind(this,f.theme),400)};a("[data-region=\"list-templates\"]").on("change","[data-field=\"component\"]",k);a("[data-region=\"list-templates\"]").on("input","[data-region=\"input\"]",k);a("[data-action=\"clearsearch\"]").on("click",function(){a("[data-region=\"input\"]").val("");h(f.theme);a(this).addClass("d-none")});h(f.theme);return{}});
-//# sourceMappingURL=search.min.js.map
+/**
+ * This module adds ajax search functions to the template library page.
+ *
+ * @module tool_templatelibrary/search
+ * @copyright 2015 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("tool_templatelibrary/search",["jquery","core/ajax","core/log","core/notification","core/templates","core/config"],(function($,ajax,log,notification,templates,config){var reloadListTemplate=function(templateList){templates.render("tool_templatelibrary/search_results",{templates:templateList}).done((function(result,js){templates.replaceNode($('[data-region="searchresults"]'),result,js)})).fail(notification.exception)},refreshSearch=function(themename){var componentStr=$('[data-field="component"]').val(),searchStr=$('[data-region="list-templates"] [data-region="input"]').val();""!==searchStr?$('[data-region="list-templates"] [data-action="clearsearch"]').removeClass("d-none"):$('[data-region="list-templates"] [data-action="clearsearch"]').addClass("d-none"),ajax.call([{methodname:"tool_templatelibrary_list_templates",args:{component:componentStr,search:searchStr,themename:themename},done:reloadListTemplate,fail:notification.exception}],!0,!1)},throttle=null,changeHandler=function(){var callback,delay;callback=refreshSearch.bind(this,config.theme),delay=400,null!==throttle&&window.clearTimeout(throttle),throttle=window.setTimeout((function(){callback(),throttle=null}),delay)};return $('[data-region="list-templates"]').on("change",'[data-field="component"]',changeHandler),$('[data-region="list-templates"]').on("input",'[data-region="input"]',changeHandler),$('[data-action="clearsearch"]').on("click",(function(){$('[data-region="input"]').val(""),refreshSearch(config.theme),$(this).addClass("d-none")})),refreshSearch(config.theme),{}}));
+
+//# sourceMappingURL=search.min.js.map
\ No newline at end of file
diff --git a/admin/tool/templatelibrary/amd/build/search.min.js.map b/admin/tool/templatelibrary/amd/build/search.min.js.map
index 7d606eaf503..51ef5370a44 100644
--- a/admin/tool/templatelibrary/amd/build/search.min.js.map
+++ b/admin/tool/templatelibrary/amd/build/search.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/search.js"],"names":["define","$","ajax","log","notification","templates","config","reloadListTemplate","templateList","render","done","result","js","replaceNode","fail","exception","refreshSearch","themename","componentStr","val","searchStr","removeClass","addClass","call","methodname","args","component","search","throttle","queueRefresh","callback","delay","window","clearTimeout","setTimeout","changeHandler","bind","theme","on"],"mappings":"AAsBAA,OAAM,+BAAC,CAAC,QAAD,CAAW,WAAX,CAAwB,UAAxB,CAAoC,mBAApC,CAAyD,gBAAzD,CAA2E,aAA3E,CAAD,CACC,SAASC,CAAT,CAAYC,CAAZ,CAAkBC,CAAlB,CAAuBC,CAAvB,CAAqCC,CAArC,CAAgDC,CAAhD,CAAwD,IAQvDC,CAAAA,CAAkB,CAAG,SAASC,CAAT,CAAuB,CAC5CH,CAAS,CAACI,MAAV,CAAiB,qCAAjB,CAAwD,CAACJ,SAAS,CAAEG,CAAZ,CAAxD,EACKE,IADL,CACU,SAASC,CAAT,CAAiBC,CAAjB,CAAqB,CACvBP,CAAS,CAACQ,WAAV,CAAsBZ,CAAC,CAAC,iCAAD,CAAvB,CAA0DU,CAA1D,CAAkEC,CAAlE,CACH,CAHL,EAGOE,IAHP,CAGYV,CAAY,CAACW,SAHzB,CAIH,CAb0D,CAqBvDC,CAAa,CAAG,SAASC,CAAT,CAAoB,IAChCC,CAAAA,CAAY,CAAGjB,CAAC,CAAC,4BAAD,CAAD,CAA8BkB,GAA9B,EADiB,CAEhCC,CAAS,CAAGnB,CAAC,CAAC,0DAAD,CAAD,CAA0DkB,GAA1D,EAFoB,CAIpC,GAAkB,EAAd,GAAAC,CAAJ,CAAsB,CAClBnB,CAAC,CAAC,gEAAD,CAAD,CAAgEoB,WAAhE,CAA4E,QAA5E,CACH,CAFD,IAEO,CACHpB,CAAC,CAAC,gEAAD,CAAD,CAAgEqB,QAAhE,CAAyE,QAAzE,CACH,CAGDpB,CAAI,CAACqB,IAAL,CAAU,CACN,CAACC,UAAU,CAAE,qCAAb,CACEC,IAAI,CAAE,CAACC,SAAS,CAAER,CAAZ,CAA0BS,MAAM,CAAEP,CAAlC,CAA6CH,SAAS,CAAEA,CAAxD,CADR,CAEEP,IAAI,CAAEH,CAFR,CAGEO,IAAI,CAAEV,CAAY,CAACW,SAHrB,CADM,CAAV,OAMH,CAtC0D,CAwCvDa,CAAQ,CAAG,IAxC4C,CAkDvDC,CAAY,CAAG,SAASC,CAAT,CAAmBC,CAAnB,CAA0B,CACzC,GAAiB,IAAb,GAAAH,CAAJ,CAAuB,CACnBI,MAAM,CAACC,YAAP,CAAoBL,CAApB,CACH,CAEDA,CAAQ,CAAGI,MAAM,CAACE,UAAP,CAAkB,UAAW,CACpCJ,CAAQ,GACRF,CAAQ,CAAG,IACd,CAHU,CAGRG,CAHQ,CAId,CA3D0D,CA6DvDI,CAAa,CAAG,UAAW,CAC3BN,CAAY,CAACb,CAAa,CAACoB,IAAd,CAAmB,IAAnB,CAAyB9B,CAAM,CAAC+B,KAAhC,CAAD,CAAyC,GAAzC,CACf,CA/D0D,CAiE3DpC,CAAC,CAAC,kCAAD,CAAD,CAAoCqC,EAApC,CAAuC,QAAvC,CAAiD,4BAAjD,CAA6EH,CAA7E,EACAlC,CAAC,CAAC,kCAAD,CAAD,CAAoCqC,EAApC,CAAuC,OAAvC,CAAgD,yBAAhD,CAAyEH,CAAzE,EACAlC,CAAC,CAAC,+BAAD,CAAD,CAAiCqC,EAAjC,CAAoC,OAApC,CAA6C,UAAW,CACpDrC,CAAC,CAAC,yBAAD,CAAD,CAA2BkB,GAA3B,CAA+B,EAA/B,EACAH,CAAa,CAACV,CAAM,CAAC+B,KAAR,CAAb,CACApC,CAAC,CAAC,IAAD,CAAD,CAAQqB,QAAR,CAAiB,QAAjB,CACH,CAJD,EAMAN,CAAa,CAACV,CAAM,CAAC+B,KAAR,CAAb,CACA,MAAO,EACV,CA5EK,CAAN","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 .\n\n/**\n * This module adds ajax search functions to the template library page.\n *\n * @module tool_templatelibrary/search\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates', 'core/config'],\n function($, ajax, log, notification, templates, config) {\n\n /**\n * The ajax call has returned with a new list of templates.\n *\n * @method reloadListTemplate\n * @param {String[]} templateList List of template ids.\n */\n var reloadListTemplate = function(templateList) {\n templates.render('tool_templatelibrary/search_results', {templates: templateList})\n .done(function(result, js) {\n templates.replaceNode($('[data-region=\"searchresults\"]'), result, js);\n }).fail(notification.exception);\n };\n\n /**\n * Get the current values for the form inputs and refresh the list of matching templates.\n *\n * @method refreshSearch\n * @param {String} themename The naeme of the theme.\n */\n var refreshSearch = function(themename) {\n var componentStr = $('[data-field=\"component\"]').val();\n var searchStr = $('[data-region=\"list-templates\"] [data-region=\"input\"]').val();\n\n if (searchStr !== '') {\n $('[data-region=\"list-templates\"] [data-action=\"clearsearch\"]').removeClass('d-none');\n } else {\n $('[data-region=\"list-templates\"] [data-action=\"clearsearch\"]').addClass('d-none');\n }\n\n // Trigger the search.\n ajax.call([\n {methodname: 'tool_templatelibrary_list_templates',\n args: {component: componentStr, search: searchStr, themename: themename},\n done: reloadListTemplate,\n fail: notification.exception}\n ], true, false);\n };\n\n var throttle = null;\n\n /**\n * Call the specified function after a delay. If this function is called again before the function is executed,\n * the function will only be executed once.\n *\n * @method queueRefresh\n * @param {function} callback\n * @param {Number} delay The time in milliseconds to delay.\n */\n var queueRefresh = function(callback, delay) {\n if (throttle !== null) {\n window.clearTimeout(throttle);\n }\n\n throttle = window.setTimeout(function() {\n callback();\n throttle = null;\n }, delay);\n };\n\n var changeHandler = function() {\n queueRefresh(refreshSearch.bind(this, config.theme), 400);\n };\n // Add change handlers to refresh the list.\n $('[data-region=\"list-templates\"]').on('change', '[data-field=\"component\"]', changeHandler);\n $('[data-region=\"list-templates\"]').on('input', '[data-region=\"input\"]', changeHandler);\n $('[data-action=\"clearsearch\"]').on('click', function() {\n $('[data-region=\"input\"]').val('');\n refreshSearch(config.theme);\n $(this).addClass('d-none');\n });\n\n refreshSearch(config.theme);\n return {};\n});\n"],"file":"search.min.js"}
\ No newline at end of file
+{"version":3,"file":"search.min.js","sources":["../src/search.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 .\n\n/**\n * This module adds ajax search functions to the template library page.\n *\n * @module tool_templatelibrary/search\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates', 'core/config'],\n function($, ajax, log, notification, templates, config) {\n\n /**\n * The ajax call has returned with a new list of templates.\n *\n * @method reloadListTemplate\n * @param {String[]} templateList List of template ids.\n */\n var reloadListTemplate = function(templateList) {\n templates.render('tool_templatelibrary/search_results', {templates: templateList})\n .done(function(result, js) {\n templates.replaceNode($('[data-region=\"searchresults\"]'), result, js);\n }).fail(notification.exception);\n };\n\n /**\n * Get the current values for the form inputs and refresh the list of matching templates.\n *\n * @method refreshSearch\n * @param {String} themename The naeme of the theme.\n */\n var refreshSearch = function(themename) {\n var componentStr = $('[data-field=\"component\"]').val();\n var searchStr = $('[data-region=\"list-templates\"] [data-region=\"input\"]').val();\n\n if (searchStr !== '') {\n $('[data-region=\"list-templates\"] [data-action=\"clearsearch\"]').removeClass('d-none');\n } else {\n $('[data-region=\"list-templates\"] [data-action=\"clearsearch\"]').addClass('d-none');\n }\n\n // Trigger the search.\n ajax.call([\n {methodname: 'tool_templatelibrary_list_templates',\n args: {component: componentStr, search: searchStr, themename: themename},\n done: reloadListTemplate,\n fail: notification.exception}\n ], true, false);\n };\n\n var throttle = null;\n\n /**\n * Call the specified function after a delay. If this function is called again before the function is executed,\n * the function will only be executed once.\n *\n * @method queueRefresh\n * @param {function} callback\n * @param {Number} delay The time in milliseconds to delay.\n */\n var queueRefresh = function(callback, delay) {\n if (throttle !== null) {\n window.clearTimeout(throttle);\n }\n\n throttle = window.setTimeout(function() {\n callback();\n throttle = null;\n }, delay);\n };\n\n var changeHandler = function() {\n queueRefresh(refreshSearch.bind(this, config.theme), 400);\n };\n // Add change handlers to refresh the list.\n $('[data-region=\"list-templates\"]').on('change', '[data-field=\"component\"]', changeHandler);\n $('[data-region=\"list-templates\"]').on('input', '[data-region=\"input\"]', changeHandler);\n $('[data-action=\"clearsearch\"]').on('click', function() {\n $('[data-region=\"input\"]').val('');\n refreshSearch(config.theme);\n $(this).addClass('d-none');\n });\n\n refreshSearch(config.theme);\n return {};\n});\n"],"names":["define","$","ajax","log","notification","templates","config","reloadListTemplate","templateList","render","done","result","js","replaceNode","fail","exception","refreshSearch","themename","componentStr","val","searchStr","removeClass","addClass","call","methodname","args","component","search","throttle","changeHandler","callback","delay","bind","this","theme","window","clearTimeout","setTimeout","on"],"mappings":";;;;;;;AAsBAA,qCAAO,CAAC,SAAU,YAAa,WAAY,oBAAqB,iBAAkB,gBAC3E,SAASC,EAAGC,KAAMC,IAAKC,aAAcC,UAAWC,YAQ/CC,mBAAqB,SAASC,cAC9BH,UAAUI,OAAO,sCAAuC,CAACJ,UAAWG,eAC/DE,MAAK,SAASC,OAAQC,IACnBP,UAAUQ,YAAYZ,EAAE,iCAAkCU,OAAQC,OACnEE,KAAKV,aAAaW,YASzBC,cAAgB,SAASC,eACrBC,aAAejB,EAAE,4BAA4BkB,MAC7CC,UAAYnB,EAAE,wDAAwDkB,MAExD,KAAdC,UACAnB,EAAE,8DAA8DoB,YAAY,UAE5EpB,EAAE,8DAA8DqB,SAAS,UAI7EpB,KAAKqB,KAAK,CACN,CAACC,WAAY,sCACXC,KAAM,CAACC,UAAWR,aAAcS,OAAQP,UAAWH,UAAWA,WAC9DP,KAAMH,mBACNO,KAAMV,aAAaW,aACtB,GAAM,IAGTa,SAAW,KAqBXC,cAAgB,WAXD,IAASC,SAAUC,MAAVD,SAYXd,cAAcgB,KAAKC,KAAM3B,OAAO4B,OAZXH,MAYmB,IAXpC,OAAbH,UACAO,OAAOC,aAAaR,UAGxBA,SAAWO,OAAOE,YAAW,WACzBP,WACAF,SAAW,OACZG,eAOP9B,EAAE,kCAAkCqC,GAAG,SAAU,2BAA4BT,eAC7E5B,EAAE,kCAAkCqC,GAAG,QAAS,wBAAyBT,eACzE5B,EAAE,+BAA+BqC,GAAG,SAAS,WACzCrC,EAAE,yBAAyBkB,IAAI,IAC/BH,cAAcV,OAAO4B,OACrBjC,EAAEgC,MAAMX,SAAS,aAGrBN,cAAcV,OAAO4B,OACd"}
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/events.min.js b/admin/tool/usertours/amd/build/events.min.js
index c11e5f9b53f..9ca58ad87c0 100644
--- a/admin/tool/usertours/amd/build/events.min.js
+++ b/admin/tool/usertours/amd/build/events.min.js
@@ -1,2 +1,3 @@
-define ("tool_usertours/events",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.eventTypes=void 0;a.eventTypes={stepRender:"tool_usertours/stepRender",stepRendered:"tool_usertours/stepRendered",tourStart:"tool_usertours/tourStart",tourStarted:"tool_usertours/tourStarted",tourEnd:"tool_usertours/tourEnd",tourEnded:"tool_usertours/tourEnded",stepHide:"tool_usertours/stepHide",stepHidden:"tool_usertours/stepHidden"}});
-//# sourceMappingURL=events.min.js.map
+define("tool_usertours/events",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.eventTypes=void 0;_exports.eventTypes={stepRender:"tool_usertours/stepRender",stepRendered:"tool_usertours/stepRendered",tourStart:"tool_usertours/tourStart",tourStarted:"tool_usertours/tourStarted",tourEnd:"tool_usertours/tourEnd",tourEnded:"tool_usertours/tourEnded",stepHide:"tool_usertours/stepHide",stepHidden:"tool_usertours/stepHidden"}}));
+
+//# sourceMappingURL=events.min.js.map
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/events.min.js.map b/admin/tool/usertours/amd/build/events.min.js.map
index aa04927359e..33b8481c3fb 100644
--- a/admin/tool/usertours/amd/build/events.min.js.map
+++ b/admin/tool/usertours/amd/build/events.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/events.js"],"names":["stepRender","stepRendered","tourStart","tourStarted","tourEnd","tourEnded","stepHide","stepHidden"],"mappings":"uJA6C0B,CAYtBA,UAAU,CAAE,2BAZU,CAuBtBC,YAAY,CAAE,6BAvBQ,CAoCtBC,SAAS,CAAE,0BApCW,CA8CtBC,WAAW,CAAE,4BA9CS,CA0DtBC,OAAO,CAAE,wBA1Da,CAoEtBC,SAAS,CAAE,0BApEW,CAgFtBC,QAAQ,CAAE,yBAhFY,CA0FtBC,UAAU,CAAE,2BA1FU,C","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 .\n\n/**\n * Javascript events for the `tool_usertours` subsystem.\n *\n * @module tool_usertours/events\n * @copyright 2021 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n *\n * @example
Example of listening to a step rendering event and cancelling it.
\n * import {eventTypes as userTourEvents} from 'tool_usertours/events';\n *\n * document.addEventListener(userTourEvents.stepRender, e => {\n * console.log(e.detail.tour); // The Tour instance\n * e.preventDefault();\n * });\n */\n\n/**\n * Events for the component.\n *\n * @constant\n * @property {object} eventTypes\n * @property {String} eventTypes.stepRender See {@link event:tool_usertours/stepRender}\n * @property {String} eventTypes.stepRendered See {@link event:tool_usertours/stepRendered}\n * @property {String} eventTypes.tourStart See {@link event:tool_usertours/tourStart}\n * @property {String} eventTypes.tourStarted See {@link event:tool_usertours/tourStarted}\n * @property {String} eventTypes.tourEnd See {@link event:tool_usertours/tourEnd}\n * @property {String} eventTypes.tourEnded See {@link event:tool_usertours/tourEnded}\n * @property {String} eventTypes.stepHide See {@link event:tool_usertours/stepHide}\n * @property {String} eventTypes.stepHidden See {@link event:tool_usertours/stepHidden}\n */\nexport const eventTypes = {\n /**\n * An event triggered before a user tour step is rendered.\n *\n * This event is cancellable.\n *\n * @event tool_usertours/stepRender\n * @type {CustomEvent}\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @property {object} detail.stepConfig\n */\n stepRender: 'tool_usertours/stepRender',\n\n /**\n * An event triggered after a user tour step has been rendered.\n *\n * @event tool_usertours/stepRendered\n * @type {CustomEvent}\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @property {object} detail.stepConfig\n */\n stepRendered: 'tool_usertours/stepRendered',\n\n /**\n * An event triggered before a user tour starts.\n *\n * This event is cancellable.\n *\n * @event tool_usertours/tourStart\n * @type {CustomEvent}\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @property {Number} detail.startAt\n */\n tourStart: 'tool_usertours/tourStart',\n\n /**\n * An event triggered after a user tour has started.\n *\n * @event tool_usertours/tourStarted\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @type {CustomEvent}\n */\n tourStarted: 'tool_usertours/tourStarted',\n\n /**\n * An event triggered before a tour ends.\n *\n * This event is cancellable.\n *\n * @event tool_usertours/tourEnd\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @type {CustomEvent}\n */\n tourEnd: 'tool_usertours/tourEnd',\n\n /**\n * An event triggered after a tour has ended.\n *\n * @event tool_usertours/tourEnded\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @type {CustomEvent}\n */\n tourEnded: 'tool_usertours/tourEnded',\n\n /**\n * An event triggered before a step is hidden.\n *\n * This event is cancellable.\n *\n * @event tool_usertours/stepHide\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @type {CustomEvent}\n */\n stepHide: 'tool_usertours/stepHide',\n\n /**\n * An event triggered after a step has been hidden.\n *\n * @event tool_usertours/stepHidden\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @type {CustomEvent}\n */\n stepHidden: 'tool_usertours/stepHidden',\n};\n"],"file":"events.min.js"}
\ No newline at end of file
+{"version":3,"file":"events.min.js","sources":["../src/events.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 .\n\n/**\n * Javascript events for the `tool_usertours` subsystem.\n *\n * @module tool_usertours/events\n * @copyright 2021 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n *\n * @example
Example of listening to a step rendering event and cancelling it.
\n * import {eventTypes as userTourEvents} from 'tool_usertours/events';\n *\n * document.addEventListener(userTourEvents.stepRender, e => {\n * console.log(e.detail.tour); // The Tour instance\n * e.preventDefault();\n * });\n */\n\n/**\n * Events for the component.\n *\n * @constant\n * @property {object} eventTypes\n * @property {String} eventTypes.stepRender See {@link event:tool_usertours/stepRender}\n * @property {String} eventTypes.stepRendered See {@link event:tool_usertours/stepRendered}\n * @property {String} eventTypes.tourStart See {@link event:tool_usertours/tourStart}\n * @property {String} eventTypes.tourStarted See {@link event:tool_usertours/tourStarted}\n * @property {String} eventTypes.tourEnd See {@link event:tool_usertours/tourEnd}\n * @property {String} eventTypes.tourEnded See {@link event:tool_usertours/tourEnded}\n * @property {String} eventTypes.stepHide See {@link event:tool_usertours/stepHide}\n * @property {String} eventTypes.stepHidden See {@link event:tool_usertours/stepHidden}\n */\nexport const eventTypes = {\n /**\n * An event triggered before a user tour step is rendered.\n *\n * This event is cancellable.\n *\n * @event tool_usertours/stepRender\n * @type {CustomEvent}\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @property {object} detail.stepConfig\n */\n stepRender: 'tool_usertours/stepRender',\n\n /**\n * An event triggered after a user tour step has been rendered.\n *\n * @event tool_usertours/stepRendered\n * @type {CustomEvent}\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @property {object} detail.stepConfig\n */\n stepRendered: 'tool_usertours/stepRendered',\n\n /**\n * An event triggered before a user tour starts.\n *\n * This event is cancellable.\n *\n * @event tool_usertours/tourStart\n * @type {CustomEvent}\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @property {Number} detail.startAt\n */\n tourStart: 'tool_usertours/tourStart',\n\n /**\n * An event triggered after a user tour has started.\n *\n * @event tool_usertours/tourStarted\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @type {CustomEvent}\n */\n tourStarted: 'tool_usertours/tourStarted',\n\n /**\n * An event triggered before a tour ends.\n *\n * This event is cancellable.\n *\n * @event tool_usertours/tourEnd\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @type {CustomEvent}\n */\n tourEnd: 'tool_usertours/tourEnd',\n\n /**\n * An event triggered after a tour has ended.\n *\n * @event tool_usertours/tourEnded\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @type {CustomEvent}\n */\n tourEnded: 'tool_usertours/tourEnded',\n\n /**\n * An event triggered before a step is hidden.\n *\n * This event is cancellable.\n *\n * @event tool_usertours/stepHide\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @type {CustomEvent}\n */\n stepHide: 'tool_usertours/stepHide',\n\n /**\n * An event triggered after a step has been hidden.\n *\n * @event tool_usertours/stepHidden\n * @property {object} detail\n * @property {tool_usertours/tour} detail.tour\n * @type {CustomEvent}\n */\n stepHidden: 'tool_usertours/stepHidden',\n};\n"],"names":["stepRender","stepRendered","tourStart","tourStarted","tourEnd","tourEnded","stepHide","stepHidden"],"mappings":"sKA6C0B,CAYtBA,WAAY,4BAWZC,aAAc,8BAadC,UAAW,2BAUXC,YAAa,6BAYbC,QAAS,yBAUTC,UAAW,2BAYXC,SAAU,0BAUVC,WAAY"}
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/filter_cssselector.min.js b/admin/tool/usertours/amd/build/filter_cssselector.min.js
index 6dbb873f9c9..551b50be739 100644
--- a/admin/tool/usertours/amd/build/filter_cssselector.min.js
+++ b/admin/tool/usertours/amd/build/filter_cssselector.min.js
@@ -1,2 +1,3 @@
-define ("tool_usertours/filter_cssselector",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.filterMatches=void 0;a.filterMatches=function filterMatches(a){var b=a.filtervalues.cssselector;if(b[0]){return!!document.querySelector(b[0])}return!0}});
-//# sourceMappingURL=filter_cssselector.min.js.map
+define("tool_usertours/filter_cssselector",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.filterMatches=void 0;_exports.filterMatches=function(tourConfig){let filterValues=tourConfig.filtervalues.cssselector;return!filterValues[0]||!!document.querySelector(filterValues[0])}}));
+
+//# sourceMappingURL=filter_cssselector.min.js.map
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/filter_cssselector.min.js.map b/admin/tool/usertours/amd/build/filter_cssselector.min.js.map
index 969f574c204..e29a30215d8 100644
--- a/admin/tool/usertours/amd/build/filter_cssselector.min.js.map
+++ b/admin/tool/usertours/amd/build/filter_cssselector.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/filter_cssselector.js"],"names":["filterMatches","tourConfig","filterValues","filtervalues","cssselector","document","querySelector"],"mappings":"yKA6B6B,QAAhBA,CAAAA,aAAgB,CAASC,CAAT,CAAqB,CAC9C,GAAIC,CAAAA,CAAY,CAAGD,CAAU,CAACE,YAAX,CAAwBC,WAA3C,CACA,GAAIF,CAAY,CAAC,CAAD,CAAhB,CAAqB,CACjB,MAAO,CAAC,CAACG,QAAQ,CAACC,aAAT,CAAuBJ,CAAY,CAAC,CAAD,CAAnC,CACZ,CAED,QACH,C","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 .\n\n/**\n * CSS selector client side filter.\n *\n * @module tool_usertours/filter_cssselector\n * @copyright 2020 The Open University\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Checks whether the configured CSS selector exists on this page.\n *\n * @param {array} tourConfig The tour configuration.\n * @returns {boolean}\n */\nexport const filterMatches = function(tourConfig) {\n let filterValues = tourConfig.filtervalues.cssselector;\n if (filterValues[0]) {\n return !!document.querySelector(filterValues[0]);\n }\n // If there is no CSS selector configured, this page matches.\n return true;\n};\n"],"file":"filter_cssselector.min.js"}
\ No newline at end of file
+{"version":3,"file":"filter_cssselector.min.js","sources":["../src/filter_cssselector.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 .\n\n/**\n * CSS selector client side filter.\n *\n * @module tool_usertours/filter_cssselector\n * @copyright 2020 The Open University\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Checks whether the configured CSS selector exists on this page.\n *\n * @param {array} tourConfig The tour configuration.\n * @returns {boolean}\n */\nexport const filterMatches = function(tourConfig) {\n let filterValues = tourConfig.filtervalues.cssselector;\n if (filterValues[0]) {\n return !!document.querySelector(filterValues[0]);\n }\n // If there is no CSS selector configured, this page matches.\n return true;\n};\n"],"names":["tourConfig","filterValues","filtervalues","cssselector","document","querySelector"],"mappings":"wLA6B6B,SAASA,gBAC9BC,aAAeD,WAAWE,aAAaC,mBACvCF,aAAa,MACJG,SAASC,cAAcJ,aAAa"}
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/managesteps.min.js b/admin/tool/usertours/amd/build/managesteps.min.js
index e566fba502f..4c8a4a1ebb4 100644
--- a/admin/tool/usertours/amd/build/managesteps.min.js
+++ b/admin/tool/usertours/amd/build/managesteps.min.js
@@ -1,2 +1,3 @@
-define ("tool_usertours/managesteps",["exports","core/prefetch","core/str","core/notification"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.setup=void 0;var e=function(a){var b=a.target.closest("[data-action=\"delete\"]");if(b){a.preventDefault();f(b.href)}},f=function(a){(0,d.confirm)((0,c.get_string)("confirmstepremovaltitle","tool_usertours"),(0,c.get_string)("confirmstepremovalquestion","tool_usertours"),(0,c.get_string)("yes","core"),(0,c.get_string)("no","core"),function(){window.location=a})};a.setup=function setup(){(0,b.prefetchStrings)("tool_usertours",["confirmstepremovaltitle","confirmstepremovalquestion"]);(0,b.prefetchStrings)("core",["yes","no"]);document.querySelector("body").addEventListener("click",e)}});
-//# sourceMappingURL=managesteps.min.js.map
+define("tool_usertours/managesteps",["exports","core/prefetch","core/str","core/notification"],(function(_exports,_prefetch,_str,_notification){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.setup=void 0;const removeStepHandler=e=>{const deleteButton=e.target.closest('[data-action="delete"]');deleteButton&&(e.preventDefault(),removeStepFromLink(deleteButton.href))},removeStepFromLink=targetUrl=>{(0,_notification.confirm)((0,_str.get_string)("confirmstepremovaltitle","tool_usertours"),(0,_str.get_string)("confirmstepremovalquestion","tool_usertours"),(0,_str.get_string)("yes","core"),(0,_str.get_string)("no","core"),(()=>{window.location=targetUrl}))};_exports.setup=()=>{(0,_prefetch.prefetchStrings)("tool_usertours",["confirmstepremovaltitle","confirmstepremovalquestion"]),(0,_prefetch.prefetchStrings)("core",["yes","no"]),document.querySelector("body").addEventListener("click",removeStepHandler)}}));
+
+//# sourceMappingURL=managesteps.min.js.map
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/managesteps.min.js.map b/admin/tool/usertours/amd/build/managesteps.min.js.map
index 7c8052becff..e42c77cbf65 100644
--- a/admin/tool/usertours/amd/build/managesteps.min.js.map
+++ b/admin/tool/usertours/amd/build/managesteps.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/managesteps.js"],"names":["removeStepHandler","e","deleteButton","target","closest","preventDefault","removeStepFromLink","href","targetUrl","window","location","setup","document","querySelector","addEventListener"],"mappings":"kMAgBMA,CAAAA,CAAiB,CAAG,SAAAC,CAAC,CAAI,CAC3B,GAAMC,CAAAA,CAAY,CAAGD,CAAC,CAACE,MAAF,CAASC,OAAT,CAAiB,0BAAjB,CAArB,CACA,GAAIF,CAAJ,CAAkB,CACdD,CAAC,CAACI,cAAF,GACAC,CAAkB,CAACJ,CAAY,CAACK,IAAd,CACrB,CACJ,C,CAQKD,CAAkB,CAAG,SAAAE,CAAS,CAAI,CACpC,cACI,iBAAU,yBAAV,CAAqC,gBAArC,CADJ,CAEI,iBAAU,4BAAV,CAAwC,gBAAxC,CAFJ,CAGI,iBAAU,KAAV,CAAiB,MAAjB,CAHJ,CAII,iBAAU,IAAV,CAAgB,MAAhB,CAJJ,CAKI,UAAM,CACFC,MAAM,CAACC,QAAP,CAAkBF,CACrB,CAPL,CASH,C,SAKoB,QAARG,CAAAA,KAAQ,EAAM,CACvB,sBAAgB,gBAAhB,CAAkC,CAC9B,yBAD8B,CAE9B,4BAF8B,CAAlC,EAKA,sBAAgB,MAAhB,CAAwB,CACpB,KADoB,CAEpB,IAFoB,CAAxB,EAKAC,QAAQ,CAACC,aAAT,CAAuB,MAAvB,EAA+BC,gBAA/B,CAAgD,OAAhD,CAAyDd,CAAzD,CACH,C","sourcesContent":["/**\n * Step management code.\n *\n * @module tool_usertours/managesteps\n * @copyright 2016 Andrew Nicols \n */\nimport {prefetchStrings} from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\nimport {confirm as confirmModal} from 'core/notification';\n\n/**\n * Handle step management actions.\n *\n * @param {Event} e\n * @private\n */\nconst removeStepHandler = e => {\n const deleteButton = e.target.closest('[data-action=\"delete\"]');\n if (deleteButton) {\n e.preventDefault();\n removeStepFromLink(deleteButton.href);\n }\n};\n\n/**\n * Handle removal of a step with confirmation.\n *\n * @param {string} targetUrl\n * @private\n */\nconst removeStepFromLink = targetUrl => {\n confirmModal(\n getString('confirmstepremovaltitle', 'tool_usertours'),\n getString('confirmstepremovalquestion', 'tool_usertours'),\n getString('yes', 'core'),\n getString('no', 'core'),\n () => {\n window.location = targetUrl;\n }\n );\n};\n\n/**\n * Set up the step management handlers.\n */\nexport const setup = () => {\n prefetchStrings('tool_usertours', [\n 'confirmstepremovaltitle',\n 'confirmstepremovalquestion',\n ]);\n\n prefetchStrings('core', [\n 'yes',\n 'no',\n ]);\n\n document.querySelector('body').addEventListener('click', removeStepHandler);\n};\n"],"file":"managesteps.min.js"}
\ No newline at end of file
+{"version":3,"file":"managesteps.min.js","sources":["../src/managesteps.js"],"sourcesContent":["/**\n * Step management code.\n *\n * @module tool_usertours/managesteps\n * @copyright 2016 Andrew Nicols \n */\nimport {prefetchStrings} from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\nimport {confirm as confirmModal} from 'core/notification';\n\n/**\n * Handle step management actions.\n *\n * @param {Event} e\n * @private\n */\nconst removeStepHandler = e => {\n const deleteButton = e.target.closest('[data-action=\"delete\"]');\n if (deleteButton) {\n e.preventDefault();\n removeStepFromLink(deleteButton.href);\n }\n};\n\n/**\n * Handle removal of a step with confirmation.\n *\n * @param {string} targetUrl\n * @private\n */\nconst removeStepFromLink = targetUrl => {\n confirmModal(\n getString('confirmstepremovaltitle', 'tool_usertours'),\n getString('confirmstepremovalquestion', 'tool_usertours'),\n getString('yes', 'core'),\n getString('no', 'core'),\n () => {\n window.location = targetUrl;\n }\n );\n};\n\n/**\n * Set up the step management handlers.\n */\nexport const setup = () => {\n prefetchStrings('tool_usertours', [\n 'confirmstepremovaltitle',\n 'confirmstepremovalquestion',\n ]);\n\n prefetchStrings('core', [\n 'yes',\n 'no',\n ]);\n\n document.querySelector('body').addEventListener('click', removeStepHandler);\n};\n"],"names":["removeStepHandler","e","deleteButton","target","closest","preventDefault","removeStepFromLink","href","targetUrl","window","location","document","querySelector","addEventListener"],"mappings":"oOAgBMA,kBAAoBC,UAChBC,aAAeD,EAAEE,OAAOC,QAAQ,0BAClCF,eACAD,EAAEI,iBACFC,mBAAmBJ,aAAaK,QAUlCD,mBAAqBE,uCAEnB,mBAAU,0BAA2B,mBACrC,mBAAU,6BAA8B,mBACxC,mBAAU,MAAO,SACjB,mBAAU,KAAM,SAChB,KACIC,OAAOC,SAAWF,6BAQT,mCACD,iBAAkB,CAC9B,0BACA,6DAGY,OAAQ,CACpB,MACA,OAGJG,SAASC,cAAc,QAAQC,iBAAiB,QAASb"}
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/managetours.min.js b/admin/tool/usertours/amd/build/managetours.min.js
index 5d502854d90..301aca618e5 100644
--- a/admin/tool/usertours/amd/build/managetours.min.js
+++ b/admin/tool/usertours/amd/build/managetours.min.js
@@ -1,2 +1,3 @@
-define ("tool_usertours/managetours",["exports","core/prefetch","core/str","core/notification"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.setup=void 0;var e=function(a){var b=a.target.closest("[data-action=\"delete\"]");if(b){a.preventDefault();f(b.href)}},f=function(a){(0,d.confirm)((0,c.get_string)("confirmtourremovaltitle","tool_usertours"),(0,c.get_string)("confirmtourremovalquestion","tool_usertours"),(0,c.get_string)("yes","core"),(0,c.get_string)("no","core"),function(){window.location=a})};a.setup=function setup(){(0,b.prefetchStrings)("tool_usertours",["confirmtourremovaltitle","confirmtourremovalquestion"]);(0,b.prefetchStrings)("core",["yes","no"]);document.querySelector("body").addEventListener("click",e)}});
-//# sourceMappingURL=managetours.min.js.map
+define("tool_usertours/managetours",["exports","core/prefetch","core/str","core/notification"],(function(_exports,_prefetch,_str,_notification){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.setup=void 0;const removeTourHandler=e=>{const deleteButton=e.target.closest('[data-action="delete"]');deleteButton&&(e.preventDefault(),removeTourFromLink(deleteButton.href))},removeTourFromLink=targetUrl=>{(0,_notification.confirm)((0,_str.get_string)("confirmtourremovaltitle","tool_usertours"),(0,_str.get_string)("confirmtourremovalquestion","tool_usertours"),(0,_str.get_string)("yes","core"),(0,_str.get_string)("no","core"),(()=>{window.location=targetUrl}))};_exports.setup=()=>{(0,_prefetch.prefetchStrings)("tool_usertours",["confirmtourremovaltitle","confirmtourremovalquestion"]),(0,_prefetch.prefetchStrings)("core",["yes","no"]),document.querySelector("body").addEventListener("click",removeTourHandler)}}));
+
+//# sourceMappingURL=managetours.min.js.map
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/managetours.min.js.map b/admin/tool/usertours/amd/build/managetours.min.js.map
index 35243deae2c..702cd1a661c 100644
--- a/admin/tool/usertours/amd/build/managetours.min.js.map
+++ b/admin/tool/usertours/amd/build/managetours.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/managetours.js"],"names":["removeTourHandler","e","deleteButton","target","closest","preventDefault","removeTourFromLink","href","targetUrl","window","location","setup","document","querySelector","addEventListener"],"mappings":"kMAgBMA,CAAAA,CAAiB,CAAG,SAAAC,CAAC,CAAI,CAC3B,GAAMC,CAAAA,CAAY,CAAGD,CAAC,CAACE,MAAF,CAASC,OAAT,CAAiB,0BAAjB,CAArB,CACA,GAAIF,CAAJ,CAAkB,CACdD,CAAC,CAACI,cAAF,GACAC,CAAkB,CAACJ,CAAY,CAACK,IAAd,CACrB,CACJ,C,CAQKD,CAAkB,CAAG,SAAAE,CAAS,CAAI,CACpC,cACI,iBAAU,yBAAV,CAAqC,gBAArC,CADJ,CAEI,iBAAU,4BAAV,CAAwC,gBAAxC,CAFJ,CAGI,iBAAU,KAAV,CAAiB,MAAjB,CAHJ,CAII,iBAAU,IAAV,CAAgB,MAAhB,CAJJ,CAKI,UAAM,CACFC,MAAM,CAACC,QAAP,CAAkBF,CACrB,CAPL,CASH,C,SAKoB,QAARG,CAAAA,KAAQ,EAAM,CACvB,sBAAgB,gBAAhB,CAAkC,CAC9B,yBAD8B,CAE9B,4BAF8B,CAAlC,EAKA,sBAAgB,MAAhB,CAAwB,CACpB,KADoB,CAEpB,IAFoB,CAAxB,EAKAC,QAAQ,CAACC,aAAT,CAAuB,MAAvB,EAA+BC,gBAA/B,CAAgD,OAAhD,CAAyDd,CAAzD,CACH,C","sourcesContent":["/**\n * Tour management code.\n *\n * @module tool_usertours/managetours\n * @copyright 2016 Andrew Nicols \n */\nimport {prefetchStrings} from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\nimport {confirm as confirmModal} from 'core/notification';\n\n/**\n * Handle tour management actions.\n *\n * @param {Event} e\n * @private\n */\nconst removeTourHandler = e => {\n const deleteButton = e.target.closest('[data-action=\"delete\"]');\n if (deleteButton) {\n e.preventDefault();\n removeTourFromLink(deleteButton.href);\n }\n};\n\n/**\n * Handle removal of a tour with confirmation.\n *\n * @param {string} targetUrl\n * @private\n */\nconst removeTourFromLink = targetUrl => {\n confirmModal(\n getString('confirmtourremovaltitle', 'tool_usertours'),\n getString('confirmtourremovalquestion', 'tool_usertours'),\n getString('yes', 'core'),\n getString('no', 'core'),\n () => {\n window.location = targetUrl;\n }\n );\n};\n\n/**\n * Set up the tour management handlers.\n */\nexport const setup = () => {\n prefetchStrings('tool_usertours', [\n 'confirmtourremovaltitle',\n 'confirmtourremovalquestion',\n ]);\n\n prefetchStrings('core', [\n 'yes',\n 'no',\n ]);\n\n document.querySelector('body').addEventListener('click', removeTourHandler);\n};\n"],"file":"managetours.min.js"}
\ No newline at end of file
+{"version":3,"file":"managetours.min.js","sources":["../src/managetours.js"],"sourcesContent":["/**\n * Tour management code.\n *\n * @module tool_usertours/managetours\n * @copyright 2016 Andrew Nicols \n */\nimport {prefetchStrings} from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\nimport {confirm as confirmModal} from 'core/notification';\n\n/**\n * Handle tour management actions.\n *\n * @param {Event} e\n * @private\n */\nconst removeTourHandler = e => {\n const deleteButton = e.target.closest('[data-action=\"delete\"]');\n if (deleteButton) {\n e.preventDefault();\n removeTourFromLink(deleteButton.href);\n }\n};\n\n/**\n * Handle removal of a tour with confirmation.\n *\n * @param {string} targetUrl\n * @private\n */\nconst removeTourFromLink = targetUrl => {\n confirmModal(\n getString('confirmtourremovaltitle', 'tool_usertours'),\n getString('confirmtourremovalquestion', 'tool_usertours'),\n getString('yes', 'core'),\n getString('no', 'core'),\n () => {\n window.location = targetUrl;\n }\n );\n};\n\n/**\n * Set up the tour management handlers.\n */\nexport const setup = () => {\n prefetchStrings('tool_usertours', [\n 'confirmtourremovaltitle',\n 'confirmtourremovalquestion',\n ]);\n\n prefetchStrings('core', [\n 'yes',\n 'no',\n ]);\n\n document.querySelector('body').addEventListener('click', removeTourHandler);\n};\n"],"names":["removeTourHandler","e","deleteButton","target","closest","preventDefault","removeTourFromLink","href","targetUrl","window","location","document","querySelector","addEventListener"],"mappings":"oOAgBMA,kBAAoBC,UAChBC,aAAeD,EAAEE,OAAOC,QAAQ,0BAClCF,eACAD,EAAEI,iBACFC,mBAAmBJ,aAAaK,QAUlCD,mBAAqBE,uCAEnB,mBAAU,0BAA2B,mBACrC,mBAAU,6BAA8B,mBACxC,mBAAU,MAAO,SACjB,mBAAU,KAAM,SAChB,KACIC,OAAOC,SAAWF,6BAQT,mCACD,iBAAkB,CAC9B,0BACA,6DAGY,OAAQ,CACpB,MACA,OAGJG,SAASC,cAAc,QAAQC,iBAAiB,QAASb"}
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/repository.min.js b/admin/tool/usertours/amd/build/repository.min.js
index 3f253d6e1c5..633fe176f16 100644
--- a/admin/tool/usertours/amd/build/repository.min.js
+++ b/admin/tool/usertours/amd/build/repository.min.js
@@ -1,2 +1,3 @@
-define ("tool_usertours/repository",["exports","core/ajax","core/config"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.markStepShown=a.fetchTour=a.markTourComplete=a.resetTourState=void 0;c=function(a){return a&&a.__esModule?a:{default:a}}(c);var d=function(a){return(0,b.call)([{methodname:"tool_usertours_reset_tour",args:{tourid:a,context:c.default.contextid,pageurl:window.location.href}}])[0]};a.resetTourState=d;var e=function(a,d,e){return(0,b.call)([{methodname:"tool_usertours_complete_tour",args:{stepid:a,stepindex:e,tourid:d,context:c.default.contextid,pageurl:window.location.href}}])[0]};a.markTourComplete=e;var f=function(a){return(0,b.call)([{methodname:"tool_usertours_fetch_and_start_tour",args:{tourid:a,context:c.default.contextid,pageurl:window.location.href}}])[0]};a.fetchTour=f;var g=function(a,d,e){return(0,b.call)([{methodname:"tool_usertours_step_shown",args:{tourid:d,stepid:a,stepindex:e,context:c.default.contextid,pageurl:window.location.href}}])[0]};a.markStepShown=g});
-//# sourceMappingURL=repository.min.js.map
+define("tool_usertours/repository",["exports","core/ajax","core/config"],(function(_exports,_ajax,_config){var obj;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.resetTourState=_exports.markTourComplete=_exports.markStepShown=_exports.fetchTour=void 0,_config=(obj=_config)&&obj.__esModule?obj:{default:obj};_exports.resetTourState=tourid=>(0,_ajax.call)([{methodname:"tool_usertours_reset_tour",args:{tourid:tourid,context:_config.default.contextid,pageurl:window.location.href}}])[0];_exports.markTourComplete=(stepid,tourid,stepindex)=>(0,_ajax.call)([{methodname:"tool_usertours_complete_tour",args:{stepid:stepid,stepindex:stepindex,tourid:tourid,context:_config.default.contextid,pageurl:window.location.href}}])[0];_exports.fetchTour=tourid=>(0,_ajax.call)([{methodname:"tool_usertours_fetch_and_start_tour",args:{tourid:tourid,context:_config.default.contextid,pageurl:window.location.href}}])[0];_exports.markStepShown=(stepid,tourid,stepindex)=>(0,_ajax.call)([{methodname:"tool_usertours_step_shown",args:{tourid:tourid,stepid:stepid,stepindex:stepindex,context:_config.default.contextid,pageurl:window.location.href}}])[0]}));
+
+//# sourceMappingURL=repository.min.js.map
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/repository.min.js.map b/admin/tool/usertours/amd/build/repository.min.js.map
index c2552d58fdc..8afcf933c7f 100644
--- a/admin/tool/usertours/amd/build/repository.min.js.map
+++ b/admin/tool/usertours/amd/build/repository.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/repository.js"],"names":["resetTourState","tourid","methodname","args","context","moodleConfig","contextid","pageurl","window","location","href","markTourComplete","stepid","stepindex","fetchTour","markStepShown"],"mappings":"+NAOA,uDAQO,GAAMA,CAAAA,CAAc,CAAG,SAAAC,CAAM,QAAI,WAAU,CAAC,CAC/CC,UAAU,CAAE,2BADmC,CAE/CC,IAAI,CAAE,CACFF,MAAM,CAANA,CADE,CAEFG,OAAO,CAAEC,UAAaC,SAFpB,CAGFC,OAAO,CAAEC,MAAM,CAACC,QAAP,CAAgBC,IAHvB,CAFyC,CAAD,CAAV,EAOpC,CAPoC,CAAJ,CAA7B,C,mBAiBA,GAAMC,CAAAA,CAAgB,CAAG,SAACC,CAAD,CAASX,CAAT,CAAiBY,CAAjB,QAA+B,WAAU,CAAC,CACtEX,UAAU,CAAE,8BAD0D,CAEtEC,IAAI,CAAE,CACFS,MAAM,CAANA,CADE,CAEFC,SAAS,CAAEA,CAFT,CAGFZ,MAAM,CAANA,CAHE,CAIFG,OAAO,CAAEC,UAAaC,SAJpB,CAKFC,OAAO,CAAEC,MAAM,CAACC,QAAP,CAAgBC,IALvB,CAFgE,CAAD,CAAV,EAS3D,CAT2D,CAA/B,CAAzB,C,qBAiBA,GAAMI,CAAAA,CAAS,CAAG,SAAAb,CAAM,QAAI,WAAU,CAAC,CAC1CC,UAAU,CAAE,qCAD8B,CAE1CC,IAAI,CAAE,CACFF,MAAM,CAANA,CADE,CAEFG,OAAO,CAAEC,UAAaC,SAFpB,CAGFC,OAAO,CAAEC,MAAM,CAACC,QAAP,CAAgBC,IAHvB,CAFoC,CAAD,CAAV,EAO/B,CAP+B,CAAJ,CAAxB,C,cAiBA,GAAMK,CAAAA,CAAa,CAAG,SAACH,CAAD,CAASX,CAAT,CAAiBY,CAAjB,QAA+B,WAAU,CAAC,CACnEX,UAAU,CAAE,2BADuD,CAEnEC,IAAI,CAAE,CACFF,MAAM,CAANA,CADE,CAEFW,MAAM,CAANA,CAFE,CAGFC,SAAS,CAATA,CAHE,CAIFT,OAAO,CAAEC,UAAaC,SAJpB,CAKFC,OAAO,CAAEC,MAAM,CAACC,QAAP,CAAgBC,IALvB,CAF6D,CAAD,CAAV,EASxD,CATwD,CAA/B,CAAtB,C","sourcesContent":["/**\n * Step management code.\n *\n * @module tool_usertours/managesteps\n * @copyright 2016 Andrew Nicols \n */\nimport {call as fetchMany} from 'core/ajax';\nimport moodleConfig from 'core/config';\n\n/**\n * Reset the tour state of the specified tour.\n *\n * @param {number} tourid\n * @return {Promise}\n */\nexport const resetTourState = tourid => fetchMany([{\n methodname: 'tool_usertours_reset_tour',\n args: {\n tourid,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n\n/**\n * Mark the specified tour as complete.\n *\n * @param {number} stepid\n * @param {number} tourid\n * @param {number} stepindex\n * @return {Promise}\n */\nexport const markTourComplete = (stepid, tourid, stepindex) => fetchMany([{\n methodname: 'tool_usertours_complete_tour',\n args: {\n stepid,\n stepindex: stepindex,\n tourid,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n\n/**\n * Fetch the specified tour.\n *\n * @param {number} tourid\n * @return {Promise}\n */\nexport const fetchTour = tourid => fetchMany([{\n methodname: 'tool_usertours_fetch_and_start_tour',\n args: {\n tourid,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n\n/**\n * Mark the specified step as having been shown.\n *\n * @param {number} stepid\n * @param {number} tourid\n * @param {number} stepindex\n * @return {Promise}\n */\nexport const markStepShown = (stepid, tourid, stepindex) => fetchMany([{\n methodname: 'tool_usertours_step_shown',\n args: {\n tourid,\n stepid,\n stepindex,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n"],"file":"repository.min.js"}
\ No newline at end of file
+{"version":3,"file":"repository.min.js","sources":["../src/repository.js"],"sourcesContent":["/**\n * Step management code.\n *\n * @module tool_usertours/managesteps\n * @copyright 2016 Andrew Nicols \n */\nimport {call as fetchMany} from 'core/ajax';\nimport moodleConfig from 'core/config';\n\n/**\n * Reset the tour state of the specified tour.\n *\n * @param {number} tourid\n * @return {Promise}\n */\nexport const resetTourState = tourid => fetchMany([{\n methodname: 'tool_usertours_reset_tour',\n args: {\n tourid,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n\n/**\n * Mark the specified tour as complete.\n *\n * @param {number} stepid\n * @param {number} tourid\n * @param {number} stepindex\n * @return {Promise}\n */\nexport const markTourComplete = (stepid, tourid, stepindex) => fetchMany([{\n methodname: 'tool_usertours_complete_tour',\n args: {\n stepid,\n stepindex: stepindex,\n tourid,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n\n/**\n * Fetch the specified tour.\n *\n * @param {number} tourid\n * @return {Promise}\n */\nexport const fetchTour = tourid => fetchMany([{\n methodname: 'tool_usertours_fetch_and_start_tour',\n args: {\n tourid,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n\n/**\n * Mark the specified step as having been shown.\n *\n * @param {number} stepid\n * @param {number} tourid\n * @param {number} stepindex\n * @return {Promise}\n */\nexport const markStepShown = (stepid, tourid, stepindex) => fetchMany([{\n methodname: 'tool_usertours_step_shown',\n args: {\n tourid,\n stepid,\n stepindex,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n"],"names":["tourid","methodname","args","context","moodleConfig","contextid","pageurl","window","location","href","stepid","stepindex"],"mappings":"8VAe8BA,SAAU,cAAU,CAAC,CAC/CC,WAAY,4BACZC,KAAM,CACFF,OAAAA,OACAG,QAASC,gBAAaC,UACtBC,QAASC,OAAOC,SAASC,SAE7B,6BAU4B,CAACC,OAAQV,OAAQW,aAAc,cAAU,CAAC,CACtEV,WAAY,+BACZC,KAAM,CACFQ,OAAAA,OACAC,UAAWA,UACXX,OAAAA,OACAG,QAASC,gBAAaC,UACtBC,QAASC,OAAOC,SAASC,SAE7B,sBAQqBT,SAAU,cAAU,CAAC,CAC1CC,WAAY,sCACZC,KAAM,CACFF,OAAAA,OACAG,QAASC,gBAAaC,UACtBC,QAASC,OAAOC,SAASC,SAE7B,0BAUyB,CAACC,OAAQV,OAAQW,aAAc,cAAU,CAAC,CACnEV,WAAY,4BACZC,KAAM,CACFF,OAAAA,OACAU,OAAAA,OACAC,UAAAA,UACAR,QAASC,gBAAaC,UACtBC,QAASC,OAAOC,SAASC,SAE7B"}
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/tour.min.js b/admin/tool/usertours/amd/build/tour.min.js
index 9aa89c46b95..031a72682b6 100644
--- a/admin/tool/usertours/amd/build/tour.min.js
+++ b/admin/tool/usertours/amd/build/tour.min.js
@@ -1,2 +1,3 @@
-define ("tool_usertours/tour",["exports","jquery","core/aria","core/popper","core/event_dispatcher","./events","core/str","core/prefetch"],function(a,b,c,d,e,f,g,h){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=k(b);c=j(c);d=k(d);var s;function i(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;i=function(){return a};return a}function j(a){if(a&&a.__esModule){return a}if(null===a||"object"!==n(a)&&"function"!=typeof a){return{default:a}}var b=i();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function k(a){return a&&a.__esModule?a:{default:a}}function l(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);if(b)d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable});c.push.apply(c,d)}return c}function m(a){for(var b=1,c;ba){return this.endTour()}var c=this.getStepConfig(a);if(null===c){return this.endTour()}return this._gotoStep(c,b)}},{key:"_gotoStep",value:function _gotoStep(a,b){if(!a){return this.endTour()}if("undefined"!=typeof a.delay&&a.delay&&!a.delayed){a.delayed=!0;window.setTimeout(this._gotoStep.bind(this),a.delay,a,b);return this}else if(!a.orphan&&!this.isStepActuallyVisible(a)){var d=-1==b?"getPreviousStepNumber":"getNextStepNumber";return this.gotoStep(this[d](a.stepNumber),b)}this.hide();var c=this.dispatchEvent(f.eventTypes.stepRender,{stepConfig:a},!0);if(!c.defaultPrevented){this.renderStep(a);this.dispatchEvent(f.eventTypes.stepRendered,{stepConfig:a})}return this}},{key:"getStepConfig",value:function getStepConfig(a){if(null===a||0>a||a>=this.steps.length){return null}var c=this.normalizeStepConfig(this.steps[a]);c=b.default.extend(c,{stepNumber:a});return c}},{key:"normalizeStepConfig",value:function normalizeStepConfig(a){if("undefined"!=typeof a.reflex&&"undefined"==typeof a.moveAfterClick){a.moveAfterClick=a.reflex}if("undefined"!=typeof a.element&&"undefined"==typeof a.target){a.target=a.element}if("undefined"!=typeof a.content&&"undefined"==typeof a.body){a.body=a.content}a=b.default.extend({},this.stepDefaults,a);a=b.default.extend({},{attachTo:a.target,attachPoint:"after"},a);if(a.attachTo){a.attachTo=(0,b.default)(a.attachTo).first()}return a}},{key:"getStepTarget",value:function getStepTarget(a){if(a.target){return(0,b.default)(a.target)}return null}},{key:"dispatchEvent",value:function dispatchEvent(a){var b=1").html(a.template).hide(),e=(0,b.default)("body, html").stop(!0,!0);if(this.isStepActuallyVisible(a)){var f=this.getStepTarget(a);if(f.parents("[data-usertour=\"scroller\"]").length){e=f.parents("[data-usertour=\"scroller\"]")}f.data("flexitour","target");var g=this.calculateZIndex(f);if(g){a.zIndex=g+1}if(a.zIndex){c.css("zIndex",a.zIndex+1)}this.positionBackdrop(a);(0,b.default)(document.body).append(c);this.currentStepNode=c;this.currentStepNode.css({top:0,left:0});e.animate({scrollTop:this.calculateScrollTop(a)}).promise().then(function(){this.positionStep(a);this.revealStep(a)}.bind(this)).catch(function(){})}else if(a.orphan){a.isOrphan=!0;a.attachTo=(0,b.default)("body").first();a.attachPoint="append";this.positionBackdrop(a);c.addClass("orphan");(0,b.default)(document.body).append(c);this.currentStepNode=c;this.currentStepNode.offset(this.calculateStepPositionInPage());this.currentStepNode.css("position","fixed");this.currentStepPopper=new d.default((0,b.default)("body"),this.currentStepNode[0],{removeOnDestroy:!0,placement:a.placement+"-start",arrowElement:"[data-role=\"arrow\"]",modifiers:{hide:{enabled:!1},applyStyle:{onLoad:null,enabled:!1}}});this.revealStep(a)}return this}},{key:"revealStep",value:function revealStep(a){this.currentStepNode.fadeIn("",b.default.proxy(function(){this.announceStep(a);this.currentStepNode.focus();window.setTimeout(b.default.proxy(function(){if(this.currentStepNode){this.currentStepNode.focus()}},this),100)},this));return this}},{key:"announceStep",value:function announceStep(a){var b="tour-step-"+this.tourName+"-"+a.stepNumber;this.currentStepNode.attr("id",b);var c=this.currentStepNode.find("[data-placeholder=\"body\"]").first();c.attr("id",b+"-body");c.attr("role","document");var d=this.currentStepNode.find("[data-placeholder=\"title\"]").first();d.attr("id",b+"-title");d.attr("aria-labelledby",b+"-body");this.currentStepNode.attr("role","dialog");this.currentStepNode.attr("tabindex",0);this.currentStepNode.attr("aria-labelledby",b+"-title");this.currentStepNode.attr("aria-describedby",b+"-body");var e=this.getStepTarget(a);if(e){if(!e.attr("tabindex")){e.attr("tabindex",0)}e.data("original-describedby",e.attr("aria-describedby")).attr("aria-describedby",b+"-body")}this.accessibilityShow(a);return this}},{key:"handleKeyDown",value:function handleKeyDown(a){var c="a[href], link[href], [draggable=true], [contenteditable=true], ";c+=":input:enabled, [tabindex], button:enabled";switch(a.keyCode){case 27:this.endTour();break;case 9:(function(){if(!this.currentStepConfig.hasBackdrop){return}var d=(0,b.default)(document.activeElement),e=this.getStepTarget(this.currentStepConfig),f=(0,b.default)(c),g=(0,b.default)("span[data-flexitour=\"container\"]"),h;if(e){f=f.filter(function(a,b){return null!==e&&(e.has(b).length||g.has(b).length||e.is(b)||g.is(b))})}f.each(function(a,b){if(d.is(b)){h=a;return!1}return!0});var i,j,k;if(void 0!=h){var l=1;if(a.shiftKey){l=-1}i=h;do{i+=l;j=(0,b.default)(f[i])}while(j.length&&j.is(":disabled")||j.is(":hidden"));if(j.length){k=j.closest(e).length;k=k||j.closest(this.currentStepNode).length}else{k=!1}}if(k){j.focus()}else{if(a.shiftKey){this.currentStepNode.find(c).last().focus()}else{if(this.currentStepConfig.isOrphan){this.currentStepNode.focus()}else{e.focus()}}}a.preventDefault()}).call(this);break;}}},{key:"startTour",value:function startTour(a){if(this.storage&&"undefined"==typeof a){var c=this.storage.getItem(this.storageKey);if(c){var d=parseInt(c,10);if(d<=this.steps.length){a=d}}}if("undefined"==typeof a){a=this.getCurrentStepNumber()}var b=this.dispatchEvent(f.eventTypes.tourStart,{startAt:a},!0);if(!b.defaultPrevented){this.gotoStep(a);this.tourRunning=!0;this.dispatchEvent(f.eventTypes.tourStarted,{startAt:a})}return this}},{key:"restartTour",value:function restartTour(){return this.startTour(0)}},{key:"endTour",value:function endTour(){var a=this.dispatchEvent(f.eventTypes.tourEnd,{},!0);if(a.defaultPrevented){return this}if(this.currentStepConfig){var b=this.getStepTarget(this.currentStepConfig);if(b){if(!b.attr("tabindex")){b.attr("tabindex","-1")}b.focus()}}this.hide(!0);this.tourRunning=!1;this.dispatchEvent(f.eventTypes.tourEnded);return this}},{key:"hide",value:function hide(a){var c=this.dispatchEvent(f.eventTypes.stepHide,{},!0);if(c.defaultPrevented){return this}if(this.currentStepNode&&this.currentStepNode.length){this.currentStepNode.hide();if(this.currentStepPopper){this.currentStepPopper.destroy()}}if(this.currentStepConfig){var e=this.getStepTarget(this.currentStepConfig);if(e){if(e.data("original-labelledby")){e.attr("aria-labelledby",e.data("original-labelledby"))}if(e.data("original-describedby")){e.attr("aria-describedby",e.data("original-describedby"))}if(e.data("original-tabindex")){e.attr("tabindex",e.data("tabindex"))}}this.currentStepConfig=null}var d=0;if(a){d=400}(0,b.default)("[data-flexitour=\"step-background\"]").remove();(0,b.default)("[data-flexitour=\"step-backdrop\"]").removeAttr("data-flexitour");(0,b.default)("[data-flexitour=\"backdrop\"]").fadeOut(d,function(){(0,b.default)(this).remove()});if(this.currentStepNode&&this.currentStepNode.length){var g=this.currentStepNode.attr("id");if(g){var h="[aria-describedby=\""+g+"-body\"]";(0,b.default)(h).removeAttr("tabindex");(0,b.default)(h).removeAttr("aria-describedby")}}this.resetStepListeners();this.accessibilityHide();this.dispatchEvent(f.eventTypes.stepHidden);this.currentStepNode=null;this.currentStepPopper=null;return this}},{key:"show",value:function show(){var a=this.getCurrentStepNumber();return this.gotoStep(a)}},{key:"getStepContainer",value:function getStepContainer(){return(0,b.default)(this.currentStepNode)}},{key:"calculateScrollTop",value:function calculateScrollTop(a){var c=(0,b.default)(window).height(),d=this.getStepTarget(a),e=(0,b.default)(window);if(d.parents("[data-usertour=\"scroller\"]").length){e=d.parents("[data-usertour=\"scroller\"]")}var f=e.scrollTop();if("top"===a.placement){f=d.offset().top-c/2}else if("bottom"===a.placement){f=d.offset().top+d.height()+f-c/2}else if(d.height()<=.8*c){f=d.offset().top-(c-d.height())/2}else{f=d.offset().top-.2*c}f=Math.max(0,f);f=Math.min((0,b.default)(document).height()-c,f);return Math.ceil(f)}},{key:"calculateStepPositionInPage",value:function calculateStepPositionInPage(){var a=(0,b.default)(window).height(),c=this.currentStepNode.height(),d=(0,b.default)(window).width(),e=this.currentStepNode.width();return{top:Math.ceil((a-c)/2),left:Math.ceil((d-e)/2)}}},{key:"positionStep",value:function positionStep(a){var c=this.currentStepNode;if(!c||!c.length){return this}a.placement=this.recalculatePlacement(a);var e;switch(a.placement){case"left":e=["left","right","top","bottom"];break;case"right":e=["right","left","top","bottom"];break;case"top":e=["top","bottom","right","left"];break;case"bottom":e=["bottom","top","right","left"];break;default:e="flip";break;}var f=this.getStepTarget(a),g={placement:a.placement+"-start",removeOnDestroy:!0,modifiers:{flip:{behaviour:e},arrow:{element:"[data-role=\"arrow\"]"}},onCreate:function onCreate(a){h(a)},onUpdate:function onUpdate(a){h(a)}},h=function(a){var c=a.placement.split("-")[0],d=-1!==["left","right"].indexOf(c),e=a.instance.popper.querySelector("[data-role=\"arrow\"]"),f=(0,b.default)(a.instance.popper.querySelector("[data-role=\"flexitour-step\"]"));if(d){var g=parseFloat(window.getComputedStyle(e).height),h=parseFloat(window.getComputedStyle(e).top),i=parseFloat(window.getComputedStyle(a.instance.popper).height),j=parseFloat(window.getComputedStyle(a.instance.popper).top),k=parseFloat(f.css("borderTopWidth")),l=2*parseFloat(f.css("borderTopLeftRadius")),m=h+g/2,n=i+j-k-l,o=j+k+l;if(m>=n||m<=o){var y=0;if(m>i/2){y=n-g}else{y=o+g}(0,b.default)(e).css("top",y)}}else{var p=parseFloat(window.getComputedStyle(e).width),q=parseFloat(window.getComputedStyle(e).left),r=parseFloat(window.getComputedStyle(a.instance.popper).width),s=parseFloat(window.getComputedStyle(a.instance.popper).left),t=parseFloat(f.css("borderTopWidth")),u=2*parseFloat(f.css("borderTopLeftRadius")),v=q+p/2,w=r+s-t-u,x=s+t+u;if(v>=w||v<=x){var z=0;if(v>r/2){z=w-p}else{z=x+p}(0,b.default)(e).css("left",z)}}},i=(0,b.default)("[data-flexitour=\"step-background\"]");if(i.length){f=i}this.currentStepPopper=new d.default(f,c[0],g);return this}},{key:"recalculatePlacement",value:function recalculatePlacement(a){var b=this.getStepTarget(a),c=this.currentStepNode.width()+16,d=b.offset().left-10,e=b.offset().left+b.width()+10,f=a.placement;if(-1!==["left","right"].indexOf(f)){if(ddocument.documentElement.clientWidth){f="top"}}return f}},{key:"positionBackdrop",value:function positionBackdrop(a){if(a.backdrop){this.currentStepConfig.hasBackdrop=!0;var h=(0,b.default)("");if(a.zIndex){if("append"===a.attachPoint){a.attachTo.append(h)}else{h.insertAfter(a.attachTo)}}else{(0,b.default)("body").append(h)}if(this.isStepActuallyVisible(a)){var i=(0,b.default)("[data-flexitour=\"step-background\"]");if(!i.length){i=(0,b.default)("")}var c=this.getStepTarget(a),d=10,e=c;if(d){e=(0,b.default)("body")}var j=0;if(c.parents("[data-usertour=\"scroller\"]").length){var f=c.parents("[data-usertour=\"scroller\"]"),g=f.offset().top;if(f.scrollTop()>=g){j=f.scrollTop()-g;i.css({position:"fixed"})}}i.css({width:c.outerWidth()+d+d,height:c.outerHeight()+d+d,left:c.offset().left-d,top:c.offset().top+j-d,backgroundColor:this.calculateInherittedBackgroundColor(e)});if(c.offset().left").hide();(0,b.default)("body").append(c);var d=c.css("backgroundColor");c.remove();a=(0,b.default)(a);while(a.length&&a[0]!==document){var e=a.css("backgroundColor");if(e!==d){return e}a=a.parent()}return null}},{key:"calculatePosition",value:function calculatePosition(a){a=(0,b.default)(a);while(a.length&&a[0]!==document){var c=a.css("position");if("static"!==c){return c}a=a.parent()}return null}},{key:"accessibilityShow",value:function accessibilityShow(){var a=function(a){var b=a.data("flexitour");if(b){switch(b){case"container":case"target":return;}}var d=a.attr("aria-hidden");if(!d){a.attr("data-has-hidden",!0);c.hide(a)}};this.currentStepNode.siblings().each(function(c,d){a((0,b.default)(d))});this.currentStepNode.parentsUntil("body").siblings().each(function(c,d){a((0,b.default)(d))})}},{key:"accessibilityHide",value:function accessibilityHide(){var a=function(a){var b=a.attr("data-has-hidden");if("undefined"!=typeof b){a.removeAttr("data-has-hidden");c.unhide(a)}};(0,b.default)("[data-has-hidden]").each(function(c,d){a((0,b.default)(d))})}}]);return a}(),s);a.default=t;return a.default});
-//# sourceMappingURL=tour.min.js.map
+define("tool_usertours/tour",["exports","jquery","core/aria","core/popper","core/event_dispatcher","./events","core/str","core/prefetch"],(function(_exports,_jquery,Aria,_popper,_event_dispatcher,_events,_str,_prefetch){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}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_jquery=_interopRequireDefault(_jquery),Aria=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}(Aria),_popper=_interopRequireDefault(_popper);var _default=class{constructor(config){var obj,key,value;value=!1,(key="tourRunning")in(obj=this)?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,this.init(config)}init(config){this.eventHandlers={},this.reset(),this.originalConfiguration=config||{},this.configure.apply(this,arguments);try{this.storage=window.sessionStorage,this.storageKey="tourstate_"+this.tourName}catch(e){this.storage=!1,this.storageKey=""}return(0,_prefetch.prefetchStrings)("tool_usertours",["nextstep_sequence","skip_tour"]),this}reset(){return this.hide(),this.eventHandlers=[],this.resetStepListeners(),this.originalConfiguration={},this.steps=[],this.currentStepNumber=0,this}configure(config){if("object"==typeof config){if(void 0!==config.tourName&&(this.tourName=config.tourName),config.eventHandlers)for(let eventName in config.eventHandlers)config.eventHandlers[eventName].forEach((function(handler){this.addEventHandler(eventName,handler)}),this);this.resetStepDefaults(!0),"object"==typeof config.steps&&(this.steps=config.steps),void 0!==config.template&&(this.templateContent=config.template)}return this.checkMinimumRequirements(),this}checkMinimumRequirements(){if(!this.tourName)throw new Error("Tour Name required");if(!this.steps||!this.steps.length)throw new Error("Steps must be specified")}resetStepDefaults(loadOriginalConfiguration){return void 0===loadOriginalConfiguration&&(loadOriginalConfiguration=!0),this.stepDefaults={},loadOriginalConfiguration&&void 0!==this.originalConfiguration.stepDefaults?this.setStepDefaults(this.originalConfiguration.stepDefaults):this.setStepDefaults({}),this}setStepDefaults(stepDefaults){return this.stepDefaults||(this.stepDefaults={}),_jquery.default.extend(this.stepDefaults,{element:"",placement:"top",delay:0,moveOnClick:!1,moveAfterTime:0,orphan:!1,direction:1},stepDefaults),this}getCurrentStepNumber(){return parseInt(this.currentStepNumber,10)}setCurrentStepNumber(stepNumber){if(this.currentStepNumber=stepNumber,this.storage)try{this.storage.setItem(this.storageKey,stepNumber)}catch(e){e.code===DOMException.QUOTA_EXCEEDED_ERR&&this.storage.removeItem(this.storageKey)}}getNextStepNumber(stepNumber){void 0===stepNumber&&(stepNumber=this.getCurrentStepNumber());let nextStepNumber=stepNumber+1;for(;nextStepNumber<=this.steps.length;){if(this.isStepPotentiallyVisible(this.getStepConfig(nextStepNumber)))return nextStepNumber;nextStepNumber++}return null}getPreviousStepNumber(stepNumber){void 0===stepNumber&&(stepNumber=this.getCurrentStepNumber());let previousStepNumber=stepNumber-1;for(;previousStepNumber>=0;){if(this.isStepPotentiallyVisible(this.getStepConfig(previousStepNumber)))return previousStepNumber;previousStepNumber--}return null}isLastStep(stepNumber){return null===this.getNextStepNumber(stepNumber)}isStepPotentiallyVisible(stepConfig){return!!stepConfig&&(!!this.isStepActuallyVisible(stepConfig)||(!(void 0===stepConfig.orphan||!stepConfig.orphan)||!(void 0===stepConfig.delay||!stepConfig.delay)))}getPotentiallyVisibleSteps(){let position=1,result=[];for(let stepNumber=0;stepNumber=this.steps.length)return null;let stepConfig=this.normalizeStepConfig(this.steps[stepNumber]);return stepConfig=_jquery.default.extend(stepConfig,{stepNumber:stepNumber}),stepConfig}normalizeStepConfig(stepConfig){return void 0!==stepConfig.reflex&&void 0===stepConfig.moveAfterClick&&(stepConfig.moveAfterClick=stepConfig.reflex),void 0!==stepConfig.element&&void 0===stepConfig.target&&(stepConfig.target=stepConfig.element),void 0!==stepConfig.content&&void 0===stepConfig.body&&(stepConfig.body=stepConfig.content),stepConfig=_jquery.default.extend({},this.stepDefaults,stepConfig),(stepConfig=_jquery.default.extend({},{attachTo:stepConfig.target,attachPoint:"after"},stepConfig)).attachTo&&(stepConfig.attachTo=(0,_jquery.default)(stepConfig.attachTo).first()),stepConfig}getStepTarget(stepConfig){return stepConfig.target?(0,_jquery.default)(stepConfig.target):null}dispatchEvent(eventName){let detail=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},cancelable=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return(0,_event_dispatcher.dispatchEvent)(eventName,{tour:this,...detail},document,{cancelable:cancelable})}addEventHandler(eventName,handler){return void 0===this.eventHandlers[eventName]&&(this.eventHandlers[eventName]=[]),this.eventHandlers[eventName].push(handler),this}processStepListeners(stepConfig){if(this.listeners.push({node:this.currentStepNode,args:["click",'[data-role="next"]',_jquery.default.proxy(this.next,this)]},{node:this.currentStepNode,args:["click",'[data-role="end"]',_jquery.default.proxy(this.endTour,this)]},{node:(0,_jquery.default)('[data-flexitour="backdrop"]'),args:["click",_jquery.default.proxy(this.hide,this)]},{node:(0,_jquery.default)("body"),args:["keydown",_jquery.default.proxy(this.handleKeyDown,this)]}),stepConfig.moveOnClick){var targetNode=this.getStepTarget(stepConfig);this.listeners.push({node:targetNode,args:["click",_jquery.default.proxy((function(e){0===(0,_jquery.default)(e.target).parents('[data-flexitour="container"]').length&&window.setTimeout(_jquery.default.proxy(this.next,this),500)}),this)]})}return this.listeners.forEach((function(listener){listener.node.on.apply(listener.node,listener.args)})),this}resetStepListeners(){return this.listeners&&this.listeners.forEach((function(listener){listener.node.off.apply(listener.node,listener.args)})),this.listeners=[],this}renderStep(stepConfig){this.currentStepConfig=stepConfig,this.setCurrentStepNumber(stepConfig.stepNumber);let template=(0,_jquery.default)(this.getTemplateContent());template.find('[data-placeholder="title"]').html(stepConfig.title),template.find('[data-placeholder="body"]').html(stepConfig.body);const nextBtn=template.find('[data-role="next"]'),endBtn=template.find('[data-role="end"]');if(this.isLastStep(stepConfig.stepNumber)?(nextBtn.hide(),endBtn.removeClass("btn-secondary").addClass("btn-primary")):(nextBtn.prop("disabled",!1),(0,_str.get_string)("skip_tour","tool_usertours").then((value=>{endBtn.html(value)})).catch()),nextBtn.attr("role","button"),endBtn.attr("role","button"),this.originalConfiguration.displaystepnumbers){const stepsPotentiallyVisible=this.getPotentiallyVisibleSteps(),totalStepsPotentiallyVisible=stepsPotentiallyVisible.length,position=stepsPotentiallyVisible[stepConfig.stepNumber].position;totalStepsPotentiallyVisible>1&&(0,_str.get_string)("nextstep_sequence","tool_usertours",{position:position,total:totalStepsPotentiallyVisible}).then((value=>{nextBtn.html(value)})).catch()}return stepConfig.template=template,this.addStepToPage(stepConfig),this.processStepListeners(stepConfig),this}getTemplateContent(){return(0,_jquery.default)(this.templateContent).clone()}addStepToPage(stepConfig){let currentStepNode=(0,_jquery.default)('').html(stepConfig.template).hide(),animationTarget=(0,_jquery.default)("body, html").stop(!0,!0);if(this.isStepActuallyVisible(stepConfig)){let targetNode=this.getStepTarget(stepConfig);targetNode.parents('[data-usertour="scroller"]').length&&(animationTarget=targetNode.parents('[data-usertour="scroller"]')),targetNode.data("flexitour","target");let zIndex=this.calculateZIndex(targetNode);zIndex&&(stepConfig.zIndex=zIndex+1),stepConfig.zIndex&¤tStepNode.css("zIndex",stepConfig.zIndex+1),this.positionBackdrop(stepConfig),(0,_jquery.default)(document.body).append(currentStepNode),this.currentStepNode=currentStepNode,this.currentStepNode.css({top:0,left:0}),animationTarget.animate({scrollTop:this.calculateScrollTop(stepConfig)}).promise().then(function(){this.positionStep(stepConfig),this.revealStep(stepConfig)}.bind(this)).catch((function(){}))}else stepConfig.orphan&&(stepConfig.isOrphan=!0,stepConfig.attachTo=(0,_jquery.default)("body").first(),stepConfig.attachPoint="append",this.positionBackdrop(stepConfig),currentStepNode.addClass("orphan"),(0,_jquery.default)(document.body).append(currentStepNode),this.currentStepNode=currentStepNode,this.currentStepNode.offset(this.calculateStepPositionInPage()),this.currentStepNode.css("position","fixed"),this.currentStepPopper=new _popper.default((0,_jquery.default)("body"),this.currentStepNode[0],{removeOnDestroy:!0,placement:stepConfig.placement+"-start",arrowElement:'[data-role="arrow"]',modifiers:{hide:{enabled:!1},applyStyle:{onLoad:null,enabled:!1}}}),this.revealStep(stepConfig));return this}revealStep(stepConfig){return this.currentStepNode.fadeIn("",_jquery.default.proxy((function(){this.announceStep(stepConfig),this.currentStepNode.focus(),window.setTimeout(_jquery.default.proxy((function(){this.currentStepNode&&this.currentStepNode.focus()}),this),100)}),this)),this}announceStep(stepConfig){let stepId="tour-step-"+this.tourName+"-"+stepConfig.stepNumber;this.currentStepNode.attr("id",stepId);let bodyRegion=this.currentStepNode.find('[data-placeholder="body"]').first();bodyRegion.attr("id",stepId+"-body"),bodyRegion.attr("role","document");let headerRegion=this.currentStepNode.find('[data-placeholder="title"]').first();headerRegion.attr("id",stepId+"-title"),headerRegion.attr("aria-labelledby",stepId+"-body"),this.currentStepNode.attr("role","dialog"),this.currentStepNode.attr("tabindex",0),this.currentStepNode.attr("aria-labelledby",stepId+"-title"),this.currentStepNode.attr("aria-describedby",stepId+"-body");let target=this.getStepTarget(stepConfig);return target&&(target.attr("tabindex")||target.attr("tabindex",0),target.data("original-describedby",target.attr("aria-describedby")).attr("aria-describedby",stepId+"-body")),this.accessibilityShow(stepConfig),this}handleKeyDown(e){let tabbableSelector="a[href], link[href], [draggable=true], [contenteditable=true], ";switch(tabbableSelector+=":input:enabled, [tabindex], button:enabled",e.keyCode){case 27:this.endTour();break;case 9:(function(){if(!this.currentStepConfig.hasBackdrop)return;let currentIndex,nextIndex,nextNode,focusRelevant,activeElement=(0,_jquery.default)(document.activeElement),stepTarget=this.getStepTarget(this.currentStepConfig),tabbableNodes=(0,_jquery.default)(tabbableSelector),dialogContainer=(0,_jquery.default)('span[data-flexitour="container"]');if(stepTarget&&(tabbableNodes=tabbableNodes.filter((function(index,element){return null!==stepTarget&&(stepTarget.has(element).length||dialogContainer.has(element).length||stepTarget.is(element)||dialogContainer.is(element))}))),tabbableNodes.each((function(index,element){return!activeElement.is(element)||(currentIndex=index,!1)})),null!=currentIndex){let direction=1;e.shiftKey&&(direction=-1),nextIndex=currentIndex;do{nextIndex+=direction,nextNode=(0,_jquery.default)(tabbableNodes[nextIndex])}while(nextNode.length&&nextNode.is(":disabled")||nextNode.is(":hidden"));nextNode.length?(focusRelevant=nextNode.closest(stepTarget).length,focusRelevant=focusRelevant||nextNode.closest(this.currentStepNode).length):focusRelevant=!1}focusRelevant?nextNode.focus():e.shiftKey?this.currentStepNode.find(tabbableSelector).last().focus():this.currentStepConfig.isOrphan?this.currentStepNode.focus():stepTarget.focus(),e.preventDefault()}).call(this)}}startTour(startAt){if(this.storage&&void 0===startAt){let storageStartValue=this.storage.getItem(this.storageKey);if(storageStartValue){let storageStartAt=parseInt(storageStartValue,10);storageStartAt<=this.steps.length&&(startAt=storageStartAt)}}void 0===startAt&&(startAt=this.getCurrentStepNumber());return this.dispatchEvent(_events.eventTypes.tourStart,{startAt:startAt},!0).defaultPrevented||(this.gotoStep(startAt),this.tourRunning=!0,this.dispatchEvent(_events.eventTypes.tourStarted,{startAt:startAt})),this}restartTour(){return this.startTour(0)}endTour(){if(this.dispatchEvent(_events.eventTypes.tourEnd,{},!0).defaultPrevented)return this;if(this.currentStepConfig){let previousTarget=this.getStepTarget(this.currentStepConfig);previousTarget&&(previousTarget.attr("tabindex")||previousTarget.attr("tabindex","-1"),previousTarget.focus())}return this.hide(!0),this.tourRunning=!1,this.dispatchEvent(_events.eventTypes.tourEnded),this}hide(transition){if(this.dispatchEvent(_events.eventTypes.stepHide,{},!0).defaultPrevented)return this;if(this.currentStepNode&&this.currentStepNode.length&&(this.currentStepNode.hide(),this.currentStepPopper&&this.currentStepPopper.destroy()),this.currentStepConfig){let target=this.getStepTarget(this.currentStepConfig);target&&(target.data("original-labelledby")&&target.attr("aria-labelledby",target.data("original-labelledby")),target.data("original-describedby")&&target.attr("aria-describedby",target.data("original-describedby")),target.data("original-tabindex")&&target.attr("tabindex",target.data("tabindex"))),this.currentStepConfig=null}let fadeTime=0;if(transition&&(fadeTime=400),(0,_jquery.default)('[data-flexitour="step-background"]').remove(),(0,_jquery.default)('[data-flexitour="step-backdrop"]').removeAttr("data-flexitour"),(0,_jquery.default)('[data-flexitour="backdrop"]').fadeOut(fadeTime,(function(){(0,_jquery.default)(this).remove()})),this.currentStepNode&&this.currentStepNode.length){let stepId=this.currentStepNode.attr("id");if(stepId){let currentStepElement='[aria-describedby="'+stepId+'-body"]';(0,_jquery.default)(currentStepElement).removeAttr("tabindex"),(0,_jquery.default)(currentStepElement).removeAttr("aria-describedby")}}return this.resetStepListeners(),this.accessibilityHide(),this.dispatchEvent(_events.eventTypes.stepHidden),this.currentStepNode=null,this.currentStepPopper=null,this}show(){let startAt=this.getCurrentStepNumber();return this.gotoStep(startAt)}getStepContainer(){return(0,_jquery.default)(this.currentStepNode)}calculateScrollTop(stepConfig){let viewportHeight=(0,_jquery.default)(window).height(),targetNode=this.getStepTarget(stepConfig),scrollParent=(0,_jquery.default)(window);targetNode.parents('[data-usertour="scroller"]').length&&(scrollParent=targetNode.parents('[data-usertour="scroller"]'));let scrollTop=scrollParent.scrollTop();return scrollTop="top"===stepConfig.placement?targetNode.offset().top-viewportHeight/2:"bottom"===stepConfig.placement?targetNode.offset().top+targetNode.height()+scrollTop-viewportHeight/2:targetNode.height()<=.8*viewportHeight?targetNode.offset().top-(viewportHeight-targetNode.height())/2:targetNode.offset().top-.2*viewportHeight,scrollTop=Math.max(0,scrollTop),scrollTop=Math.min((0,_jquery.default)(document).height()-viewportHeight,scrollTop),Math.ceil(scrollTop)}calculateStepPositionInPage(){let viewportHeight=(0,_jquery.default)(window).height(),stepHeight=this.currentStepNode.height(),viewportWidth=(0,_jquery.default)(window).width(),stepWidth=this.currentStepNode.width();return{top:Math.ceil((viewportHeight-stepHeight)/2),left:Math.ceil((viewportWidth-stepWidth)/2)}}positionStep(stepConfig){let flipBehavior,content=this.currentStepNode;if(!content||!content.length)return this;switch(stepConfig.placement=this.recalculatePlacement(stepConfig),stepConfig.placement){case"left":flipBehavior=["left","right","top","bottom"];break;case"right":flipBehavior=["right","left","top","bottom"];break;case"top":flipBehavior=["top","bottom","right","left"];break;case"bottom":flipBehavior=["bottom","top","right","left"];break;default:flipBehavior="flip"}let target=this.getStepTarget(stepConfig);var config={placement:stepConfig.placement+"-start",removeOnDestroy:!0,modifiers:{flip:{behaviour:flipBehavior},arrow:{element:'[data-role="arrow"]'}},onCreate:function(data){recalculateArrowPosition(data)},onUpdate:function(data){recalculateArrowPosition(data)}};let recalculateArrowPosition=function(data){let placement=data.placement.split("-")[0];const isVertical=-1!==["left","right"].indexOf(placement),arrowElement=data.instance.popper.querySelector('[data-role="arrow"]'),stepElement=(0,_jquery.default)(data.instance.popper.querySelector('[data-role="flexitour-step"]'));if(isVertical){let arrowHeight=parseFloat(window.getComputedStyle(arrowElement).height),arrowOffset=parseFloat(window.getComputedStyle(arrowElement).top),popperHeight=parseFloat(window.getComputedStyle(data.instance.popper).height),popperOffset=parseFloat(window.getComputedStyle(data.instance.popper).top),popperBorderWidth=parseFloat(stepElement.css("borderTopWidth")),popperBorderRadiusWidth=2*parseFloat(stepElement.css("borderTopLeftRadius")),arrowPos=arrowOffset+arrowHeight/2,maxPos=popperHeight+popperOffset-popperBorderWidth-popperBorderRadiusWidth,minPos=popperOffset+popperBorderWidth+popperBorderRadiusWidth;if(arrowPos>=maxPos||arrowPos<=minPos){let newArrowPos=0;newArrowPos=arrowPos>popperHeight/2?maxPos-arrowHeight:minPos+arrowHeight,(0,_jquery.default)(arrowElement).css("top",newArrowPos)}}else{let arrowWidth=parseFloat(window.getComputedStyle(arrowElement).width),arrowOffset=parseFloat(window.getComputedStyle(arrowElement).left),popperWidth=parseFloat(window.getComputedStyle(data.instance.popper).width),popperOffset=parseFloat(window.getComputedStyle(data.instance.popper).left),popperBorderWidth=parseFloat(stepElement.css("borderTopWidth")),popperBorderRadiusWidth=2*parseFloat(stepElement.css("borderTopLeftRadius")),arrowPos=arrowOffset+arrowWidth/2,maxPos=popperWidth+popperOffset-popperBorderWidth-popperBorderRadiusWidth,minPos=popperOffset+popperBorderWidth+popperBorderRadiusWidth;if(arrowPos>=maxPos||arrowPos<=minPos){let newArrowPos=0;newArrowPos=arrowPos>popperWidth/2?maxPos-arrowWidth:minPos+arrowWidth,(0,_jquery.default)(arrowElement).css("left",newArrowPos)}}},background=(0,_jquery.default)('[data-flexitour="step-background"]');return background.length&&(target=background),this.currentStepPopper=new _popper.default(target,content[0],config),this}recalculatePlacement(stepConfig){let target=this.getStepTarget(stepConfig),widthContent=this.currentStepNode.width()+16,targetOffsetLeft=target.offset().left-10,targetOffsetRight=target.offset().left+target.width()+10,placement=stepConfig.placement;return-1!==["left","right"].indexOf(placement)&&targetOffsetLeftdocument.documentElement.clientWidth&&(placement="top"),placement}positionBackdrop(stepConfig){if(stepConfig.backdrop){this.currentStepConfig.hasBackdrop=!0;let backdrop=(0,_jquery.default)('');if(stepConfig.zIndex?"append"===stepConfig.attachPoint?stepConfig.attachTo.append(backdrop):backdrop.insertAfter(stepConfig.attachTo):(0,_jquery.default)("body").append(backdrop),this.isStepActuallyVisible(stepConfig)){let background=(0,_jquery.default)('[data-flexitour="step-background"]');background.length||(background=(0,_jquery.default)(''));let targetNode=this.getStepTarget(stepConfig),buffer=10,colorNode=targetNode;buffer&&(colorNode=(0,_jquery.default)("body"));let drawertop=0;if(targetNode.parents('[data-usertour="scroller"]').length){const scrollerElement=targetNode.parents('[data-usertour="scroller"]'),navigationBuffer=scrollerElement.offset().top;scrollerElement.scrollTop()>=navigationBuffer&&(drawertop=scrollerElement.scrollTop()-navigationBuffer,background.css({position:"fixed"}))}background.css({width:targetNode.outerWidth()+buffer+buffer,height:targetNode.outerHeight()+buffer+buffer,left:targetNode.offset().left-buffer,top:targetNode.offset().top+drawertop-buffer,backgroundColor:this.calculateInherittedBackgroundColor(colorNode)}),targetNode.offset().left").hide();(0,_jquery.default)("body").append(fakeNode);let fakeElemColor=fakeNode.css("backgroundColor");for(fakeNode.remove(),elem=(0,_jquery.default)(elem);elem.length&&elem[0]!==document;){let color=elem.css("backgroundColor");if(color!==fakeElemColor)return color;elem=elem.parent()}return null}calculatePosition(elem){for(elem=(0,_jquery.default)(elem);elem.length&&elem[0]!==document;){let position=elem.css("position");if("static"!==position)return position;elem=elem.parent()}return null}accessibilityShow(){let hideFunction=function(child){let flexitourRole=child.data("flexitour");if(flexitourRole)switch(flexitourRole){case"container":case"target":return}child.attr("aria-hidden")||(child.attr("data-has-hidden",!0),Aria.hide(child))};this.currentStepNode.siblings().each((function(index,node){hideFunction((0,_jquery.default)(node))})),this.currentStepNode.parentsUntil("body").siblings().each((function(index,node){hideFunction((0,_jquery.default)(node))}))}accessibilityHide(){(0,_jquery.default)("[data-has-hidden]").each((function(index,node){var child;void 0!==(child=(0,_jquery.default)(node)).attr("data-has-hidden")&&(child.removeAttr("data-has-hidden"),Aria.unhide(child))}))}};return _exports.default=_default,_exports.default}));
+
+//# sourceMappingURL=tour.min.js.map
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/tour.min.js.map b/admin/tool/usertours/amd/build/tour.min.js.map
index 266a79dba3d..1e58fd2b5ca 100644
--- a/admin/tool/usertours/amd/build/tour.min.js.map
+++ b/admin/tool/usertours/amd/build/tour.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/tour.js"],"names":["Tour","config","init","eventHandlers","reset","originalConfiguration","configure","apply","arguments","storage","window","sessionStorage","storageKey","tourName","e","hide","resetStepListeners","steps","currentStepNumber","eventName","forEach","handler","addEventHandler","resetStepDefaults","template","templateContent","checkMinimumRequirements","Error","length","loadOriginalConfiguration","stepDefaults","setStepDefaults","$","extend","element","placement","delay","moveOnClick","moveAfterTime","orphan","direction","parseInt","stepNumber","setItem","code","DOMException","QUOTA_EXCEEDED_ERR","removeItem","getCurrentStepNumber","nextStepNumber","isStepPotentiallyVisible","getStepConfig","previousStepNumber","getNextStepNumber","stepConfig","isStepActuallyVisible","position","result","stepId","stepid","target","getStepTarget","is","gotoStep","getPreviousStepNumber","endTour","_gotoStep","delayed","setTimeout","bind","fn","stepRenderEvent","dispatchEvent","eventTypes","stepRender","defaultPrevented","renderStep","stepRendered","normalizeStepConfig","reflex","moveAfterClick","content","body","attachTo","attachPoint","first","detail","cancelable","tour","document","push","listeners","node","currentStepNode","args","proxy","next","handleKeyDown","targetNode","parents","listener","on","off","currentStepConfig","setCurrentStepNumber","getTemplateContent","find","html","title","nextBtn","endBtn","isLastStep","removeClass","addClass","prop","then","value","catch","attr","displaystepnumbers","stepsPotentiallyVisible","getPotentiallyVisibleSteps","totalStepsPotentiallyVisible","total","addStepToPage","processStepListeners","clone","animationTarget","stop","data","zIndex","calculateZIndex","css","positionBackdrop","append","top","left","animate","scrollTop","calculateScrollTop","promise","positionStep","revealStep","isOrphan","offset","calculateStepPositionInPage","currentStepPopper","Popper","removeOnDestroy","arrowElement","modifiers","enabled","applyStyle","onLoad","fadeIn","announceStep","focus","bodyRegion","headerRegion","accessibilityShow","tabbableSelector","keyCode","hasBackdrop","activeElement","stepTarget","tabbableNodes","dialogContainer","currentIndex","filter","index","has","each","nextIndex","nextNode","focusRelevant","shiftKey","closest","last","preventDefault","call","startAt","storageStartValue","getItem","storageStartAt","tourStartEvent","tourStart","tourRunning","tourStarted","startTour","tourEndEvent","tourEnd","previousTarget","tourEnded","transition","stepHideEvent","stepHide","destroy","fadeTime","remove","removeAttr","fadeOut","currentStepElement","accessibilityHide","stepHidden","viewportHeight","height","scrollParent","Math","max","min","ceil","stepHeight","viewportWidth","width","stepWidth","recalculatePlacement","flipBehavior","flip","behaviour","arrow","onCreate","recalculateArrowPosition","onUpdate","split","isVertical","indexOf","instance","popper","querySelector","stepElement","arrowHeight","parseFloat","getComputedStyle","arrowOffset","popperHeight","popperOffset","popperBorderWidth","popperBorderRadiusWidth","arrowPos","maxPos","minPos","newArrowPos","arrowWidth","popperWidth","background","widthContent","targetOffsetLeft","targetOffsetRight","documentElement","clientWidth","backdrop","insertAfter","buffer","colorNode","drawertop","scrollerElement","navigationBuffer","outerWidth","outerHeight","backgroundColor","calculateInherittedBackgroundColor","targetRadius","targetPosition","calculatePosition","fader","opacity","targetClone","elem","isNaN","parent","fakeNode","fakeElemColor","color","hideFunction","child","flexitourRole","hidden","Aria","siblings","parentsUntil","showFunction","unhide"],"mappings":"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","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 .\n\n/**\n * A user tour.\n *\n * @module tool_usertours/tour\n * @copyright 2018 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * A list of steps.\n *\n * @typedef {Object[]} StepList\n * @property {Number} stepId The id of the step in the database\n * @property {Number} position The position of the step within the tour (zero-indexed)\n */\n\nimport $ from 'jquery';\nimport * as Aria from 'core/aria';\nimport Popper from 'core/popper';\nimport {dispatchEvent} from 'core/event_dispatcher';\nimport {eventTypes} from './events';\nimport {get_string as getString} from 'core/str';\nimport {prefetchStrings} from 'core/prefetch';\n\n/**\n * A user tour.\n *\n * @class tool_usertours/tour\n * @property {boolean} tourRunning Whether the tour is currently running.\n */\nconst Tour = class {\n tourRunning = false;\n\n /**\n * @param {object} config The configuration object.\n */\n constructor(config) {\n this.init(config);\n }\n\n /**\n * Initialise the tour.\n *\n * @method init\n * @param {Object} config The configuration object.\n * @chainable\n * @return {Object} this.\n */\n init(config) {\n // Unset all handlers.\n this.eventHandlers = {};\n\n // Reset the current tour states.\n this.reset();\n\n // Store the initial configuration.\n this.originalConfiguration = config || {};\n\n // Apply configuration.\n this.configure.apply(this, arguments);\n\n try {\n this.storage = window.sessionStorage;\n this.storageKey = 'tourstate_' + this.tourName;\n } catch (e) {\n this.storage = false;\n this.storageKey = '';\n }\n\n prefetchStrings('tool_usertours', [\n 'nextstep_sequence',\n 'skip_tour'\n ]);\n\n return this;\n }\n\n /**\n * Reset the current tour state.\n *\n * @method reset\n * @chainable\n * @return {Object} this.\n */\n reset() {\n // Hide the current step.\n this.hide();\n\n // Unset all handlers.\n this.eventHandlers = [];\n\n // Unset all listeners.\n this.resetStepListeners();\n\n // Unset the original configuration.\n this.originalConfiguration = {};\n\n // Reset the current step number and list of steps.\n this.steps = [];\n\n // Reset the current step number.\n this.currentStepNumber = 0;\n\n return this;\n }\n\n /**\n * Prepare tour configuration.\n *\n * @method configure\n * @param {Object} config The configuration object.\n * @chainable\n * @return {Object} this.\n */\n configure(config) {\n if (typeof config === 'object') {\n // Tour name.\n if (typeof config.tourName !== 'undefined') {\n this.tourName = config.tourName;\n }\n\n // Set up eventHandlers.\n if (config.eventHandlers) {\n for (let eventName in config.eventHandlers) {\n config.eventHandlers[eventName].forEach(function(handler) {\n this.addEventHandler(eventName, handler);\n }, this);\n }\n }\n\n // Reset the step configuration.\n this.resetStepDefaults(true);\n\n // Configure the steps.\n if (typeof config.steps === 'object') {\n this.steps = config.steps;\n }\n\n if (typeof config.template !== 'undefined') {\n this.templateContent = config.template;\n }\n }\n\n // Check that we have enough to start the tour.\n this.checkMinimumRequirements();\n\n return this;\n }\n\n /**\n * Check that the configuration meets the minimum requirements.\n *\n * @method checkMinimumRequirements\n */\n checkMinimumRequirements() {\n // Need a tourName.\n if (!this.tourName) {\n throw new Error(\"Tour Name required\");\n }\n\n // Need a minimum of one step.\n if (!this.steps || !this.steps.length) {\n throw new Error(\"Steps must be specified\");\n }\n }\n\n /**\n * Reset step default configuration.\n *\n * @method resetStepDefaults\n * @param {Boolean} loadOriginalConfiguration Whether to load the original configuration supplied with the Tour.\n * @chainable\n * @return {Object} this.\n */\n resetStepDefaults(loadOriginalConfiguration) {\n if (typeof loadOriginalConfiguration === 'undefined') {\n loadOriginalConfiguration = true;\n }\n\n this.stepDefaults = {};\n if (!loadOriginalConfiguration || typeof this.originalConfiguration.stepDefaults === 'undefined') {\n this.setStepDefaults({});\n } else {\n this.setStepDefaults(this.originalConfiguration.stepDefaults);\n }\n\n return this;\n }\n\n /**\n * Set the step defaults.\n *\n * @method setStepDefaults\n * @param {Object} stepDefaults The step defaults to apply to all steps\n * @chainable\n * @return {Object} this.\n */\n setStepDefaults(stepDefaults) {\n if (!this.stepDefaults) {\n this.stepDefaults = {};\n }\n $.extend(\n this.stepDefaults,\n {\n element: '',\n placement: 'top',\n delay: 0,\n moveOnClick: false,\n moveAfterTime: 0,\n orphan: false,\n direction: 1,\n },\n stepDefaults\n );\n\n return this;\n }\n\n /**\n * Retrieve the current step number.\n *\n * @method getCurrentStepNumber\n * @return {Number} The current step number\n */\n getCurrentStepNumber() {\n return parseInt(this.currentStepNumber, 10);\n }\n\n /**\n * Store the current step number.\n *\n * @method setCurrentStepNumber\n * @param {Number} stepNumber The current step number\n * @chainable\n */\n setCurrentStepNumber(stepNumber) {\n this.currentStepNumber = stepNumber;\n if (this.storage) {\n try {\n this.storage.setItem(this.storageKey, stepNumber);\n } catch (e) {\n if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {\n this.storage.removeItem(this.storageKey);\n }\n }\n }\n }\n\n /**\n * Get the next step number after the currently displayed step.\n *\n * @method getNextStepNumber\n * @param {Number} stepNumber The current step number\n * @return {Number} The next step number to display\n */\n getNextStepNumber(stepNumber) {\n if (typeof stepNumber === 'undefined') {\n stepNumber = this.getCurrentStepNumber();\n }\n let nextStepNumber = stepNumber + 1;\n\n // Keep checking the remaining steps.\n while (nextStepNumber <= this.steps.length) {\n if (this.isStepPotentiallyVisible(this.getStepConfig(nextStepNumber))) {\n return nextStepNumber;\n }\n nextStepNumber++;\n }\n\n return null;\n }\n\n /**\n * Get the previous step number before the currently displayed step.\n *\n * @method getPreviousStepNumber\n * @param {Number} stepNumber The current step number\n * @return {Number} The previous step number to display\n */\n getPreviousStepNumber(stepNumber) {\n if (typeof stepNumber === 'undefined') {\n stepNumber = this.getCurrentStepNumber();\n }\n let previousStepNumber = stepNumber - 1;\n\n // Keep checking the remaining steps.\n while (previousStepNumber >= 0) {\n if (this.isStepPotentiallyVisible(this.getStepConfig(previousStepNumber))) {\n return previousStepNumber;\n }\n previousStepNumber--;\n }\n\n return null;\n }\n\n /**\n * Is the step the final step number?\n *\n * @method isLastStep\n * @param {Number} stepNumber Step number to test\n * @return {Boolean} Whether the step is the final step\n */\n isLastStep(stepNumber) {\n let nextStepNumber = this.getNextStepNumber(stepNumber);\n\n return nextStepNumber === null;\n }\n\n /**\n * Is this step potentially visible?\n *\n * @method isStepPotentiallyVisible\n * @param {Object} stepConfig The step configuration to normalise\n * @return {Boolean} Whether the step is the potentially visible\n */\n isStepPotentiallyVisible(stepConfig) {\n if (!stepConfig) {\n // Without step config, there can be no step.\n return false;\n }\n\n if (this.isStepActuallyVisible(stepConfig)) {\n // If it is actually visible, it is already potentially visible.\n return true;\n }\n\n if (typeof stepConfig.orphan !== 'undefined' && stepConfig.orphan) {\n // Orphan steps have no target. They are always visible.\n return true;\n }\n\n if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay) {\n // Only return true if the activated has not been used yet.\n return true;\n }\n\n // Not theoretically, or actually visible.\n return false;\n }\n\n /**\n * Get potentially visible steps in a tour.\n *\n * @returns {StepList} A list of ordered steps\n */\n getPotentiallyVisibleSteps() {\n let position = 1;\n let result = [];\n // Checking the total steps.\n for (let stepNumber = 0; stepNumber < this.steps.length; stepNumber++) {\n const stepConfig = this.getStepConfig(stepNumber);\n if (this.isStepPotentiallyVisible(stepConfig)) {\n result[stepNumber] = {stepId: stepConfig.stepid, position: position};\n position++;\n }\n }\n\n return result;\n }\n\n /**\n * Is this step actually visible?\n *\n * @method isStepActuallyVisible\n * @param {Object} stepConfig The step configuration to normalise\n * @return {Boolean} Whether the step is actually visible\n */\n isStepActuallyVisible(stepConfig) {\n if (!stepConfig) {\n // Without step config, there can be no step.\n return false;\n }\n\n let target = this.getStepTarget(stepConfig);\n if (target && target.length && target.is(':visible')) {\n // Without a target, there can be no step.\n return !!target.length;\n }\n\n return false;\n }\n\n /**\n * Go to the next step in the tour.\n *\n * @method next\n * @chainable\n * @return {Object} this.\n */\n next() {\n return this.gotoStep(this.getNextStepNumber());\n }\n\n /**\n * Go to the previous step in the tour.\n *\n * @method previous\n * @chainable\n * @return {Object} this.\n */\n previous() {\n return this.gotoStep(this.getPreviousStepNumber(), -1);\n }\n\n /**\n * Go to the specified step in the tour.\n *\n * @method gotoStep\n * @param {Number} stepNumber The step number to display\n * @param {Number} direction Next or previous step\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/stepRender\n * @fires tool_usertours/stepRendered\n * @fires tool_usertours/stepHide\n * @fires tool_usertours/stepHidden\n */\n gotoStep(stepNumber, direction) {\n if (stepNumber < 0) {\n return this.endTour();\n }\n\n let stepConfig = this.getStepConfig(stepNumber);\n if (stepConfig === null) {\n return this.endTour();\n }\n\n return this._gotoStep(stepConfig, direction);\n }\n\n _gotoStep(stepConfig, direction) {\n if (!stepConfig) {\n return this.endTour();\n }\n\n if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay && !stepConfig.delayed) {\n stepConfig.delayed = true;\n window.setTimeout(this._gotoStep.bind(this), stepConfig.delay, stepConfig, direction);\n\n return this;\n } else if (!stepConfig.orphan && !this.isStepActuallyVisible(stepConfig)) {\n let fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber';\n return this.gotoStep(this[fn](stepConfig.stepNumber), direction);\n }\n\n this.hide();\n\n const stepRenderEvent = this.dispatchEvent(eventTypes.stepRender, {stepConfig}, true);\n if (!stepRenderEvent.defaultPrevented) {\n this.renderStep(stepConfig);\n this.dispatchEvent(eventTypes.stepRendered, {stepConfig});\n }\n\n return this;\n }\n\n /**\n * Fetch the normalised step configuration for the specified step number.\n *\n * @method getStepConfig\n * @param {Number} stepNumber The step number to fetch configuration for\n * @return {Object} The step configuration\n */\n getStepConfig(stepNumber) {\n if (stepNumber === null || stepNumber < 0 || stepNumber >= this.steps.length) {\n return null;\n }\n\n // Normalise the step configuration.\n let stepConfig = this.normalizeStepConfig(this.steps[stepNumber]);\n\n // Add the stepNumber to the stepConfig.\n stepConfig = $.extend(stepConfig, {stepNumber: stepNumber});\n\n return stepConfig;\n }\n\n /**\n * Normalise the supplied step configuration.\n *\n * @method normalizeStepConfig\n * @param {Object} stepConfig The step configuration to normalise\n * @return {Object} The normalised step configuration\n */\n normalizeStepConfig(stepConfig) {\n\n if (typeof stepConfig.reflex !== 'undefined' && typeof stepConfig.moveAfterClick === 'undefined') {\n stepConfig.moveAfterClick = stepConfig.reflex;\n }\n\n if (typeof stepConfig.element !== 'undefined' && typeof stepConfig.target === 'undefined') {\n stepConfig.target = stepConfig.element;\n }\n\n if (typeof stepConfig.content !== 'undefined' && typeof stepConfig.body === 'undefined') {\n stepConfig.body = stepConfig.content;\n }\n\n stepConfig = $.extend({}, this.stepDefaults, stepConfig);\n\n stepConfig = $.extend({}, {\n attachTo: stepConfig.target,\n attachPoint: 'after',\n }, stepConfig);\n\n if (stepConfig.attachTo) {\n stepConfig.attachTo = $(stepConfig.attachTo).first();\n }\n\n return stepConfig;\n }\n\n /**\n * Fetch the actual step target from the selector.\n *\n * This should not be called until after any delay has completed.\n *\n * @method getStepTarget\n * @param {Object} stepConfig The step configuration\n * @return {$}\n */\n getStepTarget(stepConfig) {\n if (stepConfig.target) {\n return $(stepConfig.target);\n }\n\n return null;\n }\n\n /**\n * Fire any event handlers for the specified event.\n *\n * @param {String} eventName The name of the event\n * @param {Object} [detail={}] Any additional details to pass into the eveent\n * @param {Boolean} [cancelable=false] Whether preventDefault() can be called\n * @returns {CustomEvent}\n */\n dispatchEvent(\n eventName,\n detail = {},\n cancelable = false\n ) {\n return dispatchEvent(eventName, {\n // Add the tour to the detail.\n tour: this,\n ...detail,\n }, document, {\n cancelable,\n });\n }\n\n /**\n * @method addEventHandler\n * @param {string} eventName The name of the event to listen for\n * @param {function} handler The event handler to call\n * @return {Object} this.\n */\n addEventHandler(eventName, handler) {\n if (typeof this.eventHandlers[eventName] === 'undefined') {\n this.eventHandlers[eventName] = [];\n }\n\n this.eventHandlers[eventName].push(handler);\n\n return this;\n }\n\n /**\n * Process listeners for the step being shown.\n *\n * @method processStepListeners\n * @param {object} stepConfig The configuration for the step\n * @chainable\n * @return {Object} this.\n */\n processStepListeners(stepConfig) {\n this.listeners.push(\n // Next button.\n {\n node: this.currentStepNode,\n args: ['click', '[data-role=\"next\"]', $.proxy(this.next, this)]\n },\n\n // Close and end tour buttons.\n {\n node: this.currentStepNode,\n args: ['click', '[data-role=\"end\"]', $.proxy(this.endTour, this)]\n },\n\n // Click backdrop and hide tour.\n {\n node: $('[data-flexitour=\"backdrop\"]'),\n args: ['click', $.proxy(this.hide, this)]\n },\n\n // Keypresses.\n {\n node: $('body'),\n args: ['keydown', $.proxy(this.handleKeyDown, this)]\n });\n\n if (stepConfig.moveOnClick) {\n var targetNode = this.getStepTarget(stepConfig);\n this.listeners.push({\n node: targetNode,\n args: ['click', $.proxy(function(e) {\n if ($(e.target).parents('[data-flexitour=\"container\"]').length === 0) {\n // Ignore clicks when they are in the flexitour.\n window.setTimeout($.proxy(this.next, this), 500);\n }\n }, this)]\n });\n }\n\n this.listeners.forEach(function(listener) {\n listener.node.on.apply(listener.node, listener.args);\n });\n\n return this;\n }\n\n /**\n * Reset step listeners.\n *\n * @method resetStepListeners\n * @chainable\n * @return {Object} this.\n */\n resetStepListeners() {\n // Stop listening to all external handlers.\n if (this.listeners) {\n this.listeners.forEach(function(listener) {\n listener.node.off.apply(listener.node, listener.args);\n });\n }\n this.listeners = [];\n\n return this;\n }\n\n /**\n * The standard step renderer.\n *\n * @method renderStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n renderStep(stepConfig) {\n // Store the current step configuration for later.\n this.currentStepConfig = stepConfig;\n this.setCurrentStepNumber(stepConfig.stepNumber);\n\n // Fetch the template and convert it to a $ object.\n let template = $(this.getTemplateContent());\n\n // Title.\n template.find('[data-placeholder=\"title\"]')\n .html(stepConfig.title);\n\n // Body.\n template.find('[data-placeholder=\"body\"]')\n .html(stepConfig.body);\n\n // Buttons.\n const nextBtn = template.find('[data-role=\"next\"]');\n const endBtn = template.find('[data-role=\"end\"]');\n\n // Is this the final step?\n if (this.isLastStep(stepConfig.stepNumber)) {\n nextBtn.hide();\n endBtn.removeClass(\"btn-secondary\").addClass(\"btn-primary\");\n } else {\n nextBtn.prop('disabled', false);\n // Use Skip tour label for the End tour button.\n getString('skip_tour', 'tool_usertours').then(value => {\n endBtn.html(value);\n return;\n }).catch();\n }\n\n nextBtn.attr('role', 'button');\n endBtn.attr('role', 'button');\n\n if (this.originalConfiguration.displaystepnumbers) {\n const stepsPotentiallyVisible = this.getPotentiallyVisibleSteps();\n const totalStepsPotentiallyVisible = stepsPotentiallyVisible.length;\n const position = stepsPotentiallyVisible[stepConfig.stepNumber].position;\n if (totalStepsPotentiallyVisible > 1) {\n // Change the label of the Next button to include the sequence.\n getString('nextstep_sequence', 'tool_usertours',\n {position: position, total: totalStepsPotentiallyVisible}).then(value => {\n nextBtn.html(value);\n return;\n }).catch();\n }\n }\n\n // Replace the template with the updated version.\n stepConfig.template = template;\n\n // Add to the page.\n this.addStepToPage(stepConfig);\n\n // Process step listeners after adding to the page.\n // This uses the currentNode.\n this.processStepListeners(stepConfig);\n\n return this;\n }\n\n /**\n * Getter for the template content.\n *\n * @method getTemplateContent\n * @return {$}\n */\n getTemplateContent() {\n return $(this.templateContent).clone();\n }\n\n /**\n * Helper to add a step to the page.\n *\n * @method addStepToPage\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n addStepToPage(stepConfig) {\n // Create the stepNode from the template data.\n let currentStepNode = $('')\n .html(stepConfig.template)\n .hide();\n\n // The scroll animation occurs on the body or html.\n let animationTarget = $('body, html')\n .stop(true, true);\n\n if (this.isStepActuallyVisible(stepConfig)) {\n let targetNode = this.getStepTarget(stepConfig);\n\n if (targetNode.parents('[data-usertour=\"scroller\"]').length) {\n animationTarget = targetNode.parents('[data-usertour=\"scroller\"]');\n }\n\n targetNode.data('flexitour', 'target');\n\n let zIndex = this.calculateZIndex(targetNode);\n if (zIndex) {\n stepConfig.zIndex = zIndex + 1;\n }\n\n if (stepConfig.zIndex) {\n currentStepNode.css('zIndex', stepConfig.zIndex + 1);\n }\n\n // Add the backdrop.\n this.positionBackdrop(stepConfig);\n\n $(document.body).append(currentStepNode);\n this.currentStepNode = currentStepNode;\n\n // Ensure that the step node is positioned.\n // Some situations mean that the value is not properly calculated without this step.\n this.currentStepNode.css({\n top: 0,\n left: 0,\n });\n\n animationTarget\n .animate({\n scrollTop: this.calculateScrollTop(stepConfig),\n }).promise().then(function() {\n this.positionStep(stepConfig);\n this.revealStep(stepConfig);\n return;\n }.bind(this))\n .catch(function() {\n // Silently fail.\n });\n\n } else if (stepConfig.orphan) {\n stepConfig.isOrphan = true;\n\n // This will be appended to the body instead.\n stepConfig.attachTo = $('body').first();\n stepConfig.attachPoint = 'append';\n\n // Add the backdrop.\n this.positionBackdrop(stepConfig);\n\n // This is an orphaned step.\n currentStepNode.addClass('orphan');\n\n // It lives in the body.\n $(document.body).append(currentStepNode);\n this.currentStepNode = currentStepNode;\n\n this.currentStepNode.offset(this.calculateStepPositionInPage());\n this.currentStepNode.css('position', 'fixed');\n\n this.currentStepPopper = new Popper(\n $('body'),\n this.currentStepNode[0], {\n removeOnDestroy: true,\n placement: stepConfig.placement + '-start',\n arrowElement: '[data-role=\"arrow\"]',\n // Empty the modifiers. We've already placed the step and don't want it moved.\n modifiers: {\n hide: {\n enabled: false,\n },\n applyStyle: {\n onLoad: null,\n enabled: false,\n },\n }\n }\n );\n\n this.revealStep(stepConfig);\n }\n\n return this;\n }\n\n /**\n * Make the given step visible.\n *\n * @method revealStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n revealStep(stepConfig) {\n // Fade the step in.\n this.currentStepNode.fadeIn('', $.proxy(function() {\n // Announce via ARIA.\n this.announceStep(stepConfig);\n\n // Focus on the current step Node.\n this.currentStepNode.focus();\n window.setTimeout($.proxy(function() {\n // After a brief delay, focus again.\n // There seems to be an issue with Jaws where it only reads the dialogue title initially.\n // This second focus helps it to read the full dialogue.\n if (this.currentStepNode) {\n this.currentStepNode.focus();\n }\n }, this), 100);\n\n }, this));\n\n return this;\n }\n\n /**\n * Helper to announce the step on the page.\n *\n * @method announceStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n announceStep(stepConfig) {\n // Setup the step Dialogue as per:\n // * https://www.w3.org/TR/wai-aria-practices/#dialog_nonmodal\n // * https://www.w3.org/TR/wai-aria-practices/#dialog_modal\n\n // Generate an ID for the current step node.\n let stepId = 'tour-step-' + this.tourName + '-' + stepConfig.stepNumber;\n this.currentStepNode.attr('id', stepId);\n\n let bodyRegion = this.currentStepNode.find('[data-placeholder=\"body\"]').first();\n bodyRegion.attr('id', stepId + '-body');\n bodyRegion.attr('role', 'document');\n\n let headerRegion = this.currentStepNode.find('[data-placeholder=\"title\"]').first();\n headerRegion.attr('id', stepId + '-title');\n headerRegion.attr('aria-labelledby', stepId + '-body');\n\n // Generally, a modal dialog has a role of dialog.\n this.currentStepNode.attr('role', 'dialog');\n this.currentStepNode.attr('tabindex', 0);\n this.currentStepNode.attr('aria-labelledby', stepId + '-title');\n this.currentStepNode.attr('aria-describedby', stepId + '-body');\n\n // Configure ARIA attributes on the target.\n let target = this.getStepTarget(stepConfig);\n if (target) {\n if (!target.attr('tabindex')) {\n target.attr('tabindex', 0);\n }\n\n target\n .data('original-describedby', target.attr('aria-describedby'))\n .attr('aria-describedby', stepId + '-body')\n ;\n }\n\n this.accessibilityShow(stepConfig);\n\n return this;\n }\n\n /**\n * Handle key down events.\n *\n * @method handleKeyDown\n * @param {EventFacade} e\n */\n handleKeyDown(e) {\n let tabbableSelector = 'a[href], link[href], [draggable=true], [contenteditable=true], ';\n tabbableSelector += ':input:enabled, [tabindex], button:enabled';\n switch (e.keyCode) {\n case 27:\n this.endTour();\n break;\n\n // 9 == Tab - trap focus for items with a backdrop.\n case 9:\n // Tab must be handled on key up only in this instance.\n (function() {\n if (!this.currentStepConfig.hasBackdrop) {\n // Trapping tab focus is only handled for those steps with a backdrop.\n return;\n }\n\n // Find all tabbable locations.\n let activeElement = $(document.activeElement);\n let stepTarget = this.getStepTarget(this.currentStepConfig);\n let tabbableNodes = $(tabbableSelector);\n let dialogContainer = $('span[data-flexitour=\"container\"]');\n let currentIndex;\n // Filter out element which is not belong to target section or dialogue.\n if (stepTarget) {\n tabbableNodes = tabbableNodes.filter(function(index, element) {\n return stepTarget !== null\n && (stepTarget.has(element).length\n || dialogContainer.has(element).length\n || stepTarget.is(element)\n || dialogContainer.is(element));\n });\n }\n\n // Find index of focusing element.\n tabbableNodes.each(function(index, element) {\n if (activeElement.is(element)) {\n currentIndex = index;\n return false;\n }\n // Keep looping.\n return true;\n });\n\n let nextIndex;\n let nextNode;\n let focusRelevant;\n if (currentIndex != void 0) {\n let direction = 1;\n if (e.shiftKey) {\n direction = -1;\n }\n nextIndex = currentIndex;\n do {\n nextIndex += direction;\n nextNode = $(tabbableNodes[nextIndex]);\n } while (nextNode.length && nextNode.is(':disabled') || nextNode.is(':hidden'));\n if (nextNode.length) {\n // A new f\n focusRelevant = nextNode.closest(stepTarget).length;\n focusRelevant = focusRelevant || nextNode.closest(this.currentStepNode).length;\n } else {\n // Unable to find the target somehow.\n focusRelevant = false;\n }\n }\n\n if (focusRelevant) {\n nextNode.focus();\n } else {\n if (e.shiftKey) {\n // Focus on the last tabbable node in the step.\n this.currentStepNode.find(tabbableSelector).last().focus();\n } else {\n if (this.currentStepConfig.isOrphan) {\n // Focus on the step - there is no target.\n this.currentStepNode.focus();\n } else {\n // Focus on the step target.\n stepTarget.focus();\n }\n }\n }\n e.preventDefault();\n }).call(this);\n break;\n }\n }\n\n /**\n * Start the current tour.\n *\n * @method startTour\n * @param {Number} startAt Which step number to start at. If not specified, starts at the last point.\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/tourStart\n * @fires tool_usertours/tourStarted\n */\n startTour(startAt) {\n if (this.storage && typeof startAt === 'undefined') {\n let storageStartValue = this.storage.getItem(this.storageKey);\n if (storageStartValue) {\n let storageStartAt = parseInt(storageStartValue, 10);\n if (storageStartAt <= this.steps.length) {\n startAt = storageStartAt;\n }\n }\n }\n\n if (typeof startAt === 'undefined') {\n startAt = this.getCurrentStepNumber();\n }\n\n const tourStartEvent = this.dispatchEvent(eventTypes.tourStart, {startAt}, true);\n if (!tourStartEvent.defaultPrevented) {\n this.gotoStep(startAt);\n this.tourRunning = true;\n this.dispatchEvent(eventTypes.tourStarted, {startAt});\n }\n\n return this;\n }\n\n /**\n * Restart the tour from the beginning, resetting the completionlag.\n *\n * @method restartTour\n * @chainable\n * @return {Object} this.\n */\n restartTour() {\n return this.startTour(0);\n }\n\n /**\n * End the current tour.\n *\n * @method endTour\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/tourEnd\n * @fires tool_usertours/tourEnded\n */\n endTour() {\n const tourEndEvent = this.dispatchEvent(eventTypes.tourEnd, {}, true);\n if (tourEndEvent.defaultPrevented) {\n return this;\n }\n\n if (this.currentStepConfig) {\n let previousTarget = this.getStepTarget(this.currentStepConfig);\n if (previousTarget) {\n if (!previousTarget.attr('tabindex')) {\n previousTarget.attr('tabindex', '-1');\n }\n previousTarget.focus();\n }\n }\n\n this.hide(true);\n\n this.tourRunning = false;\n this.dispatchEvent(eventTypes.tourEnded);\n\n return this;\n }\n\n /**\n * Hide any currently visible steps.\n *\n * @method hide\n * @param {Bool} transition Animate the visibility change\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/stepHide\n * @fires tool_usertours/stepHidden\n */\n hide(transition) {\n const stepHideEvent = this.dispatchEvent(eventTypes.stepHide, {}, true);\n if (stepHideEvent.defaultPrevented) {\n return this;\n }\n\n if (this.currentStepNode && this.currentStepNode.length) {\n this.currentStepNode.hide();\n if (this.currentStepPopper) {\n this.currentStepPopper.destroy();\n }\n }\n\n // Restore original target configuration.\n if (this.currentStepConfig) {\n let target = this.getStepTarget(this.currentStepConfig);\n if (target) {\n if (target.data('original-labelledby')) {\n target.attr('aria-labelledby', target.data('original-labelledby'));\n }\n\n if (target.data('original-describedby')) {\n target.attr('aria-describedby', target.data('original-describedby'));\n }\n\n if (target.data('original-tabindex')) {\n target.attr('tabindex', target.data('tabindex'));\n }\n }\n\n // Clear the step configuration.\n this.currentStepConfig = null;\n }\n\n let fadeTime = 0;\n if (transition) {\n fadeTime = 400;\n }\n\n // Remove the backdrop features.\n $('[data-flexitour=\"step-background\"]').remove();\n $('[data-flexitour=\"step-backdrop\"]').removeAttr('data-flexitour');\n $('[data-flexitour=\"backdrop\"]').fadeOut(fadeTime, function() {\n $(this).remove();\n });\n\n // Remove aria-describedby and tabindex attributes.\n if (this.currentStepNode && this.currentStepNode.length) {\n let stepId = this.currentStepNode.attr('id');\n if (stepId) {\n let currentStepElement = '[aria-describedby=\"' + stepId + '-body\"]';\n $(currentStepElement).removeAttr('tabindex');\n $(currentStepElement).removeAttr('aria-describedby');\n }\n }\n\n // Reset the listeners.\n this.resetStepListeners();\n\n this.accessibilityHide();\n\n this.dispatchEvent(eventTypes.stepHidden);\n\n this.currentStepNode = null;\n this.currentStepPopper = null;\n return this;\n }\n\n /**\n * Show the current steps.\n *\n * @method show\n * @chainable\n * @return {Object} this.\n */\n show() {\n // Show the current step.\n let startAt = this.getCurrentStepNumber();\n\n return this.gotoStep(startAt);\n }\n\n /**\n * Return the current step node.\n *\n * @method getStepContainer\n * @return {jQuery}\n */\n getStepContainer() {\n return $(this.currentStepNode);\n }\n\n /**\n * Calculate scrollTop.\n *\n * @method calculateScrollTop\n * @param {Object} stepConfig The step configuration of the step\n * @return {Number}\n */\n calculateScrollTop(stepConfig) {\n let viewportHeight = $(window).height();\n let targetNode = this.getStepTarget(stepConfig);\n\n let scrollParent = $(window);\n if (targetNode.parents('[data-usertour=\"scroller\"]').length) {\n scrollParent = targetNode.parents('[data-usertour=\"scroller\"]');\n }\n let scrollTop = scrollParent.scrollTop();\n\n if (stepConfig.placement === 'top') {\n // If the placement is top, center scroll at the top of the target.\n scrollTop = targetNode.offset().top - (viewportHeight / 2);\n } else if (stepConfig.placement === 'bottom') {\n // If the placement is bottom, center scroll at the bottom of the target.\n scrollTop = targetNode.offset().top + targetNode.height() + scrollTop - (viewportHeight / 2);\n } else if (targetNode.height() <= (viewportHeight * 0.8)) {\n // If the placement is left/right, and the target fits in the viewport, centre screen on the target\n scrollTop = targetNode.offset().top - ((viewportHeight - targetNode.height()) / 2);\n } else {\n // If the placement is left/right, and the target is bigger than the viewport, set scrollTop to target.top + buffer\n // and change step attachmentTarget to top+.\n scrollTop = targetNode.offset().top - (viewportHeight * 0.2);\n }\n\n // Never scroll over the top.\n scrollTop = Math.max(0, scrollTop);\n\n // Never scroll beyond the bottom.\n scrollTop = Math.min($(document).height() - viewportHeight, scrollTop);\n\n return Math.ceil(scrollTop);\n }\n\n /**\n * Calculate dialogue position for page middle.\n *\n * @method calculateScrollTop\n * @return {Number}\n */\n calculateStepPositionInPage() {\n let viewportHeight = $(window).height();\n let stepHeight = this.currentStepNode.height();\n\n let viewportWidth = $(window).width();\n let stepWidth = this.currentStepNode.width();\n\n return {\n top: Math.ceil((viewportHeight - stepHeight) / 2),\n left: Math.ceil((viewportWidth - stepWidth) / 2)\n };\n }\n\n /**\n * Position the step on the page.\n *\n * @method positionStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n positionStep(stepConfig) {\n let content = this.currentStepNode;\n if (!content || !content.length) {\n // Unable to find the step node.\n return this;\n }\n\n stepConfig.placement = this.recalculatePlacement(stepConfig);\n let flipBehavior;\n switch (stepConfig.placement) {\n case 'left':\n flipBehavior = ['left', 'right', 'top', 'bottom'];\n break;\n case 'right':\n flipBehavior = ['right', 'left', 'top', 'bottom'];\n break;\n case 'top':\n flipBehavior = ['top', 'bottom', 'right', 'left'];\n break;\n case 'bottom':\n flipBehavior = ['bottom', 'top', 'right', 'left'];\n break;\n default:\n flipBehavior = 'flip';\n break;\n }\n\n let target = this.getStepTarget(stepConfig);\n var config = {\n placement: stepConfig.placement + '-start',\n removeOnDestroy: true,\n modifiers: {\n flip: {\n behaviour: flipBehavior,\n },\n arrow: {\n element: '[data-role=\"arrow\"]',\n },\n },\n onCreate: function(data) {\n recalculateArrowPosition(data);\n },\n onUpdate: function(data) {\n recalculateArrowPosition(data);\n },\n };\n\n let recalculateArrowPosition = function(data) {\n let placement = data.placement.split('-')[0];\n const isVertical = ['left', 'right'].indexOf(placement) !== -1;\n const arrowElement = data.instance.popper.querySelector('[data-role=\"arrow\"]');\n const stepElement = $(data.instance.popper.querySelector('[data-role=\"flexitour-step\"]'));\n if (isVertical) {\n let arrowHeight = parseFloat(window.getComputedStyle(arrowElement).height);\n let arrowOffset = parseFloat(window.getComputedStyle(arrowElement).top);\n let popperHeight = parseFloat(window.getComputedStyle(data.instance.popper).height);\n let popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).top);\n let popperBorderWidth = parseFloat(stepElement.css('borderTopWidth'));\n let popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2;\n let arrowPos = arrowOffset + (arrowHeight / 2);\n let maxPos = popperHeight + popperOffset - popperBorderWidth - popperBorderRadiusWidth;\n let minPos = popperOffset + popperBorderWidth + popperBorderRadiusWidth;\n if (arrowPos >= maxPos || arrowPos <= minPos) {\n let newArrowPos = 0;\n if (arrowPos > (popperHeight / 2)) {\n newArrowPos = maxPos - arrowHeight;\n } else {\n newArrowPos = minPos + arrowHeight;\n }\n $(arrowElement).css('top', newArrowPos);\n }\n } else {\n let arrowWidth = parseFloat(window.getComputedStyle(arrowElement).width);\n let arrowOffset = parseFloat(window.getComputedStyle(arrowElement).left);\n let popperWidth = parseFloat(window.getComputedStyle(data.instance.popper).width);\n let popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).left);\n let popperBorderWidth = parseFloat(stepElement.css('borderTopWidth'));\n let popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2;\n let arrowPos = arrowOffset + (arrowWidth / 2);\n let maxPos = popperWidth + popperOffset - popperBorderWidth - popperBorderRadiusWidth;\n let minPos = popperOffset + popperBorderWidth + popperBorderRadiusWidth;\n if (arrowPos >= maxPos || arrowPos <= minPos) {\n let newArrowPos = 0;\n if (arrowPos > (popperWidth / 2)) {\n newArrowPos = maxPos - arrowWidth;\n } else {\n newArrowPos = minPos + arrowWidth;\n }\n $(arrowElement).css('left', newArrowPos);\n }\n }\n };\n\n let background = $('[data-flexitour=\"step-background\"]');\n if (background.length) {\n target = background;\n }\n this.currentStepPopper = new Popper(target, content[0], config);\n\n return this;\n }\n\n /**\n * For left/right placement, checks that there is room for the step at current window size.\n *\n * If there is not enough room, changes placement to 'top'.\n *\n * @method recalculatePlacement\n * @param {Object} stepConfig The step configuration of the step\n * @return {String} The placement after recalculate\n */\n recalculatePlacement(stepConfig) {\n const buffer = 10;\n const arrowWidth = 16;\n let target = this.getStepTarget(stepConfig);\n let widthContent = this.currentStepNode.width() + arrowWidth;\n let targetOffsetLeft = target.offset().left - buffer;\n let targetOffsetRight = target.offset().left + target.width() + buffer;\n let placement = stepConfig.placement;\n\n if (['left', 'right'].indexOf(placement) !== -1) {\n if ((targetOffsetLeft < (widthContent + buffer)) &&\n ((targetOffsetRight + widthContent + buffer) > document.documentElement.clientWidth)) {\n placement = 'top';\n }\n }\n return placement;\n }\n\n /**\n * Add the backdrop.\n *\n * @method positionBackdrop\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n positionBackdrop(stepConfig) {\n if (stepConfig.backdrop) {\n this.currentStepConfig.hasBackdrop = true;\n let backdrop = $('');\n\n if (stepConfig.zIndex) {\n if (stepConfig.attachPoint === 'append') {\n stepConfig.attachTo.append(backdrop);\n } else {\n backdrop.insertAfter(stepConfig.attachTo);\n }\n } else {\n $('body').append(backdrop);\n }\n\n if (this.isStepActuallyVisible(stepConfig)) {\n // The step has a visible target.\n // Punch a hole through the backdrop.\n let background = $('[data-flexitour=\"step-background\"]');\n if (!background.length) {\n background = $('');\n }\n\n let targetNode = this.getStepTarget(stepConfig);\n\n let buffer = 10;\n\n let colorNode = targetNode;\n if (buffer) {\n colorNode = $('body');\n }\n\n let drawertop = 0;\n if (targetNode.parents('[data-usertour=\"scroller\"]').length) {\n const scrollerElement = targetNode.parents('[data-usertour=\"scroller\"]');\n const navigationBuffer = scrollerElement.offset().top;\n if (scrollerElement.scrollTop() >= navigationBuffer) {\n drawertop = scrollerElement.scrollTop() - navigationBuffer;\n background.css({\n position: 'fixed'\n });\n }\n }\n\n background.css({\n width: targetNode.outerWidth() + buffer + buffer,\n height: targetNode.outerHeight() + buffer + buffer,\n left: targetNode.offset().left - buffer,\n top: targetNode.offset().top + drawertop - buffer,\n backgroundColor: this.calculateInherittedBackgroundColor(colorNode),\n });\n\n if (targetNode.offset().left < buffer) {\n background.css({\n width: targetNode.outerWidth() + targetNode.offset().left + buffer,\n left: targetNode.offset().left,\n });\n }\n\n if ((targetNode.offset().top + drawertop) < buffer) {\n background.css({\n height: targetNode.outerHeight() + targetNode.offset().top + buffer,\n top: targetNode.offset().top,\n });\n }\n\n let targetRadius = targetNode.css('borderRadius');\n if (targetRadius && targetRadius !== $('body').css('borderRadius')) {\n background.css('borderRadius', targetRadius);\n }\n\n let targetPosition = this.calculatePosition(targetNode);\n if (targetPosition === 'fixed') {\n background.css('top', 0);\n } else if (targetPosition === 'absolute') {\n background.css('position', 'fixed');\n }\n\n let fader = background.clone();\n fader.css({\n backgroundColor: backdrop.css('backgroundColor'),\n opacity: backdrop.css('opacity'),\n });\n fader.attr('data-flexitour', 'step-background-fader');\n\n if (targetNode.parents('[data-region=\"fixed-drawer\"]').length) {\n let targetClone = targetNode.clone();\n background.append(targetClone);\n }\n\n if (stepConfig.zIndex) {\n if (stepConfig.attachPoint === 'append') {\n stepConfig.attachTo.append(background);\n } else {\n fader.insertAfter(stepConfig.attachTo);\n background.insertAfter(stepConfig.attachTo);\n }\n } else {\n $('body').append(fader);\n $('body').append(background);\n }\n\n // Add the backdrop data to the actual target.\n // This is the part which actually does the work.\n targetNode.attr('data-flexitour', 'step-backdrop');\n\n if (stepConfig.zIndex) {\n backdrop.css('zIndex', stepConfig.zIndex);\n background.css('zIndex', stepConfig.zIndex + 1);\n targetNode.css('zIndex', stepConfig.zIndex + 2);\n }\n\n fader.fadeOut('2000', function() {\n $(this).remove();\n });\n }\n }\n return this;\n }\n\n /**\n * Calculate the inheritted z-index.\n *\n * @method calculateZIndex\n * @param {jQuery} elem The element to calculate z-index for\n * @return {Number} Calculated z-index\n */\n calculateZIndex(elem) {\n elem = $(elem);\n while (elem.length && elem[0] !== document) {\n // Ignore z-index if position is set to a value where z-index is ignored by the browser\n // This makes behavior of this function consistent across browsers\n // WebKit always returns auto if the element is positioned.\n let position = elem.css(\"position\");\n if (position === \"absolute\" || position === \"relative\" || position === \"fixed\") {\n // IE returns 0 when zIndex is not specified\n // other browsers return a string\n // we ignore the case of nested elements with an explicit value of 0\n //
\n let value = parseInt(elem.css(\"zIndex\"), 10);\n if (!isNaN(value) && value !== 0) {\n return value;\n }\n }\n elem = elem.parent();\n }\n\n return 0;\n }\n\n /**\n * Calculate the inheritted background colour.\n *\n * @method calculateInherittedBackgroundColor\n * @param {jQuery} elem The element to calculate colour for\n * @return {String} Calculated background colour\n */\n calculateInherittedBackgroundColor(elem) {\n // Use a fake node to compare each element against.\n let fakeNode = $('
').hide();\n $('body').append(fakeNode);\n let fakeElemColor = fakeNode.css('backgroundColor');\n fakeNode.remove();\n\n elem = $(elem);\n while (elem.length && elem[0] !== document) {\n let color = elem.css('backgroundColor');\n if (color !== fakeElemColor) {\n return color;\n }\n elem = elem.parent();\n }\n\n return null;\n }\n\n /**\n * Calculate the inheritted position.\n *\n * @method calculatePosition\n * @param {jQuery} elem The element to calculate position for\n * @return {String} Calculated position\n */\n calculatePosition(elem) {\n elem = $(elem);\n while (elem.length && elem[0] !== document) {\n let position = elem.css('position');\n if (position !== 'static') {\n return position;\n }\n elem = elem.parent();\n }\n\n return null;\n }\n\n /**\n * Perform accessibility changes for step shown.\n *\n * This will add aria-hidden=\"true\" to all siblings and parent siblings.\n *\n * @method accessibilityShow\n */\n accessibilityShow() {\n let stateHolder = 'data-has-hidden';\n let attrName = 'aria-hidden';\n let hideFunction = function(child) {\n let flexitourRole = child.data('flexitour');\n if (flexitourRole) {\n switch (flexitourRole) {\n case 'container':\n case 'target':\n return;\n }\n }\n\n let hidden = child.attr(attrName);\n if (!hidden) {\n child.attr(stateHolder, true);\n Aria.hide(child);\n }\n };\n\n this.currentStepNode.siblings().each(function(index, node) {\n hideFunction($(node));\n });\n this.currentStepNode.parentsUntil('body').siblings().each(function(index, node) {\n hideFunction($(node));\n });\n }\n\n /**\n * Perform accessibility changes for step hidden.\n *\n * This will remove any newly added aria-hidden=\"true\".\n *\n * @method accessibilityHide\n */\n accessibilityHide() {\n let stateHolder = 'data-has-hidden';\n let showFunction = function(child) {\n let hidden = child.attr(stateHolder);\n if (typeof hidden !== 'undefined') {\n child.removeAttr(stateHolder);\n Aria.unhide(child);\n }\n };\n\n $('[' + stateHolder + ']').each(function(index, node) {\n showFunction($(node));\n });\n }\n};\n\nexport default Tour;\n"],"file":"tour.min.js"}
\ No newline at end of file
+{"version":3,"file":"tour.min.js","sources":["../src/tour.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 .\n\n/**\n * A user tour.\n *\n * @module tool_usertours/tour\n * @copyright 2018 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * A list of steps.\n *\n * @typedef {Object[]} StepList\n * @property {Number} stepId The id of the step in the database\n * @property {Number} position The position of the step within the tour (zero-indexed)\n */\n\nimport $ from 'jquery';\nimport * as Aria from 'core/aria';\nimport Popper from 'core/popper';\nimport {dispatchEvent} from 'core/event_dispatcher';\nimport {eventTypes} from './events';\nimport {get_string as getString} from 'core/str';\nimport {prefetchStrings} from 'core/prefetch';\n\n/**\n * A user tour.\n *\n * @class tool_usertours/tour\n * @property {boolean} tourRunning Whether the tour is currently running.\n */\nconst Tour = class {\n tourRunning = false;\n\n /**\n * @param {object} config The configuration object.\n */\n constructor(config) {\n this.init(config);\n }\n\n /**\n * Initialise the tour.\n *\n * @method init\n * @param {Object} config The configuration object.\n * @chainable\n * @return {Object} this.\n */\n init(config) {\n // Unset all handlers.\n this.eventHandlers = {};\n\n // Reset the current tour states.\n this.reset();\n\n // Store the initial configuration.\n this.originalConfiguration = config || {};\n\n // Apply configuration.\n this.configure.apply(this, arguments);\n\n try {\n this.storage = window.sessionStorage;\n this.storageKey = 'tourstate_' + this.tourName;\n } catch (e) {\n this.storage = false;\n this.storageKey = '';\n }\n\n prefetchStrings('tool_usertours', [\n 'nextstep_sequence',\n 'skip_tour'\n ]);\n\n return this;\n }\n\n /**\n * Reset the current tour state.\n *\n * @method reset\n * @chainable\n * @return {Object} this.\n */\n reset() {\n // Hide the current step.\n this.hide();\n\n // Unset all handlers.\n this.eventHandlers = [];\n\n // Unset all listeners.\n this.resetStepListeners();\n\n // Unset the original configuration.\n this.originalConfiguration = {};\n\n // Reset the current step number and list of steps.\n this.steps = [];\n\n // Reset the current step number.\n this.currentStepNumber = 0;\n\n return this;\n }\n\n /**\n * Prepare tour configuration.\n *\n * @method configure\n * @param {Object} config The configuration object.\n * @chainable\n * @return {Object} this.\n */\n configure(config) {\n if (typeof config === 'object') {\n // Tour name.\n if (typeof config.tourName !== 'undefined') {\n this.tourName = config.tourName;\n }\n\n // Set up eventHandlers.\n if (config.eventHandlers) {\n for (let eventName in config.eventHandlers) {\n config.eventHandlers[eventName].forEach(function(handler) {\n this.addEventHandler(eventName, handler);\n }, this);\n }\n }\n\n // Reset the step configuration.\n this.resetStepDefaults(true);\n\n // Configure the steps.\n if (typeof config.steps === 'object') {\n this.steps = config.steps;\n }\n\n if (typeof config.template !== 'undefined') {\n this.templateContent = config.template;\n }\n }\n\n // Check that we have enough to start the tour.\n this.checkMinimumRequirements();\n\n return this;\n }\n\n /**\n * Check that the configuration meets the minimum requirements.\n *\n * @method checkMinimumRequirements\n */\n checkMinimumRequirements() {\n // Need a tourName.\n if (!this.tourName) {\n throw new Error(\"Tour Name required\");\n }\n\n // Need a minimum of one step.\n if (!this.steps || !this.steps.length) {\n throw new Error(\"Steps must be specified\");\n }\n }\n\n /**\n * Reset step default configuration.\n *\n * @method resetStepDefaults\n * @param {Boolean} loadOriginalConfiguration Whether to load the original configuration supplied with the Tour.\n * @chainable\n * @return {Object} this.\n */\n resetStepDefaults(loadOriginalConfiguration) {\n if (typeof loadOriginalConfiguration === 'undefined') {\n loadOriginalConfiguration = true;\n }\n\n this.stepDefaults = {};\n if (!loadOriginalConfiguration || typeof this.originalConfiguration.stepDefaults === 'undefined') {\n this.setStepDefaults({});\n } else {\n this.setStepDefaults(this.originalConfiguration.stepDefaults);\n }\n\n return this;\n }\n\n /**\n * Set the step defaults.\n *\n * @method setStepDefaults\n * @param {Object} stepDefaults The step defaults to apply to all steps\n * @chainable\n * @return {Object} this.\n */\n setStepDefaults(stepDefaults) {\n if (!this.stepDefaults) {\n this.stepDefaults = {};\n }\n $.extend(\n this.stepDefaults,\n {\n element: '',\n placement: 'top',\n delay: 0,\n moveOnClick: false,\n moveAfterTime: 0,\n orphan: false,\n direction: 1,\n },\n stepDefaults\n );\n\n return this;\n }\n\n /**\n * Retrieve the current step number.\n *\n * @method getCurrentStepNumber\n * @return {Number} The current step number\n */\n getCurrentStepNumber() {\n return parseInt(this.currentStepNumber, 10);\n }\n\n /**\n * Store the current step number.\n *\n * @method setCurrentStepNumber\n * @param {Number} stepNumber The current step number\n * @chainable\n */\n setCurrentStepNumber(stepNumber) {\n this.currentStepNumber = stepNumber;\n if (this.storage) {\n try {\n this.storage.setItem(this.storageKey, stepNumber);\n } catch (e) {\n if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {\n this.storage.removeItem(this.storageKey);\n }\n }\n }\n }\n\n /**\n * Get the next step number after the currently displayed step.\n *\n * @method getNextStepNumber\n * @param {Number} stepNumber The current step number\n * @return {Number} The next step number to display\n */\n getNextStepNumber(stepNumber) {\n if (typeof stepNumber === 'undefined') {\n stepNumber = this.getCurrentStepNumber();\n }\n let nextStepNumber = stepNumber + 1;\n\n // Keep checking the remaining steps.\n while (nextStepNumber <= this.steps.length) {\n if (this.isStepPotentiallyVisible(this.getStepConfig(nextStepNumber))) {\n return nextStepNumber;\n }\n nextStepNumber++;\n }\n\n return null;\n }\n\n /**\n * Get the previous step number before the currently displayed step.\n *\n * @method getPreviousStepNumber\n * @param {Number} stepNumber The current step number\n * @return {Number} The previous step number to display\n */\n getPreviousStepNumber(stepNumber) {\n if (typeof stepNumber === 'undefined') {\n stepNumber = this.getCurrentStepNumber();\n }\n let previousStepNumber = stepNumber - 1;\n\n // Keep checking the remaining steps.\n while (previousStepNumber >= 0) {\n if (this.isStepPotentiallyVisible(this.getStepConfig(previousStepNumber))) {\n return previousStepNumber;\n }\n previousStepNumber--;\n }\n\n return null;\n }\n\n /**\n * Is the step the final step number?\n *\n * @method isLastStep\n * @param {Number} stepNumber Step number to test\n * @return {Boolean} Whether the step is the final step\n */\n isLastStep(stepNumber) {\n let nextStepNumber = this.getNextStepNumber(stepNumber);\n\n return nextStepNumber === null;\n }\n\n /**\n * Is this step potentially visible?\n *\n * @method isStepPotentiallyVisible\n * @param {Object} stepConfig The step configuration to normalise\n * @return {Boolean} Whether the step is the potentially visible\n */\n isStepPotentiallyVisible(stepConfig) {\n if (!stepConfig) {\n // Without step config, there can be no step.\n return false;\n }\n\n if (this.isStepActuallyVisible(stepConfig)) {\n // If it is actually visible, it is already potentially visible.\n return true;\n }\n\n if (typeof stepConfig.orphan !== 'undefined' && stepConfig.orphan) {\n // Orphan steps have no target. They are always visible.\n return true;\n }\n\n if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay) {\n // Only return true if the activated has not been used yet.\n return true;\n }\n\n // Not theoretically, or actually visible.\n return false;\n }\n\n /**\n * Get potentially visible steps in a tour.\n *\n * @returns {StepList} A list of ordered steps\n */\n getPotentiallyVisibleSteps() {\n let position = 1;\n let result = [];\n // Checking the total steps.\n for (let stepNumber = 0; stepNumber < this.steps.length; stepNumber++) {\n const stepConfig = this.getStepConfig(stepNumber);\n if (this.isStepPotentiallyVisible(stepConfig)) {\n result[stepNumber] = {stepId: stepConfig.stepid, position: position};\n position++;\n }\n }\n\n return result;\n }\n\n /**\n * Is this step actually visible?\n *\n * @method isStepActuallyVisible\n * @param {Object} stepConfig The step configuration to normalise\n * @return {Boolean} Whether the step is actually visible\n */\n isStepActuallyVisible(stepConfig) {\n if (!stepConfig) {\n // Without step config, there can be no step.\n return false;\n }\n\n let target = this.getStepTarget(stepConfig);\n if (target && target.length && target.is(':visible')) {\n // Without a target, there can be no step.\n return !!target.length;\n }\n\n return false;\n }\n\n /**\n * Go to the next step in the tour.\n *\n * @method next\n * @chainable\n * @return {Object} this.\n */\n next() {\n return this.gotoStep(this.getNextStepNumber());\n }\n\n /**\n * Go to the previous step in the tour.\n *\n * @method previous\n * @chainable\n * @return {Object} this.\n */\n previous() {\n return this.gotoStep(this.getPreviousStepNumber(), -1);\n }\n\n /**\n * Go to the specified step in the tour.\n *\n * @method gotoStep\n * @param {Number} stepNumber The step number to display\n * @param {Number} direction Next or previous step\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/stepRender\n * @fires tool_usertours/stepRendered\n * @fires tool_usertours/stepHide\n * @fires tool_usertours/stepHidden\n */\n gotoStep(stepNumber, direction) {\n if (stepNumber < 0) {\n return this.endTour();\n }\n\n let stepConfig = this.getStepConfig(stepNumber);\n if (stepConfig === null) {\n return this.endTour();\n }\n\n return this._gotoStep(stepConfig, direction);\n }\n\n _gotoStep(stepConfig, direction) {\n if (!stepConfig) {\n return this.endTour();\n }\n\n if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay && !stepConfig.delayed) {\n stepConfig.delayed = true;\n window.setTimeout(this._gotoStep.bind(this), stepConfig.delay, stepConfig, direction);\n\n return this;\n } else if (!stepConfig.orphan && !this.isStepActuallyVisible(stepConfig)) {\n let fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber';\n return this.gotoStep(this[fn](stepConfig.stepNumber), direction);\n }\n\n this.hide();\n\n const stepRenderEvent = this.dispatchEvent(eventTypes.stepRender, {stepConfig}, true);\n if (!stepRenderEvent.defaultPrevented) {\n this.renderStep(stepConfig);\n this.dispatchEvent(eventTypes.stepRendered, {stepConfig});\n }\n\n return this;\n }\n\n /**\n * Fetch the normalised step configuration for the specified step number.\n *\n * @method getStepConfig\n * @param {Number} stepNumber The step number to fetch configuration for\n * @return {Object} The step configuration\n */\n getStepConfig(stepNumber) {\n if (stepNumber === null || stepNumber < 0 || stepNumber >= this.steps.length) {\n return null;\n }\n\n // Normalise the step configuration.\n let stepConfig = this.normalizeStepConfig(this.steps[stepNumber]);\n\n // Add the stepNumber to the stepConfig.\n stepConfig = $.extend(stepConfig, {stepNumber: stepNumber});\n\n return stepConfig;\n }\n\n /**\n * Normalise the supplied step configuration.\n *\n * @method normalizeStepConfig\n * @param {Object} stepConfig The step configuration to normalise\n * @return {Object} The normalised step configuration\n */\n normalizeStepConfig(stepConfig) {\n\n if (typeof stepConfig.reflex !== 'undefined' && typeof stepConfig.moveAfterClick === 'undefined') {\n stepConfig.moveAfterClick = stepConfig.reflex;\n }\n\n if (typeof stepConfig.element !== 'undefined' && typeof stepConfig.target === 'undefined') {\n stepConfig.target = stepConfig.element;\n }\n\n if (typeof stepConfig.content !== 'undefined' && typeof stepConfig.body === 'undefined') {\n stepConfig.body = stepConfig.content;\n }\n\n stepConfig = $.extend({}, this.stepDefaults, stepConfig);\n\n stepConfig = $.extend({}, {\n attachTo: stepConfig.target,\n attachPoint: 'after',\n }, stepConfig);\n\n if (stepConfig.attachTo) {\n stepConfig.attachTo = $(stepConfig.attachTo).first();\n }\n\n return stepConfig;\n }\n\n /**\n * Fetch the actual step target from the selector.\n *\n * This should not be called until after any delay has completed.\n *\n * @method getStepTarget\n * @param {Object} stepConfig The step configuration\n * @return {$}\n */\n getStepTarget(stepConfig) {\n if (stepConfig.target) {\n return $(stepConfig.target);\n }\n\n return null;\n }\n\n /**\n * Fire any event handlers for the specified event.\n *\n * @param {String} eventName The name of the event\n * @param {Object} [detail={}] Any additional details to pass into the eveent\n * @param {Boolean} [cancelable=false] Whether preventDefault() can be called\n * @returns {CustomEvent}\n */\n dispatchEvent(\n eventName,\n detail = {},\n cancelable = false\n ) {\n return dispatchEvent(eventName, {\n // Add the tour to the detail.\n tour: this,\n ...detail,\n }, document, {\n cancelable,\n });\n }\n\n /**\n * @method addEventHandler\n * @param {string} eventName The name of the event to listen for\n * @param {function} handler The event handler to call\n * @return {Object} this.\n */\n addEventHandler(eventName, handler) {\n if (typeof this.eventHandlers[eventName] === 'undefined') {\n this.eventHandlers[eventName] = [];\n }\n\n this.eventHandlers[eventName].push(handler);\n\n return this;\n }\n\n /**\n * Process listeners for the step being shown.\n *\n * @method processStepListeners\n * @param {object} stepConfig The configuration for the step\n * @chainable\n * @return {Object} this.\n */\n processStepListeners(stepConfig) {\n this.listeners.push(\n // Next button.\n {\n node: this.currentStepNode,\n args: ['click', '[data-role=\"next\"]', $.proxy(this.next, this)]\n },\n\n // Close and end tour buttons.\n {\n node: this.currentStepNode,\n args: ['click', '[data-role=\"end\"]', $.proxy(this.endTour, this)]\n },\n\n // Click backdrop and hide tour.\n {\n node: $('[data-flexitour=\"backdrop\"]'),\n args: ['click', $.proxy(this.hide, this)]\n },\n\n // Keypresses.\n {\n node: $('body'),\n args: ['keydown', $.proxy(this.handleKeyDown, this)]\n });\n\n if (stepConfig.moveOnClick) {\n var targetNode = this.getStepTarget(stepConfig);\n this.listeners.push({\n node: targetNode,\n args: ['click', $.proxy(function(e) {\n if ($(e.target).parents('[data-flexitour=\"container\"]').length === 0) {\n // Ignore clicks when they are in the flexitour.\n window.setTimeout($.proxy(this.next, this), 500);\n }\n }, this)]\n });\n }\n\n this.listeners.forEach(function(listener) {\n listener.node.on.apply(listener.node, listener.args);\n });\n\n return this;\n }\n\n /**\n * Reset step listeners.\n *\n * @method resetStepListeners\n * @chainable\n * @return {Object} this.\n */\n resetStepListeners() {\n // Stop listening to all external handlers.\n if (this.listeners) {\n this.listeners.forEach(function(listener) {\n listener.node.off.apply(listener.node, listener.args);\n });\n }\n this.listeners = [];\n\n return this;\n }\n\n /**\n * The standard step renderer.\n *\n * @method renderStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n renderStep(stepConfig) {\n // Store the current step configuration for later.\n this.currentStepConfig = stepConfig;\n this.setCurrentStepNumber(stepConfig.stepNumber);\n\n // Fetch the template and convert it to a $ object.\n let template = $(this.getTemplateContent());\n\n // Title.\n template.find('[data-placeholder=\"title\"]')\n .html(stepConfig.title);\n\n // Body.\n template.find('[data-placeholder=\"body\"]')\n .html(stepConfig.body);\n\n // Buttons.\n const nextBtn = template.find('[data-role=\"next\"]');\n const endBtn = template.find('[data-role=\"end\"]');\n\n // Is this the final step?\n if (this.isLastStep(stepConfig.stepNumber)) {\n nextBtn.hide();\n endBtn.removeClass(\"btn-secondary\").addClass(\"btn-primary\");\n } else {\n nextBtn.prop('disabled', false);\n // Use Skip tour label for the End tour button.\n getString('skip_tour', 'tool_usertours').then(value => {\n endBtn.html(value);\n return;\n }).catch();\n }\n\n nextBtn.attr('role', 'button');\n endBtn.attr('role', 'button');\n\n if (this.originalConfiguration.displaystepnumbers) {\n const stepsPotentiallyVisible = this.getPotentiallyVisibleSteps();\n const totalStepsPotentiallyVisible = stepsPotentiallyVisible.length;\n const position = stepsPotentiallyVisible[stepConfig.stepNumber].position;\n if (totalStepsPotentiallyVisible > 1) {\n // Change the label of the Next button to include the sequence.\n getString('nextstep_sequence', 'tool_usertours',\n {position: position, total: totalStepsPotentiallyVisible}).then(value => {\n nextBtn.html(value);\n return;\n }).catch();\n }\n }\n\n // Replace the template with the updated version.\n stepConfig.template = template;\n\n // Add to the page.\n this.addStepToPage(stepConfig);\n\n // Process step listeners after adding to the page.\n // This uses the currentNode.\n this.processStepListeners(stepConfig);\n\n return this;\n }\n\n /**\n * Getter for the template content.\n *\n * @method getTemplateContent\n * @return {$}\n */\n getTemplateContent() {\n return $(this.templateContent).clone();\n }\n\n /**\n * Helper to add a step to the page.\n *\n * @method addStepToPage\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n addStepToPage(stepConfig) {\n // Create the stepNode from the template data.\n let currentStepNode = $('')\n .html(stepConfig.template)\n .hide();\n\n // The scroll animation occurs on the body or html.\n let animationTarget = $('body, html')\n .stop(true, true);\n\n if (this.isStepActuallyVisible(stepConfig)) {\n let targetNode = this.getStepTarget(stepConfig);\n\n if (targetNode.parents('[data-usertour=\"scroller\"]').length) {\n animationTarget = targetNode.parents('[data-usertour=\"scroller\"]');\n }\n\n targetNode.data('flexitour', 'target');\n\n let zIndex = this.calculateZIndex(targetNode);\n if (zIndex) {\n stepConfig.zIndex = zIndex + 1;\n }\n\n if (stepConfig.zIndex) {\n currentStepNode.css('zIndex', stepConfig.zIndex + 1);\n }\n\n // Add the backdrop.\n this.positionBackdrop(stepConfig);\n\n $(document.body).append(currentStepNode);\n this.currentStepNode = currentStepNode;\n\n // Ensure that the step node is positioned.\n // Some situations mean that the value is not properly calculated without this step.\n this.currentStepNode.css({\n top: 0,\n left: 0,\n });\n\n animationTarget\n .animate({\n scrollTop: this.calculateScrollTop(stepConfig),\n }).promise().then(function() {\n this.positionStep(stepConfig);\n this.revealStep(stepConfig);\n return;\n }.bind(this))\n .catch(function() {\n // Silently fail.\n });\n\n } else if (stepConfig.orphan) {\n stepConfig.isOrphan = true;\n\n // This will be appended to the body instead.\n stepConfig.attachTo = $('body').first();\n stepConfig.attachPoint = 'append';\n\n // Add the backdrop.\n this.positionBackdrop(stepConfig);\n\n // This is an orphaned step.\n currentStepNode.addClass('orphan');\n\n // It lives in the body.\n $(document.body).append(currentStepNode);\n this.currentStepNode = currentStepNode;\n\n this.currentStepNode.offset(this.calculateStepPositionInPage());\n this.currentStepNode.css('position', 'fixed');\n\n this.currentStepPopper = new Popper(\n $('body'),\n this.currentStepNode[0], {\n removeOnDestroy: true,\n placement: stepConfig.placement + '-start',\n arrowElement: '[data-role=\"arrow\"]',\n // Empty the modifiers. We've already placed the step and don't want it moved.\n modifiers: {\n hide: {\n enabled: false,\n },\n applyStyle: {\n onLoad: null,\n enabled: false,\n },\n }\n }\n );\n\n this.revealStep(stepConfig);\n }\n\n return this;\n }\n\n /**\n * Make the given step visible.\n *\n * @method revealStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n revealStep(stepConfig) {\n // Fade the step in.\n this.currentStepNode.fadeIn('', $.proxy(function() {\n // Announce via ARIA.\n this.announceStep(stepConfig);\n\n // Focus on the current step Node.\n this.currentStepNode.focus();\n window.setTimeout($.proxy(function() {\n // After a brief delay, focus again.\n // There seems to be an issue with Jaws where it only reads the dialogue title initially.\n // This second focus helps it to read the full dialogue.\n if (this.currentStepNode) {\n this.currentStepNode.focus();\n }\n }, this), 100);\n\n }, this));\n\n return this;\n }\n\n /**\n * Helper to announce the step on the page.\n *\n * @method announceStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n announceStep(stepConfig) {\n // Setup the step Dialogue as per:\n // * https://www.w3.org/TR/wai-aria-practices/#dialog_nonmodal\n // * https://www.w3.org/TR/wai-aria-practices/#dialog_modal\n\n // Generate an ID for the current step node.\n let stepId = 'tour-step-' + this.tourName + '-' + stepConfig.stepNumber;\n this.currentStepNode.attr('id', stepId);\n\n let bodyRegion = this.currentStepNode.find('[data-placeholder=\"body\"]').first();\n bodyRegion.attr('id', stepId + '-body');\n bodyRegion.attr('role', 'document');\n\n let headerRegion = this.currentStepNode.find('[data-placeholder=\"title\"]').first();\n headerRegion.attr('id', stepId + '-title');\n headerRegion.attr('aria-labelledby', stepId + '-body');\n\n // Generally, a modal dialog has a role of dialog.\n this.currentStepNode.attr('role', 'dialog');\n this.currentStepNode.attr('tabindex', 0);\n this.currentStepNode.attr('aria-labelledby', stepId + '-title');\n this.currentStepNode.attr('aria-describedby', stepId + '-body');\n\n // Configure ARIA attributes on the target.\n let target = this.getStepTarget(stepConfig);\n if (target) {\n if (!target.attr('tabindex')) {\n target.attr('tabindex', 0);\n }\n\n target\n .data('original-describedby', target.attr('aria-describedby'))\n .attr('aria-describedby', stepId + '-body')\n ;\n }\n\n this.accessibilityShow(stepConfig);\n\n return this;\n }\n\n /**\n * Handle key down events.\n *\n * @method handleKeyDown\n * @param {EventFacade} e\n */\n handleKeyDown(e) {\n let tabbableSelector = 'a[href], link[href], [draggable=true], [contenteditable=true], ';\n tabbableSelector += ':input:enabled, [tabindex], button:enabled';\n switch (e.keyCode) {\n case 27:\n this.endTour();\n break;\n\n // 9 == Tab - trap focus for items with a backdrop.\n case 9:\n // Tab must be handled on key up only in this instance.\n (function() {\n if (!this.currentStepConfig.hasBackdrop) {\n // Trapping tab focus is only handled for those steps with a backdrop.\n return;\n }\n\n // Find all tabbable locations.\n let activeElement = $(document.activeElement);\n let stepTarget = this.getStepTarget(this.currentStepConfig);\n let tabbableNodes = $(tabbableSelector);\n let dialogContainer = $('span[data-flexitour=\"container\"]');\n let currentIndex;\n // Filter out element which is not belong to target section or dialogue.\n if (stepTarget) {\n tabbableNodes = tabbableNodes.filter(function(index, element) {\n return stepTarget !== null\n && (stepTarget.has(element).length\n || dialogContainer.has(element).length\n || stepTarget.is(element)\n || dialogContainer.is(element));\n });\n }\n\n // Find index of focusing element.\n tabbableNodes.each(function(index, element) {\n if (activeElement.is(element)) {\n currentIndex = index;\n return false;\n }\n // Keep looping.\n return true;\n });\n\n let nextIndex;\n let nextNode;\n let focusRelevant;\n if (currentIndex != void 0) {\n let direction = 1;\n if (e.shiftKey) {\n direction = -1;\n }\n nextIndex = currentIndex;\n do {\n nextIndex += direction;\n nextNode = $(tabbableNodes[nextIndex]);\n } while (nextNode.length && nextNode.is(':disabled') || nextNode.is(':hidden'));\n if (nextNode.length) {\n // A new f\n focusRelevant = nextNode.closest(stepTarget).length;\n focusRelevant = focusRelevant || nextNode.closest(this.currentStepNode).length;\n } else {\n // Unable to find the target somehow.\n focusRelevant = false;\n }\n }\n\n if (focusRelevant) {\n nextNode.focus();\n } else {\n if (e.shiftKey) {\n // Focus on the last tabbable node in the step.\n this.currentStepNode.find(tabbableSelector).last().focus();\n } else {\n if (this.currentStepConfig.isOrphan) {\n // Focus on the step - there is no target.\n this.currentStepNode.focus();\n } else {\n // Focus on the step target.\n stepTarget.focus();\n }\n }\n }\n e.preventDefault();\n }).call(this);\n break;\n }\n }\n\n /**\n * Start the current tour.\n *\n * @method startTour\n * @param {Number} startAt Which step number to start at. If not specified, starts at the last point.\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/tourStart\n * @fires tool_usertours/tourStarted\n */\n startTour(startAt) {\n if (this.storage && typeof startAt === 'undefined') {\n let storageStartValue = this.storage.getItem(this.storageKey);\n if (storageStartValue) {\n let storageStartAt = parseInt(storageStartValue, 10);\n if (storageStartAt <= this.steps.length) {\n startAt = storageStartAt;\n }\n }\n }\n\n if (typeof startAt === 'undefined') {\n startAt = this.getCurrentStepNumber();\n }\n\n const tourStartEvent = this.dispatchEvent(eventTypes.tourStart, {startAt}, true);\n if (!tourStartEvent.defaultPrevented) {\n this.gotoStep(startAt);\n this.tourRunning = true;\n this.dispatchEvent(eventTypes.tourStarted, {startAt});\n }\n\n return this;\n }\n\n /**\n * Restart the tour from the beginning, resetting the completionlag.\n *\n * @method restartTour\n * @chainable\n * @return {Object} this.\n */\n restartTour() {\n return this.startTour(0);\n }\n\n /**\n * End the current tour.\n *\n * @method endTour\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/tourEnd\n * @fires tool_usertours/tourEnded\n */\n endTour() {\n const tourEndEvent = this.dispatchEvent(eventTypes.tourEnd, {}, true);\n if (tourEndEvent.defaultPrevented) {\n return this;\n }\n\n if (this.currentStepConfig) {\n let previousTarget = this.getStepTarget(this.currentStepConfig);\n if (previousTarget) {\n if (!previousTarget.attr('tabindex')) {\n previousTarget.attr('tabindex', '-1');\n }\n previousTarget.focus();\n }\n }\n\n this.hide(true);\n\n this.tourRunning = false;\n this.dispatchEvent(eventTypes.tourEnded);\n\n return this;\n }\n\n /**\n * Hide any currently visible steps.\n *\n * @method hide\n * @param {Bool} transition Animate the visibility change\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/stepHide\n * @fires tool_usertours/stepHidden\n */\n hide(transition) {\n const stepHideEvent = this.dispatchEvent(eventTypes.stepHide, {}, true);\n if (stepHideEvent.defaultPrevented) {\n return this;\n }\n\n if (this.currentStepNode && this.currentStepNode.length) {\n this.currentStepNode.hide();\n if (this.currentStepPopper) {\n this.currentStepPopper.destroy();\n }\n }\n\n // Restore original target configuration.\n if (this.currentStepConfig) {\n let target = this.getStepTarget(this.currentStepConfig);\n if (target) {\n if (target.data('original-labelledby')) {\n target.attr('aria-labelledby', target.data('original-labelledby'));\n }\n\n if (target.data('original-describedby')) {\n target.attr('aria-describedby', target.data('original-describedby'));\n }\n\n if (target.data('original-tabindex')) {\n target.attr('tabindex', target.data('tabindex'));\n }\n }\n\n // Clear the step configuration.\n this.currentStepConfig = null;\n }\n\n let fadeTime = 0;\n if (transition) {\n fadeTime = 400;\n }\n\n // Remove the backdrop features.\n $('[data-flexitour=\"step-background\"]').remove();\n $('[data-flexitour=\"step-backdrop\"]').removeAttr('data-flexitour');\n $('[data-flexitour=\"backdrop\"]').fadeOut(fadeTime, function() {\n $(this).remove();\n });\n\n // Remove aria-describedby and tabindex attributes.\n if (this.currentStepNode && this.currentStepNode.length) {\n let stepId = this.currentStepNode.attr('id');\n if (stepId) {\n let currentStepElement = '[aria-describedby=\"' + stepId + '-body\"]';\n $(currentStepElement).removeAttr('tabindex');\n $(currentStepElement).removeAttr('aria-describedby');\n }\n }\n\n // Reset the listeners.\n this.resetStepListeners();\n\n this.accessibilityHide();\n\n this.dispatchEvent(eventTypes.stepHidden);\n\n this.currentStepNode = null;\n this.currentStepPopper = null;\n return this;\n }\n\n /**\n * Show the current steps.\n *\n * @method show\n * @chainable\n * @return {Object} this.\n */\n show() {\n // Show the current step.\n let startAt = this.getCurrentStepNumber();\n\n return this.gotoStep(startAt);\n }\n\n /**\n * Return the current step node.\n *\n * @method getStepContainer\n * @return {jQuery}\n */\n getStepContainer() {\n return $(this.currentStepNode);\n }\n\n /**\n * Calculate scrollTop.\n *\n * @method calculateScrollTop\n * @param {Object} stepConfig The step configuration of the step\n * @return {Number}\n */\n calculateScrollTop(stepConfig) {\n let viewportHeight = $(window).height();\n let targetNode = this.getStepTarget(stepConfig);\n\n let scrollParent = $(window);\n if (targetNode.parents('[data-usertour=\"scroller\"]').length) {\n scrollParent = targetNode.parents('[data-usertour=\"scroller\"]');\n }\n let scrollTop = scrollParent.scrollTop();\n\n if (stepConfig.placement === 'top') {\n // If the placement is top, center scroll at the top of the target.\n scrollTop = targetNode.offset().top - (viewportHeight / 2);\n } else if (stepConfig.placement === 'bottom') {\n // If the placement is bottom, center scroll at the bottom of the target.\n scrollTop = targetNode.offset().top + targetNode.height() + scrollTop - (viewportHeight / 2);\n } else if (targetNode.height() <= (viewportHeight * 0.8)) {\n // If the placement is left/right, and the target fits in the viewport, centre screen on the target\n scrollTop = targetNode.offset().top - ((viewportHeight - targetNode.height()) / 2);\n } else {\n // If the placement is left/right, and the target is bigger than the viewport, set scrollTop to target.top + buffer\n // and change step attachmentTarget to top+.\n scrollTop = targetNode.offset().top - (viewportHeight * 0.2);\n }\n\n // Never scroll over the top.\n scrollTop = Math.max(0, scrollTop);\n\n // Never scroll beyond the bottom.\n scrollTop = Math.min($(document).height() - viewportHeight, scrollTop);\n\n return Math.ceil(scrollTop);\n }\n\n /**\n * Calculate dialogue position for page middle.\n *\n * @method calculateScrollTop\n * @return {Number}\n */\n calculateStepPositionInPage() {\n let viewportHeight = $(window).height();\n let stepHeight = this.currentStepNode.height();\n\n let viewportWidth = $(window).width();\n let stepWidth = this.currentStepNode.width();\n\n return {\n top: Math.ceil((viewportHeight - stepHeight) / 2),\n left: Math.ceil((viewportWidth - stepWidth) / 2)\n };\n }\n\n /**\n * Position the step on the page.\n *\n * @method positionStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n positionStep(stepConfig) {\n let content = this.currentStepNode;\n if (!content || !content.length) {\n // Unable to find the step node.\n return this;\n }\n\n stepConfig.placement = this.recalculatePlacement(stepConfig);\n let flipBehavior;\n switch (stepConfig.placement) {\n case 'left':\n flipBehavior = ['left', 'right', 'top', 'bottom'];\n break;\n case 'right':\n flipBehavior = ['right', 'left', 'top', 'bottom'];\n break;\n case 'top':\n flipBehavior = ['top', 'bottom', 'right', 'left'];\n break;\n case 'bottom':\n flipBehavior = ['bottom', 'top', 'right', 'left'];\n break;\n default:\n flipBehavior = 'flip';\n break;\n }\n\n let target = this.getStepTarget(stepConfig);\n var config = {\n placement: stepConfig.placement + '-start',\n removeOnDestroy: true,\n modifiers: {\n flip: {\n behaviour: flipBehavior,\n },\n arrow: {\n element: '[data-role=\"arrow\"]',\n },\n },\n onCreate: function(data) {\n recalculateArrowPosition(data);\n },\n onUpdate: function(data) {\n recalculateArrowPosition(data);\n },\n };\n\n let recalculateArrowPosition = function(data) {\n let placement = data.placement.split('-')[0];\n const isVertical = ['left', 'right'].indexOf(placement) !== -1;\n const arrowElement = data.instance.popper.querySelector('[data-role=\"arrow\"]');\n const stepElement = $(data.instance.popper.querySelector('[data-role=\"flexitour-step\"]'));\n if (isVertical) {\n let arrowHeight = parseFloat(window.getComputedStyle(arrowElement).height);\n let arrowOffset = parseFloat(window.getComputedStyle(arrowElement).top);\n let popperHeight = parseFloat(window.getComputedStyle(data.instance.popper).height);\n let popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).top);\n let popperBorderWidth = parseFloat(stepElement.css('borderTopWidth'));\n let popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2;\n let arrowPos = arrowOffset + (arrowHeight / 2);\n let maxPos = popperHeight + popperOffset - popperBorderWidth - popperBorderRadiusWidth;\n let minPos = popperOffset + popperBorderWidth + popperBorderRadiusWidth;\n if (arrowPos >= maxPos || arrowPos <= minPos) {\n let newArrowPos = 0;\n if (arrowPos > (popperHeight / 2)) {\n newArrowPos = maxPos - arrowHeight;\n } else {\n newArrowPos = minPos + arrowHeight;\n }\n $(arrowElement).css('top', newArrowPos);\n }\n } else {\n let arrowWidth = parseFloat(window.getComputedStyle(arrowElement).width);\n let arrowOffset = parseFloat(window.getComputedStyle(arrowElement).left);\n let popperWidth = parseFloat(window.getComputedStyle(data.instance.popper).width);\n let popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).left);\n let popperBorderWidth = parseFloat(stepElement.css('borderTopWidth'));\n let popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2;\n let arrowPos = arrowOffset + (arrowWidth / 2);\n let maxPos = popperWidth + popperOffset - popperBorderWidth - popperBorderRadiusWidth;\n let minPos = popperOffset + popperBorderWidth + popperBorderRadiusWidth;\n if (arrowPos >= maxPos || arrowPos <= minPos) {\n let newArrowPos = 0;\n if (arrowPos > (popperWidth / 2)) {\n newArrowPos = maxPos - arrowWidth;\n } else {\n newArrowPos = minPos + arrowWidth;\n }\n $(arrowElement).css('left', newArrowPos);\n }\n }\n };\n\n let background = $('[data-flexitour=\"step-background\"]');\n if (background.length) {\n target = background;\n }\n this.currentStepPopper = new Popper(target, content[0], config);\n\n return this;\n }\n\n /**\n * For left/right placement, checks that there is room for the step at current window size.\n *\n * If there is not enough room, changes placement to 'top'.\n *\n * @method recalculatePlacement\n * @param {Object} stepConfig The step configuration of the step\n * @return {String} The placement after recalculate\n */\n recalculatePlacement(stepConfig) {\n const buffer = 10;\n const arrowWidth = 16;\n let target = this.getStepTarget(stepConfig);\n let widthContent = this.currentStepNode.width() + arrowWidth;\n let targetOffsetLeft = target.offset().left - buffer;\n let targetOffsetRight = target.offset().left + target.width() + buffer;\n let placement = stepConfig.placement;\n\n if (['left', 'right'].indexOf(placement) !== -1) {\n if ((targetOffsetLeft < (widthContent + buffer)) &&\n ((targetOffsetRight + widthContent + buffer) > document.documentElement.clientWidth)) {\n placement = 'top';\n }\n }\n return placement;\n }\n\n /**\n * Add the backdrop.\n *\n * @method positionBackdrop\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n positionBackdrop(stepConfig) {\n if (stepConfig.backdrop) {\n this.currentStepConfig.hasBackdrop = true;\n let backdrop = $('');\n\n if (stepConfig.zIndex) {\n if (stepConfig.attachPoint === 'append') {\n stepConfig.attachTo.append(backdrop);\n } else {\n backdrop.insertAfter(stepConfig.attachTo);\n }\n } else {\n $('body').append(backdrop);\n }\n\n if (this.isStepActuallyVisible(stepConfig)) {\n // The step has a visible target.\n // Punch a hole through the backdrop.\n let background = $('[data-flexitour=\"step-background\"]');\n if (!background.length) {\n background = $('');\n }\n\n let targetNode = this.getStepTarget(stepConfig);\n\n let buffer = 10;\n\n let colorNode = targetNode;\n if (buffer) {\n colorNode = $('body');\n }\n\n let drawertop = 0;\n if (targetNode.parents('[data-usertour=\"scroller\"]').length) {\n const scrollerElement = targetNode.parents('[data-usertour=\"scroller\"]');\n const navigationBuffer = scrollerElement.offset().top;\n if (scrollerElement.scrollTop() >= navigationBuffer) {\n drawertop = scrollerElement.scrollTop() - navigationBuffer;\n background.css({\n position: 'fixed'\n });\n }\n }\n\n background.css({\n width: targetNode.outerWidth() + buffer + buffer,\n height: targetNode.outerHeight() + buffer + buffer,\n left: targetNode.offset().left - buffer,\n top: targetNode.offset().top + drawertop - buffer,\n backgroundColor: this.calculateInherittedBackgroundColor(colorNode),\n });\n\n if (targetNode.offset().left < buffer) {\n background.css({\n width: targetNode.outerWidth() + targetNode.offset().left + buffer,\n left: targetNode.offset().left,\n });\n }\n\n if ((targetNode.offset().top + drawertop) < buffer) {\n background.css({\n height: targetNode.outerHeight() + targetNode.offset().top + buffer,\n top: targetNode.offset().top,\n });\n }\n\n let targetRadius = targetNode.css('borderRadius');\n if (targetRadius && targetRadius !== $('body').css('borderRadius')) {\n background.css('borderRadius', targetRadius);\n }\n\n let targetPosition = this.calculatePosition(targetNode);\n if (targetPosition === 'fixed') {\n background.css('top', 0);\n } else if (targetPosition === 'absolute') {\n background.css('position', 'fixed');\n }\n\n let fader = background.clone();\n fader.css({\n backgroundColor: backdrop.css('backgroundColor'),\n opacity: backdrop.css('opacity'),\n });\n fader.attr('data-flexitour', 'step-background-fader');\n\n if (targetNode.parents('[data-region=\"fixed-drawer\"]').length) {\n let targetClone = targetNode.clone();\n background.append(targetClone);\n }\n\n if (stepConfig.zIndex) {\n if (stepConfig.attachPoint === 'append') {\n stepConfig.attachTo.append(background);\n } else {\n fader.insertAfter(stepConfig.attachTo);\n background.insertAfter(stepConfig.attachTo);\n }\n } else {\n $('body').append(fader);\n $('body').append(background);\n }\n\n // Add the backdrop data to the actual target.\n // This is the part which actually does the work.\n targetNode.attr('data-flexitour', 'step-backdrop');\n\n if (stepConfig.zIndex) {\n backdrop.css('zIndex', stepConfig.zIndex);\n background.css('zIndex', stepConfig.zIndex + 1);\n targetNode.css('zIndex', stepConfig.zIndex + 2);\n }\n\n fader.fadeOut('2000', function() {\n $(this).remove();\n });\n }\n }\n return this;\n }\n\n /**\n * Calculate the inheritted z-index.\n *\n * @method calculateZIndex\n * @param {jQuery} elem The element to calculate z-index for\n * @return {Number} Calculated z-index\n */\n calculateZIndex(elem) {\n elem = $(elem);\n while (elem.length && elem[0] !== document) {\n // Ignore z-index if position is set to a value where z-index is ignored by the browser\n // This makes behavior of this function consistent across browsers\n // WebKit always returns auto if the element is positioned.\n let position = elem.css(\"position\");\n if (position === \"absolute\" || position === \"relative\" || position === \"fixed\") {\n // IE returns 0 when zIndex is not specified\n // other browsers return a string\n // we ignore the case of nested elements with an explicit value of 0\n //
\n let value = parseInt(elem.css(\"zIndex\"), 10);\n if (!isNaN(value) && value !== 0) {\n return value;\n }\n }\n elem = elem.parent();\n }\n\n return 0;\n }\n\n /**\n * Calculate the inheritted background colour.\n *\n * @method calculateInherittedBackgroundColor\n * @param {jQuery} elem The element to calculate colour for\n * @return {String} Calculated background colour\n */\n calculateInherittedBackgroundColor(elem) {\n // Use a fake node to compare each element against.\n let fakeNode = $('
').hide();\n $('body').append(fakeNode);\n let fakeElemColor = fakeNode.css('backgroundColor');\n fakeNode.remove();\n\n elem = $(elem);\n while (elem.length && elem[0] !== document) {\n let color = elem.css('backgroundColor');\n if (color !== fakeElemColor) {\n return color;\n }\n elem = elem.parent();\n }\n\n return null;\n }\n\n /**\n * Calculate the inheritted position.\n *\n * @method calculatePosition\n * @param {jQuery} elem The element to calculate position for\n * @return {String} Calculated position\n */\n calculatePosition(elem) {\n elem = $(elem);\n while (elem.length && elem[0] !== document) {\n let position = elem.css('position');\n if (position !== 'static') {\n return position;\n }\n elem = elem.parent();\n }\n\n return null;\n }\n\n /**\n * Perform accessibility changes for step shown.\n *\n * This will add aria-hidden=\"true\" to all siblings and parent siblings.\n *\n * @method accessibilityShow\n */\n accessibilityShow() {\n let stateHolder = 'data-has-hidden';\n let attrName = 'aria-hidden';\n let hideFunction = function(child) {\n let flexitourRole = child.data('flexitour');\n if (flexitourRole) {\n switch (flexitourRole) {\n case 'container':\n case 'target':\n return;\n }\n }\n\n let hidden = child.attr(attrName);\n if (!hidden) {\n child.attr(stateHolder, true);\n Aria.hide(child);\n }\n };\n\n this.currentStepNode.siblings().each(function(index, node) {\n hideFunction($(node));\n });\n this.currentStepNode.parentsUntil('body').siblings().each(function(index, node) {\n hideFunction($(node));\n });\n }\n\n /**\n * Perform accessibility changes for step hidden.\n *\n * This will remove any newly added aria-hidden=\"true\".\n *\n * @method accessibilityHide\n */\n accessibilityHide() {\n let stateHolder = 'data-has-hidden';\n let showFunction = function(child) {\n let hidden = child.attr(stateHolder);\n if (typeof hidden !== 'undefined') {\n child.removeAttr(stateHolder);\n Aria.unhide(child);\n }\n };\n\n $('[' + stateHolder + ']').each(function(index, node) {\n showFunction($(node));\n });\n }\n};\n\nexport default Tour;\n"],"names":["constructor","config","init","eventHandlers","reset","originalConfiguration","configure","apply","this","arguments","storage","window","sessionStorage","storageKey","tourName","e","hide","resetStepListeners","steps","currentStepNumber","eventName","forEach","handler","addEventHandler","resetStepDefaults","template","templateContent","checkMinimumRequirements","Error","length","loadOriginalConfiguration","stepDefaults","setStepDefaults","extend","element","placement","delay","moveOnClick","moveAfterTime","orphan","direction","getCurrentStepNumber","parseInt","setCurrentStepNumber","stepNumber","setItem","code","DOMException","QUOTA_EXCEEDED_ERR","removeItem","getNextStepNumber","nextStepNumber","isStepPotentiallyVisible","getStepConfig","getPreviousStepNumber","previousStepNumber","isLastStep","stepConfig","isStepActuallyVisible","getPotentiallyVisibleSteps","position","result","stepId","stepid","target","getStepTarget","is","next","gotoStep","previous","endTour","_gotoStep","delayed","setTimeout","bind","fn","dispatchEvent","eventTypes","stepRender","defaultPrevented","renderStep","stepRendered","normalizeStepConfig","$","reflex","moveAfterClick","content","body","attachTo","attachPoint","first","detail","cancelable","tour","document","push","processStepListeners","listeners","node","currentStepNode","args","proxy","handleKeyDown","targetNode","parents","listener","on","off","currentStepConfig","getTemplateContent","find","html","title","nextBtn","endBtn","removeClass","addClass","prop","then","value","catch","attr","displaystepnumbers","stepsPotentiallyVisible","totalStepsPotentiallyVisible","total","addStepToPage","clone","animationTarget","stop","data","zIndex","calculateZIndex","css","positionBackdrop","append","top","left","animate","scrollTop","calculateScrollTop","promise","positionStep","revealStep","isOrphan","offset","calculateStepPositionInPage","currentStepPopper","Popper","removeOnDestroy","arrowElement","modifiers","enabled","applyStyle","onLoad","fadeIn","announceStep","focus","bodyRegion","headerRegion","accessibilityShow","tabbableSelector","keyCode","hasBackdrop","currentIndex","nextIndex","nextNode","focusRelevant","activeElement","stepTarget","tabbableNodes","dialogContainer","filter","index","has","each","shiftKey","closest","last","preventDefault","call","startTour","startAt","storageStartValue","getItem","storageStartAt","tourStart","tourRunning","tourStarted","restartTour","tourEnd","previousTarget","tourEnded","transition","stepHide","destroy","fadeTime","remove","removeAttr","fadeOut","currentStepElement","accessibilityHide","stepHidden","show","getStepContainer","viewportHeight","height","scrollParent","Math","max","min","ceil","stepHeight","viewportWidth","width","stepWidth","flipBehavior","recalculatePlacement","flip","behaviour","arrow","onCreate","recalculateArrowPosition","onUpdate","split","isVertical","indexOf","instance","popper","querySelector","stepElement","arrowHeight","parseFloat","getComputedStyle","arrowOffset","popperHeight","popperOffset","popperBorderWidth","popperBorderRadiusWidth","arrowPos","maxPos","minPos","newArrowPos","arrowWidth","popperWidth","background","widthContent","targetOffsetLeft","targetOffsetRight","documentElement","clientWidth","backdrop","insertAfter","buffer","colorNode","drawertop","scrollerElement","navigationBuffer","outerWidth","outerHeight","backgroundColor","calculateInherittedBackgroundColor","targetRadius","targetPosition","calculatePosition","fader","opacity","targetClone","elem","isNaN","parent","fakeNode","fakeElemColor","color","hideFunction","child","flexitourRole","Aria","siblings","parentsUntil","unhide"],"mappings":"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"}
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/usertours.min.js b/admin/tool/usertours/amd/build/usertours.min.js
index 88121c93775..c0709030ff0 100644
--- a/admin/tool/usertours/amd/build/usertours.min.js
+++ b/admin/tool/usertours/amd/build/usertours.min.js
@@ -1,2 +1,3 @@
-function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("tool_usertours/usertours",["exports","./tour","core/templates","core/log","core/notification","./repository","core/pending","./events"],function(a,b,c,d,e,f,g,h){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.resetTourState=a.init=void 0;b=k(b);c=k(c);d=k(d);e=k(e);f=j(f);g=k(g);var n="undefined"!=typeof window?window:"undefined"!=typeof self?self:"undefined"!=typeof global?global:{};function i(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;i=function(){return a};return a}function j(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=i();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function k(a){return a&&a.__esModule?a:{default:a}}function l(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 m(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){l(h,d,e,f,g,"next",a)}function g(a){l(h,d,e,f,g,"throw",a)}f(void 0)})}}var o=null,p=null,q=function(a,b){return a.find(function(a){return b.some(function(b){if(b&&b.filterMatches){return b.filterMatches(a)}return!0})})},r=function(){var a=m(regeneratorRuntime.mark(function a(b,c){var d,e,f,g;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:d=[];c.forEach(function(a){d.push("function"==typeof n.define&&n.define.amd?new Promise(function(b,c){n.require(["tool_usertours/filter_".concat(a)],b,c)}):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&n.require&&"component"===n.require.loader?Promise.resolve(require(("tool_usertours/filter_".concat(a)))):Promise.resolve(n["tool_usertours/filter_".concat(a)]))});a.next=4;return Promise.all(d);case 4:e=a.sent;f=q(b,e);if(f){a.next=8;break}return a.abrupt("return");case 8:p=f.tourId;g=f.startTour;if("undefined"==typeof g){g=!0}if(g){s(p)}u();document.querySelector("body").addEventListener("click",function(a){var b=a.target.closest("#resetpagetour");if(b){a.preventDefault();y(p)}});case 14:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}();a.init=r;var s=function(){var a=m(regeneratorRuntime.mark(function a(b){var d,h,i,j;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:d=new g.default("admin_usertour_fetchTour:".concat(b));a.prev=1;a.next=4;return f.fetchTour(b);case 4:h=a.sent;if(!h.hasOwnProperty("tourconfig")){d.resolve()}a.next=8;return c.default.renderForPromise("tool_usertours/tourstep",h.tourconfig);case 8:i=a.sent;j=i.html;v(b,j,h.tourconfig);d.resolve();a.next=18;break;case 14:a.prev=14;a.t0=a["catch"](1);d.resolve();e.default.exception(a.t0);case 18:case"end":return a.stop();}}},a,null,[[1,14]])}));return function(){return a.apply(this,arguments)}}(),t=function(){var a=document.querySelector(".tool_usertours-resettourcontainer");if(a){return a}a=document.querySelector(".logininfo");if(a){return a}a=document.querySelector("footer");if(a){return a}return document.body},u=function(){var a=new g.default("admin_usertour_addResetLink");c.default.render("tool_usertours/resettour",{}).then(function(a,b){c.default.appendNodeContents(t(),a,b)}).catch().then(a.resolve).catch()},v=function(a,c,d){if(o&&o.tourRunning){o.endTour();o=null}document.addEventListener(h.eventTypes.tourEnded,x);document.addEventListener(h.eventTypes.stepRenderer,w);d.tourName=d.name;delete d.name;d.template=c;d.steps=d.steps.map(function(a){if("undefined"!=typeof a.element){a.target=a.element;delete a.element}if("undefined"!=typeof a.reflex){a.moveOnClick=!!a.reflex;delete a.reflex}if("undefined"!=typeof a.content){a.body=a.content;delete a.content}return a});o=new b.default(d);return o.startTour()},w=function(a){var b=a.detail.tour,c=b.getStepConfig(b.getCurrentStepNumber());f.markStepShown(c.stepid,p,b.getCurrentStepNumber()).catch(d.default.error)},x=function(a){document.removeEventListener(h.eventTypes.tourEnded,x);document.removeEventListener(h.eventTypes.stepRenderer,w);var b=a.detail.tour,c=b.getStepConfig(b.getCurrentStepNumber());f.markTourComplete(c.stepid,p,b.getCurrentStepNumber()).catch(d.default.error)},y=function(a){return f.resetTourState(a).then(function(a){if(a.startTour){s(a.startTour)}}).catch(e.default.exception)};a.resetTourState=y});
-//# sourceMappingURL=usertours.min.js.map
+define("tool_usertours/usertours",["exports","./tour","core/templates","core/log","core/notification","./repository","core/pending","./events"],(function(_exports,_tour,_templates,_log,_notification,tourRepository,_pending,_events){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.resetTourState=_exports.init=void 0,_tour=_interopRequireDefault(_tour),_templates=_interopRequireDefault(_templates),_log=_interopRequireDefault(_log),_notification=_interopRequireDefault(_notification),tourRepository=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}(tourRepository),_pending=_interopRequireDefault(_pending);var _systemImportTransformerGlobalIdentifier="undefined"!=typeof window?window:"undefined"!=typeof self?self:"undefined"!=typeof global?global:{};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}}let currentTour=null,tourId=null;_exports.init=async(tourDetails,filters)=>{const requirements=[];filters.forEach((filter=>{requirements.push("function"==typeof _systemImportTransformerGlobalIdentifier.define&&_systemImportTransformerGlobalIdentifier.define.amd?new Promise((function(resolve,reject){_systemImportTransformerGlobalIdentifier.require(["tool_usertours/filter_".concat(filter)],resolve,reject)})):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&_systemImportTransformerGlobalIdentifier.require&&"component"===_systemImportTransformerGlobalIdentifier.require.loader?Promise.resolve(require("tool_usertours/filter_".concat(filter))):Promise.resolve(_systemImportTransformerGlobalIdentifier["tool_usertours/filter_".concat(filter)]))}));const matchingTour=((tourDetails,filters)=>tourDetails.find((tour=>filters.some((filter=>!filter||!filter.filterMatches||filter.filterMatches(tour))))))(tourDetails,await Promise.all(requirements));if(!matchingTour)return;tourId=matchingTour.tourId;let startTour=matchingTour.startTour;void 0===startTour&&(startTour=!0),startTour&&fetchTour(tourId),addResetLink(),document.querySelector("body").addEventListener("click",(e=>{e.target.closest("#resetpagetour")&&(e.preventDefault(),resetTourState(tourId))}))};const fetchTour=async tourId=>{const pendingPromise=new _pending.default("admin_usertour_fetchTour:".concat(tourId));try{const response=await tourRepository.fetchTour(tourId);response.hasOwnProperty("tourconfig")||pendingPromise.resolve();const{html:html}=await _templates.default.renderForPromise("tool_usertours/tourstep",response.tourconfig);startBootstrapTour(tourId,html,response.tourconfig),pendingPromise.resolve()}catch(error){pendingPromise.resolve(),_notification.default.exception(error)}},addResetLink=()=>{const pendingPromise=new _pending.default("admin_usertour_addResetLink");_templates.default.render("tool_usertours/resettour",{}).then((function(html,js){_templates.default.appendNodeContents((()=>{let location=document.querySelector(".tool_usertours-resettourcontainer");return location||(location=document.querySelector(".logininfo"),location||(location=document.querySelector("footer"),location||document.body))})(),html,js)})).catch().then(pendingPromise.resolve).catch()},startBootstrapTour=(tourId,template,tourConfig)=>(currentTour&¤tTour.tourRunning&&(currentTour.endTour(),currentTour=null),document.addEventListener(_events.eventTypes.tourEnded,markTourComplete),document.addEventListener(_events.eventTypes.stepRenderer,markStepShown),tourConfig.tourName=tourConfig.name,delete tourConfig.name,tourConfig.template=template,tourConfig.steps=tourConfig.steps.map((function(step){return void 0!==step.element&&(step.target=step.element,delete step.element),void 0!==step.reflex&&(step.moveOnClick=!!step.reflex,delete step.reflex),void 0!==step.content&&(step.body=step.content,delete step.content),step})),currentTour=new _tour.default(tourConfig),currentTour.startTour()),markStepShown=e=>{const tour=e.detail.tour,stepConfig=tour.getStepConfig(tour.getCurrentStepNumber());tourRepository.markStepShown(stepConfig.stepid,tourId,tour.getCurrentStepNumber()).catch(_log.default.error)},markTourComplete=e=>{document.removeEventListener(_events.eventTypes.tourEnded,markTourComplete),document.removeEventListener(_events.eventTypes.stepRenderer,markStepShown);const tour=e.detail.tour,stepConfig=tour.getStepConfig(tour.getCurrentStepNumber());tourRepository.markTourComplete(stepConfig.stepid,tourId,tour.getCurrentStepNumber()).catch(_log.default.error)},resetTourState=tourId=>tourRepository.resetTourState(tourId).then((response=>{response.startTour&&fetchTour(response.startTour)})).catch(_notification.default.exception);_exports.resetTourState=resetTourState}));
+
+//# sourceMappingURL=usertours.min.js.map
\ No newline at end of file
diff --git a/admin/tool/usertours/amd/build/usertours.min.js.map b/admin/tool/usertours/amd/build/usertours.min.js.map
index 3c2c3357031..b01bfe115b6 100644
--- a/admin/tool/usertours/amd/build/usertours.min.js.map
+++ b/admin/tool/usertours/amd/build/usertours.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/usertours.js"],"names":["currentTour","tourId","findMatchingTour","tourDetails","filters","find","tour","some","filter","filterMatches","init","requirements","forEach","push","Promise","all","filterPlugins","matchingTour","startTour","fetchTour","addResetLink","document","querySelector","addEventListener","e","resetLink","target","closest","preventDefault","resetTourState","pendingPromise","Pending","tourRepository","response","hasOwnProperty","resolve","Templates","renderForPromise","tourconfig","html","startBootstrapTour","notification","exception","getPreferredResetLocation","location","body","render","then","js","appendNodeContents","catch","template","tourConfig","tourRunning","endTour","eventTypes","tourEnded","markTourComplete","stepRenderer","markStepShown","tourName","name","steps","map","step","element","reflex","moveOnClick","content","BootstrapTour","detail","stepConfig","getStepConfig","getCurrentStepNumber","stepid","log","error","removeEventListener"],"mappings":"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","sourcesContent":["/**\n * User tour control library.\n *\n * @module tool_usertours/usertours\n * @copyright 2016 Andrew Nicols \n */\nimport BootstrapTour from './tour';\nimport Templates from 'core/templates';\nimport log from 'core/log';\nimport notification from 'core/notification';\nimport * as tourRepository from './repository';\nimport Pending from 'core/pending';\nimport {eventTypes} from './events';\n\nlet currentTour = null;\nlet tourId = null;\n\n/**\n * Find the first matching tour.\n *\n * @param {object[]} tourDetails\n * @param {object[]} filters\n * @returns {null|object}\n */\nconst findMatchingTour = (tourDetails, filters) => {\n return tourDetails.find(tour => filters.some(filter => {\n if (filter && filter.filterMatches) {\n return filter.filterMatches(tour);\n }\n\n return true;\n }));\n};\n\n/**\n * Initialise the user tour for the current page.\n *\n * @method init\n * @param {Array} tourDetails The matching tours for this page.\n * @param {Array} filters The names of all client side filters.\n */\nexport const init = async(tourDetails, filters) => {\n const requirements = [];\n filters.forEach(filter => {\n requirements.push(import(`tool_usertours/filter_${filter}`));\n });\n\n const filterPlugins = await Promise.all(requirements);\n\n const matchingTour = findMatchingTour(tourDetails, filterPlugins);\n if (!matchingTour) {\n return;\n }\n\n // Only one tour per page is allowed.\n tourId = matchingTour.tourId;\n\n let startTour = matchingTour.startTour;\n if (typeof startTour === 'undefined') {\n startTour = true;\n }\n\n if (startTour) {\n // Fetch the tour configuration.\n fetchTour(tourId);\n }\n\n addResetLink();\n\n // Watch for the reset link.\n document.querySelector('body').addEventListener('click', e => {\n const resetLink = e.target.closest('#resetpagetour');\n if (resetLink) {\n e.preventDefault();\n resetTourState(tourId);\n }\n });\n};\n\n/**\n * Fetch the configuration specified tour, and start the tour when it has been fetched.\n *\n * @method fetchTour\n * @param {Number} tourId The ID of the tour to start.\n */\nconst fetchTour = async tourId => {\n const pendingPromise = new Pending(`admin_usertour_fetchTour:${tourId}`);\n\n try {\n const response = await tourRepository.fetchTour(tourId);\n if (!response.hasOwnProperty('tourconfig')) {\n pendingPromise.resolve();\n }\n\n const {html} = await Templates.renderForPromise('tool_usertours/tourstep', response.tourconfig);\n startBootstrapTour(tourId, html, response.tourconfig);\n\n pendingPromise.resolve();\n } catch (error) {\n pendingPromise.resolve();\n notification.exception(error);\n }\n};\n\nconst getPreferredResetLocation = () => {\n let location = document.querySelector('.tool_usertours-resettourcontainer');\n if (location) {\n return location;\n }\n\n location = document.querySelector('.logininfo');\n if (location) {\n return location;\n }\n\n location = document.querySelector('footer');\n if (location) {\n return location;\n }\n\n return document.body;\n};\n\n/**\n * Add a reset link to the page.\n *\n * @method addResetLink\n */\nconst addResetLink = () => {\n const pendingPromise = new Pending('admin_usertour_addResetLink');\n\n Templates.render('tool_usertours/resettour', {})\n .then(function(html, js) {\n // Append the link to the most suitable place on the page with fallback to legacy selectors and finally the body if\n // there is no better place.\n Templates.appendNodeContents(getPreferredResetLocation(), html, js);\n\n return;\n })\n .catch()\n .then(pendingPromise.resolve)\n .catch();\n};\n\n/**\n * Start the specified tour.\n *\n * @method startBootstrapTour\n * @param {Number} tourId The ID of the tour to start.\n * @param {String} template The template to use.\n * @param {Object} tourConfig The tour configuration.\n * @return {Object}\n */\nconst startBootstrapTour = (tourId, template, tourConfig) => {\n if (currentTour && currentTour.tourRunning) {\n // End the current tour.\n currentTour.endTour();\n currentTour = null;\n }\n\n document.addEventListener(eventTypes.tourEnded, markTourComplete);\n document.addEventListener(eventTypes.stepRenderer, markStepShown);\n\n // Sort out the tour name.\n tourConfig.tourName = tourConfig.name;\n delete tourConfig.name;\n\n // Add the template to the configuration.\n // This enables translations of the buttons.\n tourConfig.template = template;\n\n tourConfig.steps = tourConfig.steps.map(function(step) {\n if (typeof step.element !== 'undefined') {\n step.target = step.element;\n delete step.element;\n }\n\n if (typeof step.reflex !== 'undefined') {\n step.moveOnClick = !!step.reflex;\n delete step.reflex;\n }\n\n if (typeof step.content !== 'undefined') {\n step.body = step.content;\n delete step.content;\n }\n\n return step;\n });\n\n currentTour = new BootstrapTour(tourConfig);\n return currentTour.startTour();\n};\n\n/**\n * Mark the specified step as being shownd by the user.\n *\n * @method markStepShown\n * @param {Event} e\n */\nconst markStepShown = e => {\n const tour = e.detail.tour;\n const stepConfig = tour.getStepConfig(tour.getCurrentStepNumber());\n tourRepository.markStepShown(\n stepConfig.stepid,\n tourId,\n tour.getCurrentStepNumber()\n ).catch(log.error);\n};\n\n/**\n * Mark the specified tour as being completed by the user.\n *\n * @method markTourComplete\n * @param {Event} e\n * @listens tool_usertours/stepRendered\n */\nconst markTourComplete = e => {\n document.removeEventListener(eventTypes.tourEnded, markTourComplete);\n document.removeEventListener(eventTypes.stepRenderer, markStepShown);\n\n const tour = e.detail.tour;\n const stepConfig = tour.getStepConfig(tour.getCurrentStepNumber());\n tourRepository.markTourComplete(\n stepConfig.stepid,\n tourId,\n tour.getCurrentStepNumber()\n ).catch(log.error);\n};\n\n/**\n * Reset the state, and restart the the tour on the current page.\n *\n * @method resetTourState\n * @param {Number} tourId The ID of the tour to start.\n * @returns {Promise}\n */\nexport const resetTourState = tourId => tourRepository.resetTourState(tourId)\n.then(response => {\n if (response.startTour) {\n fetchTour(response.startTour);\n }\n return;\n}).catch(notification.exception);\n"],"file":"usertours.min.js"}
\ No newline at end of file
+{"version":3,"file":"usertours.min.js","sources":["../src/usertours.js"],"sourcesContent":["/**\n * User tour control library.\n *\n * @module tool_usertours/usertours\n * @copyright 2016 Andrew Nicols \n */\nimport BootstrapTour from './tour';\nimport Templates from 'core/templates';\nimport log from 'core/log';\nimport notification from 'core/notification';\nimport * as tourRepository from './repository';\nimport Pending from 'core/pending';\nimport {eventTypes} from './events';\n\nlet currentTour = null;\nlet tourId = null;\n\n/**\n * Find the first matching tour.\n *\n * @param {object[]} tourDetails\n * @param {object[]} filters\n * @returns {null|object}\n */\nconst findMatchingTour = (tourDetails, filters) => {\n return tourDetails.find(tour => filters.some(filter => {\n if (filter && filter.filterMatches) {\n return filter.filterMatches(tour);\n }\n\n return true;\n }));\n};\n\n/**\n * Initialise the user tour for the current page.\n *\n * @method init\n * @param {Array} tourDetails The matching tours for this page.\n * @param {Array} filters The names of all client side filters.\n */\nexport const init = async(tourDetails, filters) => {\n const requirements = [];\n filters.forEach(filter => {\n requirements.push(import(`tool_usertours/filter_${filter}`));\n });\n\n const filterPlugins = await Promise.all(requirements);\n\n const matchingTour = findMatchingTour(tourDetails, filterPlugins);\n if (!matchingTour) {\n return;\n }\n\n // Only one tour per page is allowed.\n tourId = matchingTour.tourId;\n\n let startTour = matchingTour.startTour;\n if (typeof startTour === 'undefined') {\n startTour = true;\n }\n\n if (startTour) {\n // Fetch the tour configuration.\n fetchTour(tourId);\n }\n\n addResetLink();\n\n // Watch for the reset link.\n document.querySelector('body').addEventListener('click', e => {\n const resetLink = e.target.closest('#resetpagetour');\n if (resetLink) {\n e.preventDefault();\n resetTourState(tourId);\n }\n });\n};\n\n/**\n * Fetch the configuration specified tour, and start the tour when it has been fetched.\n *\n * @method fetchTour\n * @param {Number} tourId The ID of the tour to start.\n */\nconst fetchTour = async tourId => {\n const pendingPromise = new Pending(`admin_usertour_fetchTour:${tourId}`);\n\n try {\n const response = await tourRepository.fetchTour(tourId);\n if (!response.hasOwnProperty('tourconfig')) {\n pendingPromise.resolve();\n }\n\n const {html} = await Templates.renderForPromise('tool_usertours/tourstep', response.tourconfig);\n startBootstrapTour(tourId, html, response.tourconfig);\n\n pendingPromise.resolve();\n } catch (error) {\n pendingPromise.resolve();\n notification.exception(error);\n }\n};\n\nconst getPreferredResetLocation = () => {\n let location = document.querySelector('.tool_usertours-resettourcontainer');\n if (location) {\n return location;\n }\n\n location = document.querySelector('.logininfo');\n if (location) {\n return location;\n }\n\n location = document.querySelector('footer');\n if (location) {\n return location;\n }\n\n return document.body;\n};\n\n/**\n * Add a reset link to the page.\n *\n * @method addResetLink\n */\nconst addResetLink = () => {\n const pendingPromise = new Pending('admin_usertour_addResetLink');\n\n Templates.render('tool_usertours/resettour', {})\n .then(function(html, js) {\n // Append the link to the most suitable place on the page with fallback to legacy selectors and finally the body if\n // there is no better place.\n Templates.appendNodeContents(getPreferredResetLocation(), html, js);\n\n return;\n })\n .catch()\n .then(pendingPromise.resolve)\n .catch();\n};\n\n/**\n * Start the specified tour.\n *\n * @method startBootstrapTour\n * @param {Number} tourId The ID of the tour to start.\n * @param {String} template The template to use.\n * @param {Object} tourConfig The tour configuration.\n * @return {Object}\n */\nconst startBootstrapTour = (tourId, template, tourConfig) => {\n if (currentTour && currentTour.tourRunning) {\n // End the current tour.\n currentTour.endTour();\n currentTour = null;\n }\n\n document.addEventListener(eventTypes.tourEnded, markTourComplete);\n document.addEventListener(eventTypes.stepRenderer, markStepShown);\n\n // Sort out the tour name.\n tourConfig.tourName = tourConfig.name;\n delete tourConfig.name;\n\n // Add the template to the configuration.\n // This enables translations of the buttons.\n tourConfig.template = template;\n\n tourConfig.steps = tourConfig.steps.map(function(step) {\n if (typeof step.element !== 'undefined') {\n step.target = step.element;\n delete step.element;\n }\n\n if (typeof step.reflex !== 'undefined') {\n step.moveOnClick = !!step.reflex;\n delete step.reflex;\n }\n\n if (typeof step.content !== 'undefined') {\n step.body = step.content;\n delete step.content;\n }\n\n return step;\n });\n\n currentTour = new BootstrapTour(tourConfig);\n return currentTour.startTour();\n};\n\n/**\n * Mark the specified step as being shownd by the user.\n *\n * @method markStepShown\n * @param {Event} e\n */\nconst markStepShown = e => {\n const tour = e.detail.tour;\n const stepConfig = tour.getStepConfig(tour.getCurrentStepNumber());\n tourRepository.markStepShown(\n stepConfig.stepid,\n tourId,\n tour.getCurrentStepNumber()\n ).catch(log.error);\n};\n\n/**\n * Mark the specified tour as being completed by the user.\n *\n * @method markTourComplete\n * @param {Event} e\n * @listens tool_usertours/stepRendered\n */\nconst markTourComplete = e => {\n document.removeEventListener(eventTypes.tourEnded, markTourComplete);\n document.removeEventListener(eventTypes.stepRenderer, markStepShown);\n\n const tour = e.detail.tour;\n const stepConfig = tour.getStepConfig(tour.getCurrentStepNumber());\n tourRepository.markTourComplete(\n stepConfig.stepid,\n tourId,\n tour.getCurrentStepNumber()\n ).catch(log.error);\n};\n\n/**\n * Reset the state, and restart the the tour on the current page.\n *\n * @method resetTourState\n * @param {Number} tourId The ID of the tour to start.\n * @returns {Promise}\n */\nexport const resetTourState = tourId => tourRepository.resetTourState(tourId)\n.then(response => {\n if (response.startTour) {\n fetchTour(response.startTour);\n }\n return;\n}).catch(notification.exception);\n"],"names":["currentTour","tourId","async","tourDetails","filters","requirements","forEach","filter","push","matchingTour","find","tour","some","filterMatches","findMatchingTour","Promise","all","startTour","fetchTour","addResetLink","document","querySelector","addEventListener","e","target","closest","preventDefault","resetTourState","pendingPromise","Pending","response","tourRepository","hasOwnProperty","resolve","html","Templates","renderForPromise","tourconfig","startBootstrapTour","error","exception","render","then","js","appendNodeContents","location","body","getPreferredResetLocation","catch","template","tourConfig","tourRunning","endTour","eventTypes","tourEnded","markTourComplete","stepRenderer","markStepShown","tourName","name","steps","map","step","element","reflex","moveOnClick","content","BootstrapTour","detail","stepConfig","getStepConfig","getCurrentStepNumber","stepid","log","removeEventListener","notification"],"mappings":"ssDAcIA,YAAc,KACdC,OAAS,mBA0BOC,MAAMC,YAAaC,iBAC7BC,aAAe,GACrBD,QAAQE,SAAQC,SACZF,aAAaG,qPAAqCD,mUAAAA,mGAAAA,oBAKhDE,aAzBe,EAACN,YAAaC,UAC5BD,YAAYO,MAAKC,MAAQP,QAAQQ,MAAKL,SACrCA,SAAUA,OAAOM,eACVN,OAAOM,cAAcF,UAsBfG,CAAiBX,kBAFVY,QAAQC,IAAIX,mBAGnCI,oBAKLR,OAASQ,aAAaR,WAElBgB,UAAYR,aAAaQ,eACJ,IAAdA,YACPA,WAAY,GAGZA,WAEAC,UAAUjB,QAGdkB,eAGAC,SAASC,cAAc,QAAQC,iBAAiB,SAASC,IACnCA,EAAEC,OAAOC,QAAQ,oBAE/BF,EAAEG,iBACFC,eAAe1B,mBAWrBiB,UAAYhB,MAAAA,eACR0B,eAAiB,IAAIC,oDAAoC5B,mBAGrD6B,eAAiBC,eAAeb,UAAUjB,QAC3C6B,SAASE,eAAe,eACzBJ,eAAeK,gBAGbC,KAACA,YAAcC,mBAAUC,iBAAiB,0BAA2BN,SAASO,YACpFC,mBAAmBrC,OAAQiC,KAAMJ,SAASO,YAE1CT,eAAeK,UACjB,MAAOM,OACLX,eAAeK,gCACFO,UAAUD,SA4BzBpB,aAAe,WACXS,eAAiB,IAAIC,iBAAQ,kDAEzBY,OAAO,2BAA4B,IAC5CC,MAAK,SAASR,KAAMS,uBAGPC,mBA/BgB,UAC1BC,SAAWzB,SAASC,cAAc,6CAClCwB,WAIJA,SAAWzB,SAASC,cAAc,cAC9BwB,WAIJA,SAAWzB,SAASC,cAAc,UAC9BwB,UAIGzB,SAAS0B,QAeiBC,GAA6Bb,KAAMS,OAInEK,QACAN,KAAKd,eAAeK,SACpBe,SAYCV,mBAAqB,CAACrC,OAAQgD,SAAUC,cACtClD,aAAeA,YAAYmD,cAE3BnD,YAAYoD,UACZpD,YAAc,MAGlBoB,SAASE,iBAAiB+B,mBAAWC,UAAWC,kBAChDnC,SAASE,iBAAiB+B,mBAAWG,aAAcC,eAGnDP,WAAWQ,SAAWR,WAAWS,YAC1BT,WAAWS,KAIlBT,WAAWD,SAAWA,SAEtBC,WAAWU,MAAQV,WAAWU,MAAMC,KAAI,SAASC,kBACjB,IAAjBA,KAAKC,UACZD,KAAKtC,OAASsC,KAAKC,eACZD,KAAKC,cAGW,IAAhBD,KAAKE,SACZF,KAAKG,cAAgBH,KAAKE,cACnBF,KAAKE,aAGY,IAAjBF,KAAKI,UACZJ,KAAKhB,KAAOgB,KAAKI,eACVJ,KAAKI,SAGTJ,QAGX9D,YAAc,IAAImE,cAAcjB,YACzBlD,YAAYiB,aASjBwC,cAAgBlC,UACZZ,KAAOY,EAAE6C,OAAOzD,KAChB0D,WAAa1D,KAAK2D,cAAc3D,KAAK4D,wBAC3CxC,eAAe0B,cACXY,WAAWG,OACXvE,OACAU,KAAK4D,wBACPvB,MAAMyB,aAAIlC,QAUVgB,iBAAmBhC,IACrBH,SAASsD,oBAAoBrB,mBAAWC,UAAWC,kBACnDnC,SAASsD,oBAAoBrB,mBAAWG,aAAcC,qBAEhD9C,KAAOY,EAAE6C,OAAOzD,KAChB0D,WAAa1D,KAAK2D,cAAc3D,KAAK4D,wBAC3CxC,eAAewB,iBACXc,WAAWG,OACXvE,OACAU,KAAK4D,wBACPvB,MAAMyB,aAAIlC,QAUHZ,eAAiB1B,QAAU8B,eAAeJ,eAAe1B,QACrEyC,MAAKZ,WACEA,SAASb,WACTC,UAAUY,SAASb,cAGxB+B,MAAM2B,sBAAanC"}
\ No newline at end of file
diff --git a/admin/tool/xmldb/amd/build/move.min.js b/admin/tool/xmldb/amd/build/move.min.js
index 3873d1b2234..2b481ebe806 100644
--- a/admin/tool/xmldb/amd/build/move.min.js
+++ b/admin/tool/xmldb/amd/build/move.min.js
@@ -1,2 +1,3 @@
-define ("tool_xmldb/move",["jquery","core/sortable_list","core/ajax","core/notification"],function(a,b,c,d){return{init:function init(e,f){var g=new b("#"+e+" tbody");g.getElementName=function(b){return a.Deferred().resolve(b.attr("data-name"))};var h;a("#"+e+" tbody tr").on(b.EVENTS.DRAGSTART,function(b,c){h=c.sourceList.children().index(c.element);setTimeout(function(){a(".sortable-list-is-dragged").width(c.element.width())},501)}).on(b.EVENTS.DROP,function(a,b){var e=b.targetList.children().index(b.element),g=b.element.find("[data-action="+f+"]");if(b.positionChanged&&g.length){var i={methodname:"tool_xmldb_invoke_move_action",args:{action:f,dir:g.attr("data-dir"),table:g.attr("data-table"),field:g.attr("data-field"),key:g.attr("data-key"),index:g.attr("data-index"),position:e-h}};c.call([i])[0].fail(d.exception)}})}}});
-//# sourceMappingURL=move.min.js.map
+define("tool_xmldb/move",["jquery","core/sortable_list","core/ajax","core/notification"],(function($,SortableList,Ajax,Notification){return{init:function(tableid,moveaction){var origIndex;new SortableList("#"+tableid+" tbody").getElementName=function(element){return $.Deferred().resolve(element.attr("data-name"))},$("#"+tableid+" tbody tr").on(SortableList.EVENTS.DRAGSTART,(function(_,info){origIndex=info.sourceList.children().index(info.element),setTimeout((function(){$(".sortable-list-is-dragged").width(info.element.width())}),501)})).on(SortableList.EVENTS.DROP,(function(_,info){var newIndex=info.targetList.children().index(info.element),t=info.element.find("[data-action="+moveaction+"]");if(info.positionChanged&&t.length){var request={methodname:"tool_xmldb_invoke_move_action",args:{action:moveaction,dir:t.attr("data-dir"),table:t.attr("data-table"),field:t.attr("data-field"),key:t.attr("data-key"),index:t.attr("data-index"),position:newIndex-origIndex}};Ajax.call([request])[0].fail(Notification.exception)}}))}}}));
+
+//# sourceMappingURL=move.min.js.map
\ No newline at end of file
diff --git a/admin/tool/xmldb/amd/build/move.min.js.map b/admin/tool/xmldb/amd/build/move.min.js.map
index 28f624fa5b9..9fb16fee00f 100644
--- a/admin/tool/xmldb/amd/build/move.min.js.map
+++ b/admin/tool/xmldb/amd/build/move.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/move.js"],"names":["define","$","SortableList","Ajax","Notification","init","tableid","moveaction","sort","getElementName","element","Deferred","resolve","attr","origIndex","on","EVENTS","DRAGSTART","_","info","sourceList","children","index","setTimeout","width","DROP","newIndex","targetList","t","find","positionChanged","length","request","methodname","args","action","dir","table","field","key","position","call","fail","exception"],"mappings":"AAeAA,OAAM,mBAAC,CAAC,QAAD,CAAW,oBAAX,CAAiC,WAAjC,CAA8C,mBAA9C,CAAD,CAAqE,SAASC,CAAT,CAAYC,CAAZ,CAA0BC,CAA1B,CAAgCC,CAAhC,CAA8C,CACrH,MAAO,CACHC,IAAI,CAAE,cAASC,CAAT,CAAkBC,CAAlB,CAA8B,CAEhC,GAAIC,CAAAA,CAAI,CAAG,GAAIN,CAAAA,CAAJ,CAAiB,IAAMI,CAAN,CAAgB,QAAjC,CAAX,CACAE,CAAI,CAACC,cAAL,CAAsB,SAASC,CAAT,CAAkB,CACpC,MAAOT,CAAAA,CAAC,CAACU,QAAF,GAAaC,OAAb,CAAqBF,CAAO,CAACG,IAAR,CAAa,WAAb,CAArB,CACV,CAFD,CAGA,GAAIC,CAAAA,CAAJ,CACAb,CAAC,CAAC,IAAMK,CAAN,CAAgB,WAAjB,CAAD,CAA+BS,EAA/B,CAAkCb,CAAY,CAACc,MAAb,CAAoBC,SAAtD,CAAiE,SAASC,CAAT,CAAYC,CAAZ,CAAkB,CAE/EL,CAAS,CAAGK,CAAI,CAACC,UAAL,CAAgBC,QAAhB,GAA2BC,KAA3B,CAAiCH,CAAI,CAACT,OAAtC,CAAZ,CAEAa,UAAU,CAAC,UAAW,CAClBtB,CAAC,CAAC,2BAAD,CAAD,CAA+BuB,KAA/B,CAAqCL,CAAI,CAACT,OAAL,CAAac,KAAb,EAArC,CACH,CAFS,CAEP,GAFO,CAGb,CAPD,EAOGT,EAPH,CAOMb,CAAY,CAACc,MAAb,CAAoBS,IAP1B,CAOgC,SAASP,CAAT,CAAYC,CAAZ,CAAkB,IAE1CO,CAAAA,CAAQ,CAAGP,CAAI,CAACQ,UAAL,CAAgBN,QAAhB,GAA2BC,KAA3B,CAAiCH,CAAI,CAACT,OAAtC,CAF+B,CAG1CkB,CAAC,CAAGT,CAAI,CAACT,OAAL,CAAamB,IAAb,CAAkB,gBAAkBtB,CAAlB,CAA+B,GAAjD,CAHsC,CAI9C,GAAIY,CAAI,CAACW,eAAL,EAAwBF,CAAC,CAACG,MAA9B,CAAsC,CAClC,GAAIC,CAAAA,CAAO,CAAG,CACVC,UAAU,CAAE,+BADF,CAEVC,IAAI,CAAE,CACFC,MAAM,CAAE5B,CADN,CAEF6B,GAAG,CAAER,CAAC,CAACf,IAAF,CAAO,UAAP,CAFH,CAGFwB,KAAK,CAAET,CAAC,CAACf,IAAF,CAAO,YAAP,CAHL,CAIFyB,KAAK,CAAEV,CAAC,CAACf,IAAF,CAAO,YAAP,CAJL,CAKF0B,GAAG,CAAEX,CAAC,CAACf,IAAF,CAAO,UAAP,CALH,CAMFS,KAAK,CAAEM,CAAC,CAACf,IAAF,CAAO,YAAP,CANL,CAOF2B,QAAQ,CAAEd,CAAQ,CAAGZ,CAPnB,CAFI,CAAd,CAYAX,CAAI,CAACsC,IAAL,CAAU,CAACT,CAAD,CAAV,EAAqB,CAArB,EAAwBU,IAAxB,CAA6BtC,CAAY,CAACuC,SAA1C,CACH,CACJ,CA1BD,CA2BH,CAnCE,CAqCV,CAtCK,CAAN","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 .\n\ndefine(['jquery', 'core/sortable_list', 'core/ajax', 'core/notification'], function($, SortableList, Ajax, Notification) {\n return {\n init: function(tableid, moveaction) {\n // Initialise sortable for the given list.\n var sort = new SortableList('#' + tableid + ' tbody');\n sort.getElementName = function(element) {\n return $.Deferred().resolve(element.attr('data-name'));\n };\n var origIndex;\n $('#' + tableid + ' tbody tr').on(SortableList.EVENTS.DRAGSTART, function(_, info) {\n // Remember position of the element in the beginning of dragging.\n origIndex = info.sourceList.children().index(info.element);\n // Resize the \"proxy\" element to be the same width as the main element.\n setTimeout(function() {\n $('.sortable-list-is-dragged').width(info.element.width());\n }, 501);\n }).on(SortableList.EVENTS.DROP, function(_, info) {\n // When a list element was moved send AJAX request to the server.\n var newIndex = info.targetList.children().index(info.element);\n var t = info.element.find('[data-action=' + moveaction + ']');\n if (info.positionChanged && t.length) {\n var request = {\n methodname: 'tool_xmldb_invoke_move_action',\n args: {\n action: moveaction,\n dir: t.attr('data-dir'),\n table: t.attr('data-table'),\n field: t.attr('data-field'),\n key: t.attr('data-key'),\n index: t.attr('data-index'),\n position: newIndex - origIndex\n }\n };\n Ajax.call([request])[0].fail(Notification.exception);\n }\n });\n }\n };\n});\n"],"file":"move.min.js"}
\ No newline at end of file
+{"version":3,"file":"move.min.js","sources":["../src/move.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 .\n\ndefine(['jquery', 'core/sortable_list', 'core/ajax', 'core/notification'], function($, SortableList, Ajax, Notification) {\n return {\n init: function(tableid, moveaction) {\n // Initialise sortable for the given list.\n var sort = new SortableList('#' + tableid + ' tbody');\n sort.getElementName = function(element) {\n return $.Deferred().resolve(element.attr('data-name'));\n };\n var origIndex;\n $('#' + tableid + ' tbody tr').on(SortableList.EVENTS.DRAGSTART, function(_, info) {\n // Remember position of the element in the beginning of dragging.\n origIndex = info.sourceList.children().index(info.element);\n // Resize the \"proxy\" element to be the same width as the main element.\n setTimeout(function() {\n $('.sortable-list-is-dragged').width(info.element.width());\n }, 501);\n }).on(SortableList.EVENTS.DROP, function(_, info) {\n // When a list element was moved send AJAX request to the server.\n var newIndex = info.targetList.children().index(info.element);\n var t = info.element.find('[data-action=' + moveaction + ']');\n if (info.positionChanged && t.length) {\n var request = {\n methodname: 'tool_xmldb_invoke_move_action',\n args: {\n action: moveaction,\n dir: t.attr('data-dir'),\n table: t.attr('data-table'),\n field: t.attr('data-field'),\n key: t.attr('data-key'),\n index: t.attr('data-index'),\n position: newIndex - origIndex\n }\n };\n Ajax.call([request])[0].fail(Notification.exception);\n }\n });\n }\n };\n});\n"],"names":["define","$","SortableList","Ajax","Notification","init","tableid","moveaction","origIndex","getElementName","element","Deferred","resolve","attr","on","EVENTS","DRAGSTART","_","info","sourceList","children","index","setTimeout","width","DROP","newIndex","targetList","t","find","positionChanged","length","request","methodname","args","action","dir","table","field","key","position","call","fail","exception"],"mappings":"AAeAA,yBAAO,CAAC,SAAU,qBAAsB,YAAa,sBAAsB,SAASC,EAAGC,aAAcC,KAAMC,oBAChG,CACHC,KAAM,SAASC,QAASC,gBAMhBC,UAJO,IAAIN,aAAa,IAAMI,QAAU,UACvCG,eAAiB,SAASC,gBACpBT,EAAEU,WAAWC,QAAQF,QAAQG,KAAK,eAG7CZ,EAAE,IAAMK,QAAU,aAAaQ,GAAGZ,aAAaa,OAAOC,WAAW,SAASC,EAAGC,MAEzEV,UAAYU,KAAKC,WAAWC,WAAWC,MAAMH,KAAKR,SAElDY,YAAW,WACPrB,EAAE,6BAA6BsB,MAAML,KAAKR,QAAQa,WACnD,QACJT,GAAGZ,aAAaa,OAAOS,MAAM,SAASP,EAAGC,UAEpCO,SAAWP,KAAKQ,WAAWN,WAAWC,MAAMH,KAAKR,SACjDiB,EAAIT,KAAKR,QAAQkB,KAAK,gBAAkBrB,WAAa,QACrDW,KAAKW,iBAAmBF,EAAEG,OAAQ,KAC9BC,QAAU,CACVC,WAAY,gCACZC,KAAM,CACFC,OAAQ3B,WACR4B,IAAKR,EAAEd,KAAK,YACZuB,MAAOT,EAAEd,KAAK,cACdwB,MAAOV,EAAEd,KAAK,cACdyB,IAAKX,EAAEd,KAAK,YACZQ,MAAOM,EAAEd,KAAK,cACd0B,SAAUd,SAAWjB,YAG7BL,KAAKqC,KAAK,CAACT,UAAU,GAAGU,KAAKrC,aAAasC"}
\ No newline at end of file
diff --git a/availability/amd/build/availability_more.min.js b/availability/amd/build/availability_more.min.js
index 9c4875851ea..22358c76610 100644
--- a/availability/amd/build/availability_more.min.js
+++ b/availability/amd/build/availability_more.min.js
@@ -1,2 +1,11 @@
-define ("core_availability/availability_more",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;var b={regions:{availability:"[data-region=\"availability-multiple\"]"},actions:{showmorelink:"[data-action=\"showmore\"]"},classes:{hidden:"d-none",visible:"d-block"}},c=function(a){var c=a.target.closest(b.actions.showmorelink);if(null===c){return}var d=c.closest(b.regions.availability);d.querySelectorAll("."+b.classes.hidden).forEach(function(a){a.classList.remove(b.classes.hidden)});d.querySelectorAll("."+b.classes.visible).forEach(function(a){a.classList.remove(b.classes.visible);a.classList.add(b.classes.hidden)});a.preventDefault()};a.init=function init(){var a=document.querySelector("body");if(!a.dataset.showmoreactive){document.addEventListener("click",c);a.dataset.showmoreactive=1}}});
-//# sourceMappingURL=availability_more.min.js.map
+define("core_availability/availability_more",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0;
+/**
+ * Show more action for availablity information.
+ *
+ * @module core_availability/availability_more
+ * @copyright 2021 Bas Brands
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+const Selectors_regions={availability:'[data-region="availability-multiple"]'},Selectors_actions={showmorelink:'[data-action="showmore"]'},Selectors_classes={hidden:"d-none",visible:"d-block"},showMoreHandler=event=>{const triggerElement=event.target.closest(Selectors_actions.showmorelink);if(null===triggerElement)return;const container=triggerElement.closest(Selectors_regions.availability);container.querySelectorAll("."+Selectors_classes.hidden).forEach((function(node){node.classList.remove(Selectors_classes.hidden)})),container.querySelectorAll("."+Selectors_classes.visible).forEach((function(node){node.classList.remove(Selectors_classes.visible),node.classList.add(Selectors_classes.hidden)})),event.preventDefault()};_exports.init=()=>{const body=document.querySelector("body");body.dataset.showmoreactive||(document.addEventListener("click",showMoreHandler),body.dataset.showmoreactive=1)}}));
+
+//# sourceMappingURL=availability_more.min.js.map
\ No newline at end of file
diff --git a/availability/amd/build/availability_more.min.js.map b/availability/amd/build/availability_more.min.js.map
index 75f162e592f..35247475686 100644
--- a/availability/amd/build/availability_more.min.js.map
+++ b/availability/amd/build/availability_more.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/availability_more.js"],"names":["Selectors","regions","availability","actions","showmorelink","classes","hidden","visible","showMoreHandler","event","triggerElement","target","closest","container","querySelectorAll","forEach","node","classList","remove","add","preventDefault","init","body","document","querySelector","dataset","showmoreactive","addEventListener"],"mappings":"qJA0BMA,CAAAA,CAAS,CAAG,CACdC,OAAO,CAAE,CACLC,YAAY,CAAE,yCADT,CADK,CAIdC,OAAO,CAAE,CACLC,YAAY,CAAE,4BADT,CAJK,CAOdC,OAAO,CAAE,CACLC,MAAM,CAAE,QADH,CAELC,OAAO,CAAE,SAFJ,CAPK,C,CAmBZC,CAAe,CAAG,SAACC,CAAD,CAAW,CAC/B,GAAMC,CAAAA,CAAc,CAAGD,CAAK,CAACE,MAAN,CAAaC,OAAb,CAAqBZ,CAAS,CAACG,OAAV,CAAkBC,YAAvC,CAAvB,CACA,GAAuB,IAAnB,GAAAM,CAAJ,CAA6B,CACzB,MACH,CACD,GAAMG,CAAAA,CAAS,CAAGH,CAAc,CAACE,OAAf,CAAuBZ,CAAS,CAACC,OAAV,CAAkBC,YAAzC,CAAlB,CACAW,CAAS,CAACC,gBAAV,CAA2B,IAAMd,CAAS,CAACK,OAAV,CAAkBC,MAAnD,EAA2DS,OAA3D,CAAmE,SAASC,CAAT,CAAe,CAC9EA,CAAI,CAACC,SAAL,CAAeC,MAAf,CAAsBlB,CAAS,CAACK,OAAV,CAAkBC,MAAxC,CACH,CAFD,EAGAO,CAAS,CAACC,gBAAV,CAA2B,IAAMd,CAAS,CAACK,OAAV,CAAkBE,OAAnD,EAA4DQ,OAA5D,CAAoE,SAASC,CAAT,CAAe,CAC/EA,CAAI,CAACC,SAAL,CAAeC,MAAf,CAAsBlB,CAAS,CAACK,OAAV,CAAkBE,OAAxC,EACAS,CAAI,CAACC,SAAL,CAAeE,GAAf,CAAmBnB,CAAS,CAACK,OAAV,CAAkBC,MAArC,CACH,CAHD,EAIAG,CAAK,CAACW,cAAN,EACH,C,QAOmB,QAAPC,CAAAA,IAAO,EAAM,CACtB,GAAMC,CAAAA,CAAI,CAAGC,QAAQ,CAACC,aAAT,CAAuB,MAAvB,CAAb,CACA,GAAI,CAACF,CAAI,CAACG,OAAL,CAAaC,cAAlB,CAAkC,CAC9BH,QAAQ,CAACI,gBAAT,CAA0B,OAA1B,CAAmCnB,CAAnC,EACAc,CAAI,CAACG,OAAL,CAAaC,cAAb,CAA8B,CACjC,CACJ,C","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 .\n\n/**\n * Show more action for availablity information.\n *\n * @module core_availability/availability_more\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Availability info selectors.\n */\nconst Selectors = {\n regions: {\n availability: '[data-region=\"availability-multiple\"]',\n },\n actions: {\n showmorelink: '[data-action=\"showmore\"]'\n },\n classes: {\n hidden: 'd-none',\n visible: 'd-block',\n\n }\n};\n\n/**\n * Displays all the availability information in case part of it is hidden.\n *\n * @param {Event} event the triggered event\n */\nconst showMoreHandler = (event) => {\n const triggerElement = event.target.closest(Selectors.actions.showmorelink);\n if (triggerElement === null) {\n return;\n }\n const container = triggerElement.closest(Selectors.regions.availability);\n container.querySelectorAll('.' + Selectors.classes.hidden).forEach(function(node) {\n node.classList.remove(Selectors.classes.hidden);\n });\n container.querySelectorAll('.' + Selectors.classes.visible).forEach(function(node) {\n node.classList.remove(Selectors.classes.visible);\n node.classList.add(Selectors.classes.hidden);\n });\n event.preventDefault();\n};\n\n/**\n * Initialise the eventlister for the showmore action on availability information.\n *\n * @method init\n */\nexport const init = () => {\n const body = document.querySelector('body');\n if (!body.dataset.showmoreactive) {\n document.addEventListener('click', showMoreHandler);\n body.dataset.showmoreactive = 1;\n }\n};\n"],"file":"availability_more.min.js"}
\ No newline at end of file
+{"version":3,"file":"availability_more.min.js","sources":["../src/availability_more.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 .\n\n/**\n * Show more action for availablity information.\n *\n * @module core_availability/availability_more\n * @copyright 2021 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Availability info selectors.\n */\nconst Selectors = {\n regions: {\n availability: '[data-region=\"availability-multiple\"]',\n },\n actions: {\n showmorelink: '[data-action=\"showmore\"]'\n },\n classes: {\n hidden: 'd-none',\n visible: 'd-block',\n\n }\n};\n\n/**\n * Displays all the availability information in case part of it is hidden.\n *\n * @param {Event} event the triggered event\n */\nconst showMoreHandler = (event) => {\n const triggerElement = event.target.closest(Selectors.actions.showmorelink);\n if (triggerElement === null) {\n return;\n }\n const container = triggerElement.closest(Selectors.regions.availability);\n container.querySelectorAll('.' + Selectors.classes.hidden).forEach(function(node) {\n node.classList.remove(Selectors.classes.hidden);\n });\n container.querySelectorAll('.' + Selectors.classes.visible).forEach(function(node) {\n node.classList.remove(Selectors.classes.visible);\n node.classList.add(Selectors.classes.hidden);\n });\n event.preventDefault();\n};\n\n/**\n * Initialise the eventlister for the showmore action on availability information.\n *\n * @method init\n */\nexport const init = () => {\n const body = document.querySelector('body');\n if (!body.dataset.showmoreactive) {\n document.addEventListener('click', showMoreHandler);\n body.dataset.showmoreactive = 1;\n }\n};\n"],"names":["Selectors","availability","showmorelink","hidden","visible","showMoreHandler","event","triggerElement","target","closest","container","querySelectorAll","forEach","node","classList","remove","add","preventDefault","body","document","querySelector","dataset","showmoreactive","addEventListener"],"mappings":";;;;;;;;MA0BMA,kBACO,CACLC,aAAc,yCAFhBD,kBAIO,CACLE,aAAc,4BALhBF,kBAOO,CACLG,OAAQ,SACRC,QAAS,WAUXC,gBAAmBC,cACfC,eAAiBD,MAAME,OAAOC,QAAQT,kBAAkBE,iBACvC,OAAnBK,4BAGEG,UAAYH,eAAeE,QAAQT,kBAAkBC,cAC3DS,UAAUC,iBAAiB,IAAMX,kBAAkBG,QAAQS,SAAQ,SAASC,MACxEA,KAAKC,UAAUC,OAAOf,kBAAkBG,WAE5CO,UAAUC,iBAAiB,IAAMX,kBAAkBI,SAASQ,SAAQ,SAASC,MACzEA,KAAKC,UAAUC,OAAOf,kBAAkBI,SACxCS,KAAKC,UAAUE,IAAIhB,kBAAkBG,WAEzCG,MAAMW,gCAQU,WACVC,KAAOC,SAASC,cAAc,QAC/BF,KAAKG,QAAQC,iBACdH,SAASI,iBAAiB,QAASlB,iBACnCa,KAAKG,QAAQC,eAAiB"}
\ No newline at end of file
diff --git a/availability/condition/completion/yui/build/moodle-availability_completion-form/moodle-availability_completion-form-min.js b/availability/condition/completion/yui/build/moodle-availability_completion-form/moodle-availability_completion-form-min.js
index 3c31ebec29f..06805c7054d 100644
--- a/availability/condition/completion/yui/build/moodle-availability_completion-form/moodle-availability_completion-form-min.js
+++ b/availability/condition/completion/yui/build/moodle-availability_completion-form/moodle-availability_completion-form-min.js
@@ -1 +1 @@
-YUI.add("moodle-availability_completion-form",function(o,e){M.availability_completion=M.availability_completion||{},M.availability_completion.form=o.Object(M.core_availability.plugin),M.availability_completion.form.initInner=function(e){this.cms=e},M.availability_completion.form.getNode=function(e){var i,l,t,a=' '+M.util.get_string("title","availability_completion")+'",t=o.Node.create(''+a+""),e.cm!==undefined&&t.one("select[name=cm] > option[value="+e.cm+"]")&&t.one("select[name=cm]").set("value",""+e.cm),e.e!==undefined&&t.one("select[name=e]").set("value",""+e.e),M.availability_completion.form.addedEvents||(M.availability_completion.form.addedEvents=!0,o.one(".availability-field").delegate("change",function(){M.core_availability.form.update()},".availability_completion select")),t},M.availability_completion.form.fillValue=function(e,i){e.cm=parseInt(i.one("select[name=cm]").get("value"),10),e.e=parseInt(i.one("select[name=e]").get("value"),10)},M.availability_completion.form.fillErrors=function(i,e){var l,t=parseInt(e.one("select[name=cm]").get("value"),10);0===t&&i.push("availability_completion:error_selectcmid"),2!==(l=parseInt(e.one("select[name=e]").get("value"),10))&&3!==l||this.cms.forEach(function(e){e.id===t&&null===e.completiongradeitemnumber&&i.push("availability_completion:error_selectcmidpassfail")})}},"@VERSION@",{requires:["base","node","event","moodle-core_availability-form"]});
\ No newline at end of file
+YUI.add("moodle-availability_completion-form",function(o,e){M.availability_completion=M.availability_completion||{},M.availability_completion.form=o.Object(M.core_availability.plugin),M.availability_completion.form.initInner=function(e){this.cms=e},M.availability_completion.form.getNode=function(e){for(var i,l,t=' '+M.util.get_string("title","availability_completion")+'",l=o.Node.create(''+t+""),e.cm!==undefined&&l.one("select[name=cm] > option[value="+e.cm+"]")&&l.one("select[name=cm]").set("value",""+e.cm),e.e!==undefined&&l.one("select[name=e]").set("value",""+e.e),M.availability_completion.form.addedEvents||(M.availability_completion.form.addedEvents=!0,o.one(".availability-field").delegate("change",function(){M.core_availability.form.update()},".availability_completion select")),l},M.availability_completion.form.fillValue=function(e,i){e.cm=parseInt(i.one("select[name=cm]").get("value"),10),e.e=parseInt(i.one("select[name=e]").get("value"),10)},M.availability_completion.form.fillErrors=function(i,e){var l=parseInt(e.one("select[name=cm]").get("value"),10);0===l&&i.push("availability_completion:error_selectcmid"),2!==(e=parseInt(e.one("select[name=e]").get("value"),10))&&3!==e||this.cms.forEach(function(e){e.id===l&&null===e.completiongradeitemnumber&&i.push("availability_completion:error_selectcmidpassfail")})}},"@VERSION@",{requires:["base","node","event","moodle-core_availability-form"]});
\ No newline at end of file
diff --git a/availability/condition/date/yui/build/moodle-availability_date-form/moodle-availability_date-form-min.js b/availability/condition/date/yui/build/moodle-availability_date-form/moodle-availability_date-form-min.js
index 4235144f9b4..04b294fb600 100644
--- a/availability/condition/date/yui/build/moodle-availability_date-form/moodle-availability_date-form-min.js
+++ b/availability/condition/date/yui/build/moodle-availability_date-form/moodle-availability_date-form-min.js
@@ -1 +1 @@
-YUI.add("moodle-availability_date-form",function(s,e){M.availability_date=M.availability_date||{},M.availability_date.form=s.Object(M.core_availability.plugin),M.availability_date.form.initInner=function(e,a){this.html=e,this.defaultTime=a},M.availability_date.form.getNode=function(e){var a,t,i,l,n=''+M.util.get_string("direction_before","availability_date")+' "+this.html,o=s.Node.create(""+n+"");return e.t!==undefined?(o.setData("time",e.t),o.all("select:not([name=direction])").each(function(e){e.set("disabled",!0)}),a=M.cfg.wwwroot+"/availability/condition/date/ajax.php?action=fromtime&time="+e.t,s.io(a,{on:{success:function(e,a){var t,i,l=s.JSON.parse(a.responseText);for(t in l)(i=o.one("select[name=x\\["+t+"\\]]")).set("value",""+l[t]),i.set("disabled",!1)},failure:function(){window.alert(M.util.get_string("ajaxerror","availability_date"))}}})):o.setData("time",this.defaultTime),e.d!==undefined&&o.one("select[name=direction]").set("value",e.d),M.availability_date.form.addedEvents||(M.availability_date.form.addedEvents=!0,(t=s.one(".availability-field")).delegate("change",function(){M.core_availability.form.update()},".availability_date select[name=direction]"),t.delegate("change",function(){M.availability_date.form.updateTime(this.ancestor("span.availability_date"))},".availability_date select:not([name=direction])")),o.one("a[href=#]")&&(M.form.dateselector.init_single_date_selector(o),i=o.one("select[name=x\\[year\\]]"),l=i.set,i.set=function(e,a){l.call(i,e,a),"selectedIndex"===e&&setTimeout(function(){M.availability_date.form.updateTime(o)},0)}),o},M.availability_date.form.updateTime=function(t){var e=M.cfg.wwwroot+"/availability/condition/date/ajax.php?action=totime&year="+t.one("select[name=x\\[year\\]]").get("value")+"&month="+t.one("select[name=x\\[month\\]]").get("value")+"&day="+t.one("select[name=x\\[day\\]]").get("value")+"&hour="+t.one("select[name=x\\[hour\\]]").get("value")+"&minute="+t.one("select[name=x\\[minute\\]]").get("value");s.io(e,{on:{success:function(e,a){t.setData("time",a.responseText),M.core_availability.form.update()},failure:function(){window.alert(M.util.get_string("ajaxerror","availability_date"))}}})},M.availability_date.form.fillValue=function(e,a){e.d=a.one("select[name=direction]").get("value"),e.t=parseInt(a.getData("time"),10)}},"@VERSION@",{requires:["base","node","event","io","moodle-core_availability-form"]});
\ No newline at end of file
+YUI.add("moodle-availability_date-form",function(o,e){M.availability_date=M.availability_date||{},M.availability_date.form=o.Object(M.core_availability.plugin),M.availability_date.form.initInner=function(e,a){this.html=e,this.defaultTime=a},M.availability_date.form.getNode=function(e){var t,i,a=''+M.util.get_string("direction_before","availability_date")+' "+this.html,n=o.Node.create(""+a+"");return e.t!==undefined?(n.setData("time",e.t),n.all("select:not([name=direction])").each(function(e){e.set("disabled",!0)}),a=M.cfg.wwwroot+"/availability/condition/date/ajax.php?action=fromtime&time="+e.t,o.io(a,{on:{success:function(e,a){var t,i,l=o.JSON.parse(a.responseText);for(t in l)(i=n.one("select[name=x\\["+t+"\\]]")).set("value",""+l[t]),i.set("disabled",!1)},failure:function(){window.alert(M.util.get_string("ajaxerror","availability_date"))}}})):n.setData("time",this.defaultTime),e.d!==undefined&&n.one("select[name=direction]").set("value",e.d),M.availability_date.form.addedEvents||(M.availability_date.form.addedEvents=!0,(a=o.one(".availability-field")).delegate("change",function(){M.core_availability.form.update()},".availability_date select[name=direction]"),a.delegate("change",function(){M.availability_date.form.updateTime(this.ancestor("span.availability_date"))},".availability_date select:not([name=direction])")),n.one("a[href=#]")&&(M.form.dateselector.init_single_date_selector(n),t=n.one("select[name=x\\[year\\]]"),i=t.set,t.set=function(e,a){i.call(t,e,a),"selectedIndex"===e&&setTimeout(function(){M.availability_date.form.updateTime(n)},0)}),n},M.availability_date.form.updateTime=function(t){var e=M.cfg.wwwroot+"/availability/condition/date/ajax.php?action=totime&year="+t.one("select[name=x\\[year\\]]").get("value")+"&month="+t.one("select[name=x\\[month\\]]").get("value")+"&day="+t.one("select[name=x\\[day\\]]").get("value")+"&hour="+t.one("select[name=x\\[hour\\]]").get("value")+"&minute="+t.one("select[name=x\\[minute\\]]").get("value");o.io(e,{on:{success:function(e,a){t.setData("time",a.responseText),M.core_availability.form.update()},failure:function(){window.alert(M.util.get_string("ajaxerror","availability_date"))}}})},M.availability_date.form.fillValue=function(e,a){e.d=a.one("select[name=direction]").get("value"),e.t=parseInt(a.getData("time"),10)}},"@VERSION@",{requires:["base","node","event","io","moodle-core_availability-form"]});
\ No newline at end of file
diff --git a/availability/condition/grade/yui/build/moodle-availability_grade-form/moodle-availability_grade-form-min.js b/availability/condition/grade/yui/build/moodle-availability_grade-form/moodle-availability_grade-form-min.js
index 0e71a081388..2e8fe8c5a40 100644
--- a/availability/condition/grade/yui/build/moodle-availability_grade-form/moodle-availability_grade-form-min.js
+++ b/availability/condition/grade/yui/build/moodle-availability_grade-form/moodle-availability_grade-form-min.js
@@ -1 +1 @@
-YUI.add("moodle-availability_grade-form",function(o,a){M.availability_grade=M.availability_grade||{},M.availability_grade.form=o.Object(M.core_availability.plugin),M.availability_grade.form.grades=null,M.availability_grade.form.initInner=function(a){this.grades=a,this.nodesSoFar=0},M.availability_grade.form.getNode=function(a){var e,i,l,t,n,r;for(this.nodesSoFar++,e=' % %',t=o.Node.create('
"),o.appendChild(a),c(a,l));u=function(){var e,n,t=g.one("#backup-bytype");o.currentlyshown?t.setHTML(M.util.get_string("showtypes","backup")):t.setHTML(M.util.get_string("hidetypes","backup")),o.currentlyshown=!o.currentlyshown,e={node:o,duration:.2},o.currentlyshown?(o.show(),e.to={maxHeight:o.get("clientHeight")+"px"},o.setStyle("maxHeight","0px"),(n=new g.Anim(e)).on("end",function(){o.setStyle("maxHeight","none")})):(e.to={maxHeight:"0px"},o.setStyle("maxHeight",o.get("clientHeight")+"px"),(n=new g.Anim(e)).on("end",function(){o.hide(),o.setStyle("maxHeight","none")})),n.run()},g.one("#backup-bytype").on("click",function(e){e.preventDefault(),u()}),g.one("#backup-all-included").on("click",function(e){d(e,!0,"_included")}),g.one("#backup-none-included").on("click",function(e){d(e,!1,"_included")}),t&&(g.one("#backup-all-userdata").on("click",function(e){d(e,!0,t)}),g.one("#backup-none-userdata").on("click",function(e){d(e,!1,t)}))}}},"@VERSION@",{requires:["node","event","node-event-simulate","anim"]});
\ No newline at end of file
+YUI.add("moodle-backup-backupselectall",function(g,e){M.core_backup=M.core_backup||{},M.core_backup.backupselectall=function(e){var t,n,i,d,c,o,r,p,l=null,a=function(e,t,i,n){var c,o;e.preventDefault(),c=void 0!==n?"setting_activity_"+n+"_":"",o=i.length,g.all('input[type="checkbox"]').each(function(e){var n=e.get("name");c&&n.substring(0,c.length)!==c||n.substring(n.length-o)===i&&e.set("checked",t)}),l&&M.form&&M.form.updateFormState(l)},u=function(e,n,t,i){return void 0===i&&(i=""),'
"),c.appendChild(r),d(0,o));p=function(){var e,n=g.one("#backup-bytype");c.currentlyshown?n.setHTML(M.util.get_string("showtypes","backup")):n.setHTML(M.util.get_string("hidetypes","backup")),c.currentlyshown=!c.currentlyshown,n={node:c,duration:.2},c.currentlyshown?(c.show(),n.to={maxHeight:c.get("clientHeight")+"px"},c.setStyle("maxHeight","0px"),(e=new g.Anim(n)).on("end",function(){c.setStyle("maxHeight","none")})):(n.to={maxHeight:"0px"},c.setStyle("maxHeight",c.get("clientHeight")+"px"),(e=new g.Anim(n)).on("end",function(){c.hide(),c.setStyle("maxHeight","none")})),e.run()},g.one("#backup-bytype").on("click",function(e){e.preventDefault(),p()}),g.one("#backup-all-included").on("click",function(e){a(e,!0,"_included")}),g.one("#backup-none-included").on("click",function(e){a(e,!1,"_included")}),t&&(g.one("#backup-all-userdata").on("click",function(e){a(e,!0,t)}),g.one("#backup-none-userdata").on("click",function(e){a(e,!1,t)}))}}},"@VERSION@",{requires:["node","event","node-event-simulate","anim"]});
\ No newline at end of file
diff --git a/backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel-min.js b/backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel-min.js
index 74d17a34a96..f6e5b92364f 100644
--- a/backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel-min.js
+++ b/backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel-min.js
@@ -1 +1 @@
-YUI.add("moodle-backup-confirmcancel",function(n,c){M.core_backup=M.core_backup||{},M.core_backup.confirmcancel={listeners:[],config:{},watch_cancel_buttons:function(c){this.config=c,this.listeners.push(n.one(n.config.doc.body).delegate("click",this.confirm_cancel,".confirmcancel",this))},confirm_cancel:function(e){e.preventDefault();var c=new M.core.confirm(this.config);c.on("complete-yes",function(){new n.EventHandle(M.core_backup.confirmcancel.listeners).detach();var c=e.currentTarget.one("input, select, button");c?c.simulate("click"):e.currentTarget.simulate("click")},this),c.show()}}},"@VERSION@",{requires:["node","node-event-simulate","moodle-core-notification-confirm"]});
\ No newline at end of file
+YUI.add("moodle-backup-confirmcancel",function(n,c){M.core_backup=M.core_backup||{},M.core_backup.confirmcancel={listeners:[],config:{},watch_cancel_buttons:function(c){this.config=c,this.listeners.push(n.one(n.config.doc.body).delegate("click",this.confirm_cancel,".confirmcancel",this))},confirm_cancel:function(e){e.preventDefault();var c=new M.core.confirm(this.config);c.on("complete-yes",function(){new n.EventHandle(M.core_backup.confirmcancel.listeners).detach();var c=e.currentTarget.one("input, select, button");(c||e.currentTarget).simulate("click")},this),c.show()}}},"@VERSION@",{requires:["node","node-event-simulate","moodle-core-notification-confirm"]});
\ No newline at end of file
diff --git a/badges/amd/build/backpackactions.min.js b/badges/amd/build/backpackactions.min.js
index 659e07cacba..2aac63c12e3 100644
--- a/badges/amd/build/backpackactions.min.js
+++ b/badges/amd/build/backpackactions.min.js
@@ -1,2 +1,10 @@
-define ("core_badges/backpackactions",["exports","jquery","core_badges/selectors","core/str","core/pending","core/modal_factory","core/modal_events","core/config"],function(a,b,c,d,e,f,g,h){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=i(b);c=i(c);e=i(e);f=i(f);g=i(g);h=i(h);function i(a){return a&&a.__esModule?a:{default:a}}function j(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 k(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){j(h,d,e,f,g,"next",a)}function g(a){j(h,d,e,f,g,"throw",a)}f(void 0)})}}var l=function(){var a=new e.default,d=(0,b.default)(c.default.elements.main);m(d);a.resolve()};a.init=l;var m=function(a){a.on("click",c.default.actions.deletebackpack,function(){var a=k(regeneratorRuntime.mark(function a(c){var d,e;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:c.preventDefault();d=(0,b.default)(c.currentTarget);a.next=4;return n(d);case 4:e=a.sent;o(e,d);case 6:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}())},n=function(){var a=k(regeneratorRuntime.mark(function a(b){var e;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:e=b.closest(c.default.elements.backpackurl).attr("data-backpackurl");a.t0=f.default;a.next=4;return(0,d.get_string)("delexternalbackpack","core_badges");case 4:a.t1=a.sent;a.next=7;return(0,d.get_string)("delexternalbackpackconfirm","core_badges",e);case 7:a.t2=a.sent;a.t3=f.default.types.SAVE_CANCEL;a.t4={title:a.t1,body:a.t2,type:a.t3};return a.abrupt("return",a.t0.create.call(a.t0,a.t4));case 11:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}(),o=function(){var a=k(regeneratorRuntime.mark(function a(b,c){return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:a.t0=b;a.next=3;return(0,d.get_string)("delete","core");case 3:a.t1=a.sent;a.t0.setSaveButtonText.call(a.t0,a.t1);b.getRoot().on(g.default.save,function(){window.location.href=c.attr("href")+"&sesskey="+h.default.sesskey+"&confirm=1"});b.getRoot().on(g.default.hidden,function(){b.destroy()});b.show();case 8:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}()});
-//# sourceMappingURL=backpackactions.min.js.map
+define("core_badges/backpackactions",["exports","jquery","core_badges/selectors","core/str","core/pending","core/modal_factory","core/modal_events","core/config"],(function(_exports,_jquery,_selectors,_str,_pending,_modal_factory,_modal_events,_config){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
+/**
+ * Action methods related to backpacks.
+ *
+ * @module core_badges/backpackactions
+ * @copyright 2020 Sara Arjona
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),_selectors=_interopRequireDefault(_selectors),_pending=_interopRequireDefault(_pending),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_config=_interopRequireDefault(_config);_exports.init=()=>{const pendingPromise=new _pending.default,root=(0,_jquery.default)(_selectors.default.elements.main);registerListenerEvents(root),pendingPromise.resolve()};const registerListenerEvents=root=>{root.on("click",_selectors.default.actions.deletebackpack,(async e=>{e.preventDefault();const link=(0,_jquery.default)(e.currentTarget),modal=await buildModal(link);displayModal(modal,link)}))},buildModal=async link=>{const backpackurl=link.closest(_selectors.default.elements.backpackurl).attr("data-backpackurl");return _modal_factory.default.create({title:await(0,_str.get_string)("delexternalbackpack","core_badges"),body:await(0,_str.get_string)("delexternalbackpackconfirm","core_badges",backpackurl),type:_modal_factory.default.types.SAVE_CANCEL})},displayModal=async(modal,link)=>{modal.setSaveButtonText(await(0,_str.get_string)("delete","core")),modal.getRoot().on(_modal_events.default.save,(function(){window.location.href=link.attr("href")+"&sesskey="+_config.default.sesskey+"&confirm=1"})),modal.getRoot().on(_modal_events.default.hidden,(function(){modal.destroy()})),modal.show()}}));
+
+//# sourceMappingURL=backpackactions.min.js.map
\ No newline at end of file
diff --git a/badges/amd/build/backpackactions.min.js.map b/badges/amd/build/backpackactions.min.js.map
index 2076c3b9b31..d409d5dce56 100644
--- a/badges/amd/build/backpackactions.min.js.map
+++ b/badges/amd/build/backpackactions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/backpackactions.js"],"names":["init","pendingPromise","Pending","root","selectors","elements","main","registerListenerEvents","resolve","on","actions","deletebackpack","e","preventDefault","link","currentTarget","buildModal","modal","displayModal","backpackurl","closest","attr","ModalFactory","types","SAVE_CANCEL","title","body","type","create","setSaveButtonText","getRoot","ModalEvents","save","window","location","href","Config","sesskey","hidden","destroy","show"],"mappings":"0QAuBA,OACA,OAEA,OACA,OACA,OACA,O,kXAOO,GAAMA,CAAAA,CAAI,CAAG,UAAM,IAChBC,CAAAA,CAAc,CAAG,GAAIC,UADL,CAGhBC,CAAI,CAAG,cAAEC,UAAUC,QAAV,CAAmBC,IAArB,CAHS,CAItBC,CAAsB,CAACJ,CAAD,CAAtB,CAEAF,CAAc,CAACO,OAAf,EACH,CAPM,C,YAeDD,CAAAA,CAAsB,CAAG,SAACJ,CAAD,CAAU,CAErCA,CAAI,CAACM,EAAL,CAAQ,OAAR,CAAiBL,UAAUM,OAAV,CAAkBC,cAAnC,4CAAmD,WAAMC,CAAN,2FAC/CA,CAAC,CAACC,cAAF,GAEMC,CAHyC,CAGlC,cAAEF,CAAC,CAACG,aAAJ,CAHkC,gBAI3BC,CAAAA,CAAU,CAACF,CAAD,CAJiB,QAIzCG,CAJyC,QAM/CC,CAAY,CAACD,CAAD,CAAQH,CAAR,CAAZ,CAN+C,wCAAnD,wDAQH,C,CAEKE,CAAU,4CAAG,WAAMF,CAAN,yFAETK,CAFS,CAEKL,CAAI,CAACM,OAAL,CAAahB,UAAUC,QAAV,CAAmBc,WAAhC,EAA6CE,IAA7C,CAAkD,kBAAlD,CAFL,MAIRC,SAJQ,gBAKE,iBAAU,qBAAV,CAAiC,aAAjC,CALF,mCAMC,iBAAU,4BAAV,CAAwC,aAAxC,CAAuDH,CAAvD,CAND,yBAOLG,UAAaC,KAAb,CAAmBC,WAPd,OAKXC,KALW,MAMXC,IANW,MAOXC,IAPW,qCAIKC,MAJL,2DAAH,uD,CAYVV,CAAY,4CAAG,WAAMD,CAAN,CAAaH,CAAb,wFACjBG,CADiB,gBACa,iBAAU,QAAV,CAAoB,MAApB,CADb,yBACXY,iBADW,iBAGjBZ,CAAK,CAACa,OAAN,GAAgBrB,EAAhB,CAAmBsB,UAAYC,IAA/B,CAAqC,UAAW,CAC5CC,MAAM,CAACC,QAAP,CAAgBC,IAAhB,CAAuBrB,CAAI,CAACO,IAAL,CAAU,MAAV,EAAoB,WAApB,CAAkCe,UAAOC,OAAzC,CAAmD,YAC7E,CAFD,EAIApB,CAAK,CAACa,OAAN,GAAgBrB,EAAhB,CAAmBsB,UAAYO,MAA/B,CAAuC,UAAW,CAC9CrB,CAAK,CAACsB,OAAN,EACH,CAFD,EAIAtB,CAAK,CAACuB,IAAN,GAXiB,wCAAH,uD","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 .\n\n/**\n * Action methods related to backpacks.\n *\n * @module core_badges/backpackactions\n * @copyright 2020 Sara Arjona \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport selectors from 'core_badges/selectors';\nimport {get_string as getString} from 'core/str';\nimport Pending from 'core/pending';\nimport ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport Config from 'core/config';\n\n/**\n * Set up the actions.\n *\n * @method init\n */\nexport const init = () => {\n const pendingPromise = new Pending();\n\n const root = $(selectors.elements.main);\n registerListenerEvents(root);\n\n pendingPromise.resolve();\n};\n\n/**\n * Register backpack related event listeners.\n *\n * @method registerListenerEvents\n * @param {Object} root The root element.\n */\nconst registerListenerEvents = (root) => {\n\n root.on('click', selectors.actions.deletebackpack, async(e) => {\n e.preventDefault();\n\n const link = $(e.currentTarget);\n const modal = await buildModal(link);\n\n displayModal(modal, link);\n });\n};\n\nconst buildModal = async(link) => {\n\n const backpackurl = link.closest(selectors.elements.backpackurl).attr('data-backpackurl');\n\n return ModalFactory.create({\n title: await getString('delexternalbackpack', 'core_badges'),\n body: await getString('delexternalbackpackconfirm', 'core_badges', backpackurl),\n type: ModalFactory.types.SAVE_CANCEL,\n });\n\n};\n\nconst displayModal = async(modal, link) => {\n modal.setSaveButtonText(await getString('delete', 'core'));\n\n modal.getRoot().on(ModalEvents.save, function() {\n window.location.href = link.attr('href') + '&sesskey=' + Config.sesskey + '&confirm=1';\n });\n\n modal.getRoot().on(ModalEvents.hidden, function() {\n modal.destroy();\n });\n\n modal.show();\n};\n"],"file":"backpackactions.min.js"}
\ No newline at end of file
+{"version":3,"file":"backpackactions.min.js","sources":["../src/backpackactions.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 .\n\n/**\n * Action methods related to backpacks.\n *\n * @module core_badges/backpackactions\n * @copyright 2020 Sara Arjona \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport selectors from 'core_badges/selectors';\nimport {get_string as getString} from 'core/str';\nimport Pending from 'core/pending';\nimport ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport Config from 'core/config';\n\n/**\n * Set up the actions.\n *\n * @method init\n */\nexport const init = () => {\n const pendingPromise = new Pending();\n\n const root = $(selectors.elements.main);\n registerListenerEvents(root);\n\n pendingPromise.resolve();\n};\n\n/**\n * Register backpack related event listeners.\n *\n * @method registerListenerEvents\n * @param {Object} root The root element.\n */\nconst registerListenerEvents = (root) => {\n\n root.on('click', selectors.actions.deletebackpack, async(e) => {\n e.preventDefault();\n\n const link = $(e.currentTarget);\n const modal = await buildModal(link);\n\n displayModal(modal, link);\n });\n};\n\nconst buildModal = async(link) => {\n\n const backpackurl = link.closest(selectors.elements.backpackurl).attr('data-backpackurl');\n\n return ModalFactory.create({\n title: await getString('delexternalbackpack', 'core_badges'),\n body: await getString('delexternalbackpackconfirm', 'core_badges', backpackurl),\n type: ModalFactory.types.SAVE_CANCEL,\n });\n\n};\n\nconst displayModal = async(modal, link) => {\n modal.setSaveButtonText(await getString('delete', 'core'));\n\n modal.getRoot().on(ModalEvents.save, function() {\n window.location.href = link.attr('href') + '&sesskey=' + Config.sesskey + '&confirm=1';\n });\n\n modal.getRoot().on(ModalEvents.hidden, function() {\n modal.destroy();\n });\n\n modal.show();\n};\n"],"names":["pendingPromise","Pending","root","selectors","elements","main","registerListenerEvents","resolve","on","actions","deletebackpack","async","e","preventDefault","link","currentTarget","modal","buildModal","displayModal","backpackurl","closest","attr","ModalFactory","create","title","body","type","types","SAVE_CANCEL","setSaveButtonText","getRoot","ModalEvents","save","window","location","href","Config","sesskey","hidden","destroy","show"],"mappings":";;;;;;;kXAoCoB,WACVA,eAAiB,IAAIC,iBAErBC,MAAO,mBAAEC,mBAAUC,SAASC,MAClCC,uBAAuBJ,MAEvBF,eAAeO,iBASbD,uBAA0BJ,OAE5BA,KAAKM,GAAG,QAASL,mBAAUM,QAAQC,gBAAgBC,MAAAA,IAC/CC,EAAEC,uBAEIC,MAAO,mBAAEF,EAAEG,eACXC,YAAcC,WAAWH,MAE/BI,aAAaF,MAAOF,UAItBG,WAAaN,MAAAA,aAETQ,YAAcL,KAAKM,QAAQjB,mBAAUC,SAASe,aAAaE,KAAK,2BAE/DC,uBAAaC,OAAO,CACvBC,YAAa,mBAAU,sBAAuB,eAC9CC,WAAY,mBAAU,6BAA8B,cAAeN,aACnEO,KAAMJ,uBAAaK,MAAMC,eAK3BV,aAAeP,MAAMK,MAAOF,QAC9BE,MAAMa,wBAAwB,mBAAU,SAAU,SAElDb,MAAMc,UAAUtB,GAAGuB,sBAAYC,MAAM,WACjCC,OAAOC,SAASC,KAAOrB,KAAKO,KAAK,QAAU,YAAce,gBAAOC,QAAU,gBAG9ErB,MAAMc,UAAUtB,GAAGuB,sBAAYO,QAAQ,WACnCtB,MAAMuB,aAGVvB,MAAMwB"}
\ No newline at end of file
diff --git a/badges/amd/build/selectors.min.js b/badges/amd/build/selectors.min.js
index dbe7b36586e..916edb19d88 100644
--- a/badges/amd/build/selectors.min.js
+++ b/badges/amd/build/selectors.min.js
@@ -1,2 +1,3 @@
-define ("core_badges/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;var b={actions:{deletebackpack:function getDataSelector(a,b){return"[data-".concat(a,"=\"").concat(b,"\"]")}("action","deletebackpack")},elements:{clearsearch:".input-group-append .clear-icon",main:"#backpacklist",backpackurl:"[data-backpackurl]"}};a.default=b;return a.default});
-//# sourceMappingURL=selectors.min.js.map
+define("core_badges/selectors",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;var name,value,_default={actions:{deletebackpack:(name="action",value="deletebackpack","[data-".concat(name,'="').concat(value,'"]'))},elements:{clearsearch:".input-group-append .clear-icon",main:"#backpacklist",backpackurl:"[data-backpackurl]"}};return _exports.default=_default,_exports.default}));
+
+//# sourceMappingURL=selectors.min.js.map
\ No newline at end of file
diff --git a/badges/amd/build/selectors.min.js.map b/badges/amd/build/selectors.min.js.map
index 1683db8e3b4..36bcd53ad01 100644
--- a/badges/amd/build/selectors.min.js.map
+++ b/badges/amd/build/selectors.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/selectors.js"],"names":["actions","deletebackpack","getDataSelector","name","value","elements","clearsearch","main","backpackurl"],"mappings":"6IAmCe,CACXA,OAAO,CAAE,CACLC,cAAc,CANE,QAAlBC,CAAAA,eAAkB,CAACC,CAAD,CAAOC,CAAP,CAAiB,CACrC,sBAAgBD,CAAhB,eAAyBC,CAAzB,OACH,CAIuB,CAAgB,QAAhB,CAA0B,gBAA1B,CADX,CADE,CAIXC,QAAQ,CAAE,CACNC,WAAW,CAAE,iCADP,CAENC,IAAI,CAAE,eAFA,CAGNC,WAAW,CAAE,oBAHP,CAJC,C","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 .\n\n/**\n * Define all of the selectors we will be using on the backpack interface.\n *\n * @module core_badges/selectors\n * @copyright 2020 Sara Arjona \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * A small helper function to build queryable data selectors.\n *\n * @method getDataSelector\n * @param {String} name\n * @param {String} value\n * @return {string}\n */\nconst getDataSelector = (name, value) => {\n return `[data-${name}=\"${value}\"]`;\n};\n\nexport default {\n actions: {\n deletebackpack: getDataSelector('action', 'deletebackpack'),\n },\n elements: {\n clearsearch: '.input-group-append .clear-icon',\n main: '#backpacklist',\n backpackurl: '[data-backpackurl]',\n },\n};\n"],"file":"selectors.min.js"}
\ No newline at end of file
+{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 .\n\n/**\n * Define all of the selectors we will be using on the backpack interface.\n *\n * @module core_badges/selectors\n * @copyright 2020 Sara Arjona \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * A small helper function to build queryable data selectors.\n *\n * @method getDataSelector\n * @param {String} name\n * @param {String} value\n * @return {string}\n */\nconst getDataSelector = (name, value) => {\n return `[data-${name}=\"${value}\"]`;\n};\n\nexport default {\n actions: {\n deletebackpack: getDataSelector('action', 'deletebackpack'),\n },\n elements: {\n clearsearch: '.input-group-append .clear-icon',\n main: '#backpacklist',\n backpackurl: '[data-backpackurl]',\n },\n};\n"],"names":["name","value","actions","deletebackpack","elements","clearsearch","main","backpackurl"],"mappings":"mJA+ByBA,KAAMC,eAIhB,CACXC,QAAS,CACLC,gBANiBH,KAMe,SANTC,MAMmB,iCAL9BD,kBAASC,cAOzBG,SAAU,CACNC,YAAa,kCACbC,KAAM,gBACNC,YAAa"}
\ No newline at end of file
diff --git a/blocks/accessreview/amd/build/module.min.js b/blocks/accessreview/amd/build/module.min.js
index 2b50196958d..bb66a3b0c6f 100644
--- a/blocks/accessreview/amd/build/module.min.js
+++ b/blocks/accessreview/amd/build/module.min.js
@@ -1,2 +1,11 @@
-function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("block_accessreview/module",["exports","core/ajax","core/templates","core/notification"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;c=f(c);function e(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;e=function(){return a};return a}function f(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=e();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var f in a){if(Object.prototype.hasOwnProperty.call(a,f)){var g=d?Object.getOwnPropertyDescriptor(a,f):null;if(g&&(g.get||g.set)){Object.defineProperty(c,f,g)}else{c[f]=a[f]}}}c.default=a;if(b){b.set(a,c)}return c}function g(a,b){return m(a)||l(a,b)||j(a,b)||h()}function h(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function j(a,b){if(!a)return;if("string"==typeof a)return k(a,b);var c=Object.prototype.toString.call(a).slice(8,-1);if("Object"===c&&a.constructor)c=a.constructor.name;if("Map"===c||"Set"===c)return Array.from(c);if("Arguments"===c||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(c))return k(a,b)}function k(a,b){if(null==b||b>a.length)b=a.length;for(var c=0,d=Array(b);cc.maxViews){c.maxViews=a.numerrors}c.totalUsers+=a.numchecks});c.viewDelta=c.maxViews-c.minViews+1;return c},t=function(a,b){document.addEventListener("click",function(c){if(c.target.closest("#toggle-accessmap")){c.preventDefault();r(a,b)}})},u=function(a){return{methodname:"core_user_update_user_preferences",args:{preferences:[{type:"block_accessreviewtogglestate",value:a}]}}},v=function(a){return(0,b.call)([u(a)])},w=function(a){var c=1
+ * @copyright 2020 Brickfield Education Labs
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */(Templates);let toggleState=!0;const renderTemplate=(element,errorCount,checkCount,displayFormat,minViews,viewDelta)=>{const weight=parseInt((errorCount-minViews)/viewDelta*2),context={resultPassed:!errorCount,classList:"",passRate:{errorCount:errorCount,checkCount:checkCount,failureRate:Math.round(errorCount/checkCount*100)}};if(!element)return Promise.resolve();const elementClassList=["block_accessreview"];context.resultPassed?elementClassList.push("block_accessreview_success"):weight?elementClassList.push("block_accessreview_danger"):elementClassList.push("block_accessreview_warning");const showIcons="showicons"==displayFormat||"showboth"==displayFormat,showBackground="showbackground"==displayFormat||"showboth"==displayFormat;return showBackground&&!showIcons?(element.classList.add(...elementClassList,"alert"),Promise.resolve()):(showIcons&&!showBackground&&(context.classList=elementClassList.join(" ")),Templates.renderForPromise("block_accessreview/status",context).then((_ref=>{let{html:html,js:js}=_ref;Templates.appendNodeContents(element,html,js),showBackground&&element.classList.add(...elementClassList,"alert")})).catch())},showAccessMap=function(courseId,displayFormat){let updatePreference=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return Promise.all(fetchReviewData(courseId,updatePreference)).then((_ref2=>{let[sectionData,moduleData]=_ref2;const{minViews:minViews,viewDelta:viewDelta}=getErrorTotals(sectionData,moduleData);return sectionData.forEach((section=>{const element=document.querySelector("#section-".concat(section.section," .summary"));element&&renderTemplate(element,section.numerrors,section.numchecks,displayFormat,minViews,viewDelta)})),moduleData.forEach((module=>{const element=document.getElementById("module-".concat(module.cmid));element&&renderTemplate(element,module.numerrors,module.numchecks,displayFormat,minViews,viewDelta)})),document.querySelector(".icon-accessmap").classList.remove("fa-eye-slash"),document.querySelector(".icon-accessmap").classList.add("fa-eye"),{sectionData:sectionData,moduleData:moduleData}})).catch(_notification.exception)},toggleAccessMap=(courseId,displayFormat)=>{toggleState=!toggleState,toggleState?showAccessMap(courseId,displayFormat,!0):function(){let updatePreference=arguments.length>0&&void 0!==arguments[0]&&arguments[0];document.querySelectorAll(".block_accessreview_view").forEach((node=>node.remove()));const classList=["block_accessreview","block_accessreview_success","block_accessreview_warning","block_accessreview_danger","block_accessreview_view","alert"];document.querySelectorAll(".block_accessreview").forEach((node=>node.classList.remove(...classList))),updatePreference&&setToggleStatePreference(!1),document.querySelector(".icon-accessmap").classList.remove("fa-eye"),document.querySelector(".icon-accessmap").classList.add("fa-eye-slash")}(!0)},getErrorTotals=(sectionData,moduleData)=>{const totals={totalErrors:0,totalUsers:0,minViews:0,maxViews:0,viewDelta:0};return[].concat(sectionData,moduleData).forEach((item=>{totals.totalErrors+=item.numerrors,item.numerrorstotals.maxViews&&(totals.maxViews=item.numerrors),totals.totalUsers+=item.numchecks})),totals.viewDelta=totals.maxViews-totals.minViews+1,totals},getTogglePreferenceParams=toggleState=>({methodname:"core_user_update_user_preferences",args:{preferences:[{type:"block_accessreviewtogglestate",value:toggleState}]}}),setToggleStatePreference=toggleState=>(0,_ajax.call)([getTogglePreferenceParams(toggleState)]),fetchReviewData=function(courseid){let updatePreference=arguments.length>1&&void 0!==arguments[1]&&arguments[1];const calls=[{methodname:"block_accessreview_get_section_data",args:{courseid:courseid}},{methodname:"block_accessreview_get_module_data",args:{courseid:courseid}}];return updatePreference&&calls.push(getTogglePreferenceParams(!0)),(0,_ajax.call)(calls)};_exports.init=(toggled,displayFormat,courseId)=>{toggleState=1==toggled,toggleState&&showAccessMap(courseId,displayFormat),((courseId,displayFormat)=>{document.addEventListener("click",(e=>{e.target.closest("#toggle-accessmap")&&(e.preventDefault(),toggleAccessMap(courseId,displayFormat))}))})(courseId,displayFormat)}}));
+
+//# sourceMappingURL=module.min.js.map
\ No newline at end of file
diff --git a/blocks/accessreview/amd/build/module.min.js.map b/blocks/accessreview/amd/build/module.min.js.map
index 2129aef2683..dca3203930d 100644
--- a/blocks/accessreview/amd/build/module.min.js.map
+++ b/blocks/accessreview/amd/build/module.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/module.js"],"names":["toggleState","renderTemplate","element","errorCount","checkCount","displayFormat","minViews","viewDelta","weight","parseInt","context","resultPassed","classList","passRate","failureRate","Math","round","Promise","resolve","elementClassList","push","showIcons","showBackground","add","join","Templates","renderForPromise","then","html","js","appendNodeContents","catch","showAccessMap","courseId","updatePreference","all","fetchReviewData","sectionData","moduleData","getErrorTotals","forEach","section","document","querySelector","numerrors","numchecks","module","getElementById","cmid","remove","displayError","hideAccessMap","querySelectorAll","node","setToggleStatePreference","toggleAccessMap","totals","totalErrors","totalUsers","maxViews","concat","item","registerEventListeners","addEventListener","e","target","closest","preventDefault","getTogglePreferenceParams","methodname","args","preferences","type","value","courseid","calls","init","toggled"],"mappings":"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","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 .\n\n/**\n * Manager for the accessreview block.\n *\n * @module block_accessreview/module\n * @author Max Larkin \n * @copyright 2020 Brickfield Education Labs \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {call as fetchMany} from 'core/ajax';\nimport * as Templates from 'core/templates';\nimport {exception as displayError} from 'core/notification';\n\n/**\n * The number of colours used to represent the heatmap. (Indexed on 0.)\n * @type {number}\n */\nconst numColours = 2;\n\n/**\n * The toggle state of the heatmap.\n * @type {boolean}\n */\nlet toggleState = true;\n\n/**\n * Renders the HTML template onto a particular HTML element.\n * @param {HTMLElement} element The element to attach the HTML to.\n * @param {number} errorCount The number of errors on this module/section.\n * @param {number} checkCount The number of checks triggered on this module/section.\n * @param {String} displayFormat\n * @param {Number} minViews\n * @param {Number} viewDelta\n * @returns {Promise}\n */\nconst renderTemplate = (element, errorCount, checkCount, displayFormat, minViews, viewDelta) => {\n // Calculate a weight?\n const weight = parseInt((errorCount - minViews) / viewDelta * numColours);\n\n const context = {\n resultPassed: !errorCount,\n classList: '',\n passRate: {\n errorCount,\n checkCount,\n failureRate: Math.round(errorCount / checkCount * 100),\n },\n };\n\n if (!element) {\n return Promise.resolve();\n }\n\n const elementClassList = ['block_accessreview'];\n if (context.resultPassed) {\n elementClassList.push('block_accessreview_success');\n } else if (weight) {\n elementClassList.push('block_accessreview_danger');\n } else {\n elementClassList.push('block_accessreview_warning');\n }\n\n const showIcons = (displayFormat == 'showicons') || (displayFormat == 'showboth');\n const showBackground = (displayFormat == 'showbackground') || (displayFormat == 'showboth');\n\n if (showBackground && !showIcons) {\n // Only the background is displayed.\n // No need to display the template.\n // Note: The case where both the background and icons are shown is handled later to avoid jankiness.\n element.classList.add(...elementClassList, 'alert');\n\n return Promise.resolve();\n }\n\n if (showIcons && !showBackground) {\n context.classList = elementClassList.join(' ');\n }\n\n // The icons are displayed either with, or without, the background.\n return Templates.renderForPromise('block_accessreview/status', context)\n .then(({html, js}) => {\n Templates.appendNodeContents(element, html, js);\n\n if (showBackground) {\n element.classList.add(...elementClassList, 'alert');\n }\n\n return;\n })\n .catch();\n};\n\n/**\n * Applies the template to all sections and modules on the course page.\n *\n * @param {Number} courseId\n * @param {String} displayFormat\n * @param {Boolean} updatePreference\n * @returns {Promise}\n */\nconst showAccessMap = (courseId, displayFormat, updatePreference = false) => {\n // Get error data.\n return Promise.all(fetchReviewData(courseId, updatePreference))\n .then(([sectionData, moduleData]) => {\n // Get total data.\n const {minViews, viewDelta} = getErrorTotals(sectionData, moduleData);\n\n sectionData.forEach(section => {\n const element = document.querySelector(`#section-${section.section} .summary`);\n if (!element) {\n return;\n }\n\n renderTemplate(element, section.numerrors, section.numchecks, displayFormat, minViews, viewDelta);\n });\n\n moduleData.forEach(module => {\n const element = document.getElementById(`module-${module.cmid}`);\n if (!element) {\n return;\n }\n\n renderTemplate(element, module.numerrors, module.numchecks, displayFormat, minViews, viewDelta);\n });\n\n // Change the icon display.\n document.querySelector('.icon-accessmap').classList.remove(...['fa-eye-slash']);\n document.querySelector('.icon-accessmap').classList.add(...['fa-eye']);\n\n return {\n sectionData,\n moduleData,\n };\n })\n .catch(displayError);\n};\n\n\n/**\n * Hides or removes the templates from the HTML of the current page.\n *\n * @param {Boolean} updatePreference\n */\nconst hideAccessMap = (updatePreference = false) => {\n // Removes the added elements.\n document.querySelectorAll('.block_accessreview_view').forEach(node => node.remove());\n\n const classList = [\n 'block_accessreview',\n 'block_accessreview_success',\n 'block_accessreview_warning',\n 'block_accessreview_danger',\n 'block_accessreview_view',\n 'alert',\n ];\n\n // Removes the added classes.\n document.querySelectorAll('.block_accessreview').forEach(node => node.classList.remove(...classList));\n\n if (updatePreference) {\n setToggleStatePreference(false);\n }\n\n // Change the icon display.\n document.querySelector('.icon-accessmap').classList.remove(...['fa-eye']);\n document.querySelector('.icon-accessmap').classList.add(...['fa-eye-slash']);\n};\n\n\n/**\n * Toggles the heatmap on/off.\n *\n * @param {Number} courseId\n * @param {String} displayFormat\n */\nconst toggleAccessMap = (courseId, displayFormat) => {\n toggleState = !toggleState;\n if (!toggleState) {\n hideAccessMap(true);\n } else {\n showAccessMap(courseId, displayFormat, true);\n }\n};\n\n/**\n * Parses information on the errors, generating the min, max and totals.\n *\n * @param {Object[]} sectionData The error data for course sections.\n * @param {Object[]} moduleData The error data for course modules.\n * @returns {Object} An object representing the extra error information.\n */\nconst getErrorTotals = (sectionData, moduleData) => {\n const totals = {\n totalErrors: 0,\n totalUsers: 0,\n minViews: 0,\n maxViews: 0,\n viewDelta: 0,\n };\n\n [].concat(sectionData, moduleData).forEach(item => {\n totals.totalErrors += item.numerrors;\n if (item.numerrors < totals.minViews) {\n totals.minViews = item.numerrors;\n }\n\n if (item.numerrors > totals.maxViews) {\n totals.maxViews = item.numerrors;\n }\n totals.totalUsers += item.numchecks;\n });\n\n totals.viewDelta = totals.maxViews - totals.minViews + 1;\n\n return totals;\n};\n\nconst registerEventListeners = (courseId, displayFormat) => {\n document.addEventListener('click', e => {\n if (e.target.closest('#toggle-accessmap')) {\n e.preventDefault();\n toggleAccessMap(courseId, displayFormat);\n }\n });\n};\n\n/**\n * Set the user preference for the toggle value.\n *\n * @param {Boolean} toggleState\n * @returns {Promise}\n */\nconst getTogglePreferenceParams = toggleState => {\n return {\n methodname: 'core_user_update_user_preferences',\n args: {\n preferences: [{\n type: 'block_accessreviewtogglestate',\n value: toggleState,\n }],\n }\n };\n};\n\nconst setToggleStatePreference = toggleState => fetchMany([getTogglePreferenceParams(toggleState)]);\n\n/**\n * Fetch the review data.\n *\n * @param {Number} courseid\n * @param {Boolean} updatePreference\n * @returns {Promise[]}\n */\nconst fetchReviewData = (courseid, updatePreference = false) => {\n const calls = [\n {\n methodname: 'block_accessreview_get_section_data',\n args: {courseid}\n },\n {\n methodname: 'block_accessreview_get_module_data',\n args: {courseid}\n },\n ];\n\n if (updatePreference) {\n calls.push(getTogglePreferenceParams(true));\n }\n\n return fetchMany(calls);\n};\n\n/**\n * Setting up the access review module.\n * @param {number} toggled A number represnting the state of the review toggle.\n * @param {string} displayFormat A string representing the display format for icons.\n * @param {number} courseId The course ID.\n */\nexport const init = (toggled, displayFormat, courseId) => {\n // Settings consts.\n toggleState = toggled == 1;\n\n if (toggleState) {\n showAccessMap(courseId, displayFormat);\n }\n\n registerEventListeners(courseId, displayFormat);\n};\n"],"file":"module.min.js"}
\ No newline at end of file
+{"version":3,"file":"module.min.js","sources":["../src/module.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 .\n\n/**\n * Manager for the accessreview block.\n *\n * @module block_accessreview/module\n * @author Max Larkin \n * @copyright 2020 Brickfield Education Labs \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {call as fetchMany} from 'core/ajax';\nimport * as Templates from 'core/templates';\nimport {exception as displayError} from 'core/notification';\n\n/**\n * The number of colours used to represent the heatmap. (Indexed on 0.)\n * @type {number}\n */\nconst numColours = 2;\n\n/**\n * The toggle state of the heatmap.\n * @type {boolean}\n */\nlet toggleState = true;\n\n/**\n * Renders the HTML template onto a particular HTML element.\n * @param {HTMLElement} element The element to attach the HTML to.\n * @param {number} errorCount The number of errors on this module/section.\n * @param {number} checkCount The number of checks triggered on this module/section.\n * @param {String} displayFormat\n * @param {Number} minViews\n * @param {Number} viewDelta\n * @returns {Promise}\n */\nconst renderTemplate = (element, errorCount, checkCount, displayFormat, minViews, viewDelta) => {\n // Calculate a weight?\n const weight = parseInt((errorCount - minViews) / viewDelta * numColours);\n\n const context = {\n resultPassed: !errorCount,\n classList: '',\n passRate: {\n errorCount,\n checkCount,\n failureRate: Math.round(errorCount / checkCount * 100),\n },\n };\n\n if (!element) {\n return Promise.resolve();\n }\n\n const elementClassList = ['block_accessreview'];\n if (context.resultPassed) {\n elementClassList.push('block_accessreview_success');\n } else if (weight) {\n elementClassList.push('block_accessreview_danger');\n } else {\n elementClassList.push('block_accessreview_warning');\n }\n\n const showIcons = (displayFormat == 'showicons') || (displayFormat == 'showboth');\n const showBackground = (displayFormat == 'showbackground') || (displayFormat == 'showboth');\n\n if (showBackground && !showIcons) {\n // Only the background is displayed.\n // No need to display the template.\n // Note: The case where both the background and icons are shown is handled later to avoid jankiness.\n element.classList.add(...elementClassList, 'alert');\n\n return Promise.resolve();\n }\n\n if (showIcons && !showBackground) {\n context.classList = elementClassList.join(' ');\n }\n\n // The icons are displayed either with, or without, the background.\n return Templates.renderForPromise('block_accessreview/status', context)\n .then(({html, js}) => {\n Templates.appendNodeContents(element, html, js);\n\n if (showBackground) {\n element.classList.add(...elementClassList, 'alert');\n }\n\n return;\n })\n .catch();\n};\n\n/**\n * Applies the template to all sections and modules on the course page.\n *\n * @param {Number} courseId\n * @param {String} displayFormat\n * @param {Boolean} updatePreference\n * @returns {Promise}\n */\nconst showAccessMap = (courseId, displayFormat, updatePreference = false) => {\n // Get error data.\n return Promise.all(fetchReviewData(courseId, updatePreference))\n .then(([sectionData, moduleData]) => {\n // Get total data.\n const {minViews, viewDelta} = getErrorTotals(sectionData, moduleData);\n\n sectionData.forEach(section => {\n const element = document.querySelector(`#section-${section.section} .summary`);\n if (!element) {\n return;\n }\n\n renderTemplate(element, section.numerrors, section.numchecks, displayFormat, minViews, viewDelta);\n });\n\n moduleData.forEach(module => {\n const element = document.getElementById(`module-${module.cmid}`);\n if (!element) {\n return;\n }\n\n renderTemplate(element, module.numerrors, module.numchecks, displayFormat, minViews, viewDelta);\n });\n\n // Change the icon display.\n document.querySelector('.icon-accessmap').classList.remove(...['fa-eye-slash']);\n document.querySelector('.icon-accessmap').classList.add(...['fa-eye']);\n\n return {\n sectionData,\n moduleData,\n };\n })\n .catch(displayError);\n};\n\n\n/**\n * Hides or removes the templates from the HTML of the current page.\n *\n * @param {Boolean} updatePreference\n */\nconst hideAccessMap = (updatePreference = false) => {\n // Removes the added elements.\n document.querySelectorAll('.block_accessreview_view').forEach(node => node.remove());\n\n const classList = [\n 'block_accessreview',\n 'block_accessreview_success',\n 'block_accessreview_warning',\n 'block_accessreview_danger',\n 'block_accessreview_view',\n 'alert',\n ];\n\n // Removes the added classes.\n document.querySelectorAll('.block_accessreview').forEach(node => node.classList.remove(...classList));\n\n if (updatePreference) {\n setToggleStatePreference(false);\n }\n\n // Change the icon display.\n document.querySelector('.icon-accessmap').classList.remove(...['fa-eye']);\n document.querySelector('.icon-accessmap').classList.add(...['fa-eye-slash']);\n};\n\n\n/**\n * Toggles the heatmap on/off.\n *\n * @param {Number} courseId\n * @param {String} displayFormat\n */\nconst toggleAccessMap = (courseId, displayFormat) => {\n toggleState = !toggleState;\n if (!toggleState) {\n hideAccessMap(true);\n } else {\n showAccessMap(courseId, displayFormat, true);\n }\n};\n\n/**\n * Parses information on the errors, generating the min, max and totals.\n *\n * @param {Object[]} sectionData The error data for course sections.\n * @param {Object[]} moduleData The error data for course modules.\n * @returns {Object} An object representing the extra error information.\n */\nconst getErrorTotals = (sectionData, moduleData) => {\n const totals = {\n totalErrors: 0,\n totalUsers: 0,\n minViews: 0,\n maxViews: 0,\n viewDelta: 0,\n };\n\n [].concat(sectionData, moduleData).forEach(item => {\n totals.totalErrors += item.numerrors;\n if (item.numerrors < totals.minViews) {\n totals.minViews = item.numerrors;\n }\n\n if (item.numerrors > totals.maxViews) {\n totals.maxViews = item.numerrors;\n }\n totals.totalUsers += item.numchecks;\n });\n\n totals.viewDelta = totals.maxViews - totals.minViews + 1;\n\n return totals;\n};\n\nconst registerEventListeners = (courseId, displayFormat) => {\n document.addEventListener('click', e => {\n if (e.target.closest('#toggle-accessmap')) {\n e.preventDefault();\n toggleAccessMap(courseId, displayFormat);\n }\n });\n};\n\n/**\n * Set the user preference for the toggle value.\n *\n * @param {Boolean} toggleState\n * @returns {Promise}\n */\nconst getTogglePreferenceParams = toggleState => {\n return {\n methodname: 'core_user_update_user_preferences',\n args: {\n preferences: [{\n type: 'block_accessreviewtogglestate',\n value: toggleState,\n }],\n }\n };\n};\n\nconst setToggleStatePreference = toggleState => fetchMany([getTogglePreferenceParams(toggleState)]);\n\n/**\n * Fetch the review data.\n *\n * @param {Number} courseid\n * @param {Boolean} updatePreference\n * @returns {Promise[]}\n */\nconst fetchReviewData = (courseid, updatePreference = false) => {\n const calls = [\n {\n methodname: 'block_accessreview_get_section_data',\n args: {courseid}\n },\n {\n methodname: 'block_accessreview_get_module_data',\n args: {courseid}\n },\n ];\n\n if (updatePreference) {\n calls.push(getTogglePreferenceParams(true));\n }\n\n return fetchMany(calls);\n};\n\n/**\n * Setting up the access review module.\n * @param {number} toggled A number represnting the state of the review toggle.\n * @param {string} displayFormat A string representing the display format for icons.\n * @param {number} courseId The course ID.\n */\nexport const init = (toggled, displayFormat, courseId) => {\n // Settings consts.\n toggleState = toggled == 1;\n\n if (toggleState) {\n showAccessMap(courseId, displayFormat);\n }\n\n registerEventListeners(courseId, displayFormat);\n};\n"],"names":["toggleState","renderTemplate","element","errorCount","checkCount","displayFormat","minViews","viewDelta","weight","parseInt","context","resultPassed","classList","passRate","failureRate","Math","round","Promise","resolve","elementClassList","push","showIcons","showBackground","add","join","Templates","renderForPromise","then","_ref","html","js","appendNodeContents","catch","showAccessMap","courseId","updatePreference","all","fetchReviewData","_ref2","sectionData","moduleData","getErrorTotals","forEach","section","document","querySelector","numerrors","numchecks","module","getElementById","cmid","remove","displayError","toggleAccessMap","querySelectorAll","node","setToggleStatePreference","hideAccessMap","totals","totalErrors","totalUsers","maxViews","concat","item","getTogglePreferenceParams","methodname","args","preferences","type","value","courseid","calls","toggled","addEventListener","e","target","closest","preventDefault","registerEventListeners"],"mappings":"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"}
\ No newline at end of file
diff --git a/blocks/amd/build/events.min.js b/blocks/amd/build/events.min.js
index be506958c34..0a95a08cf4c 100644
--- a/blocks/amd/build/events.min.js
+++ b/blocks/amd/build/events.min.js
@@ -1,2 +1,20 @@
-define ("core_block/events",["exports","core/event_dispatcher"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.notifyBlockContentUpdated=a.eventTypes=void 0;var c={blockContentUpdated:"core_block/contentUpdated"};a.eventTypes=c;a.notifyBlockContentUpdated=function notifyBlockContentUpdated(a){return(0,b.dispatchEvent)(c.blockContentUpdated,{instanceId:a.dataset.instanceId},a)};var d=!1;if(!d){Y.use("event","moodle-core-event",function(a){document.addEventListener(c.blockContentUpdated,function(b){a.Global.fire(M.core.event.BLOCK_CONTENT_UPDATED,{instanceid:b.detail.instanceId})})});d=!0}});
-//# sourceMappingURL=events.min.js.map
+define("core_block/events",["exports","core/event_dispatcher"],(function(_exports,_event_dispatcher){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.notifyBlockContentUpdated=_exports.eventTypes=void 0;
+/**
+ * Javascript events for the `core_block` subsystem.
+ *
+ * @module core_block/events
+ * @copyright 2021 Andrew Nicols
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since 4.0
+ *
+ * @example
Example of listening to a block event.
+ * import {eventTypes as blockEventTypes} from 'core_block/events';
+ *
+ * document.addEventListener(blockEventTypes.blockContentUpdated, e => {
+ * window.console.log(e.target); // The HTMLElement relating to the block whose content was updated.
+ * window.console.log(e.detail.instanceId); // The instanceId of the block that was updated.
+ * });
+ */
+const eventTypes={blockContentUpdated:"core_block/contentUpdated"};_exports.eventTypes=eventTypes;_exports.notifyBlockContentUpdated=element=>(0,_event_dispatcher.dispatchEvent)(eventTypes.blockContentUpdated,{instanceId:element.dataset.instanceId},element);let legacyEventsRegistered=!1;legacyEventsRegistered||(Y.use("event","moodle-core-event",(Y=>{document.addEventListener(eventTypes.blockContentUpdated,(e=>{Y.Global.fire(M.core.event.BLOCK_CONTENT_UPDATED,{instanceid:e.detail.instanceId})}))})),legacyEventsRegistered=!0)}));
+
+//# sourceMappingURL=events.min.js.map
\ No newline at end of file
diff --git a/blocks/amd/build/events.min.js.map b/blocks/amd/build/events.min.js.map
index b22688d2e09..aa41e06a66b 100644
--- a/blocks/amd/build/events.min.js.map
+++ b/blocks/amd/build/events.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/events.js"],"names":["eventTypes","blockContentUpdated","notifyBlockContentUpdated","element","instanceId","dataset","legacyEventsRegistered","Y","use","document","addEventListener","e","Global","fire","M","core","event","BLOCK_CONTENT_UPDATED","instanceid","detail"],"mappings":"4LAuCO,GAAMA,CAAAA,CAAU,CAAG,CAUtBC,mBAAmB,CAAE,2BAVC,CAAnB,C,2CAqBkC,QAA5BC,CAAAA,yBAA4B,CAAAC,CAAO,QAAI,oBAChDH,CAAU,CAACC,mBADqC,CAEhD,CACIG,UAAU,CAAED,CAAO,CAACE,OAAR,CAAgBD,UADhC,CAFgD,CAKhDD,CALgD,CAAJ,C,CAQhD,GAAIG,CAAAA,CAAsB,GAA1B,CACA,GAAI,CAACA,CAAL,CAA6B,CAKzBC,CAAC,CAACC,GAAF,CAAM,OAAN,CAAe,mBAAf,CAAoC,SAAAD,CAAC,CAAI,CAErCE,QAAQ,CAACC,gBAAT,CAA0BV,CAAU,CAACC,mBAArC,CAA0D,SAAAU,CAAC,CAAI,CAE3DJ,CAAC,CAACK,MAAF,CAASC,IAAT,CAAcC,CAAC,CAACC,IAAF,CAAOC,KAAP,CAAaC,qBAA3B,CAAkD,CAACC,UAAU,CAAEP,CAAC,CAACQ,MAAF,CAASf,UAAtB,CAAlD,CACH,CAHD,CAIH,CAND,EAQAE,CAAsB,GACzB,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/ //\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 * Javascript events for the `core_block` subsystem.\n *\n * @module core_block/events\n * @copyright 2021 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n *\n * @example
Example of listening to a block event.
\n * import {eventTypes as blockEventTypes} from 'core_block/events';\n *\n * document.addEventListener(blockEventTypes.blockContentUpdated, e => {\n * window.console.log(e.target); // The HTMLElement relating to the block whose content was updated.\n * window.console.log(e.detail.instanceId); // The instanceId of the block that was updated.\n * });\n */\n\nimport {dispatchEvent} from 'core/event_dispatcher';\n\n/**\n * Events for `core_block`.\n *\n * @constant\n * @property {String} blockContentUpdated See {@link event:blockContentUpdated}\n */\nexport const eventTypes = {\n /**\n * An event triggered when the content of a block has changed.\n *\n * @event blockContentUpdated\n * @type {CustomEvent}\n * @property {HTMLElement} target The block element that was updated\n * @property {object} detail\n * @property {number} detail.instanceId The block instance id\n */\n blockContentUpdated: 'core_block/contentUpdated',\n};\n\n/**\n * Trigger an event to indicate that the content of a block was updated.\n *\n * @method notifyBlockContentUpdated\n * @param {HTMLElement} element The HTMLElement containing the updated block.\n * @returns {CustomEvent}\n * @fires blockContentUpdated\n */\nexport const notifyBlockContentUpdated = element => dispatchEvent(\n eventTypes.blockContentUpdated,\n {\n instanceId: element.dataset.instanceId,\n },\n element\n);\n\nlet legacyEventsRegistered = false;\nif (!legacyEventsRegistered) {\n // The following event triggers are legacy and will be removed in the future.\n // The following approach provides a backwards-compatability layer for the new events.\n // Code should be updated to make use of native events.\n\n Y.use('event', 'moodle-core-event', Y => {\n // Provide a backwards-compatability layer for YUI Events.\n document.addEventListener(eventTypes.blockContentUpdated, e => {\n // Trigger the legacy YUI event.\n Y.Global.fire(M.core.event.BLOCK_CONTENT_UPDATED, {instanceid: e.detail.instanceId});\n });\n });\n\n legacyEventsRegistered = true;\n}\n"],"file":"events.min.js"}
\ No newline at end of file
+{"version":3,"file":"events.min.js","sources":["../src/events.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/ //\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 * Javascript events for the `core_block` subsystem.\n *\n * @module core_block/events\n * @copyright 2021 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n *\n * @example
Example of listening to a block event.
\n * import {eventTypes as blockEventTypes} from 'core_block/events';\n *\n * document.addEventListener(blockEventTypes.blockContentUpdated, e => {\n * window.console.log(e.target); // The HTMLElement relating to the block whose content was updated.\n * window.console.log(e.detail.instanceId); // The instanceId of the block that was updated.\n * });\n */\n\nimport {dispatchEvent} from 'core/event_dispatcher';\n\n/**\n * Events for `core_block`.\n *\n * @constant\n * @property {String} blockContentUpdated See {@link event:blockContentUpdated}\n */\nexport const eventTypes = {\n /**\n * An event triggered when the content of a block has changed.\n *\n * @event blockContentUpdated\n * @type {CustomEvent}\n * @property {HTMLElement} target The block element that was updated\n * @property {object} detail\n * @property {number} detail.instanceId The block instance id\n */\n blockContentUpdated: 'core_block/contentUpdated',\n};\n\n/**\n * Trigger an event to indicate that the content of a block was updated.\n *\n * @method notifyBlockContentUpdated\n * @param {HTMLElement} element The HTMLElement containing the updated block.\n * @returns {CustomEvent}\n * @fires blockContentUpdated\n */\nexport const notifyBlockContentUpdated = element => dispatchEvent(\n eventTypes.blockContentUpdated,\n {\n instanceId: element.dataset.instanceId,\n },\n element\n);\n\nlet legacyEventsRegistered = false;\nif (!legacyEventsRegistered) {\n // The following event triggers are legacy and will be removed in the future.\n // The following approach provides a backwards-compatability layer for the new events.\n // Code should be updated to make use of native events.\n\n Y.use('event', 'moodle-core-event', Y => {\n // Provide a backwards-compatability layer for YUI Events.\n document.addEventListener(eventTypes.blockContentUpdated, e => {\n // Trigger the legacy YUI event.\n Y.Global.fire(M.core.event.BLOCK_CONTENT_UPDATED, {instanceid: e.detail.instanceId});\n });\n });\n\n legacyEventsRegistered = true;\n}\n"],"names":["eventTypes","blockContentUpdated","element","instanceId","dataset","legacyEventsRegistered","Y","use","document","addEventListener","e","Global","fire","M","core","event","BLOCK_CONTENT_UPDATED","instanceid","detail"],"mappings":";;;;;;;;;;;;;;;;;MAuCaA,WAAa,CAUtBC,oBAAqB,+FAWgBC,UAAW,mCAChDF,WAAWC,oBACX,CACIE,WAAYD,QAAQE,QAAQD,YAEhCD,aAGAG,wBAAyB,EACxBA,yBAKDC,EAAEC,IAAI,QAAS,qBAAqBD,IAEhCE,SAASC,iBAAiBT,WAAWC,qBAAqBS,IAEtDJ,EAAEK,OAAOC,KAAKC,EAAEC,KAAKC,MAAMC,sBAAuB,CAACC,WAAYP,EAAEQ,OAAOf,mBAIhFE,wBAAyB"}
\ No newline at end of file
diff --git a/blocks/myoverview/amd/build/main.min.js b/blocks/myoverview/amd/build/main.min.js
index d2dc519ab9c..db4e98dba06 100644
--- a/blocks/myoverview/amd/build/main.min.js
+++ b/blocks/myoverview/amd/build/main.min.js
@@ -1,2 +1,9 @@
-function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("block_myoverview/main",["exports","block_myoverview/view","block_myoverview/view_nav"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=e(b);c=e(c);function d(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;d=function(){return a};return a}function e(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=d();if(b&&b.has(a)){return b.get(a)}var c={},e=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var f in a){if(Object.prototype.hasOwnProperty.call(a,f)){var g=e?Object.getOwnPropertyDescriptor(a,f):null;if(g&&(g.get||g.set)){Object.defineProperty(c,f,g)}else{c[f]=a[f]}}}c.default=a;if(b){b.set(a,c)}return c}var f=function(a){c.init(a);b.init(a)};a.init=f});
-//# sourceMappingURL=main.min.js.map
+define("block_myoverview/main",["exports","block_myoverview/view","block_myoverview/view_nav"],(function(_exports,View,ViewNav){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}
+/**
+ * Javascript to initialise the myoverview block.
+ *
+ * @copyright 2018 Bas Brands
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,View=_interopRequireWildcard(View),ViewNav=_interopRequireWildcard(ViewNav);_exports.init=root=>{ViewNav.init(root),View.init(root)}}));
+
+//# sourceMappingURL=main.min.js.map
\ No newline at end of file
diff --git a/blocks/myoverview/amd/build/main.min.js.map b/blocks/myoverview/amd/build/main.min.js.map
index ca97636f1c7..774fae61211 100644
--- a/blocks/myoverview/amd/build/main.min.js.map
+++ b/blocks/myoverview/amd/build/main.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/main.js"],"names":["init","root","ViewNav","View"],"mappings":"+dAsBA,OACA,O,siBAOO,GAAMA,CAAAA,CAAI,CAAG,SAACC,CAAD,CAAU,CAE1BC,CAAO,CAACF,IAAR,CAAaC,CAAb,EAEAE,CAAI,CAACH,IAAL,CAAUC,CAAV,CACH,CALM,C","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 .\n\n/**\n * Javascript to initialise the myoverview block.\n *\n * @copyright 2018 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as View from 'block_myoverview/view';\nimport * as ViewNav from 'block_myoverview/view_nav';\n\n/**\n * Initialise all of the modules for the overview block.\n *\n * @param {object} root The root element for the overview block.\n */\nexport const init = (root) => {\n // Initialise the course navigation elements.\n ViewNav.init(root);\n // Initialise the courses view modules.\n View.init(root);\n};\n"],"file":"main.min.js"}
\ No newline at end of file
+{"version":3,"file":"main.min.js","sources":["../src/main.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 .\n\n/**\n * Javascript to initialise the myoverview block.\n *\n * @copyright 2018 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as View from 'block_myoverview/view';\nimport * as ViewNav from 'block_myoverview/view_nav';\n\n/**\n * Initialise all of the modules for the overview block.\n *\n * @param {object} root The root element for the overview block.\n */\nexport const init = (root) => {\n // Initialise the course navigation elements.\n ViewNav.init(root);\n // Initialise the courses view modules.\n View.init(root);\n};\n"],"names":["root","ViewNav","init","View"],"mappings":";;;;;;4KA8BqBA,OAEjBC,QAAQC,KAAKF,MAEbG,KAAKD,KAAKF"}
\ No newline at end of file
diff --git a/blocks/myoverview/amd/build/repository.min.js b/blocks/myoverview/amd/build/repository.min.js
index ffb91fb5330..04658725f08 100644
--- a/blocks/myoverview/amd/build/repository.min.js
+++ b/blocks/myoverview/amd/build/repository.min.js
@@ -1,2 +1,10 @@
-function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("block_myoverview/repository",["exports","core/ajax","core/notification"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.updateUserPreferences=a.setFavouriteCourses=a.getEnrolledCoursesByTimeline=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);c=e(c);function d(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;d=function(){return a};return a}function e(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=d();if(b&&b.has(a)){return b.get(a)}var c={},e=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var f in a){if(Object.prototype.hasOwnProperty.call(a,f)){var g=e?Object.getOwnPropertyDescriptor(a,f):null;if(g&&(g.get||g.set)){Object.defineProperty(c,f,g)}else{c[f]=a[f]}}}c.default=a;if(b){b.set(a,c)}return c}var f=function(a){return b.default.call([{methodname:"core_course_get_enrolled_courses_by_timeline_classification",args:a}])[0]};a.getEnrolledCoursesByTimeline=f;var g=function(a){return b.default.call([{methodname:"core_course_set_favourite_courses",args:a}])[0]};a.setFavouriteCourses=g;var h=function(a){b.default.call([{methodname:"core_user_update_user_preferences",args:a}])[0].fail(c.exception)};a.updateUserPreferences=h});
-//# sourceMappingURL=repository.min.js.map
+define("block_myoverview/repository",["exports","core/ajax","core/notification"],(function(_exports,_ajax,Notification){var obj;
+/**
+ * A javascript module to retrieve enrolled coruses from the server.
+ *
+ * @module block_myoverview/repository
+ * @copyright 2018 Bas Brands
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */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)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.updateUserPreferences=_exports.setFavouriteCourses=_exports.getEnrolledCoursesByTimeline=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj},Notification=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}(Notification);_exports.getEnrolledCoursesByTimeline=args=>{const request={methodname:"core_course_get_enrolled_courses_by_timeline_classification",args:args};return _ajax.default.call([request])[0]};_exports.setFavouriteCourses=args=>{const request={methodname:"core_course_set_favourite_courses",args:args};return _ajax.default.call([request])[0]};_exports.updateUserPreferences=args=>{const request={methodname:"core_user_update_user_preferences",args:args};_ajax.default.call([request])[0].fail(Notification.exception)}}));
+
+//# sourceMappingURL=repository.min.js.map
\ No newline at end of file
diff --git a/blocks/myoverview/amd/build/repository.min.js.map b/blocks/myoverview/amd/build/repository.min.js.map
index 00f2ff66fb9..06850a439a5 100644
--- a/blocks/myoverview/amd/build/repository.min.js.map
+++ b/blocks/myoverview/amd/build/repository.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/repository.js"],"names":["getEnrolledCoursesByTimeline","args","Ajax","call","methodname","setFavouriteCourses","updateUserPreferences","fail","Notification","exception"],"mappings":"uhBAuBA,uDACA,O,siBAeO,GAAMA,CAAAA,CAA4B,CAAG,SAAAC,CAAI,CAAI,CAMhD,MAAOC,WAAKC,IAAL,CAAU,CALD,CACZC,UAAU,CAAE,6DADA,CAEZH,IAAI,CAAEA,CAFM,CAKC,CAAV,EAAqB,CAArB,CACV,CAPM,C,iCAkBA,GAAMI,CAAAA,CAAmB,CAAG,SAAAJ,CAAI,CAAI,CAMvC,MAAOC,WAAKC,IAAL,CAAU,CALD,CACZC,UAAU,CAAE,mCADA,CAEZH,IAAI,CAAEA,CAFM,CAKC,CAAV,EAAqB,CAArB,CACV,CAPM,C,wBAwBA,GAAMK,CAAAA,CAAqB,CAAG,SAAAL,CAAI,CAAI,CAMzCC,UAAKC,IAAL,CAAU,CALM,CACZC,UAAU,CAAE,mCADA,CAEZH,IAAI,CAAEA,CAFM,CAKN,CAAV,EAAqB,CAArB,EACKM,IADL,CACUC,CAAY,CAACC,SADvB,CAEH,CARM,C","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 .\n\n/**\n * A javascript module to retrieve enrolled coruses from the server.\n *\n * @module block_myoverview/repository\n * @copyright 2018 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\nimport * as Notification from 'core/notification';\n\n/**\n * Retrieve a list of enrolled courses.\n *\n * Valid args are:\n * string classification future, inprogress, past\n * int limit number of records to retreive\n * int Offset offset for pagination\n * int sort sort by lastaccess or name\n *\n * @method getEnrolledCoursesByTimeline\n * @param {object} args The request arguments\n * @return {promise} Resolved with an array of courses\n */\nexport const getEnrolledCoursesByTimeline = args => {\n const request = {\n methodname: 'core_course_get_enrolled_courses_by_timeline_classification',\n args: args\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Set the favourite state on a list of courses.\n *\n * Valid args are:\n * Array courses list of course id numbers.\n *\n * @param {Object} args Arguments send to the webservice.\n * @return {Promise} Resolve with warnings.\n */\nexport const setFavouriteCourses = args => {\n const request = {\n methodname: 'core_course_set_favourite_courses',\n args: args\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Update the user preferences.\n *\n * @param {Object} args Arguments send to the webservice.\n *\n * Sample args:\n * {\n * preferences: [\n * {\n * type: 'block_example_user_sort_preference'\n * value: 'title'\n * }\n * ]\n * }\n */\nexport const updateUserPreferences = args => {\n const request = {\n methodname: 'core_user_update_user_preferences',\n args: args\n };\n\n Ajax.call([request])[0]\n .fail(Notification.exception);\n};\n"],"file":"repository.min.js"}
\ No newline at end of file
+{"version":3,"file":"repository.min.js","sources":["../src/repository.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 .\n\n/**\n * A javascript module to retrieve enrolled coruses from the server.\n *\n * @module block_myoverview/repository\n * @copyright 2018 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\nimport * as Notification from 'core/notification';\n\n/**\n * Retrieve a list of enrolled courses.\n *\n * Valid args are:\n * string classification future, inprogress, past\n * int limit number of records to retreive\n * int Offset offset for pagination\n * int sort sort by lastaccess or name\n *\n * @method getEnrolledCoursesByTimeline\n * @param {object} args The request arguments\n * @return {promise} Resolved with an array of courses\n */\nexport const getEnrolledCoursesByTimeline = args => {\n const request = {\n methodname: 'core_course_get_enrolled_courses_by_timeline_classification',\n args: args\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Set the favourite state on a list of courses.\n *\n * Valid args are:\n * Array courses list of course id numbers.\n *\n * @param {Object} args Arguments send to the webservice.\n * @return {Promise} Resolve with warnings.\n */\nexport const setFavouriteCourses = args => {\n const request = {\n methodname: 'core_course_set_favourite_courses',\n args: args\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Update the user preferences.\n *\n * @param {Object} args Arguments send to the webservice.\n *\n * Sample args:\n * {\n * preferences: [\n * {\n * type: 'block_example_user_sort_preference'\n * value: 'title'\n * }\n * ]\n * }\n */\nexport const updateUserPreferences = args => {\n const request = {\n methodname: 'core_user_update_user_preferences',\n args: args\n };\n\n Ajax.call([request])[0]\n .fail(Notification.exception);\n};\n"],"names":["args","request","methodname","Ajax","call","fail","Notification","exception"],"mappings":";;;;;;;2rCAuC4CA,aAClCC,QAAU,CACZC,WAAY,8DACZF,KAAMA,aAGHG,cAAKC,KAAK,CAACH,UAAU,iCAYGD,aACzBC,QAAU,CACZC,WAAY,oCACZF,KAAMA,aAGHG,cAAKC,KAAK,CAACH,UAAU,mCAkBKD,aAC3BC,QAAU,CACZC,WAAY,oCACZF,KAAMA,oBAGLI,KAAK,CAACH,UAAU,GAChBI,KAAKC,aAAaC"}
\ No newline at end of file
diff --git a/blocks/myoverview/amd/build/selectors.min.js b/blocks/myoverview/amd/build/selectors.min.js
index ed27f2366b1..6a7b37fb890 100644
--- a/blocks/myoverview/amd/build/selectors.min.js
+++ b/blocks/myoverview/amd/build/selectors.min.js
@@ -1,2 +1,3 @@
-define ("block_myoverview/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;a.default={courseView:{region:"[data-region=\"courses-view\"]",regionContent:"[data-region=\"course-view-content\"]"},FILTERS:"[data-region=\"filter\"]",FILTER_OPTION:"[data-filter]",DISPLAY_OPTION:"[data-display-option]",ACTION_HIDE_COURSE:"[data-action=\"hide-course\"]",ACTION_SHOW_COURSE:"[data-action=\"show-course\"]",ACTION_ADD_FAVOURITE:"[data-action=\"add-favourite\"]",ACTION_REMOVE_FAVOURITE:"[data-action=\"remove-favourite\"]",FAVOURITE_ICON:"[data-region=\"favourite-icon\"]",ICON_IS_FAVOURITE:"[data-region=\"is-favourite\"]",ICON_NOT_FAVOURITE:"[data-region=\"not-favourite\"]",region:{selectBlock:"[data-region=\"myoverview\"]",clearIcon:"[data-action=\"clearsearch\"]",searchInput:"[data-action=\"search\"]"}};return a.default});
-//# sourceMappingURL=selectors.min.js.map
+define("block_myoverview/selectors",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;return _exports.default={courseView:{region:'[data-region="courses-view"]',regionContent:'[data-region="course-view-content"]'},FILTERS:'[data-region="filter"]',FILTER_OPTION:"[data-filter]",DISPLAY_OPTION:"[data-display-option]",ACTION_HIDE_COURSE:'[data-action="hide-course"]',ACTION_SHOW_COURSE:'[data-action="show-course"]',ACTION_ADD_FAVOURITE:'[data-action="add-favourite"]',ACTION_REMOVE_FAVOURITE:'[data-action="remove-favourite"]',FAVOURITE_ICON:'[data-region="favourite-icon"]',ICON_IS_FAVOURITE:'[data-region="is-favourite"]',ICON_NOT_FAVOURITE:'[data-region="not-favourite"]',region:{selectBlock:'[data-region="myoverview"]',clearIcon:'[data-action="clearsearch"]',searchInput:'[data-action="search"]'}},_exports.default}));
+
+//# sourceMappingURL=selectors.min.js.map
\ No newline at end of file
diff --git a/blocks/myoverview/amd/build/selectors.min.js.map b/blocks/myoverview/amd/build/selectors.min.js.map
index ae18b2f1a55..70c1d52d33e 100644
--- a/blocks/myoverview/amd/build/selectors.min.js.map
+++ b/blocks/myoverview/amd/build/selectors.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/selectors.js"],"names":["courseView","region","regionContent","FILTERS","FILTER_OPTION","DISPLAY_OPTION","ACTION_HIDE_COURSE","ACTION_SHOW_COURSE","ACTION_ADD_FAVOURITE","ACTION_REMOVE_FAVOURITE","FAVOURITE_ICON","ICON_IS_FAVOURITE","ICON_NOT_FAVOURITE","selectBlock","clearIcon","searchInput"],"mappings":"sJAsBe,CACXA,UAAU,CAAE,CACRC,MAAM,CAAE,gCADA,CAERC,aAAa,CAAE,uCAFP,CADD,CAKXC,OAAO,CAAE,0BALE,CAMXC,aAAa,CAAE,eANJ,CAOXC,cAAc,CAAE,uBAPL,CAQXC,kBAAkB,CAAE,+BART,CASXC,kBAAkB,CAAE,+BATT,CAUXC,oBAAoB,CAAE,iCAVX,CAWXC,uBAAuB,CAAE,oCAXd,CAYXC,cAAc,CAAE,kCAZL,CAaXC,iBAAiB,CAAE,gCAbR,CAcXC,kBAAkB,CAAE,iCAdT,CAeXX,MAAM,CAAE,CACJY,WAAW,CAAE,8BADT,CAEJC,SAAS,CAAE,+BAFP,CAGJC,WAAW,CAAE,0BAHT,CAfG,C","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 .\n\n/**\n * Javascript to initialise the selectors for the myoverview block.\n *\n * @copyright 2018 Peter Dias \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport default {\n courseView: {\n region: '[data-region=\"courses-view\"]',\n regionContent: '[data-region=\"course-view-content\"]'\n },\n FILTERS: '[data-region=\"filter\"]',\n FILTER_OPTION: '[data-filter]',\n DISPLAY_OPTION: '[data-display-option]',\n ACTION_HIDE_COURSE: '[data-action=\"hide-course\"]',\n ACTION_SHOW_COURSE: '[data-action=\"show-course\"]',\n ACTION_ADD_FAVOURITE: '[data-action=\"add-favourite\"]',\n ACTION_REMOVE_FAVOURITE: '[data-action=\"remove-favourite\"]',\n FAVOURITE_ICON: '[data-region=\"favourite-icon\"]',\n ICON_IS_FAVOURITE: '[data-region=\"is-favourite\"]',\n ICON_NOT_FAVOURITE: '[data-region=\"not-favourite\"]',\n region: {\n selectBlock: '[data-region=\"myoverview\"]',\n clearIcon: '[data-action=\"clearsearch\"]',\n searchInput: '[data-action=\"search\"]',\n },\n};\n"],"file":"selectors.min.js"}
\ No newline at end of file
+{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 .\n\n/**\n * Javascript to initialise the selectors for the myoverview block.\n *\n * @copyright 2018 Peter Dias \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport default {\n courseView: {\n region: '[data-region=\"courses-view\"]',\n regionContent: '[data-region=\"course-view-content\"]'\n },\n FILTERS: '[data-region=\"filter\"]',\n FILTER_OPTION: '[data-filter]',\n DISPLAY_OPTION: '[data-display-option]',\n ACTION_HIDE_COURSE: '[data-action=\"hide-course\"]',\n ACTION_SHOW_COURSE: '[data-action=\"show-course\"]',\n ACTION_ADD_FAVOURITE: '[data-action=\"add-favourite\"]',\n ACTION_REMOVE_FAVOURITE: '[data-action=\"remove-favourite\"]',\n FAVOURITE_ICON: '[data-region=\"favourite-icon\"]',\n ICON_IS_FAVOURITE: '[data-region=\"is-favourite\"]',\n ICON_NOT_FAVOURITE: '[data-region=\"not-favourite\"]',\n region: {\n selectBlock: '[data-region=\"myoverview\"]',\n clearIcon: '[data-action=\"clearsearch\"]',\n searchInput: '[data-action=\"search\"]',\n },\n};\n"],"names":["courseView","region","regionContent","FILTERS","FILTER_OPTION","DISPLAY_OPTION","ACTION_HIDE_COURSE","ACTION_SHOW_COURSE","ACTION_ADD_FAVOURITE","ACTION_REMOVE_FAVOURITE","FAVOURITE_ICON","ICON_IS_FAVOURITE","ICON_NOT_FAVOURITE","selectBlock","clearIcon","searchInput"],"mappings":"4KAsBe,CACXA,WAAY,CACRC,OAAQ,+BACRC,cAAe,uCAEnBC,QAAS,yBACTC,cAAe,gBACfC,eAAgB,wBAChBC,mBAAoB,8BACpBC,mBAAoB,8BACpBC,qBAAsB,gCACtBC,wBAAyB,mCACzBC,eAAgB,iCAChBC,kBAAmB,+BACnBC,mBAAoB,gCACpBX,OAAQ,CACJY,YAAa,6BACbC,UAAW,8BACXC,YAAa"}
\ No newline at end of file
diff --git a/blocks/myoverview/amd/build/view.min.js b/blocks/myoverview/amd/build/view.min.js
index 237ab645f22..5063245b7e7 100644
--- a/blocks/myoverview/amd/build/view.min.js
+++ b/blocks/myoverview/amd/build/view.min.js
@@ -1,2 +1,9 @@
-function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("block_myoverview/view",["exports","jquery","block_myoverview/repository","core/paged_content_factory","core/pubsub","core/custom_interaction_events","core/notification","core/templates","core_course/events","block_myoverview/selectors","core/paged_content_events","core/aria","core/utils"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.reset=a.init=a.clearSearch=void 0;b=p(b);c=o(c);d=o(d);e=o(e);f=o(f);g=o(g);h=o(h);i=o(i);j=p(j);k=o(k);l=o(l);function n(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;n=function(){return a};return a}function o(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=n();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function p(a){return a&&a.__esModule?a:{default:a}}function q(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);if(b)d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable});c.push.apply(c,d)}return c}function r(a){for(var b=1,c;ba.length)b=a.length;for(var c=0,d=Array(b);cf){var c=[];if("undefined"!=typeof C[b+1]){c=C[b+1].courses.slice(0,1)}C[b].courses=[].concat(t(C[b].courses.slice(1)),t(c))}});j=[].concat(t(j),t(l))}if(E===f+1&&0===C[f+1].courses.length){var m=a.find("[data-region=\"paged-content-container\"]");d.resetLastPageNumber((0,b.default)(m).attr("id"),f)}C[f].courses=j;D--;var k=M(a,f);aa(a,C[f]).then(function(a,b){return h.replaceNodeContents(k,a,b)}).catch(g.exception);C.forEach(function(b,c){if(c>f){var d=M(a,c);d.remove()}})},$=function(a,b){return c.setFavouriteCourses({courses:[{id:a,favourite:b}]}).then(function(c){if(0===c.warnings.length){C.forEach(function(c){c.courses.forEach(function(d,e){if(d.id===a){c.courses[e].isfavourite=b}})});return!0}else{return!1}}).catch(g.exception)},_=function(a){var b=a.find(j.default.courseView.region).attr("data-nocoursesimg"),c=a.find(j.default.courseView.region).attr("data-newcourseurl");return h.render(z.NOCOURSES,{nocoursesimg:b,newcourseurl:c})},aa=function(a,b){var c=H(a),d="";if("card"===c.display){d=z.COURSES_CARDS}else if("list"===c.display){d=z.COURSES_LIST}else{d=z.COURSES_SUMMARY}if(!b){return _(a)}else{if(!1===Array.isArray(b.courses)){b.courses=Object.values(b.courses)}b.courses=b.courses.map(function(a){a.showcoursecategory="on"===c.displaycategories;return a});if(b.courses.length){return h.render(d,{courses:b.courses})}else{return _(a)}}},ba=function(a){return function(b){return a.find(j.default.courseView.region).attr("data-paging",b)}},ca=function(a,b){var c=b+k.SET_ITEMS_PER_PAGE_LIMIT;e.subscribe(c,ba(a))},da=function(a,b){var c=B.map(function(b){var c=!1;if(b===a){c=!0}return{value:b,active:c}}),d=parseInt(b.find(j.default.courseView.region).attr("data-totalcoursecount"),10);return c.filter(function(a){return a.value
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.reset=_exports.init=_exports.clearSearch=void 0,_jquery=_interopRequireDefault(_jquery),Repository=_interopRequireWildcard(Repository),PagedContentFactory=_interopRequireWildcard(PagedContentFactory),PubSub=_interopRequireWildcard(PubSub),CustomEvents=_interopRequireWildcard(CustomEvents),Notification=_interopRequireWildcard(Notification),Templates=_interopRequireWildcard(Templates),CourseEvents=_interopRequireWildcard(CourseEvents),_selectors=_interopRequireDefault(_selectors),PagedContentEvents=_interopRequireWildcard(PagedContentEvents),Aria=_interopRequireWildcard(Aria);const TEMPLATES_COURSES_CARDS="block_myoverview/view-cards",TEMPLATES_COURSES_LIST="block_myoverview/view-list",TEMPLATES_COURSES_SUMMARY="block_myoverview/view-summary",TEMPLATES_NOCOURSES="core_course/no-courses",GROUPINGS_GROUPING_ALLINCLUDINGHIDDEN="allincludinghidden",NUMCOURSES_PERPAGE=[12,24,48,96,0];let loadedPages=[],courseOffset=0,lastPage=0,lastLimit=0,namespace=null;const getFilterValues=root=>{const courseRegion=root.find(_selectors.default.courseView.region);return{display:courseRegion.attr("data-display"),grouping:courseRegion.attr("data-grouping"),sort:courseRegion.attr("data-sort"),displaycategories:courseRegion.attr("data-displaycategories"),customfieldname:courseRegion.attr("data-customfieldname"),customfieldvalue:courseRegion.attr("data-customfieldvalue")}},DEFAULT_PAGED_CONTENT_CONFIG={ignoreControlWhileLoading:!0,controlPlacementBottom:!0,persistentLimitKey:"block_myoverview_user_paging_preference"},getFavouriteIconContainer=(root,courseId)=>root.find(_selectors.default.FAVOURITE_ICON+'[data-course-id="'+courseId+'"]'),getPagedContentContainer=(root,index)=>root.find('[data-region="paged-content-page"][data-page="'+index+'"]'),getCourseId=root=>root.attr("data-course-id"),getAddFavouriteMenuItem=(root,courseId)=>root.find('[data-action="add-favourite"][data-course-id="'+courseId+'"]'),getRemoveFavouriteMenuItem=(root,courseId)=>root.find('[data-action="remove-favourite"][data-course-id="'+courseId+'"]'),addToFavourites=(root,courseId)=>{const removeAction=getRemoveFavouriteMenuItem(root,courseId),addAction=getAddFavouriteMenuItem(root,courseId);setCourseFavouriteState(courseId,!0).then((success=>{success?(PubSub.publish(CourseEvents.favorited,courseId),removeAction.removeClass("hidden"),addAction.addClass("hidden"),((root,courseId)=>{const iconContainer=getFavouriteIconContainer(root,courseId),isFavouriteIcon=iconContainer.find(_selectors.default.ICON_IS_FAVOURITE);isFavouriteIcon.removeClass("hidden"),Aria.unhide(isFavouriteIcon);const notFavourteIcon=iconContainer.find(_selectors.default.ICON_NOT_FAVOURITE);notFavourteIcon.addClass("hidden"),Aria.hide(notFavourteIcon)})(root,courseId)):Notification.alert("Starring course failed","Could not change favourite state")})).catch(Notification.exception)},removeFromFavourites=(root,courseId)=>{const removeAction=getRemoveFavouriteMenuItem(root,courseId),addAction=getAddFavouriteMenuItem(root,courseId);setCourseFavouriteState(courseId,!1).then((success=>{success?(PubSub.publish(CourseEvents.unfavorited,courseId),removeAction.addClass("hidden"),addAction.removeClass("hidden"),((root,courseId)=>{const iconContainer=getFavouriteIconContainer(root,courseId),isFavouriteIcon=iconContainer.find(_selectors.default.ICON_IS_FAVOURITE);isFavouriteIcon.addClass("hidden"),Aria.hide(isFavouriteIcon);const notFavourteIcon=iconContainer.find(_selectors.default.ICON_NOT_FAVOURITE);notFavourteIcon.removeClass("hidden"),Aria.unhide(notFavourteIcon)})(root,courseId)):Notification.alert("Starring course failed","Could not change favourite state")})).catch(Notification.exception)},getHideCourseMenuItem=(root,courseId)=>root.find('[data-action="hide-course"][data-course-id="'+courseId+'"]'),getShowCourseMenuItem=(root,courseId)=>root.find('[data-action="show-course"][data-course-id="'+courseId+'"]'),setCourseHiddenState=(courseId,status)=>(!1===status&&(status=null),Repository.updateUserPreferences({preferences:[{type:"block_myoverview_hidden_course_"+courseId,value:status}]})),hideElement=(root,id)=>{const pagingBar=root.find('[data-region="paging-bar"]'),jumpto=parseInt(pagingBar.attr("data-active-page-number"));let reducedCourse=loadedPages[jumpto].courses.reduce(((accumulator,current)=>(+id!=+current.id&&accumulator.push(current),accumulator)),[]);if(void 0!==loadedPages[jumpto+1]){const newElement=loadedPages[jumpto+1].courses.slice(0,1);loadedPages.forEach(((courseList,index)=>{if(index>jumpto){let popElement=[];void 0!==loadedPages[index+1]&&(popElement=loadedPages[index+1].courses.slice(0,1)),loadedPages[index].courses=[...loadedPages[index].courses.slice(1),...popElement]}})),reducedCourse=[...reducedCourse,...newElement]}if(lastPage===jumpto+1&&0===loadedPages[jumpto+1].courses.length){const pagedContentContainer=root.find('[data-region="paged-content-container"]');PagedContentFactory.resetLastPageNumber((0,_jquery.default)(pagedContentContainer).attr("id"),jumpto)}loadedPages[jumpto].courses=reducedCourse,courseOffset--;const pagedContentPage=getPagedContentContainer(root,jumpto);renderCourses(root,loadedPages[jumpto]).then(((html,js)=>Templates.replaceNodeContents(pagedContentPage,html,js))).catch(Notification.exception),loadedPages.forEach(((courseList,index)=>{if(index>jumpto){getPagedContentContainer(root,index).remove()}}))},setCourseFavouriteState=(courseId,status)=>Repository.setFavouriteCourses({courses:[{id:courseId,favourite:status}]}).then((result=>0===result.warnings.length&&(loadedPages.forEach((courseList=>{courseList.courses.forEach(((course,index)=>{course.id===courseId&&(courseList.courses[index].isfavourite=status)}))})),!0))).catch(Notification.exception),noCoursesRender=root=>{const nocoursesimg=root.find(_selectors.default.courseView.region).attr("data-nocoursesimg"),newcourseurl=root.find(_selectors.default.courseView.region).attr("data-newcourseurl");return Templates.render(TEMPLATES_NOCOURSES,{nocoursesimg:nocoursesimg,newcourseurl:newcourseurl})},renderCourses=(root,coursesData)=>{const filters=getFilterValues(root);let currentTemplate="";return currentTemplate="card"===filters.display?TEMPLATES_COURSES_CARDS:"list"===filters.display?TEMPLATES_COURSES_LIST:TEMPLATES_COURSES_SUMMARY,coursesData?(!1===Array.isArray(coursesData.courses)&&(coursesData.courses=Object.values(coursesData.courses)),coursesData.courses=coursesData.courses.map((course=>(course.showcoursecategory="on"===filters.displaycategories,course))),coursesData.courses.length?Templates.render(currentTemplate,{courses:coursesData.courses}):noCoursesRender(root)):noCoursesRender(root)},registerPagedEventHandlers=(root,namespace)=>{const event=namespace+PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT;PubSub.subscribe(event,(root=>limit=>root.find(_selectors.default.courseView.region).attr("data-paging",limit))(root))},itemsPerPageFunc=(pagingLimit,root)=>{let itemsPerPage=NUMCOURSES_PERPAGE.map((value=>{let active=!1;return value===pagingLimit&&(active=!0),{value:value,active:active}}));const totalCourseCount=parseInt(root.find(_selectors.default.courseView.region).attr("data-totalcoursecount"),10);return itemsPerPage.filter((pagingOption=>pagingOption.value4&&void 0!==arguments[4]?arguments[4]:null,courses=coursesData.courses?coursesData.courses:coursesData,nextPageStart=0,pageCourses=[];if(void 0!==loadedPages[currentPage]){pageCourses=loadedPages[currentPage].courses;const currentPageLength=pageCourses.length;currentPageLength0?courses.slice(0,pageData.limit):courses;loadedPages[currentPage]={courses:pageCourses};const remainingCourses=!1!==nextPageStart?courses.slice(nextPageStart,courses.length):[];remainingCourses.length&&(loadedPages[currentPage+1]={courses:remainingCourses}),loadedPages[currentPage].courses.length{courseOffset=0,loadedPages=[],lastPage=0,lastLimit=0},standardFunctionalityCurry=()=>(resetGlobals(),(filters,currentPage,pageData,actions,root,promises,limit)=>{const pagePromise=((filters,limit)=>Repository.getEnrolledCoursesByTimeline({offset:courseOffset,limit:limit,classification:filters.grouping,sort:filters.sort,customfieldname:filters.customfieldname,customfieldvalue:filters.customfieldvalue}))(filters,limit).then((coursesData=>(pageBuilder(coursesData,currentPage,pageData,actions),renderCourses(root,loadedPages[currentPage])))).catch(Notification.exception);promises.push(pagePromise)}),searchFunctionalityCurry=()=>(resetGlobals(),(filters,currentPage,pageData,actions,root,promises,limit,inputValue)=>{const searchingPromise=((filters,limit,searchValue)=>Repository.getEnrolledCoursesByTimeline({offset:courseOffset,limit:limit,classification:"search",sort:filters.sort,customfieldname:filters.customfieldname,customfieldvalue:filters.customfieldvalue,searchvalue:searchValue}))(filters,limit,inputValue).then((coursesData=>(pageBuilder(coursesData,currentPage,pageData,actions),renderCourses(root,loadedPages[currentPage])))).catch(Notification.exception);promises.push(searchingPromise)}),initializePagedContent=function(root,promiseFunction){let inputValue=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;const pagingLimit=parseInt(root.find(_selectors.default.courseView.region).attr("data-paging"),10);let itemsPerPage=itemsPerPageFunc(pagingLimit,root);const filters=getFilterValues(root),config={...DEFAULT_PAGED_CONTENT_CONFIG};config.eventNamespace=namespace;const pagedContentPromise=PagedContentFactory.createWithLimit(itemsPerPage,((pagesData,actions)=>{let promises=[];return pagesData.forEach((pageData=>{const currentPage=pageData.pageNumber;let limit=pageData.limit>0?pageData.limit:0;if(+lastLimit!=+limit&&(loadedPages=[],courseOffset=0,lastPage=0),lastPage===currentPage)return actions.allItemsLoaded(lastPage),void promises.push(renderCourses(root,loadedPages[currentPage]));lastLimit=limit,void 0===loadedPages[currentPage+1]&&void 0===loadedPages[currentPage]&&(limit*=2),promiseFunction(filters,currentPage,pageData,actions,root,promises,limit,inputValue)})),promises}),config);pagedContentPromise.then(((html,js)=>(registerPagedEventHandlers(root,namespace),Templates.replaceNodeContents(root.find(_selectors.default.courseView.region),html,js)))).catch(Notification.exception)},registerEventListeners=(root,page)=>{CustomEvents.define(root,[CustomEvents.events.activate]),root.on(CustomEvents.events.activate,_selectors.default.ACTION_ADD_FAVOURITE,((e,data)=>{const favourite=(0,_jquery.default)(e.target).closest(_selectors.default.ACTION_ADD_FAVOURITE),courseId=getCourseId(favourite);addToFavourites(root,courseId),data.originalEvent.preventDefault()})),root.on(CustomEvents.events.activate,_selectors.default.ACTION_REMOVE_FAVOURITE,((e,data)=>{const favourite=(0,_jquery.default)(e.target).closest(_selectors.default.ACTION_REMOVE_FAVOURITE),courseId=getCourseId(favourite);removeFromFavourites(root,courseId),data.originalEvent.preventDefault()})),root.on(CustomEvents.events.activate,_selectors.default.FAVOURITE_ICON,((e,data)=>{data.originalEvent.preventDefault()})),root.on(CustomEvents.events.activate,_selectors.default.ACTION_HIDE_COURSE,((e,data)=>{const target=(0,_jquery.default)(e.target).closest(_selectors.default.ACTION_HIDE_COURSE),courseId=getCourseId(target);((root,courseId)=>{const hideAction=getHideCourseMenuItem(root,courseId),showAction=getShowCourseMenuItem(root,courseId),filters=getFilterValues(root);setCourseHiddenState(courseId,!0),filters.grouping!==GROUPINGS_GROUPING_ALLINCLUDINGHIDDEN&&hideElement(root,courseId),hideAction.addClass("hidden"),showAction.removeClass("hidden")})(root,courseId),data.originalEvent.preventDefault()})),root.on(CustomEvents.events.activate,_selectors.default.ACTION_SHOW_COURSE,((e,data)=>{const target=(0,_jquery.default)(e.target).closest(_selectors.default.ACTION_SHOW_COURSE),courseId=getCourseId(target);((root,courseId)=>{const hideAction=getHideCourseMenuItem(root,courseId),showAction=getShowCourseMenuItem(root,courseId),filters=getFilterValues(root);setCourseHiddenState(courseId,null),filters.grouping!==GROUPINGS_GROUPING_ALLINCLUDINGHIDDEN&&hideElement(root,courseId),hideAction.removeClass("hidden"),showAction.addClass("hidden")})(root,courseId),data.originalEvent.preventDefault()}));const input=page.querySelector(_selectors.default.region.searchInput),clearIcon=page.querySelector(_selectors.default.region.clearIcon);clearIcon.addEventListener("click",(()=>{input.value="",input.focus(),clearSearch(clearIcon,root)})),input.addEventListener("input",(0,_utils.debounce)((()=>{""===input.value?clearSearch(clearIcon,root):(activeSearch(clearIcon),initializePagedContent(root,searchFunctionalityCurry(),input.value.trim()))}),300))},clearSearch=(clearIcon,root)=>{clearIcon.classList.add("d-none"),init(root)};_exports.clearSearch=clearSearch;const activeSearch=clearIcon=>{clearIcon.classList.remove("d-none")},init=root=>{if(root=(0,_jquery.default)(root),loadedPages=[],lastPage=0,courseOffset=0,!root.attr("data-init")){const page=document.querySelector(_selectors.default.region.selectBlock);registerEventListeners(root,page),namespace="block_myoverview_"+root.attr("id")+"_"+Math.random(),root.attr("data-init",!0)}initializePagedContent(root,standardFunctionalityCurry())};_exports.init=init;_exports.reset=root=>{loadedPages.length>0?loadedPages.forEach(((courseList,index)=>{let pagedContentPage=getPagedContentContainer(root,index);renderCourses(root,courseList).then(((html,js)=>Templates.replaceNodeContents(pagedContentPage,html,js))).catch(Notification.exception)})):init(root)}}));
+
+//# sourceMappingURL=view.min.js.map
\ No newline at end of file
diff --git a/blocks/myoverview/amd/build/view.min.js.map b/blocks/myoverview/amd/build/view.min.js.map
index 8ede46bdd70..881ebdf0733 100644
--- a/blocks/myoverview/amd/build/view.min.js.map
+++ b/blocks/myoverview/amd/build/view.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/view.js"],"names":["TEMPLATES","COURSES_CARDS","COURSES_LIST","COURSES_SUMMARY","NOCOURSES","GROUPINGS","GROUPING_ALLINCLUDINGHIDDEN","GROUPING_ALL","GROUPING_INPROGRESS","GROUPING_FUTURE","GROUPING_PAST","GROUPING_FAVOURITES","GROUPING_HIDDEN","NUMCOURSES_PERPAGE","loadedPages","courseOffset","lastPage","lastLimit","namespace","getFilterValues","root","courseRegion","find","SELECTORS","courseView","region","display","attr","grouping","sort","displaycategories","customfieldname","customfieldvalue","DEFAULT_PAGED_CONTENT_CONFIG","ignoreControlWhileLoading","controlPlacementBottom","persistentLimitKey","getMyCourses","filters","limit","Repository","getEnrolledCoursesByTimeline","offset","classification","getSearchMyCourses","searchValue","searchvalue","getFavouriteIconContainer","courseId","FAVOURITE_ICON","getPagedContentContainer","index","getCourseId","hideFavouriteIcon","iconContainer","isFavouriteIcon","ICON_IS_FAVOURITE","addClass","Aria","hide","notFavourteIcon","ICON_NOT_FAVOURITE","removeClass","unhide","showFavouriteIcon","getAddFavouriteMenuItem","getRemoveFavouriteMenuItem","addToFavourites","removeAction","addAction","setCourseFavouriteState","then","success","PubSub","publish","CourseEvents","favorited","Notification","alert","catch","exception","removeFromFavourites","unfavorited","getHideCourseMenuItem","getShowCourseMenuItem","hideCourse","hideAction","showAction","setCourseHiddenState","hideElement","showCourse","status","updateUserPreferences","preferences","type","value","id","pagingBar","jumpto","parseInt","courseList","reducedCourse","courses","reduce","accumulator","current","push","newElement","slice","forEach","popElement","length","pagedContentContainer","PagedContentFactory","resetLastPageNumber","pagedContentPage","renderCourses","html","js","Templates","replaceNodeContents","page","remove","setFavouriteCourses","result","warnings","course","isfavourite","noCoursesRender","nocoursesimg","newcourseurl","render","coursesData","currentTemplate","Array","isArray","Object","values","map","showcoursecategory","setLimit","registerPagedEventHandlers","event","PagedContentEvents","SET_ITEMS_PER_PAGE_LIMIT","subscribe","itemsPerPageFunc","pagingLimit","itemsPerPage","active","totalCourseCount","filter","pagingOption","pageBuilder","currentPage","pageData","actions","activeSearch","nextPageStart","pageCourses","currentPageLength","remainingCourses","allItemsLoaded","nextoffset","resetGlobals","standardFunctionalityCurry","promises","pagePromise","searchFunctionalityCurry","inputValue","searchingPromise","initializePagedContent","promiseFunction","config","eventNamespace","pagedContentPromise","createWithLimit","pagesData","pageNumber","registerEventListeners","CustomEvents","define","events","activate","on","ACTION_ADD_FAVOURITE","e","data","favourite","target","closest","originalEvent","preventDefault","ACTION_REMOVE_FAVOURITE","ACTION_HIDE_COURSE","ACTION_SHOW_COURSE","input","querySelector","searchInput","clearIcon","addEventListener","focus","clearSearch","trim","classList","add","init","document","selectBlock","Math","random","reset"],"mappings":"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","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 .\n\n/**\n * Manage the courses view for the overview block.\n *\n * @copyright 2018 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport * as Repository from 'block_myoverview/repository';\nimport * as PagedContentFactory from 'core/paged_content_factory';\nimport * as PubSub from 'core/pubsub';\nimport * as CustomEvents from 'core/custom_interaction_events';\nimport * as Notification from 'core/notification';\nimport * as Templates from 'core/templates';\nimport * as CourseEvents from 'core_course/events';\nimport SELECTORS from 'block_myoverview/selectors';\nimport * as PagedContentEvents from 'core/paged_content_events';\nimport * as Aria from 'core/aria';\nimport {debounce} from 'core/utils';\n\nconst TEMPLATES = {\n COURSES_CARDS: 'block_myoverview/view-cards',\n COURSES_LIST: 'block_myoverview/view-list',\n COURSES_SUMMARY: 'block_myoverview/view-summary',\n NOCOURSES: 'core_course/no-courses'\n};\n\nconst GROUPINGS = {\n GROUPING_ALLINCLUDINGHIDDEN: 'allincludinghidden',\n GROUPING_ALL: 'all',\n GROUPING_INPROGRESS: 'inprogress',\n GROUPING_FUTURE: 'future',\n GROUPING_PAST: 'past',\n GROUPING_FAVOURITES: 'favourites',\n GROUPING_HIDDEN: 'hidden'\n};\n\nconst NUMCOURSES_PERPAGE = [12, 24, 48, 96, 0];\n\nlet loadedPages = [];\n\nlet courseOffset = 0;\n\nlet lastPage = 0;\n\nlet lastLimit = 0;\n\nlet namespace = null;\n\n/**\n * Get filter values from DOM.\n *\n * @param {object} root The root element for the courses view.\n * @return {filters} Set filters.\n */\nconst getFilterValues = root => {\n const courseRegion = root.find(SELECTORS.courseView.region);\n return {\n display: courseRegion.attr('data-display'),\n grouping: courseRegion.attr('data-grouping'),\n sort: courseRegion.attr('data-sort'),\n displaycategories: courseRegion.attr('data-displaycategories'),\n customfieldname: courseRegion.attr('data-customfieldname'),\n customfieldvalue: courseRegion.attr('data-customfieldvalue'),\n };\n};\n\n// We want the paged content controls below the paged content area.\n// and the controls should be ignored while data is loading.\nconst DEFAULT_PAGED_CONTENT_CONFIG = {\n ignoreControlWhileLoading: true,\n controlPlacementBottom: true,\n persistentLimitKey: 'block_myoverview_user_paging_preference'\n};\n\n/**\n * Get enrolled courses from backend.\n *\n * @param {object} filters The filters for this view.\n * @param {int} limit The number of courses to show.\n * @return {promise} Resolved with an array of courses.\n */\nconst getMyCourses = (filters, limit) => {\n return Repository.getEnrolledCoursesByTimeline({\n offset: courseOffset,\n limit: limit,\n classification: filters.grouping,\n sort: filters.sort,\n customfieldname: filters.customfieldname,\n customfieldvalue: filters.customfieldvalue\n });\n};\n\n/**\n * Search for enrolled courses from backend.\n *\n * @param {object} filters The filters for this view.\n * @param {int} limit The number of courses to show.\n * @param {string} searchValue What does the user want to search within their courses.\n * @return {promise} Resolved with an array of courses.\n */\nconst getSearchMyCourses = (filters, limit, searchValue) => {\n return Repository.getEnrolledCoursesByTimeline({\n offset: courseOffset,\n limit: limit,\n classification: 'search',\n sort: filters.sort,\n customfieldname: filters.customfieldname,\n customfieldvalue: filters.customfieldvalue,\n searchvalue: searchValue\n });\n};\n\n/**\n * Get the container element for the favourite icon.\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id number\n * @return {Object} The favourite icon container\n */\nconst getFavouriteIconContainer = (root, courseId) => {\n return root.find(SELECTORS.FAVOURITE_ICON + '[data-course-id=\"' + courseId + '\"]');\n};\n\n/**\n * Get the paged content container element.\n *\n * @param {Object} root The course overview container\n * @param {Number} index Rendered page index.\n * @return {Object} The rendered paged container.\n */\nconst getPagedContentContainer = (root, index) => {\n return root.find('[data-region=\"paged-content-page\"][data-page=\"' + index + '\"]');\n};\n\n/**\n * Get the course id from a favourite element.\n *\n * @param {Object} root The favourite icon container element.\n * @return {Number} Course id.\n */\nconst getCourseId = root => {\n return root.attr('data-course-id');\n};\n\n/**\n * Hide the favourite icon.\n *\n * @param {Object} root The favourite icon container element.\n * @param {Number} courseId Course id number.\n */\nconst hideFavouriteIcon = (root, courseId) => {\n const iconContainer = getFavouriteIconContainer(root, courseId);\n\n const isFavouriteIcon = iconContainer.find(SELECTORS.ICON_IS_FAVOURITE);\n isFavouriteIcon.addClass('hidden');\n Aria.hide(isFavouriteIcon);\n\n const notFavourteIcon = iconContainer.find(SELECTORS.ICON_NOT_FAVOURITE);\n notFavourteIcon.removeClass('hidden');\n Aria.unhide(notFavourteIcon);\n};\n\n/**\n * Show the favourite icon.\n *\n * @param {Object} root The course overview container.\n * @param {Number} courseId Course id number.\n */\nconst showFavouriteIcon = (root, courseId) => {\n const iconContainer = getFavouriteIconContainer(root, courseId);\n\n const isFavouriteIcon = iconContainer.find(SELECTORS.ICON_IS_FAVOURITE);\n isFavouriteIcon.removeClass('hidden');\n Aria.unhide(isFavouriteIcon);\n\n const notFavourteIcon = iconContainer.find(SELECTORS.ICON_NOT_FAVOURITE);\n notFavourteIcon.addClass('hidden');\n Aria.hide(notFavourteIcon);\n};\n\n/**\n * Get the action menu item\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id.\n * @return {Object} The add to favourite menu item.\n */\nconst getAddFavouriteMenuItem = (root, courseId) => {\n return root.find('[data-action=\"add-favourite\"][data-course-id=\"' + courseId + '\"]');\n};\n\n/**\n * Get the action menu item\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id.\n * @return {Object} The remove from favourites menu item.\n */\nconst getRemoveFavouriteMenuItem = (root, courseId) => {\n return root.find('[data-action=\"remove-favourite\"][data-course-id=\"' + courseId + '\"]');\n};\n\n/**\n * Add course to favourites\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id number\n */\nconst addToFavourites = (root, courseId) => {\n const removeAction = getRemoveFavouriteMenuItem(root, courseId);\n const addAction = getAddFavouriteMenuItem(root, courseId);\n\n setCourseFavouriteState(courseId, true).then(success => {\n if (success) {\n PubSub.publish(CourseEvents.favorited, courseId);\n removeAction.removeClass('hidden');\n addAction.addClass('hidden');\n showFavouriteIcon(root, courseId);\n } else {\n Notification.alert('Starring course failed', 'Could not change favourite state');\n }\n return;\n }).catch(Notification.exception);\n};\n\n/**\n * Remove course from favourites\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id number\n */\nconst removeFromFavourites = (root, courseId) => {\n const removeAction = getRemoveFavouriteMenuItem(root, courseId);\n const addAction = getAddFavouriteMenuItem(root, courseId);\n\n setCourseFavouriteState(courseId, false).then(success => {\n if (success) {\n PubSub.publish(CourseEvents.unfavorited, courseId);\n removeAction.addClass('hidden');\n addAction.removeClass('hidden');\n hideFavouriteIcon(root, courseId);\n } else {\n Notification.alert('Starring course failed', 'Could not change favourite state');\n }\n return;\n }).catch(Notification.exception);\n};\n\n/**\n * Get the action menu item\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id.\n * @return {Object} The hide course menu item.\n */\nconst getHideCourseMenuItem = (root, courseId) => {\n return root.find('[data-action=\"hide-course\"][data-course-id=\"' + courseId + '\"]');\n};\n\n/**\n * Get the action menu item\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id.\n * @return {Object} The show course menu item.\n */\nconst getShowCourseMenuItem = (root, courseId) => {\n return root.find('[data-action=\"show-course\"][data-course-id=\"' + courseId + '\"]');\n};\n\n/**\n * Hide course\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id number\n */\nconst hideCourse = (root, courseId) => {\n const hideAction = getHideCourseMenuItem(root, courseId);\n const showAction = getShowCourseMenuItem(root, courseId);\n const filters = getFilterValues(root);\n\n setCourseHiddenState(courseId, true);\n\n // Remove the course from this view as it is now hidden and thus not covered by this view anymore.\n // Do only if we are not in \"All (including archived)\" view mode where really all courses are shown.\n if (filters.grouping !== GROUPINGS.GROUPING_ALLINCLUDINGHIDDEN) {\n hideElement(root, courseId);\n }\n\n hideAction.addClass('hidden');\n showAction.removeClass('hidden');\n};\n\n/**\n * Show course\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id number\n */\nconst showCourse = (root, courseId) => {\n const hideAction = getHideCourseMenuItem(root, courseId);\n const showAction = getShowCourseMenuItem(root, courseId);\n const filters = getFilterValues(root);\n\n setCourseHiddenState(courseId, null);\n\n // Remove the course from this view as it is now shown again and thus not covered by this view anymore.\n // Do only if we are not in \"All (including archived)\" view mode where really all courses are shown.\n if (filters.grouping !== GROUPINGS.GROUPING_ALLINCLUDINGHIDDEN) {\n hideElement(root, courseId);\n }\n\n hideAction.removeClass('hidden');\n showAction.addClass('hidden');\n};\n\n/**\n * Set the courses hidden status and push to repository\n *\n * @param {Number} courseId Course id to favourite.\n * @param {Boolean} status new hidden status.\n * @return {Promise} Repository promise.\n */\nconst setCourseHiddenState = (courseId, status) => {\n\n // If the given status is not hidden, the preference has to be deleted with a null value.\n if (status === false) {\n status = null;\n }\n return Repository.updateUserPreferences({\n preferences: [\n {\n type: 'block_myoverview_hidden_course_' + courseId,\n value: status\n }\n ]\n });\n};\n\n/**\n * Reset the loadedPages dataset to take into account the hidden element\n *\n * @param {Object} root The course overview container\n * @param {Number} id The course id number\n */\nconst hideElement = (root, id) => {\n const pagingBar = root.find('[data-region=\"paging-bar\"]');\n const jumpto = parseInt(pagingBar.attr('data-active-page-number'));\n\n // Get a reduced dataset for the current page.\n const courseList = loadedPages[jumpto];\n let reducedCourse = courseList.courses.reduce((accumulator, current) => {\n if (+id !== +current.id) {\n accumulator.push(current);\n }\n return accumulator;\n }, []);\n\n // Get the next page's data if loaded and pop the first element from it.\n if (typeof (loadedPages[jumpto + 1]) !== 'undefined') {\n const newElement = loadedPages[jumpto + 1].courses.slice(0, 1);\n\n // Adjust the dataset for the reset of the pages that are loaded.\n loadedPages.forEach((courseList, index) => {\n if (index > jumpto) {\n let popElement = [];\n if (typeof (loadedPages[index + 1]) !== 'undefined') {\n popElement = loadedPages[index + 1].courses.slice(0, 1);\n }\n loadedPages[index].courses = [...loadedPages[index].courses.slice(1), ...popElement];\n }\n });\n\n reducedCourse = [...reducedCourse, ...newElement];\n }\n\n // Check if the next page is the last page and if it still has data associated to it.\n if (lastPage === jumpto + 1 && loadedPages[jumpto + 1].courses.length === 0) {\n const pagedContentContainer = root.find('[data-region=\"paged-content-container\"]');\n PagedContentFactory.resetLastPageNumber($(pagedContentContainer).attr('id'), jumpto);\n }\n\n loadedPages[jumpto].courses = reducedCourse;\n\n // Reduce the course offset.\n courseOffset--;\n\n // Render the paged content for the current.\n const pagedContentPage = getPagedContentContainer(root, jumpto);\n renderCourses(root, loadedPages[jumpto]).then((html, js) => {\n return Templates.replaceNodeContents(pagedContentPage, html, js);\n }).catch(Notification.exception);\n\n // Delete subsequent pages in order to trigger the callback.\n loadedPages.forEach((courseList, index) => {\n if (index > jumpto) {\n const page = getPagedContentContainer(root, index);\n page.remove();\n }\n });\n};\n\n/**\n * Set the courses favourite status and push to repository\n *\n * @param {Number} courseId Course id to favourite.\n * @param {boolean} status new favourite status.\n * @return {Promise} Repository promise.\n */\nconst setCourseFavouriteState = (courseId, status) => {\n\n return Repository.setFavouriteCourses({\n courses: [\n {\n 'id': courseId,\n 'favourite': status\n }\n ]\n }).then(result => {\n if (result.warnings.length === 0) {\n loadedPages.forEach(courseList => {\n courseList.courses.forEach((course, index) => {\n if (course.id === courseId) {\n courseList.courses[index].isfavourite = status;\n }\n });\n });\n return true;\n } else {\n return false;\n }\n }).catch(Notification.exception);\n};\n\n/**\n * Given there are no courses to render provide the rendered template.\n *\n * @param {object} root The root element for the courses view.\n * @return {promise} jQuery promise resolved after rendering is complete.\n */\nconst noCoursesRender = root => {\n const nocoursesimg = root.find(SELECTORS.courseView.region).attr('data-nocoursesimg');\n const newcourseurl = root.find(SELECTORS.courseView.region).attr('data-newcourseurl');\n return Templates.render(TEMPLATES.NOCOURSES, {\n nocoursesimg: nocoursesimg,\n newcourseurl: newcourseurl\n });\n};\n\n/**\n * Render the dashboard courses.\n *\n * @param {object} root The root element for the courses view.\n * @param {array} coursesData containing array of returned courses.\n * @return {promise} jQuery promise resolved after rendering is complete.\n */\nconst renderCourses = (root, coursesData) => {\n\n const filters = getFilterValues(root);\n\n let currentTemplate = '';\n if (filters.display === 'card') {\n currentTemplate = TEMPLATES.COURSES_CARDS;\n } else if (filters.display === 'list') {\n currentTemplate = TEMPLATES.COURSES_LIST;\n } else {\n currentTemplate = TEMPLATES.COURSES_SUMMARY;\n }\n\n if (!coursesData) {\n return noCoursesRender(root);\n } else {\n // Sometimes we get weird objects coming after a failed search, cast to ensure typing functions.\n if (Array.isArray(coursesData.courses) === false) {\n coursesData.courses = Object.values(coursesData.courses);\n }\n // Whether the course category should be displayed in the course item.\n coursesData.courses = coursesData.courses.map(course => {\n course.showcoursecategory = filters.displaycategories === 'on';\n return course;\n });\n if (coursesData.courses.length) {\n return Templates.render(currentTemplate, {\n courses: coursesData.courses,\n });\n } else {\n return noCoursesRender(root);\n }\n }\n};\n\n/**\n * Return the callback to be passed to the subscribe event\n *\n * @param {object} root The root element for the courses view\n * @return {function} Partially applied function that'll execute when passed a limit\n */\nconst setLimit = root => {\n // @param {Number} limit The paged limit that is passed through the event.\n return limit => root.find(SELECTORS.courseView.region).attr('data-paging', limit);\n};\n\n/**\n * Intialise the paged list and cards views on page load.\n * Returns an array of paged contents that we would like to handle here\n *\n * @param {object} root The root element for the courses view\n * @param {string} namespace The namespace for all the events attached\n */\nconst registerPagedEventHandlers = (root, namespace) => {\n const event = namespace + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT;\n PubSub.subscribe(event, setLimit(root));\n};\n\n/**\n * Figure out how many items are going to be allowed to be rendered in the block.\n *\n * @param {Number} pagingLimit How many courses to display\n * @param {Object} root The course overview container\n * @return {Number[]} How many courses will be rendered\n */\nconst itemsPerPageFunc = (pagingLimit, root) => {\n let itemsPerPage = NUMCOURSES_PERPAGE.map(value => {\n let active = false;\n if (value === pagingLimit) {\n active = true;\n }\n\n return {\n value: value,\n active: active\n };\n });\n\n // Filter out all pagination options which are too large for the amount of courses user is enrolled in.\n const totalCourseCount = parseInt(root.find(SELECTORS.courseView.region).attr('data-totalcoursecount'), 10);\n return itemsPerPage.filter(pagingOption => {\n return pagingOption.value < totalCourseCount || pagingOption.value === 0;\n });\n};\n\n/**\n * Mutates and controls the loadedPages array and handles the bootstrapping.\n *\n * @param {Array|Object} coursesData Array of all of the courses to start building the page from\n * @param {Number} currentPage What page are we currently on?\n * @param {Object} pageData Any current page information\n * @param {Object} actions Paged content helper\n * @param {null|boolean} activeSearch Are we currently actively searching and building up search results?\n */\nconst pageBuilder = (coursesData, currentPage, pageData, actions, activeSearch = null) => {\n // If the courseData comes in an object then get the value otherwise it is a pure array.\n let courses = coursesData.courses ? coursesData.courses : coursesData;\n let nextPageStart = 0;\n let pageCourses = [];\n\n // If current page's data is loaded make sure we max it to page limit.\n if (typeof (loadedPages[currentPage]) !== 'undefined') {\n pageCourses = loadedPages[currentPage].courses;\n const currentPageLength = pageCourses.length;\n if (currentPageLength < pageData.limit) {\n nextPageStart = pageData.limit - currentPageLength;\n pageCourses = {...loadedPages[currentPage].courses, ...courses.slice(0, nextPageStart)};\n }\n } else {\n // When the page limit is zero, there is only one page of courses, no start for next page.\n nextPageStart = pageData.limit || false;\n pageCourses = (pageData.limit > 0) ? courses.slice(0, pageData.limit) : courses;\n }\n\n // Finished setting up the current page.\n loadedPages[currentPage] = {\n courses: pageCourses\n };\n\n // Set up the next page (if there is more than one page).\n const remainingCourses = nextPageStart !== false ? courses.slice(nextPageStart, courses.length) : [];\n if (remainingCourses.length) {\n loadedPages[currentPage + 1] = {\n courses: remainingCourses\n };\n }\n\n // Set the last page to either the current or next page.\n if (loadedPages[currentPage].courses.length < pageData.limit || !remainingCourses.length) {\n lastPage = currentPage;\n if (activeSearch === null) {\n actions.allItemsLoaded(currentPage);\n }\n } else if (typeof (loadedPages[currentPage + 1]) !== 'undefined'\n && loadedPages[currentPage + 1].courses.length < pageData.limit) {\n lastPage = currentPage + 1;\n }\n\n courseOffset = coursesData.nextoffset;\n};\n\n/**\n * In cases when switching between regular rendering and search rendering we need to reset some variables.\n */\nconst resetGlobals = () => {\n courseOffset = 0;\n loadedPages = [];\n lastPage = 0;\n lastLimit = 0;\n};\n\n/**\n * The default functionality of fetching paginated courses without special handling.\n *\n * @return {function(Object, Object, Object, Object, Object, Promise, Number): void}\n */\nconst standardFunctionalityCurry = () => {\n resetGlobals();\n return (filters, currentPage, pageData, actions, root, promises, limit) => {\n const pagePromise = getMyCourses(\n filters,\n limit\n ).then(coursesData => {\n pageBuilder(coursesData, currentPage, pageData, actions);\n return renderCourses(root, loadedPages[currentPage]);\n }).catch(Notification.exception);\n\n promises.push(pagePromise);\n };\n};\n\n/**\n * Initialize the searching functionality so we can call it when required.\n *\n * @return {function(Object, Number, Object, Object, Object, Promise, Number, String): void}\n */\nconst searchFunctionalityCurry = () => {\n resetGlobals();\n return (filters, currentPage, pageData, actions, root, promises, limit, inputValue) => {\n const searchingPromise = getSearchMyCourses(\n filters,\n limit,\n inputValue\n ).then(coursesData => {\n pageBuilder(coursesData, currentPage, pageData, actions);\n return renderCourses(root, loadedPages[currentPage]);\n }).catch(Notification.exception);\n\n promises.push(searchingPromise);\n };\n};\n\n/**\n * Initialise the courses list and cards views on page load.\n *\n * @param {object} root The root element for the courses view.\n * @param {function} promiseFunction How do we fetch the courses and what do we do with them?\n * @param {null | string} inputValue What to search for\n */\nconst initializePagedContent = (root, promiseFunction, inputValue = null) => {\n const pagingLimit = parseInt(root.find(SELECTORS.courseView.region).attr('data-paging'), 10);\n let itemsPerPage = itemsPerPageFunc(pagingLimit, root);\n\n const filters = getFilterValues(root);\n const config = {...{}, ...DEFAULT_PAGED_CONTENT_CONFIG};\n config.eventNamespace = namespace;\n\n const pagedContentPromise = PagedContentFactory.createWithLimit(\n itemsPerPage,\n (pagesData, actions) => {\n let promises = [];\n pagesData.forEach(pageData => {\n const currentPage = pageData.pageNumber;\n let limit = (pageData.limit > 0) ? pageData.limit : 0;\n\n // Reset local variables if limits have changed.\n if (+lastLimit !== +limit) {\n loadedPages = [];\n courseOffset = 0;\n lastPage = 0;\n }\n\n if (lastPage === currentPage) {\n // If we are on the last page and have it's data then load it from cache.\n actions.allItemsLoaded(lastPage);\n promises.push(renderCourses(root, loadedPages[currentPage]));\n return;\n }\n\n lastLimit = limit;\n\n // Get 2 pages worth of data as we will need it for the hidden functionality.\n if (typeof (loadedPages[currentPage + 1]) === 'undefined') {\n if (typeof (loadedPages[currentPage]) === 'undefined') {\n limit *= 2;\n }\n }\n\n // Call the curried function that'll handle the course promise and any manipulation of it.\n promiseFunction(filters, currentPage, pageData, actions, root, promises, limit, inputValue);\n });\n return promises;\n },\n config\n );\n\n pagedContentPromise.then((html, js) => {\n registerPagedEventHandlers(root, namespace);\n return Templates.replaceNodeContents(root.find(SELECTORS.courseView.region), html, js);\n }).catch(Notification.exception);\n};\n\n/**\n * Listen to, and handle events for the myoverview block.\n *\n * @param {Object} root The myoverview block container element.\n * @param {HTMLElement} page The whole HTMLElement for our block.\n */\nconst registerEventListeners = (root, page) => {\n\n CustomEvents.define(root, [\n CustomEvents.events.activate\n ]);\n\n root.on(CustomEvents.events.activate, SELECTORS.ACTION_ADD_FAVOURITE, (e, data) => {\n const favourite = $(e.target).closest(SELECTORS.ACTION_ADD_FAVOURITE);\n const courseId = getCourseId(favourite);\n addToFavourites(root, courseId);\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.ACTION_REMOVE_FAVOURITE, (e, data) => {\n const favourite = $(e.target).closest(SELECTORS.ACTION_REMOVE_FAVOURITE);\n const courseId = getCourseId(favourite);\n removeFromFavourites(root, courseId);\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.FAVOURITE_ICON, (e, data) => {\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.ACTION_HIDE_COURSE, (e, data) => {\n const target = $(e.target).closest(SELECTORS.ACTION_HIDE_COURSE);\n const courseId = getCourseId(target);\n hideCourse(root, courseId);\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.ACTION_SHOW_COURSE, (e, data) => {\n const target = $(e.target).closest(SELECTORS.ACTION_SHOW_COURSE);\n const courseId = getCourseId(target);\n showCourse(root, courseId);\n data.originalEvent.preventDefault();\n });\n\n // Searching functionality event handlers.\n const input = page.querySelector(SELECTORS.region.searchInput);\n const clearIcon = page.querySelector(SELECTORS.region.clearIcon);\n\n clearIcon.addEventListener('click', () => {\n input.value = '';\n input.focus();\n clearSearch(clearIcon, root);\n });\n\n input.addEventListener('input', debounce(() => {\n if (input.value === '') {\n clearSearch(clearIcon, root);\n } else {\n activeSearch(clearIcon);\n initializePagedContent(root, searchFunctionalityCurry(), input.value.trim());\n }\n }, 300));\n};\n\n/**\n * Reset the search icon and trigger the init for the block.\n *\n * @param {HTMLElement} clearIcon Our closing icon to manipulate.\n * @param {Object} root The myoverview block container element.\n */\nexport const clearSearch = (clearIcon, root) => {\n clearIcon.classList.add('d-none');\n init(root);\n};\n\n/**\n * Change the searching icon to its' active state.\n *\n * @param {HTMLElement} clearIcon Our closing icon to manipulate.\n */\nconst activeSearch = (clearIcon) => {\n clearIcon.classList.remove('d-none');\n};\n\n/**\n * Intialise the courses list and cards views on page load.\n *\n * @param {object} root The root element for the courses view.\n */\nexport const init = root => {\n root = $(root);\n loadedPages = [];\n lastPage = 0;\n courseOffset = 0;\n\n if (!root.attr('data-init')) {\n const page = document.querySelector(SELECTORS.region.selectBlock);\n registerEventListeners(root, page);\n namespace = \"block_myoverview_\" + root.attr('id') + \"_\" + Math.random();\n root.attr('data-init', true);\n }\n\n initializePagedContent(root, standardFunctionalityCurry());\n};\n\n/**\n * Reset the courses views to their original\n * state on first page load.courseOffset\n *\n * This is called when configuration has changed for the event lists\n * to cause them to reload their data.\n *\n * @param {Object} root The root element for the timeline view.\n */\nexport const reset = root => {\n if (loadedPages.length > 0) {\n loadedPages.forEach((courseList, index) => {\n let pagedContentPage = getPagedContentContainer(root, index);\n renderCourses(root, courseList).then((html, js) => {\n return Templates.replaceNodeContents(pagedContentPage, html, js);\n }).catch(Notification.exception);\n });\n } else {\n init(root);\n }\n};\n"],"file":"view.min.js"}
\ No newline at end of file
+{"version":3,"file":"view.min.js","sources":["../src/view.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 .\n\n/**\n * Manage the courses view for the overview block.\n *\n * @copyright 2018 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport * as Repository from 'block_myoverview/repository';\nimport * as PagedContentFactory from 'core/paged_content_factory';\nimport * as PubSub from 'core/pubsub';\nimport * as CustomEvents from 'core/custom_interaction_events';\nimport * as Notification from 'core/notification';\nimport * as Templates from 'core/templates';\nimport * as CourseEvents from 'core_course/events';\nimport SELECTORS from 'block_myoverview/selectors';\nimport * as PagedContentEvents from 'core/paged_content_events';\nimport * as Aria from 'core/aria';\nimport {debounce} from 'core/utils';\n\nconst TEMPLATES = {\n COURSES_CARDS: 'block_myoverview/view-cards',\n COURSES_LIST: 'block_myoverview/view-list',\n COURSES_SUMMARY: 'block_myoverview/view-summary',\n NOCOURSES: 'core_course/no-courses'\n};\n\nconst GROUPINGS = {\n GROUPING_ALLINCLUDINGHIDDEN: 'allincludinghidden',\n GROUPING_ALL: 'all',\n GROUPING_INPROGRESS: 'inprogress',\n GROUPING_FUTURE: 'future',\n GROUPING_PAST: 'past',\n GROUPING_FAVOURITES: 'favourites',\n GROUPING_HIDDEN: 'hidden'\n};\n\nconst NUMCOURSES_PERPAGE = [12, 24, 48, 96, 0];\n\nlet loadedPages = [];\n\nlet courseOffset = 0;\n\nlet lastPage = 0;\n\nlet lastLimit = 0;\n\nlet namespace = null;\n\n/**\n * Get filter values from DOM.\n *\n * @param {object} root The root element for the courses view.\n * @return {filters} Set filters.\n */\nconst getFilterValues = root => {\n const courseRegion = root.find(SELECTORS.courseView.region);\n return {\n display: courseRegion.attr('data-display'),\n grouping: courseRegion.attr('data-grouping'),\n sort: courseRegion.attr('data-sort'),\n displaycategories: courseRegion.attr('data-displaycategories'),\n customfieldname: courseRegion.attr('data-customfieldname'),\n customfieldvalue: courseRegion.attr('data-customfieldvalue'),\n };\n};\n\n// We want the paged content controls below the paged content area.\n// and the controls should be ignored while data is loading.\nconst DEFAULT_PAGED_CONTENT_CONFIG = {\n ignoreControlWhileLoading: true,\n controlPlacementBottom: true,\n persistentLimitKey: 'block_myoverview_user_paging_preference'\n};\n\n/**\n * Get enrolled courses from backend.\n *\n * @param {object} filters The filters for this view.\n * @param {int} limit The number of courses to show.\n * @return {promise} Resolved with an array of courses.\n */\nconst getMyCourses = (filters, limit) => {\n return Repository.getEnrolledCoursesByTimeline({\n offset: courseOffset,\n limit: limit,\n classification: filters.grouping,\n sort: filters.sort,\n customfieldname: filters.customfieldname,\n customfieldvalue: filters.customfieldvalue\n });\n};\n\n/**\n * Search for enrolled courses from backend.\n *\n * @param {object} filters The filters for this view.\n * @param {int} limit The number of courses to show.\n * @param {string} searchValue What does the user want to search within their courses.\n * @return {promise} Resolved with an array of courses.\n */\nconst getSearchMyCourses = (filters, limit, searchValue) => {\n return Repository.getEnrolledCoursesByTimeline({\n offset: courseOffset,\n limit: limit,\n classification: 'search',\n sort: filters.sort,\n customfieldname: filters.customfieldname,\n customfieldvalue: filters.customfieldvalue,\n searchvalue: searchValue\n });\n};\n\n/**\n * Get the container element for the favourite icon.\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id number\n * @return {Object} The favourite icon container\n */\nconst getFavouriteIconContainer = (root, courseId) => {\n return root.find(SELECTORS.FAVOURITE_ICON + '[data-course-id=\"' + courseId + '\"]');\n};\n\n/**\n * Get the paged content container element.\n *\n * @param {Object} root The course overview container\n * @param {Number} index Rendered page index.\n * @return {Object} The rendered paged container.\n */\nconst getPagedContentContainer = (root, index) => {\n return root.find('[data-region=\"paged-content-page\"][data-page=\"' + index + '\"]');\n};\n\n/**\n * Get the course id from a favourite element.\n *\n * @param {Object} root The favourite icon container element.\n * @return {Number} Course id.\n */\nconst getCourseId = root => {\n return root.attr('data-course-id');\n};\n\n/**\n * Hide the favourite icon.\n *\n * @param {Object} root The favourite icon container element.\n * @param {Number} courseId Course id number.\n */\nconst hideFavouriteIcon = (root, courseId) => {\n const iconContainer = getFavouriteIconContainer(root, courseId);\n\n const isFavouriteIcon = iconContainer.find(SELECTORS.ICON_IS_FAVOURITE);\n isFavouriteIcon.addClass('hidden');\n Aria.hide(isFavouriteIcon);\n\n const notFavourteIcon = iconContainer.find(SELECTORS.ICON_NOT_FAVOURITE);\n notFavourteIcon.removeClass('hidden');\n Aria.unhide(notFavourteIcon);\n};\n\n/**\n * Show the favourite icon.\n *\n * @param {Object} root The course overview container.\n * @param {Number} courseId Course id number.\n */\nconst showFavouriteIcon = (root, courseId) => {\n const iconContainer = getFavouriteIconContainer(root, courseId);\n\n const isFavouriteIcon = iconContainer.find(SELECTORS.ICON_IS_FAVOURITE);\n isFavouriteIcon.removeClass('hidden');\n Aria.unhide(isFavouriteIcon);\n\n const notFavourteIcon = iconContainer.find(SELECTORS.ICON_NOT_FAVOURITE);\n notFavourteIcon.addClass('hidden');\n Aria.hide(notFavourteIcon);\n};\n\n/**\n * Get the action menu item\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id.\n * @return {Object} The add to favourite menu item.\n */\nconst getAddFavouriteMenuItem = (root, courseId) => {\n return root.find('[data-action=\"add-favourite\"][data-course-id=\"' + courseId + '\"]');\n};\n\n/**\n * Get the action menu item\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id.\n * @return {Object} The remove from favourites menu item.\n */\nconst getRemoveFavouriteMenuItem = (root, courseId) => {\n return root.find('[data-action=\"remove-favourite\"][data-course-id=\"' + courseId + '\"]');\n};\n\n/**\n * Add course to favourites\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id number\n */\nconst addToFavourites = (root, courseId) => {\n const removeAction = getRemoveFavouriteMenuItem(root, courseId);\n const addAction = getAddFavouriteMenuItem(root, courseId);\n\n setCourseFavouriteState(courseId, true).then(success => {\n if (success) {\n PubSub.publish(CourseEvents.favorited, courseId);\n removeAction.removeClass('hidden');\n addAction.addClass('hidden');\n showFavouriteIcon(root, courseId);\n } else {\n Notification.alert('Starring course failed', 'Could not change favourite state');\n }\n return;\n }).catch(Notification.exception);\n};\n\n/**\n * Remove course from favourites\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id number\n */\nconst removeFromFavourites = (root, courseId) => {\n const removeAction = getRemoveFavouriteMenuItem(root, courseId);\n const addAction = getAddFavouriteMenuItem(root, courseId);\n\n setCourseFavouriteState(courseId, false).then(success => {\n if (success) {\n PubSub.publish(CourseEvents.unfavorited, courseId);\n removeAction.addClass('hidden');\n addAction.removeClass('hidden');\n hideFavouriteIcon(root, courseId);\n } else {\n Notification.alert('Starring course failed', 'Could not change favourite state');\n }\n return;\n }).catch(Notification.exception);\n};\n\n/**\n * Get the action menu item\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id.\n * @return {Object} The hide course menu item.\n */\nconst getHideCourseMenuItem = (root, courseId) => {\n return root.find('[data-action=\"hide-course\"][data-course-id=\"' + courseId + '\"]');\n};\n\n/**\n * Get the action menu item\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id.\n * @return {Object} The show course menu item.\n */\nconst getShowCourseMenuItem = (root, courseId) => {\n return root.find('[data-action=\"show-course\"][data-course-id=\"' + courseId + '\"]');\n};\n\n/**\n * Hide course\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id number\n */\nconst hideCourse = (root, courseId) => {\n const hideAction = getHideCourseMenuItem(root, courseId);\n const showAction = getShowCourseMenuItem(root, courseId);\n const filters = getFilterValues(root);\n\n setCourseHiddenState(courseId, true);\n\n // Remove the course from this view as it is now hidden and thus not covered by this view anymore.\n // Do only if we are not in \"All (including archived)\" view mode where really all courses are shown.\n if (filters.grouping !== GROUPINGS.GROUPING_ALLINCLUDINGHIDDEN) {\n hideElement(root, courseId);\n }\n\n hideAction.addClass('hidden');\n showAction.removeClass('hidden');\n};\n\n/**\n * Show course\n *\n * @param {Object} root The course overview container\n * @param {Number} courseId Course id number\n */\nconst showCourse = (root, courseId) => {\n const hideAction = getHideCourseMenuItem(root, courseId);\n const showAction = getShowCourseMenuItem(root, courseId);\n const filters = getFilterValues(root);\n\n setCourseHiddenState(courseId, null);\n\n // Remove the course from this view as it is now shown again and thus not covered by this view anymore.\n // Do only if we are not in \"All (including archived)\" view mode where really all courses are shown.\n if (filters.grouping !== GROUPINGS.GROUPING_ALLINCLUDINGHIDDEN) {\n hideElement(root, courseId);\n }\n\n hideAction.removeClass('hidden');\n showAction.addClass('hidden');\n};\n\n/**\n * Set the courses hidden status and push to repository\n *\n * @param {Number} courseId Course id to favourite.\n * @param {Boolean} status new hidden status.\n * @return {Promise} Repository promise.\n */\nconst setCourseHiddenState = (courseId, status) => {\n\n // If the given status is not hidden, the preference has to be deleted with a null value.\n if (status === false) {\n status = null;\n }\n return Repository.updateUserPreferences({\n preferences: [\n {\n type: 'block_myoverview_hidden_course_' + courseId,\n value: status\n }\n ]\n });\n};\n\n/**\n * Reset the loadedPages dataset to take into account the hidden element\n *\n * @param {Object} root The course overview container\n * @param {Number} id The course id number\n */\nconst hideElement = (root, id) => {\n const pagingBar = root.find('[data-region=\"paging-bar\"]');\n const jumpto = parseInt(pagingBar.attr('data-active-page-number'));\n\n // Get a reduced dataset for the current page.\n const courseList = loadedPages[jumpto];\n let reducedCourse = courseList.courses.reduce((accumulator, current) => {\n if (+id !== +current.id) {\n accumulator.push(current);\n }\n return accumulator;\n }, []);\n\n // Get the next page's data if loaded and pop the first element from it.\n if (typeof (loadedPages[jumpto + 1]) !== 'undefined') {\n const newElement = loadedPages[jumpto + 1].courses.slice(0, 1);\n\n // Adjust the dataset for the reset of the pages that are loaded.\n loadedPages.forEach((courseList, index) => {\n if (index > jumpto) {\n let popElement = [];\n if (typeof (loadedPages[index + 1]) !== 'undefined') {\n popElement = loadedPages[index + 1].courses.slice(0, 1);\n }\n loadedPages[index].courses = [...loadedPages[index].courses.slice(1), ...popElement];\n }\n });\n\n reducedCourse = [...reducedCourse, ...newElement];\n }\n\n // Check if the next page is the last page and if it still has data associated to it.\n if (lastPage === jumpto + 1 && loadedPages[jumpto + 1].courses.length === 0) {\n const pagedContentContainer = root.find('[data-region=\"paged-content-container\"]');\n PagedContentFactory.resetLastPageNumber($(pagedContentContainer).attr('id'), jumpto);\n }\n\n loadedPages[jumpto].courses = reducedCourse;\n\n // Reduce the course offset.\n courseOffset--;\n\n // Render the paged content for the current.\n const pagedContentPage = getPagedContentContainer(root, jumpto);\n renderCourses(root, loadedPages[jumpto]).then((html, js) => {\n return Templates.replaceNodeContents(pagedContentPage, html, js);\n }).catch(Notification.exception);\n\n // Delete subsequent pages in order to trigger the callback.\n loadedPages.forEach((courseList, index) => {\n if (index > jumpto) {\n const page = getPagedContentContainer(root, index);\n page.remove();\n }\n });\n};\n\n/**\n * Set the courses favourite status and push to repository\n *\n * @param {Number} courseId Course id to favourite.\n * @param {boolean} status new favourite status.\n * @return {Promise} Repository promise.\n */\nconst setCourseFavouriteState = (courseId, status) => {\n\n return Repository.setFavouriteCourses({\n courses: [\n {\n 'id': courseId,\n 'favourite': status\n }\n ]\n }).then(result => {\n if (result.warnings.length === 0) {\n loadedPages.forEach(courseList => {\n courseList.courses.forEach((course, index) => {\n if (course.id === courseId) {\n courseList.courses[index].isfavourite = status;\n }\n });\n });\n return true;\n } else {\n return false;\n }\n }).catch(Notification.exception);\n};\n\n/**\n * Given there are no courses to render provide the rendered template.\n *\n * @param {object} root The root element for the courses view.\n * @return {promise} jQuery promise resolved after rendering is complete.\n */\nconst noCoursesRender = root => {\n const nocoursesimg = root.find(SELECTORS.courseView.region).attr('data-nocoursesimg');\n const newcourseurl = root.find(SELECTORS.courseView.region).attr('data-newcourseurl');\n return Templates.render(TEMPLATES.NOCOURSES, {\n nocoursesimg: nocoursesimg,\n newcourseurl: newcourseurl\n });\n};\n\n/**\n * Render the dashboard courses.\n *\n * @param {object} root The root element for the courses view.\n * @param {array} coursesData containing array of returned courses.\n * @return {promise} jQuery promise resolved after rendering is complete.\n */\nconst renderCourses = (root, coursesData) => {\n\n const filters = getFilterValues(root);\n\n let currentTemplate = '';\n if (filters.display === 'card') {\n currentTemplate = TEMPLATES.COURSES_CARDS;\n } else if (filters.display === 'list') {\n currentTemplate = TEMPLATES.COURSES_LIST;\n } else {\n currentTemplate = TEMPLATES.COURSES_SUMMARY;\n }\n\n if (!coursesData) {\n return noCoursesRender(root);\n } else {\n // Sometimes we get weird objects coming after a failed search, cast to ensure typing functions.\n if (Array.isArray(coursesData.courses) === false) {\n coursesData.courses = Object.values(coursesData.courses);\n }\n // Whether the course category should be displayed in the course item.\n coursesData.courses = coursesData.courses.map(course => {\n course.showcoursecategory = filters.displaycategories === 'on';\n return course;\n });\n if (coursesData.courses.length) {\n return Templates.render(currentTemplate, {\n courses: coursesData.courses,\n });\n } else {\n return noCoursesRender(root);\n }\n }\n};\n\n/**\n * Return the callback to be passed to the subscribe event\n *\n * @param {object} root The root element for the courses view\n * @return {function} Partially applied function that'll execute when passed a limit\n */\nconst setLimit = root => {\n // @param {Number} limit The paged limit that is passed through the event.\n return limit => root.find(SELECTORS.courseView.region).attr('data-paging', limit);\n};\n\n/**\n * Intialise the paged list and cards views on page load.\n * Returns an array of paged contents that we would like to handle here\n *\n * @param {object} root The root element for the courses view\n * @param {string} namespace The namespace for all the events attached\n */\nconst registerPagedEventHandlers = (root, namespace) => {\n const event = namespace + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT;\n PubSub.subscribe(event, setLimit(root));\n};\n\n/**\n * Figure out how many items are going to be allowed to be rendered in the block.\n *\n * @param {Number} pagingLimit How many courses to display\n * @param {Object} root The course overview container\n * @return {Number[]} How many courses will be rendered\n */\nconst itemsPerPageFunc = (pagingLimit, root) => {\n let itemsPerPage = NUMCOURSES_PERPAGE.map(value => {\n let active = false;\n if (value === pagingLimit) {\n active = true;\n }\n\n return {\n value: value,\n active: active\n };\n });\n\n // Filter out all pagination options which are too large for the amount of courses user is enrolled in.\n const totalCourseCount = parseInt(root.find(SELECTORS.courseView.region).attr('data-totalcoursecount'), 10);\n return itemsPerPage.filter(pagingOption => {\n return pagingOption.value < totalCourseCount || pagingOption.value === 0;\n });\n};\n\n/**\n * Mutates and controls the loadedPages array and handles the bootstrapping.\n *\n * @param {Array|Object} coursesData Array of all of the courses to start building the page from\n * @param {Number} currentPage What page are we currently on?\n * @param {Object} pageData Any current page information\n * @param {Object} actions Paged content helper\n * @param {null|boolean} activeSearch Are we currently actively searching and building up search results?\n */\nconst pageBuilder = (coursesData, currentPage, pageData, actions, activeSearch = null) => {\n // If the courseData comes in an object then get the value otherwise it is a pure array.\n let courses = coursesData.courses ? coursesData.courses : coursesData;\n let nextPageStart = 0;\n let pageCourses = [];\n\n // If current page's data is loaded make sure we max it to page limit.\n if (typeof (loadedPages[currentPage]) !== 'undefined') {\n pageCourses = loadedPages[currentPage].courses;\n const currentPageLength = pageCourses.length;\n if (currentPageLength < pageData.limit) {\n nextPageStart = pageData.limit - currentPageLength;\n pageCourses = {...loadedPages[currentPage].courses, ...courses.slice(0, nextPageStart)};\n }\n } else {\n // When the page limit is zero, there is only one page of courses, no start for next page.\n nextPageStart = pageData.limit || false;\n pageCourses = (pageData.limit > 0) ? courses.slice(0, pageData.limit) : courses;\n }\n\n // Finished setting up the current page.\n loadedPages[currentPage] = {\n courses: pageCourses\n };\n\n // Set up the next page (if there is more than one page).\n const remainingCourses = nextPageStart !== false ? courses.slice(nextPageStart, courses.length) : [];\n if (remainingCourses.length) {\n loadedPages[currentPage + 1] = {\n courses: remainingCourses\n };\n }\n\n // Set the last page to either the current or next page.\n if (loadedPages[currentPage].courses.length < pageData.limit || !remainingCourses.length) {\n lastPage = currentPage;\n if (activeSearch === null) {\n actions.allItemsLoaded(currentPage);\n }\n } else if (typeof (loadedPages[currentPage + 1]) !== 'undefined'\n && loadedPages[currentPage + 1].courses.length < pageData.limit) {\n lastPage = currentPage + 1;\n }\n\n courseOffset = coursesData.nextoffset;\n};\n\n/**\n * In cases when switching between regular rendering and search rendering we need to reset some variables.\n */\nconst resetGlobals = () => {\n courseOffset = 0;\n loadedPages = [];\n lastPage = 0;\n lastLimit = 0;\n};\n\n/**\n * The default functionality of fetching paginated courses without special handling.\n *\n * @return {function(Object, Object, Object, Object, Object, Promise, Number): void}\n */\nconst standardFunctionalityCurry = () => {\n resetGlobals();\n return (filters, currentPage, pageData, actions, root, promises, limit) => {\n const pagePromise = getMyCourses(\n filters,\n limit\n ).then(coursesData => {\n pageBuilder(coursesData, currentPage, pageData, actions);\n return renderCourses(root, loadedPages[currentPage]);\n }).catch(Notification.exception);\n\n promises.push(pagePromise);\n };\n};\n\n/**\n * Initialize the searching functionality so we can call it when required.\n *\n * @return {function(Object, Number, Object, Object, Object, Promise, Number, String): void}\n */\nconst searchFunctionalityCurry = () => {\n resetGlobals();\n return (filters, currentPage, pageData, actions, root, promises, limit, inputValue) => {\n const searchingPromise = getSearchMyCourses(\n filters,\n limit,\n inputValue\n ).then(coursesData => {\n pageBuilder(coursesData, currentPage, pageData, actions);\n return renderCourses(root, loadedPages[currentPage]);\n }).catch(Notification.exception);\n\n promises.push(searchingPromise);\n };\n};\n\n/**\n * Initialise the courses list and cards views on page load.\n *\n * @param {object} root The root element for the courses view.\n * @param {function} promiseFunction How do we fetch the courses and what do we do with them?\n * @param {null | string} inputValue What to search for\n */\nconst initializePagedContent = (root, promiseFunction, inputValue = null) => {\n const pagingLimit = parseInt(root.find(SELECTORS.courseView.region).attr('data-paging'), 10);\n let itemsPerPage = itemsPerPageFunc(pagingLimit, root);\n\n const filters = getFilterValues(root);\n const config = {...{}, ...DEFAULT_PAGED_CONTENT_CONFIG};\n config.eventNamespace = namespace;\n\n const pagedContentPromise = PagedContentFactory.createWithLimit(\n itemsPerPage,\n (pagesData, actions) => {\n let promises = [];\n pagesData.forEach(pageData => {\n const currentPage = pageData.pageNumber;\n let limit = (pageData.limit > 0) ? pageData.limit : 0;\n\n // Reset local variables if limits have changed.\n if (+lastLimit !== +limit) {\n loadedPages = [];\n courseOffset = 0;\n lastPage = 0;\n }\n\n if (lastPage === currentPage) {\n // If we are on the last page and have it's data then load it from cache.\n actions.allItemsLoaded(lastPage);\n promises.push(renderCourses(root, loadedPages[currentPage]));\n return;\n }\n\n lastLimit = limit;\n\n // Get 2 pages worth of data as we will need it for the hidden functionality.\n if (typeof (loadedPages[currentPage + 1]) === 'undefined') {\n if (typeof (loadedPages[currentPage]) === 'undefined') {\n limit *= 2;\n }\n }\n\n // Call the curried function that'll handle the course promise and any manipulation of it.\n promiseFunction(filters, currentPage, pageData, actions, root, promises, limit, inputValue);\n });\n return promises;\n },\n config\n );\n\n pagedContentPromise.then((html, js) => {\n registerPagedEventHandlers(root, namespace);\n return Templates.replaceNodeContents(root.find(SELECTORS.courseView.region), html, js);\n }).catch(Notification.exception);\n};\n\n/**\n * Listen to, and handle events for the myoverview block.\n *\n * @param {Object} root The myoverview block container element.\n * @param {HTMLElement} page The whole HTMLElement for our block.\n */\nconst registerEventListeners = (root, page) => {\n\n CustomEvents.define(root, [\n CustomEvents.events.activate\n ]);\n\n root.on(CustomEvents.events.activate, SELECTORS.ACTION_ADD_FAVOURITE, (e, data) => {\n const favourite = $(e.target).closest(SELECTORS.ACTION_ADD_FAVOURITE);\n const courseId = getCourseId(favourite);\n addToFavourites(root, courseId);\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.ACTION_REMOVE_FAVOURITE, (e, data) => {\n const favourite = $(e.target).closest(SELECTORS.ACTION_REMOVE_FAVOURITE);\n const courseId = getCourseId(favourite);\n removeFromFavourites(root, courseId);\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.FAVOURITE_ICON, (e, data) => {\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.ACTION_HIDE_COURSE, (e, data) => {\n const target = $(e.target).closest(SELECTORS.ACTION_HIDE_COURSE);\n const courseId = getCourseId(target);\n hideCourse(root, courseId);\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.ACTION_SHOW_COURSE, (e, data) => {\n const target = $(e.target).closest(SELECTORS.ACTION_SHOW_COURSE);\n const courseId = getCourseId(target);\n showCourse(root, courseId);\n data.originalEvent.preventDefault();\n });\n\n // Searching functionality event handlers.\n const input = page.querySelector(SELECTORS.region.searchInput);\n const clearIcon = page.querySelector(SELECTORS.region.clearIcon);\n\n clearIcon.addEventListener('click', () => {\n input.value = '';\n input.focus();\n clearSearch(clearIcon, root);\n });\n\n input.addEventListener('input', debounce(() => {\n if (input.value === '') {\n clearSearch(clearIcon, root);\n } else {\n activeSearch(clearIcon);\n initializePagedContent(root, searchFunctionalityCurry(), input.value.trim());\n }\n }, 300));\n};\n\n/**\n * Reset the search icon and trigger the init for the block.\n *\n * @param {HTMLElement} clearIcon Our closing icon to manipulate.\n * @param {Object} root The myoverview block container element.\n */\nexport const clearSearch = (clearIcon, root) => {\n clearIcon.classList.add('d-none');\n init(root);\n};\n\n/**\n * Change the searching icon to its' active state.\n *\n * @param {HTMLElement} clearIcon Our closing icon to manipulate.\n */\nconst activeSearch = (clearIcon) => {\n clearIcon.classList.remove('d-none');\n};\n\n/**\n * Intialise the courses list and cards views on page load.\n *\n * @param {object} root The root element for the courses view.\n */\nexport const init = root => {\n root = $(root);\n loadedPages = [];\n lastPage = 0;\n courseOffset = 0;\n\n if (!root.attr('data-init')) {\n const page = document.querySelector(SELECTORS.region.selectBlock);\n registerEventListeners(root, page);\n namespace = \"block_myoverview_\" + root.attr('id') + \"_\" + Math.random();\n root.attr('data-init', true);\n }\n\n initializePagedContent(root, standardFunctionalityCurry());\n};\n\n/**\n * Reset the courses views to their original\n * state on first page load.courseOffset\n *\n * This is called when configuration has changed for the event lists\n * to cause them to reload their data.\n *\n * @param {Object} root The root element for the timeline view.\n */\nexport const reset = root => {\n if (loadedPages.length > 0) {\n loadedPages.forEach((courseList, index) => {\n let pagedContentPage = getPagedContentContainer(root, index);\n renderCourses(root, courseList).then((html, js) => {\n return Templates.replaceNodeContents(pagedContentPage, html, js);\n }).catch(Notification.exception);\n });\n } else {\n init(root);\n }\n};\n"],"names":["TEMPLATES","GROUPINGS","NUMCOURSES_PERPAGE","loadedPages","courseOffset","lastPage","lastLimit","namespace","getFilterValues","root","courseRegion","find","SELECTORS","courseView","region","display","attr","grouping","sort","displaycategories","customfieldname","customfieldvalue","DEFAULT_PAGED_CONTENT_CONFIG","ignoreControlWhileLoading","controlPlacementBottom","persistentLimitKey","getFavouriteIconContainer","courseId","FAVOURITE_ICON","getPagedContentContainer","index","getCourseId","getAddFavouriteMenuItem","getRemoveFavouriteMenuItem","addToFavourites","removeAction","addAction","setCourseFavouriteState","then","success","PubSub","publish","CourseEvents","favorited","removeClass","addClass","iconContainer","isFavouriteIcon","ICON_IS_FAVOURITE","Aria","unhide","notFavourteIcon","ICON_NOT_FAVOURITE","hide","showFavouriteIcon","Notification","alert","catch","exception","removeFromFavourites","unfavorited","hideFavouriteIcon","getHideCourseMenuItem","getShowCourseMenuItem","setCourseHiddenState","status","Repository","updateUserPreferences","preferences","type","value","hideElement","id","pagingBar","jumpto","parseInt","reducedCourse","courses","reduce","accumulator","current","push","newElement","slice","forEach","courseList","popElement","length","pagedContentContainer","PagedContentFactory","resetLastPageNumber","pagedContentPage","renderCourses","html","js","Templates","replaceNodeContents","remove","setFavouriteCourses","result","warnings","course","isfavourite","noCoursesRender","nocoursesimg","newcourseurl","render","coursesData","filters","currentTemplate","Array","isArray","Object","values","map","showcoursecategory","registerPagedEventHandlers","event","PagedContentEvents","SET_ITEMS_PER_PAGE_LIMIT","subscribe","limit","setLimit","itemsPerPageFunc","pagingLimit","itemsPerPage","active","totalCourseCount","filter","pagingOption","pageBuilder","currentPage","pageData","actions","activeSearch","nextPageStart","pageCourses","currentPageLength","remainingCourses","allItemsLoaded","nextoffset","resetGlobals","standardFunctionalityCurry","promises","pagePromise","getEnrolledCoursesByTimeline","offset","classification","getMyCourses","searchFunctionalityCurry","inputValue","searchingPromise","searchValue","searchvalue","getSearchMyCourses","initializePagedContent","promiseFunction","config","eventNamespace","pagedContentPromise","createWithLimit","pagesData","pageNumber","registerEventListeners","page","CustomEvents","define","events","activate","on","ACTION_ADD_FAVOURITE","e","data","favourite","target","closest","originalEvent","preventDefault","ACTION_REMOVE_FAVOURITE","ACTION_HIDE_COURSE","hideAction","showAction","hideCourse","ACTION_SHOW_COURSE","showCourse","input","querySelector","searchInput","clearIcon","addEventListener","focus","clearSearch","trim","classList","add","init","document","selectBlock","Math","random"],"mappings":"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"}
\ No newline at end of file
diff --git a/blocks/myoverview/amd/build/view_nav.min.js b/blocks/myoverview/amd/build/view_nav.min.js
index d57cdfb979e..16301eaad6f 100644
--- a/blocks/myoverview/amd/build/view_nav.min.js
+++ b/blocks/myoverview/amd/build/view_nav.min.js
@@ -1,2 +1,9 @@
-function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("block_myoverview/view_nav",["exports","jquery","core/custom_interaction_events","block_myoverview/repository","block_myoverview/view","block_myoverview/selectors"],function(a,b,c,d,f,g){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=j(b);c=i(c);d=i(d);f=i(f);g=j(g);function h(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;h=function(){return a};return a}function i(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=h();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function j(a){return a&&a.__esModule?a:{default:a}}var k=function(a,b){var c=null;if("display"===a){c="block_myoverview_user_view_preference"}else if("sort"===a){c="block_myoverview_user_sort_preference"}else if("customfieldvalue"===a){c="block_myoverview_user_grouping_customfieldvalue_preference"}else{c="block_myoverview_user_grouping_preference"}d.updateUserPreferences({preferences:[{type:c,value:b}]})},l=function(a){var d=a.find(g.default.FILTERS);c.define(d,[c.events.activate]);d.on(c.events.activate,g.default.FILTER_OPTION,function(c,d){var e=(0,b.default)(c.target);if(e.hasClass("active")){return}var h=e.attr("data-filter"),i=e.attr("data-pref"),j=e.attr("data-customfieldvalue");a.find(g.default.courseView.region).attr("data-"+h,e.attr("data-value"));k(h,i);if(j){a.find(g.default.courseView.region).attr("data-customfieldvalue",j);k("customfieldvalue",j)}var l=document.querySelector(g.default.region.selectBlock),m=l.querySelector(g.default.region.searchInput);if(""!==m.value){var n=l.querySelector(g.default.region.clearIcon);m.value="";f.clearSearch(n,a)}else{f.init(a)}d.originalEvent.preventDefault()});d.on(c.events.activate,g.default.DISPLAY_OPTION,function(c,d){var e=(0,b.default)(c.target);if(e.hasClass("active")){return}var h=e.attr("data-display-option"),i=e.attr("data-pref");a.find(g.default.courseView.region).attr("data-display",e.attr("data-value"));k(h,i);f.reset(a);d.originalEvent.preventDefault()})},m=function(a){a=(0,b.default)(a);l(a)};a.init=m});
-//# sourceMappingURL=view_nav.min.js.map
+define("block_myoverview/view_nav",["exports","jquery","core/custom_interaction_events","block_myoverview/repository","block_myoverview/view","block_myoverview/selectors"],(function(_exports,_jquery,CustomEvents,Repository,View,_selectors){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}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
+/**
+ * Manage the timeline view navigation for the overview block.
+ *
+ * @copyright 2018 Bas Brands
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),CustomEvents=_interopRequireWildcard(CustomEvents),Repository=_interopRequireWildcard(Repository),View=_interopRequireWildcard(View),_selectors=_interopRequireDefault(_selectors);const updatePreferences=(filter,value)=>{let type=null;type="display"===filter?"block_myoverview_user_view_preference":"sort"===filter?"block_myoverview_user_sort_preference":"customfieldvalue"===filter?"block_myoverview_user_grouping_customfieldvalue_preference":"block_myoverview_user_grouping_preference",Repository.updateUserPreferences({preferences:[{type:type,value:value}]})};_exports.init=root=>{(root=>{const Selector=root.find(_selectors.default.FILTERS);CustomEvents.define(Selector,[CustomEvents.events.activate]),Selector.on(CustomEvents.events.activate,_selectors.default.FILTER_OPTION,((e,data)=>{const option=(0,_jquery.default)(e.target);if(option.hasClass("active"))return;const filter=option.attr("data-filter"),pref=option.attr("data-pref"),customfieldvalue=option.attr("data-customfieldvalue");root.find(_selectors.default.courseView.region).attr("data-"+filter,option.attr("data-value")),updatePreferences(filter,pref),customfieldvalue&&(root.find(_selectors.default.courseView.region).attr("data-customfieldvalue",customfieldvalue),updatePreferences("customfieldvalue",customfieldvalue));const page=document.querySelector(_selectors.default.region.selectBlock),input=page.querySelector(_selectors.default.region.searchInput);if(""!==input.value){const clearIcon=page.querySelector(_selectors.default.region.clearIcon);input.value="",View.clearSearch(clearIcon,root)}else View.init(root);data.originalEvent.preventDefault()})),Selector.on(CustomEvents.events.activate,_selectors.default.DISPLAY_OPTION,((e,data)=>{const option=(0,_jquery.default)(e.target);if(option.hasClass("active"))return;const filter=option.attr("data-display-option"),pref=option.attr("data-pref");root.find(_selectors.default.courseView.region).attr("data-display",option.attr("data-value")),updatePreferences(filter,pref),View.reset(root),data.originalEvent.preventDefault()}))})(root=(0,_jquery.default)(root))}}));
+
+//# sourceMappingURL=view_nav.min.js.map
\ No newline at end of file
diff --git a/blocks/myoverview/amd/build/view_nav.min.js.map b/blocks/myoverview/amd/build/view_nav.min.js.map
index b9f5e2f429c..c2c822eac0f 100644
--- a/blocks/myoverview/amd/build/view_nav.min.js.map
+++ b/blocks/myoverview/amd/build/view_nav.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/view_nav.js"],"names":["updatePreferences","filter","value","type","Repository","updateUserPreferences","preferences","registerSelector","root","Selector","find","SELECTORS","FILTERS","CustomEvents","define","events","activate","on","FILTER_OPTION","e","data","option","target","hasClass","attr","pref","customfieldvalue","courseView","region","page","document","querySelector","selectBlock","input","searchInput","clearIcon","View","clearSearch","init","originalEvent","preventDefault","DISPLAY_OPTION","reset"],"mappings":"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","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 .\n\n/**\n * Manage the timeline view navigation for the overview block.\n *\n * @copyright 2018 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport * as CustomEvents from 'core/custom_interaction_events';\nimport * as Repository from 'block_myoverview/repository';\nimport * as View from 'block_myoverview/view';\nimport SELECTORS from 'block_myoverview/selectors';\n\n/**\n * Update the user preference for the block.\n *\n * @param {String} filter The type of filter: display/sort/grouping.\n * @param {String} value The current preferred value.\n */\nconst updatePreferences = (filter, value) => {\n let type = null;\n if (filter === 'display') {\n type = 'block_myoverview_user_view_preference';\n } else if (filter === 'sort') {\n type = 'block_myoverview_user_sort_preference';\n } else if (filter === 'customfieldvalue') {\n type = 'block_myoverview_user_grouping_customfieldvalue_preference';\n } else {\n type = 'block_myoverview_user_grouping_preference';\n }\n\n Repository.updateUserPreferences({\n preferences: [\n {\n type: type,\n value: value\n }\n ]\n });\n};\n\n/**\n * Event listener for the Display filter (cards, list).\n *\n * @param {object} root The root element for the overview block\n */\nconst registerSelector = root => {\n\n const Selector = root.find(SELECTORS.FILTERS);\n\n CustomEvents.define(Selector, [CustomEvents.events.activate]);\n Selector.on(\n CustomEvents.events.activate,\n SELECTORS.FILTER_OPTION,\n (e, data) => {\n const option = $(e.target);\n\n if (option.hasClass('active')) {\n // If it's already active then we don't need to do anything.\n return;\n }\n\n const filter = option.attr('data-filter');\n const pref = option.attr('data-pref');\n const customfieldvalue = option.attr('data-customfieldvalue');\n\n root.find(SELECTORS.courseView.region).attr('data-' + filter, option.attr('data-value'));\n updatePreferences(filter, pref);\n\n if (customfieldvalue) {\n root.find(SELECTORS.courseView.region).attr('data-customfieldvalue', customfieldvalue);\n updatePreferences('customfieldvalue', customfieldvalue);\n }\n\n // Reset the views.\n\n // Check if the user is currently in a searching state, if so we'll reset it.\n const page = document.querySelector(SELECTORS.region.selectBlock);\n const input = page.querySelector(SELECTORS.region.searchInput);\n if (input.value !== '') {\n const clearIcon = page.querySelector(SELECTORS.region.clearIcon);\n input.value = '';\n // Triggers the init so wont need to call it again.\n View.clearSearch(clearIcon, root);\n } else {\n View.init(root);\n }\n\n data.originalEvent.preventDefault();\n }\n );\n\n Selector.on(\n CustomEvents.events.activate,\n SELECTORS.DISPLAY_OPTION,\n (e, data) => {\n const option = $(e.target);\n\n if (option.hasClass('active')) {\n return;\n }\n\n const filter = option.attr('data-display-option');\n const pref = option.attr('data-pref');\n\n root.find(SELECTORS.courseView.region).attr('data-display', option.attr('data-value'));\n updatePreferences(filter, pref);\n View.reset(root);\n data.originalEvent.preventDefault();\n }\n );\n};\n\n/**\n * Initialise the timeline view navigation by adding event listeners to\n * the navigation elements.\n *\n * @param {object} root The root element for the myoverview block\n */\nexport const init = root => {\n root = $(root);\n registerSelector(root);\n};\n"],"file":"view_nav.min.js"}
\ No newline at end of file
+{"version":3,"file":"view_nav.min.js","sources":["../src/view_nav.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 .\n\n/**\n * Manage the timeline view navigation for the overview block.\n *\n * @copyright 2018 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport * as CustomEvents from 'core/custom_interaction_events';\nimport * as Repository from 'block_myoverview/repository';\nimport * as View from 'block_myoverview/view';\nimport SELECTORS from 'block_myoverview/selectors';\n\n/**\n * Update the user preference for the block.\n *\n * @param {String} filter The type of filter: display/sort/grouping.\n * @param {String} value The current preferred value.\n */\nconst updatePreferences = (filter, value) => {\n let type = null;\n if (filter === 'display') {\n type = 'block_myoverview_user_view_preference';\n } else if (filter === 'sort') {\n type = 'block_myoverview_user_sort_preference';\n } else if (filter === 'customfieldvalue') {\n type = 'block_myoverview_user_grouping_customfieldvalue_preference';\n } else {\n type = 'block_myoverview_user_grouping_preference';\n }\n\n Repository.updateUserPreferences({\n preferences: [\n {\n type: type,\n value: value\n }\n ]\n });\n};\n\n/**\n * Event listener for the Display filter (cards, list).\n *\n * @param {object} root The root element for the overview block\n */\nconst registerSelector = root => {\n\n const Selector = root.find(SELECTORS.FILTERS);\n\n CustomEvents.define(Selector, [CustomEvents.events.activate]);\n Selector.on(\n CustomEvents.events.activate,\n SELECTORS.FILTER_OPTION,\n (e, data) => {\n const option = $(e.target);\n\n if (option.hasClass('active')) {\n // If it's already active then we don't need to do anything.\n return;\n }\n\n const filter = option.attr('data-filter');\n const pref = option.attr('data-pref');\n const customfieldvalue = option.attr('data-customfieldvalue');\n\n root.find(SELECTORS.courseView.region).attr('data-' + filter, option.attr('data-value'));\n updatePreferences(filter, pref);\n\n if (customfieldvalue) {\n root.find(SELECTORS.courseView.region).attr('data-customfieldvalue', customfieldvalue);\n updatePreferences('customfieldvalue', customfieldvalue);\n }\n\n // Reset the views.\n\n // Check if the user is currently in a searching state, if so we'll reset it.\n const page = document.querySelector(SELECTORS.region.selectBlock);\n const input = page.querySelector(SELECTORS.region.searchInput);\n if (input.value !== '') {\n const clearIcon = page.querySelector(SELECTORS.region.clearIcon);\n input.value = '';\n // Triggers the init so wont need to call it again.\n View.clearSearch(clearIcon, root);\n } else {\n View.init(root);\n }\n\n data.originalEvent.preventDefault();\n }\n );\n\n Selector.on(\n CustomEvents.events.activate,\n SELECTORS.DISPLAY_OPTION,\n (e, data) => {\n const option = $(e.target);\n\n if (option.hasClass('active')) {\n return;\n }\n\n const filter = option.attr('data-display-option');\n const pref = option.attr('data-pref');\n\n root.find(SELECTORS.courseView.region).attr('data-display', option.attr('data-value'));\n updatePreferences(filter, pref);\n View.reset(root);\n data.originalEvent.preventDefault();\n }\n );\n};\n\n/**\n * Initialise the timeline view navigation by adding event listeners to\n * the navigation elements.\n *\n * @param {object} root The root element for the myoverview block\n */\nexport const init = root => {\n root = $(root);\n registerSelector(root);\n};\n"],"names":["updatePreferences","filter","value","type","Repository","updateUserPreferences","preferences","root","Selector","find","SELECTORS","FILTERS","CustomEvents","define","events","activate","on","FILTER_OPTION","e","data","option","target","hasClass","attr","pref","customfieldvalue","courseView","region","page","document","querySelector","selectBlock","input","searchInput","clearIcon","View","clearSearch","init","originalEvent","preventDefault","DISPLAY_OPTION","reset","registerSelector"],"mappings":";;;;;;mTAkCMA,kBAAoB,CAACC,OAAQC,aAC3BC,KAAO,KAEPA,KADW,YAAXF,OACO,wCACW,SAAXA,OACA,wCACW,qBAAXA,OACA,6DAEA,4CAGXG,WAAWC,sBAAsB,CAC7BC,YAAa,CACT,CACIH,KAAMA,KACND,MAAOA,yBAoFHK,OAzEKA,CAAAA,aAEfC,SAAWD,KAAKE,KAAKC,mBAAUC,SAErCC,aAAaC,OAAOL,SAAU,CAACI,aAAaE,OAAOC,WACnDP,SAASQ,GACLJ,aAAaE,OAAOC,SACpBL,mBAAUO,eACV,CAACC,EAAGC,cACMC,QAAS,mBAAEF,EAAEG,WAEfD,OAAOE,SAAS,uBAKdrB,OAASmB,OAAOG,KAAK,eACrBC,KAAOJ,OAAOG,KAAK,aACnBE,iBAAmBL,OAAOG,KAAK,yBAErChB,KAAKE,KAAKC,mBAAUgB,WAAWC,QAAQJ,KAAK,QAAUtB,OAAQmB,OAAOG,KAAK,eAC1EvB,kBAAkBC,OAAQuB,MAEtBC,mBACAlB,KAAKE,KAAKC,mBAAUgB,WAAWC,QAAQJ,KAAK,wBAAyBE,kBACrEzB,kBAAkB,mBAAoByB,yBAMpCG,KAAOC,SAASC,cAAcpB,mBAAUiB,OAAOI,aAC/CC,MAAQJ,KAAKE,cAAcpB,mBAAUiB,OAAOM,gBAC9B,KAAhBD,MAAM9B,MAAc,OACdgC,UAAYN,KAAKE,cAAcpB,mBAAUiB,OAAOO,WACtDF,MAAM9B,MAAQ,GAEdiC,KAAKC,YAAYF,UAAW3B,WAE5B4B,KAAKE,KAAK9B,MAGdY,KAAKmB,cAAcC,oBAI3B/B,SAASQ,GACLJ,aAAaE,OAAOC,SACpBL,mBAAU8B,gBACV,CAACtB,EAAGC,cACMC,QAAS,mBAAEF,EAAEG,WAEfD,OAAOE,SAAS,uBAIdrB,OAASmB,OAAOG,KAAK,uBACrBC,KAAOJ,OAAOG,KAAK,aAEzBhB,KAAKE,KAAKC,mBAAUgB,WAAWC,QAAQJ,KAAK,eAAgBH,OAAOG,KAAK,eACxEvB,kBAAkBC,OAAQuB,MAC1BW,KAAKM,MAAMlC,MACXY,KAAKmB,cAAcC,qBAa3BG,CADAnC,MAAO,mBAAEA"}
\ No newline at end of file
diff --git a/blocks/navigation/amd/build/ajax_response_renderer.min.js b/blocks/navigation/amd/build/ajax_response_renderer.min.js
index a3d3c377c11..bfd9e6ac7a2 100644
--- a/blocks/navigation/amd/build/ajax_response_renderer.min.js
+++ b/blocks/navigation/amd/build/ajax_response_renderer.min.js
@@ -1,2 +1,11 @@
-function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("block_navigation/ajax_response_renderer",["jquery","core/templates","core/notification","core/url","core/aria"],function(a,b,c,d,e){var g={ACTIVITY:40,RESOURCE:50};function f(h,i){var j=a("
");j.attr("role","group");e.hide(j);a.each(i,function(e,h){if("object"!==_typeof(h)){return}var i=a(""),k=a(""),l=h.id||h.key+"_tree_item",m=null,n=h.expandable||h.haschildren?!0:!1;i.attr("role","treeitem");k.addClass("tree_item");k.attr("id",l);k.attr("tabindex","-1");if(h.requiresajaxloading){i.attr("data-requires-ajax",!0);i.attr("data-node-id",h.id);i.attr("data-node-key",h.key);i.attr("data-node-type",h.type)}if(n){i.addClass("collapsed contains_branch");i.attr("aria-expanded",!1);k.addClass("branch")}var o=null;if(h.link){var p=a("");o=p;p.append(""+h.name+"");if(h.hidden){p.addClass("dimmed")}k.append(p)}else{var q=a("");o=q;q.append(""+h.name+"");if(h.hidden){q.addClass("dimmed")}k.append(q)}if(h.icon&&(!n||h.type===g.ACTIVITY||h.type===g.RESOURCE)){i.addClass("item_with_icon");k.addClass("hasicon");if(h.type===g.ACTIVITY||h.type===g.RESOURCE){m=a("");m.attr("alt",h.icon.alt);m.attr("title",h.icon.title);m.attr("src",d.imageUrl(h.icon.pix,h.icon.component));a.each(h.icon.classes,function(a,b){m.addClass(b)});o.prepend(m)}else{if("moodle"==h.icon.component){h.icon.component="core"}b.renderPix(h.icon.pix,h.icon.component,h.icon.title).then(function(a){o.prepend(a)}).catch(c.exception)}}i.append(k);j.append(i);if(h.children&&h.children.length){f(i,h.children)}else if(n&&!h.requiresajaxloading){i.removeClass("contains_branch");k.addClass("emptybranch")}});h.append(j);var k=h.attr("id")+"_group";j.attr("id",k);h.attr("aria-owns",k);h.attr("role","treeitem")}return{render:function render(a,b){if(b.children&&b.children.length){f(a,b.children);var c=a.children("[role='treeitem']").first(),d=a.find("#"+c.attr("aria-owns"));c.attr("aria-expanded",!0);e.unhide(d)}else{if(a.hasClass("contains_branch")){a.removeClass("contains_branch");a.addClass("emptybranch")}}}}});
-//# sourceMappingURL=ajax_response_renderer.min.js.map
+/**
+ * Parse the response from the navblock ajax page and render the correct DOM
+ * structure for the tree from it.
+ *
+ * @module block_navigation/ajax_response_renderer
+ * @copyright 2015 John Okely
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_navigation/ajax_response_renderer",["jquery","core/templates","core/notification","core/url","core/aria"],(function($,Templates,Notification,Url,Aria){var NODETYPE_ACTIVITY=40,NODETYPE_RESOURCE=50;function buildDOM(rootElement,nodes){var ul=$("
");ul.attr("role","group"),Aria.hide(ul),$.each(nodes,(function(index,node){if("object"==typeof node){var li=$(""),p=$(""),id=node.id||node.key+"_tree_item",icon=null,isBranch=!(!node.expandable&&!node.haschildren);li.attr("role","treeitem"),p.addClass("tree_item"),p.attr("id",id),p.attr("tabindex","-1"),node.requiresajaxloading&&(li.attr("data-requires-ajax",!0),li.attr("data-node-id",node.id),li.attr("data-node-key",node.key),li.attr("data-node-type",node.type)),isBranch&&(li.addClass("collapsed contains_branch"),li.attr("aria-expanded",!1),p.addClass("branch"));var eleToAddIcon=null;if(node.link){var link=$('');eleToAddIcon=link,link.append(''+node.name+""),node.hidden&&link.addClass("dimmed"),p.append(link)}else{var span=$("");eleToAddIcon=span,span.append(''+node.name+""),node.hidden&&span.addClass("dimmed"),p.append(span)}!node.icon||isBranch&&node.type!==NODETYPE_ACTIVITY&&node.type!==NODETYPE_RESOURCE||(li.addClass("item_with_icon"),p.addClass("hasicon"),node.type===NODETYPE_ACTIVITY||node.type===NODETYPE_RESOURCE?((icon=$("")).attr("alt",node.icon.alt),icon.attr("title",node.icon.title),icon.attr("src",Url.imageUrl(node.icon.pix,node.icon.component)),$.each(node.icon.classes,(function(index,className){icon.addClass(className)})),eleToAddIcon.prepend(icon)):("moodle"==node.icon.component&&(node.icon.component="core"),Templates.renderPix(node.icon.pix,node.icon.component,node.icon.title).then((function(html){eleToAddIcon.prepend(html)})).catch(Notification.exception))),li.append(p),ul.append(li),node.children&&node.children.length?buildDOM(li,node.children):isBranch&&!node.requiresajaxloading&&(li.removeClass("contains_branch"),p.addClass("emptybranch"))}})),rootElement.append(ul);var id=rootElement.attr("id")+"_group";ul.attr("id",id),rootElement.attr("aria-owns",id),rootElement.attr("role","treeitem")}return{render:function(element,nodes){if(nodes.children&&nodes.children.length){buildDOM(element,nodes.children);var item=element.children("[role='treeitem']").first(),group=element.find("#"+item.attr("aria-owns"));item.attr("aria-expanded",!0),Aria.unhide(group)}else element.hasClass("contains_branch")&&(element.removeClass("contains_branch"),element.addClass("emptybranch"))}}}));
+
+//# sourceMappingURL=ajax_response_renderer.min.js.map
\ No newline at end of file
diff --git a/blocks/navigation/amd/build/ajax_response_renderer.min.js.map b/blocks/navigation/amd/build/ajax_response_renderer.min.js.map
index d0a51f60826..9326e87fb70 100644
--- a/blocks/navigation/amd/build/ajax_response_renderer.min.js.map
+++ b/blocks/navigation/amd/build/ajax_response_renderer.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/ajax_response_renderer.js"],"names":["define","$","Templates","Notification","Url","Aria","NODETYPE","ACTIVITY","RESOURCE","buildDOM","rootElement","nodes","ul","attr","hide","each","index","node","li","p","id","key","icon","isBranch","expandable","haschildren","addClass","requiresajaxloading","type","eleToAddIcon","link","title","append","name","hidden","span","alt","imageUrl","pix","component","classes","className","prepend","renderPix","then","html","catch","exception","children","length","removeClass","render","element","item","first","group","find","unhide","hasClass"],"mappings":"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","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 .\n\n/**\n * Parse the response from the navblock ajax page and render the correct DOM\n * structure for the tree from it.\n *\n * @module block_navigation/ajax_response_renderer\n * @copyright 2015 John Okely \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/templates',\n 'core/notification',\n 'core/url',\n 'core/aria',\n], function(\n $,\n Templates,\n Notification,\n Url,\n Aria\n) {\n\n // Mappings for the different types of nodes coming from the navigation.\n // Copied from lib/navigationlib.php navigation_node constants.\n var NODETYPE = {\n // @type int Activity (course module) = 40.\n ACTIVITY: 40,\n // @type int Resource (course module = 50.\n RESOURCE: 50,\n };\n\n /**\n * Build DOM.\n *\n * @method buildDOM\n * @param {Object} rootElement the root element of DOM.\n * @param {object} nodes jquery object representing the nodes to be build.\n */\n function buildDOM(rootElement, nodes) {\n var ul = $('
');\n ul.attr('role', 'group');\n Aria.hide(ul);\n\n $.each(nodes, function(index, node) {\n if (typeof node !== 'object') {\n return;\n }\n\n var li = $('');\n var p = $('');\n var id = node.id || node.key + '_tree_item';\n var icon = null;\n var isBranch = (node.expandable || node.haschildren) ? true : false;\n\n li.attr('role', 'treeitem');\n p.addClass('tree_item');\n p.attr('id', id);\n // Negative tab index to allow it to receive focus.\n p.attr('tabindex', '-1');\n\n if (node.requiresajaxloading) {\n li.attr('data-requires-ajax', true);\n li.attr('data-node-id', node.id);\n li.attr('data-node-key', node.key);\n li.attr('data-node-type', node.type);\n }\n\n if (isBranch) {\n li.addClass('collapsed contains_branch');\n li.attr('aria-expanded', false);\n p.addClass('branch');\n }\n\n var eleToAddIcon = null;\n if (node.link) {\n var link = $('');\n\n eleToAddIcon = link;\n link.append('' + node.name + '');\n\n if (node.hidden) {\n link.addClass('dimmed');\n }\n\n p.append(link);\n } else {\n var span = $('');\n\n eleToAddIcon = span;\n span.append('' + node.name + '');\n\n if (node.hidden) {\n span.addClass('dimmed');\n }\n\n p.append(span);\n }\n\n if (node.icon && (!isBranch || node.type === NODETYPE.ACTIVITY || node.type === NODETYPE.RESOURCE)) {\n li.addClass('item_with_icon');\n p.addClass('hasicon');\n\n if (node.type === NODETYPE.ACTIVITY || node.type === NODETYPE.RESOURCE) {\n icon = $('');\n icon.attr('alt', node.icon.alt);\n icon.attr('title', node.icon.title);\n icon.attr('src', Url.imageUrl(node.icon.pix, node.icon.component));\n $.each(node.icon.classes, function(index, className) {\n icon.addClass(className);\n });\n eleToAddIcon.prepend(icon);\n } else {\n if (node.icon.component == 'moodle') {\n node.icon.component = 'core';\n }\n Templates.renderPix(node.icon.pix, node.icon.component, node.icon.title).then(function(html) {\n // Prepend.\n eleToAddIcon.prepend(html);\n return;\n }).catch(Notification.exception);\n }\n }\n\n li.append(p);\n ul.append(li);\n\n if (node.children && node.children.length) {\n buildDOM(li, node.children);\n } else if (isBranch && !node.requiresajaxloading) {\n li.removeClass('contains_branch');\n p.addClass('emptybranch');\n }\n });\n\n rootElement.append(ul);\n var id = rootElement.attr('id') + '_group';\n ul.attr('id', id);\n rootElement.attr('aria-owns', id);\n rootElement.attr('role', 'treeitem');\n }\n\n return {\n render: function(element, nodes) {\n // The first element of the response is the existing node so we start with processing the children.\n if (nodes.children && nodes.children.length) {\n buildDOM(element, nodes.children);\n\n var item = element.children(\"[role='treeitem']\").first();\n var group = element.find('#' + item.attr('aria-owns'));\n\n item.attr('aria-expanded', true);\n Aria.unhide(group);\n } else {\n if (element.hasClass('contains_branch')) {\n element.removeClass('contains_branch');\n element.addClass('emptybranch');\n }\n }\n }\n };\n});\n"],"file":"ajax_response_renderer.min.js"}
\ No newline at end of file
+{"version":3,"file":"ajax_response_renderer.min.js","sources":["../src/ajax_response_renderer.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 .\n\n/**\n * Parse the response from the navblock ajax page and render the correct DOM\n * structure for the tree from it.\n *\n * @module block_navigation/ajax_response_renderer\n * @copyright 2015 John Okely \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/templates',\n 'core/notification',\n 'core/url',\n 'core/aria',\n], function(\n $,\n Templates,\n Notification,\n Url,\n Aria\n) {\n\n // Mappings for the different types of nodes coming from the navigation.\n // Copied from lib/navigationlib.php navigation_node constants.\n var NODETYPE = {\n // @type int Activity (course module) = 40.\n ACTIVITY: 40,\n // @type int Resource (course module = 50.\n RESOURCE: 50,\n };\n\n /**\n * Build DOM.\n *\n * @method buildDOM\n * @param {Object} rootElement the root element of DOM.\n * @param {object} nodes jquery object representing the nodes to be build.\n */\n function buildDOM(rootElement, nodes) {\n var ul = $('
');\n ul.attr('role', 'group');\n Aria.hide(ul);\n\n $.each(nodes, function(index, node) {\n if (typeof node !== 'object') {\n return;\n }\n\n var li = $('');\n var p = $('');\n var id = node.id || node.key + '_tree_item';\n var icon = null;\n var isBranch = (node.expandable || node.haschildren) ? true : false;\n\n li.attr('role', 'treeitem');\n p.addClass('tree_item');\n p.attr('id', id);\n // Negative tab index to allow it to receive focus.\n p.attr('tabindex', '-1');\n\n if (node.requiresajaxloading) {\n li.attr('data-requires-ajax', true);\n li.attr('data-node-id', node.id);\n li.attr('data-node-key', node.key);\n li.attr('data-node-type', node.type);\n }\n\n if (isBranch) {\n li.addClass('collapsed contains_branch');\n li.attr('aria-expanded', false);\n p.addClass('branch');\n }\n\n var eleToAddIcon = null;\n if (node.link) {\n var link = $('');\n\n eleToAddIcon = link;\n link.append('' + node.name + '');\n\n if (node.hidden) {\n link.addClass('dimmed');\n }\n\n p.append(link);\n } else {\n var span = $('');\n\n eleToAddIcon = span;\n span.append('' + node.name + '');\n\n if (node.hidden) {\n span.addClass('dimmed');\n }\n\n p.append(span);\n }\n\n if (node.icon && (!isBranch || node.type === NODETYPE.ACTIVITY || node.type === NODETYPE.RESOURCE)) {\n li.addClass('item_with_icon');\n p.addClass('hasicon');\n\n if (node.type === NODETYPE.ACTIVITY || node.type === NODETYPE.RESOURCE) {\n icon = $('');\n icon.attr('alt', node.icon.alt);\n icon.attr('title', node.icon.title);\n icon.attr('src', Url.imageUrl(node.icon.pix, node.icon.component));\n $.each(node.icon.classes, function(index, className) {\n icon.addClass(className);\n });\n eleToAddIcon.prepend(icon);\n } else {\n if (node.icon.component == 'moodle') {\n node.icon.component = 'core';\n }\n Templates.renderPix(node.icon.pix, node.icon.component, node.icon.title).then(function(html) {\n // Prepend.\n eleToAddIcon.prepend(html);\n return;\n }).catch(Notification.exception);\n }\n }\n\n li.append(p);\n ul.append(li);\n\n if (node.children && node.children.length) {\n buildDOM(li, node.children);\n } else if (isBranch && !node.requiresajaxloading) {\n li.removeClass('contains_branch');\n p.addClass('emptybranch');\n }\n });\n\n rootElement.append(ul);\n var id = rootElement.attr('id') + '_group';\n ul.attr('id', id);\n rootElement.attr('aria-owns', id);\n rootElement.attr('role', 'treeitem');\n }\n\n return {\n render: function(element, nodes) {\n // The first element of the response is the existing node so we start with processing the children.\n if (nodes.children && nodes.children.length) {\n buildDOM(element, nodes.children);\n\n var item = element.children(\"[role='treeitem']\").first();\n var group = element.find('#' + item.attr('aria-owns'));\n\n item.attr('aria-expanded', true);\n Aria.unhide(group);\n } else {\n if (element.hasClass('contains_branch')) {\n element.removeClass('contains_branch');\n element.addClass('emptybranch');\n }\n }\n }\n };\n});\n"],"names":["define","$","Templates","Notification","Url","Aria","NODETYPE","buildDOM","rootElement","nodes","ul","attr","hide","each","index","node","li","p","id","key","icon","isBranch","expandable","haschildren","addClass","requiresajaxloading","type","eleToAddIcon","link","title","append","name","hidden","span","alt","imageUrl","pix","component","classes","className","prepend","renderPix","then","html","catch","exception","children","length","removeClass","render","element","item","first","group","find","unhide","hasClass"],"mappings":"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"}
\ No newline at end of file
diff --git a/blocks/navigation/amd/build/nav_loader.min.js b/blocks/navigation/amd/build/nav_loader.min.js
index 444e8543969..40cd9aea60f 100644
--- a/blocks/navigation/amd/build/nav_loader.min.js
+++ b/blocks/navigation/amd/build/nav_loader.min.js
@@ -1,2 +1,10 @@
-define ("block_navigation/nav_loader",["jquery","core/ajax","core/config","block_navigation/ajax_response_renderer"],function(a,b,c,d){var f=c.wwwroot+"/lib/ajax/getnavbranch.php";function e(a){return a.closest("[data-block]").attr("data-instanceid")}return{load:function load(b){b=a(b);var g=a.Deferred(),h={elementid:b.attr("data-node-id"),id:b.attr("data-node-key"),type:b.attr("data-node-type"),sesskey:c.sesskey,instance:e(b)};a.ajax(f,{type:"POST",dataType:"json",data:h}).done(function(a){d.render(b,a);g.resolve()});return g}}});
-//# sourceMappingURL=nav_loader.min.js.map
+/**
+ * Load the nav tree items via ajax and render the response.
+ *
+ * @module block_navigation/nav_loader
+ * @copyright 2015 John Okely
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_navigation/nav_loader",["jquery","core/ajax","core/config","block_navigation/ajax_response_renderer"],(function($,ajax,config,renderer){var URL=config.wwwroot+"/lib/ajax/getnavbranch.php";function getBlockInstanceId(element){return element.closest("[data-block]").attr("data-instanceid")}return{load:function(element){element=$(element);var promise=$.Deferred(),settings={type:"POST",dataType:"json",data:{elementid:element.attr("data-node-id"),id:element.attr("data-node-key"),type:element.attr("data-node-type"),sesskey:config.sesskey,instance:getBlockInstanceId(element)}};return $.ajax(URL,settings).done((function(nodes){renderer.render(element,nodes),promise.resolve()})),promise}}}));
+
+//# sourceMappingURL=nav_loader.min.js.map
\ No newline at end of file
diff --git a/blocks/navigation/amd/build/nav_loader.min.js.map b/blocks/navigation/amd/build/nav_loader.min.js.map
index 31fc53da1b1..e53f935caea 100644
--- a/blocks/navigation/amd/build/nav_loader.min.js.map
+++ b/blocks/navigation/amd/build/nav_loader.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/nav_loader.js"],"names":["define","$","ajax","config","renderer","URL","wwwroot","getBlockInstanceId","element","closest","attr","load","promise","Deferred","data","elementid","id","type","sesskey","instance","dataType","done","nodes","render","resolve"],"mappings":"AAsBAA,OAAM,+BAAC,CAAC,QAAD,CAAW,WAAX,CAAwB,aAAxB,CAAuC,yCAAvC,CAAD,CACF,SAASC,CAAT,CAAYC,CAAZ,CAAkBC,CAAlB,CAA0BC,CAA1B,CAAoC,CAChC,GAAIC,CAAAA,CAAG,CAAGF,CAAM,CAACG,OAAP,CAAiB,4BAA3B,CASA,QAASC,CAAAA,CAAT,CAA4BC,CAA5B,CAAqC,CACjC,MAAOA,CAAAA,CAAO,CAACC,OAAR,CAAgB,cAAhB,EAAgCC,IAAhC,CAAqC,iBAArC,CACV,CAEL,MAAO,CACHC,IAAI,CAAE,cAASH,CAAT,CAAkB,CACpBA,CAAO,CAAGP,CAAC,CAACO,CAAD,CAAX,CADoB,GAEhBI,CAAAA,CAAO,CAAGX,CAAC,CAACY,QAAF,EAFM,CAGhBC,CAAI,CAAG,CACPC,SAAS,CAAEP,CAAO,CAACE,IAAR,CAAa,cAAb,CADJ,CAEPM,EAAE,CAAER,CAAO,CAACE,IAAR,CAAa,eAAb,CAFG,CAGPO,IAAI,CAAET,CAAO,CAACE,IAAR,CAAa,gBAAb,CAHC,CAIPQ,OAAO,CAAEf,CAAM,CAACe,OAJT,CAKPC,QAAQ,CAAEZ,CAAkB,CAACC,CAAD,CALrB,CAHS,CAgBpBP,CAAC,CAACC,IAAF,CAAOG,CAAP,CANe,CACXY,IAAI,CAAE,MADK,CAEXG,QAAQ,CAAE,MAFC,CAGXN,IAAI,CAAEA,CAHK,CAMf,EAAsBO,IAAtB,CAA2B,SAASC,CAAT,CAAgB,CACvClB,CAAQ,CAACmB,MAAT,CAAgBf,CAAhB,CAAyBc,CAAzB,EACAV,CAAO,CAACY,OAAR,EACH,CAHD,EAKA,MAAOZ,CAAAA,CACV,CAvBE,CAyBV,CAxCK,CAAN","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 .\n\n/**\n * Load the nav tree items via ajax and render the response.\n *\n * @module block_navigation/nav_loader\n * @copyright 2015 John Okely \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/config', 'block_navigation/ajax_response_renderer'],\n function($, ajax, config, renderer) {\n var URL = config.wwwroot + '/lib/ajax/getnavbranch.php';\n\n /**\n * Get the block instance id.\n *\n * @function getBlockInstanceId\n * @param {Element} element\n * @returns {String} the instance id\n */\n function getBlockInstanceId(element) {\n return element.closest('[data-block]').attr('data-instanceid');\n }\n\n return {\n load: function(element) {\n element = $(element);\n var promise = $.Deferred();\n var data = {\n elementid: element.attr('data-node-id'),\n id: element.attr('data-node-key'),\n type: element.attr('data-node-type'),\n sesskey: config.sesskey,\n instance: getBlockInstanceId(element)\n };\n var settings = {\n type: 'POST',\n dataType: 'json',\n data: data\n };\n\n $.ajax(URL, settings).done(function(nodes) {\n renderer.render(element, nodes);\n promise.resolve();\n });\n\n return promise;\n }\n };\n});\n"],"file":"nav_loader.min.js"}
\ No newline at end of file
+{"version":3,"file":"nav_loader.min.js","sources":["../src/nav_loader.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 .\n\n/**\n * Load the nav tree items via ajax and render the response.\n *\n * @module block_navigation/nav_loader\n * @copyright 2015 John Okely \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/config', 'block_navigation/ajax_response_renderer'],\n function($, ajax, config, renderer) {\n var URL = config.wwwroot + '/lib/ajax/getnavbranch.php';\n\n /**\n * Get the block instance id.\n *\n * @function getBlockInstanceId\n * @param {Element} element\n * @returns {String} the instance id\n */\n function getBlockInstanceId(element) {\n return element.closest('[data-block]').attr('data-instanceid');\n }\n\n return {\n load: function(element) {\n element = $(element);\n var promise = $.Deferred();\n var data = {\n elementid: element.attr('data-node-id'),\n id: element.attr('data-node-key'),\n type: element.attr('data-node-type'),\n sesskey: config.sesskey,\n instance: getBlockInstanceId(element)\n };\n var settings = {\n type: 'POST',\n dataType: 'json',\n data: data\n };\n\n $.ajax(URL, settings).done(function(nodes) {\n renderer.render(element, nodes);\n promise.resolve();\n });\n\n return promise;\n }\n };\n});\n"],"names":["define","$","ajax","config","renderer","URL","wwwroot","getBlockInstanceId","element","closest","attr","load","promise","Deferred","settings","type","dataType","data","elementid","id","sesskey","instance","done","nodes","render","resolve"],"mappings":";;;;;;;AAsBAA,qCAAO,CAAC,SAAU,YAAa,cAAe,4CAC1C,SAASC,EAAGC,KAAMC,OAAQC,cAClBC,IAAMF,OAAOG,QAAU,sCASlBC,mBAAmBC,gBACjBA,QAAQC,QAAQ,gBAAgBC,KAAK,yBAG7C,CACHC,KAAM,SAASH,SACXA,QAAUP,EAAEO,aACRI,QAAUX,EAAEY,WAQZC,SAAW,CACXC,KAAM,OACNC,SAAU,OACVC,KAVO,CACPC,UAAWV,QAAQE,KAAK,gBACxBS,GAAIX,QAAQE,KAAK,iBACjBK,KAAMP,QAAQE,KAAK,kBACnBU,QAASjB,OAAOiB,QAChBC,SAAUd,mBAAmBC,kBAQjCP,EAAEC,KAAKG,IAAKS,UAAUQ,MAAK,SAASC,OAChCnB,SAASoB,OAAOhB,QAASe,OACzBX,QAAQa,aAGLb"}
\ No newline at end of file
diff --git a/blocks/navigation/amd/build/navblock.min.js b/blocks/navigation/amd/build/navblock.min.js
index 040e89a1c37..2a1c8625227 100644
--- a/blocks/navigation/amd/build/navblock.min.js
+++ b/blocks/navigation/amd/build/navblock.min.js
@@ -1,2 +1,10 @@
-define ("block_navigation/navblock",["exports","core_block/events","core/tree"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;c=function(a){return a&&a.__esModule?a:{default:a}}(c);var d=function(a){var d=new c.default(".block_navigation .block_tree"),e=document.querySelector("[data-instance-id=\"".concat(a,"\"]"));d.finishExpandingGroup=function(a){c.default.prototype.finishExpandingGroup.call(d,a);(0,b.notifyBlockContentUpdated)(e)};d.collapseGroup=function(a){c.default.prototype.collapseGroup.call(d,a);(0,b.notifyBlockContentUpdated)(e)}};a.init=d});
-//# sourceMappingURL=navblock.min.js.map
+define("block_navigation/navblock",["exports","core_block/events","core/tree"],(function(_exports,_events,_tree){var obj;
+/**
+ * Load the navigation tree javascript.
+ *
+ * @module block_navigation/navblock
+ * @copyright 2015 John Okely
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_tree=(obj=_tree)&&obj.__esModule?obj:{default:obj};_exports.init=instanceId=>{const navTree=new _tree.default(".block_navigation .block_tree"),blockNode=document.querySelector('[data-instance-id="'.concat(instanceId,'"]'));navTree.finishExpandingGroup=item=>{_tree.default.prototype.finishExpandingGroup.call(navTree,item),(0,_events.notifyBlockContentUpdated)(blockNode)},navTree.collapseGroup=item=>{_tree.default.prototype.collapseGroup.call(navTree,item),(0,_events.notifyBlockContentUpdated)(blockNode)}}}));
+
+//# sourceMappingURL=navblock.min.js.map
\ No newline at end of file
diff --git a/blocks/navigation/amd/build/navblock.min.js.map b/blocks/navigation/amd/build/navblock.min.js.map
index 9f743e82454..1f963812e7a 100644
--- a/blocks/navigation/amd/build/navblock.min.js.map
+++ b/blocks/navigation/amd/build/navblock.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/navblock.js"],"names":["init","instanceId","navTree","Tree","blockNode","document","querySelector","finishExpandingGroup","item","prototype","call","collapseGroup"],"mappings":"4KAuBA,uDAQO,GAAMA,CAAAA,CAAI,CAAG,SAAAC,CAAU,CAAI,IACxBC,CAAAA,CAAO,CAAG,GAAIC,UAAJ,CAAS,+BAAT,CADc,CAExBC,CAAS,CAAGC,QAAQ,CAACC,aAAT,+BAA6CL,CAA7C,QAFY,CAW9BC,CAAO,CAACK,oBAAR,CAA+B,SAAAC,CAAI,CAAI,CACnCL,UAAKM,SAAL,CAAeF,oBAAf,CAAoCG,IAApC,CAAyCR,CAAzC,CAAkDM,CAAlD,EACA,gCAA0BJ,CAA1B,CACH,CAHD,CAYAF,CAAO,CAACS,aAAR,CAAwB,SAAAH,CAAI,CAAI,CAC5BL,UAAKM,SAAL,CAAeE,aAAf,CAA6BD,IAA7B,CAAkCR,CAAlC,CAA2CM,CAA3C,EACA,gCAA0BJ,CAA1B,CACH,CACJ,CA3BM,C","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 .\n\n/**\n * Load the navigation tree javascript.\n *\n * @module block_navigation/navblock\n * @copyright 2015 John Okely \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {notifyBlockContentUpdated} from 'core_block/events';\nimport Tree from 'core/tree';\n\n/**\n * Initialise the navblock javascript for the specified block instance.\n *\n * @method\n * @param {Number} instanceId\n */\nexport const init = instanceId => {\n const navTree = new Tree(\".block_navigation .block_tree\");\n const blockNode = document.querySelector(`[data-instance-id=\"${instanceId}\"]`);\n\n /**\n * The method to call when then the navtree finishes expanding a group.\n *\n * @method finishExpandingGroup\n * @param {Object} item\n * @fires event:blockContentUpdated\n */\n navTree.finishExpandingGroup = item => {\n Tree.prototype.finishExpandingGroup.call(navTree, item);\n notifyBlockContentUpdated(blockNode);\n };\n\n /**\n * The method to call whe then the navtree collapses a group\n *\n * @method collapseGroup\n * @param {Object} item\n * @fires event:blockContentUpdated\n */\n navTree.collapseGroup = item => {\n Tree.prototype.collapseGroup.call(navTree, item);\n notifyBlockContentUpdated(blockNode);\n };\n};\n"],"file":"navblock.min.js"}
\ No newline at end of file
+{"version":3,"file":"navblock.min.js","sources":["../src/navblock.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 .\n\n/**\n * Load the navigation tree javascript.\n *\n * @module block_navigation/navblock\n * @copyright 2015 John Okely \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {notifyBlockContentUpdated} from 'core_block/events';\nimport Tree from 'core/tree';\n\n/**\n * Initialise the navblock javascript for the specified block instance.\n *\n * @method\n * @param {Number} instanceId\n */\nexport const init = instanceId => {\n const navTree = new Tree(\".block_navigation .block_tree\");\n const blockNode = document.querySelector(`[data-instance-id=\"${instanceId}\"]`);\n\n /**\n * The method to call when then the navtree finishes expanding a group.\n *\n * @method finishExpandingGroup\n * @param {Object} item\n * @fires event:blockContentUpdated\n */\n navTree.finishExpandingGroup = item => {\n Tree.prototype.finishExpandingGroup.call(navTree, item);\n notifyBlockContentUpdated(blockNode);\n };\n\n /**\n * The method to call whe then the navtree collapses a group\n *\n * @method collapseGroup\n * @param {Object} item\n * @fires event:blockContentUpdated\n */\n navTree.collapseGroup = item => {\n Tree.prototype.collapseGroup.call(navTree, item);\n notifyBlockContentUpdated(blockNode);\n };\n};\n"],"names":["instanceId","navTree","Tree","blockNode","document","querySelector","finishExpandingGroup","item","prototype","call","collapseGroup"],"mappings":";;;;;;;oJA+BoBA,mBACVC,QAAU,IAAIC,cAAK,iCACnBC,UAAYC,SAASC,2CAAoCL,kBAS/DC,QAAQK,qBAAuBC,qBACtBC,UAAUF,qBAAqBG,KAAKR,QAASM,4CACxBJ,YAU9BF,QAAQS,cAAgBH,qBACfC,UAAUE,cAAcD,KAAKR,QAASM,4CACjBJ"}
\ No newline at end of file
diff --git a/blocks/navigation/amd/build/site_admin_loader.min.js b/blocks/navigation/amd/build/site_admin_loader.min.js
index a1ee89786e0..c1dc390b701 100644
--- a/blocks/navigation/amd/build/site_admin_loader.min.js
+++ b/blocks/navigation/amd/build/site_admin_loader.min.js
@@ -1,2 +1,10 @@
-define ("block_navigation/site_admin_loader",["jquery","core/ajax","core/config","block_navigation/ajax_response_renderer"],function(a,b,c,d){var e=c.wwwroot+"/lib/ajax/getsiteadminbranch.php";return{load:function load(b){b=a(b);var f=a.Deferred(),g={type:71,sesskey:c.sesskey};a.ajax(e,{type:"POST",dataType:"json",data:g}).done(function(a){d.render(b,a);f.resolve()});return f}}});
-//# sourceMappingURL=site_admin_loader.min.js.map
+/**
+ * Load the site admin nav tree via ajax and render the response.
+ *
+ * @module block_navigation/site_admin_loader
+ * @copyright 2015 John Okely
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_navigation/site_admin_loader",["jquery","core/ajax","core/config","block_navigation/ajax_response_renderer"],(function($,ajax,config,renderer){var URL=config.wwwroot+"/lib/ajax/getsiteadminbranch.php";return{load:function(element){element=$(element);var promise=$.Deferred(),settings={type:"POST",dataType:"json",data:{type:71,sesskey:config.sesskey}};return $.ajax(URL,settings).done((function(nodes){renderer.render(element,nodes),promise.resolve()})),promise}}}));
+
+//# sourceMappingURL=site_admin_loader.min.js.map
\ No newline at end of file
diff --git a/blocks/navigation/amd/build/site_admin_loader.min.js.map b/blocks/navigation/amd/build/site_admin_loader.min.js.map
index 61216fb9cd3..4eecd6aaf71 100644
--- a/blocks/navigation/amd/build/site_admin_loader.min.js.map
+++ b/blocks/navigation/amd/build/site_admin_loader.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/site_admin_loader.js"],"names":["define","$","ajax","config","renderer","URL","wwwroot","load","element","promise","Deferred","data","type","sesskey","dataType","done","nodes","render","resolve"],"mappings":"AAsBAA,OAAM,sCAAC,CAAC,QAAD,CAAW,WAAX,CAAwB,aAAxB,CAAuC,yCAAvC,CAAD,CACE,SAASC,CAAT,CAAYC,CAAZ,CAAkBC,CAAlB,CAA0BC,CAA1B,CAAoC,IAGpCC,CAAAA,CAAG,CAAGF,CAAM,CAACG,OAAP,CAAiB,kCAHa,CAKxC,MAAO,CACHC,IAAI,CAAE,cAASC,CAAT,CAAkB,CACpBA,CAAO,CAAGP,CAAC,CAACO,CAAD,CAAX,CADoB,GAEhBC,CAAAA,CAAO,CAAGR,CAAC,CAACS,QAAF,EAFM,CAGhBC,CAAI,CAAG,CACPC,IAAI,GADG,CAEPC,OAAO,CAAEV,CAAM,CAACU,OAFT,CAHS,CAapBZ,CAAC,CAACC,IAAF,CAAOG,CAAP,CANe,CACXO,IAAI,CAAE,MADK,CAEXE,QAAQ,CAAE,MAFC,CAGXH,IAAI,CAAEA,CAHK,CAMf,EAAsBI,IAAtB,CAA2B,SAASC,CAAT,CAAgB,CACvCZ,CAAQ,CAACa,MAAT,CAAgBT,CAAhB,CAAyBQ,CAAzB,EACAP,CAAO,CAACS,OAAR,EACH,CAHD,EAKA,MAAOT,CAAAA,CACV,CApBE,CAsBV,CA5BK,CAAN","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 .\n\n/**\n * Load the site admin nav tree via ajax and render the response.\n *\n * @module block_navigation/site_admin_loader\n * @copyright 2015 John Okely \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/config', 'block_navigation/ajax_response_renderer'],\n function($, ajax, config, renderer) {\n\n var SITE_ADMIN_NODE_TYPE = 71;\n var URL = config.wwwroot + '/lib/ajax/getsiteadminbranch.php';\n\n return {\n load: function(element) {\n element = $(element);\n var promise = $.Deferred();\n var data = {\n type: SITE_ADMIN_NODE_TYPE,\n sesskey: config.sesskey\n };\n var settings = {\n type: 'POST',\n dataType: 'json',\n data: data\n };\n\n $.ajax(URL, settings).done(function(nodes) {\n renderer.render(element, nodes);\n promise.resolve();\n });\n\n return promise;\n }\n };\n});\n"],"file":"site_admin_loader.min.js"}
\ No newline at end of file
+{"version":3,"file":"site_admin_loader.min.js","sources":["../src/site_admin_loader.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 .\n\n/**\n * Load the site admin nav tree via ajax and render the response.\n *\n * @module block_navigation/site_admin_loader\n * @copyright 2015 John Okely \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/config', 'block_navigation/ajax_response_renderer'],\n function($, ajax, config, renderer) {\n\n var SITE_ADMIN_NODE_TYPE = 71;\n var URL = config.wwwroot + '/lib/ajax/getsiteadminbranch.php';\n\n return {\n load: function(element) {\n element = $(element);\n var promise = $.Deferred();\n var data = {\n type: SITE_ADMIN_NODE_TYPE,\n sesskey: config.sesskey\n };\n var settings = {\n type: 'POST',\n dataType: 'json',\n data: data\n };\n\n $.ajax(URL, settings).done(function(nodes) {\n renderer.render(element, nodes);\n promise.resolve();\n });\n\n return promise;\n }\n };\n});\n"],"names":["define","$","ajax","config","renderer","URL","wwwroot","load","element","promise","Deferred","settings","type","dataType","data","sesskey","done","nodes","render","resolve"],"mappings":";;;;;;;AAsBAA,4CAAO,CAAC,SAAU,YAAa,cAAe,4CACtC,SAASC,EAAGC,KAAMC,OAAQC,cAG1BC,IAAMF,OAAOG,QAAU,yCAEpB,CACHC,KAAM,SAASC,SACXA,QAAUP,EAAEO,aACRC,QAAUR,EAAES,WAKZC,SAAW,CACXC,KAAM,OACNC,SAAU,OACVC,KAPO,CACPF,KARe,GASfG,QAASZ,OAAOY,iBAQpBd,EAAEC,KAAKG,IAAKM,UAAUK,MAAK,SAASC,OAChCb,SAASc,OAAOV,QAASS,OACzBR,QAAQU,aAGLV"}
\ No newline at end of file
diff --git a/blocks/online_users/amd/build/change_user_visibility.min.js b/blocks/online_users/amd/build/change_user_visibility.min.js
index c80c6e45117..4a00a330256 100644
--- a/blocks/online_users/amd/build/change_user_visibility.min.js
+++ b/blocks/online_users/amd/build/change_user_visibility.min.js
@@ -1,2 +1,11 @@
-define ("block_online_users/change_user_visibility",["jquery","core/ajax","core/str","core/notification"],function(a,b,c,d){var e={CHANGE_VISIBILITY_LINK:"#change-user-visibility",CHANGE_VISIBILITY_ICON:"#change-user-visibility .icon"},f=function(a,c){var e="show"==a?1:0;b.call([{methodname:"core_user_set_user_preferences",args:{preferences:[{name:"block_online_users_uservisibility",value:e,userid:c}]}}])[0].then(function(b){if(b.saved){var c=g(a);h(c);i(c)}}).catch(d.exception)},g=function(a){return"show"==a?"hide":"show"},h=function(b){k(b).then(function(c){a(e.CHANGE_VISIBILITY_LINK).attr({"data-action":b,title:c})}).catch(d.exception)},i=function(b){var c=a(e.CHANGE_VISIBILITY_ICON);k(b).then(function(d){a(c).attr({title:d,"aria-label":d});if(c.is("img")){a(c).attr({src:M.util.image_url("t/"+b),alt:d})}else{a(c).addClass(j(b));a(c).removeClass(j(g(b)))}}).catch(d.exception)},j=function(a){return"show"==a?"fa-eye-slash":"fa-eye"},k=function(a){return c.get_string("online_status:"+a,"block_online_users")};return{init:function init(){a(e.CHANGE_VISIBILITY_LINK).on("click",function(b){b.preventDefault();var c=a(this).attr("data-action"),d=a(this).attr("data-userid");f(c,d)})}}});
-//# sourceMappingURL=change_user_visibility.min.js.map
+/**
+ * A javascript module that handles the change of the user's visibility in the
+ * online users block.
+ *
+ * @module block_online_users/change_user_visibility
+ * @copyright 2018 Mihail Geshoski
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_online_users/change_user_visibility",["jquery","core/ajax","core/str","core/notification"],(function($,Ajax,Str,Notification){var SELECTORS_CHANGE_VISIBILITY_LINK="#change-user-visibility",SELECTORS_CHANGE_VISIBILITY_ICON="#change-user-visibility .icon",oppositeAction=function(action){return"show"==action?"hide":"show"},changeVisibilityLinkAttr=function(action){getTitle(action).then((function(title){$(SELECTORS_CHANGE_VISIBILITY_LINK).attr({"data-action":action,title:title})})).catch(Notification.exception)},changeVisibilityIconAttr=function(action){var icon=$(SELECTORS_CHANGE_VISIBILITY_ICON);getTitle(action).then((function(title){$(icon).attr({title:title,"aria-label":title}),icon.is("img")?$(icon).attr({src:M.util.image_url("t/"+action),alt:title}):($(icon).addClass(getIconClass(action)),$(icon).removeClass(getIconClass(oppositeAction(action))))})).catch(Notification.exception)},getIconClass=function(action){return"show"==action?"fa-eye-slash":"fa-eye"},getTitle=function(action){return Str.get_string("online_status:"+action,"block_online_users")};return{init:function(){$(SELECTORS_CHANGE_VISIBILITY_LINK).on("click",(function(e){e.preventDefault(),function(action,userid){var request={methodname:"core_user_set_user_preferences",args:{preferences:[{name:"block_online_users_uservisibility",value:"show"==action?1:0,userid:userid}]}};Ajax.call([request])[0].then((function(data){if(data.saved){var newAction=oppositeAction(action);changeVisibilityLinkAttr(newAction),changeVisibilityIconAttr(newAction)}})).catch(Notification.exception)}($(this).attr("data-action"),$(this).attr("data-userid"))}))}}}));
+
+//# sourceMappingURL=change_user_visibility.min.js.map
\ No newline at end of file
diff --git a/blocks/online_users/amd/build/change_user_visibility.min.js.map b/blocks/online_users/amd/build/change_user_visibility.min.js.map
index 757879b7f26..683db00dfa2 100644
--- a/blocks/online_users/amd/build/change_user_visibility.min.js.map
+++ b/blocks/online_users/amd/build/change_user_visibility.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/change_user_visibility.js"],"names":["define","$","Ajax","Str","Notification","SELECTORS","CHANGE_VISIBILITY_LINK","CHANGE_VISIBILITY_ICON","changeVisibility","action","userid","value","call","methodname","args","preferences","then","data","saved","newAction","oppositeAction","changeVisibilityLinkAttr","changeVisibilityIconAttr","catch","exception","getTitle","title","attr","icon","is","M","util","image_url","addClass","getIconClass","removeClass","get_string","init","on","e","preventDefault"],"mappings":"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","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 .\n\n/**\n * A javascript module that handles the change of the user's visibility in the\n * online users block.\n *\n * @module block_online_users/change_user_visibility\n * @copyright 2018 Mihail Geshoski \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/str', 'core/notification'],\n function($, Ajax, Str, Notification) {\n\n /**\n * Selectors.\n *\n * @access private\n * @type {Object}\n */\n var SELECTORS = {\n CHANGE_VISIBILITY_LINK: '#change-user-visibility',\n CHANGE_VISIBILITY_ICON: '#change-user-visibility .icon'\n };\n\n /**\n * Change user visibility in the online users block.\n *\n * @method changeVisibility\n * @param {String} action\n * @param {String} userid\n * @private\n */\n var changeVisibility = function(action, userid) {\n\n var value = action == \"show\" ? 1 : 0;\n var preferences = [{\n 'name': 'block_online_users_uservisibility',\n 'value': value,\n 'userid': userid\n }];\n\n var request = {\n methodname: 'core_user_set_user_preferences',\n args: {\n preferences: preferences\n }\n };\n Ajax.call([request])[0].then(function(data) {\n if (data.saved) {\n var newAction = oppositeAction(action);\n changeVisibilityLinkAttr(newAction);\n changeVisibilityIconAttr(newAction);\n }\n return;\n }).catch(Notification.exception);\n };\n\n /**\n * Get the opposite action.\n *\n * @method oppositeAction\n * @param {String} action\n * @return {String}\n * @private\n */\n var oppositeAction = function(action) {\n return action == 'show' ? 'hide' : 'show';\n };\n\n /**\n * Change the attribute values of the user visibility link in the online users block.\n *\n * @method changeVisibilityLinkAttr\n * @param {String} action\n * @private\n */\n var changeVisibilityLinkAttr = function(action) {\n getTitle(action).then(function(title) {\n $(SELECTORS.CHANGE_VISIBILITY_LINK).attr({\n 'data-action': action,\n 'title': title\n });\n return;\n }).catch(Notification.exception);\n };\n\n /**\n * Change the attribute values of the user visibility icon in the online users block.\n *\n * @method changeVisibilityIconAttr\n * @param {String} action\n * @private\n */\n var changeVisibilityIconAttr = function(action) {\n var icon = $(SELECTORS.CHANGE_VISIBILITY_ICON);\n getTitle(action).then(function(title) {\n // Add the proper title to the icon.\n $(icon).attr({\n 'title': title,\n 'aria-label': title\n });\n // If the icon is an image.\n if (icon.is(\"img\")) {\n $(icon).attr({\n 'src': M.util.image_url('t/' + action),\n 'alt': title\n });\n } else {\n // Add the new icon class and remove the old one.\n $(icon).addClass(getIconClass(action));\n $(icon).removeClass(getIconClass(oppositeAction(action)));\n }\n return;\n }).catch(Notification.exception);\n };\n\n /**\n * Get the proper class for the user visibility icon in the online users block.\n *\n * @method getIconClass\n * @param {String} action\n * @return {String}\n * @private\n */\n var getIconClass = function(action) {\n return action == 'show' ? 'fa-eye-slash' : 'fa-eye';\n };\n\n /**\n * Get the title description of the user visibility link in the online users block.\n *\n * @method getTitle\n * @param {String} action\n * @return {object} jQuery promise\n * @private\n */\n var getTitle = function(action) {\n return Str.get_string('online_status:' + action, 'block_online_users');\n };\n\n return {\n // Public variables and functions.\n /**\n * Initialise change user visibility function.\n *\n * @method init\n */\n init: function() {\n $(SELECTORS.CHANGE_VISIBILITY_LINK).on('click', function(e) {\n e.preventDefault();\n var action = ($(this).attr('data-action'));\n var userid = ($(this).attr('data-userid'));\n changeVisibility(action, userid);\n });\n }\n };\n});\n"],"file":"change_user_visibility.min.js"}
\ No newline at end of file
+{"version":3,"file":"change_user_visibility.min.js","sources":["../src/change_user_visibility.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 .\n\n/**\n * A javascript module that handles the change of the user's visibility in the\n * online users block.\n *\n * @module block_online_users/change_user_visibility\n * @copyright 2018 Mihail Geshoski \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/str', 'core/notification'],\n function($, Ajax, Str, Notification) {\n\n /**\n * Selectors.\n *\n * @access private\n * @type {Object}\n */\n var SELECTORS = {\n CHANGE_VISIBILITY_LINK: '#change-user-visibility',\n CHANGE_VISIBILITY_ICON: '#change-user-visibility .icon'\n };\n\n /**\n * Change user visibility in the online users block.\n *\n * @method changeVisibility\n * @param {String} action\n * @param {String} userid\n * @private\n */\n var changeVisibility = function(action, userid) {\n\n var value = action == \"show\" ? 1 : 0;\n var preferences = [{\n 'name': 'block_online_users_uservisibility',\n 'value': value,\n 'userid': userid\n }];\n\n var request = {\n methodname: 'core_user_set_user_preferences',\n args: {\n preferences: preferences\n }\n };\n Ajax.call([request])[0].then(function(data) {\n if (data.saved) {\n var newAction = oppositeAction(action);\n changeVisibilityLinkAttr(newAction);\n changeVisibilityIconAttr(newAction);\n }\n return;\n }).catch(Notification.exception);\n };\n\n /**\n * Get the opposite action.\n *\n * @method oppositeAction\n * @param {String} action\n * @return {String}\n * @private\n */\n var oppositeAction = function(action) {\n return action == 'show' ? 'hide' : 'show';\n };\n\n /**\n * Change the attribute values of the user visibility link in the online users block.\n *\n * @method changeVisibilityLinkAttr\n * @param {String} action\n * @private\n */\n var changeVisibilityLinkAttr = function(action) {\n getTitle(action).then(function(title) {\n $(SELECTORS.CHANGE_VISIBILITY_LINK).attr({\n 'data-action': action,\n 'title': title\n });\n return;\n }).catch(Notification.exception);\n };\n\n /**\n * Change the attribute values of the user visibility icon in the online users block.\n *\n * @method changeVisibilityIconAttr\n * @param {String} action\n * @private\n */\n var changeVisibilityIconAttr = function(action) {\n var icon = $(SELECTORS.CHANGE_VISIBILITY_ICON);\n getTitle(action).then(function(title) {\n // Add the proper title to the icon.\n $(icon).attr({\n 'title': title,\n 'aria-label': title\n });\n // If the icon is an image.\n if (icon.is(\"img\")) {\n $(icon).attr({\n 'src': M.util.image_url('t/' + action),\n 'alt': title\n });\n } else {\n // Add the new icon class and remove the old one.\n $(icon).addClass(getIconClass(action));\n $(icon).removeClass(getIconClass(oppositeAction(action)));\n }\n return;\n }).catch(Notification.exception);\n };\n\n /**\n * Get the proper class for the user visibility icon in the online users block.\n *\n * @method getIconClass\n * @param {String} action\n * @return {String}\n * @private\n */\n var getIconClass = function(action) {\n return action == 'show' ? 'fa-eye-slash' : 'fa-eye';\n };\n\n /**\n * Get the title description of the user visibility link in the online users block.\n *\n * @method getTitle\n * @param {String} action\n * @return {object} jQuery promise\n * @private\n */\n var getTitle = function(action) {\n return Str.get_string('online_status:' + action, 'block_online_users');\n };\n\n return {\n // Public variables and functions.\n /**\n * Initialise change user visibility function.\n *\n * @method init\n */\n init: function() {\n $(SELECTORS.CHANGE_VISIBILITY_LINK).on('click', function(e) {\n e.preventDefault();\n var action = ($(this).attr('data-action'));\n var userid = ($(this).attr('data-userid'));\n changeVisibility(action, userid);\n });\n }\n };\n});\n"],"names":["define","$","Ajax","Str","Notification","SELECTORS","oppositeAction","action","changeVisibilityLinkAttr","getTitle","then","title","attr","catch","exception","changeVisibilityIconAttr","icon","is","M","util","image_url","addClass","getIconClass","removeClass","get_string","init","on","e","preventDefault","userid","request","methodname","args","preferences","call","data","saved","newAction","changeVisibility","this"],"mappings":";;;;;;;;AAuBAA,mDAAO,CAAC,SAAU,YAAa,WAAY,sBACnC,SAASC,EAAGC,KAAMC,IAAKC,kBAQvBC,iCACwB,0BADxBA,iCAEwB,gCA4CxBC,eAAiB,SAASC,cACT,QAAVA,OAAmB,OAAS,QAUnCC,yBAA2B,SAASD,QACpCE,SAASF,QAAQG,MAAK,SAASC,OAC3BV,EAAEI,kCAAkCO,KAAK,eACtBL,aACNI,WAGdE,MAAMT,aAAaU,YAUtBC,yBAA2B,SAASR,YAChCS,KAAOf,EAAEI,kCACbI,SAASF,QAAQG,MAAK,SAASC,OAE3BV,EAAEe,MAAMJ,KAAK,OACAD,mBACKA,QAGdK,KAAKC,GAAG,OACRhB,EAAEe,MAAMJ,KAAK,KACFM,EAAEC,KAAKC,UAAU,KAAOb,YACxBI,SAIXV,EAAEe,MAAMK,SAASC,aAAaf,SAC9BN,EAAEe,MAAMO,YAAYD,aAAahB,eAAeC,cAGrDM,MAAMT,aAAaU,YAWtBQ,aAAe,SAASf,cACP,QAAVA,OAAmB,eAAiB,UAW3CE,SAAW,SAASF,eACbJ,IAAIqB,WAAW,iBAAmBjB,OAAQ,6BAG9C,CAOHkB,KAAM,WACFxB,EAAEI,kCAAkCqB,GAAG,SAAS,SAASC,GACrDA,EAAEC,iBArHS,SAASrB,OAAQsB,YAShCC,QAAU,CACVC,WAAY,iCACZC,KAAM,CACFC,YATU,CAAC,MACP,0CAFU,QAAV1B,OAAmB,EAAI,SAIrBsB,WASd3B,KAAKgC,KAAK,CAACJ,UAAU,GAAGpB,MAAK,SAASyB,SAC9BA,KAAKC,MAAO,KACRC,UAAY/B,eAAeC,QAC/BC,yBAAyB6B,WACzBtB,yBAAyBsB,eAG9BxB,MAAMT,aAAaU,WAkGdwB,CAFcrC,EAAEsC,MAAM3B,KAAK,eACbX,EAAEsC,MAAM3B,KAAK"}
\ No newline at end of file
diff --git a/blocks/private_files/amd/build/files_tree.min.js b/blocks/private_files/amd/build/files_tree.min.js
index b587d0cc423..ceb29f6ce69 100644
--- a/blocks/private_files/amd/build/files_tree.min.js
+++ b/blocks/private_files/amd/build/files_tree.min.js
@@ -1,2 +1,10 @@
-define ("block_private_files/files_tree",["exports","core/tree"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);var c=function(a){new b.default("#".concat(a," [role=\"tree\"]"))};a.init=c});
-//# sourceMappingURL=files_tree.min.js.map
+define("block_private_files/files_tree",["exports","core/tree"],(function(_exports,_tree){var obj;
+/**
+ * Changes the display of directories and files into a tree.
+ *
+ * @module block_private_files/files_tree
+ * @copyright 2021 Shamim Rezaie
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_tree=(obj=_tree)&&obj.__esModule?obj:{default:obj};_exports.init=blockId=>{new _tree.default("#".concat(blockId,' [role="tree"]'))}}));
+
+//# sourceMappingURL=files_tree.min.js.map
\ No newline at end of file
diff --git a/blocks/private_files/amd/build/files_tree.min.js.map b/blocks/private_files/amd/build/files_tree.min.js.map
index c1fa974b3e7..7acba375ae7 100644
--- a/blocks/private_files/amd/build/files_tree.min.js.map
+++ b/blocks/private_files/amd/build/files_tree.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/files_tree.js"],"names":["init","blockId","Tree"],"mappings":"2JAsBA,uDAQO,GAAMA,CAAAA,CAAI,CAAG,SAACC,CAAD,CAAa,CAC7B,GAAIC,UAAJ,YAAaD,CAAb,qBACH,CAFM,C","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 .\n\n/**\n * Changes the display of directories and files into a tree.\n *\n * @module block_private_files/files_tree\n * @copyright 2021 Shamim Rezaie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Tree from 'core/tree';\n\n/**\n * The init function that does the job.\n * It changes the display of directories and files into a tree.\n *\n * @param {string} blockId\n */\nexport const init = (blockId) => {\n new Tree(`#${blockId} [role=\"tree\"]`);\n};\n"],"file":"files_tree.min.js"}
\ No newline at end of file
+{"version":3,"file":"files_tree.min.js","sources":["../src/files_tree.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 .\n\n/**\n * Changes the display of directories and files into a tree.\n *\n * @module block_private_files/files_tree\n * @copyright 2021 Shamim Rezaie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Tree from 'core/tree';\n\n/**\n * The init function that does the job.\n * It changes the display of directories and files into a tree.\n *\n * @param {string} blockId\n */\nexport const init = (blockId) => {\n new Tree(`#${blockId} [role=\"tree\"]`);\n};\n"],"names":["blockId","Tree"],"mappings":";;;;;;;oJA8BqBA,cACbC,yBAASD"}
\ No newline at end of file
diff --git a/blocks/recentlyaccessedcourses/amd/build/main.min.js b/blocks/recentlyaccessedcourses/amd/build/main.min.js
index 91540413a74..6f7d2a9e27b 100644
--- a/blocks/recentlyaccessedcourses/amd/build/main.min.js
+++ b/blocks/recentlyaccessedcourses/amd/build/main.min.js
@@ -1,2 +1,10 @@
-define ("block_recentlyaccessedcourses/main",["jquery","core/custom_interaction_events","core/notification","core/pubsub","core/paged_content_paging_bar","core/templates","core_course/events","core_course/repository","core/aria"],function(a,b,c,d,e,f,g,h,i){var j={BLOCK_CONTAINER:"[data-region=\"recentlyaccessedcourses\"]",CARD_CONTAINER:"[data-region=\"card-deck\"]",COURSE_IS_FAVOURITE:"[data-region=\"is-favourite\"]",CONTENT:"[data-region=\"view-content\"]",EMPTY_MESSAGE:"[data-region=\"empty-message\"]",LOADING_PLACEHOLDER:"[data-region=\"loading-placeholder\"]",PAGING_BAR:"[data-region=\"paging-bar\"]",PAGING_BAR_NEXT:"[data-control=\"next\"]",PAGING_BAR_PREVIOUS:"[data-control=\"previous\"]"},k=!1,l=[],m=null,n=null,o=0,p=1,q=function(a){a.find(j.EMPTY_MESSAGE).removeClass("hidden");a.find(j.LOADING_PLACEHOLDER).addClass("hidden");a.find(j.CONTENT).addClass("hidden")},r=function(a){a.find(j.CONTENT).removeClass("hidden");a.find(j.EMPTY_MESSAGE).addClass("hidden");a.find(j.LOADING_PLACEHOLDER).addClass("hidden")},s=function(a){var b=a.find(j.PAGING_BAR);b.css("opacity",1);b.css("visibility","visible");i.unhide(b)},t=function(a){var b=a.find(j.PAGING_BAR);b.css("opacity",0);b.css("visibility","hidden");i.hide(b)},u=function(a,b){l.forEach(function(a){if(a.attr("data-course-id")==b){a.find(j.COURSE_IS_FAVOURITE).removeClass("hidden")}})},v=function(a,b){l.forEach(function(a){if(a.attr("data-course-id")==b){a.find(j.COURSE_IS_FAVOURITE).addClass("hidden")}})},w=function(b){var d=a(j.BLOCK_CONTAINER).data("displaycoursecategory"),e=b.map(function(a){a.showcoursecategory=d;return f.render("block_recentlyaccessedcourses/course-card",a)});return a.when.apply(null,e).then(function(){var b=[];e.forEach(function(d){d.then(function(c){b.push(a(c))}).catch(c.exception)});return b})},x=function(a){return h.getLastAccessedCourses(a,10).then(function(a){return w(a)})},y=function(a){var b=a.find(j.CONTENT).find(j.CARD_CONTAINER),c=parseFloat(a.css("width")),d=l.length,f=0;if(!n){b.html(l[0]);n=l[0].outerWidth(!0)}p=Math.floor(c/n);if(o+ph.length){b.addClass("justify-content-center");b.removeClass("justify-content-start")}else{b.removeClass("justify-content-center");b.addClass("justify-content-start")}if(m!=i){var k=a.find(e.rootSelector);b.html(h);m=i;if(p>=l.length){t(a)}else{s(a);if(0===o){e.disablePreviousControlButtons(k)}else{e.enablePreviousControlButtons(k)}if(o+p>=l.length){e.disableNextControlButtons(k)}else{e.enableNextControlButtons(k)}}}},z=function(c){var e=null,f=!1;d.subscribe(g.favourited,function(a){u(c,a)});d.subscribe(g.unfavorited,function(a){v(c,a)});d.subscribe("nav-drawer-toggle-start",function(){if(!k||!l.length||f){return}f=!0;var a=0,b=function(){setTimeout(function(){y(c);a++;if(5>a&&f){b()}},100)};b(c)});d.subscribe("nav-drawer-toggle-end",function(){f=!1});a(window).on("resize",function(){if(!k||!l.length){return}if(!e){e=setTimeout(function(){e=null;y(c)},66)}});b.define(c,[b.events.activate]);c.on(b.events.activate,j.PAGING_BAR_NEXT,function(b,d){var e=a(b.target).closest(j.PAGING_BAR_NEXT);if(!e.hasClass("disabled")){o=o+p;y(c)}d.originalEvent.preventDefault()});c.on(b.events.activate,j.PAGING_BAR_PREVIOUS,function(b,d){var e=a(b.target).closest(j.PAGING_BAR_PREVIOUS);if(!e.hasClass("disabled")){o=o-p;o=0>o?0:o;y(c)}d.originalEvent.preventDefault()})};return{init:function init(b,d){d=a(d);z(d);x(b).then(function(a){l=a;k=!0;if(l.length){r(d);y(d)}else{q(d)}}).catch(c.exception)}}});
-//# sourceMappingURL=main.min.js.map
+/**
+ * Javascript to initialise the Recently accessed courses block.
+ *
+ * @module block_recentlyaccessedcourses/main
+ * @copyright 2018 Victor Deniz
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_recentlyaccessedcourses/main",["jquery","core/custom_interaction_events","core/notification","core/pubsub","core/paged_content_paging_bar","core/templates","core_course/events","core_course/repository","core/aria"],(function($,CustomEvents,Notification,PubSub,PagedContentPagingBar,Templates,CourseEvents,CoursesRepository,Aria){var SELECTORS_BLOCK_CONTAINER='[data-region="recentlyaccessedcourses"]',SELECTORS_CARD_CONTAINER='[data-region="card-deck"]',SELECTORS_COURSE_IS_FAVOURITE='[data-region="is-favourite"]',SELECTORS_CONTENT='[data-region="view-content"]',SELECTORS_EMPTY_MESSAGE='[data-region="empty-message"]',SELECTORS_LOADING_PLACEHOLDER='[data-region="loading-placeholder"]',SELECTORS_PAGING_BAR='[data-region="paging-bar"]',SELECTORS_PAGING_BAR_NEXT='[data-control="next"]',SELECTORS_PAGING_BAR_PREVIOUS='[data-control="previous"]',contentLoaded=!1,allCourses=[],visibleCoursesId=null,cardWidth=null,viewIndex=0,availableVisibleCards=1,loadContent=function(userid){return CoursesRepository.getLastAccessedCourses(userid,10).then((function(courses){return function(courses){var showcoursecategory=$(SELECTORS_BLOCK_CONTAINER).data("displaycoursecategory"),promises=courses.map((function(course){return course.showcoursecategory=showcoursecategory,Templates.render("block_recentlyaccessedcourses/course-card",course)}));return $.when.apply(null,promises).then((function(){var renderedCourses=[];return promises.forEach((function(promise){promise.then((function(html){renderedCourses.push($(html))})).catch(Notification.exception)})),renderedCourses}))}(courses)}))},recalculateVisibleCourses=function(root){var container=root.find(SELECTORS_CONTENT).find(SELECTORS_CARD_CONTAINER),availableWidth=parseFloat(root.css("width")),numberOfCourses=allCourses.length,start=0;(cardWidth||(container.html(allCourses[0]),cardWidth=allCourses[0].outerWidth(!0)),availableVisibleCards=Math.floor(availableWidth/cardWidth),viewIndex+availableVisibleCards=0?start:0;0===availableVisibleCards&&(availableVisibleCards=1);var coursesToShow=allCourses.slice(start,start+availableVisibleCards),newVisibleCoursesId=coursesToShow.reduce((function(carry,course){return carry+course.attr("data-course-id")}),"");if(allCourses.length>coursesToShow.length?(container.addClass("justify-content-center"),container.removeClass("justify-content-start")):(container.removeClass("justify-content-center"),container.addClass("justify-content-start")),visibleCoursesId!=newVisibleCoursesId){var pagingBar=root.find(PagedContentPagingBar.rootSelector);container.html(coursesToShow),visibleCoursesId=newVisibleCoursesId,availableVisibleCards>=allCourses.length?function(root){var pagingBar=root.find(SELECTORS_PAGING_BAR);pagingBar.css("opacity",0),pagingBar.css("visibility","hidden"),Aria.hide(pagingBar)}(root):(!function(root){var pagingBar=root.find(SELECTORS_PAGING_BAR);pagingBar.css("opacity",1),pagingBar.css("visibility","visible"),Aria.unhide(pagingBar)}(root),0===viewIndex?PagedContentPagingBar.disablePreviousControlButtons(pagingBar):PagedContentPagingBar.enablePreviousControlButtons(pagingBar),viewIndex+availableVisibleCards>=allCourses.length?PagedContentPagingBar.disableNextControlButtons(pagingBar):PagedContentPagingBar.enableNextControlButtons(pagingBar))}},registerEventListeners=function(root){var resizeTimeout=null,drawerToggling=!1;PubSub.subscribe(CourseEvents.favourited,(function(courseId){!function(root,courseId){allCourses.forEach((function(course){course.attr("data-course-id")==courseId&&course.find(SELECTORS_COURSE_IS_FAVOURITE).removeClass("hidden")}))}(0,courseId)})),PubSub.subscribe(CourseEvents.unfavorited,(function(courseId){!function(root,courseId){allCourses.forEach((function(course){course.attr("data-course-id")==courseId&&course.find(SELECTORS_COURSE_IS_FAVOURITE).addClass("hidden")}))}(0,courseId)})),PubSub.subscribe("nav-drawer-toggle-start",(function(){if(contentLoaded&&allCourses.length&&!drawerToggling){drawerToggling=!0;var recalculationCount=0,doRecalculation=function(){setTimeout((function(){recalculateVisibleCourses(root),++recalculationCount<5&&drawerToggling&&doRecalculation()}),100)};doRecalculation(root)}})),PubSub.subscribe("nav-drawer-toggle-end",(function(){drawerToggling=!1})),$(window).on("resize",(function(){contentLoaded&&allCourses.length&&(resizeTimeout||(resizeTimeout=setTimeout((function(){resizeTimeout=null,recalculateVisibleCourses(root)}),66)))})),CustomEvents.define(root,[CustomEvents.events.activate]),root.on(CustomEvents.events.activate,SELECTORS_PAGING_BAR_NEXT,(function(e,data){$(e.target).closest(SELECTORS_PAGING_BAR_NEXT).hasClass("disabled")||(viewIndex+=availableVisibleCards,recalculateVisibleCourses(root)),data.originalEvent.preventDefault()})),root.on(CustomEvents.events.activate,SELECTORS_PAGING_BAR_PREVIOUS,(function(e,data){$(e.target).closest(SELECTORS_PAGING_BAR_PREVIOUS).hasClass("disabled")||(viewIndex=(viewIndex-=availableVisibleCards)<0?0:viewIndex,recalculateVisibleCourses(root)),data.originalEvent.preventDefault()}))};return{init:function(userid,root){root=$(root),registerEventListeners(root),loadContent(userid).then((function(renderedCourses){contentLoaded=!0,(allCourses=renderedCourses).length?(!function(root){root.find(SELECTORS_CONTENT).removeClass("hidden"),root.find(SELECTORS_EMPTY_MESSAGE).addClass("hidden"),root.find(SELECTORS_LOADING_PLACEHOLDER).addClass("hidden")}(root),recalculateVisibleCourses(root)):function(root){root.find(SELECTORS_EMPTY_MESSAGE).removeClass("hidden"),root.find(SELECTORS_LOADING_PLACEHOLDER).addClass("hidden"),root.find(SELECTORS_CONTENT).addClass("hidden")}(root)})).catch(Notification.exception)}}}));
+
+//# sourceMappingURL=main.min.js.map
\ No newline at end of file
diff --git a/blocks/recentlyaccessedcourses/amd/build/main.min.js.map b/blocks/recentlyaccessedcourses/amd/build/main.min.js.map
index b2d60005855..2e42d7b4895 100644
--- a/blocks/recentlyaccessedcourses/amd/build/main.min.js.map
+++ b/blocks/recentlyaccessedcourses/amd/build/main.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/main.js"],"names":["define","$","CustomEvents","Notification","PubSub","PagedContentPagingBar","Templates","CourseEvents","CoursesRepository","Aria","SELECTORS","BLOCK_CONTAINER","CARD_CONTAINER","COURSE_IS_FAVOURITE","CONTENT","EMPTY_MESSAGE","LOADING_PLACEHOLDER","PAGING_BAR","PAGING_BAR_NEXT","PAGING_BAR_PREVIOUS","contentLoaded","allCourses","visibleCoursesId","cardWidth","viewIndex","availableVisibleCards","showEmptyMessage","root","find","removeClass","addClass","showContent","showPagingBar","pagingBar","css","unhide","hidePagingBar","hide","favouriteCourse","courseId","forEach","course","attr","unfavouriteCourse","renderAllCourses","courses","showcoursecategory","data","promises","map","render","when","apply","then","renderedCourses","promise","html","push","catch","exception","loadContent","userid","getLastAccessedCourses","recalculateVisibleCourses","container","availableWidth","parseFloat","numberOfCourses","length","start","outerWidth","Math","floor","overflow","coursesToShow","slice","newVisibleCoursesId","reduce","carry","rootSelector","disablePreviousControlButtons","enablePreviousControlButtons","disableNextControlButtons","enableNextControlButtons","registerEventListeners","resizeTimeout","drawerToggling","subscribe","favourited","unfavorited","recalculationCount","doRecalculation","setTimeout","window","on","events","activate","e","button","target","closest","hasClass","originalEvent","preventDefault","init"],"mappings":"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","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 .\n\n/**\n * Javascript to initialise the Recently accessed courses block.\n *\n * @module block_recentlyaccessedcourses/main\n * @copyright 2018 Victor Deniz \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n [\n 'jquery',\n 'core/custom_interaction_events',\n 'core/notification',\n 'core/pubsub',\n 'core/paged_content_paging_bar',\n 'core/templates',\n 'core_course/events',\n 'core_course/repository',\n 'core/aria',\n ],\n function(\n $,\n CustomEvents,\n Notification,\n PubSub,\n PagedContentPagingBar,\n Templates,\n CourseEvents,\n CoursesRepository,\n Aria\n ) {\n\n // Constants.\n var NUM_COURSES_TOTAL = 10;\n var SELECTORS = {\n BLOCK_CONTAINER: '[data-region=\"recentlyaccessedcourses\"]',\n CARD_CONTAINER: '[data-region=\"card-deck\"]',\n COURSE_IS_FAVOURITE: '[data-region=\"is-favourite\"]',\n CONTENT: '[data-region=\"view-content\"]',\n EMPTY_MESSAGE: '[data-region=\"empty-message\"]',\n LOADING_PLACEHOLDER: '[data-region=\"loading-placeholder\"]',\n PAGING_BAR: '[data-region=\"paging-bar\"]',\n PAGING_BAR_NEXT: '[data-control=\"next\"]',\n PAGING_BAR_PREVIOUS: '[data-control=\"previous\"]'\n };\n // Module variables.\n var contentLoaded = false;\n var allCourses = [];\n var visibleCoursesId = null;\n var cardWidth = null;\n var viewIndex = 0;\n var availableVisibleCards = 1;\n\n /**\n * Show the empty message when no course are found.\n *\n * @param {object} root The root element for the courses view.\n */\n var showEmptyMessage = function(root) {\n root.find(SELECTORS.EMPTY_MESSAGE).removeClass('hidden');\n root.find(SELECTORS.LOADING_PLACEHOLDER).addClass('hidden');\n root.find(SELECTORS.CONTENT).addClass('hidden');\n };\n\n /**\n * Show the empty message when no course are found.\n *\n * @param {object} root The root element for the courses view.\n */\n var showContent = function(root) {\n root.find(SELECTORS.CONTENT).removeClass('hidden');\n root.find(SELECTORS.EMPTY_MESSAGE).addClass('hidden');\n root.find(SELECTORS.LOADING_PLACEHOLDER).addClass('hidden');\n };\n\n /**\n * Show the paging bar.\n *\n * @param {object} root The root element for the courses view.\n */\n var showPagingBar = function(root) {\n var pagingBar = root.find(SELECTORS.PAGING_BAR);\n pagingBar.css('opacity', 1);\n pagingBar.css('visibility', 'visible');\n Aria.unhide(pagingBar);\n };\n\n /**\n * Hide the paging bar.\n *\n * @param {object} root The root element for the courses view.\n */\n var hidePagingBar = function(root) {\n var pagingBar = root.find(SELECTORS.PAGING_BAR);\n pagingBar.css('opacity', 0);\n pagingBar.css('visibility', 'hidden');\n Aria.hide(pagingBar);\n };\n\n /**\n * Show the favourite indicator for the given course (if it's in the list).\n *\n * @param {object} root The root element for the courses view.\n * @param {number} courseId The id of the course to be favourited.\n */\n var favouriteCourse = function(root, courseId) {\n allCourses.forEach(function(course) {\n if (course.attr('data-course-id') == courseId) {\n course.find(SELECTORS.COURSE_IS_FAVOURITE).removeClass('hidden');\n }\n });\n };\n\n /**\n * Hide the favourite indicator for the given course (if it's in the list).\n *\n * @param {object} root The root element for the courses view.\n * @param {number} courseId The id of the course to be unfavourited.\n */\n var unfavouriteCourse = function(root, courseId) {\n allCourses.forEach(function(course) {\n if (course.attr('data-course-id') == courseId) {\n course.find(SELECTORS.COURSE_IS_FAVOURITE).addClass('hidden');\n }\n });\n };\n\n /**\n * Render the a list of courses.\n *\n * @param {array} courses containing array of courses.\n * @return {promise} Resolved with list of rendered courses as jQuery objects.\n */\n var renderAllCourses = function(courses) {\n var showcoursecategory = $(SELECTORS.BLOCK_CONTAINER).data('displaycoursecategory');\n var promises = courses.map(function(course) {\n course.showcoursecategory = showcoursecategory;\n return Templates.render('block_recentlyaccessedcourses/course-card', course);\n });\n\n return $.when.apply(null, promises).then(function() {\n var renderedCourses = [];\n\n promises.forEach(function(promise) {\n promise.then(function(html) {\n renderedCourses.push($(html));\n return;\n })\n .catch(Notification.exception);\n });\n\n return renderedCourses;\n });\n };\n\n /**\n * Fetch user's recently accessed courses and reload the content of the block.\n *\n * @param {int} userid User whose courses will be shown\n * @returns {promise} The updated content for the block.\n */\n var loadContent = function(userid) {\n return CoursesRepository.getLastAccessedCourses(userid, NUM_COURSES_TOTAL)\n .then(function(courses) {\n return renderAllCourses(courses);\n });\n };\n\n /**\n * Recalculate the number of courses that should be visible.\n *\n * @param {object} root The root element for the courses view.\n */\n var recalculateVisibleCourses = function(root) {\n var container = root.find(SELECTORS.CONTENT).find(SELECTORS.CARD_CONTAINER);\n var availableWidth = parseFloat(root.css('width'));\n var numberOfCourses = allCourses.length;\n var start = 0;\n\n if (!cardWidth) {\n container.html(allCourses[0]);\n // Render one card initially to calculate the width of the cards\n // including the margins.\n cardWidth = allCourses[0].outerWidth(true);\n }\n\n availableVisibleCards = Math.floor(availableWidth / cardWidth);\n\n if (viewIndex + availableVisibleCards < numberOfCourses) {\n start = viewIndex;\n } else {\n var overflow = (viewIndex + availableVisibleCards) - numberOfCourses;\n start = viewIndex - overflow;\n start = start >= 0 ? start : 0;\n }\n\n // At least show one card.\n if (availableVisibleCards === 0) {\n availableVisibleCards = 1;\n }\n\n var coursesToShow = allCourses.slice(start, start + availableVisibleCards);\n // Create an id for the list of courses we expect to be displayed.\n var newVisibleCoursesId = coursesToShow.reduce(function(carry, course) {\n return carry + course.attr('data-course-id');\n }, '');\n\n // Centre the courses if we have an overflow of courses.\n if (allCourses.length > coursesToShow.length) {\n container.addClass('justify-content-center');\n container.removeClass('justify-content-start');\n } else {\n container.removeClass('justify-content-center');\n container.addClass('justify-content-start');\n }\n\n // Don't bother updating the DOM unless the visible courses have changed.\n if (visibleCoursesId != newVisibleCoursesId) {\n var pagingBar = root.find(PagedContentPagingBar.rootSelector);\n container.html(coursesToShow);\n visibleCoursesId = newVisibleCoursesId;\n\n if (availableVisibleCards >= allCourses.length) {\n hidePagingBar(root);\n } else {\n showPagingBar(root);\n\n if (viewIndex === 0) {\n PagedContentPagingBar.disablePreviousControlButtons(pagingBar);\n } else {\n PagedContentPagingBar.enablePreviousControlButtons(pagingBar);\n }\n\n if (viewIndex + availableVisibleCards >= allCourses.length) {\n PagedContentPagingBar.disableNextControlButtons(pagingBar);\n } else {\n PagedContentPagingBar.enableNextControlButtons(pagingBar);\n }\n }\n }\n };\n\n /**\n * Register event listeners for the block.\n *\n * @param {object} root The root element for the recentlyaccessedcourses block.\n */\n var registerEventListeners = function(root) {\n var resizeTimeout = null;\n var drawerToggling = false;\n\n PubSub.subscribe(CourseEvents.favourited, function(courseId) {\n favouriteCourse(root, courseId);\n });\n\n PubSub.subscribe(CourseEvents.unfavorited, function(courseId) {\n unfavouriteCourse(root, courseId);\n });\n\n PubSub.subscribe('nav-drawer-toggle-start', function() {\n if (!contentLoaded || !allCourses.length || drawerToggling) {\n // Nothing to recalculate.\n return;\n }\n\n drawerToggling = true;\n var recalculationCount = 0;\n // This function is going to recalculate the number of courses while\n // the nav drawer is opening or closes (up to a maximum of 5 recalcs).\n var doRecalculation = function() {\n setTimeout(function() {\n recalculateVisibleCourses(root);\n recalculationCount++;\n\n if (recalculationCount < 5 && drawerToggling) {\n // If we haven't done too many recalculations and the drawer\n // is still toggling then recurse.\n doRecalculation();\n }\n }, 100);\n };\n\n // Start the recalculations.\n doRecalculation(root);\n });\n\n PubSub.subscribe('nav-drawer-toggle-end', function() {\n drawerToggling = false;\n });\n\n $(window).on('resize', function() {\n if (!contentLoaded || !allCourses.length) {\n // Nothing to reclculate.\n return;\n }\n\n // Resize events fire rapidly so recalculating the visible courses each\n // time can be expensive. Let's debounce them,\n if (!resizeTimeout) {\n resizeTimeout = setTimeout(function() {\n resizeTimeout = null;\n recalculateVisibleCourses(root);\n // The recalculateVisibleCourses function will execute at a rate of 15fps.\n }, 66);\n }\n });\n\n CustomEvents.define(root, [CustomEvents.events.activate]);\n root.on(CustomEvents.events.activate, SELECTORS.PAGING_BAR_NEXT, function(e, data) {\n var button = $(e.target).closest(SELECTORS.PAGING_BAR_NEXT);\n if (!button.hasClass('disabled')) {\n viewIndex = viewIndex + availableVisibleCards;\n recalculateVisibleCourses(root);\n }\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.PAGING_BAR_PREVIOUS, function(e, data) {\n var button = $(e.target).closest(SELECTORS.PAGING_BAR_PREVIOUS);\n if (!button.hasClass('disabled')) {\n viewIndex = viewIndex - availableVisibleCards;\n viewIndex = viewIndex < 0 ? 0 : viewIndex;\n recalculateVisibleCourses(root);\n }\n\n data.originalEvent.preventDefault();\n });\n };\n\n /**\n * Get and show the recent courses into the block.\n *\n * @param {int} userid User from which the courses will be obtained\n * @param {object} root The root element for the recentlyaccessedcourses block.\n */\n var init = function(userid, root) {\n root = $(root);\n\n registerEventListeners(root);\n loadContent(userid)\n .then(function(renderedCourses) {\n allCourses = renderedCourses;\n contentLoaded = true;\n\n if (allCourses.length) {\n showContent(root);\n recalculateVisibleCourses(root);\n } else {\n showEmptyMessage(root);\n }\n\n return;\n })\n .catch(Notification.exception);\n };\n\n return {\n init: init\n };\n });\n"],"file":"main.min.js"}
\ No newline at end of file
+{"version":3,"file":"main.min.js","sources":["../src/main.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 .\n\n/**\n * Javascript to initialise the Recently accessed courses block.\n *\n * @module block_recentlyaccessedcourses/main\n * @copyright 2018 Victor Deniz \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n [\n 'jquery',\n 'core/custom_interaction_events',\n 'core/notification',\n 'core/pubsub',\n 'core/paged_content_paging_bar',\n 'core/templates',\n 'core_course/events',\n 'core_course/repository',\n 'core/aria',\n ],\n function(\n $,\n CustomEvents,\n Notification,\n PubSub,\n PagedContentPagingBar,\n Templates,\n CourseEvents,\n CoursesRepository,\n Aria\n ) {\n\n // Constants.\n var NUM_COURSES_TOTAL = 10;\n var SELECTORS = {\n BLOCK_CONTAINER: '[data-region=\"recentlyaccessedcourses\"]',\n CARD_CONTAINER: '[data-region=\"card-deck\"]',\n COURSE_IS_FAVOURITE: '[data-region=\"is-favourite\"]',\n CONTENT: '[data-region=\"view-content\"]',\n EMPTY_MESSAGE: '[data-region=\"empty-message\"]',\n LOADING_PLACEHOLDER: '[data-region=\"loading-placeholder\"]',\n PAGING_BAR: '[data-region=\"paging-bar\"]',\n PAGING_BAR_NEXT: '[data-control=\"next\"]',\n PAGING_BAR_PREVIOUS: '[data-control=\"previous\"]'\n };\n // Module variables.\n var contentLoaded = false;\n var allCourses = [];\n var visibleCoursesId = null;\n var cardWidth = null;\n var viewIndex = 0;\n var availableVisibleCards = 1;\n\n /**\n * Show the empty message when no course are found.\n *\n * @param {object} root The root element for the courses view.\n */\n var showEmptyMessage = function(root) {\n root.find(SELECTORS.EMPTY_MESSAGE).removeClass('hidden');\n root.find(SELECTORS.LOADING_PLACEHOLDER).addClass('hidden');\n root.find(SELECTORS.CONTENT).addClass('hidden');\n };\n\n /**\n * Show the empty message when no course are found.\n *\n * @param {object} root The root element for the courses view.\n */\n var showContent = function(root) {\n root.find(SELECTORS.CONTENT).removeClass('hidden');\n root.find(SELECTORS.EMPTY_MESSAGE).addClass('hidden');\n root.find(SELECTORS.LOADING_PLACEHOLDER).addClass('hidden');\n };\n\n /**\n * Show the paging bar.\n *\n * @param {object} root The root element for the courses view.\n */\n var showPagingBar = function(root) {\n var pagingBar = root.find(SELECTORS.PAGING_BAR);\n pagingBar.css('opacity', 1);\n pagingBar.css('visibility', 'visible');\n Aria.unhide(pagingBar);\n };\n\n /**\n * Hide the paging bar.\n *\n * @param {object} root The root element for the courses view.\n */\n var hidePagingBar = function(root) {\n var pagingBar = root.find(SELECTORS.PAGING_BAR);\n pagingBar.css('opacity', 0);\n pagingBar.css('visibility', 'hidden');\n Aria.hide(pagingBar);\n };\n\n /**\n * Show the favourite indicator for the given course (if it's in the list).\n *\n * @param {object} root The root element for the courses view.\n * @param {number} courseId The id of the course to be favourited.\n */\n var favouriteCourse = function(root, courseId) {\n allCourses.forEach(function(course) {\n if (course.attr('data-course-id') == courseId) {\n course.find(SELECTORS.COURSE_IS_FAVOURITE).removeClass('hidden');\n }\n });\n };\n\n /**\n * Hide the favourite indicator for the given course (if it's in the list).\n *\n * @param {object} root The root element for the courses view.\n * @param {number} courseId The id of the course to be unfavourited.\n */\n var unfavouriteCourse = function(root, courseId) {\n allCourses.forEach(function(course) {\n if (course.attr('data-course-id') == courseId) {\n course.find(SELECTORS.COURSE_IS_FAVOURITE).addClass('hidden');\n }\n });\n };\n\n /**\n * Render the a list of courses.\n *\n * @param {array} courses containing array of courses.\n * @return {promise} Resolved with list of rendered courses as jQuery objects.\n */\n var renderAllCourses = function(courses) {\n var showcoursecategory = $(SELECTORS.BLOCK_CONTAINER).data('displaycoursecategory');\n var promises = courses.map(function(course) {\n course.showcoursecategory = showcoursecategory;\n return Templates.render('block_recentlyaccessedcourses/course-card', course);\n });\n\n return $.when.apply(null, promises).then(function() {\n var renderedCourses = [];\n\n promises.forEach(function(promise) {\n promise.then(function(html) {\n renderedCourses.push($(html));\n return;\n })\n .catch(Notification.exception);\n });\n\n return renderedCourses;\n });\n };\n\n /**\n * Fetch user's recently accessed courses and reload the content of the block.\n *\n * @param {int} userid User whose courses will be shown\n * @returns {promise} The updated content for the block.\n */\n var loadContent = function(userid) {\n return CoursesRepository.getLastAccessedCourses(userid, NUM_COURSES_TOTAL)\n .then(function(courses) {\n return renderAllCourses(courses);\n });\n };\n\n /**\n * Recalculate the number of courses that should be visible.\n *\n * @param {object} root The root element for the courses view.\n */\n var recalculateVisibleCourses = function(root) {\n var container = root.find(SELECTORS.CONTENT).find(SELECTORS.CARD_CONTAINER);\n var availableWidth = parseFloat(root.css('width'));\n var numberOfCourses = allCourses.length;\n var start = 0;\n\n if (!cardWidth) {\n container.html(allCourses[0]);\n // Render one card initially to calculate the width of the cards\n // including the margins.\n cardWidth = allCourses[0].outerWidth(true);\n }\n\n availableVisibleCards = Math.floor(availableWidth / cardWidth);\n\n if (viewIndex + availableVisibleCards < numberOfCourses) {\n start = viewIndex;\n } else {\n var overflow = (viewIndex + availableVisibleCards) - numberOfCourses;\n start = viewIndex - overflow;\n start = start >= 0 ? start : 0;\n }\n\n // At least show one card.\n if (availableVisibleCards === 0) {\n availableVisibleCards = 1;\n }\n\n var coursesToShow = allCourses.slice(start, start + availableVisibleCards);\n // Create an id for the list of courses we expect to be displayed.\n var newVisibleCoursesId = coursesToShow.reduce(function(carry, course) {\n return carry + course.attr('data-course-id');\n }, '');\n\n // Centre the courses if we have an overflow of courses.\n if (allCourses.length > coursesToShow.length) {\n container.addClass('justify-content-center');\n container.removeClass('justify-content-start');\n } else {\n container.removeClass('justify-content-center');\n container.addClass('justify-content-start');\n }\n\n // Don't bother updating the DOM unless the visible courses have changed.\n if (visibleCoursesId != newVisibleCoursesId) {\n var pagingBar = root.find(PagedContentPagingBar.rootSelector);\n container.html(coursesToShow);\n visibleCoursesId = newVisibleCoursesId;\n\n if (availableVisibleCards >= allCourses.length) {\n hidePagingBar(root);\n } else {\n showPagingBar(root);\n\n if (viewIndex === 0) {\n PagedContentPagingBar.disablePreviousControlButtons(pagingBar);\n } else {\n PagedContentPagingBar.enablePreviousControlButtons(pagingBar);\n }\n\n if (viewIndex + availableVisibleCards >= allCourses.length) {\n PagedContentPagingBar.disableNextControlButtons(pagingBar);\n } else {\n PagedContentPagingBar.enableNextControlButtons(pagingBar);\n }\n }\n }\n };\n\n /**\n * Register event listeners for the block.\n *\n * @param {object} root The root element for the recentlyaccessedcourses block.\n */\n var registerEventListeners = function(root) {\n var resizeTimeout = null;\n var drawerToggling = false;\n\n PubSub.subscribe(CourseEvents.favourited, function(courseId) {\n favouriteCourse(root, courseId);\n });\n\n PubSub.subscribe(CourseEvents.unfavorited, function(courseId) {\n unfavouriteCourse(root, courseId);\n });\n\n PubSub.subscribe('nav-drawer-toggle-start', function() {\n if (!contentLoaded || !allCourses.length || drawerToggling) {\n // Nothing to recalculate.\n return;\n }\n\n drawerToggling = true;\n var recalculationCount = 0;\n // This function is going to recalculate the number of courses while\n // the nav drawer is opening or closes (up to a maximum of 5 recalcs).\n var doRecalculation = function() {\n setTimeout(function() {\n recalculateVisibleCourses(root);\n recalculationCount++;\n\n if (recalculationCount < 5 && drawerToggling) {\n // If we haven't done too many recalculations and the drawer\n // is still toggling then recurse.\n doRecalculation();\n }\n }, 100);\n };\n\n // Start the recalculations.\n doRecalculation(root);\n });\n\n PubSub.subscribe('nav-drawer-toggle-end', function() {\n drawerToggling = false;\n });\n\n $(window).on('resize', function() {\n if (!contentLoaded || !allCourses.length) {\n // Nothing to reclculate.\n return;\n }\n\n // Resize events fire rapidly so recalculating the visible courses each\n // time can be expensive. Let's debounce them,\n if (!resizeTimeout) {\n resizeTimeout = setTimeout(function() {\n resizeTimeout = null;\n recalculateVisibleCourses(root);\n // The recalculateVisibleCourses function will execute at a rate of 15fps.\n }, 66);\n }\n });\n\n CustomEvents.define(root, [CustomEvents.events.activate]);\n root.on(CustomEvents.events.activate, SELECTORS.PAGING_BAR_NEXT, function(e, data) {\n var button = $(e.target).closest(SELECTORS.PAGING_BAR_NEXT);\n if (!button.hasClass('disabled')) {\n viewIndex = viewIndex + availableVisibleCards;\n recalculateVisibleCourses(root);\n }\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.PAGING_BAR_PREVIOUS, function(e, data) {\n var button = $(e.target).closest(SELECTORS.PAGING_BAR_PREVIOUS);\n if (!button.hasClass('disabled')) {\n viewIndex = viewIndex - availableVisibleCards;\n viewIndex = viewIndex < 0 ? 0 : viewIndex;\n recalculateVisibleCourses(root);\n }\n\n data.originalEvent.preventDefault();\n });\n };\n\n /**\n * Get and show the recent courses into the block.\n *\n * @param {int} userid User from which the courses will be obtained\n * @param {object} root The root element for the recentlyaccessedcourses block.\n */\n var init = function(userid, root) {\n root = $(root);\n\n registerEventListeners(root);\n loadContent(userid)\n .then(function(renderedCourses) {\n allCourses = renderedCourses;\n contentLoaded = true;\n\n if (allCourses.length) {\n showContent(root);\n recalculateVisibleCourses(root);\n } else {\n showEmptyMessage(root);\n }\n\n return;\n })\n .catch(Notification.exception);\n };\n\n return {\n init: init\n };\n });\n"],"names":["define","$","CustomEvents","Notification","PubSub","PagedContentPagingBar","Templates","CourseEvents","CoursesRepository","Aria","SELECTORS","contentLoaded","allCourses","visibleCoursesId","cardWidth","viewIndex","availableVisibleCards","loadContent","userid","getLastAccessedCourses","then","courses","showcoursecategory","data","promises","map","course","render","when","apply","renderedCourses","forEach","promise","html","push","catch","exception","renderAllCourses","recalculateVisibleCourses","root","container","find","availableWidth","parseFloat","css","numberOfCourses","length","start","outerWidth","Math","floor","coursesToShow","slice","newVisibleCoursesId","reduce","carry","attr","addClass","removeClass","pagingBar","rootSelector","hide","hidePagingBar","unhide","showPagingBar","disablePreviousControlButtons","enablePreviousControlButtons","disableNextControlButtons","enableNextControlButtons","registerEventListeners","resizeTimeout","drawerToggling","subscribe","favourited","courseId","favouriteCourse","unfavorited","unfavouriteCourse","recalculationCount","doRecalculation","setTimeout","window","on","events","activate","e","target","closest","hasClass","originalEvent","preventDefault","init","showContent","showEmptyMessage"],"mappings":"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"}
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/amd/build/main.min.js b/blocks/recentlyaccesseditems/amd/build/main.min.js
index 0f3c4882a1e..95d9b5cc6aa 100644
--- a/blocks/recentlyaccesseditems/amd/build/main.min.js
+++ b/blocks/recentlyaccesseditems/amd/build/main.min.js
@@ -1,2 +1,10 @@
-define ("block_recentlyaccesseditems/main",["jquery","block_recentlyaccesseditems/repository","core/templates","core/notification"],function(a,b,c,d){var e={CARDDECK_CONTAINER:"[data-region=\"recentlyaccesseditems-view\"]",CARDDECK:"[data-region=\"recentlyaccesseditems-view-content\"]"},f=function(a){return b.getRecentItems(a)},g=function(a,b){if(0
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_recentlyaccesseditems/main",["jquery","block_recentlyaccesseditems/repository","core/templates","core/notification"],(function($,Repository,Templates,Notification){var SELECTORS_CARDDECK_CONTAINER='[data-region="recentlyaccesseditems-view"]',SELECTORS_CARDDECK='[data-region="recentlyaccesseditems-view-content"]';return{init:function(root){var limit,itemsContainer=(root=$(root)).find(SELECTORS_CARDDECK_CONTAINER),itemsContent=root.find(SELECTORS_CARDDECK),itemsPromise=(limit=9,Repository.getRecentItems(limit));itemsPromise.then((function(items){var pageContentPromise=function(root,items){if(items.length>0)return Templates.render("block_recentlyaccesseditems/view-cards",{items:items});var noitemsimgurl=root.attr("data-noitemsimgurl");return Templates.render("block_recentlyaccesseditems/no-items",{noitemsimgurl:noitemsimgurl})}(itemsContainer,items);return pageContentPromise.then((function(html,js){return Templates.replaceNodeContents(itemsContent,html,js)})).catch(Notification.exception),itemsPromise})).catch(Notification.exception)}}}));
+
+//# sourceMappingURL=main.min.js.map
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/amd/build/main.min.js.map b/blocks/recentlyaccesseditems/amd/build/main.min.js.map
index 0ec27118f46..dd50ff751b2 100644
--- a/blocks/recentlyaccesseditems/amd/build/main.min.js.map
+++ b/blocks/recentlyaccesseditems/amd/build/main.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/main.js"],"names":["define","$","Repository","Templates","Notification","SELECTORS","CARDDECK_CONTAINER","CARDDECK","getRecentItems","limit","renderItems","root","items","length","render","noitemsimgurl","attr","init","itemsContainer","find","itemsContent","itemsPromise","then","pageContentPromise","html","js","replaceNodeContents","catch","exception"],"mappings":"AAwBAA,OAAM,oCACF,CACI,QADJ,CAEI,wCAFJ,CAGI,gBAHJ,CAII,mBAJJ,CADE,CAOF,SACIC,CADJ,CAEIC,CAFJ,CAGIC,CAHJ,CAIIC,CAJJ,CAKE,IAIMC,CAAAA,CAAS,CAAG,CACZC,kBAAkB,CAAE,8CADR,CAEZC,QAAQ,CAAE,sDAFE,CAJlB,CAgBMC,CAAc,CAAG,SAASC,CAAT,CAAgB,CACjC,MAAOP,CAAAA,CAAU,CAACM,cAAX,CAA0BC,CAA1B,CACV,CAlBH,CA4BMC,CAAW,CAAG,SAASC,CAAT,CAAeC,CAAf,CAAsB,CACpC,GAAmB,CAAf,CAAAA,CAAK,CAACC,MAAV,CAAsB,CAClB,MAAOV,CAAAA,CAAS,CAACW,MAAV,CAAiB,wCAAjB,CAA2D,CAC9DF,KAAK,CAAEA,CADuD,CAA3D,CAGV,CAJD,IAIO,CACH,GAAIG,CAAAA,CAAa,CAAGJ,CAAI,CAACK,IAAL,CAAU,oBAAV,CAApB,CACA,MAAOb,CAAAA,CAAS,CAACW,MAAV,CAAiB,sCAAjB,CAAyD,CAC5DC,aAAa,CAAEA,CAD6C,CAAzD,CAGV,CACJ,CAvCH,CAgEE,MAAO,CACHE,IAAI,CAnBG,QAAPA,CAAAA,IAAO,CAASN,CAAT,CAAe,CACtBA,CAAI,CAAGV,CAAC,CAACU,CAAD,CAAR,CADsB,GAGlBO,CAAAA,CAAc,CAAGP,CAAI,CAACQ,IAAL,CAAUd,CAAS,CAACC,kBAApB,CAHC,CAIlBc,CAAY,CAAGT,CAAI,CAACQ,IAAL,CAAUd,CAAS,CAACE,QAApB,CAJG,CAMlBc,CAAY,CAAGb,CAAc,GANX,CAQtBa,CAAY,CAACC,IAAb,CAAkB,SAASV,CAAT,CAAgB,CAC9B,GAAIW,CAAAA,CAAkB,CAAGb,CAAW,CAACQ,CAAD,CAAiBN,CAAjB,CAApC,CAEAW,CAAkB,CAACD,IAAnB,CAAwB,SAASE,CAAT,CAAeC,CAAf,CAAmB,CACvC,MAAOtB,CAAAA,CAAS,CAACuB,mBAAV,CAA8BN,CAA9B,CAA4CI,CAA5C,CAAkDC,CAAlD,CACV,CAFD,EAEGE,KAFH,CAESvB,CAAY,CAACwB,SAFtB,EAGA,MAAOP,CAAAA,CACV,CAPD,EAOGM,KAPH,CAOSvB,CAAY,CAACwB,SAPtB,CAQH,CAEM,CAGV,CA/EC,CAAN","sourcesContent":["\n// 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 .\n\n/**\n * Javascript to initialise the Recently accessed items block.\n *\n * @module block_recentlyaccesseditems/main\n * @copyright 2018 Victor Deniz \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n [\n 'jquery',\n 'block_recentlyaccesseditems/repository',\n 'core/templates',\n 'core/notification'\n ],\n function(\n $,\n Repository,\n Templates,\n Notification\n ) {\n\n var NUM_ITEMS = 9;\n\n var SELECTORS = {\n CARDDECK_CONTAINER: '[data-region=\"recentlyaccesseditems-view\"]',\n CARDDECK: '[data-region=\"recentlyaccesseditems-view-content\"]',\n };\n\n /**\n * Get recent items from backend.\n *\n * @method getRecentItems\n * @param {int} limit Only return this many results\n * @return {array} Items user most recently has accessed\n */\n var getRecentItems = function(limit) {\n return Repository.getRecentItems(limit);\n };\n\n /**\n * Render the block content.\n *\n * @method renderItems\n * @param {object} root The root element for the items view.\n * @param {array} items containing array of returned items.\n * @return {promise} Resolved with HTML and JS strings\n */\n var renderItems = function(root, items) {\n if (items.length > 0) {\n return Templates.render('block_recentlyaccesseditems/view-cards', {\n items: items\n });\n } else {\n var noitemsimgurl = root.attr('data-noitemsimgurl');\n return Templates.render('block_recentlyaccesseditems/no-items', {\n noitemsimgurl: noitemsimgurl\n });\n }\n };\n\n /**\n * Get and show the recent items into the block.\n *\n * @param {object} root The root element for the items block.\n */\n var init = function(root) {\n root = $(root);\n\n var itemsContainer = root.find(SELECTORS.CARDDECK_CONTAINER);\n var itemsContent = root.find(SELECTORS.CARDDECK);\n\n var itemsPromise = getRecentItems(NUM_ITEMS);\n\n itemsPromise.then(function(items) {\n var pageContentPromise = renderItems(itemsContainer, items);\n\n pageContentPromise.then(function(html, js) {\n return Templates.replaceNodeContents(itemsContent, html, js);\n }).catch(Notification.exception);\n return itemsPromise;\n }).catch(Notification.exception);\n };\n\n return {\n init: init\n };\n });"],"file":"main.min.js"}
\ No newline at end of file
+{"version":3,"file":"main.min.js","sources":["../src/main.js"],"sourcesContent":["\n// 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 .\n\n/**\n * Javascript to initialise the Recently accessed items block.\n *\n * @module block_recentlyaccesseditems/main\n * @copyright 2018 Victor Deniz \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n [\n 'jquery',\n 'block_recentlyaccesseditems/repository',\n 'core/templates',\n 'core/notification'\n ],\n function(\n $,\n Repository,\n Templates,\n Notification\n ) {\n\n var NUM_ITEMS = 9;\n\n var SELECTORS = {\n CARDDECK_CONTAINER: '[data-region=\"recentlyaccesseditems-view\"]',\n CARDDECK: '[data-region=\"recentlyaccesseditems-view-content\"]',\n };\n\n /**\n * Get recent items from backend.\n *\n * @method getRecentItems\n * @param {int} limit Only return this many results\n * @return {array} Items user most recently has accessed\n */\n var getRecentItems = function(limit) {\n return Repository.getRecentItems(limit);\n };\n\n /**\n * Render the block content.\n *\n * @method renderItems\n * @param {object} root The root element for the items view.\n * @param {array} items containing array of returned items.\n * @return {promise} Resolved with HTML and JS strings\n */\n var renderItems = function(root, items) {\n if (items.length > 0) {\n return Templates.render('block_recentlyaccesseditems/view-cards', {\n items: items\n });\n } else {\n var noitemsimgurl = root.attr('data-noitemsimgurl');\n return Templates.render('block_recentlyaccesseditems/no-items', {\n noitemsimgurl: noitemsimgurl\n });\n }\n };\n\n /**\n * Get and show the recent items into the block.\n *\n * @param {object} root The root element for the items block.\n */\n var init = function(root) {\n root = $(root);\n\n var itemsContainer = root.find(SELECTORS.CARDDECK_CONTAINER);\n var itemsContent = root.find(SELECTORS.CARDDECK);\n\n var itemsPromise = getRecentItems(NUM_ITEMS);\n\n itemsPromise.then(function(items) {\n var pageContentPromise = renderItems(itemsContainer, items);\n\n pageContentPromise.then(function(html, js) {\n return Templates.replaceNodeContents(itemsContent, html, js);\n }).catch(Notification.exception);\n return itemsPromise;\n }).catch(Notification.exception);\n };\n\n return {\n init: init\n };\n });"],"names":["define","$","Repository","Templates","Notification","SELECTORS","init","root","limit","itemsContainer","find","itemsContent","itemsPromise","getRecentItems","then","items","pageContentPromise","length","render","noitemsimgurl","attr","renderItems","html","js","replaceNodeContents","catch","exception"],"mappings":";;;;;;;AAwBAA,0CACI,CACI,SACA,yCACA,iBACA,sBAEJ,SACIC,EACAC,WACAC,UACAC,kBAKIC,6BACoB,6CADpBA,mBAEU,2DA0DP,CACHC,KAnBO,SAASC,UA9BUC,MAiCtBC,gBAFJF,KAAON,EAAEM,OAEiBG,KAAKL,8BAC3BM,aAAeJ,KAAKG,KAAKL,oBAEzBO,cApCsBJ,MAdd,EAeLN,WAAWW,eAAeL,QAqCjCI,aAAaE,MAAK,SAASC,WACnBC,mBA3BM,SAAST,KAAMQ,UACzBA,MAAME,OAAS,SACRd,UAAUe,OAAO,yCAA0C,CAC9DH,MAAOA,YAGPI,cAAgBZ,KAAKa,KAAK,6BACvBjB,UAAUe,OAAO,uCAAwC,CAC5DC,cAAeA,gBAmBME,CAAYZ,eAAgBM,cAErDC,mBAAmBF,MAAK,SAASQ,KAAMC,WAC5BpB,UAAUqB,oBAAoBb,aAAcW,KAAMC,OAC1DE,MAAMrB,aAAasB,WACfd,gBACRa,MAAMrB,aAAasB"}
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/amd/build/repository.min.js b/blocks/recentlyaccesseditems/amd/build/repository.min.js
index f86b1960b04..e65de5baa85 100644
--- a/blocks/recentlyaccesseditems/amd/build/repository.min.js
+++ b/blocks/recentlyaccesseditems/amd/build/repository.min.js
@@ -1,2 +1,10 @@
-define ("block_recentlyaccesseditems/repository",["core/ajax"],function(a){return{getRecentItems:function getRecentItems(b){var c={};if("undefined"!=typeof b){c.limit=b}return a.call([{methodname:"block_recentlyaccesseditems_get_recent_items",args:c}])[0]}}});
-//# sourceMappingURL=repository.min.js.map
+/**
+ * A javascript module to handle user ajax actions.
+ *
+ * @module block_recentlyaccesseditems/repository
+ * @copyright 2018 Victor Deniz
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_recentlyaccesseditems/repository",["core/ajax"],(function(Ajax){return{getRecentItems:function(limit){var args={};void 0!==limit&&(args.limit=limit);var request={methodname:"block_recentlyaccesseditems_get_recent_items",args:args};return Ajax.call([request])[0]}}}));
+
+//# sourceMappingURL=repository.min.js.map
\ No newline at end of file
diff --git a/blocks/recentlyaccesseditems/amd/build/repository.min.js.map b/blocks/recentlyaccesseditems/amd/build/repository.min.js.map
index 6037b6471a0..07ca64dd574 100644
--- a/blocks/recentlyaccesseditems/amd/build/repository.min.js.map
+++ b/blocks/recentlyaccesseditems/amd/build/repository.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/repository.js"],"names":["define","Ajax","getRecentItems","limit","args","call","methodname"],"mappings":"AAsBAA,OAAM,0CAAC,CAAC,WAAD,CAAD,CAAgB,SAASC,CAAT,CAAe,CAoBjC,MAAO,CACHC,cAAc,CAZG,QAAjBA,CAAAA,cAAiB,CAASC,CAAT,CAAgB,CACjC,GAAIC,CAAAA,CAAI,CAAG,EAAX,CACA,GAAqB,WAAjB,QAAOD,CAAAA,CAAX,CAAkC,CAC9BC,CAAI,CAACD,KAAL,CAAaA,CAChB,CAKD,MAAOF,CAAAA,CAAI,CAACI,IAAL,CAAU,CAJH,CACVC,UAAU,CAAE,8CADF,CAEVF,IAAI,CAAEA,CAFI,CAIG,CAAV,EAAqB,CAArB,CACV,CACM,CAGV,CAvBK,CAAN","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 .\n\n/**\n * A javascript module to handle user ajax actions.\n *\n * @module block_recentlyaccesseditems/repository\n * @copyright 2018 Victor Deniz \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['core/ajax'], function(Ajax) {\n\n /**\n * Get the list of items that the user has most recently accessed.\n *\n * @method getRecentItems\n * @param {int} limit Only return this many results\n * @return {promise} Resolved with an array of items\n */\n var getRecentItems = function(limit) {\n var args = {};\n if (typeof limit !== 'undefined') {\n args.limit = limit;\n }\n var request = {\n methodname: 'block_recentlyaccesseditems_get_recent_items',\n args: args\n };\n return Ajax.call([request])[0];\n };\n return {\n getRecentItems: getRecentItems\n };\n});"],"file":"repository.min.js"}
\ No newline at end of file
+{"version":3,"file":"repository.min.js","sources":["../src/repository.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 .\n\n/**\n * A javascript module to handle user ajax actions.\n *\n * @module block_recentlyaccesseditems/repository\n * @copyright 2018 Victor Deniz \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['core/ajax'], function(Ajax) {\n\n /**\n * Get the list of items that the user has most recently accessed.\n *\n * @method getRecentItems\n * @param {int} limit Only return this many results\n * @return {promise} Resolved with an array of items\n */\n var getRecentItems = function(limit) {\n var args = {};\n if (typeof limit !== 'undefined') {\n args.limit = limit;\n }\n var request = {\n methodname: 'block_recentlyaccesseditems_get_recent_items',\n args: args\n };\n return Ajax.call([request])[0];\n };\n return {\n getRecentItems: getRecentItems\n };\n});"],"names":["define","Ajax","getRecentItems","limit","args","request","methodname","call"],"mappings":";;;;;;;AAsBAA,gDAAO,CAAC,cAAc,SAASC,YAoBpB,CACHC,eAZiB,SAASC,WACtBC,KAAO,QACU,IAAVD,QACPC,KAAKD,MAAQA,WAEbE,QAAU,CACVC,WAAY,+CACZF,KAAMA,aAEHH,KAAKM,KAAK,CAACF,UAAU"}
\ No newline at end of file
diff --git a/blocks/settings/amd/build/settingsblock.min.js b/blocks/settings/amd/build/settingsblock.min.js
index c6815839b16..cc85e1eacc0 100644
--- a/blocks/settings/amd/build/settingsblock.min.js
+++ b/blocks/settings/amd/build/settingsblock.min.js
@@ -1,2 +1,10 @@
-define ("block_settings/settingsblock",["exports","core_block/events","core/tree"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;c=function(a){return a&&a.__esModule?a:{default:a}}(c);var d=function(a,d){var e=new c.default(".block_settings .block_tree"),f=document.querySelector("[data-instance-id=\"".concat(a,"\"]"));if(d){var g=e.treeRoot.get(0).querySelector("#".concat(d," a")),h=document.createElement("span");h.setAttribute("tabindex","0");g.childNodes.forEach(function(a){return h.appendChild(a)});g.replaceWith(h)}e.finishExpandingGroup=function(a){c.default.prototype.finishExpandingGroup.call(e,a);(0,b.notifyBlockContentUpdated)(f)};e.collapseGroup=function(a){c.default.prototype.collapseGroup.call(e,a);(0,b.notifyBlockContentUpdated)(f)}};a.init=d});
-//# sourceMappingURL=settingsblock.min.js.map
+define("block_settings/settingsblock",["exports","core_block/events","core/tree"],(function(_exports,_events,_tree){var obj;
+/**
+ * Load the settings block tree javscript
+ *
+ * @module block_settings/settingsblock
+ * @copyright 2015 John Okely
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_tree=(obj=_tree)&&obj.__esModule?obj:{default:obj};_exports.init=(instanceId,siteAdminNodeId)=>{const adminTree=new _tree.default(".block_settings .block_tree"),blockNode=document.querySelector('[data-instance-id="'.concat(instanceId,'"]'));if(siteAdminNodeId){const siteAdminLink=adminTree.treeRoot.get(0).querySelector("#".concat(siteAdminNodeId," a")),newContainer=document.createElement("span");newContainer.setAttribute("tabindex","0"),siteAdminLink.childNodes.forEach((node=>newContainer.appendChild(node))),siteAdminLink.replaceWith(newContainer)}adminTree.finishExpandingGroup=function(item){_tree.default.prototype.finishExpandingGroup.call(adminTree,item),(0,_events.notifyBlockContentUpdated)(blockNode)},adminTree.collapseGroup=function(item){_tree.default.prototype.collapseGroup.call(adminTree,item),(0,_events.notifyBlockContentUpdated)(blockNode)}}}));
+
+//# sourceMappingURL=settingsblock.min.js.map
\ No newline at end of file
diff --git a/blocks/settings/amd/build/settingsblock.min.js.map b/blocks/settings/amd/build/settingsblock.min.js.map
index 6d4ea5a2821..50d99b7282f 100644
--- a/blocks/settings/amd/build/settingsblock.min.js.map
+++ b/blocks/settings/amd/build/settingsblock.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/settingsblock.js"],"names":["init","instanceId","siteAdminNodeId","adminTree","Tree","blockNode","document","querySelector","siteAdminLink","treeRoot","get","newContainer","createElement","setAttribute","childNodes","forEach","node","appendChild","replaceWith","finishExpandingGroup","item","prototype","call","collapseGroup"],"mappings":"+KAuBA,uDAEO,GAAMA,CAAAA,CAAI,CAAG,SAACC,CAAD,CAAaC,CAAb,CAAiC,IAC3CC,CAAAA,CAAS,CAAG,GAAIC,UAAJ,CAAS,6BAAT,CAD+B,CAE3CC,CAAS,CAAGC,QAAQ,CAACC,aAAT,+BAA6CN,CAA7C,QAF+B,CAIjD,GAAIC,CAAJ,CAAqB,IACXM,CAAAA,CAAa,CAAGL,CAAS,CAACM,QAAV,CAAmBC,GAAnB,CAAuB,CAAvB,EAA0BH,aAA1B,YAA4CL,CAA5C,OADL,CAEXS,CAAY,CAAGL,QAAQ,CAACM,aAAT,CAAuB,MAAvB,CAFJ,CAGjBD,CAAY,CAACE,YAAb,CAA0B,UAA1B,CAAsC,GAAtC,EACAL,CAAa,CAACM,UAAd,CAAyBC,OAAzB,CAAiC,SAAAC,CAAI,QAAIL,CAAAA,CAAY,CAACM,WAAb,CAAyBD,CAAzB,CAAJ,CAArC,EACAR,CAAa,CAACU,WAAd,CAA0BP,CAA1B,CACH,CASDR,CAAS,CAACgB,oBAAV,CAAiC,SAASC,CAAT,CAAe,CAC5ChB,UAAKiB,SAAL,CAAeF,oBAAf,CAAoCG,IAApC,CAAyCnB,CAAzC,CAAoDiB,CAApD,EACA,gCAA0Bf,CAA1B,CACH,CAHD,CAYAF,CAAS,CAACoB,aAAV,CAA0B,SAASH,CAAT,CAAe,CACrChB,UAAKiB,SAAL,CAAeE,aAAf,CAA6BD,IAA7B,CAAkCnB,CAAlC,CAA6CiB,CAA7C,EACA,gCAA0Bf,CAA1B,CACH,CACJ,CAnCM,C","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 .\n\n/**\n * Load the settings block tree javscript\n *\n * @module block_settings/settingsblock\n * @copyright 2015 John Okely \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {notifyBlockContentUpdated} from 'core_block/events';\nimport Tree from 'core/tree';\n\nexport const init = (instanceId, siteAdminNodeId) => {\n const adminTree = new Tree(\".block_settings .block_tree\");\n const blockNode = document.querySelector(`[data-instance-id=\"${instanceId}\"]`);\n\n if (siteAdminNodeId) {\n const siteAdminLink = adminTree.treeRoot.get(0).querySelector(`#${siteAdminNodeId} a`);\n const newContainer = document.createElement('span');\n newContainer.setAttribute('tabindex', '0');\n siteAdminLink.childNodes.forEach(node => newContainer.appendChild(node));\n siteAdminLink.replaceWith(newContainer);\n }\n\n /**\n * The method to call when then the navtree finishes expanding a group.\n *\n * @method finishExpandingGroup\n * @param {Object} item\n * @fires event:blockContentUpdated\n */\n adminTree.finishExpandingGroup = function(item) {\n Tree.prototype.finishExpandingGroup.call(adminTree, item);\n notifyBlockContentUpdated(blockNode);\n };\n\n /**\n * The method to call whe then the navtree collapses a group\n *\n * @method collapseGroup\n * @param {Object} item\n * @fires event:blockContentUpdated\n */\n adminTree.collapseGroup = function(item) {\n Tree.prototype.collapseGroup.call(adminTree, item);\n notifyBlockContentUpdated(blockNode);\n };\n};\n"],"file":"settingsblock.min.js"}
\ No newline at end of file
+{"version":3,"file":"settingsblock.min.js","sources":["../src/settingsblock.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 .\n\n/**\n * Load the settings block tree javscript\n *\n * @module block_settings/settingsblock\n * @copyright 2015 John Okely \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {notifyBlockContentUpdated} from 'core_block/events';\nimport Tree from 'core/tree';\n\nexport const init = (instanceId, siteAdminNodeId) => {\n const adminTree = new Tree(\".block_settings .block_tree\");\n const blockNode = document.querySelector(`[data-instance-id=\"${instanceId}\"]`);\n\n if (siteAdminNodeId) {\n const siteAdminLink = adminTree.treeRoot.get(0).querySelector(`#${siteAdminNodeId} a`);\n const newContainer = document.createElement('span');\n newContainer.setAttribute('tabindex', '0');\n siteAdminLink.childNodes.forEach(node => newContainer.appendChild(node));\n siteAdminLink.replaceWith(newContainer);\n }\n\n /**\n * The method to call when then the navtree finishes expanding a group.\n *\n * @method finishExpandingGroup\n * @param {Object} item\n * @fires event:blockContentUpdated\n */\n adminTree.finishExpandingGroup = function(item) {\n Tree.prototype.finishExpandingGroup.call(adminTree, item);\n notifyBlockContentUpdated(blockNode);\n };\n\n /**\n * The method to call whe then the navtree collapses a group\n *\n * @method collapseGroup\n * @param {Object} item\n * @fires event:blockContentUpdated\n */\n adminTree.collapseGroup = function(item) {\n Tree.prototype.collapseGroup.call(adminTree, item);\n notifyBlockContentUpdated(blockNode);\n };\n};\n"],"names":["instanceId","siteAdminNodeId","adminTree","Tree","blockNode","document","querySelector","siteAdminLink","treeRoot","get","newContainer","createElement","setAttribute","childNodes","forEach","node","appendChild","replaceWith","finishExpandingGroup","item","prototype","call","collapseGroup"],"mappings":";;;;;;;oJAyBoB,CAACA,WAAYC,yBACvBC,UAAY,IAAIC,cAAK,+BACrBC,UAAYC,SAASC,2CAAoCN,qBAE3DC,gBAAiB,OACXM,cAAgBL,UAAUM,SAASC,IAAI,GAAGH,yBAAkBL,uBAC5DS,aAAeL,SAASM,cAAc,QAC5CD,aAAaE,aAAa,WAAY,KACtCL,cAAcM,WAAWC,SAAQC,MAAQL,aAAaM,YAAYD,QAClER,cAAcU,YAAYP,cAU9BR,UAAUgB,qBAAuB,SAASC,oBACjCC,UAAUF,qBAAqBG,KAAKnB,UAAWiB,4CAC1Bf,YAU9BF,UAAUoB,cAAgB,SAASH,oBAC1BC,UAAUE,cAAcD,KAAKnB,UAAWiB,4CACnBf"}
\ No newline at end of file
diff --git a/blocks/starredcourses/amd/build/main.min.js b/blocks/starredcourses/amd/build/main.min.js
index 060eb3e88ef..771e6c5c027 100644
--- a/blocks/starredcourses/amd/build/main.min.js
+++ b/blocks/starredcourses/amd/build/main.min.js
@@ -1,2 +1,10 @@
-define ("block_starredcourses/main",["jquery","core/notification","block_starredcourses/repository","core/pubsub","core/templates","core_course/events"],function(a,b,c,d,e,f){var g={BLOCK_CONTAINER:"[data-region=\"starred-courses\"]",STARRED_COURSES_REGION_VIEW:"[data-region=\"starred-courses-view\"]",STARRED_COURSES_REGION:"[data-region=\"starred-courses-view-content\"]"},h=function(a,b){if(0
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_starredcourses/main",["jquery","core/notification","block_starredcourses/repository","core/pubsub","core/templates","core_course/events"],(function($,Notification,Repository,PubSub,Templates,CourseEvents){var SELECTORS_BLOCK_CONTAINER='[data-region="starred-courses"]',SELECTORS_STARRED_COURSES_REGION_VIEW='[data-region="starred-courses-view"]',SELECTORS_STARRED_COURSES_REGION='[data-region="starred-courses-view-content"]',reloadContent=function(root){var content=root.find(SELECTORS_STARRED_COURSES_REGION);return Repository.getStarredCourses({limit:0,offset:0}).then((function(courses){var showcoursecategory=$(SELECTORS_BLOCK_CONTAINER).data("displaycoursecategory");return courses=courses.map((function(course){return course.showcoursecategory=showcoursecategory,course})),function(root,courses){if(courses.length>0)return Templates.render("core_course/view-cards",{courses:courses});var nocoursesimg=root.find(SELECTORS_STARRED_COURSES_REGION_VIEW).attr("data-nocoursesimg");return Templates.render("block_starredcourses/no-courses",{nocoursesimg:nocoursesimg})}(root,courses)})).then((function(html,js){return Templates.replaceNodeContents(content,html,js)})).catch(Notification.exception)};return{init:function(root){(function(root){PubSub.subscribe(CourseEvents.favourited,(function(){reloadContent(root)})),PubSub.subscribe(CourseEvents.unfavorited,(function(){reloadContent(root)}))})(root=$(root)),reloadContent(root)}}}));
+
+//# sourceMappingURL=main.min.js.map
\ No newline at end of file
diff --git a/blocks/starredcourses/amd/build/main.min.js.map b/blocks/starredcourses/amd/build/main.min.js.map
index 23eeb0c8cca..6f4db1059de 100644
--- a/blocks/starredcourses/amd/build/main.min.js.map
+++ b/blocks/starredcourses/amd/build/main.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/main.js"],"names":["define","$","Notification","Repository","PubSub","Templates","CourseEvents","SELECTORS","BLOCK_CONTAINER","STARRED_COURSES_REGION_VIEW","STARRED_COURSES_REGION","renderCourses","root","courses","length","render","nocoursesimg","find","attr","reloadContent","content","getStarredCourses","limit","offset","then","showcoursecategory","data","map","course","html","js","replaceNodeContents","catch","exception","registerEventListeners","subscribe","favourited","unfavorited","init"],"mappings":"AAuBAA,OAAM,6BACN,CACI,QADJ,CAEI,mBAFJ,CAGI,iCAHJ,CAII,aAJJ,CAKI,gBALJ,CAMI,oBANJ,CADM,CASN,SACIC,CADJ,CAEIC,CAFJ,CAGIC,CAHJ,CAIIC,CAJJ,CAKIC,CALJ,CAMIC,CANJ,CAOE,IAEMC,CAAAA,CAAS,CAAG,CACZC,eAAe,CAAE,mCADL,CAEZC,2BAA2B,CAAE,wCAFjB,CAGZC,sBAAsB,CAAE,gDAHZ,CAFlB,CAgBMC,CAAa,CAAG,SAASC,CAAT,CAAeC,CAAf,CAAwB,CACxC,GAAqB,CAAjB,CAAAA,CAAO,CAACC,MAAZ,CAAwB,CACpB,MAAOT,CAAAA,CAAS,CAACU,MAAV,CAAiB,wBAAjB,CAA2C,CAC9CF,OAAO,CAAEA,CADqC,CAA3C,CAGV,CAJD,IAIO,CACH,GAAIG,CAAAA,CAAY,CAAGJ,CAAI,CAACK,IAAL,CAAUV,CAAS,CAACE,2BAApB,EAAiDS,IAAjD,CAAsD,mBAAtD,CAAnB,CACA,MAAOb,CAAAA,CAAS,CAACU,MAAV,CAAiB,iCAAjB,CAAoD,CACvDC,YAAY,CAAEA,CADyC,CAApD,CAGV,CACJ,CA3BH,CAmCMG,CAAa,CAAG,SAASP,CAAT,CAAe,IAC3BQ,CAAAA,CAAO,CAAGR,CAAI,CAACK,IAAL,CAAUV,CAAS,CAACG,sBAApB,CADiB,CAQ/B,MAAOP,CAAAA,CAAU,CAACkB,iBAAX,CALI,CACPC,KAAK,CAAE,CADA,CAEPC,MAAM,CAAE,CAFD,CAKJ,EACFC,IADE,CACG,SAASX,CAAT,CAAkB,CAEpB,GAAIY,CAAAA,CAAkB,CAAGxB,CAAC,CAACM,CAAS,CAACC,eAAX,CAAD,CAA6BkB,IAA7B,CAAkC,uBAAlC,CAAzB,CACAb,CAAO,CAAGA,CAAO,CAACc,GAAR,CAAY,SAASC,CAAT,CAAiB,CACnCA,CAAM,CAACH,kBAAP,CAA4BA,CAA5B,CACA,MAAOG,CAAAA,CACV,CAHS,CAAV,CAIA,MAAOjB,CAAAA,CAAa,CAACC,CAAD,CAAOC,CAAP,CACvB,CATE,EASAW,IATA,CASK,SAASK,CAAT,CAAeC,CAAf,CAAmB,CACvB,MAAOzB,CAAAA,CAAS,CAAC0B,mBAAV,CAA8BX,CAA9B,CAAuCS,CAAvC,CAA6CC,CAA7C,CACV,CAXE,EAWAE,KAXA,CAWM9B,CAAY,CAAC+B,SAXnB,CAYV,CAvDH,CA8DMC,CAAsB,CAAG,SAAStB,CAAT,CAAe,CACxCR,CAAM,CAAC+B,SAAP,CAAiB7B,CAAY,CAAC8B,UAA9B,CAA0C,UAAW,CACjDjB,CAAa,CAACP,CAAD,CAChB,CAFD,EAIAR,CAAM,CAAC+B,SAAP,CAAiB7B,CAAY,CAAC+B,WAA9B,CAA2C,UAAW,CAClDlB,CAAa,CAACP,CAAD,CAChB,CAFD,CAGH,CAtEH,CAoFE,MAAO,CACH0B,IAAI,CARG,QAAPA,CAAAA,IAAO,CAAS1B,CAAT,CAAe,CACtBA,CAAI,CAAGX,CAAC,CAACW,CAAD,CAAR,CAEAsB,CAAsB,CAACtB,CAAD,CAAtB,CACAO,CAAa,CAACP,CAAD,CAChB,CAEM,CAGV,CAvGK,CAAN","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 .\n\n/**\n * Javascript to initialise the starred courses block.\n *\n * @module block_starredcourses/main\n * @copyright 2018 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'core/notification',\n 'block_starredcourses/repository',\n 'core/pubsub',\n 'core/templates',\n 'core_course/events'\n],\nfunction(\n $,\n Notification,\n Repository,\n PubSub,\n Templates,\n CourseEvents\n) {\n\n var SELECTORS = {\n BLOCK_CONTAINER: '[data-region=\"starred-courses\"]',\n STARRED_COURSES_REGION_VIEW: '[data-region=\"starred-courses-view\"]',\n STARRED_COURSES_REGION: '[data-region=\"starred-courses-view-content\"]'\n };\n\n /**\n * Render the starred courses.\n *\n * @method renderCourses\n * @param {object} root The root element for the starred view.\n * @param {array} courses containing array of returned courses.\n * @returns {promise} Resolved with HTML and JS strings\n */\n var renderCourses = function(root, courses) {\n if (courses.length > 0) {\n return Templates.render('core_course/view-cards', {\n courses: courses\n });\n } else {\n var nocoursesimg = root.find(SELECTORS.STARRED_COURSES_REGION_VIEW).attr('data-nocoursesimg');\n return Templates.render('block_starredcourses/no-courses', {\n nocoursesimg: nocoursesimg\n });\n }\n };\n\n /**\n * Fetch user's starred courses and reload the content of the block.\n *\n * @param {object} root The root element for the starred view.\n * @returns {promise} The updated content for the block.\n */\n var reloadContent = function(root) {\n var content = root.find(SELECTORS.STARRED_COURSES_REGION);\n\n var args = {\n limit: 0,\n offset: 0,\n };\n\n return Repository.getStarredCourses(args)\n .then(function(courses) {\n // Whether the course category should be displayed in the course item.\n var showcoursecategory = $(SELECTORS.BLOCK_CONTAINER).data('displaycoursecategory');\n courses = courses.map(function(course) {\n course.showcoursecategory = showcoursecategory;\n return course;\n });\n return renderCourses(root, courses);\n }).then(function(html, js) {\n return Templates.replaceNodeContents(content, html, js);\n }).catch(Notification.exception);\n };\n\n /**\n * Register event listeners for the block.\n *\n * @param {object} root The calendar root element\n */\n var registerEventListeners = function(root) {\n PubSub.subscribe(CourseEvents.favourited, function() {\n reloadContent(root);\n });\n\n PubSub.subscribe(CourseEvents.unfavorited, function() {\n reloadContent(root);\n });\n };\n\n /**\n * Initialise all of the modules for the starred courses block.\n *\n * @param {object} root The root element for the block.\n */\n var init = function(root) {\n root = $(root);\n\n registerEventListeners(root);\n reloadContent(root);\n };\n\n return {\n init: init\n };\n});\n"],"file":"main.min.js"}
\ No newline at end of file
+{"version":3,"file":"main.min.js","sources":["../src/main.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 .\n\n/**\n * Javascript to initialise the starred courses block.\n *\n * @module block_starredcourses/main\n * @copyright 2018 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'core/notification',\n 'block_starredcourses/repository',\n 'core/pubsub',\n 'core/templates',\n 'core_course/events'\n],\nfunction(\n $,\n Notification,\n Repository,\n PubSub,\n Templates,\n CourseEvents\n) {\n\n var SELECTORS = {\n BLOCK_CONTAINER: '[data-region=\"starred-courses\"]',\n STARRED_COURSES_REGION_VIEW: '[data-region=\"starred-courses-view\"]',\n STARRED_COURSES_REGION: '[data-region=\"starred-courses-view-content\"]'\n };\n\n /**\n * Render the starred courses.\n *\n * @method renderCourses\n * @param {object} root The root element for the starred view.\n * @param {array} courses containing array of returned courses.\n * @returns {promise} Resolved with HTML and JS strings\n */\n var renderCourses = function(root, courses) {\n if (courses.length > 0) {\n return Templates.render('core_course/view-cards', {\n courses: courses\n });\n } else {\n var nocoursesimg = root.find(SELECTORS.STARRED_COURSES_REGION_VIEW).attr('data-nocoursesimg');\n return Templates.render('block_starredcourses/no-courses', {\n nocoursesimg: nocoursesimg\n });\n }\n };\n\n /**\n * Fetch user's starred courses and reload the content of the block.\n *\n * @param {object} root The root element for the starred view.\n * @returns {promise} The updated content for the block.\n */\n var reloadContent = function(root) {\n var content = root.find(SELECTORS.STARRED_COURSES_REGION);\n\n var args = {\n limit: 0,\n offset: 0,\n };\n\n return Repository.getStarredCourses(args)\n .then(function(courses) {\n // Whether the course category should be displayed in the course item.\n var showcoursecategory = $(SELECTORS.BLOCK_CONTAINER).data('displaycoursecategory');\n courses = courses.map(function(course) {\n course.showcoursecategory = showcoursecategory;\n return course;\n });\n return renderCourses(root, courses);\n }).then(function(html, js) {\n return Templates.replaceNodeContents(content, html, js);\n }).catch(Notification.exception);\n };\n\n /**\n * Register event listeners for the block.\n *\n * @param {object} root The calendar root element\n */\n var registerEventListeners = function(root) {\n PubSub.subscribe(CourseEvents.favourited, function() {\n reloadContent(root);\n });\n\n PubSub.subscribe(CourseEvents.unfavorited, function() {\n reloadContent(root);\n });\n };\n\n /**\n * Initialise all of the modules for the starred courses block.\n *\n * @param {object} root The root element for the block.\n */\n var init = function(root) {\n root = $(root);\n\n registerEventListeners(root);\n reloadContent(root);\n };\n\n return {\n init: init\n };\n});\n"],"names":["define","$","Notification","Repository","PubSub","Templates","CourseEvents","SELECTORS","reloadContent","root","content","find","getStarredCourses","limit","offset","then","courses","showcoursecategory","data","map","course","length","render","nocoursesimg","attr","renderCourses","html","js","replaceNodeContents","catch","exception","init","subscribe","favourited","unfavorited","registerEventListeners"],"mappings":";;;;;;;AAuBAA,mCACA,CACI,SACA,oBACA,kCACA,cACA,iBACA,uBAEJ,SACIC,EACAC,aACAC,WACAC,OACAC,UACAC,kBAGIC,0BACiB,kCADjBA,sCAE6B,uCAF7BA,iCAGwB,+CA8BxBC,cAAgB,SAASC,UACrBC,QAAUD,KAAKE,KAAKJ,yCAOjBJ,WAAWS,kBALP,CACPC,MAAO,EACPC,OAAQ,IAIPC,MAAK,SAASC,aAEPC,mBAAqBhB,EAAEM,2BAA2BW,KAAK,gCAC3DF,QAAUA,QAAQG,KAAI,SAASC,eAC3BA,OAAOH,mBAAqBA,mBACrBG,UAjCH,SAASX,KAAMO,YAC3BA,QAAQK,OAAS,SACVhB,UAAUiB,OAAO,yBAA0B,CAC9CN,QAASA,cAGTO,aAAed,KAAKE,KAAKJ,uCAAuCiB,KAAK,4BAClEnB,UAAUiB,OAAO,kCAAmC,CACvDC,aAAcA,eA2BPE,CAAchB,KAAMO,YAC5BD,MAAK,SAASW,KAAMC,WACZtB,UAAUuB,oBAAoBlB,QAASgB,KAAMC,OACrDE,MAAM3B,aAAa4B,kBA8BvB,CACHC,KARO,SAAStB,OAfS,SAASA,MAClCL,OAAO4B,UAAU1B,aAAa2B,YAAY,WACtCzB,cAAcC,SAGlBL,OAAO4B,UAAU1B,aAAa4B,aAAa,WACvC1B,cAAcC,UAYlB0B,CAFA1B,KAAOR,EAAEQ,OAGTD,cAAcC"}
\ No newline at end of file
diff --git a/blocks/starredcourses/amd/build/repository.min.js b/blocks/starredcourses/amd/build/repository.min.js
index 98c45aad3e3..f5b0d4bd552 100644
--- a/blocks/starredcourses/amd/build/repository.min.js
+++ b/blocks/starredcourses/amd/build/repository.min.js
@@ -1,2 +1,10 @@
-define ("block_starredcourses/repository",["jquery","core/ajax","core/notification"],function(a,b,c){return{getStarredCourses:function getStarredCourses(a){var d=b.call([{methodname:"block_starredcourses_get_starred_courses",args:a}])[0];d.fail(c.exception);return d}}});
-//# sourceMappingURL=repository.min.js.map
+/**
+ * A javascript module to retrieve user's starred courses.
+ *
+ * @module block_starredcourses/repository
+ * @copyright 2018 Simey Lameze
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_starredcourses/repository",["jquery","core/ajax","core/notification"],(function($,Ajax,Notification){return{getStarredCourses:function(args){var request={methodname:"block_starredcourses_get_starred_courses",args:args},promise=Ajax.call([request])[0];return promise.fail(Notification.exception),promise}}}));
+
+//# sourceMappingURL=repository.min.js.map
\ No newline at end of file
diff --git a/blocks/starredcourses/amd/build/repository.min.js.map b/blocks/starredcourses/amd/build/repository.min.js.map
index 3b99a7bc119..e2d69161fdf 100644
--- a/blocks/starredcourses/amd/build/repository.min.js.map
+++ b/blocks/starredcourses/amd/build/repository.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/repository.js"],"names":["define","$","Ajax","Notification","getStarredCourses","args","promise","call","methodname","fail","exception"],"mappings":"AAsBAA,OAAM,mCAAC,CAAC,QAAD,CAAW,WAAX,CAAwB,mBAAxB,CAAD,CAA+C,SAASC,CAAT,CAAYC,CAAZ,CAAkBC,CAAlB,CAAgC,CA2BjF,MAAO,CACHC,iBAAiB,CAfG,QAApBA,CAAAA,iBAAoB,CAASC,CAAT,CAAe,IAO/BC,CAAAA,CAAO,CAAGJ,CAAI,CAACK,IAAL,CAAU,CALV,CACVC,UAAU,CAAE,0CADF,CAEVH,IAAI,CAAEA,CAFI,CAKU,CAAV,EAAqB,CAArB,CAPqB,CASnCC,CAAO,CAACG,IAAR,CAAaN,CAAY,CAACO,SAA1B,EAEA,MAAOJ,CAAAA,CACV,CAEM,CAGV,CA9BK,CAAN","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 .\n\n/**\n * A javascript module to retrieve user's starred courses.\n *\n * @module block_starredcourses/repository\n * @copyright 2018 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notification) {\n\n /**\n * Retrieve a list of starred courses.\n *\n * Valid args are:\n * int limit number of records to retrieve\n * int offset the offset of records to retrieve\n *\n * @method getStarredCourses\n * @param {object} args The request arguments\n * @return {promise} Resolved with an array of courses\n */\n var getStarredCourses = function(args) {\n\n var request = {\n methodname: 'block_starredcourses_get_starred_courses',\n args: args\n };\n\n var promise = Ajax.call([request])[0];\n\n promise.fail(Notification.exception);\n\n return promise;\n };\n\n return {\n getStarredCourses: getStarredCourses\n };\n});\n"],"file":"repository.min.js"}
\ No newline at end of file
+{"version":3,"file":"repository.min.js","sources":["../src/repository.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 .\n\n/**\n * A javascript module to retrieve user's starred courses.\n *\n * @module block_starredcourses/repository\n * @copyright 2018 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notification) {\n\n /**\n * Retrieve a list of starred courses.\n *\n * Valid args are:\n * int limit number of records to retrieve\n * int offset the offset of records to retrieve\n *\n * @method getStarredCourses\n * @param {object} args The request arguments\n * @return {promise} Resolved with an array of courses\n */\n var getStarredCourses = function(args) {\n\n var request = {\n methodname: 'block_starredcourses_get_starred_courses',\n args: args\n };\n\n var promise = Ajax.call([request])[0];\n\n promise.fail(Notification.exception);\n\n return promise;\n };\n\n return {\n getStarredCourses: getStarredCourses\n };\n});\n"],"names":["define","$","Ajax","Notification","getStarredCourses","args","request","methodname","promise","call","fail","exception"],"mappings":";;;;;;;AAsBAA,yCAAO,CAAC,SAAU,YAAa,sBAAsB,SAASC,EAAGC,KAAMC,oBA2B5D,CACHC,kBAfoB,SAASC,UAEzBC,QAAU,CACVC,WAAY,2CACZF,KAAMA,MAGNG,QAAUN,KAAKO,KAAK,CAACH,UAAU,UAEnCE,QAAQE,KAAKP,aAAaQ,WAEnBH"}
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/calendar_events_repository.min.js b/blocks/timeline/amd/build/calendar_events_repository.min.js
index 94e56a9fb61..0f2d8047b67 100644
--- a/blocks/timeline/amd/build/calendar_events_repository.min.js
+++ b/blocks/timeline/amd/build/calendar_events_repository.min.js
@@ -1,2 +1,10 @@
-define ("block_timeline/calendar_events_repository",["jquery","core/ajax","core/notification"],function(a,b,c){return{queryByTime:function queryByTime(a){if(!a.hasOwnProperty("limit")){a.limit=20}a.limitnum=a.limit;delete a.limit;if(a.hasOwnProperty("starttime")){a.timesortfrom=a.starttime;delete a.starttime}if(a.hasOwnProperty("endtime")){a.timesortto=a.endtime;delete a.endtime}a.limittononsuspendedevents=!0;var d=b.call([{methodname:"core_calendar_get_action_events_by_timesort",args:a}])[0];d.fail(c.exception);return d},queryByCourse:function queryByCourse(a){if(!a.hasOwnProperty("limit")){a.limit=20}a.limitnum=a.limit;delete a.limit;if(a.hasOwnProperty("starttime")){a.timesortfrom=a.starttime;delete a.starttime}if(a.hasOwnProperty("endtime")){a.timesortto=a.endtime;delete a.endtime}var d=b.call([{methodname:"core_calendar_get_action_events_by_course",args:a}])[0];d.fail(c.exception);return d},queryByCourses:function queryByCourses(a){if(!a.hasOwnProperty("limit")){a.limit=10}a.limitnum=a.limit;delete a.limit;if(a.hasOwnProperty("starttime")){a.timesortfrom=a.starttime;delete a.starttime}if(a.hasOwnProperty("endtime")){a.timesortto=a.endtime;delete a.endtime}var d=b.call([{methodname:"core_calendar_get_action_events_by_courses",args:a}])[0];d.fail(c.exception);return d}}});
-//# sourceMappingURL=calendar_events_repository.min.js.map
+/**
+ * A javascript module to retrieve calendar events from the server.
+ *
+ * @module block_timeline/calendar_events_repository
+ * @copyright 2018 Ryan Wyllie
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_timeline/calendar_events_repository",["jquery","core/ajax","core/notification"],(function($,Ajax,Notification){return{queryByTime:function(args){args.hasOwnProperty("limit")||(args.limit=20),args.limitnum=args.limit,delete args.limit,args.hasOwnProperty("starttime")&&(args.timesortfrom=args.starttime,delete args.starttime),args.hasOwnProperty("endtime")&&(args.timesortto=args.endtime,delete args.endtime),args.limittononsuspendedevents=!0;var request={methodname:"core_calendar_get_action_events_by_timesort",args:args},promise=Ajax.call([request])[0];return promise.fail(Notification.exception),promise},queryByCourse:function(args){args.hasOwnProperty("limit")||(args.limit=20),args.limitnum=args.limit,delete args.limit,args.hasOwnProperty("starttime")&&(args.timesortfrom=args.starttime,delete args.starttime),args.hasOwnProperty("endtime")&&(args.timesortto=args.endtime,delete args.endtime);var request={methodname:"core_calendar_get_action_events_by_course",args:args},promise=Ajax.call([request])[0];return promise.fail(Notification.exception),promise},queryByCourses:function(args){args.hasOwnProperty("limit")||(args.limit=10),args.limitnum=args.limit,delete args.limit,args.hasOwnProperty("starttime")&&(args.timesortfrom=args.starttime,delete args.starttime),args.hasOwnProperty("endtime")&&(args.timesortto=args.endtime,delete args.endtime);var request={methodname:"core_calendar_get_action_events_by_courses",args:args},promise=Ajax.call([request])[0];return promise.fail(Notification.exception),promise}}}));
+
+//# sourceMappingURL=calendar_events_repository.min.js.map
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/calendar_events_repository.min.js.map b/blocks/timeline/amd/build/calendar_events_repository.min.js.map
index a4aa5e2b7d2..f8dfa0e612e 100644
--- a/blocks/timeline/amd/build/calendar_events_repository.min.js.map
+++ b/blocks/timeline/amd/build/calendar_events_repository.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/calendar_events_repository.js"],"names":["define","$","Ajax","Notification","queryByTime","args","hasOwnProperty","limit","limitnum","timesortfrom","starttime","timesortto","endtime","limittononsuspendedevents","promise","call","methodname","fail","exception","queryByCourse","queryByCourses"],"mappings":"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","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 .\n\n/**\n * A javascript module to retrieve calendar events from the server.\n *\n * @module block_timeline/calendar_events_repository\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notification) {\n\n var DEFAULT_LIMIT = 20;\n\n /**\n * Retrieve a list of calendar events for the logged in user for the\n * given course.\n *\n * Valid args are:\n * int courseid Only get events for this course\n * int starttime Only get events after this time\n * int endtime Only get events before this time\n * int limit Limit the number of results returned\n * int aftereventid Offset the result set from the given id\n *\n * @method queryByCourse\n * @param {object} args The request arguments\n * @return {promise} Resolved with an array of the calendar events\n */\n var queryByCourse = function(args) {\n if (!args.hasOwnProperty('limit')) {\n args.limit = DEFAULT_LIMIT;\n }\n\n args.limitnum = args.limit;\n delete args.limit;\n\n if (args.hasOwnProperty('starttime')) {\n args.timesortfrom = args.starttime;\n delete args.starttime;\n }\n\n if (args.hasOwnProperty('endtime')) {\n args.timesortto = args.endtime;\n delete args.endtime;\n }\n\n var request = {\n methodname: 'core_calendar_get_action_events_by_course',\n args: args\n };\n\n var promise = Ajax.call([request])[0];\n\n promise.fail(Notification.exception);\n\n return promise;\n };\n\n /**\n * Retrieve a list of calendar events for the given courses for the\n * logged in user.\n *\n * Valid args are:\n * array courseids Get events for these courses\n * int starttime Only get events after this time\n * int endtime Only get events before this time\n * int limit Limit the number of results returned\n *\n * @method queryByCourses\n * @param {object} args The request arguments\n * @return {promise} Resolved with an array of the calendar events\n */\n var queryByCourses = function(args) {\n if (!args.hasOwnProperty('limit')) {\n // This is intentionally smaller than the default limit.\n args.limit = 10;\n }\n\n args.limitnum = args.limit;\n delete args.limit;\n\n if (args.hasOwnProperty('starttime')) {\n args.timesortfrom = args.starttime;\n delete args.starttime;\n }\n\n if (args.hasOwnProperty('endtime')) {\n args.timesortto = args.endtime;\n delete args.endtime;\n }\n\n var request = {\n methodname: 'core_calendar_get_action_events_by_courses',\n args: args\n };\n\n var promise = Ajax.call([request])[0];\n\n promise.fail(Notification.exception);\n\n return promise;\n };\n\n /**\n * Retrieve a list of calendar events for the logged in user after the given\n * time.\n *\n * Valid args are:\n * int starttime Only get events after this time\n * int endtime Only get events before this time\n * int limit Limit the number of results returned\n * int aftereventid Offset the result set from the given id\n *\n * @method queryByTime\n * @param {object} args The request arguments\n * @return {promise} Resolved with an array of the calendar events\n */\n var queryByTime = function(args) {\n if (!args.hasOwnProperty('limit')) {\n args.limit = DEFAULT_LIMIT;\n }\n\n args.limitnum = args.limit;\n delete args.limit;\n\n if (args.hasOwnProperty('starttime')) {\n args.timesortfrom = args.starttime;\n delete args.starttime;\n }\n\n if (args.hasOwnProperty('endtime')) {\n args.timesortto = args.endtime;\n delete args.endtime;\n }\n // Don't show events related to courses that the user is suspended in.\n args.limittononsuspendedevents = true;\n\n var request = {\n methodname: 'core_calendar_get_action_events_by_timesort',\n args: args\n };\n\n var promise = Ajax.call([request])[0];\n\n promise.fail(Notification.exception);\n\n return promise;\n };\n\n return {\n queryByTime: queryByTime,\n queryByCourse: queryByCourse,\n queryByCourses: queryByCourses,\n };\n});\n"],"file":"calendar_events_repository.min.js"}
\ No newline at end of file
+{"version":3,"file":"calendar_events_repository.min.js","sources":["../src/calendar_events_repository.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 .\n\n/**\n * A javascript module to retrieve calendar events from the server.\n *\n * @module block_timeline/calendar_events_repository\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notification) {\n\n var DEFAULT_LIMIT = 20;\n\n /**\n * Retrieve a list of calendar events for the logged in user for the\n * given course.\n *\n * Valid args are:\n * int courseid Only get events for this course\n * int starttime Only get events after this time\n * int endtime Only get events before this time\n * int limit Limit the number of results returned\n * int aftereventid Offset the result set from the given id\n *\n * @method queryByCourse\n * @param {object} args The request arguments\n * @return {promise} Resolved with an array of the calendar events\n */\n var queryByCourse = function(args) {\n if (!args.hasOwnProperty('limit')) {\n args.limit = DEFAULT_LIMIT;\n }\n\n args.limitnum = args.limit;\n delete args.limit;\n\n if (args.hasOwnProperty('starttime')) {\n args.timesortfrom = args.starttime;\n delete args.starttime;\n }\n\n if (args.hasOwnProperty('endtime')) {\n args.timesortto = args.endtime;\n delete args.endtime;\n }\n\n var request = {\n methodname: 'core_calendar_get_action_events_by_course',\n args: args\n };\n\n var promise = Ajax.call([request])[0];\n\n promise.fail(Notification.exception);\n\n return promise;\n };\n\n /**\n * Retrieve a list of calendar events for the given courses for the\n * logged in user.\n *\n * Valid args are:\n * array courseids Get events for these courses\n * int starttime Only get events after this time\n * int endtime Only get events before this time\n * int limit Limit the number of results returned\n *\n * @method queryByCourses\n * @param {object} args The request arguments\n * @return {promise} Resolved with an array of the calendar events\n */\n var queryByCourses = function(args) {\n if (!args.hasOwnProperty('limit')) {\n // This is intentionally smaller than the default limit.\n args.limit = 10;\n }\n\n args.limitnum = args.limit;\n delete args.limit;\n\n if (args.hasOwnProperty('starttime')) {\n args.timesortfrom = args.starttime;\n delete args.starttime;\n }\n\n if (args.hasOwnProperty('endtime')) {\n args.timesortto = args.endtime;\n delete args.endtime;\n }\n\n var request = {\n methodname: 'core_calendar_get_action_events_by_courses',\n args: args\n };\n\n var promise = Ajax.call([request])[0];\n\n promise.fail(Notification.exception);\n\n return promise;\n };\n\n /**\n * Retrieve a list of calendar events for the logged in user after the given\n * time.\n *\n * Valid args are:\n * int starttime Only get events after this time\n * int endtime Only get events before this time\n * int limit Limit the number of results returned\n * int aftereventid Offset the result set from the given id\n *\n * @method queryByTime\n * @param {object} args The request arguments\n * @return {promise} Resolved with an array of the calendar events\n */\n var queryByTime = function(args) {\n if (!args.hasOwnProperty('limit')) {\n args.limit = DEFAULT_LIMIT;\n }\n\n args.limitnum = args.limit;\n delete args.limit;\n\n if (args.hasOwnProperty('starttime')) {\n args.timesortfrom = args.starttime;\n delete args.starttime;\n }\n\n if (args.hasOwnProperty('endtime')) {\n args.timesortto = args.endtime;\n delete args.endtime;\n }\n // Don't show events related to courses that the user is suspended in.\n args.limittononsuspendedevents = true;\n\n var request = {\n methodname: 'core_calendar_get_action_events_by_timesort',\n args: args\n };\n\n var promise = Ajax.call([request])[0];\n\n promise.fail(Notification.exception);\n\n return promise;\n };\n\n return {\n queryByTime: queryByTime,\n queryByCourse: queryByCourse,\n queryByCourses: queryByCourses,\n };\n});\n"],"names":["define","$","Ajax","Notification","queryByTime","args","hasOwnProperty","limit","limitnum","timesortfrom","starttime","timesortto","endtime","limittononsuspendedevents","request","methodname","promise","call","fail","exception","queryByCourse","queryByCourses"],"mappings":";;;;;;;AAsBAA,mDAAO,CAAC,SAAU,YAAa,sBAAsB,SAASC,EAAGC,KAAMC,oBA4I5D,CACHC,YAjCc,SAASC,MAClBA,KAAKC,eAAe,WACrBD,KAAKE,MA5GO,IA+GhBF,KAAKG,SAAWH,KAAKE,aACdF,KAAKE,MAERF,KAAKC,eAAe,eACpBD,KAAKI,aAAeJ,KAAKK,iBAClBL,KAAKK,WAGZL,KAAKC,eAAe,aACpBD,KAAKM,WAAaN,KAAKO,eAChBP,KAAKO,SAGhBP,KAAKQ,2BAA4B,MAE7BC,QAAU,CACVC,WAAY,8CACZV,KAAMA,MAGNW,QAAUd,KAAKe,KAAK,CAACH,UAAU,UAEnCE,QAAQE,KAAKf,aAAagB,WAEnBH,SAKPI,cA3HgB,SAASf,MACpBA,KAAKC,eAAe,WACrBD,KAAKE,MAnBO,IAsBhBF,KAAKG,SAAWH,KAAKE,aACdF,KAAKE,MAERF,KAAKC,eAAe,eACpBD,KAAKI,aAAeJ,KAAKK,iBAClBL,KAAKK,WAGZL,KAAKC,eAAe,aACpBD,KAAKM,WAAaN,KAAKO,eAChBP,KAAKO,aAGZE,QAAU,CACVC,WAAY,4CACZV,KAAMA,MAGNW,QAAUd,KAAKe,KAAK,CAACH,UAAU,UAEnCE,QAAQE,KAAKf,aAAagB,WAEnBH,SAiGPK,eAhFiB,SAAShB,MACrBA,KAAKC,eAAe,WAErBD,KAAKE,MAAQ,IAGjBF,KAAKG,SAAWH,KAAKE,aACdF,KAAKE,MAERF,KAAKC,eAAe,eACpBD,KAAKI,aAAeJ,KAAKK,iBAClBL,KAAKK,WAGZL,KAAKC,eAAe,aACpBD,KAAKM,WAAaN,KAAKO,eAChBP,KAAKO,aAGZE,QAAU,CACVC,WAAY,6CACZV,KAAMA,MAGNW,QAAUd,KAAKe,KAAK,CAACH,UAAU,UAEnCE,QAAQE,KAAKf,aAAagB,WAEnBH"}
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/event_list.min.js b/blocks/timeline/amd/build/event_list.min.js
index b97a9ba0924..6027347a307 100644
--- a/blocks/timeline/amd/build/event_list.min.js
+++ b/blocks/timeline/amd/build/event_list.min.js
@@ -1,2 +1,11 @@
-define ("block_timeline/event_list",["jquery","core/notification","core/templates","core/str","core/user_date","block_timeline/calendar_events_repository","core/pending"],function(a,b,c,d,e,f,g){var h=!1,i={EMPTY_MESSAGE:"[data-region=\"no-events-empty-message\"]",ROOT:"[data-region=\"event-list-container\"]",EVENT_LIST_CONTENT:"[data-region=\"event-list-content\"]",EVENT_LIST_WRAPPER:"[data-region=\"event-list-wrapper\"]",EVENT_LIST_LOADING_PLACEHOLDER:"[data-region=\"event-list-loading-placeholder\"]",TIMELINE_BLOCK:"[data-region=\"timeline\"]",TIMELINE_SEARCH:"[data-action=\"search\"]",MORE_ACTIVITIES_BUTTON:"[data-action=\"more-events\"]",MORE_ACTIVITIES_BUTTON_CONTAINER:"[data-region=\"more-events-button-container\"]"},j={EVENT_LIST_CONTENT:"block_timeline/event-list-content",MORE_ACTIVITIES_BUTTON:"block_timeline/event-list-loadmore",LOADING_ICON:"core/loading"},k=function(a){a.find(i.EVENT_LIST_CONTENT).addClass("hidden");a.find(i.EMPTY_MESSAGE).removeClass("hidden")},l=function(a){a.find(i.EVENT_LIST_CONTENT).removeClass("hidden");a.find(i.EMPTY_MESSAGE).addClass("hidden")},m=function(a){a.find(i.EVENT_LIST_CONTENT).empty()},n=function(a){var b={},c={courseview:h,eventsbyday:[]};a.forEach(function(a){var c=a.timeusermidnight;if(b[c]){b[c].push(a)}else{b[c]=[a]}});Object.keys(b).forEach(function(a){var d=b[a];c.eventsbyday.push({dayTimestamp:a,events:d})});return c},o=function(a){var b=n(a),d=j.EVENT_LIST_CONTENT;return c.render(d,b)},p=function(a,b,c,d,e,g,h){var i=d!=void 0?a+d*86400:!1,j={starttime:a+c*86400,limit:b};if(e){j.aftereventid=e}if(i){j.endtime=i}if(h){j.searchvalue=h}if(g){j.courseid=g;return f.queryByCourse(j)}else{return f.queryByTime(j)}},q=function(a,c,d,e,f,g,h,i,j){return r(a,d,e,f,g,h,i,j).then(function(a){if(a.calendarEvents.length){var b=a.calendarEvents.at(-1).id,d=a.calendarEvents.at(-1).timeusermidnight;c.resolve({hasContent:!0,lastId:b,lastTimeStamp:d,loadedAll:a.loadedAll});return o(a.calendarEvents,e)}else{c.resolve({hasContent:!1,lastId:0,lastTimeStamp:0,loadedAll:!0});return a.calendarEvents}}).catch(b.exception)},r=function(a,b,c,d,f,g,h,i){var j=p(c,b+1,g,h,d,f,i),k=[],l=!0;return j.then(function(d){if(!d.events.length){return{calendarEvents:k,loadedAll:l}}var f=document.querySelector("[data-filtername='overdue']"),g=f&&f.getAttribute("aria-current");k=d.events.filter(function(a){if("open"==a.eventtype||"opensubmission"==a.eventtype){var b=e.getUserMidnightForTimestamp(a.timesort,c);return b>c}return!g||a.overdue});l=k.length<=b;if(!l){k.pop()}if(k.length){var h=k.at(-1).id;u(a,h)}return{calendarEvents:k,loadedAll:l}})},s=function(d){var e=parseInt(d.attr("data-midnight"),10),f=d.attr("data-course-id"),g=parseInt(d.attr("data-days-offset"),10),h=d.attr("data-days-limit"),k=t(d),l=d.find(i.EVENT_LIST_WRAPPER),m=d.closest(i.TIMELINE_BLOCK).find(i.TIMELINE_SEARCH).val(),n=r(d,10,e,k,f,g,h,m);n.then(function(e){if(e.calendarEvents.length){var f=o(e.calendarEvents),g=v(d);f.then(function(b,f){b=a(b);b.find("[data-timestamp=\"".concat(g,"\"]")).remove();c.appendNodeContents(l,b.html(),f);if(!e.loadedAll){c.render(j.MORE_ACTIVITIES_BUTTON,{}).then(function(a){l.append(a);w(d,e.calendarEvents.at(-1).timeusermidnight);z(d);return a}).catch(function(){return!1})}return b}).catch(b.exception)}return e}).then(function(){return y(d)}).catch(b.exception)},t=function(a){return parseInt(a.attr("data-lazyload-offset"),10)},u=function(a,b){a.attr("data-lazyload-offset",b)},v=function(a){return parseInt(a.attr("data-timestamp"),10)},w=function(a,b){a.attr("data-timestamp",b)},x=function(a){var b=a.find(i.MORE_ACTIVITIES_BUTTON);b.prop("disabled",!0);c.render(j.LOADING_ICON,{}).then(function(a){b.append(a);return a}).catch(function(){return!1})},y=function(a){var b=a.find(i.MORE_ACTIVITIES_BUTTON_CONTAINER);b.remove()},z=function(a){var b=a.find(i.MORE_ACTIVITIES_BUTTON);b.on("click",function(){x(a);s(a)})};return{init:function init(d){var e=1
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_timeline/event_list",["jquery","core/notification","core/templates","core/str","core/user_date","block_timeline/calendar_events_repository","core/pending"],(function($,Notification,Templates,Str,UserDate,CalendarEventsRepository,Pending){var courseview=!1,SELECTORS_EMPTY_MESSAGE='[data-region="no-events-empty-message"]',SELECTORS_EVENT_LIST_CONTENT='[data-region="event-list-content"]',SELECTORS_EVENT_LIST_WRAPPER='[data-region="event-list-wrapper"]',SELECTORS_EVENT_LIST_LOADING_PLACEHOLDER='[data-region="event-list-loading-placeholder"]',SELECTORS_TIMELINE_BLOCK='[data-region="timeline"]',SELECTORS_TIMELINE_SEARCH='[data-action="search"]',SELECTORS_MORE_ACTIVITIES_BUTTON='[data-action="more-events"]',SELECTORS_MORE_ACTIVITIES_BUTTON_CONTAINER='[data-region="more-events-button-container"]',TEMPLATES_EVENT_LIST_CONTENT="block_timeline/event-list-content",TEMPLATES_MORE_ACTIVITIES_BUTTON="block_timeline/event-list-loadmore",TEMPLATES_LOADING_ICON="core/loading";var hideContent=function(root){root.find(SELECTORS_EVENT_LIST_CONTENT).addClass("hidden"),root.find(SELECTORS_EMPTY_MESSAGE).removeClass("hidden")},showContent=function(root){root.find(SELECTORS_EVENT_LIST_CONTENT).removeClass("hidden"),root.find(SELECTORS_EMPTY_MESSAGE).addClass("hidden")},emptyContent=function(root){root.find(SELECTORS_EVENT_LIST_CONTENT).empty()},render=function(calendarEvents){var templateContext=function(calendarEvents){var eventsByDay={},templateContext={courseview:courseview,eventsbyday:[]};return calendarEvents.forEach((function(calendarEvent){var dayTimestamp=calendarEvent.timeusermidnight;eventsByDay[dayTimestamp]?eventsByDay[dayTimestamp].push(calendarEvent):eventsByDay[dayTimestamp]=[calendarEvent]})),Object.keys(eventsByDay).forEach((function(dayTimestamp){var events=eventsByDay[dayTimestamp];templateContext.eventsbyday.push({dayTimestamp:dayTimestamp,events:events})})),templateContext}(calendarEvents),templateName=TEMPLATES_EVENT_LIST_CONTENT;return Templates.render(templateName,templateContext)};const createLazyLoadingContent=(root,firstLoad,itemLimit,midnight,lastId,courseId,daysOffset,daysLimit,searchValue)=>loadEventsForLazyLoading(root,itemLimit,midnight,lastId,courseId,daysOffset,daysLimit,searchValue).then((data=>{if(data.calendarEvents.length){const lastEventId=data.calendarEvents.at(-1).id,lastTimeStamp=data.calendarEvents.at(-1).timeusermidnight;return firstLoad.resolve({hasContent:!0,lastId:lastEventId,lastTimeStamp:lastTimeStamp,loadedAll:data.loadedAll}),render(data.calendarEvents)}return firstLoad.resolve({hasContent:!1,lastId:0,lastTimeStamp:0,loadedAll:!0}),data.calendarEvents})).catch(Notification.exception),loadEventsForLazyLoading=(root,itemLimit,midnight,lastId,courseId,daysOffset,daysLimit,searchValue)=>{const eventsPromise=function(midnight,limit,daysOffset,daysLimit,lastId,courseId,searchValue){var endTime=null!=daysLimit&&midnight+86400*daysLimit,args={starttime:midnight+86400*daysOffset,limit:limit};return lastId&&(args.aftereventid=lastId),endTime&&(args.endtime=endTime),searchValue&&(args.searchvalue=searchValue),courseId?(args.courseid=courseId,CalendarEventsRepository.queryByCourse(args)):CalendarEventsRepository.queryByTime(args)}(midnight,itemLimit+1,daysOffset,daysLimit,lastId,courseId,searchValue);let calendarEvents=[],loadedAll=!0;return eventsPromise.then((result=>{if(!result.events.length)return{calendarEvents:calendarEvents,loadedAll:loadedAll};const overdueFilter=document.querySelector("[data-filtername='overdue']"),filterByOverdue=overdueFilter&&overdueFilter.getAttribute("aria-current");if(calendarEvents=result.events.filter((event=>{if("open"==event.eventtype||"opensubmission"==event.eventtype){return UserDate.getUserMidnightForTimestamp(event.timesort,midnight)>midnight}return!filterByOverdue||event.overdue})),loadedAll=calendarEvents.length<=itemLimit,loadedAll||calendarEvents.pop(),calendarEvents.length){const lastEventId=calendarEvents.at(-1).id;setOffset(root,lastEventId)}return{calendarEvents:calendarEvents,loadedAll:loadedAll}}))},getOffset=element=>parseInt(element.attr("data-lazyload-offset"),10),setOffset=(element,offset)=>{element.attr("data-lazyload-offset",offset)},getLastTimestamp=element=>parseInt(element.attr("data-timestamp"),10),setLastTimestamp=(element,timestamp)=>{element.attr("data-timestamp",timestamp)},disableMoreActivitiesButtonLoading=root=>{root.find(SELECTORS_MORE_ACTIVITIES_BUTTON_CONTAINER).remove()},initEventListener=root=>{root.find(SELECTORS_MORE_ACTIVITIES_BUTTON).on("click",(()=>{(root=>{const loadMoreButton=root.find(SELECTORS_MORE_ACTIVITIES_BUTTON);loadMoreButton.prop("disabled",!0),Templates.render(TEMPLATES_LOADING_ICON,{}).then((html=>(loadMoreButton.append(html),html))).catch((()=>!1))})(root),(root=>{const midnight=parseInt(root.attr("data-midnight"),10),courseId=root.attr("data-course-id"),daysOffset=parseInt(root.attr("data-days-offset"),10),daysLimit=root.attr("data-days-limit"),lastId=getOffset(root),eventListWrapper=root.find(SELECTORS_EVENT_LIST_WRAPPER),searchValue=root.closest(SELECTORS_TIMELINE_BLOCK).find(SELECTORS_TIMELINE_SEARCH).val();loadEventsForLazyLoading(root,10,midnight,lastId,courseId,daysOffset,daysLimit,searchValue).then((data=>{if(data.calendarEvents.length){const renderPromise=render(data.calendarEvents),lastTimestamp=getLastTimestamp(root);renderPromise.then(((html,js)=>((html=$(html)).find('[data-timestamp="'.concat(lastTimestamp,'"]')).remove(),Templates.appendNodeContents(eventListWrapper,html.html(),js),data.loadedAll||Templates.render(TEMPLATES_MORE_ACTIVITIES_BUTTON,{}).then((html=>(eventListWrapper.append(html),setLastTimestamp(root,data.calendarEvents.at(-1).timeusermidnight),initEventListener(root),html))).catch((()=>!1)),html))).catch(Notification.exception)}return data})).then((()=>disableMoreActivitiesButtonLoading(root))).catch(Notification.exception)})(root)}))};return{init:function(root){let additionalConfig=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const pendingPromise=new Pending("block/timeline:event-init");root=$(root),courseview=!!additionalConfig.courseview;var firstLoad=$.Deferred(),eventListContent=root.find(SELECTORS_EVENT_LIST_CONTENT),loadingPlaceholder=root.find(SELECTORS_EVENT_LIST_LOADING_PLACEHOLDER),courseId=root.attr("data-course-id"),daysOffset=parseInt(root.attr("data-days-offset"),10),daysLimit=root.attr("data-days-limit"),midnight=parseInt(root.attr("data-midnight"),10);const searchValue=root.closest(SELECTORS_TIMELINE_BLOCK).find(SELECTORS_TIMELINE_SEARCH).val();return emptyContent(root),showContent(root),loadingPlaceholder.removeClass("hidden"),null!=daysLimit&&(daysLimit=parseInt(daysLimit,10)),createLazyLoadingContent(root,firstLoad,5,midnight,0,courseId,daysOffset,daysLimit,searchValue).then((function(html,js){return firstLoad.then((function(data){return data.hasContent?((html=$(html)).addClass("hidden"),Templates.replaceNodeContents(eventListContent,html,js),html.removeClass("hidden"),loadingPlaceholder.addClass("hidden"),data.loadedAll||Templates.render(TEMPLATES_MORE_ACTIVITIES_BUTTON,{courseview:courseview}).then((function(html){return eventListContent.append(html),setLastTimestamp(root,data.lastTimeStamp),initEventListener(root),html})).catch((function(){return!1})),data):(loadingPlaceholder.addClass("hidden"),hideContent(root))})).catch((function(){return!1})),html})).then((()=>pendingPromise.resolve())).catch(Notification.exception)},rootSelector:'[data-region="event-list-container"]'}}));
+
+//# sourceMappingURL=event_list.min.js.map
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/event_list.min.js.map b/blocks/timeline/amd/build/event_list.min.js.map
index 4beb2109ac4..10576772a91 100644
--- a/blocks/timeline/amd/build/event_list.min.js.map
+++ b/blocks/timeline/amd/build/event_list.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/event_list.js"],"names":["define","$","Notification","Templates","Str","UserDate","CalendarEventsRepository","Pending","courseview","SELECTORS","EMPTY_MESSAGE","ROOT","EVENT_LIST_CONTENT","EVENT_LIST_WRAPPER","EVENT_LIST_LOADING_PLACEHOLDER","TIMELINE_BLOCK","TIMELINE_SEARCH","MORE_ACTIVITIES_BUTTON","MORE_ACTIVITIES_BUTTON_CONTAINER","TEMPLATES","LOADING_ICON","hideContent","root","find","addClass","removeClass","showContent","emptyContent","empty","buildTemplateContext","calendarEvents","eventsByDay","templateContext","eventsbyday","forEach","calendarEvent","dayTimestamp","timeusermidnight","push","Object","keys","events","render","templateName","load","midnight","limit","daysOffset","daysLimit","lastId","courseId","searchValue","endTime","args","starttime","aftereventid","endtime","searchvalue","courseid","queryByCourse","queryByTime","createLazyLoadingContent","firstLoad","itemLimit","loadEventsForLazyLoading","then","data","length","lastEventId","at","id","lastTimeStamp","resolve","hasContent","loadedAll","catch","exception","eventsPromise","result","overdueFilter","document","querySelector","filterByOverdue","getAttribute","filter","event","eventtype","getUserMidnightForTimestamp","timesort","overdue","pop","setOffset","loadMoreEvents","parseInt","attr","getOffset","eventListWrapper","closest","val","renderPromise","lastTimestamp","getLastTimestamp","html","js","remove","appendNodeContents","append","setLastTimestamp","initEventListener","disableMoreActivitiesButtonLoading","element","offset","timestamp","enableMoreActivitiesButtonLoading","loadMoreButton","prop","loadMoreButtonContainer","on","init","additionalConfig","pendingPromise","Deferred","eventListContent","loadingPlaceholder","replaceNodeContents","rootSelector"],"mappings":"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","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 .\n\n/**\n * Javascript to load and render the list of calendar events for a\n * given day range.\n *\n * @module block_timeline/event_list\n * @copyright 2016 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n 'jquery',\n 'core/notification',\n 'core/templates',\n 'core/str',\n 'core/user_date',\n 'block_timeline/calendar_events_repository',\n 'core/pending'\n],\nfunction(\n $,\n Notification,\n Templates,\n Str,\n UserDate,\n CalendarEventsRepository,\n Pending\n) {\n\n var SECONDS_IN_DAY = 60 * 60 * 24;\n var courseview = false;\n\n var SELECTORS = {\n EMPTY_MESSAGE: '[data-region=\"no-events-empty-message\"]',\n ROOT: '[data-region=\"event-list-container\"]',\n EVENT_LIST_CONTENT: '[data-region=\"event-list-content\"]',\n EVENT_LIST_WRAPPER: '[data-region=\"event-list-wrapper\"]',\n EVENT_LIST_LOADING_PLACEHOLDER: '[data-region=\"event-list-loading-placeholder\"]',\n TIMELINE_BLOCK: '[data-region=\"timeline\"]',\n TIMELINE_SEARCH: '[data-action=\"search\"]',\n MORE_ACTIVITIES_BUTTON: '[data-action=\"more-events\"]',\n MORE_ACTIVITIES_BUTTON_CONTAINER: '[data-region=\"more-events-button-container\"]'\n };\n\n var TEMPLATES = {\n EVENT_LIST_CONTENT: 'block_timeline/event-list-content',\n MORE_ACTIVITIES_BUTTON: 'block_timeline/event-list-loadmore',\n LOADING_ICON: 'core/loading'\n };\n\n /** @type {number} The total items will be shown on the first load. */\n const DEFAULT_LAZY_LOADING_ITEMS_FIRST_LOAD = 5;\n /** @type {number} The total items will be shown when click on the Show more activities button. */\n const DEFAULT_LAZY_LOADING_ITEMS_OTHER_LOAD = 10;\n\n /**\n * Hide the content area and display the empty content message.\n *\n * @param {object} root The container element\n */\n var hideContent = function(root) {\n root.find(SELECTORS.EVENT_LIST_CONTENT).addClass('hidden');\n root.find(SELECTORS.EMPTY_MESSAGE).removeClass('hidden');\n };\n\n /**\n * Show the content area and hide the empty content message.\n *\n * @param {object} root The container element\n */\n var showContent = function(root) {\n root.find(SELECTORS.EVENT_LIST_CONTENT).removeClass('hidden');\n root.find(SELECTORS.EMPTY_MESSAGE).addClass('hidden');\n };\n\n /**\n * Empty the content area.\n *\n * @param {object} root The container element\n */\n var emptyContent = function(root) {\n root.find(SELECTORS.EVENT_LIST_CONTENT).empty();\n };\n\n /**\n * Construct the template context from a list of calendar events. The events\n * are grouped by which day they are on. The day is calculated from the user's\n * midnight timestamp to ensure that the calculation is timezone agnostic.\n *\n * The return data structure will look like:\n * {\n * eventsbyday: [\n * {\n * dayTimestamp: 1533744000,\n * events: [\n * { ...event 1 data... },\n * { ...event 2 data... }\n * ]\n * },\n * {\n * dayTimestamp: 1533830400,\n * events: [\n * { ...event 3 data... },\n * { ...event 4 data... }\n * ]\n * }\n * ]\n * }\n *\n * Each day timestamp is the day's midnight in the user's timezone.\n *\n * @param {array} calendarEvents List of calendar events\n * @return {object}\n */\n var buildTemplateContext = function(calendarEvents) {\n var eventsByDay = {};\n var templateContext = {\n courseview,\n eventsbyday: []\n };\n\n calendarEvents.forEach(function(calendarEvent) {\n var dayTimestamp = calendarEvent.timeusermidnight;\n if (eventsByDay[dayTimestamp]) {\n eventsByDay[dayTimestamp].push(calendarEvent);\n } else {\n eventsByDay[dayTimestamp] = [calendarEvent];\n }\n });\n\n Object.keys(eventsByDay).forEach(function(dayTimestamp) {\n var events = eventsByDay[dayTimestamp];\n templateContext.eventsbyday.push({\n dayTimestamp: dayTimestamp,\n events: events\n });\n });\n\n return templateContext;\n };\n\n /**\n * Render the HTML for the given calendar events.\n *\n * @param {array} calendarEvents A list of calendar events\n * @return {promise} Resolved with HTML and JS strings.\n */\n var render = function(calendarEvents) {\n var templateContext = buildTemplateContext(calendarEvents);\n var templateName = TEMPLATES.EVENT_LIST_CONTENT;\n\n return Templates.render(templateName, templateContext);\n };\n\n /**\n * Retrieve a list of calendar events from the server for the given\n * constraints.\n *\n * @param {Number} midnight The user's midnight time in unix timestamp.\n * @param {Number} limit Limit the result set to this number of items\n * @param {Number} daysOffset How many days (from midnight) to offset the results from\n * @param {int|undefined} daysLimit How many dates (from midnight) to limit the result to\n * @param {int|false} lastId The ID of the last seen event (if any)\n * @param {int|undefined} courseId Course ID to restrict events to\n * @param {string|undefined} searchValue Search value\n * @return {Promise} A jquery promise\n */\n var load = function(midnight, limit, daysOffset, daysLimit, lastId, courseId, searchValue) {\n var startTime = midnight + (daysOffset * SECONDS_IN_DAY);\n var endTime = daysLimit != undefined ? midnight + (daysLimit * SECONDS_IN_DAY) : false;\n\n var args = {\n starttime: startTime,\n limit: limit,\n };\n\n if (lastId) {\n args.aftereventid = lastId;\n }\n\n if (endTime) {\n args.endtime = endTime;\n }\n\n if (searchValue) {\n args.searchvalue = searchValue;\n }\n\n if (courseId) {\n // If we have a course id then we only want events from that course.\n args.courseid = courseId;\n return CalendarEventsRepository.queryByCourse(args);\n } else {\n // Otherwise we want events from any course.\n return CalendarEventsRepository.queryByTime(args);\n }\n };\n\n /**\n * Create a lazy-loading region for the calendar events in the given root element.\n *\n * @param {object} root The event list container element.\n * @param {object} additionalConfig Additional config options to pass to pagedContentFactory.\n */\n var init = function(root, additionalConfig = {}) {\n const pendingPromise = new Pending('block/timeline:event-init');\n root = $(root);\n\n courseview = !!additionalConfig.courseview;\n\n // Create a promise that will be resolved once the first set of page\n // data has been loaded. This ensures that the loading placeholder isn't\n // hidden until we have all of the data back to prevent the page elements\n // jumping around.\n var firstLoad = $.Deferred();\n var eventListContent = root.find(SELECTORS.EVENT_LIST_CONTENT);\n var loadingPlaceholder = root.find(SELECTORS.EVENT_LIST_LOADING_PLACEHOLDER);\n var courseId = root.attr('data-course-id');\n var daysOffset = parseInt(root.attr('data-days-offset'), 10);\n var daysLimit = root.attr('data-days-limit');\n var midnight = parseInt(root.attr('data-midnight'), 10);\n const searchValue = root.closest(SELECTORS.TIMELINE_BLOCK).find(SELECTORS.TIMELINE_SEARCH).val();\n\n // Make sure the content area and loading placeholder is visible.\n // This is because the init function can be called to re-initialise\n // an existing event list area.\n emptyContent(root);\n showContent(root);\n loadingPlaceholder.removeClass('hidden');\n\n // Days limit isn't mandatory.\n if (daysLimit != undefined) {\n daysLimit = parseInt(daysLimit, 10);\n }\n\n // Create the lazy loading content element.\n return createLazyLoadingContent(root, firstLoad,\n DEFAULT_LAZY_LOADING_ITEMS_FIRST_LOAD, midnight, 0, courseId, daysOffset, daysLimit, searchValue)\n .then(function(html, js) {\n firstLoad.then(function(data) {\n if (!data.hasContent) {\n loadingPlaceholder.addClass('hidden');\n // If we didn't get any data then show the empty data message.\n return hideContent(root);\n }\n\n html = $(html);\n // Hide the content for now.\n html.addClass('hidden');\n // Replace existing elements with the newly created lazy-loading region.\n Templates.replaceNodeContents(eventListContent, html, js);\n\n // Prevent changing page elements too much by only showing the content\n // once we've loaded some data for the first time. This allows our\n // fancy loading placeholder to shine.\n html.removeClass('hidden');\n loadingPlaceholder.addClass('hidden');\n\n if (!data.loadedAll) {\n Templates.render(TEMPLATES.MORE_ACTIVITIES_BUTTON, {courseview}).then(function(html) {\n eventListContent.append(html);\n setLastTimestamp(root, data.lastTimeStamp);\n // Init the event handler.\n initEventListener(root);\n return html;\n }).catch(function() {\n return false;\n });\n }\n\n return data;\n })\n .catch(function() {\n return false;\n });\n\n return html;\n }).then(() => {\n return pendingPromise.resolve();\n })\n .catch(Notification.exception);\n };\n\n /**\n * Create a lazy-loading content element for showing the event list for the initial load.\n *\n * @param {object} root The event list container element.\n * @param {object} firstLoad A jQuery promise to be resolved after the first set of data is loaded.\n * @param {int} itemLimit Limit the number of items.\n * @param {Number} midnight The user's midnight time in unix timestamp.\n * @param {int} lastId The last event ID for each loaded page. Page number is key, id is value.\n * @param {int|undefined} courseId Course ID to restrict events to.\n * @param {Number} daysOffset How many days (from midnight) to offset the results from.\n * @param {int|undefined} daysLimit How many dates (from midnight) to limit the result to.\n * @param {string|undefined} searchValue Search value.\n * @return {object} jQuery promise resolved with calendar events.\n */\n const createLazyLoadingContent = (root, firstLoad, itemLimit, midnight, lastId,\n courseId, daysOffset, daysLimit, searchValue) => {\n return loadEventsForLazyLoading(\n root,\n itemLimit,\n midnight,\n lastId,\n courseId,\n daysOffset,\n daysLimit,\n searchValue\n ).then(data => {\n if (data.calendarEvents.length) {\n const lastEventId = data.calendarEvents.at(-1).id;\n const lastTimeStamp = data.calendarEvents.at(-1).timeusermidnight;\n firstLoad.resolve({\n hasContent: true,\n lastId: lastEventId,\n lastTimeStamp: lastTimeStamp,\n loadedAll: data.loadedAll\n });\n return render(data.calendarEvents, midnight);\n } else {\n firstLoad.resolve({\n hasContent: false,\n lastId: 0,\n lastTimeStamp: 0,\n loadedAll: true\n });\n return data.calendarEvents;\n }\n }).catch(Notification.exception);\n };\n\n /**\n * Handle the request from the lazy-loading region.\n * Uses the given data like course id, offset... to request the events from the server.\n *\n * @param {object} root The event list container element.\n * @param {int} itemLimit Limit the number of items.\n * @param {Number} midnight The user's midnight time in unix timestamp.\n * @param {int} lastId The last event ID for each loaded page.\n * @param {int|undefined} courseId Course ID to restrict events to.\n * @param {Number} daysOffset How many days (from midnight) to offset the results from.\n * @param {int|undefined} daysLimit How many dates (from midnight) to limit the result to.\n * @param {string|undefined} searchValue Search value.\n * @return {object} jQuery promise resolved with calendar events.\n */\n const loadEventsForLazyLoading = (root, itemLimit, midnight, lastId, courseId, daysOffset, daysLimit, searchValue) => {\n // Load one more than the given limit so that we can tell if there\n // is more content to load after this.\n const eventsPromise = load(midnight, itemLimit + 1, daysOffset, daysLimit, lastId, courseId, searchValue);\n let calendarEvents = [];\n let loadedAll = true;\n\n return eventsPromise.then(result => {\n if (!result.events.length) {\n return {calendarEvents, loadedAll};\n }\n\n // Determine if the overdue filter is applied.\n const overdueFilter = document.querySelector(\"[data-filtername='overdue']\");\n const filterByOverdue = (overdueFilter && overdueFilter.getAttribute('aria-current'));\n\n calendarEvents = result.events.filter(event => {\n if (event.eventtype == 'open' || event.eventtype == 'opensubmission') {\n const dayTimestamp = UserDate.getUserMidnightForTimestamp(event.timesort, midnight);\n return dayTimestamp > midnight;\n }\n // When filtering by overdue, we fetch all events due today, in case any have elapsed already and are overdue.\n // This means if filtering by overdue, some events fetched might not be required (eg if due later today).\n return (!filterByOverdue || event.overdue);\n });\n\n loadedAll = calendarEvents.length <= itemLimit;\n\n if (!loadedAll) {\n // Remove the last element from the array because it isn't\n // needed in this result set.\n calendarEvents.pop();\n }\n\n if (calendarEvents.length) {\n const lastEventId = calendarEvents.at(-1).id;\n setOffset(root, lastEventId);\n }\n\n return {calendarEvents, loadedAll};\n });\n };\n\n /**\n * Load new events and append to current list.\n *\n * @param {object} root The event list container element.\n */\n const loadMoreEvents = root => {\n const midnight = parseInt(root.attr('data-midnight'), 10);\n const courseId = root.attr('data-course-id');\n const daysOffset = parseInt(root.attr('data-days-offset'), 10);\n const daysLimit = root.attr('data-days-limit');\n const lastId = getOffset(root);\n const eventListWrapper = root.find(SELECTORS.EVENT_LIST_WRAPPER);\n const searchValue = root.closest(SELECTORS.TIMELINE_BLOCK).find(SELECTORS.TIMELINE_SEARCH).val();\n const eventsPromise = loadEventsForLazyLoading(\n root,\n DEFAULT_LAZY_LOADING_ITEMS_OTHER_LOAD,\n midnight,\n lastId,\n courseId,\n daysOffset,\n daysLimit,\n searchValue\n );\n eventsPromise.then(data => {\n if (data.calendarEvents.length) {\n const renderPromise = render(data.calendarEvents);\n const lastTimestamp = getLastTimestamp(root);\n renderPromise.then((html, js) => {\n html = $(html);\n\n // Remove the date heading if it has the same value as the previous one.\n html.find(`[data-timestamp=\"${lastTimestamp}\"]`).remove();\n Templates.appendNodeContents(eventListWrapper, html.html(), js);\n\n if (!data.loadedAll) {\n Templates.render(TEMPLATES.MORE_ACTIVITIES_BUTTON, {}).then(html => {\n eventListWrapper.append(html);\n setLastTimestamp(root, data.calendarEvents.at(-1).timeusermidnight);\n // Init the event handler.\n initEventListener(root);\n\n return html;\n }).catch(() => {\n return false;\n });\n }\n\n return html;\n }).catch(Notification.exception);\n }\n\n return data;\n }).then(() => {\n return disableMoreActivitiesButtonLoading(root);\n }).catch(Notification.exception);\n };\n\n /**\n * Return the offset value for lazy loading fetching.\n *\n * @param {object} element The event list container element.\n * @return {Number} Offset value.\n */\n const getOffset = element => {\n return parseInt(element.attr('data-lazyload-offset'), 10);\n };\n\n /**\n * Set the offset value for lazy loading fetching.\n *\n * @param {object} element The event list container element.\n * @param {Number} offset Offset value.\n */\n const setOffset = (element, offset) => {\n element.attr('data-lazyload-offset', offset);\n };\n\n /**\n * Return the timestamp value for lazy loading fetching.\n *\n * @param {object} element The event list container element.\n * @return {Number} Timestamp value.\n */\n const getLastTimestamp = element => {\n return parseInt(element.attr('data-timestamp'), 10);\n };\n\n /**\n * Set the timestamp value for lazy loading fetching.\n *\n * @param {object} element The event list container element.\n * @param {Number} timestamp Timestamp value.\n */\n const setLastTimestamp = (element, timestamp) => {\n element.attr('data-timestamp', timestamp);\n };\n\n /**\n * Add the \"Show more activities\" button and remove and loading spinner.\n *\n * @param {object} root The event list container element.\n */\n const enableMoreActivitiesButtonLoading = root => {\n const loadMoreButton = root.find(SELECTORS.MORE_ACTIVITIES_BUTTON);\n loadMoreButton.prop('disabled', true);\n Templates.render(TEMPLATES.LOADING_ICON, {}).then(html => {\n loadMoreButton.append(html);\n return html;\n }).catch(() => {\n // It's not important if this false so just do so silently.\n return false;\n });\n };\n\n /**\n * Remove the \"Show more activities\" button and remove and loading spinner.\n *\n * @param {object} root The event list container element.\n */\n const disableMoreActivitiesButtonLoading = root => {\n const loadMoreButtonContainer = root.find(SELECTORS.MORE_ACTIVITIES_BUTTON_CONTAINER);\n loadMoreButtonContainer.remove();\n };\n\n /**\n * Event initialise.\n *\n * @param {object} root The event list container element.\n */\n const initEventListener = root => {\n const loadMoreButton = root.find(SELECTORS.MORE_ACTIVITIES_BUTTON);\n loadMoreButton.on('click', () => {\n enableMoreActivitiesButtonLoading(root);\n loadMoreEvents(root);\n });\n };\n\n return {\n init: init,\n rootSelector: SELECTORS.ROOT,\n };\n});\n"],"file":"event_list.min.js"}
\ No newline at end of file
+{"version":3,"file":"event_list.min.js","sources":["../src/event_list.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 .\n\n/**\n * Javascript to load and render the list of calendar events for a\n * given day range.\n *\n * @module block_timeline/event_list\n * @copyright 2016 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n 'jquery',\n 'core/notification',\n 'core/templates',\n 'core/str',\n 'core/user_date',\n 'block_timeline/calendar_events_repository',\n 'core/pending'\n],\nfunction(\n $,\n Notification,\n Templates,\n Str,\n UserDate,\n CalendarEventsRepository,\n Pending\n) {\n\n var SECONDS_IN_DAY = 60 * 60 * 24;\n var courseview = false;\n\n var SELECTORS = {\n EMPTY_MESSAGE: '[data-region=\"no-events-empty-message\"]',\n ROOT: '[data-region=\"event-list-container\"]',\n EVENT_LIST_CONTENT: '[data-region=\"event-list-content\"]',\n EVENT_LIST_WRAPPER: '[data-region=\"event-list-wrapper\"]',\n EVENT_LIST_LOADING_PLACEHOLDER: '[data-region=\"event-list-loading-placeholder\"]',\n TIMELINE_BLOCK: '[data-region=\"timeline\"]',\n TIMELINE_SEARCH: '[data-action=\"search\"]',\n MORE_ACTIVITIES_BUTTON: '[data-action=\"more-events\"]',\n MORE_ACTIVITIES_BUTTON_CONTAINER: '[data-region=\"more-events-button-container\"]'\n };\n\n var TEMPLATES = {\n EVENT_LIST_CONTENT: 'block_timeline/event-list-content',\n MORE_ACTIVITIES_BUTTON: 'block_timeline/event-list-loadmore',\n LOADING_ICON: 'core/loading'\n };\n\n /** @type {number} The total items will be shown on the first load. */\n const DEFAULT_LAZY_LOADING_ITEMS_FIRST_LOAD = 5;\n /** @type {number} The total items will be shown when click on the Show more activities button. */\n const DEFAULT_LAZY_LOADING_ITEMS_OTHER_LOAD = 10;\n\n /**\n * Hide the content area and display the empty content message.\n *\n * @param {object} root The container element\n */\n var hideContent = function(root) {\n root.find(SELECTORS.EVENT_LIST_CONTENT).addClass('hidden');\n root.find(SELECTORS.EMPTY_MESSAGE).removeClass('hidden');\n };\n\n /**\n * Show the content area and hide the empty content message.\n *\n * @param {object} root The container element\n */\n var showContent = function(root) {\n root.find(SELECTORS.EVENT_LIST_CONTENT).removeClass('hidden');\n root.find(SELECTORS.EMPTY_MESSAGE).addClass('hidden');\n };\n\n /**\n * Empty the content area.\n *\n * @param {object} root The container element\n */\n var emptyContent = function(root) {\n root.find(SELECTORS.EVENT_LIST_CONTENT).empty();\n };\n\n /**\n * Construct the template context from a list of calendar events. The events\n * are grouped by which day they are on. The day is calculated from the user's\n * midnight timestamp to ensure that the calculation is timezone agnostic.\n *\n * The return data structure will look like:\n * {\n * eventsbyday: [\n * {\n * dayTimestamp: 1533744000,\n * events: [\n * { ...event 1 data... },\n * { ...event 2 data... }\n * ]\n * },\n * {\n * dayTimestamp: 1533830400,\n * events: [\n * { ...event 3 data... },\n * { ...event 4 data... }\n * ]\n * }\n * ]\n * }\n *\n * Each day timestamp is the day's midnight in the user's timezone.\n *\n * @param {array} calendarEvents List of calendar events\n * @return {object}\n */\n var buildTemplateContext = function(calendarEvents) {\n var eventsByDay = {};\n var templateContext = {\n courseview,\n eventsbyday: []\n };\n\n calendarEvents.forEach(function(calendarEvent) {\n var dayTimestamp = calendarEvent.timeusermidnight;\n if (eventsByDay[dayTimestamp]) {\n eventsByDay[dayTimestamp].push(calendarEvent);\n } else {\n eventsByDay[dayTimestamp] = [calendarEvent];\n }\n });\n\n Object.keys(eventsByDay).forEach(function(dayTimestamp) {\n var events = eventsByDay[dayTimestamp];\n templateContext.eventsbyday.push({\n dayTimestamp: dayTimestamp,\n events: events\n });\n });\n\n return templateContext;\n };\n\n /**\n * Render the HTML for the given calendar events.\n *\n * @param {array} calendarEvents A list of calendar events\n * @return {promise} Resolved with HTML and JS strings.\n */\n var render = function(calendarEvents) {\n var templateContext = buildTemplateContext(calendarEvents);\n var templateName = TEMPLATES.EVENT_LIST_CONTENT;\n\n return Templates.render(templateName, templateContext);\n };\n\n /**\n * Retrieve a list of calendar events from the server for the given\n * constraints.\n *\n * @param {Number} midnight The user's midnight time in unix timestamp.\n * @param {Number} limit Limit the result set to this number of items\n * @param {Number} daysOffset How many days (from midnight) to offset the results from\n * @param {int|undefined} daysLimit How many dates (from midnight) to limit the result to\n * @param {int|false} lastId The ID of the last seen event (if any)\n * @param {int|undefined} courseId Course ID to restrict events to\n * @param {string|undefined} searchValue Search value\n * @return {Promise} A jquery promise\n */\n var load = function(midnight, limit, daysOffset, daysLimit, lastId, courseId, searchValue) {\n var startTime = midnight + (daysOffset * SECONDS_IN_DAY);\n var endTime = daysLimit != undefined ? midnight + (daysLimit * SECONDS_IN_DAY) : false;\n\n var args = {\n starttime: startTime,\n limit: limit,\n };\n\n if (lastId) {\n args.aftereventid = lastId;\n }\n\n if (endTime) {\n args.endtime = endTime;\n }\n\n if (searchValue) {\n args.searchvalue = searchValue;\n }\n\n if (courseId) {\n // If we have a course id then we only want events from that course.\n args.courseid = courseId;\n return CalendarEventsRepository.queryByCourse(args);\n } else {\n // Otherwise we want events from any course.\n return CalendarEventsRepository.queryByTime(args);\n }\n };\n\n /**\n * Create a lazy-loading region for the calendar events in the given root element.\n *\n * @param {object} root The event list container element.\n * @param {object} additionalConfig Additional config options to pass to pagedContentFactory.\n */\n var init = function(root, additionalConfig = {}) {\n const pendingPromise = new Pending('block/timeline:event-init');\n root = $(root);\n\n courseview = !!additionalConfig.courseview;\n\n // Create a promise that will be resolved once the first set of page\n // data has been loaded. This ensures that the loading placeholder isn't\n // hidden until we have all of the data back to prevent the page elements\n // jumping around.\n var firstLoad = $.Deferred();\n var eventListContent = root.find(SELECTORS.EVENT_LIST_CONTENT);\n var loadingPlaceholder = root.find(SELECTORS.EVENT_LIST_LOADING_PLACEHOLDER);\n var courseId = root.attr('data-course-id');\n var daysOffset = parseInt(root.attr('data-days-offset'), 10);\n var daysLimit = root.attr('data-days-limit');\n var midnight = parseInt(root.attr('data-midnight'), 10);\n const searchValue = root.closest(SELECTORS.TIMELINE_BLOCK).find(SELECTORS.TIMELINE_SEARCH).val();\n\n // Make sure the content area and loading placeholder is visible.\n // This is because the init function can be called to re-initialise\n // an existing event list area.\n emptyContent(root);\n showContent(root);\n loadingPlaceholder.removeClass('hidden');\n\n // Days limit isn't mandatory.\n if (daysLimit != undefined) {\n daysLimit = parseInt(daysLimit, 10);\n }\n\n // Create the lazy loading content element.\n return createLazyLoadingContent(root, firstLoad,\n DEFAULT_LAZY_LOADING_ITEMS_FIRST_LOAD, midnight, 0, courseId, daysOffset, daysLimit, searchValue)\n .then(function(html, js) {\n firstLoad.then(function(data) {\n if (!data.hasContent) {\n loadingPlaceholder.addClass('hidden');\n // If we didn't get any data then show the empty data message.\n return hideContent(root);\n }\n\n html = $(html);\n // Hide the content for now.\n html.addClass('hidden');\n // Replace existing elements with the newly created lazy-loading region.\n Templates.replaceNodeContents(eventListContent, html, js);\n\n // Prevent changing page elements too much by only showing the content\n // once we've loaded some data for the first time. This allows our\n // fancy loading placeholder to shine.\n html.removeClass('hidden');\n loadingPlaceholder.addClass('hidden');\n\n if (!data.loadedAll) {\n Templates.render(TEMPLATES.MORE_ACTIVITIES_BUTTON, {courseview}).then(function(html) {\n eventListContent.append(html);\n setLastTimestamp(root, data.lastTimeStamp);\n // Init the event handler.\n initEventListener(root);\n return html;\n }).catch(function() {\n return false;\n });\n }\n\n return data;\n })\n .catch(function() {\n return false;\n });\n\n return html;\n }).then(() => {\n return pendingPromise.resolve();\n })\n .catch(Notification.exception);\n };\n\n /**\n * Create a lazy-loading content element for showing the event list for the initial load.\n *\n * @param {object} root The event list container element.\n * @param {object} firstLoad A jQuery promise to be resolved after the first set of data is loaded.\n * @param {int} itemLimit Limit the number of items.\n * @param {Number} midnight The user's midnight time in unix timestamp.\n * @param {int} lastId The last event ID for each loaded page. Page number is key, id is value.\n * @param {int|undefined} courseId Course ID to restrict events to.\n * @param {Number} daysOffset How many days (from midnight) to offset the results from.\n * @param {int|undefined} daysLimit How many dates (from midnight) to limit the result to.\n * @param {string|undefined} searchValue Search value.\n * @return {object} jQuery promise resolved with calendar events.\n */\n const createLazyLoadingContent = (root, firstLoad, itemLimit, midnight, lastId,\n courseId, daysOffset, daysLimit, searchValue) => {\n return loadEventsForLazyLoading(\n root,\n itemLimit,\n midnight,\n lastId,\n courseId,\n daysOffset,\n daysLimit,\n searchValue\n ).then(data => {\n if (data.calendarEvents.length) {\n const lastEventId = data.calendarEvents.at(-1).id;\n const lastTimeStamp = data.calendarEvents.at(-1).timeusermidnight;\n firstLoad.resolve({\n hasContent: true,\n lastId: lastEventId,\n lastTimeStamp: lastTimeStamp,\n loadedAll: data.loadedAll\n });\n return render(data.calendarEvents, midnight);\n } else {\n firstLoad.resolve({\n hasContent: false,\n lastId: 0,\n lastTimeStamp: 0,\n loadedAll: true\n });\n return data.calendarEvents;\n }\n }).catch(Notification.exception);\n };\n\n /**\n * Handle the request from the lazy-loading region.\n * Uses the given data like course id, offset... to request the events from the server.\n *\n * @param {object} root The event list container element.\n * @param {int} itemLimit Limit the number of items.\n * @param {Number} midnight The user's midnight time in unix timestamp.\n * @param {int} lastId The last event ID for each loaded page.\n * @param {int|undefined} courseId Course ID to restrict events to.\n * @param {Number} daysOffset How many days (from midnight) to offset the results from.\n * @param {int|undefined} daysLimit How many dates (from midnight) to limit the result to.\n * @param {string|undefined} searchValue Search value.\n * @return {object} jQuery promise resolved with calendar events.\n */\n const loadEventsForLazyLoading = (root, itemLimit, midnight, lastId, courseId, daysOffset, daysLimit, searchValue) => {\n // Load one more than the given limit so that we can tell if there\n // is more content to load after this.\n const eventsPromise = load(midnight, itemLimit + 1, daysOffset, daysLimit, lastId, courseId, searchValue);\n let calendarEvents = [];\n let loadedAll = true;\n\n return eventsPromise.then(result => {\n if (!result.events.length) {\n return {calendarEvents, loadedAll};\n }\n\n // Determine if the overdue filter is applied.\n const overdueFilter = document.querySelector(\"[data-filtername='overdue']\");\n const filterByOverdue = (overdueFilter && overdueFilter.getAttribute('aria-current'));\n\n calendarEvents = result.events.filter(event => {\n if (event.eventtype == 'open' || event.eventtype == 'opensubmission') {\n const dayTimestamp = UserDate.getUserMidnightForTimestamp(event.timesort, midnight);\n return dayTimestamp > midnight;\n }\n // When filtering by overdue, we fetch all events due today, in case any have elapsed already and are overdue.\n // This means if filtering by overdue, some events fetched might not be required (eg if due later today).\n return (!filterByOverdue || event.overdue);\n });\n\n loadedAll = calendarEvents.length <= itemLimit;\n\n if (!loadedAll) {\n // Remove the last element from the array because it isn't\n // needed in this result set.\n calendarEvents.pop();\n }\n\n if (calendarEvents.length) {\n const lastEventId = calendarEvents.at(-1).id;\n setOffset(root, lastEventId);\n }\n\n return {calendarEvents, loadedAll};\n });\n };\n\n /**\n * Load new events and append to current list.\n *\n * @param {object} root The event list container element.\n */\n const loadMoreEvents = root => {\n const midnight = parseInt(root.attr('data-midnight'), 10);\n const courseId = root.attr('data-course-id');\n const daysOffset = parseInt(root.attr('data-days-offset'), 10);\n const daysLimit = root.attr('data-days-limit');\n const lastId = getOffset(root);\n const eventListWrapper = root.find(SELECTORS.EVENT_LIST_WRAPPER);\n const searchValue = root.closest(SELECTORS.TIMELINE_BLOCK).find(SELECTORS.TIMELINE_SEARCH).val();\n const eventsPromise = loadEventsForLazyLoading(\n root,\n DEFAULT_LAZY_LOADING_ITEMS_OTHER_LOAD,\n midnight,\n lastId,\n courseId,\n daysOffset,\n daysLimit,\n searchValue\n );\n eventsPromise.then(data => {\n if (data.calendarEvents.length) {\n const renderPromise = render(data.calendarEvents);\n const lastTimestamp = getLastTimestamp(root);\n renderPromise.then((html, js) => {\n html = $(html);\n\n // Remove the date heading if it has the same value as the previous one.\n html.find(`[data-timestamp=\"${lastTimestamp}\"]`).remove();\n Templates.appendNodeContents(eventListWrapper, html.html(), js);\n\n if (!data.loadedAll) {\n Templates.render(TEMPLATES.MORE_ACTIVITIES_BUTTON, {}).then(html => {\n eventListWrapper.append(html);\n setLastTimestamp(root, data.calendarEvents.at(-1).timeusermidnight);\n // Init the event handler.\n initEventListener(root);\n\n return html;\n }).catch(() => {\n return false;\n });\n }\n\n return html;\n }).catch(Notification.exception);\n }\n\n return data;\n }).then(() => {\n return disableMoreActivitiesButtonLoading(root);\n }).catch(Notification.exception);\n };\n\n /**\n * Return the offset value for lazy loading fetching.\n *\n * @param {object} element The event list container element.\n * @return {Number} Offset value.\n */\n const getOffset = element => {\n return parseInt(element.attr('data-lazyload-offset'), 10);\n };\n\n /**\n * Set the offset value for lazy loading fetching.\n *\n * @param {object} element The event list container element.\n * @param {Number} offset Offset value.\n */\n const setOffset = (element, offset) => {\n element.attr('data-lazyload-offset', offset);\n };\n\n /**\n * Return the timestamp value for lazy loading fetching.\n *\n * @param {object} element The event list container element.\n * @return {Number} Timestamp value.\n */\n const getLastTimestamp = element => {\n return parseInt(element.attr('data-timestamp'), 10);\n };\n\n /**\n * Set the timestamp value for lazy loading fetching.\n *\n * @param {object} element The event list container element.\n * @param {Number} timestamp Timestamp value.\n */\n const setLastTimestamp = (element, timestamp) => {\n element.attr('data-timestamp', timestamp);\n };\n\n /**\n * Add the \"Show more activities\" button and remove and loading spinner.\n *\n * @param {object} root The event list container element.\n */\n const enableMoreActivitiesButtonLoading = root => {\n const loadMoreButton = root.find(SELECTORS.MORE_ACTIVITIES_BUTTON);\n loadMoreButton.prop('disabled', true);\n Templates.render(TEMPLATES.LOADING_ICON, {}).then(html => {\n loadMoreButton.append(html);\n return html;\n }).catch(() => {\n // It's not important if this false so just do so silently.\n return false;\n });\n };\n\n /**\n * Remove the \"Show more activities\" button and remove and loading spinner.\n *\n * @param {object} root The event list container element.\n */\n const disableMoreActivitiesButtonLoading = root => {\n const loadMoreButtonContainer = root.find(SELECTORS.MORE_ACTIVITIES_BUTTON_CONTAINER);\n loadMoreButtonContainer.remove();\n };\n\n /**\n * Event initialise.\n *\n * @param {object} root The event list container element.\n */\n const initEventListener = root => {\n const loadMoreButton = root.find(SELECTORS.MORE_ACTIVITIES_BUTTON);\n loadMoreButton.on('click', () => {\n enableMoreActivitiesButtonLoading(root);\n loadMoreEvents(root);\n });\n };\n\n return {\n init: init,\n rootSelector: SELECTORS.ROOT,\n };\n});\n"],"names":["define","$","Notification","Templates","Str","UserDate","CalendarEventsRepository","Pending","courseview","SELECTORS","TEMPLATES","hideContent","root","find","addClass","removeClass","showContent","emptyContent","empty","render","calendarEvents","templateContext","eventsByDay","eventsbyday","forEach","calendarEvent","dayTimestamp","timeusermidnight","push","Object","keys","events","buildTemplateContext","templateName","createLazyLoadingContent","firstLoad","itemLimit","midnight","lastId","courseId","daysOffset","daysLimit","searchValue","loadEventsForLazyLoading","then","data","length","lastEventId","at","id","lastTimeStamp","resolve","hasContent","loadedAll","catch","exception","eventsPromise","limit","endTime","undefined","args","starttime","aftereventid","endtime","searchvalue","courseid","queryByCourse","queryByTime","load","result","overdueFilter","document","querySelector","filterByOverdue","getAttribute","filter","event","eventtype","getUserMidnightForTimestamp","timesort","overdue","pop","setOffset","getOffset","element","parseInt","attr","offset","getLastTimestamp","setLastTimestamp","timestamp","disableMoreActivitiesButtonLoading","remove","initEventListener","on","loadMoreButton","prop","html","append","enableMoreActivitiesButtonLoading","eventListWrapper","closest","val","renderPromise","lastTimestamp","js","appendNodeContents","loadMoreEvents","init","additionalConfig","pendingPromise","Deferred","eventListContent","loadingPlaceholder","replaceNodeContents","rootSelector"],"mappings":"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"}
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/main.min.js b/blocks/timeline/amd/build/main.min.js
index 7aacd6361d2..f81bd758488 100644
--- a/blocks/timeline/amd/build/main.min.js
+++ b/blocks/timeline/amd/build/main.min.js
@@ -1,2 +1,9 @@
-define ("block_timeline/main",["jquery","block_timeline/view_nav","block_timeline/view"],function(a,b,c){var d={TIMELINE_VIEW:"[data-region=\"timeline-view\"]"};return{init:function init(e){e=a(e);var f=e.find(d.TIMELINE_VIEW);b.init(e,f);c.init(f)}}});
-//# sourceMappingURL=main.min.js.map
+/**
+ * Javascript to initialise the timeline block.
+ *
+ * @copyright 2018 Ryan Wyllie
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_timeline/main",["jquery","block_timeline/view_nav","block_timeline/view"],(function($,ViewNav,View){var SELECTORS_TIMELINE_VIEW='[data-region="timeline-view"]';return{init:function(root){var viewRoot=(root=$(root)).find(SELECTORS_TIMELINE_VIEW);ViewNav.init(root,viewRoot),View.init(viewRoot)}}}));
+
+//# sourceMappingURL=main.min.js.map
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/main.min.js.map b/blocks/timeline/amd/build/main.min.js.map
index 64ba6b70a08..b8a83abf783 100644
--- a/blocks/timeline/amd/build/main.min.js.map
+++ b/blocks/timeline/amd/build/main.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/main.js"],"names":["define","$","ViewNav","View","SELECTORS","TIMELINE_VIEW","init","root","viewRoot","find"],"mappings":"AAsBAA,OAAM,uBACN,CACI,QADJ,CAEI,yBAFJ,CAGI,qBAHJ,CADM,CAMN,SACIC,CADJ,CAEIC,CAFJ,CAGIC,CAHJ,CAIE,IAEMC,CAAAA,CAAS,CAAG,CACZC,aAAa,CAAE,iCADH,CAFlB,CAqBE,MAAO,CACHC,IAAI,CAXG,QAAPA,CAAAA,IAAO,CAASC,CAAT,CAAe,CACtBA,CAAI,CAAGN,CAAC,CAACM,CAAD,CAAR,CACA,GAAIC,CAAAA,CAAQ,CAAGD,CAAI,CAACE,IAAL,CAAUL,CAAS,CAACC,aAApB,CAAf,CAGAH,CAAO,CAACI,IAAR,CAAaC,CAAb,CAAmBC,CAAnB,EAEAL,CAAI,CAACG,IAAL,CAAUE,CAAV,CACH,CAEM,CAGV,CAlCK,CAAN","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 .\n\n/**\n * Javascript to initialise the timeline block.\n *\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'block_timeline/view_nav',\n 'block_timeline/view'\n],\nfunction(\n $,\n ViewNav,\n View\n) {\n\n var SELECTORS = {\n TIMELINE_VIEW: '[data-region=\"timeline-view\"]'\n };\n\n /**\n * Initialise all of the modules for the timeline block.\n *\n * @param {object} root The root element for the timeline block.\n */\n var init = function(root) {\n root = $(root);\n var viewRoot = root.find(SELECTORS.TIMELINE_VIEW);\n\n // Initialise the timeline navigation elements.\n ViewNav.init(root, viewRoot);\n // Initialise the timeline view modules.\n View.init(viewRoot);\n };\n\n return {\n init: init\n };\n});\n"],"file":"main.min.js"}
\ No newline at end of file
+{"version":3,"file":"main.min.js","sources":["../src/main.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 .\n\n/**\n * Javascript to initialise the timeline block.\n *\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'block_timeline/view_nav',\n 'block_timeline/view'\n],\nfunction(\n $,\n ViewNav,\n View\n) {\n\n var SELECTORS = {\n TIMELINE_VIEW: '[data-region=\"timeline-view\"]'\n };\n\n /**\n * Initialise all of the modules for the timeline block.\n *\n * @param {object} root The root element for the timeline block.\n */\n var init = function(root) {\n root = $(root);\n var viewRoot = root.find(SELECTORS.TIMELINE_VIEW);\n\n // Initialise the timeline navigation elements.\n ViewNav.init(root, viewRoot);\n // Initialise the timeline view modules.\n View.init(viewRoot);\n };\n\n return {\n init: init\n };\n});\n"],"names":["define","$","ViewNav","View","SELECTORS","init","root","viewRoot","find"],"mappings":";;;;;;AAsBAA,6BACA,CACI,SACA,0BACA,wBAEJ,SACIC,EACAC,QACAC,UAGIC,wBACe,sCAkBZ,CACHC,KAXO,SAASC,UAEZC,UADJD,KAAOL,EAAEK,OACWE,KAAKJ,yBAGzBF,QAAQG,KAAKC,KAAMC,UAEnBJ,KAAKE,KAAKE"}
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/view.min.js b/blocks/timeline/amd/build/view.min.js
index ac57cbeefad..a11999824f1 100644
--- a/blocks/timeline/amd/build/view.min.js
+++ b/blocks/timeline/amd/build/view.min.js
@@ -1,2 +1,9 @@
-define ("block_timeline/view",["jquery","block_timeline/view_dates","block_timeline/view_courses"],function(a,b,c){var d={TIMELINE_DATES_VIEW:"[data-region=\"view-dates\"]",TIMELINE_COURSES_VIEW:"[data-region=\"view-courses\"]"};return{init:function init(e){e=a(e);var f=e.find(d.TIMELINE_DATES_VIEW),g=e.find(d.TIMELINE_COURSES_VIEW);b.init(f);c.init(g)},reset:function reset(a){var e=a.find(d.TIMELINE_DATES_VIEW),f=a.find(d.TIMELINE_COURSES_VIEW);b.reset(e);c.reset(f)},shown:function shown(a){var e=a.find(d.TIMELINE_DATES_VIEW),f=a.find(d.TIMELINE_COURSES_VIEW);if(e.hasClass("active")){b.shown(e)}else{c.shown(f)}}}});
-//# sourceMappingURL=view.min.js.map
+/**
+ * Manage the timeline view for the timeline block.
+ *
+ * @copyright 2018 Ryan Wyllie
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_timeline/view",["jquery","block_timeline/view_dates","block_timeline/view_courses"],(function($,ViewDates,ViewCourses){var SELECTORS_TIMELINE_DATES_VIEW='[data-region="view-dates"]',SELECTORS_TIMELINE_COURSES_VIEW='[data-region="view-courses"]';return{init:function(root){var datesViewRoot=(root=$(root)).find(SELECTORS_TIMELINE_DATES_VIEW),coursesViewRoot=root.find(SELECTORS_TIMELINE_COURSES_VIEW);ViewDates.init(datesViewRoot),ViewCourses.init(coursesViewRoot)},reset:function(root){var datesViewRoot=root.find(SELECTORS_TIMELINE_DATES_VIEW),coursesViewRoot=root.find(SELECTORS_TIMELINE_COURSES_VIEW);ViewDates.reset(datesViewRoot),ViewCourses.reset(coursesViewRoot)},shown:function(root){var datesViewRoot=root.find(SELECTORS_TIMELINE_DATES_VIEW),coursesViewRoot=root.find(SELECTORS_TIMELINE_COURSES_VIEW);datesViewRoot.hasClass("active")?ViewDates.shown(datesViewRoot):ViewCourses.shown(coursesViewRoot)}}}));
+
+//# sourceMappingURL=view.min.js.map
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/view.min.js.map b/blocks/timeline/amd/build/view.min.js.map
index 3934e19066f..515b6be786b 100644
--- a/blocks/timeline/amd/build/view.min.js.map
+++ b/blocks/timeline/amd/build/view.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/view.js"],"names":["define","$","ViewDates","ViewCourses","SELECTORS","TIMELINE_DATES_VIEW","TIMELINE_COURSES_VIEW","init","root","datesViewRoot","find","coursesViewRoot","reset","shown","hasClass"],"mappings":"AAsBAA,OAAM,uBACN,CACI,QADJ,CAEI,2BAFJ,CAGI,6BAHJ,CADM,CAMN,SACIC,CADJ,CAEIC,CAFJ,CAGIC,CAHJ,CAIE,IAEMC,CAAAA,CAAS,CAAG,CACZC,mBAAmB,CAAE,8BADT,CAEZC,qBAAqB,CAAE,gCAFX,CAFlB,CA0DE,MAAO,CACHC,IAAI,CA7CG,QAAPA,CAAAA,IAAO,CAASC,CAAT,CAAe,CACtBA,CAAI,CAAGP,CAAC,CAACO,CAAD,CAAR,CADsB,GAElBC,CAAAA,CAAa,CAAGD,CAAI,CAACE,IAAL,CAAUN,CAAS,CAACC,mBAApB,CAFE,CAGlBM,CAAe,CAAGH,CAAI,CAACE,IAAL,CAAUN,CAAS,CAACE,qBAApB,CAHA,CAKtBJ,CAAS,CAACK,IAAV,CAAeE,CAAf,EACAN,CAAW,CAACI,IAAZ,CAAiBI,CAAjB,CACH,CAqCM,CAEHC,KAAK,CA5BG,QAARA,CAAAA,KAAQ,CAASJ,CAAT,CAAe,IACnBC,CAAAA,CAAa,CAAGD,CAAI,CAACE,IAAL,CAAUN,CAAS,CAACC,mBAApB,CADG,CAEnBM,CAAe,CAAGH,CAAI,CAACE,IAAL,CAAUN,CAAS,CAACE,qBAApB,CAFC,CAGvBJ,CAAS,CAACU,KAAV,CAAgBH,CAAhB,EACAN,CAAW,CAACS,KAAZ,CAAkBD,CAAlB,CACH,CAqBM,CAGHE,KAAK,CAdG,QAARA,CAAAA,KAAQ,CAASL,CAAT,CAAe,IACnBC,CAAAA,CAAa,CAAGD,CAAI,CAACE,IAAL,CAAUN,CAAS,CAACC,mBAApB,CADG,CAEnBM,CAAe,CAAGH,CAAI,CAACE,IAAL,CAAUN,CAAS,CAACE,qBAApB,CAFC,CAIvB,GAAIG,CAAa,CAACK,QAAd,CAAuB,QAAvB,CAAJ,CAAsC,CAClCZ,CAAS,CAACW,KAAV,CAAgBJ,CAAhB,CACH,CAFD,IAEO,CACHN,CAAW,CAACU,KAAZ,CAAkBF,CAAlB,CACH,CACJ,CAEM,CAKV,CAzEK,CAAN","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 .\n\n/**\n * Manage the timeline view for the timeline block.\n *\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'block_timeline/view_dates',\n 'block_timeline/view_courses',\n],\nfunction(\n $,\n ViewDates,\n ViewCourses\n) {\n\n var SELECTORS = {\n TIMELINE_DATES_VIEW: '[data-region=\"view-dates\"]',\n TIMELINE_COURSES_VIEW: '[data-region=\"view-courses\"]',\n };\n\n /**\n * Intialise the timeline dates and courses views on page load.\n * This function should only be called once per page load because\n * it can cause event listeners to be added to the page.\n *\n * @param {object} root The root element for the timeline view.\n */\n var init = function(root) {\n root = $(root);\n var datesViewRoot = root.find(SELECTORS.TIMELINE_DATES_VIEW);\n var coursesViewRoot = root.find(SELECTORS.TIMELINE_COURSES_VIEW);\n\n ViewDates.init(datesViewRoot);\n ViewCourses.init(coursesViewRoot);\n };\n\n /**\n * Reset the timeline dates and courses views to their original\n * state on first page load.\n *\n * This is called when configuration has changed for the event lists\n * to cause them to reload their data.\n *\n * @param {object} root The root element for the timeline view.\n */\n var reset = function(root) {\n var datesViewRoot = root.find(SELECTORS.TIMELINE_DATES_VIEW);\n var coursesViewRoot = root.find(SELECTORS.TIMELINE_COURSES_VIEW);\n ViewDates.reset(datesViewRoot);\n ViewCourses.reset(coursesViewRoot);\n };\n\n /**\n * Tell the timeline dates or courses view that it has been displayed.\n *\n * This is called each time one of the views is displayed and is used to\n * lazy load the data within it on first load.\n *\n * @param {object} root The root element for the timeline view.\n */\n var shown = function(root) {\n var datesViewRoot = root.find(SELECTORS.TIMELINE_DATES_VIEW);\n var coursesViewRoot = root.find(SELECTORS.TIMELINE_COURSES_VIEW);\n\n if (datesViewRoot.hasClass('active')) {\n ViewDates.shown(datesViewRoot);\n } else {\n ViewCourses.shown(coursesViewRoot);\n }\n };\n\n return {\n init: init,\n reset: reset,\n shown: shown,\n };\n});\n"],"file":"view.min.js"}
\ No newline at end of file
+{"version":3,"file":"view.min.js","sources":["../src/view.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 .\n\n/**\n * Manage the timeline view for the timeline block.\n *\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'block_timeline/view_dates',\n 'block_timeline/view_courses',\n],\nfunction(\n $,\n ViewDates,\n ViewCourses\n) {\n\n var SELECTORS = {\n TIMELINE_DATES_VIEW: '[data-region=\"view-dates\"]',\n TIMELINE_COURSES_VIEW: '[data-region=\"view-courses\"]',\n };\n\n /**\n * Intialise the timeline dates and courses views on page load.\n * This function should only be called once per page load because\n * it can cause event listeners to be added to the page.\n *\n * @param {object} root The root element for the timeline view.\n */\n var init = function(root) {\n root = $(root);\n var datesViewRoot = root.find(SELECTORS.TIMELINE_DATES_VIEW);\n var coursesViewRoot = root.find(SELECTORS.TIMELINE_COURSES_VIEW);\n\n ViewDates.init(datesViewRoot);\n ViewCourses.init(coursesViewRoot);\n };\n\n /**\n * Reset the timeline dates and courses views to their original\n * state on first page load.\n *\n * This is called when configuration has changed for the event lists\n * to cause them to reload their data.\n *\n * @param {object} root The root element for the timeline view.\n */\n var reset = function(root) {\n var datesViewRoot = root.find(SELECTORS.TIMELINE_DATES_VIEW);\n var coursesViewRoot = root.find(SELECTORS.TIMELINE_COURSES_VIEW);\n ViewDates.reset(datesViewRoot);\n ViewCourses.reset(coursesViewRoot);\n };\n\n /**\n * Tell the timeline dates or courses view that it has been displayed.\n *\n * This is called each time one of the views is displayed and is used to\n * lazy load the data within it on first load.\n *\n * @param {object} root The root element for the timeline view.\n */\n var shown = function(root) {\n var datesViewRoot = root.find(SELECTORS.TIMELINE_DATES_VIEW);\n var coursesViewRoot = root.find(SELECTORS.TIMELINE_COURSES_VIEW);\n\n if (datesViewRoot.hasClass('active')) {\n ViewDates.shown(datesViewRoot);\n } else {\n ViewCourses.shown(coursesViewRoot);\n }\n };\n\n return {\n init: init,\n reset: reset,\n shown: shown,\n };\n});\n"],"names":["define","$","ViewDates","ViewCourses","SELECTORS","init","root","datesViewRoot","find","coursesViewRoot","reset","shown","hasClass"],"mappings":";;;;;;AAsBAA,6BACA,CACI,SACA,4BACA,gCAEJ,SACIC,EACAC,UACAC,iBAGIC,8BACqB,6BADrBA,gCAEuB,qCAsDpB,CACHC,KA7CO,SAASC,UAEZC,eADJD,KAAOL,EAAEK,OACgBE,KAAKJ,+BAC1BK,gBAAkBH,KAAKE,KAAKJ,iCAEhCF,UAAUG,KAAKE,eACfJ,YAAYE,KAAKI,kBAwCjBC,MA5BQ,SAASJ,UACbC,cAAgBD,KAAKE,KAAKJ,+BAC1BK,gBAAkBH,KAAKE,KAAKJ,iCAChCF,UAAUQ,MAAMH,eAChBJ,YAAYO,MAAMD,kBAyBlBE,MAdQ,SAASL,UACbC,cAAgBD,KAAKE,KAAKJ,+BAC1BK,gBAAkBH,KAAKE,KAAKJ,iCAE5BG,cAAcK,SAAS,UACvBV,UAAUS,MAAMJ,eAEhBJ,YAAYQ,MAAMF"}
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/view_courses.min.js b/blocks/timeline/amd/build/view_courses.min.js
index 164b1833b48..06effd8cfa9 100644
--- a/blocks/timeline/amd/build/view_courses.min.js
+++ b/blocks/timeline/amd/build/view_courses.min.js
@@ -1,2 +1,9 @@
-define ("block_timeline/view_courses",["jquery","core/notification","core/custom_interaction_events","core/templates","block_timeline/event_list","core_course/repository","block_timeline/calendar_events_repository","core/pending"],function(a,b,c,d,e,f,g,h){var i={MORE_COURSES_BUTTON:"[data-action=\"more-courses\"]",MORE_COURSES_BUTTON_CONTAINER:"[data-region=\"more-courses-button-container\"]",NO_COURSES_EMPTY_MESSAGE:"[data-region=\"no-courses-empty-message\"]",NO_COURSES_WITH_EVENTS_MESSAGE:"[data-region=\"no-events-empty-message\"]",COURSES_LIST:"[data-region=\"courses-list\"]",COURSE_ITEMS_LOADING_PLACEHOLDER:"[data-region=\"course-items-loading-placeholder\"]",COURSE_EVENTS_CONTAINER:"[data-region=\"course-events-container\"]",COURSE_NAME:"[data-region=\"course-name\"]",LOADING_ICON:".loading-icon",TIMELINE_BLOCK:"[data-region=\"timeline\"]",TIMELINE_SEARCH:"[data-action=\"search\"]"},j={COURSE_ITEMS:"block_timeline/course-items",LOADING_ICON:"core/loading"},k=86400,l={courseview:!0},m=function(a){a.find(i.COURSE_ITEMS_LOADING_PLACEHOLDER).addClass("hidden")},n=function(a){a.find(i.COURSE_ITEMS_LOADING_PLACEHOLDER).removeClass("hidden")},o=function(a){a.find(i.MORE_COURSES_BUTTON_CONTAINER).addClass("hidden")},p=function(a){a.find(i.MORE_COURSES_BUTTON_CONTAINER).removeClass("hidden")},q=function(a){var b=a.find(i.MORE_COURSES_BUTTON);b.prop("disabled",!0);d.render(j.LOADING_ICON,{}).then(function(a){b.append(a);return a}).catch(function(){return!1})},r=function(a){var b=a.find(i.MORE_COURSES_BUTTON);b.prop("disabled",!1);b.find(i.LOADING_ICON).remove()},s=function(a){var b=a.find(i.COURSES_LIST);d.replaceNodeContents(b,"","");a.find(i.NO_COURSES_WITH_EVENTS_MESSAGE).removeClass("hidden")},t=function(a){a.find(i.NO_COURSES_WITH_EVENTS_MESSAGE).addClass("hidden")},u=function(a,b){var c=2b},H=function(a,b,c,d){var e=a.map(function(a){return a.id});return D(e,b,5+1,c,d)},I=function(a,b,c,e,f,g){return d.render(j.COURSE_ITEMS,{courses:a,midnight:c,hasdaysoffset:!0,hasdayslimit:f!=void 0,daysoffset:e,dayslimit:f,nodayslimit:f==void 0,courseview:!0,hascourses:!0}).then(function(a){m(b);if(a){u(b,a,g)}return a}).then(function(c){if(a.length<2){o(b)}else{p(b)}return c}).catch(function(){m(b)})},J=function(c){var d=1
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_timeline/view_courses",["jquery","core/notification","core/custom_interaction_events","core/templates","block_timeline/event_list","core_course/repository","block_timeline/calendar_events_repository","core/pending"],(function($,Notification,CustomEvents,Templates,EventList,CourseRepository,EventsRepository,Pending){var SELECTORS_MORE_COURSES_BUTTON='[data-action="more-courses"]',SELECTORS_MORE_COURSES_BUTTON_CONTAINER='[data-region="more-courses-button-container"]',SELECTORS_NO_COURSES_EMPTY_MESSAGE='[data-region="no-courses-empty-message"]',SELECTORS_NO_COURSES_WITH_EVENTS_MESSAGE='[data-region="no-events-empty-message"]',SELECTORS_COURSES_LIST='[data-region="courses-list"]',SELECTORS_COURSE_ITEMS_LOADING_PLACEHOLDER='[data-region="course-items-loading-placeholder"]',SELECTORS_LOADING_ICON=".loading-icon",SELECTORS_TIMELINE_BLOCK='[data-region="timeline"]',SELECTORS_TIMELINE_SEARCH='[data-action="search"]',TEMPLATES_COURSE_ITEMS="block_timeline/course-items",TEMPLATES_LOADING_ICON="core/loading";const additionalConfig={courseview:!0};var hideLoadingPlaceholder=function(root){root.find(SELECTORS_COURSE_ITEMS_LOADING_PLACEHOLDER).addClass("hidden")};var hideMoreCoursesButton=function(root){root.find(SELECTORS_MORE_COURSES_BUTTON_CONTAINER).addClass("hidden")},showMoreCoursesButton=function(root){root.find(SELECTORS_MORE_COURSES_BUTTON_CONTAINER).removeClass("hidden")},disableMoreCoursesButtonLoading=function(root){var button=root.find(SELECTORS_MORE_COURSES_BUTTON);button.prop("disabled",!1),button.find(SELECTORS_LOADING_ICON).remove()};const showNoCoursesWithEventsMessage=function(root){const container=root.find(SELECTORS_COURSES_LIST);Templates.replaceNodeContents(container,"",""),root.find(SELECTORS_NO_COURSES_WITH_EVENTS_MESSAGE).removeClass("hidden")};var getOffset=function(root){return parseInt(root.attr("data-offset"),10)},setOffset=function(root,offset){root.attr("data-offset",offset)},getLimit=function(root){return parseInt(root.attr("data-limit"),10)},getDaysOffset=function(root){return parseInt(root.attr("data-days-offset"),10)},getDaysLimit=function(root){var daysLimit=root.attr("data-days-limit");return null!=daysLimit?parseInt(daysLimit,10):void 0},getMidnight=function(root){return parseInt(root.attr("data-midnight"),10)},getStartTime=function(root){return getMidnight(root)+86400*getDaysOffset(root)},getEndTime=function(root){let endTime=null;if(root.attr("data-filter-overdue"))endTime=Math.floor(Date.now()/1e3);else{const midnight=getMidnight(root),daysLimit=getDaysLimit(root);null!=daysLimit&&(endTime=midnight+86400*daysLimit)}return endTime},hasReloadedEventsSince=function(root,time){return function(root){return root.data("last-event-load-time")}(root)>time},loadEventsForCourses=function(courses,startTime,endTime,searchValue){return function(courseIds,startTime,limit,endTime,searchValue){var args={courseids:courseIds,starttime:startTime,limit:limit};return endTime&&(args.endtime=endTime),searchValue&&(args.searchvalue=searchValue),EventsRepository.queryByCourses(args)}(courses.map((function(course){return course.id})),startTime,6,endTime,searchValue)},updateDisplayFromCourses=function(courses,root,midnight,daysOffset,daysLimit,append){return Templates.render(TEMPLATES_COURSE_ITEMS,{courses:courses,midnight:midnight,hasdaysoffset:!0,hasdayslimit:null!=daysLimit,daysoffset:daysOffset,dayslimit:daysLimit,nodayslimit:null==daysLimit,courseview:!0,hascourses:!0}).then((function(html){return hideLoadingPlaceholder(root),html&&function(root,html){let append=arguments.length>2&&void 0!==arguments[2]&&arguments[2];var container=root.find(SELECTORS_COURSES_LIST);append?Templates.appendNodeContents(container,html,""):Templates.replaceNodeContents(container,html,"")}(root,html,append),html})).then((function(html){return courses.length<2?hideMoreCoursesButton(root):showMoreCoursesButton(root),html})).catch((function(){hideLoadingPlaceholder(root)}))},loadMoreCourses=function(root){let append=arguments.length>1&&void 0!==arguments[1]&&arguments[1];const pendingPromise=new Pending("block/timeline:load-more-courses");var offset=getOffset(root),limit=getLimit(root);const startTime=getStartTime(root),endTime=getEndTime(root),searchValue=root.closest(SELECTORS_TIMELINE_BLOCK).find(SELECTORS_TIMELINE_SEARCH).val();return CourseRepository.getEnrolledCoursesWithEventsByTimelineClassification("inprogress",limit,offset,"fullname asc",searchValue,startTime,endTime).then((function(result){var startEventLoadingTime=Date.now(),courses=result.courses,nextOffset=result.nextoffset,daysOffset=getDaysOffset(root),daysLimit=getDaysLimit(root),midnight=getMidnight(root);const moreCoursesAvailable=result.morecoursesavailable;setOffset(root,nextOffset);var eventsPromise=loadEventsForCourses(courses,startTime,endTime,searchValue),renderPromise=updateDisplayFromCourses(courses,root,midnight,daysOffset,daysLimit,append);return $.when(eventsPromise,renderPromise).then((function(eventsByCourse){return hasReloadedEventsSince(root,startEventLoadingTime)||(courses.length>0?(courses.forEach((function(course){const containerSelector='[data-region="course-events-container"][data-course-id="'+course.id+'"]',eventListRoot=root.find(containerSelector).find(EventList.rootSelector);EventList.init(eventListRoot,additionalConfig)})),moreCoursesAvailable?showMoreCoursesButton(root):hideMoreCoursesButton(root)):(hideMoreCoursesButton(root),0==offset&&showNoCoursesWithEventsMessage(root))),eventsByCourse}))})).then((()=>pendingPromise.resolve())).catch(Notification.exception)},registerEventListeners=function(root){CustomEvents.define(root,[CustomEvents.events.activate]),root.on(CustomEvents.events.activate,SELECTORS_MORE_COURSES_BUTTON,(function(e,data){!function(root){var button=root.find(SELECTORS_MORE_COURSES_BUTTON);button.prop("disabled",!0),Templates.render(TEMPLATES_LOADING_ICON,{}).then((function(html){return button.append(html),html})).catch((function(){return!1}))}(root),loadMoreCourses(root,!0).then((function(){disableMoreCoursesButtonLoading(root)})).catch((function(){disableMoreCoursesButtonLoading(root)})),data&&(data.originalEvent.preventDefault(),data.originalEvent.stopPropagation()),e.stopPropagation()}))},shown=function(root){root.attr("data-seen")||root.find(SELECTORS_NO_COURSES_EMPTY_MESSAGE).length||(loadMoreCourses(root),root.attr("data-seen",!0))};return{init:function(root){(root=$(root)).find(SELECTORS_NO_COURSES_EMPTY_MESSAGE).length||(!function(root,time){root.data("last-event-load-time",time)}(root,Date.now()),root.hasClass("active")&&(loadMoreCourses(root),root.attr("data-seen",!0)),registerEventListeners(root))},reset:function(root){setOffset(root,0),function(root){root.find(SELECTORS_COURSE_ITEMS_LOADING_PLACEHOLDER).removeClass("hidden")}(root),function(root){root.find(SELECTORS_NO_COURSES_WITH_EVENTS_MESSAGE).addClass("hidden")}(root),root.removeAttr("data-seen"),root.hasClass("active")&&shown(root)},shown:shown}}));
+
+//# sourceMappingURL=view_courses.min.js.map
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/view_courses.min.js.map b/blocks/timeline/amd/build/view_courses.min.js.map
index daa99f81ac3..495db72018d 100644
--- a/blocks/timeline/amd/build/view_courses.min.js.map
+++ b/blocks/timeline/amd/build/view_courses.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/view_courses.js"],"names":["define","$","Notification","CustomEvents","Templates","EventList","CourseRepository","EventsRepository","Pending","SELECTORS","MORE_COURSES_BUTTON","MORE_COURSES_BUTTON_CONTAINER","NO_COURSES_EMPTY_MESSAGE","NO_COURSES_WITH_EVENTS_MESSAGE","COURSES_LIST","COURSE_ITEMS_LOADING_PLACEHOLDER","COURSE_EVENTS_CONTAINER","COURSE_NAME","LOADING_ICON","TIMELINE_BLOCK","TIMELINE_SEARCH","TEMPLATES","COURSE_ITEMS","SECONDS_IN_DAY","additionalConfig","courseview","hideLoadingPlaceholder","root","find","addClass","showLoadingPlaceholder","removeClass","hideMoreCoursesButton","showMoreCoursesButton","enableMoreCoursesButtonLoading","button","prop","render","then","html","append","catch","disableMoreCoursesButtonLoading","remove","showNoCoursesWithEventsMessage","container","replaceNodeContents","hideNoCoursesWithEventsMessage","renderCourseItemsHTML","appendNodeContents","getOffset","parseInt","attr","setOffset","offset","getLimit","getDaysOffset","getDaysLimit","daysLimit","getMidnight","getStartTime","midnight","daysOffset","getEndTime","endTime","Math","floor","Date","now","getEventsForCourseIds","courseIds","startTime","limit","searchValue","args","courseids","starttime","endtime","searchvalue","queryByCourses","getEventReloadTime","data","setEventReloadTime","time","hasReloadedEventsSince","loadEventsForCourses","courses","map","course","id","updateDisplayFromCourses","hasdaysoffset","hasdayslimit","daysoffset","dayslimit","nodayslimit","hascourses","length","loadMoreCourses","pendingPromise","closest","val","getEnrolledCoursesWithEventsByTimelineClassification","result","startEventLoadingTime","nextOffset","nextoffset","moreCoursesAvailable","morecoursesavailable","eventsPromise","renderPromise","when","eventsByCourse","forEach","courseId","courseEventsContainer","eventListRoot","rootSelector","init","resolve","exception","registerEventListeners","events","activate","on","e","originalEvent","preventDefault","stopPropagation","shown","hasClass","reset","removeAttr"],"mappings":"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","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 .\n\n/**\n * Manage the timeline courses view for the timeline block.\n *\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/templates',\n 'block_timeline/event_list',\n 'core_course/repository',\n 'block_timeline/calendar_events_repository',\n 'core/pending'\n],\nfunction(\n $,\n Notification,\n CustomEvents,\n Templates,\n EventList,\n CourseRepository,\n EventsRepository,\n Pending\n) {\n\n var SELECTORS = {\n MORE_COURSES_BUTTON: '[data-action=\"more-courses\"]',\n MORE_COURSES_BUTTON_CONTAINER: '[data-region=\"more-courses-button-container\"]',\n NO_COURSES_EMPTY_MESSAGE: '[data-region=\"no-courses-empty-message\"]',\n NO_COURSES_WITH_EVENTS_MESSAGE: '[data-region=\"no-events-empty-message\"]',\n COURSES_LIST: '[data-region=\"courses-list\"]',\n COURSE_ITEMS_LOADING_PLACEHOLDER: '[data-region=\"course-items-loading-placeholder\"]',\n COURSE_EVENTS_CONTAINER: '[data-region=\"course-events-container\"]',\n COURSE_NAME: '[data-region=\"course-name\"]',\n LOADING_ICON: '.loading-icon',\n TIMELINE_BLOCK: '[data-region=\"timeline\"]',\n TIMELINE_SEARCH: '[data-action=\"search\"]'\n };\n\n var TEMPLATES = {\n COURSE_ITEMS: 'block_timeline/course-items',\n LOADING_ICON: 'core/loading'\n };\n\n var COURSE_CLASSIFICATION = 'inprogress';\n var COURSE_SORT = 'fullname asc';\n var COURSE_EVENT_LIMIT = 5;\n var COURSE_LIMIT = 2;\n var SECONDS_IN_DAY = 60 * 60 * 24;\n\n const additionalConfig = {courseview: true};\n\n /**\n * Hide the loading placeholder elements.\n *\n * @param {object} root The rool element.\n */\n var hideLoadingPlaceholder = function(root) {\n root.find(SELECTORS.COURSE_ITEMS_LOADING_PLACEHOLDER).addClass('hidden');\n };\n\n /**\n * Show the loading placeholder elements.\n *\n * @param {object} root The rool element.\n */\n const showLoadingPlaceholder = function(root) {\n root.find(SELECTORS.COURSE_ITEMS_LOADING_PLACEHOLDER).removeClass('hidden');\n };\n\n /**\n * Hide the \"more courses\" button.\n *\n * @param {object} root The rool element.\n */\n var hideMoreCoursesButton = function(root) {\n root.find(SELECTORS.MORE_COURSES_BUTTON_CONTAINER).addClass('hidden');\n };\n\n /**\n * Show the \"more courses\" button.\n *\n * @param {object} root The rool element.\n */\n var showMoreCoursesButton = function(root) {\n root.find(SELECTORS.MORE_COURSES_BUTTON_CONTAINER).removeClass('hidden');\n };\n\n /**\n * Disable the \"more courses\" button and show the loading spinner.\n *\n * @param {object} root The rool element.\n */\n var enableMoreCoursesButtonLoading = function(root) {\n var button = root.find(SELECTORS.MORE_COURSES_BUTTON);\n button.prop('disabled', true);\n Templates.render(TEMPLATES.LOADING_ICON, {})\n .then(function(html) {\n button.append(html);\n return html;\n })\n .catch(function() {\n // It's not important if this false so just do so silently.\n return false;\n });\n };\n\n /**\n * Enable the \"more courses\" button and remove the loading spinner.\n *\n * @param {object} root The rool element.\n */\n var disableMoreCoursesButtonLoading = function(root) {\n var button = root.find(SELECTORS.MORE_COURSES_BUTTON);\n button.prop('disabled', false);\n button.find(SELECTORS.LOADING_ICON).remove();\n };\n\n /**\n * Display the message for when courses have no events available (within the current filtering).\n *\n * @param {object} root The rool element.\n */\n const showNoCoursesWithEventsMessage = function(root) {\n // Remove any course list contents, since we will display the no events message.\n const container = root.find(SELECTORS.COURSES_LIST);\n Templates.replaceNodeContents(container, '', '');\n root.find(SELECTORS.NO_COURSES_WITH_EVENTS_MESSAGE).removeClass('hidden');\n };\n\n /**\n * Hide the message for when courses have no events available (within the current filtering).\n *\n * @param {object} root The rool element.\n */\n const hideNoCoursesWithEventsMessage = function(root) {\n root.find(SELECTORS.NO_COURSES_WITH_EVENTS_MESSAGE).addClass('hidden');\n };\n\n /**\n * Render the course items HTML to the page.\n *\n * @param {object} root The rool element.\n * @param {string} html The course items HTML to render.\n * @param {boolean} append Whether the HTML should be appended (eg pressed \"show more courses\").\n * Defaults to false - replaces the existing content (eg when modifying filter values).\n */\n var renderCourseItemsHTML = function(root, html, append = false) {\n var container = root.find(SELECTORS.COURSES_LIST);\n\n if (append) {\n Templates.appendNodeContents(container, html, '');\n } else {\n Templates.replaceNodeContents(container, html, '');\n }\n };\n\n /**\n * Return the offset value for fetching courses.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getOffset = function(root) {\n return parseInt(root.attr('data-offset'), 10);\n };\n\n /**\n * Set the offset value for fetching courses.\n *\n * @param {object} root The rool element.\n * @param {Number} offset Offset value.\n */\n var setOffset = function(root, offset) {\n root.attr('data-offset', offset);\n };\n\n /**\n * Return the limit value for fetching courses.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getLimit = function(root) {\n return parseInt(root.attr('data-limit'), 10);\n };\n\n /**\n * Return the days offset value for fetching events.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getDaysOffset = function(root) {\n return parseInt(root.attr('data-days-offset'), 10);\n };\n\n /**\n * Return the days limit value for fetching events. The days\n * limit is optional so undefined will be returned if it isn't\n * set.\n *\n * @param {object} root The rool element.\n * @return {int|undefined}\n */\n var getDaysLimit = function(root) {\n var daysLimit = root.attr('data-days-limit');\n return daysLimit != undefined ? parseInt(daysLimit, 10) : undefined;\n };\n\n /**\n * Return the timestamp for the user's midnight.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getMidnight = function(root) {\n return parseInt(root.attr('data-midnight'), 10);\n };\n\n /**\n * Return the start time for fetching events. This is calculated\n * based on the user's midnight value so that timezones are\n * preserved.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getStartTime = function(root) {\n var midnight = getMidnight(root);\n var daysOffset = getDaysOffset(root);\n return midnight + (daysOffset * SECONDS_IN_DAY);\n };\n\n /**\n * Return the end time for fetching events. This is calculated\n * based on the user's midnight value so that timezones are\n * preserved, unless filtering by overdue, where the current UNIX timestamp is used.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getEndTime = function(root) {\n let endTime = null;\n\n if (root.attr('data-filter-overdue')) {\n // If filtering by overdue, end time will be the current timestamp in seconds.\n endTime = Math.floor(Date.now() / 1000);\n } else {\n const midnight = getMidnight(root);\n const daysLimit = getDaysLimit(root);\n\n if (daysLimit != undefined) {\n endTime = midnight + (daysLimit * SECONDS_IN_DAY);\n }\n }\n\n return endTime;\n };\n\n /**\n * Get a list of events for the given course ids. Returns a promise that will\n * be resolved with the events.\n *\n * @param {array} courseIds The list of course ids to fetch events for.\n * @param {Number} startTime Timestamp to fetch events from.\n * @param {Number} limit Limit to the number of events (this applies per course, not total)\n * @param {Number} endTime Timestamp to fetch events to.\n * @param {string|undefined} searchValue Search value\n * @return {object} jQuery promise.\n */\n var getEventsForCourseIds = function(courseIds, startTime, limit, endTime, searchValue) {\n var args = {\n courseids: courseIds,\n starttime: startTime,\n limit: limit\n };\n\n if (endTime) {\n args.endtime = endTime;\n }\n\n if (searchValue) {\n args.searchvalue = searchValue;\n }\n\n return EventsRepository.queryByCourses(args);\n };\n\n /**\n * Get the last time the events were reloaded.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getEventReloadTime = function(root) {\n return root.data('last-event-load-time');\n };\n\n /**\n * Set the last time the events were reloaded.\n *\n * @param {object} root The rool element.\n * @param {Number} time Timestamp in milliseconds.\n */\n var setEventReloadTime = function(root, time) {\n root.data('last-event-load-time', time);\n };\n\n /**\n * Check if events have begun reloading since the given\n * time.\n *\n * @param {object} root The rool element.\n * @param {Number} time Timestamp in milliseconds.\n * @return {bool}\n */\n var hasReloadedEventsSince = function(root, time) {\n return getEventReloadTime(root) > time;\n };\n\n /**\n * Send a request to the server to load the events for the courses.\n *\n * @param {array} courses List of course objects.\n * @param {Number} startTime Timestamp to load events after.\n * @param {int|undefined} endTime Timestamp to load events up until.\n * @param {string|undefined} searchValue Search value\n * @return {object} jQuery promise resolved with the events.\n */\n var loadEventsForCourses = function(courses, startTime, endTime, searchValue) {\n var courseIds = courses.map(function(course) {\n return course.id;\n });\n\n return getEventsForCourseIds(courseIds, startTime, COURSE_EVENT_LIMIT + 1, endTime, searchValue);\n };\n\n /**\n * Render the courses in the DOM once the server has returned the courses.\n *\n * @param {array} courses List of course objects.\n * @param {object} root The root element\n * @param {Number} midnight The midnight timestamp in the user's timezone.\n * @param {Number} daysOffset Number of days from today to offset the events.\n * @param {Number} daysLimit Number of days from today to limit the events to.\n * @param {boolean} append Whether new content should be appended instead of replaced (eg \"show more courses\").\n * @return {object} jQuery promise resolved after rendering is complete.\n */\n var updateDisplayFromCourses = function(courses, root, midnight, daysOffset, daysLimit, append) {\n // Render the courses template.\n return Templates.render(TEMPLATES.COURSE_ITEMS, {\n courses: courses,\n midnight: midnight,\n hasdaysoffset: true,\n hasdayslimit: daysLimit != undefined,\n daysoffset: daysOffset,\n dayslimit: daysLimit,\n nodayslimit: daysLimit == undefined,\n courseview: true,\n hascourses: true\n }).then(function(html) {\n hideLoadingPlaceholder(root);\n\n if (html) {\n // Template rendering is complete and we have the HTML so we can\n // add it to the DOM.\n renderCourseItemsHTML(root, html, append);\n }\n\n return html;\n })\n .then(function(html) {\n if (courses.length < COURSE_LIMIT) {\n // We know there aren't any more courses because we got back less\n // than we asked for so hide the button to request more.\n hideMoreCoursesButton(root);\n } else {\n // Make sure the button is visible if there are more courses to load.\n showMoreCoursesButton(root);\n }\n\n return html;\n })\n .catch(function() {\n hideLoadingPlaceholder(root);\n });\n };\n\n /**\n * Find all of the visible course blocks and initialise the event\n * list module to being loading the events for the course block.\n *\n * @param {object} root The root element for the timeline courses view.\n * @param {boolean} append Whether content should be appended instead of replaced (eg \"show more courses\"). False by default.\n * @return {object} jQuery promise resolved with courses and events.\n */\n var loadMoreCourses = function(root, append = false) {\n const pendingPromise = new Pending('block/timeline:load-more-courses');\n var offset = getOffset(root);\n var limit = getLimit(root);\n const startTime = getStartTime(root);\n const endTime = getEndTime(root);\n const searchValue = root.closest(SELECTORS.TIMELINE_BLOCK).find(SELECTORS.TIMELINE_SEARCH).val();\n\n // Start loading the next set of courses.\n // Fetch up to limit number of courses with at least one action event in the time filtering specified.\n // Courses without events will also be fetched, but hidden in case they have events in other timespans.\n return CourseRepository.getEnrolledCoursesWithEventsByTimelineClassification(\n COURSE_CLASSIFICATION,\n limit,\n offset,\n COURSE_SORT,\n searchValue,\n startTime,\n endTime\n ).then(function(result) {\n var startEventLoadingTime = Date.now();\n var courses = result.courses;\n var nextOffset = result.nextoffset;\n var daysOffset = getDaysOffset(root);\n var daysLimit = getDaysLimit(root);\n var midnight = getMidnight(root);\n const moreCoursesAvailable = result.morecoursesavailable;\n\n // Record the next offset if we want to request more courses.\n setOffset(root, nextOffset);\n // Load the events for these courses.\n var eventsPromise = loadEventsForCourses(courses, startTime, endTime, searchValue);\n // Render the courses in the DOM.\n var renderPromise = updateDisplayFromCourses(courses, root, midnight, daysOffset, daysLimit, append);\n\n return $.when(eventsPromise, renderPromise)\n .then(function(eventsByCourse) {\n if (hasReloadedEventsSince(root, startEventLoadingTime)) {\n // All of the events are being reloaded so ignore our results.\n return eventsByCourse;\n }\n\n if (courses.length > 0) {\n // Render the events in the correct course event list.\n courses.forEach(function(course) {\n const courseId = course.id;\n const containerSelector = '[data-region=\"course-events-container\"][data-course-id=\"' + courseId + '\"]';\n const courseEventsContainer = root.find(containerSelector);\n const eventListRoot = courseEventsContainer.find(EventList.rootSelector);\n\n EventList.init(eventListRoot, additionalConfig);\n });\n\n if (!moreCoursesAvailable) {\n // If no more courses with events matching the current filtering exist, hide the more courses button.\n hideMoreCoursesButton(root);\n } else {\n // If more courses exist with events matching the current filtering, show the more courses button.\n showMoreCoursesButton(root);\n }\n } else {\n // No more courses to load, hide the more courses button.\n hideMoreCoursesButton(root);\n\n // A zero offset means this was not loading \"more courses\", so we need to display the no results message.\n if (offset == 0) {\n showNoCoursesWithEventsMessage(root);\n }\n }\n\n return eventsByCourse;\n });\n }).then(() => {\n return pendingPromise.resolve();\n }).catch(Notification.exception);\n };\n\n /**\n * Add event listeners to load more courses for the courses view.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var registerEventListeners = function(root) {\n CustomEvents.define(root, [CustomEvents.events.activate]);\n // Show more courses and load their events when the user clicks the \"more courses\" button.\n root.on(CustomEvents.events.activate, SELECTORS.MORE_COURSES_BUTTON, function(e, data) {\n enableMoreCoursesButtonLoading(root);\n loadMoreCourses(root, true)\n .then(function() {\n disableMoreCoursesButtonLoading(root);\n return;\n })\n .catch(function() {\n disableMoreCoursesButtonLoading(root);\n });\n\n if (data) {\n data.originalEvent.preventDefault();\n data.originalEvent.stopPropagation();\n }\n e.stopPropagation();\n });\n };\n\n /**\n * Initialise the timeline courses view. Begin loading the events\n * if this view is active. Add the relevant event listeners.\n *\n * This function should only be called once per page load because it\n * is adding event listeners to the page.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var init = function(root) {\n root = $(root);\n\n // Only need to handle course loading if the user is actively enrolled in a course.\n if (!root.find(SELECTORS.NO_COURSES_EMPTY_MESSAGE).length) {\n setEventReloadTime(root, Date.now());\n\n if (root.hasClass('active')) {\n // Only load if this is active otherwise it will be lazy loaded later.\n loadMoreCourses(root);\n root.attr('data-seen', true);\n }\n\n registerEventListeners(root);\n }\n };\n\n /**\n * Reset the element back to it's initial state. Begin loading the events again\n * if this view is active.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var reset = function(root) {\n\n setOffset(root, 0);\n showLoadingPlaceholder(root);\n hideNoCoursesWithEventsMessage(root);\n root.removeAttr('data-seen');\n\n if (root.hasClass('active')) {\n shown(root);\n }\n };\n\n /**\n * Begin loading the events unless we know there are no actively enrolled courses.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var shown = function(root) {\n if (!root.attr('data-seen') && !root.find(SELECTORS.NO_COURSES_EMPTY_MESSAGE).length) {\n loadMoreCourses(root);\n root.attr('data-seen', true);\n }\n };\n\n return {\n init: init,\n reset: reset,\n shown: shown\n };\n});\n"],"file":"view_courses.min.js"}
\ No newline at end of file
+{"version":3,"file":"view_courses.min.js","sources":["../src/view_courses.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 .\n\n/**\n * Manage the timeline courses view for the timeline block.\n *\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/templates',\n 'block_timeline/event_list',\n 'core_course/repository',\n 'block_timeline/calendar_events_repository',\n 'core/pending'\n],\nfunction(\n $,\n Notification,\n CustomEvents,\n Templates,\n EventList,\n CourseRepository,\n EventsRepository,\n Pending\n) {\n\n var SELECTORS = {\n MORE_COURSES_BUTTON: '[data-action=\"more-courses\"]',\n MORE_COURSES_BUTTON_CONTAINER: '[data-region=\"more-courses-button-container\"]',\n NO_COURSES_EMPTY_MESSAGE: '[data-region=\"no-courses-empty-message\"]',\n NO_COURSES_WITH_EVENTS_MESSAGE: '[data-region=\"no-events-empty-message\"]',\n COURSES_LIST: '[data-region=\"courses-list\"]',\n COURSE_ITEMS_LOADING_PLACEHOLDER: '[data-region=\"course-items-loading-placeholder\"]',\n COURSE_EVENTS_CONTAINER: '[data-region=\"course-events-container\"]',\n COURSE_NAME: '[data-region=\"course-name\"]',\n LOADING_ICON: '.loading-icon',\n TIMELINE_BLOCK: '[data-region=\"timeline\"]',\n TIMELINE_SEARCH: '[data-action=\"search\"]'\n };\n\n var TEMPLATES = {\n COURSE_ITEMS: 'block_timeline/course-items',\n LOADING_ICON: 'core/loading'\n };\n\n var COURSE_CLASSIFICATION = 'inprogress';\n var COURSE_SORT = 'fullname asc';\n var COURSE_EVENT_LIMIT = 5;\n var COURSE_LIMIT = 2;\n var SECONDS_IN_DAY = 60 * 60 * 24;\n\n const additionalConfig = {courseview: true};\n\n /**\n * Hide the loading placeholder elements.\n *\n * @param {object} root The rool element.\n */\n var hideLoadingPlaceholder = function(root) {\n root.find(SELECTORS.COURSE_ITEMS_LOADING_PLACEHOLDER).addClass('hidden');\n };\n\n /**\n * Show the loading placeholder elements.\n *\n * @param {object} root The rool element.\n */\n const showLoadingPlaceholder = function(root) {\n root.find(SELECTORS.COURSE_ITEMS_LOADING_PLACEHOLDER).removeClass('hidden');\n };\n\n /**\n * Hide the \"more courses\" button.\n *\n * @param {object} root The rool element.\n */\n var hideMoreCoursesButton = function(root) {\n root.find(SELECTORS.MORE_COURSES_BUTTON_CONTAINER).addClass('hidden');\n };\n\n /**\n * Show the \"more courses\" button.\n *\n * @param {object} root The rool element.\n */\n var showMoreCoursesButton = function(root) {\n root.find(SELECTORS.MORE_COURSES_BUTTON_CONTAINER).removeClass('hidden');\n };\n\n /**\n * Disable the \"more courses\" button and show the loading spinner.\n *\n * @param {object} root The rool element.\n */\n var enableMoreCoursesButtonLoading = function(root) {\n var button = root.find(SELECTORS.MORE_COURSES_BUTTON);\n button.prop('disabled', true);\n Templates.render(TEMPLATES.LOADING_ICON, {})\n .then(function(html) {\n button.append(html);\n return html;\n })\n .catch(function() {\n // It's not important if this false so just do so silently.\n return false;\n });\n };\n\n /**\n * Enable the \"more courses\" button and remove the loading spinner.\n *\n * @param {object} root The rool element.\n */\n var disableMoreCoursesButtonLoading = function(root) {\n var button = root.find(SELECTORS.MORE_COURSES_BUTTON);\n button.prop('disabled', false);\n button.find(SELECTORS.LOADING_ICON).remove();\n };\n\n /**\n * Display the message for when courses have no events available (within the current filtering).\n *\n * @param {object} root The rool element.\n */\n const showNoCoursesWithEventsMessage = function(root) {\n // Remove any course list contents, since we will display the no events message.\n const container = root.find(SELECTORS.COURSES_LIST);\n Templates.replaceNodeContents(container, '', '');\n root.find(SELECTORS.NO_COURSES_WITH_EVENTS_MESSAGE).removeClass('hidden');\n };\n\n /**\n * Hide the message for when courses have no events available (within the current filtering).\n *\n * @param {object} root The rool element.\n */\n const hideNoCoursesWithEventsMessage = function(root) {\n root.find(SELECTORS.NO_COURSES_WITH_EVENTS_MESSAGE).addClass('hidden');\n };\n\n /**\n * Render the course items HTML to the page.\n *\n * @param {object} root The rool element.\n * @param {string} html The course items HTML to render.\n * @param {boolean} append Whether the HTML should be appended (eg pressed \"show more courses\").\n * Defaults to false - replaces the existing content (eg when modifying filter values).\n */\n var renderCourseItemsHTML = function(root, html, append = false) {\n var container = root.find(SELECTORS.COURSES_LIST);\n\n if (append) {\n Templates.appendNodeContents(container, html, '');\n } else {\n Templates.replaceNodeContents(container, html, '');\n }\n };\n\n /**\n * Return the offset value for fetching courses.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getOffset = function(root) {\n return parseInt(root.attr('data-offset'), 10);\n };\n\n /**\n * Set the offset value for fetching courses.\n *\n * @param {object} root The rool element.\n * @param {Number} offset Offset value.\n */\n var setOffset = function(root, offset) {\n root.attr('data-offset', offset);\n };\n\n /**\n * Return the limit value for fetching courses.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getLimit = function(root) {\n return parseInt(root.attr('data-limit'), 10);\n };\n\n /**\n * Return the days offset value for fetching events.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getDaysOffset = function(root) {\n return parseInt(root.attr('data-days-offset'), 10);\n };\n\n /**\n * Return the days limit value for fetching events. The days\n * limit is optional so undefined will be returned if it isn't\n * set.\n *\n * @param {object} root The rool element.\n * @return {int|undefined}\n */\n var getDaysLimit = function(root) {\n var daysLimit = root.attr('data-days-limit');\n return daysLimit != undefined ? parseInt(daysLimit, 10) : undefined;\n };\n\n /**\n * Return the timestamp for the user's midnight.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getMidnight = function(root) {\n return parseInt(root.attr('data-midnight'), 10);\n };\n\n /**\n * Return the start time for fetching events. This is calculated\n * based on the user's midnight value so that timezones are\n * preserved.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getStartTime = function(root) {\n var midnight = getMidnight(root);\n var daysOffset = getDaysOffset(root);\n return midnight + (daysOffset * SECONDS_IN_DAY);\n };\n\n /**\n * Return the end time for fetching events. This is calculated\n * based on the user's midnight value so that timezones are\n * preserved, unless filtering by overdue, where the current UNIX timestamp is used.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getEndTime = function(root) {\n let endTime = null;\n\n if (root.attr('data-filter-overdue')) {\n // If filtering by overdue, end time will be the current timestamp in seconds.\n endTime = Math.floor(Date.now() / 1000);\n } else {\n const midnight = getMidnight(root);\n const daysLimit = getDaysLimit(root);\n\n if (daysLimit != undefined) {\n endTime = midnight + (daysLimit * SECONDS_IN_DAY);\n }\n }\n\n return endTime;\n };\n\n /**\n * Get a list of events for the given course ids. Returns a promise that will\n * be resolved with the events.\n *\n * @param {array} courseIds The list of course ids to fetch events for.\n * @param {Number} startTime Timestamp to fetch events from.\n * @param {Number} limit Limit to the number of events (this applies per course, not total)\n * @param {Number} endTime Timestamp to fetch events to.\n * @param {string|undefined} searchValue Search value\n * @return {object} jQuery promise.\n */\n var getEventsForCourseIds = function(courseIds, startTime, limit, endTime, searchValue) {\n var args = {\n courseids: courseIds,\n starttime: startTime,\n limit: limit\n };\n\n if (endTime) {\n args.endtime = endTime;\n }\n\n if (searchValue) {\n args.searchvalue = searchValue;\n }\n\n return EventsRepository.queryByCourses(args);\n };\n\n /**\n * Get the last time the events were reloaded.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getEventReloadTime = function(root) {\n return root.data('last-event-load-time');\n };\n\n /**\n * Set the last time the events were reloaded.\n *\n * @param {object} root The rool element.\n * @param {Number} time Timestamp in milliseconds.\n */\n var setEventReloadTime = function(root, time) {\n root.data('last-event-load-time', time);\n };\n\n /**\n * Check if events have begun reloading since the given\n * time.\n *\n * @param {object} root The rool element.\n * @param {Number} time Timestamp in milliseconds.\n * @return {bool}\n */\n var hasReloadedEventsSince = function(root, time) {\n return getEventReloadTime(root) > time;\n };\n\n /**\n * Send a request to the server to load the events for the courses.\n *\n * @param {array} courses List of course objects.\n * @param {Number} startTime Timestamp to load events after.\n * @param {int|undefined} endTime Timestamp to load events up until.\n * @param {string|undefined} searchValue Search value\n * @return {object} jQuery promise resolved with the events.\n */\n var loadEventsForCourses = function(courses, startTime, endTime, searchValue) {\n var courseIds = courses.map(function(course) {\n return course.id;\n });\n\n return getEventsForCourseIds(courseIds, startTime, COURSE_EVENT_LIMIT + 1, endTime, searchValue);\n };\n\n /**\n * Render the courses in the DOM once the server has returned the courses.\n *\n * @param {array} courses List of course objects.\n * @param {object} root The root element\n * @param {Number} midnight The midnight timestamp in the user's timezone.\n * @param {Number} daysOffset Number of days from today to offset the events.\n * @param {Number} daysLimit Number of days from today to limit the events to.\n * @param {boolean} append Whether new content should be appended instead of replaced (eg \"show more courses\").\n * @return {object} jQuery promise resolved after rendering is complete.\n */\n var updateDisplayFromCourses = function(courses, root, midnight, daysOffset, daysLimit, append) {\n // Render the courses template.\n return Templates.render(TEMPLATES.COURSE_ITEMS, {\n courses: courses,\n midnight: midnight,\n hasdaysoffset: true,\n hasdayslimit: daysLimit != undefined,\n daysoffset: daysOffset,\n dayslimit: daysLimit,\n nodayslimit: daysLimit == undefined,\n courseview: true,\n hascourses: true\n }).then(function(html) {\n hideLoadingPlaceholder(root);\n\n if (html) {\n // Template rendering is complete and we have the HTML so we can\n // add it to the DOM.\n renderCourseItemsHTML(root, html, append);\n }\n\n return html;\n })\n .then(function(html) {\n if (courses.length < COURSE_LIMIT) {\n // We know there aren't any more courses because we got back less\n // than we asked for so hide the button to request more.\n hideMoreCoursesButton(root);\n } else {\n // Make sure the button is visible if there are more courses to load.\n showMoreCoursesButton(root);\n }\n\n return html;\n })\n .catch(function() {\n hideLoadingPlaceholder(root);\n });\n };\n\n /**\n * Find all of the visible course blocks and initialise the event\n * list module to being loading the events for the course block.\n *\n * @param {object} root The root element for the timeline courses view.\n * @param {boolean} append Whether content should be appended instead of replaced (eg \"show more courses\"). False by default.\n * @return {object} jQuery promise resolved with courses and events.\n */\n var loadMoreCourses = function(root, append = false) {\n const pendingPromise = new Pending('block/timeline:load-more-courses');\n var offset = getOffset(root);\n var limit = getLimit(root);\n const startTime = getStartTime(root);\n const endTime = getEndTime(root);\n const searchValue = root.closest(SELECTORS.TIMELINE_BLOCK).find(SELECTORS.TIMELINE_SEARCH).val();\n\n // Start loading the next set of courses.\n // Fetch up to limit number of courses with at least one action event in the time filtering specified.\n // Courses without events will also be fetched, but hidden in case they have events in other timespans.\n return CourseRepository.getEnrolledCoursesWithEventsByTimelineClassification(\n COURSE_CLASSIFICATION,\n limit,\n offset,\n COURSE_SORT,\n searchValue,\n startTime,\n endTime\n ).then(function(result) {\n var startEventLoadingTime = Date.now();\n var courses = result.courses;\n var nextOffset = result.nextoffset;\n var daysOffset = getDaysOffset(root);\n var daysLimit = getDaysLimit(root);\n var midnight = getMidnight(root);\n const moreCoursesAvailable = result.morecoursesavailable;\n\n // Record the next offset if we want to request more courses.\n setOffset(root, nextOffset);\n // Load the events for these courses.\n var eventsPromise = loadEventsForCourses(courses, startTime, endTime, searchValue);\n // Render the courses in the DOM.\n var renderPromise = updateDisplayFromCourses(courses, root, midnight, daysOffset, daysLimit, append);\n\n return $.when(eventsPromise, renderPromise)\n .then(function(eventsByCourse) {\n if (hasReloadedEventsSince(root, startEventLoadingTime)) {\n // All of the events are being reloaded so ignore our results.\n return eventsByCourse;\n }\n\n if (courses.length > 0) {\n // Render the events in the correct course event list.\n courses.forEach(function(course) {\n const courseId = course.id;\n const containerSelector = '[data-region=\"course-events-container\"][data-course-id=\"' + courseId + '\"]';\n const courseEventsContainer = root.find(containerSelector);\n const eventListRoot = courseEventsContainer.find(EventList.rootSelector);\n\n EventList.init(eventListRoot, additionalConfig);\n });\n\n if (!moreCoursesAvailable) {\n // If no more courses with events matching the current filtering exist, hide the more courses button.\n hideMoreCoursesButton(root);\n } else {\n // If more courses exist with events matching the current filtering, show the more courses button.\n showMoreCoursesButton(root);\n }\n } else {\n // No more courses to load, hide the more courses button.\n hideMoreCoursesButton(root);\n\n // A zero offset means this was not loading \"more courses\", so we need to display the no results message.\n if (offset == 0) {\n showNoCoursesWithEventsMessage(root);\n }\n }\n\n return eventsByCourse;\n });\n }).then(() => {\n return pendingPromise.resolve();\n }).catch(Notification.exception);\n };\n\n /**\n * Add event listeners to load more courses for the courses view.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var registerEventListeners = function(root) {\n CustomEvents.define(root, [CustomEvents.events.activate]);\n // Show more courses and load their events when the user clicks the \"more courses\" button.\n root.on(CustomEvents.events.activate, SELECTORS.MORE_COURSES_BUTTON, function(e, data) {\n enableMoreCoursesButtonLoading(root);\n loadMoreCourses(root, true)\n .then(function() {\n disableMoreCoursesButtonLoading(root);\n return;\n })\n .catch(function() {\n disableMoreCoursesButtonLoading(root);\n });\n\n if (data) {\n data.originalEvent.preventDefault();\n data.originalEvent.stopPropagation();\n }\n e.stopPropagation();\n });\n };\n\n /**\n * Initialise the timeline courses view. Begin loading the events\n * if this view is active. Add the relevant event listeners.\n *\n * This function should only be called once per page load because it\n * is adding event listeners to the page.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var init = function(root) {\n root = $(root);\n\n // Only need to handle course loading if the user is actively enrolled in a course.\n if (!root.find(SELECTORS.NO_COURSES_EMPTY_MESSAGE).length) {\n setEventReloadTime(root, Date.now());\n\n if (root.hasClass('active')) {\n // Only load if this is active otherwise it will be lazy loaded later.\n loadMoreCourses(root);\n root.attr('data-seen', true);\n }\n\n registerEventListeners(root);\n }\n };\n\n /**\n * Reset the element back to it's initial state. Begin loading the events again\n * if this view is active.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var reset = function(root) {\n\n setOffset(root, 0);\n showLoadingPlaceholder(root);\n hideNoCoursesWithEventsMessage(root);\n root.removeAttr('data-seen');\n\n if (root.hasClass('active')) {\n shown(root);\n }\n };\n\n /**\n * Begin loading the events unless we know there are no actively enrolled courses.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var shown = function(root) {\n if (!root.attr('data-seen') && !root.find(SELECTORS.NO_COURSES_EMPTY_MESSAGE).length) {\n loadMoreCourses(root);\n root.attr('data-seen', true);\n }\n };\n\n return {\n init: init,\n reset: reset,\n shown: shown\n };\n});\n"],"names":["define","$","Notification","CustomEvents","Templates","EventList","CourseRepository","EventsRepository","Pending","SELECTORS","TEMPLATES","additionalConfig","courseview","hideLoadingPlaceholder","root","find","addClass","hideMoreCoursesButton","showMoreCoursesButton","removeClass","disableMoreCoursesButtonLoading","button","prop","remove","showNoCoursesWithEventsMessage","container","replaceNodeContents","getOffset","parseInt","attr","setOffset","offset","getLimit","getDaysOffset","getDaysLimit","daysLimit","undefined","getMidnight","getStartTime","getEndTime","endTime","Math","floor","Date","now","midnight","hasReloadedEventsSince","time","data","getEventReloadTime","loadEventsForCourses","courses","startTime","searchValue","courseIds","limit","args","courseids","starttime","endtime","searchvalue","queryByCourses","getEventsForCourseIds","map","course","id","COURSE_EVENT_LIMIT","updateDisplayFromCourses","daysOffset","append","render","hasdaysoffset","hasdayslimit","daysoffset","dayslimit","nodayslimit","hascourses","then","html","appendNodeContents","renderCourseItemsHTML","length","catch","loadMoreCourses","pendingPromise","closest","val","getEnrolledCoursesWithEventsByTimelineClassification","result","startEventLoadingTime","nextOffset","nextoffset","moreCoursesAvailable","morecoursesavailable","eventsPromise","renderPromise","when","eventsByCourse","forEach","containerSelector","eventListRoot","rootSelector","init","resolve","exception","registerEventListeners","events","activate","on","e","enableMoreCoursesButtonLoading","originalEvent","preventDefault","stopPropagation","shown","setEventReloadTime","hasClass","reset","showLoadingPlaceholder","hideNoCoursesWithEventsMessage","removeAttr"],"mappings":"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"}
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/view_dates.min.js b/blocks/timeline/amd/build/view_dates.min.js
index 957469239bf..845fa865663 100644
--- a/blocks/timeline/amd/build/view_dates.min.js
+++ b/blocks/timeline/amd/build/view_dates.min.js
@@ -1,2 +1,9 @@
-define ("block_timeline/view_dates",["jquery","block_timeline/event_list","core/pubsub","core/paged_content_events"],function(a,b,c,d){var e={EVENT_LIST_CONTAINER:"[data-region=\"event-list-container\"]",NO_COURSES_EMPTY_MESSAGE:"[data-region=\"no-courses-empty-message\"]"},f=function(b,e){var f=e+d.SET_ITEMS_PER_PAGE_LIMIT;c.subscribe(f,function(c){a(b).data("limit",c)})},g=function(c){if(!c.find(e.NO_COURSES_EMPTY_MESSAGE).length){var d=c.find(e.EVENT_LIST_CONTAINER),g=a(d).attr("id")+"user_block_timeline"+Math.random();f(c,g);b.init(d,{persistentLimitKey:"block_timeline_user_limit_preference",eventNamespace:g})}};return{init:function init(b){b=a(b);if(b.hasClass("active")&&!b.find(e.NO_COURSES_EMPTY_MESSAGE).length){g(b);b.attr("data-seen",!0)}},reset:function reset(a){a.removeAttr("data-seen");if(a.hasClass("active")){g(a);a.attr("data-seen",!0)}},shown:function shown(a){if(!a.attr("data-seen")){g(a);a.attr("data-seen",!0)}}}});
-//# sourceMappingURL=view_dates.min.js.map
+/**
+ * Manage the timeline dates view for the timeline block.
+ *
+ * @copyright 2018 Ryan Wyllie
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_timeline/view_dates",["jquery","block_timeline/event_list","core/pubsub","core/paged_content_events"],(function($,EventList,PubSub,PagedContentEvents){var SELECTORS_EVENT_LIST_CONTAINER='[data-region="event-list-container"]',SELECTORS_NO_COURSES_EMPTY_MESSAGE='[data-region="no-courses-empty-message"]',load=function(root){if(!root.find(SELECTORS_NO_COURSES_EMPTY_MESSAGE).length){var eventListContainer=root.find(SELECTORS_EVENT_LIST_CONTAINER),namespace=$(eventListContainer).attr("id")+"user_block_timeline"+Math.random();!function(root,namespace){var event=namespace+PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT;PubSub.subscribe(event,(function(limit){$(root).data("limit",limit)}))}(root,namespace);var config={persistentLimitKey:"block_timeline_user_limit_preference",eventNamespace:namespace};EventList.init(eventListContainer,config)}};return{init:function(root){(root=$(root)).hasClass("active")&&!root.find(SELECTORS_NO_COURSES_EMPTY_MESSAGE).length&&(load(root),root.attr("data-seen",!0))},reset:function(root){root.removeAttr("data-seen"),root.hasClass("active")&&(load(root),root.attr("data-seen",!0))},shown:function(root){root.attr("data-seen")||(load(root),root.attr("data-seen",!0))}}}));
+
+//# sourceMappingURL=view_dates.min.js.map
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/view_dates.min.js.map b/blocks/timeline/amd/build/view_dates.min.js.map
index 85d788e9c80..209dac7dccf 100644
--- a/blocks/timeline/amd/build/view_dates.min.js.map
+++ b/blocks/timeline/amd/build/view_dates.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/view_dates.js"],"names":["define","$","EventList","PubSub","PagedContentEvents","SELECTORS","EVENT_LIST_CONTAINER","NO_COURSES_EMPTY_MESSAGE","registerEventListeners","root","namespace","event","SET_ITEMS_PER_PAGE_LIMIT","subscribe","limit","data","load","find","length","eventListContainer","attr","Math","random","init","persistentLimitKey","eventNamespace","hasClass","reset","removeAttr","shown"],"mappings":"AAsBAA,OAAM,6BACN,CACI,QADJ,CAEI,2BAFJ,CAGI,aAHJ,CAII,2BAJJ,CADM,CAON,SACIC,CADJ,CAEIC,CAFJ,CAGIC,CAHJ,CAIIC,CAJJ,CAKE,IAEMC,CAAAA,CAAS,CAAG,CACZC,oBAAoB,CAAE,wCADV,CAEZC,wBAAwB,CAAE,4CAFd,CAFlB,CAaMC,CAAsB,CAAG,SAASC,CAAT,CAAeC,CAAf,CAA0B,CACnD,GAAIC,CAAAA,CAAK,CAAGD,CAAS,CAAGN,CAAkB,CAACQ,wBAA3C,CACAT,CAAM,CAACU,SAAP,CAAiBF,CAAjB,CAAwB,SAASG,CAAT,CAAgB,CACpCb,CAAC,CAACQ,CAAD,CAAD,CAAQM,IAAR,CAAa,OAAb,CAAsBD,CAAtB,CACH,CAFD,CAGH,CAlBH,CAyBME,CAAI,CAAG,SAASP,CAAT,CAAe,CAEtB,GAAI,CAACA,CAAI,CAACQ,IAAL,CAAUZ,CAAS,CAACE,wBAApB,EAA8CW,MAAnD,CAA2D,IACnDC,CAAAA,CAAkB,CAAGV,CAAI,CAACQ,IAAL,CAAUZ,CAAS,CAACC,oBAApB,CAD8B,CAEnDI,CAAS,CAAGT,CAAC,CAACkB,CAAD,CAAD,CAAsBC,IAAtB,CAA2B,IAA3B,EAAmC,qBAAnC,CAA2DC,IAAI,CAACC,MAAL,EAFpB,CAGvDd,CAAsB,CAACC,CAAD,CAAOC,CAAP,CAAtB,CAMAR,CAAS,CAACqB,IAAV,CAAeJ,CAAf,CAJa,CACTK,kBAAkB,CAAE,sCADX,CAETC,cAAc,CAAEf,CAFP,CAIb,CACH,CACJ,CAtCH,CAkFE,MAAO,CACHa,IAAI,CArCG,QAAPA,CAAAA,IAAO,CAASd,CAAT,CAAe,CACtBA,CAAI,CAAGR,CAAC,CAACQ,CAAD,CAAR,CAGA,GAAIA,CAAI,CAACiB,QAAL,CAAc,QAAd,GAA2B,CAACjB,CAAI,CAACQ,IAAL,CAAUZ,CAAS,CAACE,wBAApB,EAA8CW,MAA9E,CAAsF,CAClFF,CAAI,CAACP,CAAD,CAAJ,CACAA,CAAI,CAACW,IAAL,CAAU,WAAV,IACH,CACJ,CA4BM,CAEHO,KAAK,CAtBG,QAARA,CAAAA,KAAQ,CAASlB,CAAT,CAAe,CACvBA,CAAI,CAACmB,UAAL,CAAgB,WAAhB,EACA,GAAInB,CAAI,CAACiB,QAAL,CAAc,QAAd,CAAJ,CAA6B,CACzBV,CAAI,CAACP,CAAD,CAAJ,CACAA,CAAI,CAACW,IAAL,CAAU,WAAV,IACH,CACJ,CAcM,CAGHS,KAAK,CAVG,QAARA,CAAAA,KAAQ,CAASpB,CAAT,CAAe,CACvB,GAAI,CAACA,CAAI,CAACW,IAAL,CAAU,WAAV,CAAL,CAA6B,CACzBJ,CAAI,CAACP,CAAD,CAAJ,CACAA,CAAI,CAACW,IAAL,CAAU,WAAV,IACH,CACJ,CAEM,CAKV,CAnGK,CAAN","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 .\n\n/**\n * Manage the timeline dates view for the timeline block.\n *\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'block_timeline/event_list',\n 'core/pubsub',\n 'core/paged_content_events'\n],\nfunction(\n $,\n EventList,\n PubSub,\n PagedContentEvents\n) {\n\n var SELECTORS = {\n EVENT_LIST_CONTAINER: '[data-region=\"event-list-container\"]',\n NO_COURSES_EMPTY_MESSAGE: '[data-region=\"no-courses-empty-message\"]',\n };\n\n /**\n * Setup the listeners for the timeline block\n *\n * @param {string} root view dates container\n * @param {string} namespace The namespace for the paged content\n */\n var registerEventListeners = function(root, namespace) {\n var event = namespace + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT;\n PubSub.subscribe(event, function(limit) {\n $(root).data('limit', limit);\n });\n };\n\n /**\n * Initialise the event list and being loading the events.\n *\n * @param {object} root The root element for the timeline dates view.\n */\n var load = function(root) {\n\n if (!root.find(SELECTORS.NO_COURSES_EMPTY_MESSAGE).length) {\n var eventListContainer = root.find(SELECTORS.EVENT_LIST_CONTAINER);\n var namespace = $(eventListContainer).attr('id') + \"user_block_timeline\" + Math.random();\n registerEventListeners(root, namespace);\n\n var config = {\n persistentLimitKey: \"block_timeline_user_limit_preference\",\n eventNamespace: namespace\n };\n EventList.init(eventListContainer, config);\n }\n };\n\n /**\n * Initialise the timeline dates view. Begin loading the events\n * if this view is active.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var init = function(root) {\n root = $(root);\n\n // Only need to handle events loading if the user is actively enrolled in a course and this view is active.\n if (root.hasClass('active') && !root.find(SELECTORS.NO_COURSES_EMPTY_MESSAGE).length) {\n load(root);\n root.attr('data-seen', true);\n }\n };\n\n /**\n * Reset the view back to it's initial state. If this view is active then\n * beging loading the events.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var reset = function(root) {\n root.removeAttr('data-seen');\n if (root.hasClass('active')) {\n load(root);\n root.attr('data-seen', true);\n }\n };\n\n /**\n * Load the events if this is the first time the view is displayed.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var shown = function(root) {\n if (!root.attr('data-seen')) {\n load(root);\n root.attr('data-seen', true);\n }\n };\n\n return {\n init: init,\n reset: reset,\n shown: shown\n };\n});\n"],"file":"view_dates.min.js"}
\ No newline at end of file
+{"version":3,"file":"view_dates.min.js","sources":["../src/view_dates.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 .\n\n/**\n * Manage the timeline dates view for the timeline block.\n *\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'block_timeline/event_list',\n 'core/pubsub',\n 'core/paged_content_events'\n],\nfunction(\n $,\n EventList,\n PubSub,\n PagedContentEvents\n) {\n\n var SELECTORS = {\n EVENT_LIST_CONTAINER: '[data-region=\"event-list-container\"]',\n NO_COURSES_EMPTY_MESSAGE: '[data-region=\"no-courses-empty-message\"]',\n };\n\n /**\n * Setup the listeners for the timeline block\n *\n * @param {string} root view dates container\n * @param {string} namespace The namespace for the paged content\n */\n var registerEventListeners = function(root, namespace) {\n var event = namespace + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT;\n PubSub.subscribe(event, function(limit) {\n $(root).data('limit', limit);\n });\n };\n\n /**\n * Initialise the event list and being loading the events.\n *\n * @param {object} root The root element for the timeline dates view.\n */\n var load = function(root) {\n\n if (!root.find(SELECTORS.NO_COURSES_EMPTY_MESSAGE).length) {\n var eventListContainer = root.find(SELECTORS.EVENT_LIST_CONTAINER);\n var namespace = $(eventListContainer).attr('id') + \"user_block_timeline\" + Math.random();\n registerEventListeners(root, namespace);\n\n var config = {\n persistentLimitKey: \"block_timeline_user_limit_preference\",\n eventNamespace: namespace\n };\n EventList.init(eventListContainer, config);\n }\n };\n\n /**\n * Initialise the timeline dates view. Begin loading the events\n * if this view is active.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var init = function(root) {\n root = $(root);\n\n // Only need to handle events loading if the user is actively enrolled in a course and this view is active.\n if (root.hasClass('active') && !root.find(SELECTORS.NO_COURSES_EMPTY_MESSAGE).length) {\n load(root);\n root.attr('data-seen', true);\n }\n };\n\n /**\n * Reset the view back to it's initial state. If this view is active then\n * beging loading the events.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var reset = function(root) {\n root.removeAttr('data-seen');\n if (root.hasClass('active')) {\n load(root);\n root.attr('data-seen', true);\n }\n };\n\n /**\n * Load the events if this is the first time the view is displayed.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var shown = function(root) {\n if (!root.attr('data-seen')) {\n load(root);\n root.attr('data-seen', true);\n }\n };\n\n return {\n init: init,\n reset: reset,\n shown: shown\n };\n});\n"],"names":["define","$","EventList","PubSub","PagedContentEvents","SELECTORS","load","root","find","length","eventListContainer","namespace","attr","Math","random","event","SET_ITEMS_PER_PAGE_LIMIT","subscribe","limit","data","registerEventListeners","config","persistentLimitKey","eventNamespace","init","hasClass","reset","removeAttr","shown"],"mappings":";;;;;;AAsBAA,mCACA,CACI,SACA,4BACA,cACA,8BAEJ,SACIC,EACAC,UACAC,OACAC,wBAGIC,+BACsB,uCADtBA,mCAE0B,2CAqB1BC,KAAO,SAASC,UAEXA,KAAKC,KAAKH,oCAAoCI,OAAQ,KACnDC,mBAAqBH,KAAKC,KAAKH,gCAC/BM,UAAYV,EAAES,oBAAoBE,KAAK,MAAQ,sBAAwBC,KAAKC,UAhB3D,SAASP,KAAMI,eACpCI,MAAQJ,UAAYP,mBAAmBY,yBAC3Cb,OAAOc,UAAUF,OAAO,SAASG,OAC7BjB,EAAEM,MAAMY,KAAK,QAASD,UActBE,CAAuBb,KAAMI,eAEzBU,OAAS,CACTC,mBAAoB,uCACpBC,eAAgBZ,WAEpBT,UAAUsB,KAAKd,mBAAoBW,gBA8CpC,CACHG,KArCO,SAASjB,OAChBA,KAAON,EAAEM,OAGAkB,SAAS,YAAclB,KAAKC,KAAKH,oCAAoCI,SAC1EH,KAAKC,MACLA,KAAKK,KAAK,aAAa,KAgC3Bc,MAtBQ,SAASnB,MACjBA,KAAKoB,WAAW,aACZpB,KAAKkB,SAAS,YACdnB,KAAKC,MACLA,KAAKK,KAAK,aAAa,KAmB3BgB,MAVQ,SAASrB,MACZA,KAAKK,KAAK,eACXN,KAAKC,MACLA,KAAKK,KAAK,aAAa"}
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/view_nav.min.js b/blocks/timeline/amd/build/view_nav.min.js
index dec2c5d3983..52c1bc2b454 100644
--- a/blocks/timeline/amd/build/view_nav.min.js
+++ b/blocks/timeline/amd/build/view_nav.min.js
@@ -1,2 +1,9 @@
-define ("block_timeline/view_nav",["jquery","core/custom_interaction_events","block_timeline/view","core/ajax","core/notification","core/utils"],function(a,b,c,d,e,f){var g={TIMELINE_DAY_FILTER:"[data-region=\"day-filter\"]",TIMELINE_DAY_FILTER_OPTION:"[data-from]",TIMELINE_VIEW_SELECTOR:"[data-region=\"view-selector\"]",DATA_DAYS_OFFSET:"[data-days-offset]",DATA_DAYS_LIMIT:"[data-days-limit]",TIMELINE_SEARCH_INPUT:"[data-action=\"search\"]",TIMELINE_SEARCH_CLEAR_ICON:"[data-action=\"clearsearch\"]",NO_COURSES_EMPTY_MESSAGE:"[data-region=\"no-courses-empty-message\"]"},h=function(a,b){d.call([{methodname:"core_user_update_user_preferences",args:{preferences:[{type:a,value:b}]}}])[0].fail(e.exception)},i=function(d,f){var i=d.find(g.TIMELINE_DAY_FILTER);b.define(i,[b.events.activate]);i.on(b.events.activate,g.TIMELINE_DAY_FILTER_OPTION,function(b,e){var i=a(b.currentTarget).data("filtername");h("block_timeline_user_filter_preference",i);var j=a(b.target).closest(g.TIMELINE_DAY_FILTER_OPTION);if("true"==j.attr("aria-current")){return}var k=j.attr("data-from"),l=j.attr("data-to"),m=d.find(g.DATA_DAYS_OFFSET);m.attr("data-days-offset",k);if(l!=void 0){m.attr("data-days-limit",l)}else{m.removeAttr("data-days-limit")}if("overdue"===j.attr("data-filtername")){m.attr("data-filter-overdue",!0)}else{m.removeAttr("data-filter-overdue")}c.reset(f);e.originalEvent.preventDefault()})},j=function(d,f){var i=d.find(g.TIMELINE_VIEW_SELECTOR);i.on("shown shown.bs.tab",function(b){c.shown(f);a(b.target).removeClass("active")});b.define(i,[b.events.activate]);i.on(b.events.activate,"[data-toggle='tab']",function(b){var c=a(b.currentTarget).data("filtername");h("block_timeline_user_sort_preference",c)})},k=function(a,b){var c=a.find(g.TIMELINE_SEARCH_INPUT),d=a.find(g.TIMELINE_SEARCH_CLEAR_ICON);c.on("input",f.debounce(function(){if(""!==c.val()){l(d,b)}else{m(d,b)}},300));d.on("click",function(){c.val("");m(d,b);c.focus()})},l=function(a,b){a.removeClass("d-none");c.reset(b)},m=function(a,b){a.addClass("d-none");c.reset(b)};return{init:function init(b,c){b=a(b);j(b,c);if(!b.find(g.NO_COURSES_EMPTY_MESSAGE).length){i(b,c);k(b,c)}}}});
-//# sourceMappingURL=view_nav.min.js.map
+/**
+ * Manage the timeline view navigation for the timeline block.
+ *
+ * @copyright 2018 Ryan Wyllie
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("block_timeline/view_nav",["jquery","core/custom_interaction_events","block_timeline/view","core/ajax","core/notification","core/utils"],(function($,CustomEvents,View,Ajax,Notification,Utils){var SELECTORS_TIMELINE_DAY_FILTER='[data-region="day-filter"]',SELECTORS_TIMELINE_DAY_FILTER_OPTION="[data-from]",SELECTORS_TIMELINE_VIEW_SELECTOR='[data-region="view-selector"]',SELECTORS_DATA_DAYS_OFFSET="[data-days-offset]",SELECTORS_TIMELINE_SEARCH_INPUT='[data-action="search"]',SELECTORS_TIMELINE_SEARCH_CLEAR_ICON='[data-action="clearsearch"]',SELECTORS_NO_COURSES_EMPTY_MESSAGE='[data-region="no-courses-empty-message"]',updateUserPreferences=function(type,value){var request={methodname:"core_user_update_user_preferences",args:{preferences:[{type:type,value:value}]}};Ajax.call([request])[0].fail(Notification.exception)};const activeSearchState=(clearSearchIcon,timelineViewRoot)=>{clearSearchIcon.removeClass("d-none"),View.reset(timelineViewRoot)},clearSearchState=(clearSearchIcon,timelineViewRoot)=>{clearSearchIcon.addClass("d-none"),View.reset(timelineViewRoot)};return{init:function(root,timelineViewRoot){(function(root,timelineViewRoot){var viewSelector=root.find(SELECTORS_TIMELINE_VIEW_SELECTOR);viewSelector.on("shown shown.bs.tab",(function(e){View.shown(timelineViewRoot),$(e.target).removeClass("active")})),CustomEvents.define(viewSelector,[CustomEvents.events.activate]),viewSelector.on(CustomEvents.events.activate,"[data-toggle='tab']",(function(e){var filtername=$(e.currentTarget).data("filtername");updateUserPreferences("block_timeline_user_sort_preference",filtername)}))})(root=$(root),timelineViewRoot),root.find(SELECTORS_NO_COURSES_EMPTY_MESSAGE).length||(function(root,timelineViewRoot){var timelineDaySelectorContainer=root.find(SELECTORS_TIMELINE_DAY_FILTER);CustomEvents.define(timelineDaySelectorContainer,[CustomEvents.events.activate]),timelineDaySelectorContainer.on(CustomEvents.events.activate,SELECTORS_TIMELINE_DAY_FILTER_OPTION,(function(e,data){var filtername=$(e.currentTarget).data("filtername");updateUserPreferences("block_timeline_user_filter_preference",filtername);var option=$(e.target).closest(SELECTORS_TIMELINE_DAY_FILTER_OPTION);if("true"!=option.attr("aria-current")){var daysOffset=option.attr("data-from"),daysLimit=option.attr("data-to"),elementsWithDaysOffset=root.find(SELECTORS_DATA_DAYS_OFFSET);elementsWithDaysOffset.attr("data-days-offset",daysOffset),null!=daysLimit?elementsWithDaysOffset.attr("data-days-limit",daysLimit):elementsWithDaysOffset.removeAttr("data-days-limit"),"overdue"===option.attr("data-filtername")?elementsWithDaysOffset.attr("data-filter-overdue",!0):elementsWithDaysOffset.removeAttr("data-filter-overdue"),View.reset(timelineViewRoot),data.originalEvent.preventDefault()}}))}(root,timelineViewRoot),((root,timelineViewRoot)=>{const searchInput=root.find(SELECTORS_TIMELINE_SEARCH_INPUT),clearSearchIcon=root.find(SELECTORS_TIMELINE_SEARCH_CLEAR_ICON);searchInput.on("input",Utils.debounce((()=>{""!==searchInput.val()?activeSearchState(clearSearchIcon,timelineViewRoot):clearSearchState(clearSearchIcon,timelineViewRoot)}),300)),clearSearchIcon.on("click",(()=>{searchInput.val(""),clearSearchState(clearSearchIcon,timelineViewRoot),searchInput.focus()}))})(root,timelineViewRoot))}}}));
+
+//# sourceMappingURL=view_nav.min.js.map
\ No newline at end of file
diff --git a/blocks/timeline/amd/build/view_nav.min.js.map b/blocks/timeline/amd/build/view_nav.min.js.map
index a772fa0f3c4..fead7cf6fd1 100644
--- a/blocks/timeline/amd/build/view_nav.min.js.map
+++ b/blocks/timeline/amd/build/view_nav.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/view_nav.js"],"names":["define","$","CustomEvents","View","Ajax","Notification","Utils","SELECTORS","TIMELINE_DAY_FILTER","TIMELINE_DAY_FILTER_OPTION","TIMELINE_VIEW_SELECTOR","DATA_DAYS_OFFSET","DATA_DAYS_LIMIT","TIMELINE_SEARCH_INPUT","TIMELINE_SEARCH_CLEAR_ICON","NO_COURSES_EMPTY_MESSAGE","updateUserPreferences","type","value","call","methodname","args","preferences","fail","exception","registerTimelineDaySelector","root","timelineViewRoot","timelineDaySelectorContainer","find","events","activate","on","e","data","filtername","currentTarget","option","target","closest","attr","daysOffset","daysLimit","elementsWithDaysOffset","removeAttr","reset","originalEvent","preventDefault","registerViewSelector","viewSelector","shown","removeClass","registerSearch","searchInput","clearSearchIcon","debounce","val","activeSearchState","clearSearchState","focus","addClass","init","length"],"mappings":"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","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 .\n\n/**\n * Manage the timeline view navigation for the timeline block.\n *\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'core/custom_interaction_events',\n 'block_timeline/view',\n 'core/ajax',\n 'core/notification',\n 'core/utils'\n],\nfunction(\n $,\n CustomEvents,\n View,\n Ajax,\n Notification,\n Utils\n) {\n\n var SELECTORS = {\n TIMELINE_DAY_FILTER: '[data-region=\"day-filter\"]',\n TIMELINE_DAY_FILTER_OPTION: '[data-from]',\n TIMELINE_VIEW_SELECTOR: '[data-region=\"view-selector\"]',\n DATA_DAYS_OFFSET: '[data-days-offset]',\n DATA_DAYS_LIMIT: '[data-days-limit]',\n TIMELINE_SEARCH_INPUT: '[data-action=\"search\"]',\n TIMELINE_SEARCH_CLEAR_ICON: '[data-action=\"clearsearch\"]',\n NO_COURSES_EMPTY_MESSAGE: '[data-region=\"no-courses-empty-message\"]',\n };\n\n /**\n * Generic handler to persist user preferences\n *\n * @param {string} type The name of the attribute you're updating\n * @param {string} value The value of the attribute you're updating\n */\n var updateUserPreferences = function(type, value) {\n var request = {\n methodname: 'core_user_update_user_preferences',\n args: {\n preferences: [\n {\n type: type,\n value: value\n }\n ]\n }\n };\n\n Ajax.call([request])[0]\n .fail(Notification.exception);\n };\n\n /**\n * Event listener for the day selector (\"Next 7 days\", \"Next 30 days\", etc).\n *\n * @param {object} root The root element for the timeline block\n * @param {object} timelineViewRoot The root element for the timeline view\n */\n var registerTimelineDaySelector = function(root, timelineViewRoot) {\n var timelineDaySelectorContainer = root.find(SELECTORS.TIMELINE_DAY_FILTER);\n\n CustomEvents.define(timelineDaySelectorContainer, [CustomEvents.events.activate]);\n timelineDaySelectorContainer.on(\n CustomEvents.events.activate,\n SELECTORS.TIMELINE_DAY_FILTER_OPTION,\n function(e, data) {\n // Update the user preference\n var filtername = $(e.currentTarget).data('filtername');\n var type = 'block_timeline_user_filter_preference';\n updateUserPreferences(type, filtername);\n\n var option = $(e.target).closest(SELECTORS.TIMELINE_DAY_FILTER_OPTION);\n\n if (option.attr('aria-current') == 'true') {\n // If it's already active then we don't need to do anything.\n return;\n }\n\n var daysOffset = option.attr('data-from');\n var daysLimit = option.attr('data-to');\n var elementsWithDaysOffset = root.find(SELECTORS.DATA_DAYS_OFFSET);\n\n elementsWithDaysOffset.attr('data-days-offset', daysOffset);\n\n if (daysLimit != undefined) {\n elementsWithDaysOffset.attr('data-days-limit', daysLimit);\n } else {\n elementsWithDaysOffset.removeAttr('data-days-limit');\n }\n\n if (option.attr('data-filtername') === 'overdue') {\n elementsWithDaysOffset.attr('data-filter-overdue', true);\n } else {\n elementsWithDaysOffset.removeAttr('data-filter-overdue');\n }\n\n // Reset the views to reinitialise the event lists now that we've\n // updated the day limits.\n View.reset(timelineViewRoot);\n\n data.originalEvent.preventDefault();\n }\n );\n };\n\n /**\n * Event listener for the \"sort\" button in the timeline navigation that allows for\n * changing between the timeline dates and courses views.\n *\n * On a view change we tell the timeline view module that the view has been shown\n * so that it can handle how to display the appropriate view.\n *\n * @param {object} root The root element for the timeline block\n * @param {object} timelineViewRoot The root element for the timeline view\n */\n var registerViewSelector = function(root, timelineViewRoot) {\n var viewSelector = root.find(SELECTORS.TIMELINE_VIEW_SELECTOR);\n\n // Listen for when the user changes tab so that we can show the first set of courses\n // and load their events when they request the sort by courses view for the first time.\n viewSelector.on('shown shown.bs.tab', function(e) {\n View.shown(timelineViewRoot);\n $(e.target).removeClass('active');\n });\n\n\n // Event selector for user_sort\n CustomEvents.define(viewSelector, [CustomEvents.events.activate]);\n viewSelector.on(CustomEvents.events.activate, \"[data-toggle='tab']\", function(e) {\n var filtername = $(e.currentTarget).data('filtername');\n var type = 'block_timeline_user_sort_preference';\n updateUserPreferences(type, filtername);\n });\n };\n\n /**\n * Event listener for the \"search\" input field in the timeline navigation that allows for\n * searching the activity name, course name and activity type.\n *\n * @param {object} root The root element for the timeline block\n * @param {object} timelineViewRoot The root element for the timeline view\n */\n const registerSearch = (root, timelineViewRoot) => {\n const searchInput = root.find(SELECTORS.TIMELINE_SEARCH_INPUT);\n const clearSearchIcon = root.find(SELECTORS.TIMELINE_SEARCH_CLEAR_ICON);\n searchInput.on('input', Utils.debounce(() => {\n if (searchInput.val() !== '') {\n activeSearchState(clearSearchIcon, timelineViewRoot);\n } else {\n clearSearchState(clearSearchIcon, timelineViewRoot);\n }\n }, 300));\n clearSearchIcon.on('click', () => {\n searchInput.val('');\n clearSearchState(clearSearchIcon, timelineViewRoot);\n searchInput.focus();\n });\n };\n\n /**\n * Show the clear search icon.\n *\n * @param {object} clearSearchIcon Clear search icon element.\n * @param {object} timelineViewRoot The root element for the timeline view\n */\n const activeSearchState = (clearSearchIcon, timelineViewRoot) => {\n clearSearchIcon.removeClass('d-none');\n View.reset(timelineViewRoot);\n };\n\n /**\n * Hide the clear search icon.\n *\n * @param {object} clearSearchIcon Clear search icon element.\n * @param {object} timelineViewRoot The root element for the timeline view\n */\n const clearSearchState = (clearSearchIcon, timelineViewRoot) => {\n clearSearchIcon.addClass('d-none');\n View.reset(timelineViewRoot);\n };\n\n /**\n * Initialise the timeline view navigation by adding event listeners to\n * the navigation elements.\n *\n * @param {object} root The root element for the timeline block\n * @param {object} timelineViewRoot The root element for the timeline view\n */\n var init = function(root, timelineViewRoot) {\n root = $(root);\n\n registerViewSelector(root, timelineViewRoot);\n\n // Only need to handle filtering if the user is actively enrolled in a course.\n if (!root.find(SELECTORS.NO_COURSES_EMPTY_MESSAGE).length) {\n registerTimelineDaySelector(root, timelineViewRoot);\n registerSearch(root, timelineViewRoot);\n }\n };\n\n return {\n init: init\n };\n});\n"],"file":"view_nav.min.js"}
\ No newline at end of file
+{"version":3,"file":"view_nav.min.js","sources":["../src/view_nav.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 .\n\n/**\n * Manage the timeline view navigation for the timeline block.\n *\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'core/custom_interaction_events',\n 'block_timeline/view',\n 'core/ajax',\n 'core/notification',\n 'core/utils'\n],\nfunction(\n $,\n CustomEvents,\n View,\n Ajax,\n Notification,\n Utils\n) {\n\n var SELECTORS = {\n TIMELINE_DAY_FILTER: '[data-region=\"day-filter\"]',\n TIMELINE_DAY_FILTER_OPTION: '[data-from]',\n TIMELINE_VIEW_SELECTOR: '[data-region=\"view-selector\"]',\n DATA_DAYS_OFFSET: '[data-days-offset]',\n DATA_DAYS_LIMIT: '[data-days-limit]',\n TIMELINE_SEARCH_INPUT: '[data-action=\"search\"]',\n TIMELINE_SEARCH_CLEAR_ICON: '[data-action=\"clearsearch\"]',\n NO_COURSES_EMPTY_MESSAGE: '[data-region=\"no-courses-empty-message\"]',\n };\n\n /**\n * Generic handler to persist user preferences\n *\n * @param {string} type The name of the attribute you're updating\n * @param {string} value The value of the attribute you're updating\n */\n var updateUserPreferences = function(type, value) {\n var request = {\n methodname: 'core_user_update_user_preferences',\n args: {\n preferences: [\n {\n type: type,\n value: value\n }\n ]\n }\n };\n\n Ajax.call([request])[0]\n .fail(Notification.exception);\n };\n\n /**\n * Event listener for the day selector (\"Next 7 days\", \"Next 30 days\", etc).\n *\n * @param {object} root The root element for the timeline block\n * @param {object} timelineViewRoot The root element for the timeline view\n */\n var registerTimelineDaySelector = function(root, timelineViewRoot) {\n var timelineDaySelectorContainer = root.find(SELECTORS.TIMELINE_DAY_FILTER);\n\n CustomEvents.define(timelineDaySelectorContainer, [CustomEvents.events.activate]);\n timelineDaySelectorContainer.on(\n CustomEvents.events.activate,\n SELECTORS.TIMELINE_DAY_FILTER_OPTION,\n function(e, data) {\n // Update the user preference\n var filtername = $(e.currentTarget).data('filtername');\n var type = 'block_timeline_user_filter_preference';\n updateUserPreferences(type, filtername);\n\n var option = $(e.target).closest(SELECTORS.TIMELINE_DAY_FILTER_OPTION);\n\n if (option.attr('aria-current') == 'true') {\n // If it's already active then we don't need to do anything.\n return;\n }\n\n var daysOffset = option.attr('data-from');\n var daysLimit = option.attr('data-to');\n var elementsWithDaysOffset = root.find(SELECTORS.DATA_DAYS_OFFSET);\n\n elementsWithDaysOffset.attr('data-days-offset', daysOffset);\n\n if (daysLimit != undefined) {\n elementsWithDaysOffset.attr('data-days-limit', daysLimit);\n } else {\n elementsWithDaysOffset.removeAttr('data-days-limit');\n }\n\n if (option.attr('data-filtername') === 'overdue') {\n elementsWithDaysOffset.attr('data-filter-overdue', true);\n } else {\n elementsWithDaysOffset.removeAttr('data-filter-overdue');\n }\n\n // Reset the views to reinitialise the event lists now that we've\n // updated the day limits.\n View.reset(timelineViewRoot);\n\n data.originalEvent.preventDefault();\n }\n );\n };\n\n /**\n * Event listener for the \"sort\" button in the timeline navigation that allows for\n * changing between the timeline dates and courses views.\n *\n * On a view change we tell the timeline view module that the view has been shown\n * so that it can handle how to display the appropriate view.\n *\n * @param {object} root The root element for the timeline block\n * @param {object} timelineViewRoot The root element for the timeline view\n */\n var registerViewSelector = function(root, timelineViewRoot) {\n var viewSelector = root.find(SELECTORS.TIMELINE_VIEW_SELECTOR);\n\n // Listen for when the user changes tab so that we can show the first set of courses\n // and load their events when they request the sort by courses view for the first time.\n viewSelector.on('shown shown.bs.tab', function(e) {\n View.shown(timelineViewRoot);\n $(e.target).removeClass('active');\n });\n\n\n // Event selector for user_sort\n CustomEvents.define(viewSelector, [CustomEvents.events.activate]);\n viewSelector.on(CustomEvents.events.activate, \"[data-toggle='tab']\", function(e) {\n var filtername = $(e.currentTarget).data('filtername');\n var type = 'block_timeline_user_sort_preference';\n updateUserPreferences(type, filtername);\n });\n };\n\n /**\n * Event listener for the \"search\" input field in the timeline navigation that allows for\n * searching the activity name, course name and activity type.\n *\n * @param {object} root The root element for the timeline block\n * @param {object} timelineViewRoot The root element for the timeline view\n */\n const registerSearch = (root, timelineViewRoot) => {\n const searchInput = root.find(SELECTORS.TIMELINE_SEARCH_INPUT);\n const clearSearchIcon = root.find(SELECTORS.TIMELINE_SEARCH_CLEAR_ICON);\n searchInput.on('input', Utils.debounce(() => {\n if (searchInput.val() !== '') {\n activeSearchState(clearSearchIcon, timelineViewRoot);\n } else {\n clearSearchState(clearSearchIcon, timelineViewRoot);\n }\n }, 300));\n clearSearchIcon.on('click', () => {\n searchInput.val('');\n clearSearchState(clearSearchIcon, timelineViewRoot);\n searchInput.focus();\n });\n };\n\n /**\n * Show the clear search icon.\n *\n * @param {object} clearSearchIcon Clear search icon element.\n * @param {object} timelineViewRoot The root element for the timeline view\n */\n const activeSearchState = (clearSearchIcon, timelineViewRoot) => {\n clearSearchIcon.removeClass('d-none');\n View.reset(timelineViewRoot);\n };\n\n /**\n * Hide the clear search icon.\n *\n * @param {object} clearSearchIcon Clear search icon element.\n * @param {object} timelineViewRoot The root element for the timeline view\n */\n const clearSearchState = (clearSearchIcon, timelineViewRoot) => {\n clearSearchIcon.addClass('d-none');\n View.reset(timelineViewRoot);\n };\n\n /**\n * Initialise the timeline view navigation by adding event listeners to\n * the navigation elements.\n *\n * @param {object} root The root element for the timeline block\n * @param {object} timelineViewRoot The root element for the timeline view\n */\n var init = function(root, timelineViewRoot) {\n root = $(root);\n\n registerViewSelector(root, timelineViewRoot);\n\n // Only need to handle filtering if the user is actively enrolled in a course.\n if (!root.find(SELECTORS.NO_COURSES_EMPTY_MESSAGE).length) {\n registerTimelineDaySelector(root, timelineViewRoot);\n registerSearch(root, timelineViewRoot);\n }\n };\n\n return {\n init: init\n };\n});\n"],"names":["define","$","CustomEvents","View","Ajax","Notification","Utils","SELECTORS","updateUserPreferences","type","value","request","methodname","args","preferences","call","fail","exception","activeSearchState","clearSearchIcon","timelineViewRoot","removeClass","reset","clearSearchState","addClass","init","root","viewSelector","find","on","e","shown","target","events","activate","filtername","currentTarget","data","registerViewSelector","length","timelineDaySelectorContainer","option","closest","attr","daysOffset","daysLimit","elementsWithDaysOffset","undefined","removeAttr","originalEvent","preventDefault","registerTimelineDaySelector","searchInput","debounce","val","focus","registerSearch"],"mappings":";;;;;;AAsBAA,iCACA,CACI,SACA,iCACA,sBACA,YACA,oBACA,eAEJ,SACIC,EACAC,aACAC,KACAC,KACAC,aACAC,WAGIC,8BACqB,6BADrBA,qCAE4B,cAF5BA,iCAGwB,gCAHxBA,2BAIkB,qBAJlBA,gCAMuB,yBANvBA,qCAO4B,8BAP5BA,mCAQ0B,2CAS1BC,sBAAwB,SAASC,KAAMC,WACnCC,QAAU,CACVC,WAAY,oCACZC,KAAM,CACFC,YAAa,CACT,CACIL,KAAMA,KACNC,MAAOA,UAMvBN,KAAKW,KAAK,CAACJ,UAAU,GAChBK,KAAKX,aAAaY,kBAoHrBC,kBAAoB,CAACC,gBAAiBC,oBACxCD,gBAAgBE,YAAY,UAC5BlB,KAAKmB,MAAMF,mBASTG,iBAAmB,CAACJ,gBAAiBC,oBACvCD,gBAAgBK,SAAS,UACzBrB,KAAKmB,MAAMF,yBAsBR,CACHK,KAbO,SAASC,KAAMN,mBAzEC,SAASM,KAAMN,sBAClCO,aAAeD,KAAKE,KAAKrB,kCAI7BoB,aAAaE,GAAG,sBAAsB,SAASC,GAC3C3B,KAAK4B,MAAMX,kBACXnB,EAAE6B,EAAEE,QAAQX,YAAY,aAK5BnB,aAAaF,OAAO2B,aAAc,CAACzB,aAAa+B,OAAOC,WACvDP,aAAaE,GAAG3B,aAAa+B,OAAOC,SAAU,uBAAuB,SAASJ,OACtEK,WAAalC,EAAE6B,EAAEM,eAAeC,KAAK,cAEzC7B,sBADW,sCACiB2B,gBA4DhCG,CAFAZ,KAAOzB,EAAEyB,MAEkBN,kBAGtBM,KAAKE,KAAKrB,oCAAoCgC,SAxIrB,SAASb,KAAMN,sBACzCoB,6BAA+Bd,KAAKE,KAAKrB,+BAE7CL,aAAaF,OAAOwC,6BAA8B,CAACtC,aAAa+B,OAAOC,WACvEM,6BAA6BX,GACzB3B,aAAa+B,OAAOC,SACpB3B,sCACA,SAASuB,EAAGO,UAEJF,WAAalC,EAAE6B,EAAEM,eAAeC,KAAK,cAEzC7B,sBADW,wCACiB2B,gBAExBM,OAASxC,EAAE6B,EAAEE,QAAQU,QAAQnC,yCAEE,QAA/BkC,OAAOE,KAAK,qBAKZC,WAAaH,OAAOE,KAAK,aACzBE,UAAYJ,OAAOE,KAAK,WACxBG,uBAAyBpB,KAAKE,KAAKrB,4BAEvCuC,uBAAuBH,KAAK,mBAAoBC,YAE/BG,MAAbF,UACAC,uBAAuBH,KAAK,kBAAmBE,WAE/CC,uBAAuBE,WAAW,mBAGC,YAAnCP,OAAOE,KAAK,mBACZG,uBAAuBH,KAAK,uBAAuB,GAEnDG,uBAAuBE,WAAW,uBAKtC7C,KAAKmB,MAAMF,kBAEXiB,KAAKY,cAAcC,qBA+FvBC,CAA4BzB,KAAMN,kBArDnB,EAACM,KAAMN,0BACpBgC,YAAc1B,KAAKE,KAAKrB,iCACxBY,gBAAkBO,KAAKE,KAAKrB,sCAClC6C,YAAYvB,GAAG,QAASvB,MAAM+C,UAAS,KACT,KAAtBD,YAAYE,MACZpC,kBAAkBC,gBAAiBC,kBAEnCG,iBAAiBJ,gBAAiBC,oBAEvC,MACHD,gBAAgBU,GAAG,SAAS,KACxBuB,YAAYE,IAAI,IAChB/B,iBAAiBJ,gBAAiBC,kBAClCgC,YAAYG,YAyCZC,CAAe9B,KAAMN"}
\ No newline at end of file
diff --git a/calendar/amd/build/calendar.min.js b/calendar/amd/build/calendar.min.js
index eadb3e66efe..0817c63201c 100644
--- a/calendar/amd/build/calendar.min.js
+++ b/calendar/amd/build/calendar.min.js
@@ -1,2 +1,14 @@
-define ("core_calendar/calendar",["jquery","core/ajax","core/str","core/templates","core/notification","core/custom_interaction_events","core/modal_events","core/modal_factory","core_calendar/modal_event_form","core_calendar/summary_modal","core_calendar/repository","core_calendar/events","core_calendar/view_manager","core_calendar/crud","core_calendar/selectors","core/config"],function(a,b,c,d,f,g,h,i,j,k,l,m,n,o,p,q){var r={ROOT:"[data-region='calendar']",DAY:"[data-region='day']",NEW_EVENT_BUTTON:"[data-action='new-event-button']",DAY_CONTENT:"[data-region='day-content']",LOADING_ICON:".loading-icon",VIEW_DAY_LINK:"[data-action='view-day-link']",CALENDAR_MONTH_WRAPPER:".calendarwrapper",TODAY:".today",DAY_NUMBER_CIRCLE:".day-number-circle",DAY_NUMBER:".day-number"},s=function(b,c,e,g){var h=null,i=g.attr("data-day-timestamp");if(e){h=e.attr("data-day-timestamp")}if(!e||h!=i){d.render("core/loading",{}).then(function(a,b){g.find(r.DAY_CONTENT).addClass("hidden");d.appendNodeContents(g,a,b);if(e){e.find(r.DAY_CONTENT).addClass("hidden");d.appendNodeContents(e,a,b)}}).then(function(){return l.updateEventStartDay(c,i)}).then(function(){a("body").trigger(m.eventMoved,[c,e,g])}).always(function(){var a=g.find(r.LOADING_ICON);g.find(r.DAY_CONTENT).removeClass("hidden");d.replaceNode(a,"","");if(e){var b=e.find(r.LOADING_ICON);e.find(r.DAY_CONTENT).removeClass("hidden");d.replaceNode(b,"","")}}).fail(f.exception)}},t=function(b,c){var d=a("body");d.on(m.created,function(){n.reloadCurrentMonth(b)});d.on(m.deleted,function(){n.reloadCurrentMonth(b)});d.on(m.updated,function(){n.reloadCurrentMonth(b)});d.on(m.editActionEvent,function(a,b){window.location.assign(b)});d.on(m.moveEvent,s);d.on(m.eventMoved,function(){n.reloadCurrentMonth(b)});o.registerEditListeners(b,c)},u=function(b){var c=document.getElementById(p.fullCalendarView);b.on("click",r.VIEW_DAY_LINK,function(d){var e=a(d.target).closest(r.VIEW_DAY_LINK),g=e.data("year"),h=e.data("month"),i=e.data("day"),j=e.data("courseid"),k=e.data("categoryid"),l="?view=day&time="+e.data("timestamp");if(c){n.refreshDayContent(b,g,h,i,j,k,b,"core_calendar/calendar_day").then(function(){d.preventDefault();return n.updateUrl(l)}).fail(f.exception)}else{window.location.assign(q.wwwroot+"/calendar/view.php"+l)}});b.on("change",p.elements.courseSelector,function(){var c=a(this),d=c.val();n.reloadCurrentMonth(b,d,null).then(function(){return b.find(p.elements.courseSelector).val(d)}).fail(f.exception)});var d=o.registerEventFormModal(b),e=a(r.CALENDAR_MONTH_WRAPPER).data("context-id");t(b,d);if(e){b.on("click",r.DAY,function(g){var e=a(g.target),h="side-pre"===b.parents("aside").data("blockregion");if(!c&&h){var i=e.closest(r.DAY),j="?view=day&time="+i.data("day-timestamp");window.location.assign(q.wwwroot+"/calendar/view.php"+j)}else{var k=e.closest(r.VIEW_DAY_LINK).length;if(!k){var l=a(this).attr("data-new-event-timestamp");d.then(function(a){var b=e.closest(p.wrapper);a.setCourseId(b.data("courseid"));var c=b.data("categoryid");if("undefined"!=typeof c){a.setCategoryId(c)}a.setContextId(b.data("contextId"));a.setStartTime(l);a.show()}).fail(f.exception)}}g.preventDefault()})}};return{init:function init(b){b=a(b);n.init(b);u(b)}}});
-//# sourceMappingURL=calendar.min.js.map
+/**
+ * This module is the highest level module for the calendar. It is
+ * responsible for initialising all of the components required for
+ * the calendar to run. It also coordinates the interaction between
+ * components by listening for and responding to different events
+ * triggered within the calendar UI.
+ *
+ * @module core_calendar/calendar
+ * @copyright 2017 Simey Lameze
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/calendar",["jquery","core/ajax","core/str","core/templates","core/notification","core/custom_interaction_events","core/modal_events","core/modal_factory","core_calendar/modal_event_form","core_calendar/summary_modal","core_calendar/repository","core_calendar/events","core_calendar/view_manager","core_calendar/crud","core_calendar/selectors","core/config"],(function($,Ajax,Str,Templates,Notification,CustomEvents,ModalEvents,ModalFactory,ModalEventForm,SummaryModal,CalendarRepository,CalendarEvents,CalendarViewManager,CalendarCrud,CalendarSelectors,Config){var SELECTORS_DAY="[data-region='day']",SELECTORS_DAY_CONTENT="[data-region='day-content']",SELECTORS_LOADING_ICON=".loading-icon",SELECTORS_VIEW_DAY_LINK="[data-action='view-day-link']",SELECTORS_CALENDAR_MONTH_WRAPPER=".calendarwrapper",handleMoveEvent=function(e,eventId,originElement,destinationElement){var originTimestamp=null,destinationTimestamp=destinationElement.attr("data-day-timestamp");originElement&&(originTimestamp=originElement.attr("data-day-timestamp")),originElement&&originTimestamp==destinationTimestamp||Templates.render("core/loading",{}).then((function(html,js){destinationElement.find(SELECTORS_DAY_CONTENT).addClass("hidden"),Templates.appendNodeContents(destinationElement,html,js),originElement&&(originElement.find(SELECTORS_DAY_CONTENT).addClass("hidden"),Templates.appendNodeContents(originElement,html,js))})).then((function(){return CalendarRepository.updateEventStartDay(eventId,destinationTimestamp)})).then((function(){$("body").trigger(CalendarEvents.eventMoved,[eventId,originElement,destinationElement])})).always((function(){var destinationLoadingElement=destinationElement.find(SELECTORS_LOADING_ICON);if(destinationElement.find(SELECTORS_DAY_CONTENT).removeClass("hidden"),Templates.replaceNode(destinationLoadingElement,"",""),originElement){var originLoadingElement=originElement.find(SELECTORS_LOADING_ICON);originElement.find(SELECTORS_DAY_CONTENT).removeClass("hidden"),Templates.replaceNode(originLoadingElement,"","")}})).fail(Notification.exception)},registerEventListeners=function(root){const viewingFullCalendar=document.getElementById(CalendarSelectors.fullCalendarView);root.on("click",SELECTORS_VIEW_DAY_LINK,(function(e){var dayLink=$(e.target).closest(SELECTORS_VIEW_DAY_LINK),year=dayLink.data("year"),month=dayLink.data("month"),day=dayLink.data("day"),courseId=dayLink.data("courseid"),categoryId=dayLink.data("categoryid");const url="?view=day&time="+dayLink.data("timestamp");viewingFullCalendar?CalendarViewManager.refreshDayContent(root,year,month,day,courseId,categoryId,root,"core_calendar/calendar_day").then((function(){return e.preventDefault(),CalendarViewManager.updateUrl(url)})).fail(Notification.exception):window.location.assign(Config.wwwroot+"/calendar/view.php"+url)})),root.on("change",CalendarSelectors.elements.courseSelector,(function(){var courseId=$(this).val();CalendarViewManager.reloadCurrentMonth(root,courseId,null).then((function(){return root.find(CalendarSelectors.elements.courseSelector).val(courseId)})).fail(Notification.exception)}));var eventFormPromise=CalendarCrud.registerEventFormModal(root),contextId=$(SELECTORS_CALENDAR_MONTH_WRAPPER).data("context-id");!function(root,eventFormModalPromise){var body=$("body");body.on(CalendarEvents.created,(function(){CalendarViewManager.reloadCurrentMonth(root)})),body.on(CalendarEvents.deleted,(function(){CalendarViewManager.reloadCurrentMonth(root)})),body.on(CalendarEvents.updated,(function(){CalendarViewManager.reloadCurrentMonth(root)})),body.on(CalendarEvents.editActionEvent,(function(e,url){window.location.assign(url)})),body.on(CalendarEvents.moveEvent,handleMoveEvent),body.on(CalendarEvents.eventMoved,(function(){CalendarViewManager.reloadCurrentMonth(root)})),CalendarCrud.registerEditListeners(root,eventFormModalPromise)}(root,eventFormPromise),contextId&&root.on("click",SELECTORS_DAY,(function(e){var target=$(e.target);const displayingSmallBlockCalendar="side-pre"===root.parents("aside").data("blockregion");if(!viewingFullCalendar&&displayingSmallBlockCalendar){const url="?view=day&time="+target.closest(SELECTORS_DAY).data("day-timestamp");window.location.assign(Config.wwwroot+"/calendar/view.php"+url)}else{if(!target.closest(SELECTORS_VIEW_DAY_LINK).length){var startTime=$(this).attr("data-new-event-timestamp");eventFormPromise.then((function(modal){var wrapper=target.closest(CalendarSelectors.wrapper);modal.setCourseId(wrapper.data("courseid"));var categoryId=wrapper.data("categoryid");void 0!==categoryId&&modal.setCategoryId(categoryId),modal.setContextId(wrapper.data("contextId")),modal.setStartTime(startTime),modal.show()})).fail(Notification.exception)}}e.preventDefault()}))};return{init:function(root){root=$(root),CalendarViewManager.init(root),registerEventListeners(root)}}}));
+
+//# sourceMappingURL=calendar.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/calendar.min.js.map b/calendar/amd/build/calendar.min.js.map
index c923c58fa94..363129b3ed2 100644
--- a/calendar/amd/build/calendar.min.js.map
+++ b/calendar/amd/build/calendar.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/calendar.js"],"names":["define","$","Ajax","Str","Templates","Notification","CustomEvents","ModalEvents","ModalFactory","ModalEventForm","SummaryModal","CalendarRepository","CalendarEvents","CalendarViewManager","CalendarCrud","CalendarSelectors","Config","SELECTORS","ROOT","DAY","NEW_EVENT_BUTTON","DAY_CONTENT","LOADING_ICON","VIEW_DAY_LINK","CALENDAR_MONTH_WRAPPER","TODAY","DAY_NUMBER_CIRCLE","DAY_NUMBER","handleMoveEvent","e","eventId","originElement","destinationElement","originTimestamp","destinationTimestamp","attr","render","then","html","js","find","addClass","appendNodeContents","updateEventStartDay","trigger","eventMoved","always","destinationLoadingElement","removeClass","replaceNode","originLoadingElement","fail","exception","registerCalendarEventListeners","root","eventFormModalPromise","body","on","created","reloadCurrentMonth","deleted","updated","editActionEvent","url","window","location","assign","moveEvent","registerEditListeners","registerEventListeners","viewingFullCalendar","document","getElementById","fullCalendarView","dayLink","target","closest","year","data","month","day","courseId","categoryId","refreshDayContent","preventDefault","updateUrl","wwwroot","elements","courseSelector","selectElement","val","eventFormPromise","registerEventFormModal","contextId","displayingSmallBlockCalendar","parents","dateContainer","hasViewDayLink","length","startTime","modal","wrapper","setCourseId","setCategoryId","setContextId","setStartTime","show","init"],"mappings":"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","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 .\n\n/**\n * This module is the highest level module for the calendar. It is\n * responsible for initialising all of the components required for\n * the calendar to run. It also coordinates the interaction between\n * components by listening for and responding to different events\n * triggered within the calendar UI.\n *\n * @module core_calendar/calendar\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/str',\n 'core/templates',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/modal_events',\n 'core/modal_factory',\n 'core_calendar/modal_event_form',\n 'core_calendar/summary_modal',\n 'core_calendar/repository',\n 'core_calendar/events',\n 'core_calendar/view_manager',\n 'core_calendar/crud',\n 'core_calendar/selectors',\n 'core/config',\n ],\n function(\n $,\n Ajax,\n Str,\n Templates,\n Notification,\n CustomEvents,\n ModalEvents,\n ModalFactory,\n ModalEventForm,\n SummaryModal,\n CalendarRepository,\n CalendarEvents,\n CalendarViewManager,\n CalendarCrud,\n CalendarSelectors,\n Config,\n ) {\n\n var SELECTORS = {\n ROOT: \"[data-region='calendar']\",\n DAY: \"[data-region='day']\",\n NEW_EVENT_BUTTON: \"[data-action='new-event-button']\",\n DAY_CONTENT: \"[data-region='day-content']\",\n LOADING_ICON: '.loading-icon',\n VIEW_DAY_LINK: \"[data-action='view-day-link']\",\n CALENDAR_MONTH_WRAPPER: \".calendarwrapper\",\n TODAY: '.today',\n DAY_NUMBER_CIRCLE: '.day-number-circle',\n DAY_NUMBER: '.day-number'\n };\n\n /**\n * Handler for the drag and drop move event. Provides a loading indicator\n * while the request is sent to the server to update the event start date.\n *\n * Triggers a eventMoved calendar javascript event if the event was successfully\n * updated.\n *\n * @param {event} e The calendar move event\n * @param {int} eventId The event id being moved\n * @param {object|null} originElement The jQuery element for where the event is moving from\n * @param {object} destinationElement The jQuery element for where the event is moving to\n */\n var handleMoveEvent = function(e, eventId, originElement, destinationElement) {\n var originTimestamp = null;\n var destinationTimestamp = destinationElement.attr('data-day-timestamp');\n\n if (originElement) {\n originTimestamp = originElement.attr('data-day-timestamp');\n }\n\n // If the event has actually changed day.\n if (!originElement || originTimestamp != destinationTimestamp) {\n Templates.render('core/loading', {})\n .then(function(html, js) {\n // First we show some loading icons in each of the days being affected.\n destinationElement.find(SELECTORS.DAY_CONTENT).addClass('hidden');\n Templates.appendNodeContents(destinationElement, html, js);\n\n if (originElement) {\n originElement.find(SELECTORS.DAY_CONTENT).addClass('hidden');\n Templates.appendNodeContents(originElement, html, js);\n }\n return;\n })\n .then(function() {\n // Send a request to the server to make the change.\n return CalendarRepository.updateEventStartDay(eventId, destinationTimestamp);\n })\n .then(function() {\n // If the update was successful then broadcast an event letting the calendar\n // know that an event has been moved.\n $('body').trigger(CalendarEvents.eventMoved, [eventId, originElement, destinationElement]);\n return;\n })\n .always(function() {\n // Always remove the loading icons regardless of whether the update\n // request was successful or not.\n var destinationLoadingElement = destinationElement.find(SELECTORS.LOADING_ICON);\n destinationElement.find(SELECTORS.DAY_CONTENT).removeClass('hidden');\n Templates.replaceNode(destinationLoadingElement, '', '');\n\n if (originElement) {\n var originLoadingElement = originElement.find(SELECTORS.LOADING_ICON);\n originElement.find(SELECTORS.DAY_CONTENT).removeClass('hidden');\n Templates.replaceNode(originLoadingElement, '', '');\n }\n return;\n })\n .fail(Notification.exception);\n }\n };\n\n /**\n * Listen to and handle any calendar events fired by the calendar UI.\n *\n * @method registerCalendarEventListeners\n * @param {object} root The calendar root element\n * @param {object} eventFormModalPromise A promise reolved with the event form modal\n */\n var registerCalendarEventListeners = function(root, eventFormModalPromise) {\n var body = $('body');\n\n body.on(CalendarEvents.created, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n body.on(CalendarEvents.deleted, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n body.on(CalendarEvents.updated, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n body.on(CalendarEvents.editActionEvent, function(e, url) {\n // Action events needs to be edit directly on the course module.\n window.location.assign(url);\n });\n // Handle the event fired by the drag and drop code.\n body.on(CalendarEvents.moveEvent, handleMoveEvent);\n // When an event is successfully moved we should updated the UI.\n body.on(CalendarEvents.eventMoved, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n\n CalendarCrud.registerEditListeners(root, eventFormModalPromise);\n };\n\n /**\n * Register event listeners for the module.\n *\n * @param {object} root The calendar root element\n */\n var registerEventListeners = function(root) {\n const viewingFullCalendar = document.getElementById(CalendarSelectors.fullCalendarView);\n // Listen the click on the day link to render the day view.\n root.on('click', SELECTORS.VIEW_DAY_LINK, function(e) {\n var dayLink = $(e.target).closest(SELECTORS.VIEW_DAY_LINK);\n var year = dayLink.data('year'),\n month = dayLink.data('month'),\n day = dayLink.data('day'),\n courseId = dayLink.data('courseid'),\n categoryId = dayLink.data('categoryid');\n const url = '?view=day&time=' + dayLink.data('timestamp');\n if (viewingFullCalendar) {\n CalendarViewManager.refreshDayContent(root, year, month, day, courseId, categoryId, root,\n 'core_calendar/calendar_day').then(function() {\n e.preventDefault();\n return CalendarViewManager.updateUrl(url);\n }).fail(Notification.exception);\n } else {\n window.location.assign(Config.wwwroot + '/calendar/view.php' + url);\n }\n });\n\n root.on('change', CalendarSelectors.elements.courseSelector, function() {\n var selectElement = $(this);\n var courseId = selectElement.val();\n CalendarViewManager.reloadCurrentMonth(root, courseId, null)\n .then(function() {\n // We need to get the selector again because the content has changed.\n return root.find(CalendarSelectors.elements.courseSelector).val(courseId);\n })\n .fail(Notification.exception);\n });\n\n var eventFormPromise = CalendarCrud.registerEventFormModal(root),\n contextId = $(SELECTORS.CALENDAR_MONTH_WRAPPER).data('context-id');\n registerCalendarEventListeners(root, eventFormPromise);\n\n if (contextId) {\n // Bind click events to calendar days.\n root.on('click', SELECTORS.DAY, function(e) {\n var target = $(e.target);\n const displayingSmallBlockCalendar = root.parents('aside').data('blockregion') === 'side-pre';\n\n if (!viewingFullCalendar && displayingSmallBlockCalendar) {\n const dateContainer = target.closest(SELECTORS.DAY);\n const url = '?view=day&time=' + dateContainer.data('day-timestamp');\n window.location.assign(Config.wwwroot + '/calendar/view.php' + url);\n } else {\n const hasViewDayLink = target.closest(SELECTORS.VIEW_DAY_LINK).length;\n const shouldShowNewEventModal = !hasViewDayLink;\n if (shouldShowNewEventModal) {\n var startTime = $(this).attr('data-new-event-timestamp');\n eventFormPromise.then(function(modal) {\n var wrapper = target.closest(CalendarSelectors.wrapper);\n modal.setCourseId(wrapper.data('courseid'));\n\n var categoryId = wrapper.data('categoryid');\n if (typeof categoryId !== 'undefined') {\n modal.setCategoryId(categoryId);\n }\n\n modal.setContextId(wrapper.data('contextId'));\n modal.setStartTime(startTime);\n modal.show();\n return;\n }).fail(Notification.exception);\n }\n }\n e.preventDefault();\n });\n }\n };\n\n return {\n init: function(root) {\n root = $(root);\n CalendarViewManager.init(root);\n registerEventListeners(root);\n }\n };\n});\n"],"file":"calendar.min.js"}
\ No newline at end of file
+{"version":3,"file":"calendar.min.js","sources":["../src/calendar.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 .\n\n/**\n * This module is the highest level module for the calendar. It is\n * responsible for initialising all of the components required for\n * the calendar to run. It also coordinates the interaction between\n * components by listening for and responding to different events\n * triggered within the calendar UI.\n *\n * @module core_calendar/calendar\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/str',\n 'core/templates',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/modal_events',\n 'core/modal_factory',\n 'core_calendar/modal_event_form',\n 'core_calendar/summary_modal',\n 'core_calendar/repository',\n 'core_calendar/events',\n 'core_calendar/view_manager',\n 'core_calendar/crud',\n 'core_calendar/selectors',\n 'core/config',\n ],\n function(\n $,\n Ajax,\n Str,\n Templates,\n Notification,\n CustomEvents,\n ModalEvents,\n ModalFactory,\n ModalEventForm,\n SummaryModal,\n CalendarRepository,\n CalendarEvents,\n CalendarViewManager,\n CalendarCrud,\n CalendarSelectors,\n Config,\n ) {\n\n var SELECTORS = {\n ROOT: \"[data-region='calendar']\",\n DAY: \"[data-region='day']\",\n NEW_EVENT_BUTTON: \"[data-action='new-event-button']\",\n DAY_CONTENT: \"[data-region='day-content']\",\n LOADING_ICON: '.loading-icon',\n VIEW_DAY_LINK: \"[data-action='view-day-link']\",\n CALENDAR_MONTH_WRAPPER: \".calendarwrapper\",\n TODAY: '.today',\n DAY_NUMBER_CIRCLE: '.day-number-circle',\n DAY_NUMBER: '.day-number'\n };\n\n /**\n * Handler for the drag and drop move event. Provides a loading indicator\n * while the request is sent to the server to update the event start date.\n *\n * Triggers a eventMoved calendar javascript event if the event was successfully\n * updated.\n *\n * @param {event} e The calendar move event\n * @param {int} eventId The event id being moved\n * @param {object|null} originElement The jQuery element for where the event is moving from\n * @param {object} destinationElement The jQuery element for where the event is moving to\n */\n var handleMoveEvent = function(e, eventId, originElement, destinationElement) {\n var originTimestamp = null;\n var destinationTimestamp = destinationElement.attr('data-day-timestamp');\n\n if (originElement) {\n originTimestamp = originElement.attr('data-day-timestamp');\n }\n\n // If the event has actually changed day.\n if (!originElement || originTimestamp != destinationTimestamp) {\n Templates.render('core/loading', {})\n .then(function(html, js) {\n // First we show some loading icons in each of the days being affected.\n destinationElement.find(SELECTORS.DAY_CONTENT).addClass('hidden');\n Templates.appendNodeContents(destinationElement, html, js);\n\n if (originElement) {\n originElement.find(SELECTORS.DAY_CONTENT).addClass('hidden');\n Templates.appendNodeContents(originElement, html, js);\n }\n return;\n })\n .then(function() {\n // Send a request to the server to make the change.\n return CalendarRepository.updateEventStartDay(eventId, destinationTimestamp);\n })\n .then(function() {\n // If the update was successful then broadcast an event letting the calendar\n // know that an event has been moved.\n $('body').trigger(CalendarEvents.eventMoved, [eventId, originElement, destinationElement]);\n return;\n })\n .always(function() {\n // Always remove the loading icons regardless of whether the update\n // request was successful or not.\n var destinationLoadingElement = destinationElement.find(SELECTORS.LOADING_ICON);\n destinationElement.find(SELECTORS.DAY_CONTENT).removeClass('hidden');\n Templates.replaceNode(destinationLoadingElement, '', '');\n\n if (originElement) {\n var originLoadingElement = originElement.find(SELECTORS.LOADING_ICON);\n originElement.find(SELECTORS.DAY_CONTENT).removeClass('hidden');\n Templates.replaceNode(originLoadingElement, '', '');\n }\n return;\n })\n .fail(Notification.exception);\n }\n };\n\n /**\n * Listen to and handle any calendar events fired by the calendar UI.\n *\n * @method registerCalendarEventListeners\n * @param {object} root The calendar root element\n * @param {object} eventFormModalPromise A promise reolved with the event form modal\n */\n var registerCalendarEventListeners = function(root, eventFormModalPromise) {\n var body = $('body');\n\n body.on(CalendarEvents.created, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n body.on(CalendarEvents.deleted, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n body.on(CalendarEvents.updated, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n body.on(CalendarEvents.editActionEvent, function(e, url) {\n // Action events needs to be edit directly on the course module.\n window.location.assign(url);\n });\n // Handle the event fired by the drag and drop code.\n body.on(CalendarEvents.moveEvent, handleMoveEvent);\n // When an event is successfully moved we should updated the UI.\n body.on(CalendarEvents.eventMoved, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n\n CalendarCrud.registerEditListeners(root, eventFormModalPromise);\n };\n\n /**\n * Register event listeners for the module.\n *\n * @param {object} root The calendar root element\n */\n var registerEventListeners = function(root) {\n const viewingFullCalendar = document.getElementById(CalendarSelectors.fullCalendarView);\n // Listen the click on the day link to render the day view.\n root.on('click', SELECTORS.VIEW_DAY_LINK, function(e) {\n var dayLink = $(e.target).closest(SELECTORS.VIEW_DAY_LINK);\n var year = dayLink.data('year'),\n month = dayLink.data('month'),\n day = dayLink.data('day'),\n courseId = dayLink.data('courseid'),\n categoryId = dayLink.data('categoryid');\n const url = '?view=day&time=' + dayLink.data('timestamp');\n if (viewingFullCalendar) {\n CalendarViewManager.refreshDayContent(root, year, month, day, courseId, categoryId, root,\n 'core_calendar/calendar_day').then(function() {\n e.preventDefault();\n return CalendarViewManager.updateUrl(url);\n }).fail(Notification.exception);\n } else {\n window.location.assign(Config.wwwroot + '/calendar/view.php' + url);\n }\n });\n\n root.on('change', CalendarSelectors.elements.courseSelector, function() {\n var selectElement = $(this);\n var courseId = selectElement.val();\n CalendarViewManager.reloadCurrentMonth(root, courseId, null)\n .then(function() {\n // We need to get the selector again because the content has changed.\n return root.find(CalendarSelectors.elements.courseSelector).val(courseId);\n })\n .fail(Notification.exception);\n });\n\n var eventFormPromise = CalendarCrud.registerEventFormModal(root),\n contextId = $(SELECTORS.CALENDAR_MONTH_WRAPPER).data('context-id');\n registerCalendarEventListeners(root, eventFormPromise);\n\n if (contextId) {\n // Bind click events to calendar days.\n root.on('click', SELECTORS.DAY, function(e) {\n var target = $(e.target);\n const displayingSmallBlockCalendar = root.parents('aside').data('blockregion') === 'side-pre';\n\n if (!viewingFullCalendar && displayingSmallBlockCalendar) {\n const dateContainer = target.closest(SELECTORS.DAY);\n const url = '?view=day&time=' + dateContainer.data('day-timestamp');\n window.location.assign(Config.wwwroot + '/calendar/view.php' + url);\n } else {\n const hasViewDayLink = target.closest(SELECTORS.VIEW_DAY_LINK).length;\n const shouldShowNewEventModal = !hasViewDayLink;\n if (shouldShowNewEventModal) {\n var startTime = $(this).attr('data-new-event-timestamp');\n eventFormPromise.then(function(modal) {\n var wrapper = target.closest(CalendarSelectors.wrapper);\n modal.setCourseId(wrapper.data('courseid'));\n\n var categoryId = wrapper.data('categoryid');\n if (typeof categoryId !== 'undefined') {\n modal.setCategoryId(categoryId);\n }\n\n modal.setContextId(wrapper.data('contextId'));\n modal.setStartTime(startTime);\n modal.show();\n return;\n }).fail(Notification.exception);\n }\n }\n e.preventDefault();\n });\n }\n };\n\n return {\n init: function(root) {\n root = $(root);\n CalendarViewManager.init(root);\n registerEventListeners(root);\n }\n };\n});\n"],"names":["define","$","Ajax","Str","Templates","Notification","CustomEvents","ModalEvents","ModalFactory","ModalEventForm","SummaryModal","CalendarRepository","CalendarEvents","CalendarViewManager","CalendarCrud","CalendarSelectors","Config","SELECTORS","handleMoveEvent","e","eventId","originElement","destinationElement","originTimestamp","destinationTimestamp","attr","render","then","html","js","find","addClass","appendNodeContents","updateEventStartDay","trigger","eventMoved","always","destinationLoadingElement","removeClass","replaceNode","originLoadingElement","fail","exception","registerEventListeners","root","viewingFullCalendar","document","getElementById","fullCalendarView","on","dayLink","target","closest","year","data","month","day","courseId","categoryId","url","refreshDayContent","preventDefault","updateUrl","window","location","assign","wwwroot","elements","courseSelector","this","val","reloadCurrentMonth","eventFormPromise","registerEventFormModal","contextId","eventFormModalPromise","body","created","deleted","updated","editActionEvent","moveEvent","registerEditListeners","registerCalendarEventListeners","displayingSmallBlockCalendar","parents","length","startTime","modal","wrapper","setCourseId","setCategoryId","setContextId","setStartTime","show","init"],"mappings":"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"}
\ No newline at end of file
diff --git a/calendar/amd/build/calendar_filter.min.js b/calendar/amd/build/calendar_filter.min.js
index 9f72034c7d4..1fbb4cf23cf 100644
--- a/calendar/amd/build/calendar_filter.min.js
+++ b/calendar/amd/build/calendar_filter.min.js
@@ -1,2 +1,10 @@
-define ("core_calendar/calendar_filter",["jquery","core_calendar/selectors","core_calendar/events","core/str","core/templates"],function(a,b,c,d,e){var f=function(d){d.on("click",b.eventFilterItem,function(b){var c=a(b.currentTarget);g(c);b.preventDefault()});a("body").on(c.viewUpdated,function(){var c=d.find(b.eventFilterItem);c.each(function(b,c){c=a(c);if(c.data("eventtype-hidden")){var d=i(c);h(d)}})})},g=function(a){var b=i(a);b.hidden=!b.hidden;M.util.js_pending("core_calendar/calendar_filter:toggleFilter");return d.get_string("eventtype"+b.eventtype,"calendar").then(function(a){b.name=a;b.icon=!0;b.key="i/"+b.eventtype+"event";b.component="core";return b}).then(function(a){return e.render("core_calendar/event_filter_key",a)}).then(function(b,c){return e.replaceNode(a,b,c)}).then(function(){h(b);M.util.js_complete("core_calendar/calendar_filter:toggleFilter")})},h=function(b){M.util.js_pending("month-mini-filterChanged");a("body").trigger(c.filterChanged,{type:b.eventtype,hidden:b.hidden});M.util.js_complete("month-mini-filterChanged")},i=function(a){return{eventtype:a.data("eventtype"),hidden:a.data("eventtype-hidden")}};return{init:function init(b){b=a(b);f(b)}}});
-//# sourceMappingURL=calendar_filter.min.js.map
+/**
+ * This module is responsible for the calendar filter.
+ *
+ * @module core_calendar/calendar_filter
+ * @copyright 2017 Andrew Nicols
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/calendar_filter",["jquery","core_calendar/selectors","core_calendar/events","core/str","core/templates"],(function($,CalendarSelectors,CalendarEvents,Str,Templates){var toggleFilter=function(target){var data=getFilterData(target);return data.hidden=!data.hidden,M.util.js_pending("core_calendar/calendar_filter:toggleFilter"),Str.get_string("eventtype"+data.eventtype,"calendar").then((function(nameStr){return data.name=nameStr,data.icon=!0,data.key="i/"+data.eventtype+"event",data.component="core",data})).then((function(context){return Templates.render("core_calendar/event_filter_key",context)})).then((function(html,js){return Templates.replaceNode(target,html,js)})).then((function(){fireFilterChangedEvent(data),M.util.js_complete("core_calendar/calendar_filter:toggleFilter")}))},fireFilterChangedEvent=function(data){M.util.js_pending("month-mini-filterChanged"),$("body").trigger(CalendarEvents.filterChanged,{type:data.eventtype,hidden:data.hidden}),M.util.js_complete("month-mini-filterChanged")},getFilterData=function(target){return{eventtype:target.data("eventtype"),hidden:target.data("eventtype-hidden")}};return{init:function(root){!function(root){root.on("click",CalendarSelectors.eventFilterItem,(function(e){var target=$(e.currentTarget);toggleFilter(target),e.preventDefault()})),$("body").on(CalendarEvents.viewUpdated,(function(){root.find(CalendarSelectors.eventFilterItem).each((function(i,filter){if((filter=$(filter)).data("eventtype-hidden")){var data=getFilterData(filter);fireFilterChangedEvent(data)}}))}))}(root=$(root))}}}));
+
+//# sourceMappingURL=calendar_filter.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/calendar_filter.min.js.map b/calendar/amd/build/calendar_filter.min.js.map
index 1962b1a27e3..14d1fe3be3c 100644
--- a/calendar/amd/build/calendar_filter.min.js.map
+++ b/calendar/amd/build/calendar_filter.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/calendar_filter.js"],"names":["define","$","CalendarSelectors","CalendarEvents","Str","Templates","registerEventListeners","root","on","eventFilterItem","e","target","currentTarget","toggleFilter","preventDefault","viewUpdated","filters","find","each","i","filter","data","getFilterData","fireFilterChangedEvent","hidden","M","util","js_pending","get_string","eventtype","then","nameStr","name","icon","key","component","context","render","html","js","replaceNode","js_complete","trigger","filterChanged","type","init"],"mappings":"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","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 .\n\n/**\n * This module is responsible for the calendar filter.\n *\n * @module core_calendar/calendar_filter\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core_calendar/selectors',\n 'core_calendar/events',\n 'core/str',\n 'core/templates',\n],\nfunction(\n $,\n CalendarSelectors,\n CalendarEvents,\n Str,\n Templates\n) {\n\n var registerEventListeners = function(root) {\n root.on('click', CalendarSelectors.eventFilterItem, function(e) {\n var target = $(e.currentTarget);\n\n toggleFilter(target);\n\n e.preventDefault();\n });\n\n $('body').on(CalendarEvents.viewUpdated, function() {\n var filters = root.find(CalendarSelectors.eventFilterItem);\n\n filters.each(function(i, filter) {\n filter = $(filter);\n if (filter.data('eventtype-hidden')) {\n var data = getFilterData(filter);\n fireFilterChangedEvent(data);\n }\n });\n });\n };\n\n var toggleFilter = function(target) {\n var data = getFilterData(target);\n\n // Toggle the hidden. We need to render the template before we change the value.\n data.hidden = !data.hidden;\n\n M.util.js_pending(\"core_calendar/calendar_filter:toggleFilter\");\n return Str.get_string('eventtype' + data.eventtype, 'calendar')\n .then(function(nameStr) {\n data.name = nameStr;\n data.icon = true;\n data.key = 'i/' + data.eventtype + 'event';\n data.component = 'core';\n\n return data;\n })\n .then(function(context) {\n return Templates.render('core_calendar/event_filter_key', context);\n })\n .then(function(html, js) {\n return Templates.replaceNode(target, html, js);\n })\n .then(function() {\n fireFilterChangedEvent(data);\n M.util.js_complete(\"core_calendar/calendar_filter:toggleFilter\");\n return;\n });\n };\n\n /**\n * Fire the filterChanged event for the specified data.\n *\n * @param {object} data The data to include\n */\n var fireFilterChangedEvent = function(data) {\n M.util.js_pending(\"month-mini-filterChanged\");\n $('body').trigger(CalendarEvents.filterChanged, {\n type: data.eventtype,\n hidden: data.hidden,\n });\n M.util.js_complete(\"month-mini-filterChanged\");\n };\n\n /**\n * Get the filter data for the specified target.\n *\n * @param {jQuery} target The target node\n * @return {Object}\n */\n var getFilterData = function(target) {\n return {\n eventtype: target.data('eventtype'),\n hidden: target.data('eventtype-hidden'),\n };\n };\n\n return {\n init: function(root) {\n root = $(root);\n\n registerEventListeners(root);\n }\n };\n});\n"],"file":"calendar_filter.min.js"}
\ No newline at end of file
+{"version":3,"file":"calendar_filter.min.js","sources":["../src/calendar_filter.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 .\n\n/**\n * This module is responsible for the calendar filter.\n *\n * @module core_calendar/calendar_filter\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core_calendar/selectors',\n 'core_calendar/events',\n 'core/str',\n 'core/templates',\n],\nfunction(\n $,\n CalendarSelectors,\n CalendarEvents,\n Str,\n Templates\n) {\n\n var registerEventListeners = function(root) {\n root.on('click', CalendarSelectors.eventFilterItem, function(e) {\n var target = $(e.currentTarget);\n\n toggleFilter(target);\n\n e.preventDefault();\n });\n\n $('body').on(CalendarEvents.viewUpdated, function() {\n var filters = root.find(CalendarSelectors.eventFilterItem);\n\n filters.each(function(i, filter) {\n filter = $(filter);\n if (filter.data('eventtype-hidden')) {\n var data = getFilterData(filter);\n fireFilterChangedEvent(data);\n }\n });\n });\n };\n\n var toggleFilter = function(target) {\n var data = getFilterData(target);\n\n // Toggle the hidden. We need to render the template before we change the value.\n data.hidden = !data.hidden;\n\n M.util.js_pending(\"core_calendar/calendar_filter:toggleFilter\");\n return Str.get_string('eventtype' + data.eventtype, 'calendar')\n .then(function(nameStr) {\n data.name = nameStr;\n data.icon = true;\n data.key = 'i/' + data.eventtype + 'event';\n data.component = 'core';\n\n return data;\n })\n .then(function(context) {\n return Templates.render('core_calendar/event_filter_key', context);\n })\n .then(function(html, js) {\n return Templates.replaceNode(target, html, js);\n })\n .then(function() {\n fireFilterChangedEvent(data);\n M.util.js_complete(\"core_calendar/calendar_filter:toggleFilter\");\n return;\n });\n };\n\n /**\n * Fire the filterChanged event for the specified data.\n *\n * @param {object} data The data to include\n */\n var fireFilterChangedEvent = function(data) {\n M.util.js_pending(\"month-mini-filterChanged\");\n $('body').trigger(CalendarEvents.filterChanged, {\n type: data.eventtype,\n hidden: data.hidden,\n });\n M.util.js_complete(\"month-mini-filterChanged\");\n };\n\n /**\n * Get the filter data for the specified target.\n *\n * @param {jQuery} target The target node\n * @return {Object}\n */\n var getFilterData = function(target) {\n return {\n eventtype: target.data('eventtype'),\n hidden: target.data('eventtype-hidden'),\n };\n };\n\n return {\n init: function(root) {\n root = $(root);\n\n registerEventListeners(root);\n }\n };\n});\n"],"names":["define","$","CalendarSelectors","CalendarEvents","Str","Templates","toggleFilter","target","data","getFilterData","hidden","M","util","js_pending","get_string","eventtype","then","nameStr","name","icon","key","component","context","render","html","js","replaceNode","fireFilterChangedEvent","js_complete","trigger","filterChanged","type","init","root","on","eventFilterItem","e","currentTarget","preventDefault","viewUpdated","find","each","i","filter","registerEventListeners"],"mappings":";;;;;;;AAsBAA,uCAAO,CACH,SACA,0BACA,uBACA,WACA,mBAEJ,SACIC,EACAC,kBACAC,eACAC,IACAC,eAyBIC,aAAe,SAASC,YACpBC,KAAOC,cAAcF,eAGzBC,KAAKE,QAAUF,KAAKE,OAEpBC,EAAEC,KAAKC,WAAW,8CACXT,IAAIU,WAAW,YAAcN,KAAKO,UAAW,YACnDC,MAAK,SAASC,gBACXT,KAAKU,KAAOD,QACZT,KAAKW,MAAO,EACZX,KAAKY,IAAM,KAAOZ,KAAKO,UAAY,QACnCP,KAAKa,UAAY,OAEVb,QAEVQ,MAAK,SAASM,gBACJjB,UAAUkB,OAAO,iCAAkCD,YAE7DN,MAAK,SAASQ,KAAMC,WACVpB,UAAUqB,YAAYnB,OAAQiB,KAAMC,OAE9CT,MAAK,WACFW,uBAAuBnB,MACvBG,EAAEC,KAAKgB,YAAY,kDAUvBD,uBAAyB,SAASnB,MAClCG,EAAEC,KAAKC,WAAW,4BAClBZ,EAAE,QAAQ4B,QAAQ1B,eAAe2B,cAAe,CAC5CC,KAAMvB,KAAKO,UACXL,OAAQF,KAAKE,SAEjBC,EAAEC,KAAKgB,YAAY,6BASnBnB,cAAgB,SAASF,cAClB,CACHQ,UAAWR,OAAOC,KAAK,aACvBE,OAAQH,OAAOC,KAAK,4BAIrB,CACHwB,KAAM,SAASC,OA/EU,SAASA,MAClCA,KAAKC,GAAG,QAAShC,kBAAkBiC,iBAAiB,SAASC,OACrD7B,OAASN,EAAEmC,EAAEC,eAEjB/B,aAAaC,QAEb6B,EAAEE,oBAGNrC,EAAE,QAAQiC,GAAG/B,eAAeoC,aAAa,WACvBN,KAAKO,KAAKtC,kBAAkBiC,iBAElCM,MAAK,SAASC,EAAGC,YACrBA,OAAS1C,EAAE0C,SACAnC,KAAK,oBAAqB,KAC7BA,KAAOC,cAAckC,QACzBhB,uBAAuBnB,aAkE/BoC,CAFAX,KAAOhC,EAAEgC"}
\ No newline at end of file
diff --git a/calendar/amd/build/calendar_mini.min.js b/calendar/amd/build/calendar_mini.min.js
index 7f9d3ec2f12..942f5d356ea 100644
--- a/calendar/amd/build/calendar_mini.min.js
+++ b/calendar/amd/build/calendar_mini.min.js
@@ -1,2 +1,14 @@
-define ("core_calendar/calendar_mini",["jquery","core_calendar/selectors","core_calendar/events","core_calendar/view_manager"],function(a,b,c,d){var e=function(b){var d=a("body"),e="."+b.attr("id");d.on(c.created+e,b,f);d.on(c.deleted+e,b,f);d.on(c.updated+e,b,f);d.on(c.eventMoved+e,b,f)},f=function(b){var e=b.data,f=a("body"),g="."+e.attr("id");if(e.is(":visible")){d.reloadCurrentMonth(e)}else{f.off(c.created+g);f.off(c.deleted+g);f.off(c.updated+g);f.off(c.eventMoved+g)}},g=function(f){a("body").on(c.filterChanged,function(a,c){var d=f.find(b.eventType[c.type]);d.toggleClass("calendar_event_"+c.type,!c.hidden)});var g="."+f.attr("id");a("body").on("change"+g,b.elements.courseSelector,function(){if(f.is(":visible")){var b=a(this),c=b.val();d.reloadCurrentMonth(f,c,null)}else{a("body").off("change"+g)}})};return{init:function init(b,c){b=a(b);d.init(b);g(b);e(b);if(c){d.reloadCurrentMonth(b)}}}});
-//# sourceMappingURL=calendar_mini.min.js.map
+/**
+ * This module is the highest level module for the calendar. It is
+ * responsible for initialising all of the components required for
+ * the calendar to run. It also coordinates the interaction between
+ * components by listening for and responding to different events
+ * triggered within the calendar UI.
+ *
+ * @module core_calendar/calendar_mini
+ * @copyright 2017 Andrew Nicols
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/calendar_mini",["jquery","core_calendar/selectors","core_calendar/events","core_calendar/view_manager"],(function($,CalendarSelectors,CalendarEvents,CalendarViewManager){var reloadMonth=function(e){var root=e.data,body=$("body"),namespace="."+root.attr("id");root.is(":visible")?CalendarViewManager.reloadCurrentMonth(root):(body.off(CalendarEvents.created+namespace),body.off(CalendarEvents.deleted+namespace),body.off(CalendarEvents.updated+namespace),body.off(CalendarEvents.eventMoved+namespace))};return{init:function(root,loadOnInit){root=$(root),CalendarViewManager.init(root),function(root){$("body").on(CalendarEvents.filterChanged,(function(e,data){root.find(CalendarSelectors.eventType[data.type]).toggleClass("calendar_event_"+data.type,!data.hidden)}));var namespace="."+root.attr("id");$("body").on("change"+namespace,CalendarSelectors.elements.courseSelector,(function(){if(root.is(":visible")){var courseId=$(this).val();CalendarViewManager.reloadCurrentMonth(root,courseId,null)}else $("body").off("change"+namespace)}))}(root),function(root){var body=$("body"),namespace="."+root.attr("id");body.on(CalendarEvents.created+namespace,root,reloadMonth),body.on(CalendarEvents.deleted+namespace,root,reloadMonth),body.on(CalendarEvents.updated+namespace,root,reloadMonth),body.on(CalendarEvents.eventMoved+namespace,root,reloadMonth)}(root),loadOnInit&&CalendarViewManager.reloadCurrentMonth(root)}}}));
+
+//# sourceMappingURL=calendar_mini.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/calendar_mini.min.js.map b/calendar/amd/build/calendar_mini.min.js.map
index 979529eb1b7..6aa3420722f 100644
--- a/calendar/amd/build/calendar_mini.min.js.map
+++ b/calendar/amd/build/calendar_mini.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/calendar_mini.js"],"names":["define","$","CalendarSelectors","CalendarEvents","CalendarViewManager","registerCalendarEventListeners","root","body","namespace","attr","on","created","reloadMonth","deleted","updated","eventMoved","e","data","is","reloadCurrentMonth","off","registerEventListeners","filterChanged","daysWithEvent","find","eventType","type","toggleClass","hidden","elements","courseSelector","selectElement","courseId","val","init","loadOnInit"],"mappings":"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","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 .\n\n/**\n * This module is the highest level module for the calendar. It is\n * responsible for initialising all of the components required for\n * the calendar to run. It also coordinates the interaction between\n * components by listening for and responding to different events\n * triggered within the calendar UI.\n *\n * @module core_calendar/calendar_mini\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core_calendar/selectors',\n 'core_calendar/events',\n 'core_calendar/view_manager',\n],\nfunction(\n $,\n CalendarSelectors,\n CalendarEvents,\n CalendarViewManager\n) {\n\n /**\n * Listen to and handle any calendar events fired by the calendar UI.\n *\n * @method registerCalendarEventListeners\n * @param {object} root The calendar root element\n */\n var registerCalendarEventListeners = function(root) {\n var body = $('body');\n var namespace = '.' + root.attr('id');\n\n body.on(CalendarEvents.created + namespace, root, reloadMonth);\n body.on(CalendarEvents.deleted + namespace, root, reloadMonth);\n body.on(CalendarEvents.updated + namespace, root, reloadMonth);\n body.on(CalendarEvents.eventMoved + namespace, root, reloadMonth);\n };\n\n /**\n * Reload the month view in this month.\n *\n * @param {EventFacade} e\n */\n var reloadMonth = function(e) {\n var root = e.data;\n var body = $('body');\n var namespace = '.' + root.attr('id');\n\n if (root.is(':visible')) {\n CalendarViewManager.reloadCurrentMonth(root);\n } else {\n // The root has been removed.\n // Remove all events in the namespace.\n body.off(CalendarEvents.created + namespace);\n body.off(CalendarEvents.deleted + namespace);\n body.off(CalendarEvents.updated + namespace);\n body.off(CalendarEvents.eventMoved + namespace);\n }\n };\n\n var registerEventListeners = function(root) {\n $('body').on(CalendarEvents.filterChanged, function(e, data) {\n var daysWithEvent = root.find(CalendarSelectors.eventType[data.type]);\n\n daysWithEvent.toggleClass('calendar_event_' + data.type, !data.hidden);\n });\n\n var namespace = '.' + root.attr('id');\n $('body').on('change' + namespace, CalendarSelectors.elements.courseSelector, function() {\n if (root.is(':visible')) {\n var selectElement = $(this);\n var courseId = selectElement.val();\n var categoryId = null;\n\n CalendarViewManager.reloadCurrentMonth(root, courseId, categoryId);\n } else {\n $('body').off('change' + namespace);\n }\n });\n\n };\n\n return {\n init: function(root, loadOnInit) {\n root = $(root);\n\n CalendarViewManager.init(root);\n registerEventListeners(root);\n registerCalendarEventListeners(root);\n\n if (loadOnInit) {\n // The calendar hasn't yet loaded it's events so we\n // should load them as soon as we've initialised.\n CalendarViewManager.reloadCurrentMonth(root);\n }\n\n }\n };\n});\n"],"file":"calendar_mini.min.js"}
\ No newline at end of file
+{"version":3,"file":"calendar_mini.min.js","sources":["../src/calendar_mini.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 .\n\n/**\n * This module is the highest level module for the calendar. It is\n * responsible for initialising all of the components required for\n * the calendar to run. It also coordinates the interaction between\n * components by listening for and responding to different events\n * triggered within the calendar UI.\n *\n * @module core_calendar/calendar_mini\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core_calendar/selectors',\n 'core_calendar/events',\n 'core_calendar/view_manager',\n],\nfunction(\n $,\n CalendarSelectors,\n CalendarEvents,\n CalendarViewManager\n) {\n\n /**\n * Listen to and handle any calendar events fired by the calendar UI.\n *\n * @method registerCalendarEventListeners\n * @param {object} root The calendar root element\n */\n var registerCalendarEventListeners = function(root) {\n var body = $('body');\n var namespace = '.' + root.attr('id');\n\n body.on(CalendarEvents.created + namespace, root, reloadMonth);\n body.on(CalendarEvents.deleted + namespace, root, reloadMonth);\n body.on(CalendarEvents.updated + namespace, root, reloadMonth);\n body.on(CalendarEvents.eventMoved + namespace, root, reloadMonth);\n };\n\n /**\n * Reload the month view in this month.\n *\n * @param {EventFacade} e\n */\n var reloadMonth = function(e) {\n var root = e.data;\n var body = $('body');\n var namespace = '.' + root.attr('id');\n\n if (root.is(':visible')) {\n CalendarViewManager.reloadCurrentMonth(root);\n } else {\n // The root has been removed.\n // Remove all events in the namespace.\n body.off(CalendarEvents.created + namespace);\n body.off(CalendarEvents.deleted + namespace);\n body.off(CalendarEvents.updated + namespace);\n body.off(CalendarEvents.eventMoved + namespace);\n }\n };\n\n var registerEventListeners = function(root) {\n $('body').on(CalendarEvents.filterChanged, function(e, data) {\n var daysWithEvent = root.find(CalendarSelectors.eventType[data.type]);\n\n daysWithEvent.toggleClass('calendar_event_' + data.type, !data.hidden);\n });\n\n var namespace = '.' + root.attr('id');\n $('body').on('change' + namespace, CalendarSelectors.elements.courseSelector, function() {\n if (root.is(':visible')) {\n var selectElement = $(this);\n var courseId = selectElement.val();\n var categoryId = null;\n\n CalendarViewManager.reloadCurrentMonth(root, courseId, categoryId);\n } else {\n $('body').off('change' + namespace);\n }\n });\n\n };\n\n return {\n init: function(root, loadOnInit) {\n root = $(root);\n\n CalendarViewManager.init(root);\n registerEventListeners(root);\n registerCalendarEventListeners(root);\n\n if (loadOnInit) {\n // The calendar hasn't yet loaded it's events so we\n // should load them as soon as we've initialised.\n CalendarViewManager.reloadCurrentMonth(root);\n }\n\n }\n };\n});\n"],"names":["define","$","CalendarSelectors","CalendarEvents","CalendarViewManager","reloadMonth","e","root","data","body","namespace","attr","is","reloadCurrentMonth","off","created","deleted","updated","eventMoved","init","loadOnInit","on","filterChanged","find","eventType","type","toggleClass","hidden","elements","courseSelector","courseId","this","val","registerEventListeners","registerCalendarEventListeners"],"mappings":";;;;;;;;;;;AA0BAA,qCAAO,CACH,SACA,0BACA,uBACA,+BAEJ,SACIC,EACAC,kBACAC,eACAC,yBAwBIC,YAAc,SAASC,OACnBC,KAAOD,EAAEE,KACTC,KAAOR,EAAE,QACTS,UAAY,IAAMH,KAAKI,KAAK,MAE5BJ,KAAKK,GAAG,YACRR,oBAAoBS,mBAAmBN,OAIvCE,KAAKK,IAAIX,eAAeY,QAAUL,WAClCD,KAAKK,IAAIX,eAAea,QAAUN,WAClCD,KAAKK,IAAIX,eAAec,QAAUP,WAClCD,KAAKK,IAAIX,eAAee,WAAaR,mBA0BtC,CACHS,KAAM,SAASZ,KAAMa,YACjBb,KAAON,EAAEM,MAETH,oBAAoBe,KAAKZ,MA1BJ,SAASA,MAClCN,EAAE,QAAQoB,GAAGlB,eAAemB,eAAe,SAAShB,EAAGE,MAC/BD,KAAKgB,KAAKrB,kBAAkBsB,UAAUhB,KAAKiB,OAEjDC,YAAY,kBAAoBlB,KAAKiB,MAAOjB,KAAKmB,eAG/DjB,UAAY,IAAMH,KAAKI,KAAK,MAChCV,EAAE,QAAQoB,GAAG,SAAWX,UAAWR,kBAAkB0B,SAASC,gBAAgB,cACtEtB,KAAKK,GAAG,YAAa,KAEjBkB,SADgB7B,EAAE8B,MACOC,MAG7B5B,oBAAoBS,mBAAmBN,KAAMuB,SAF5B,WAIjB7B,EAAE,QAAQa,IAAI,SAAWJ,cAW7BuB,CAAuB1B,MA3DM,SAASA,UACtCE,KAAOR,EAAE,QACTS,UAAY,IAAMH,KAAKI,KAAK,MAEhCF,KAAKY,GAAGlB,eAAeY,QAAUL,UAAWH,KAAMF,aAClDI,KAAKY,GAAGlB,eAAea,QAAUN,UAAWH,KAAMF,aAClDI,KAAKY,GAAGlB,eAAec,QAAUP,UAAWH,KAAMF,aAClDI,KAAKY,GAAGlB,eAAee,WAAaR,UAAWH,KAAMF,aAqDjD6B,CAA+B3B,MAE3Ba,YAGAhB,oBAAoBS,mBAAmBN"}
\ No newline at end of file
diff --git a/calendar/amd/build/calendar_threemonth.min.js b/calendar/amd/build/calendar_threemonth.min.js
index 17e1186eb38..93cae7033aa 100644
--- a/calendar/amd/build/calendar_threemonth.min.js
+++ b/calendar/amd/build/calendar_threemonth.min.js
@@ -1,2 +1,13 @@
-define ("core_calendar/calendar_threemonth",["jquery","core/notification","core_calendar/selectors","core_calendar/events","core/templates","core_calendar/view_manager"],function(a,b,c,d,e,f){var g=function(g){var h=a("body");h.on([d.monthChanged,d.dayChanged].join(" "),function(a,c,d,e,f){g.queue(function(g){return i(a,c,d,e,f).then(function(){return g()}).fail(b.exception)})});var i=function(b,d,e,h,i){var j=g.find("[data-year=\""+d+"\"][data-month=\""+e+"\"]"),k=j.closest(c.calendarPeriods.month),l=g.find(c.calendarPeriods.month),m=a(l[0]),n=a(l[2]),o=a("");o.attr("data-template","core_calendar/threemonth_month");o.attr("data-includenavigation",!1);o.attr("data-mini",!0);var p=a("
");p.hide();p.append(o);var q,r,s;if(k.is(m)){p.insertBefore(m);q=m.data("previousYear");r=m.data("previousMonth");s=n}else if(k.is(n)){p.insertAfter(n);q=n.data("nextYear");r=n.data("nextMonth");s=m}else{return a.Deferred().resolve()}return f.refreshMonthContent(o,q,r,h,i,o).then(function(){var b=a.Deferred(),c=a.Deferred();s.slideUp("fast",function(){a(this).remove();b.resolve()});p.slideDown("fast",function(){c.resolve()});return a.when(b,c)})};g.on("click",c.links.miniDayLink,function(b){var d=a(b.target),e=d.data("year"),g=d.data("month"),h=d.text(),i=d.data("courseid"),j=d.data("categoryid"),k=a("body").find(c.calendarMain);f.refreshDayContent(k,e,g,h,i,j,k.find("[id^=\"calendar-\"][data-template^=\"core_calendar/\"]"),"core_calendar/calendar_day");b.preventDefault();f.updateUrl("?view=day")})};return{init:function init(b){b=a(b);g(b)}}});
-//# sourceMappingURL=calendar_threemonth.min.js.map
+/**
+ * This module handles display of multiple mini calendars in a view, and
+ * movement through them.
+ *
+ * @deprecated since 4.0 MDL-72810.
+ * @todo MDL-73117 This will be deleted in Moodle 4.4.
+ * @module core_calendar/calendar_threemonth
+ * @copyright 2017 Andrew Nicols
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/calendar_threemonth",["jquery","core/notification","core_calendar/selectors","core_calendar/events","core/templates","core_calendar/view_manager"],(function($,Notification,CalendarSelectors,CalendarEvents,Templates,CalendarViewManager){return{init:function(root){!function(root){$("body").on([CalendarEvents.monthChanged,CalendarEvents.dayChanged].join(" "),(function(e,year,month,courseId,categoryId){root.queue((function(next){return processRequest(e,year,month,courseId,categoryId).then((function(){return next()})).fail(Notification.exception)}))}));var processRequest=function(e,year,month,courseId,categoryId){var newParent=root.find('[data-year="'+year+'"][data-month="'+month+'"]').closest(CalendarSelectors.calendarPeriods.month),allMonths=root.find(CalendarSelectors.calendarPeriods.month),previousMonth=$(allMonths[0]),nextMonth=$(allMonths[2]),placeHolder=$("");placeHolder.attr("data-template","core_calendar/threemonth_month"),placeHolder.attr("data-includenavigation",!1),placeHolder.attr("data-mini",!0);var requestYear,requestMonth,oldMonth,placeHolderContainer=$("
");if(placeHolderContainer.hide(),placeHolderContainer.append(placeHolder),newParent.is(previousMonth))placeHolderContainer.insertBefore(previousMonth),requestYear=previousMonth.data("previousYear"),requestMonth=previousMonth.data("previousMonth"),oldMonth=nextMonth;else{if(!newParent.is(nextMonth))return $.Deferred().resolve();placeHolderContainer.insertAfter(nextMonth),requestYear=nextMonth.data("nextYear"),requestMonth=nextMonth.data("nextMonth"),oldMonth=previousMonth}return CalendarViewManager.refreshMonthContent(placeHolder,requestYear,requestMonth,courseId,categoryId,placeHolder).then((function(){var slideUpPromise=$.Deferred(),slideDownPromise=$.Deferred();return oldMonth.slideUp("fast",(function(){$(this).remove(),slideUpPromise.resolve()})),placeHolderContainer.slideDown("fast",(function(){slideDownPromise.resolve()})),$.when(slideUpPromise,slideDownPromise)}))};root.on("click",CalendarSelectors.links.miniDayLink,(function(e){var miniDayLink=$(e.target),year=miniDayLink.data("year"),month=miniDayLink.data("month"),day=miniDayLink.text(),courseId=miniDayLink.data("courseid"),categoryId=miniDayLink.data("categoryid"),calendarRoot=$("body").find(CalendarSelectors.calendarMain);CalendarViewManager.refreshDayContent(calendarRoot,year,month,day,courseId,categoryId,calendarRoot.find('[id^="calendar-"][data-template^="core_calendar/"]'),"core_calendar/calendar_day"),e.preventDefault(),CalendarViewManager.updateUrl("?view=day")}))}(root=$(root))}}}));
+
+//# sourceMappingURL=calendar_threemonth.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/calendar_threemonth.min.js.map b/calendar/amd/build/calendar_threemonth.min.js.map
index ba3216ebda7..fc4a2155b07 100644
--- a/calendar/amd/build/calendar_threemonth.min.js.map
+++ b/calendar/amd/build/calendar_threemonth.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/calendar_threemonth.js"],"names":["define","$","Notification","CalendarSelectors","CalendarEvents","Templates","CalendarViewManager","registerCalendarEventListeners","root","body","on","monthChanged","dayChanged","join","e","year","month","courseId","categoryId","queue","next","processRequest","then","fail","exception","newCurrentMonth","find","newParent","closest","calendarPeriods","allMonths","previousMonth","nextMonth","placeHolder","attr","placeHolderContainer","hide","append","requestYear","requestMonth","oldMonth","is","insertBefore","data","insertAfter","Deferred","resolve","refreshMonthContent","slideUpPromise","slideDownPromise","slideUp","remove","slideDown","when","links","miniDayLink","target","day","text","calendarRoot","calendarMain","refreshDayContent","preventDefault","updateUrl","init"],"mappings":"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","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 .\n\n/**\n * This module handles display of multiple mini calendars in a view, and\n * movement through them.\n *\n * @deprecated since 4.0 MDL-72810.\n * @todo MDL-73117 This will be deleted in Moodle 4.4.\n * @module core_calendar/calendar_threemonth\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/notification',\n 'core_calendar/selectors',\n 'core_calendar/events',\n 'core/templates',\n 'core_calendar/view_manager',\n],\nfunction(\n $,\n Notification,\n CalendarSelectors,\n CalendarEvents,\n Templates,\n CalendarViewManager\n) {\n\n /**\n * Listen to and handle any calendar events fired by the calendar UI.\n *\n * @method registerCalendarEventListeners\n * @param {object} root The calendar root element\n */\n var registerCalendarEventListeners = function(root) {\n var body = $('body');\n body.on([CalendarEvents.monthChanged, CalendarEvents.dayChanged].join(' '), function(e, year, month, courseId, categoryId) {\n // We have to use a queue here because the calling code is decoupled from these listeners.\n // It's possible for the event to be called multiple times before one call is fully resolved.\n root.queue(function(next) {\n return processRequest(e, year, month, courseId, categoryId)\n .then(function() {\n return next();\n })\n .fail(Notification.exception)\n ;\n });\n });\n\n var processRequest = function(e, year, month, courseId, categoryId) {\n var newCurrentMonth = root.find('[data-year=\"' + year + '\"][data-month=\"' + month + '\"]');\n var newParent = newCurrentMonth.closest(CalendarSelectors.calendarPeriods.month);\n var allMonths = root.find(CalendarSelectors.calendarPeriods.month);\n\n var previousMonth = $(allMonths[0]);\n var nextMonth = $(allMonths[2]);\n\n var placeHolder = $('');\n placeHolder.attr('data-template', 'core_calendar/threemonth_month');\n placeHolder.attr('data-includenavigation', false);\n placeHolder.attr('data-mini', true);\n var placeHolderContainer = $('
');\n placeHolderContainer.hide();\n placeHolderContainer.append(placeHolder);\n\n var requestYear;\n var requestMonth;\n var oldMonth;\n\n if (newParent.is(previousMonth)) {\n // Fetch the new previous month.\n placeHolderContainer.insertBefore(previousMonth);\n\n requestYear = previousMonth.data('previousYear');\n requestMonth = previousMonth.data('previousMonth');\n oldMonth = nextMonth;\n } else if (newParent.is(nextMonth)) {\n // Fetch the new next month.\n placeHolderContainer.insertAfter(nextMonth);\n requestYear = nextMonth.data('nextYear');\n requestMonth = nextMonth.data('nextMonth');\n oldMonth = previousMonth;\n } else {\n return $.Deferred().resolve();\n }\n\n return CalendarViewManager.refreshMonthContent(\n placeHolder,\n requestYear,\n requestMonth,\n courseId,\n categoryId,\n placeHolder\n )\n .then(function() {\n var slideUpPromise = $.Deferred();\n var slideDownPromise = $.Deferred();\n oldMonth.slideUp('fast', function() {\n $(this).remove();\n slideUpPromise.resolve();\n });\n placeHolderContainer.slideDown('fast', function() {\n slideDownPromise.resolve();\n });\n\n return $.when(slideUpPromise, slideDownPromise);\n });\n };\n\n // Listen for a click on the day link in the three month block to load the day view.\n root.on('click', CalendarSelectors.links.miniDayLink, function(e) {\n\n var miniDayLink = $(e.target);\n var year = miniDayLink.data('year'),\n month = miniDayLink.data('month'),\n day = miniDayLink.text(),\n courseId = miniDayLink.data('courseid'),\n categoryId = miniDayLink.data('categoryid'),\n calendarRoot = $('body').find(CalendarSelectors.calendarMain);\n CalendarViewManager.refreshDayContent(calendarRoot, year, month, day, courseId, categoryId,\n calendarRoot.find('[id^=\"calendar-\"][data-template^=\"core_calendar/\"]'), 'core_calendar/calendar_day');\n e.preventDefault();\n CalendarViewManager.updateUrl('?view=day');\n });\n };\n\n return {\n init: function(root) {\n root = $(root);\n\n registerCalendarEventListeners(root);\n }\n };\n});\n"],"file":"calendar_threemonth.min.js"}
\ No newline at end of file
+{"version":3,"file":"calendar_threemonth.min.js","sources":["../src/calendar_threemonth.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 .\n\n/**\n * This module handles display of multiple mini calendars in a view, and\n * movement through them.\n *\n * @deprecated since 4.0 MDL-72810.\n * @todo MDL-73117 This will be deleted in Moodle 4.4.\n * @module core_calendar/calendar_threemonth\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/notification',\n 'core_calendar/selectors',\n 'core_calendar/events',\n 'core/templates',\n 'core_calendar/view_manager',\n],\nfunction(\n $,\n Notification,\n CalendarSelectors,\n CalendarEvents,\n Templates,\n CalendarViewManager\n) {\n\n /**\n * Listen to and handle any calendar events fired by the calendar UI.\n *\n * @method registerCalendarEventListeners\n * @param {object} root The calendar root element\n */\n var registerCalendarEventListeners = function(root) {\n var body = $('body');\n body.on([CalendarEvents.monthChanged, CalendarEvents.dayChanged].join(' '), function(e, year, month, courseId, categoryId) {\n // We have to use a queue here because the calling code is decoupled from these listeners.\n // It's possible for the event to be called multiple times before one call is fully resolved.\n root.queue(function(next) {\n return processRequest(e, year, month, courseId, categoryId)\n .then(function() {\n return next();\n })\n .fail(Notification.exception)\n ;\n });\n });\n\n var processRequest = function(e, year, month, courseId, categoryId) {\n var newCurrentMonth = root.find('[data-year=\"' + year + '\"][data-month=\"' + month + '\"]');\n var newParent = newCurrentMonth.closest(CalendarSelectors.calendarPeriods.month);\n var allMonths = root.find(CalendarSelectors.calendarPeriods.month);\n\n var previousMonth = $(allMonths[0]);\n var nextMonth = $(allMonths[2]);\n\n var placeHolder = $('');\n placeHolder.attr('data-template', 'core_calendar/threemonth_month');\n placeHolder.attr('data-includenavigation', false);\n placeHolder.attr('data-mini', true);\n var placeHolderContainer = $('
');\n placeHolderContainer.hide();\n placeHolderContainer.append(placeHolder);\n\n var requestYear;\n var requestMonth;\n var oldMonth;\n\n if (newParent.is(previousMonth)) {\n // Fetch the new previous month.\n placeHolderContainer.insertBefore(previousMonth);\n\n requestYear = previousMonth.data('previousYear');\n requestMonth = previousMonth.data('previousMonth');\n oldMonth = nextMonth;\n } else if (newParent.is(nextMonth)) {\n // Fetch the new next month.\n placeHolderContainer.insertAfter(nextMonth);\n requestYear = nextMonth.data('nextYear');\n requestMonth = nextMonth.data('nextMonth');\n oldMonth = previousMonth;\n } else {\n return $.Deferred().resolve();\n }\n\n return CalendarViewManager.refreshMonthContent(\n placeHolder,\n requestYear,\n requestMonth,\n courseId,\n categoryId,\n placeHolder\n )\n .then(function() {\n var slideUpPromise = $.Deferred();\n var slideDownPromise = $.Deferred();\n oldMonth.slideUp('fast', function() {\n $(this).remove();\n slideUpPromise.resolve();\n });\n placeHolderContainer.slideDown('fast', function() {\n slideDownPromise.resolve();\n });\n\n return $.when(slideUpPromise, slideDownPromise);\n });\n };\n\n // Listen for a click on the day link in the three month block to load the day view.\n root.on('click', CalendarSelectors.links.miniDayLink, function(e) {\n\n var miniDayLink = $(e.target);\n var year = miniDayLink.data('year'),\n month = miniDayLink.data('month'),\n day = miniDayLink.text(),\n courseId = miniDayLink.data('courseid'),\n categoryId = miniDayLink.data('categoryid'),\n calendarRoot = $('body').find(CalendarSelectors.calendarMain);\n CalendarViewManager.refreshDayContent(calendarRoot, year, month, day, courseId, categoryId,\n calendarRoot.find('[id^=\"calendar-\"][data-template^=\"core_calendar/\"]'), 'core_calendar/calendar_day');\n e.preventDefault();\n CalendarViewManager.updateUrl('?view=day');\n });\n };\n\n return {\n init: function(root) {\n root = $(root);\n\n registerCalendarEventListeners(root);\n }\n };\n});\n"],"names":["define","$","Notification","CalendarSelectors","CalendarEvents","Templates","CalendarViewManager","init","root","on","monthChanged","dayChanged","join","e","year","month","courseId","categoryId","queue","next","processRequest","then","fail","exception","newParent","find","closest","calendarPeriods","allMonths","previousMonth","nextMonth","placeHolder","attr","requestYear","requestMonth","oldMonth","placeHolderContainer","hide","append","is","insertBefore","data","Deferred","resolve","insertAfter","refreshMonthContent","slideUpPromise","slideDownPromise","slideUp","this","remove","slideDown","when","links","miniDayLink","target","day","text","calendarRoot","calendarMain","refreshDayContent","preventDefault","updateUrl","registerCalendarEventListeners"],"mappings":";;;;;;;;;;AAyBAA,2CAAO,CACH,SACA,oBACA,0BACA,uBACA,iBACA,+BAEJ,SACIC,EACAC,aACAC,kBACAC,eACAC,UACAC,2BAqGO,CACHC,KAAM,SAASC,OA7FkB,SAASA,MAC/BP,EAAE,QACRQ,GAAG,CAACL,eAAeM,aAAcN,eAAeO,YAAYC,KAAK,MAAM,SAASC,EAAGC,KAAMC,MAAOC,SAAUC,YAG3GT,KAAKU,OAAM,SAASC,aACTC,eAAeP,EAAGC,KAAMC,MAAOC,SAAUC,YAC/CI,MAAK,kBACKF,UAEVG,KAAKpB,aAAaqB,qBAKvBH,eAAiB,SAASP,EAAGC,KAAMC,MAAOC,SAAUC,gBAEhDO,UADkBhB,KAAKiB,KAAK,eAAiBX,KAAO,kBAAoBC,MAAQ,MACpDW,QAAQvB,kBAAkBwB,gBAAgBZ,OACtEa,UAAYpB,KAAKiB,KAAKtB,kBAAkBwB,gBAAgBZ,OAExDc,cAAgB5B,EAAE2B,UAAU,IAC5BE,UAAY7B,EAAE2B,UAAU,IAExBG,YAAc9B,EAAE,UACpB8B,YAAYC,KAAK,gBAAiB,kCAClCD,YAAYC,KAAK,0BAA0B,GAC3CD,YAAYC,KAAK,aAAa,OAK1BC,YACAC,aACAC,SANAC,qBAAuBnC,EAAE,YAC7BmC,qBAAqBC,OACrBD,qBAAqBE,OAAOP,aAMxBP,UAAUe,GAAGV,eAEbO,qBAAqBI,aAAaX,eAElCI,YAAcJ,cAAcY,KAAK,gBACjCP,aAAeL,cAAcY,KAAK,iBAClCN,SAAWL,cACR,CAAA,IAAIN,UAAUe,GAAGT,kBAOb7B,EAAEyC,WAAWC,UALpBP,qBAAqBQ,YAAYd,WACjCG,YAAcH,UAAUW,KAAK,YAC7BP,aAAeJ,UAAUW,KAAK,aAC9BN,SAAWN,qBAKRvB,oBAAoBuC,oBACvBd,YACAE,YACAC,aACAlB,SACAC,WACAc,aAEHV,MAAK,eACEyB,eAAiB7C,EAAEyC,WACnBK,iBAAmB9C,EAAEyC,kBACzBP,SAASa,QAAQ,QAAQ,WACrB/C,EAAEgD,MAAMC,SACRJ,eAAeH,aAEnBP,qBAAqBe,UAAU,QAAQ,WACnCJ,iBAAiBJ,aAGd1C,EAAEmD,KAAKN,eAAgBC,sBAKtCvC,KAAKC,GAAG,QAASN,kBAAkBkD,MAAMC,aAAa,SAASzC,OAEnDyC,YAAcrD,EAAEY,EAAE0C,QAClBzC,KAAOwC,YAAYb,KAAK,QACxB1B,MAAQuC,YAAYb,KAAK,SACzBe,IAAMF,YAAYG,OAClBzC,SAAWsC,YAAYb,KAAK,YAC5BxB,WAAaqC,YAAYb,KAAK,cAC9BiB,aAAezD,EAAE,QAAQwB,KAAKtB,kBAAkBwD,cACpDrD,oBAAoBsD,kBAAkBF,aAAc5C,KAAMC,MAAOyC,IAAKxC,SAAUC,WAC5EyC,aAAajC,KAAK,sDAAuD,8BAC7EZ,EAAEgD,iBACFvD,oBAAoBwD,UAAU,gBAQlCC,CAFAvD,KAAOP,EAAEO"}
\ No newline at end of file
diff --git a/calendar/amd/build/calendar_view.min.js b/calendar/amd/build/calendar_view.min.js
index 4839944c6a0..915843d4e93 100644
--- a/calendar/amd/build/calendar_view.min.js
+++ b/calendar/amd/build/calendar_view.min.js
@@ -1,2 +1,10 @@
-define ("core_calendar/calendar_view",["jquery","core/str","core/notification","core_calendar/selectors","core_calendar/events","core_calendar/view_manager","core_calendar/repository","core/modal_factory","core_calendar/modal_event_form","core/modal_events","core_calendar/crud"],function(a,b,c,d,e,f,g,h,i,j,k){var l=function(b,g){var h=a("body");k.registerRemove(b);var i="reloadCurrent"+g.charAt(0).toUpperCase()+g.slice(1);h.on(e.created,function(){f[i](b)});h.on(e.deleted,function(){f[i](b)});h.on(e.updated,function(){f[i](b)});b.on("change",d.courseSelector,function(){var e=a(this),g=e.val();f[i](b,g,null).then(function(){return b.find(d.courseSelector).val(g)}).then(function(){f.updateUrl("?view=upcoming&course="+g)}).fail(c.exception)});h.on(e.filterChanged,function(a,c){var e=b.find(d.eventType[c.type]);if(!0==c.hidden){e.addClass("hidden")}else{e.removeClass("hidden")}f.foldDayEvents(b)});var j=k.registerEventFormModal(b);k.registerEditListeners(b,j)};return{init:function init(b,c){b=a(b);f.init(b,c);l(b,c)}}});
-//# sourceMappingURL=calendar_view.min.js.map
+/**
+ * This module is responsible for handle calendar day and upcoming view.
+ *
+ * @module core_calendar/calendar
+ * @copyright 2017 Simey Lameze
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/calendar_view",["jquery","core/str","core/notification","core_calendar/selectors","core_calendar/events","core_calendar/view_manager","core_calendar/repository","core/modal_factory","core_calendar/modal_event_form","core/modal_events","core_calendar/crud"],(function($,Str,Notification,CalendarSelectors,CalendarEvents,CalendarViewManager,CalendarRepository,ModalFactory,ModalEventForm,ModalEvents,CalendarCrud){return{init:function(root,type){root=$(root),CalendarViewManager.init(root,type),function(root,type){var body=$("body");CalendarCrud.registerRemove(root);var reloadFunction="reloadCurrent"+type.charAt(0).toUpperCase()+type.slice(1);body.on(CalendarEvents.created,(function(){CalendarViewManager[reloadFunction](root)})),body.on(CalendarEvents.deleted,(function(){CalendarViewManager[reloadFunction](root)})),body.on(CalendarEvents.updated,(function(){CalendarViewManager[reloadFunction](root)})),root.on("change",CalendarSelectors.courseSelector,(function(){var courseId=$(this).val();CalendarViewManager[reloadFunction](root,courseId,null).then((function(){return root.find(CalendarSelectors.courseSelector).val(courseId)})).then((function(){CalendarViewManager.updateUrl("?view=upcoming&course="+courseId)})).fail(Notification.exception)})),body.on(CalendarEvents.filterChanged,(function(e,data){var daysWithEvent=root.find(CalendarSelectors.eventType[data.type]);1==data.hidden?daysWithEvent.addClass("hidden"):daysWithEvent.removeClass("hidden"),CalendarViewManager.foldDayEvents(root)}));var eventFormPromise=CalendarCrud.registerEventFormModal(root);CalendarCrud.registerEditListeners(root,eventFormPromise)}(root,type)}}}));
+
+//# sourceMappingURL=calendar_view.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/calendar_view.min.js.map b/calendar/amd/build/calendar_view.min.js.map
index fb0b7bdfa64..afacfe7aa48 100644
--- a/calendar/amd/build/calendar_view.min.js.map
+++ b/calendar/amd/build/calendar_view.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/calendar_view.js"],"names":["define","$","Str","Notification","CalendarSelectors","CalendarEvents","CalendarViewManager","CalendarRepository","ModalFactory","ModalEventForm","ModalEvents","CalendarCrud","registerEventListeners","root","type","body","registerRemove","reloadFunction","charAt","toUpperCase","slice","on","created","deleted","updated","courseSelector","selectElement","courseId","val","then","find","updateUrl","fail","exception","filterChanged","e","data","daysWithEvent","eventType","hidden","addClass","removeClass","foldDayEvents","eventFormPromise","registerEventFormModal","registerEditListeners","init"],"mappings":"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","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 .\n\n/**\n * This module is responsible for handle calendar day and upcoming view.\n *\n * @module core_calendar/calendar\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/notification',\n 'core_calendar/selectors',\n 'core_calendar/events',\n 'core_calendar/view_manager',\n 'core_calendar/repository',\n 'core/modal_factory',\n 'core_calendar/modal_event_form',\n 'core/modal_events',\n 'core_calendar/crud'\n ],\n function(\n $,\n Str,\n Notification,\n CalendarSelectors,\n CalendarEvents,\n CalendarViewManager,\n CalendarRepository,\n ModalFactory,\n ModalEventForm,\n ModalEvents,\n CalendarCrud\n ) {\n\n var registerEventListeners = function(root, type) {\n var body = $('body');\n\n CalendarCrud.registerRemove(root);\n\n var reloadFunction = 'reloadCurrent' + type.charAt(0).toUpperCase() + type.slice(1);\n\n body.on(CalendarEvents.created, function() {\n CalendarViewManager[reloadFunction](root);\n });\n body.on(CalendarEvents.deleted, function() {\n CalendarViewManager[reloadFunction](root);\n });\n body.on(CalendarEvents.updated, function() {\n CalendarViewManager[reloadFunction](root);\n });\n\n root.on('change', CalendarSelectors.courseSelector, function() {\n var selectElement = $(this);\n var courseId = selectElement.val();\n CalendarViewManager[reloadFunction](root, courseId, null)\n .then(function() {\n // We need to get the selector again because the content has changed.\n return root.find(CalendarSelectors.courseSelector).val(courseId);\n })\n .then(function() {\n CalendarViewManager.updateUrl('?view=upcoming&course=' + courseId);\n })\n .fail(Notification.exception);\n });\n\n body.on(CalendarEvents.filterChanged, function(e, data) {\n var daysWithEvent = root.find(CalendarSelectors.eventType[data.type]);\n if (data.hidden == true) {\n daysWithEvent.addClass('hidden');\n } else {\n daysWithEvent.removeClass('hidden');\n }\n CalendarViewManager.foldDayEvents(root);\n });\n\n var eventFormPromise = CalendarCrud.registerEventFormModal(root);\n CalendarCrud.registerEditListeners(root, eventFormPromise);\n };\n\n return {\n init: function(root, type) {\n root = $(root);\n\n CalendarViewManager.init(root, type);\n registerEventListeners(root, type);\n }\n };\n });\n"],"file":"calendar_view.min.js"}
\ No newline at end of file
+{"version":3,"file":"calendar_view.min.js","sources":["../src/calendar_view.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 .\n\n/**\n * This module is responsible for handle calendar day and upcoming view.\n *\n * @module core_calendar/calendar\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/notification',\n 'core_calendar/selectors',\n 'core_calendar/events',\n 'core_calendar/view_manager',\n 'core_calendar/repository',\n 'core/modal_factory',\n 'core_calendar/modal_event_form',\n 'core/modal_events',\n 'core_calendar/crud'\n ],\n function(\n $,\n Str,\n Notification,\n CalendarSelectors,\n CalendarEvents,\n CalendarViewManager,\n CalendarRepository,\n ModalFactory,\n ModalEventForm,\n ModalEvents,\n CalendarCrud\n ) {\n\n var registerEventListeners = function(root, type) {\n var body = $('body');\n\n CalendarCrud.registerRemove(root);\n\n var reloadFunction = 'reloadCurrent' + type.charAt(0).toUpperCase() + type.slice(1);\n\n body.on(CalendarEvents.created, function() {\n CalendarViewManager[reloadFunction](root);\n });\n body.on(CalendarEvents.deleted, function() {\n CalendarViewManager[reloadFunction](root);\n });\n body.on(CalendarEvents.updated, function() {\n CalendarViewManager[reloadFunction](root);\n });\n\n root.on('change', CalendarSelectors.courseSelector, function() {\n var selectElement = $(this);\n var courseId = selectElement.val();\n CalendarViewManager[reloadFunction](root, courseId, null)\n .then(function() {\n // We need to get the selector again because the content has changed.\n return root.find(CalendarSelectors.courseSelector).val(courseId);\n })\n .then(function() {\n CalendarViewManager.updateUrl('?view=upcoming&course=' + courseId);\n })\n .fail(Notification.exception);\n });\n\n body.on(CalendarEvents.filterChanged, function(e, data) {\n var daysWithEvent = root.find(CalendarSelectors.eventType[data.type]);\n if (data.hidden == true) {\n daysWithEvent.addClass('hidden');\n } else {\n daysWithEvent.removeClass('hidden');\n }\n CalendarViewManager.foldDayEvents(root);\n });\n\n var eventFormPromise = CalendarCrud.registerEventFormModal(root);\n CalendarCrud.registerEditListeners(root, eventFormPromise);\n };\n\n return {\n init: function(root, type) {\n root = $(root);\n\n CalendarViewManager.init(root, type);\n registerEventListeners(root, type);\n }\n };\n });\n"],"names":["define","$","Str","Notification","CalendarSelectors","CalendarEvents","CalendarViewManager","CalendarRepository","ModalFactory","ModalEventForm","ModalEvents","CalendarCrud","init","root","type","body","registerRemove","reloadFunction","charAt","toUpperCase","slice","on","created","deleted","updated","courseSelector","courseId","this","val","then","find","updateUrl","fail","exception","filterChanged","e","data","daysWithEvent","eventType","hidden","addClass","removeClass","foldDayEvents","eventFormPromise","registerEventFormModal","registerEditListeners","registerEventListeners"],"mappings":";;;;;;;AAsBAA,qCAAO,CACC,SACA,WACA,oBACA,0BACA,uBACA,6BACA,2BACA,qBACA,iCACA,oBACA,uBAEJ,SACIC,EACAC,IACAC,aACAC,kBACAC,eACAC,oBACAC,mBACAC,aACAC,eACAC,YACAC,oBAgDO,CACHC,KAAM,SAASC,KAAMC,MACjBD,KAAOZ,EAAEY,MAETP,oBAAoBM,KAAKC,KAAMC,MAjDV,SAASD,KAAMC,UACpCC,KAAOd,EAAE,QAEbU,aAAaK,eAAeH,UAExBI,eAAiB,gBAAkBH,KAAKI,OAAO,GAAGC,cAAgBL,KAAKM,MAAM,GAEjFL,KAAKM,GAAGhB,eAAeiB,SAAS,WAC5BhB,oBAAoBW,gBAAgBJ,SAExCE,KAAKM,GAAGhB,eAAekB,SAAS,WAC5BjB,oBAAoBW,gBAAgBJ,SAExCE,KAAKM,GAAGhB,eAAemB,SAAS,WAC5BlB,oBAAoBW,gBAAgBJ,SAGxCA,KAAKQ,GAAG,SAAUjB,kBAAkBqB,gBAAgB,eAE5CC,SADgBzB,EAAE0B,MACOC,MAC7BtB,oBAAoBW,gBAAgBJ,KAAMa,SAAU,MAC/CG,MAAK,kBAEKhB,KAAKiB,KAAK1B,kBAAkBqB,gBAAgBG,IAAIF,aAE1DG,MAAK,WACFvB,oBAAoByB,UAAU,yBAA2BL,aAE5DM,KAAK7B,aAAa8B,cAG3BlB,KAAKM,GAAGhB,eAAe6B,eAAe,SAASC,EAAGC,UAC1CC,cAAgBxB,KAAKiB,KAAK1B,kBAAkBkC,UAAUF,KAAKtB,OAC5C,GAAfsB,KAAKG,OACLF,cAAcG,SAAS,UAEvBH,cAAcI,YAAY,UAE9BnC,oBAAoBoC,cAAc7B,aAGlC8B,iBAAmBhC,aAAaiC,uBAAuB/B,MAC3DF,aAAakC,sBAAsBhC,KAAM8B,kBAQrCG,CAAuBjC,KAAMC"}
\ No newline at end of file
diff --git a/calendar/amd/build/crud.min.js b/calendar/amd/build/crud.min.js
index 9f0d0e1413f..622af5a4497 100644
--- a/calendar/amd/build/crud.min.js
+++ b/calendar/amd/build/crud.min.js
@@ -1,2 +1,10 @@
-define ("core_calendar/crud",["jquery","core/str","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","core/modal_factory","core/modal_events","core_calendar/modal_event_form","core_calendar/repository","core_calendar/events","core_calendar/modal_delete","core_calendar/selectors","core/pending"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n){function o(d,e,f){var i=new n("core_calendar/crud:confirmDeletion"),m=[{key:"deleteevent",component:"calendar"}];f=parseInt(f,10);var o,p=1
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/crud",["jquery","core/str","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","core/modal_factory","core/modal_events","core_calendar/modal_event_form","core_calendar/repository","core_calendar/events","core_calendar/modal_delete","core_calendar/selectors","core/pending"],(function($,Str,Notification,CustomEvents,Modal,ModalRegistry,ModalFactory,ModalEvents,ModalEventForm,CalendarRepository,CalendarEvents,ModalDelete,CalendarSelectors,Pending){return{registerRemove:function(root){root.on("click",CalendarSelectors.actions.remove,(function(e){var eventSource=$(this).closest(CalendarSelectors.eventItem);!function(eventId,eventTitle,eventCount){var deletePromise,pendingPromise=new Pending("core_calendar/crud:confirmDeletion"),deleteStrings=[{key:"deleteevent",component:"calendar"}],isRepeatedEvent=(eventCount=parseInt(eventCount,10))>1;isRepeatedEvent?(deleteStrings.push({key:"confirmeventseriesdelete",component:"calendar",param:{name:eventTitle,count:eventCount}}),deletePromise=ModalFactory.create({type:ModalDelete.TYPE})):(deleteStrings.push({key:"confirmeventdelete",component:"calendar",param:eventTitle}),deletePromise=ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL}));var stringsPromise=Str.get_strings(deleteStrings);$.when(stringsPromise,deletePromise).then((function(strings,deleteModal){return deleteModal.setRemoveOnClose(!0),deleteModal.setTitle(strings[0]),deleteModal.setBody(strings[1]),isRepeatedEvent||deleteModal.setSaveButtonText(strings[0]),deleteModal.show(),deleteModal.getRoot().on(ModalEvents.save,(function(){var pendingPromise=new Pending("calendar/crud:initModal:deletedevent");CalendarRepository.deleteEvent(eventId,!1).then((function(){$("body").trigger(CalendarEvents.deleted,[eventId,!1])})).then(pendingPromise.resolve).catch(Notification.exception)})),deleteModal.getRoot().on(CalendarEvents.deleteAll,(function(){var pendingPromise=new Pending("calendar/crud:initModal:deletedallevent");CalendarRepository.deleteEvent(eventId,!0).then((function(){$("body").trigger(CalendarEvents.deleted,[eventId,!0])})).then(pendingPromise.resolve).catch(Notification.exception)})),deleteModal})).then((function(modal){return pendingPromise.resolve(),modal})).catch(Notification.exception)}(eventSource.data("eventId"),eventSource.data("eventTitle"),eventSource.data("eventCount")),e.preventDefault()}))},registerEditListeners:function(root,eventFormModalPromise){var pendingPromise=new Pending("core_calendar/crud:registerEditListeners");return eventFormModalPromise.then((function(modal){return $("body").on(CalendarEvents.editEvent,(function(e,eventId){var calendarWrapper=root.find(CalendarSelectors.wrapper);modal.setEventId(eventId),modal.setContextId(calendarWrapper.data("contextId")),modal.show(),e.stopImmediatePropagation()})),modal})).then((function(modal){return pendingPromise.resolve(),modal})).catch(Notification.exception)},registerEventFormModal:function(root){var eventFormPromise=ModalFactory.create({type:ModalEventForm.TYPE,large:!0});return root.on("click",CalendarSelectors.actions.create,(function(e){eventFormPromise.then((function(modal){var wrapper=root.find(CalendarSelectors.wrapper),categoryId=wrapper.data("categoryid");void 0!==categoryId&&modal.setCategoryId(categoryId);var today=root.find(CalendarSelectors.today),firstDay=root.find(CalendarSelectors.day);!today.length&&firstDay.length&&modal.setStartTime(firstDay.data("newEventTimestamp")),modal.setContextId(wrapper.data("contextId")),modal.setCourseId(wrapper.data("courseid")),modal.show()})).fail(Notification.exception),e.preventDefault()})),root.on("click",CalendarSelectors.actions.edit,(function(e){e.preventDefault();var target=$(e.currentTarget),calendarWrapper=target.closest(CalendarSelectors.wrapper),eventWrapper=target.closest(CalendarSelectors.eventItem);eventFormPromise.then((function(modal){modal.setEventId(eventWrapper.data("eventId")),modal.setContextId(calendarWrapper.data("contextId")),modal.show(),e.stopImmediatePropagation()})).fail(Notification.exception)})),eventFormPromise}}}));
+
+//# sourceMappingURL=crud.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/crud.min.js.map b/calendar/amd/build/crud.min.js.map
index e9c3d90b0b8..02f297211c6 100644
--- a/calendar/amd/build/crud.min.js.map
+++ b/calendar/amd/build/crud.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/crud.js"],"names":["define","$","Str","Notification","CustomEvents","Modal","ModalRegistry","ModalFactory","ModalEvents","ModalEventForm","CalendarRepository","CalendarEvents","ModalDelete","CalendarSelectors","Pending","confirmDeletion","eventId","eventTitle","eventCount","pendingPromise","deleteStrings","key","component","parseInt","deletePromise","isRepeatedEvent","push","param","name","count","create","type","TYPE","types","SAVE_CANCEL","stringsPromise","get_strings","finalPromise","when","then","strings","deleteModal","setRemoveOnClose","setTitle","setBody","setSaveButtonText","show","getRoot","on","save","deleteEvent","trigger","deleted","resolve","catch","exception","deleteAll","modal","registerRemove","root","actions","remove","e","eventSource","closest","eventItem","data","preventDefault","registerEditListeners","eventFormModalPromise","editEvent","calendarWrapper","find","wrapper","setEventId","setContextId","stopImmediatePropagation","registerEventFormModal","eventFormPromise","large","categoryId","setCategoryId","today","firstDay","day","length","setStartTime","setCourseId","fail","edit","target","currentTarget","eventWrapper"],"mappings":"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","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 .\n\n/**\n * A module to handle CRUD operations within the UI.\n *\n * @module core_calendar/crud\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_registry',\n 'core/modal_factory',\n 'core/modal_events',\n 'core_calendar/modal_event_form',\n 'core_calendar/repository',\n 'core_calendar/events',\n 'core_calendar/modal_delete',\n 'core_calendar/selectors',\n 'core/pending',\n],\nfunction(\n $,\n Str,\n Notification,\n CustomEvents,\n Modal,\n ModalRegistry,\n ModalFactory,\n ModalEvents,\n ModalEventForm,\n CalendarRepository,\n CalendarEvents,\n ModalDelete,\n CalendarSelectors,\n Pending\n) {\n\n /**\n * Prepares the action for the summary modal's delete action.\n *\n * @param {Number} eventId The ID of the event.\n * @param {string} eventTitle The event title.\n * @param {Number} eventCount The number of events in the series.\n * @return {Promise}\n */\n function confirmDeletion(eventId, eventTitle, eventCount) {\n var pendingPromise = new Pending('core_calendar/crud:confirmDeletion');\n var deleteStrings = [\n {\n key: 'deleteevent',\n component: 'calendar'\n },\n ];\n\n eventCount = parseInt(eventCount, 10);\n var deletePromise;\n var isRepeatedEvent = eventCount > 1;\n if (isRepeatedEvent) {\n deleteStrings.push({\n key: 'confirmeventseriesdelete',\n component: 'calendar',\n param: {\n name: eventTitle,\n count: eventCount,\n },\n });\n\n deletePromise = ModalFactory.create(\n {\n type: ModalDelete.TYPE\n }\n );\n } else {\n deleteStrings.push({\n key: 'confirmeventdelete',\n component: 'calendar',\n param: eventTitle\n });\n\n\n deletePromise = ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n });\n }\n\n var stringsPromise = Str.get_strings(deleteStrings);\n\n var finalPromise = $.when(stringsPromise, deletePromise)\n .then(function(strings, deleteModal) {\n deleteModal.setRemoveOnClose(true);\n deleteModal.setTitle(strings[0]);\n deleteModal.setBody(strings[1]);\n if (!isRepeatedEvent) {\n deleteModal.setSaveButtonText(strings[0]);\n }\n\n deleteModal.show();\n\n deleteModal.getRoot().on(ModalEvents.save, function() {\n var pendingPromise = new Pending('calendar/crud:initModal:deletedevent');\n CalendarRepository.deleteEvent(eventId, false)\n .then(function() {\n $('body').trigger(CalendarEvents.deleted, [eventId, false]);\n return;\n })\n .then(pendingPromise.resolve)\n .catch(Notification.exception);\n });\n\n deleteModal.getRoot().on(CalendarEvents.deleteAll, function() {\n var pendingPromise = new Pending('calendar/crud:initModal:deletedallevent');\n CalendarRepository.deleteEvent(eventId, true)\n .then(function() {\n $('body').trigger(CalendarEvents.deleted, [eventId, true]);\n return;\n })\n .then(pendingPromise.resolve)\n .catch(Notification.exception);\n });\n\n return deleteModal;\n })\n .then(function(modal) {\n pendingPromise.resolve();\n\n return modal;\n })\n .catch(Notification.exception);\n\n return finalPromise;\n }\n\n /**\n * Create the event form modal for creating new events and\n * editing existing events.\n *\n * @method registerEventFormModal\n * @param {object} root The calendar root element\n * @return {object} The create modal promise\n */\n var registerEventFormModal = function(root) {\n var eventFormPromise = ModalFactory.create({\n type: ModalEventForm.TYPE,\n large: true\n });\n\n // Bind click event on the new event button.\n root.on('click', CalendarSelectors.actions.create, function(e) {\n eventFormPromise.then(function(modal) {\n var wrapper = root.find(CalendarSelectors.wrapper);\n\n var categoryId = wrapper.data('categoryid');\n if (typeof categoryId !== 'undefined') {\n modal.setCategoryId(categoryId);\n }\n\n // Attempt to find the cell for today.\n // If it can't be found, then use the start time of the first day on the calendar.\n var today = root.find(CalendarSelectors.today);\n var firstDay = root.find(CalendarSelectors.day);\n if (!today.length && firstDay.length) {\n modal.setStartTime(firstDay.data('newEventTimestamp'));\n }\n\n modal.setContextId(wrapper.data('contextId'));\n modal.setCourseId(wrapper.data('courseid'));\n modal.show();\n return;\n })\n .fail(Notification.exception);\n\n e.preventDefault();\n });\n\n root.on('click', CalendarSelectors.actions.edit, function(e) {\n e.preventDefault();\n var target = $(e.currentTarget),\n calendarWrapper = target.closest(CalendarSelectors.wrapper),\n eventWrapper = target.closest(CalendarSelectors.eventItem);\n\n eventFormPromise.then(function(modal) {\n // When something within the calendar tells us the user wants\n // to edit an event then show the event form modal.\n modal.setEventId(eventWrapper.data('eventId'));\n\n modal.setContextId(calendarWrapper.data('contextId'));\n modal.show();\n\n e.stopImmediatePropagation();\n return;\n }).fail(Notification.exception);\n });\n\n\n return eventFormPromise;\n };\n /**\n * Register the listeners required to remove the event.\n *\n * @param {jQuery} root\n */\n function registerRemove(root) {\n root.on('click', CalendarSelectors.actions.remove, function(e) {\n // Fetch the event title, count, and pass them into the new dialogue.\n var eventSource = $(this).closest(CalendarSelectors.eventItem);\n var eventId = eventSource.data('eventId'),\n eventTitle = eventSource.data('eventTitle'),\n eventCount = eventSource.data('eventCount');\n confirmDeletion(eventId, eventTitle, eventCount);\n\n e.preventDefault();\n });\n }\n\n /**\n * Register the listeners required to edit the event.\n *\n * @param {jQuery} root\n * @param {Promise} eventFormModalPromise\n * @returns {Promise}\n */\n function registerEditListeners(root, eventFormModalPromise) {\n var pendingPromise = new Pending('core_calendar/crud:registerEditListeners');\n\n return eventFormModalPromise\n .then(function(modal) {\n // When something within the calendar tells us the user wants\n // to edit an event then show the event form modal.\n $('body').on(CalendarEvents.editEvent, function(e, eventId) {\n var calendarWrapper = root.find(CalendarSelectors.wrapper);\n modal.setEventId(eventId);\n modal.setContextId(calendarWrapper.data('contextId'));\n modal.show();\n\n e.stopImmediatePropagation();\n });\n return modal;\n })\n .then(function(modal) {\n pendingPromise.resolve();\n\n return modal;\n })\n .catch(Notification.exception);\n }\n\n return {\n registerRemove: registerRemove,\n registerEditListeners: registerEditListeners,\n registerEventFormModal: registerEventFormModal\n };\n});\n"],"file":"crud.min.js"}
\ No newline at end of file
+{"version":3,"file":"crud.min.js","sources":["../src/crud.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 .\n\n/**\n * A module to handle CRUD operations within the UI.\n *\n * @module core_calendar/crud\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_registry',\n 'core/modal_factory',\n 'core/modal_events',\n 'core_calendar/modal_event_form',\n 'core_calendar/repository',\n 'core_calendar/events',\n 'core_calendar/modal_delete',\n 'core_calendar/selectors',\n 'core/pending',\n],\nfunction(\n $,\n Str,\n Notification,\n CustomEvents,\n Modal,\n ModalRegistry,\n ModalFactory,\n ModalEvents,\n ModalEventForm,\n CalendarRepository,\n CalendarEvents,\n ModalDelete,\n CalendarSelectors,\n Pending\n) {\n\n /**\n * Prepares the action for the summary modal's delete action.\n *\n * @param {Number} eventId The ID of the event.\n * @param {string} eventTitle The event title.\n * @param {Number} eventCount The number of events in the series.\n * @return {Promise}\n */\n function confirmDeletion(eventId, eventTitle, eventCount) {\n var pendingPromise = new Pending('core_calendar/crud:confirmDeletion');\n var deleteStrings = [\n {\n key: 'deleteevent',\n component: 'calendar'\n },\n ];\n\n eventCount = parseInt(eventCount, 10);\n var deletePromise;\n var isRepeatedEvent = eventCount > 1;\n if (isRepeatedEvent) {\n deleteStrings.push({\n key: 'confirmeventseriesdelete',\n component: 'calendar',\n param: {\n name: eventTitle,\n count: eventCount,\n },\n });\n\n deletePromise = ModalFactory.create(\n {\n type: ModalDelete.TYPE\n }\n );\n } else {\n deleteStrings.push({\n key: 'confirmeventdelete',\n component: 'calendar',\n param: eventTitle\n });\n\n\n deletePromise = ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n });\n }\n\n var stringsPromise = Str.get_strings(deleteStrings);\n\n var finalPromise = $.when(stringsPromise, deletePromise)\n .then(function(strings, deleteModal) {\n deleteModal.setRemoveOnClose(true);\n deleteModal.setTitle(strings[0]);\n deleteModal.setBody(strings[1]);\n if (!isRepeatedEvent) {\n deleteModal.setSaveButtonText(strings[0]);\n }\n\n deleteModal.show();\n\n deleteModal.getRoot().on(ModalEvents.save, function() {\n var pendingPromise = new Pending('calendar/crud:initModal:deletedevent');\n CalendarRepository.deleteEvent(eventId, false)\n .then(function() {\n $('body').trigger(CalendarEvents.deleted, [eventId, false]);\n return;\n })\n .then(pendingPromise.resolve)\n .catch(Notification.exception);\n });\n\n deleteModal.getRoot().on(CalendarEvents.deleteAll, function() {\n var pendingPromise = new Pending('calendar/crud:initModal:deletedallevent');\n CalendarRepository.deleteEvent(eventId, true)\n .then(function() {\n $('body').trigger(CalendarEvents.deleted, [eventId, true]);\n return;\n })\n .then(pendingPromise.resolve)\n .catch(Notification.exception);\n });\n\n return deleteModal;\n })\n .then(function(modal) {\n pendingPromise.resolve();\n\n return modal;\n })\n .catch(Notification.exception);\n\n return finalPromise;\n }\n\n /**\n * Create the event form modal for creating new events and\n * editing existing events.\n *\n * @method registerEventFormModal\n * @param {object} root The calendar root element\n * @return {object} The create modal promise\n */\n var registerEventFormModal = function(root) {\n var eventFormPromise = ModalFactory.create({\n type: ModalEventForm.TYPE,\n large: true\n });\n\n // Bind click event on the new event button.\n root.on('click', CalendarSelectors.actions.create, function(e) {\n eventFormPromise.then(function(modal) {\n var wrapper = root.find(CalendarSelectors.wrapper);\n\n var categoryId = wrapper.data('categoryid');\n if (typeof categoryId !== 'undefined') {\n modal.setCategoryId(categoryId);\n }\n\n // Attempt to find the cell for today.\n // If it can't be found, then use the start time of the first day on the calendar.\n var today = root.find(CalendarSelectors.today);\n var firstDay = root.find(CalendarSelectors.day);\n if (!today.length && firstDay.length) {\n modal.setStartTime(firstDay.data('newEventTimestamp'));\n }\n\n modal.setContextId(wrapper.data('contextId'));\n modal.setCourseId(wrapper.data('courseid'));\n modal.show();\n return;\n })\n .fail(Notification.exception);\n\n e.preventDefault();\n });\n\n root.on('click', CalendarSelectors.actions.edit, function(e) {\n e.preventDefault();\n var target = $(e.currentTarget),\n calendarWrapper = target.closest(CalendarSelectors.wrapper),\n eventWrapper = target.closest(CalendarSelectors.eventItem);\n\n eventFormPromise.then(function(modal) {\n // When something within the calendar tells us the user wants\n // to edit an event then show the event form modal.\n modal.setEventId(eventWrapper.data('eventId'));\n\n modal.setContextId(calendarWrapper.data('contextId'));\n modal.show();\n\n e.stopImmediatePropagation();\n return;\n }).fail(Notification.exception);\n });\n\n\n return eventFormPromise;\n };\n /**\n * Register the listeners required to remove the event.\n *\n * @param {jQuery} root\n */\n function registerRemove(root) {\n root.on('click', CalendarSelectors.actions.remove, function(e) {\n // Fetch the event title, count, and pass them into the new dialogue.\n var eventSource = $(this).closest(CalendarSelectors.eventItem);\n var eventId = eventSource.data('eventId'),\n eventTitle = eventSource.data('eventTitle'),\n eventCount = eventSource.data('eventCount');\n confirmDeletion(eventId, eventTitle, eventCount);\n\n e.preventDefault();\n });\n }\n\n /**\n * Register the listeners required to edit the event.\n *\n * @param {jQuery} root\n * @param {Promise} eventFormModalPromise\n * @returns {Promise}\n */\n function registerEditListeners(root, eventFormModalPromise) {\n var pendingPromise = new Pending('core_calendar/crud:registerEditListeners');\n\n return eventFormModalPromise\n .then(function(modal) {\n // When something within the calendar tells us the user wants\n // to edit an event then show the event form modal.\n $('body').on(CalendarEvents.editEvent, function(e, eventId) {\n var calendarWrapper = root.find(CalendarSelectors.wrapper);\n modal.setEventId(eventId);\n modal.setContextId(calendarWrapper.data('contextId'));\n modal.show();\n\n e.stopImmediatePropagation();\n });\n return modal;\n })\n .then(function(modal) {\n pendingPromise.resolve();\n\n return modal;\n })\n .catch(Notification.exception);\n }\n\n return {\n registerRemove: registerRemove,\n registerEditListeners: registerEditListeners,\n registerEventFormModal: registerEventFormModal\n };\n});\n"],"names":["define","$","Str","Notification","CustomEvents","Modal","ModalRegistry","ModalFactory","ModalEvents","ModalEventForm","CalendarRepository","CalendarEvents","ModalDelete","CalendarSelectors","Pending","registerRemove","root","on","actions","remove","e","eventSource","this","closest","eventItem","eventId","eventTitle","eventCount","deletePromise","pendingPromise","deleteStrings","key","component","isRepeatedEvent","parseInt","push","param","name","count","create","type","TYPE","types","SAVE_CANCEL","stringsPromise","get_strings","when","then","strings","deleteModal","setRemoveOnClose","setTitle","setBody","setSaveButtonText","show","getRoot","save","deleteEvent","trigger","deleted","resolve","catch","exception","deleteAll","modal","confirmDeletion","data","preventDefault","registerEditListeners","eventFormModalPromise","editEvent","calendarWrapper","find","wrapper","setEventId","setContextId","stopImmediatePropagation","registerEventFormModal","eventFormPromise","large","categoryId","setCategoryId","today","firstDay","day","length","setStartTime","setCourseId","fail","edit","target","currentTarget","eventWrapper"],"mappings":"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"}
\ No newline at end of file
diff --git a/calendar/amd/build/drag_drop_data_store.min.js b/calendar/amd/build/drag_drop_data_store.min.js
index 092a92cac17..ca54ca4b76c 100644
--- a/calendar/amd/build/drag_drop_data_store.min.js
+++ b/calendar/amd/build/drag_drop_data_store.min.js
@@ -1,2 +1,14 @@
-define ("core_calendar/drag_drop_data_store",[],function(){var a=null,b=null,c=null,d=null,e=null,f=null,g=function(b){a=b},h=function(){return a},i=function(){return null!==a},j=function(a){b=a},k=function(){return b},l=function(a){c=a},m=function(){return c},n=function(){return null!==c},o=function(a){d=a},p=function(){return d},q=function(){return null!==d},r=function(a){e=a},s=function(){return e},t=function(a){f=a},u=function(){return f};return{setEventId:g,getEventId:h,hasEventId:i,setDurationDays:j,getDurationDays:k,setMinTimestart:l,getMinTimestart:m,hasMinTimestart:n,setMaxTimestart:o,getMaxTimestart:p,hasMaxTimestart:q,setMinError:r,getMinError:s,setMaxError:t,getMaxError:u,clearAll:function clearAll(){g(null);j(null);l(null);o(null);r(null);t(null)}}});
-//# sourceMappingURL=drag_drop_data_store.min.js.map
+/**
+ * A javascript module to store calendar drag and drop data.
+ *
+ * This module is unfortunately required because of the limitations
+ * of the HTML5 drag and drop API and it's ability to provide data
+ * between the different stages of the drag/drop lifecycle.
+ *
+ * @module core_calendar/drag_drop_data_store
+ * @copyright 2017 Ryan Wyllie
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/drag_drop_data_store",[],(function(){var eventId=null,durationDays=null,minTimestart=null,maxTimestart=null,minError=null,maxError=null,setEventId=function(id){eventId=id},setDurationDays=function(days){durationDays=days},setMinTimestart=function(timestamp){minTimestart=timestamp},setMaxTimestart=function(timestamp){maxTimestart=timestamp},setMinError=function(message){minError=message},setMaxError=function(message){maxError=message};return{setEventId:setEventId,getEventId:function(){return eventId},hasEventId:function(){return null!==eventId},setDurationDays:setDurationDays,getDurationDays:function(){return durationDays},setMinTimestart:setMinTimestart,getMinTimestart:function(){return minTimestart},hasMinTimestart:function(){return null!==minTimestart},setMaxTimestart:setMaxTimestart,getMaxTimestart:function(){return maxTimestart},hasMaxTimestart:function(){return null!==maxTimestart},setMinError:setMinError,getMinError:function(){return minError},setMaxError:setMaxError,getMaxError:function(){return maxError},clearAll:function(){setEventId(null),setDurationDays(null),setMinTimestart(null),setMaxTimestart(null),setMinError(null),setMaxError(null)}}}));
+
+//# sourceMappingURL=drag_drop_data_store.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/drag_drop_data_store.min.js.map b/calendar/amd/build/drag_drop_data_store.min.js.map
index 9a339242cbb..bbba73e8937 100644
--- a/calendar/amd/build/drag_drop_data_store.min.js.map
+++ b/calendar/amd/build/drag_drop_data_store.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/drag_drop_data_store.js"],"names":["define","eventId","durationDays","minTimestart","maxTimestart","minError","maxError","setEventId","id","getEventId","hasEventId","setDurationDays","days","getDurationDays","setMinTimestart","timestamp","getMinTimestart","hasMinTimestart","setMaxTimestart","getMaxTimestart","hasMaxTimestart","setMinError","message","getMinError","setMaxError","getMaxError","clearAll"],"mappings":"AA0BAA,OAAM,sCAAC,EAAD,CAAK,UAAW,IAEdC,CAAAA,CAAO,CAAG,IAFI,CAIdC,CAAY,CAAG,IAJD,CAMdC,CAAY,CAAG,IAND,CAQdC,CAAY,CAAG,IARD,CAUdC,CAAQ,CAAG,IAVG,CAYdC,CAAQ,CAAG,IAZG,CAmBdC,CAAU,CAAG,SAASC,CAAT,CAAa,CAC1BP,CAAO,CAAGO,CACb,CArBiB,CA4BdC,CAAU,CAAG,UAAW,CACxB,MAAOR,CAAAA,CACV,CA9BiB,CAqCdS,CAAU,CAAG,UAAW,CACxB,MAAmB,KAAZ,GAAAT,CACV,CAvCiB,CA8CdU,CAAe,CAAG,SAASC,CAAT,CAAe,CACjCV,CAAY,CAAGU,CAClB,CAhDiB,CAuDdC,CAAe,CAAG,UAAW,CAC7B,MAAOX,CAAAA,CACV,CAzDiB,CAgEdY,CAAe,CAAG,SAASC,CAAT,CAAoB,CACtCZ,CAAY,CAAGY,CAClB,CAlEiB,CAyEdC,CAAe,CAAG,UAAW,CAC7B,MAAOb,CAAAA,CACV,CA3EiB,CAkFdc,CAAe,CAAG,UAAW,CAC7B,MAAwB,KAAjB,GAAAd,CACV,CApFiB,CA2Fde,CAAe,CAAG,SAASH,CAAT,CAAoB,CACtCX,CAAY,CAAGW,CAClB,CA7FiB,CAoGdI,CAAe,CAAG,UAAW,CAC7B,MAAOf,CAAAA,CACV,CAtGiB,CA6GdgB,CAAe,CAAG,UAAW,CAC7B,MAAwB,KAAjB,GAAAhB,CACV,CA/GiB,CAuHdiB,CAAW,CAAG,SAASC,CAAT,CAAkB,CAChCjB,CAAQ,CAAGiB,CACd,CAzHiB,CAgIdC,CAAW,CAAG,UAAW,CACzB,MAAOlB,CAAAA,CACV,CAlIiB,CA0IdmB,CAAW,CAAG,SAASF,CAAT,CAAkB,CAChChB,CAAQ,CAAGgB,CACd,CA5IiB,CAmJdG,CAAW,CAAG,UAAW,CACzB,MAAOnB,CAAAA,CACV,CArJiB,CAmKlB,MAAO,CACHC,UAAU,CAAEA,CADT,CAEHE,UAAU,CAAEA,CAFT,CAGHC,UAAU,CAAEA,CAHT,CAIHC,eAAe,CAAEA,CAJd,CAKHE,eAAe,CAAEA,CALd,CAMHC,eAAe,CAAEA,CANd,CAOHE,eAAe,CAAEA,CAPd,CAQHC,eAAe,CAAEA,CARd,CASHC,eAAe,CAAEA,CATd,CAUHC,eAAe,CAAEA,CAVd,CAWHC,eAAe,CAAEA,CAXd,CAYHC,WAAW,CAAEA,CAZV,CAaHE,WAAW,CAAEA,CAbV,CAcHC,WAAW,CAAEA,CAdV,CAeHC,WAAW,CAAEA,CAfV,CAgBHC,QAAQ,CAzBG,QAAXA,CAAAA,QAAW,EAAW,CACtBnB,CAAU,CAAC,IAAD,CAAV,CACAI,CAAe,CAAC,IAAD,CAAf,CACAG,CAAe,CAAC,IAAD,CAAf,CACAI,CAAe,CAAC,IAAD,CAAf,CACAG,CAAW,CAAC,IAAD,CAAX,CACAG,CAAW,CAAC,IAAD,CACd,CAEM,CAkBV,CArLK,CAAN","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 .\n\n/**\n * A javascript module to store calendar drag and drop data.\n *\n * This module is unfortunately required because of the limitations\n * of the HTML5 drag and drop API and it's ability to provide data\n * between the different stages of the drag/drop lifecycle.\n *\n * @module core_calendar/drag_drop_data_store\n * @copyright 2017 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n /* @var {int|null} eventId The id of the event being dragged */\n var eventId = null;\n /* @var {int|null} durationDays How many days the event spans */\n var durationDays = null;\n /* @var {int|null} minTimestart The earliest valid timestart */\n var minTimestart = null;\n /* @var {int|null} maxTimestart The latest valid tiemstart */\n var maxTimestart = null;\n /* @var {string|null} minError Error message for min timestamp violation */\n var minError = null;\n /* @var {string|null} maxError Error message for max timestamp violation */\n var maxError = null;\n\n /**\n * Store the id of the event being dragged.\n *\n * @param {int} id The event id\n */\n var setEventId = function(id) {\n eventId = id;\n };\n\n /**\n * Get the stored event id.\n *\n * @return {int|null}\n */\n var getEventId = function() {\n return eventId;\n };\n\n /**\n * Check if the store has an event id.\n *\n * @return {bool}\n */\n var hasEventId = function() {\n return eventId !== null;\n };\n\n /**\n * Store the duration (in days) of the event being dragged.\n *\n * @param {int} days Number of days the event spans\n */\n var setDurationDays = function(days) {\n durationDays = days;\n };\n\n /**\n * Get the stored number of days.\n *\n * @return {int|null}\n */\n var getDurationDays = function() {\n return durationDays;\n };\n\n /**\n * Store the minimum timestart valid for an event being dragged.\n *\n * @param {int} timestamp The unix timstamp\n */\n var setMinTimestart = function(timestamp) {\n minTimestart = timestamp;\n };\n\n /**\n * Get the minimum valid timestart.\n *\n * @return {int|null}\n */\n var getMinTimestart = function() {\n return minTimestart;\n };\n\n /**\n * Check if a minimum timestamp is set.\n *\n * @return {bool}\n */\n var hasMinTimestart = function() {\n return minTimestart !== null;\n };\n\n /**\n * Store the maximum timestart valid for an event being dragged.\n *\n * @param {int} timestamp The unix timstamp\n */\n var setMaxTimestart = function(timestamp) {\n maxTimestart = timestamp;\n };\n\n /**\n * Get the maximum valid timestart.\n *\n * @return {int|null}\n */\n var getMaxTimestart = function() {\n return maxTimestart;\n };\n\n /**\n * Check if a maximum timestamp is set.\n *\n * @return {bool}\n */\n var hasMaxTimestart = function() {\n return maxTimestart !== null;\n };\n\n /**\n * Store the error string to display if trying to drag an event\n * earlier than the minimum allowed date.\n *\n * @param {string} message The error message\n */\n var setMinError = function(message) {\n minError = message;\n };\n\n /**\n * Get the error message for a minimum time start violation.\n *\n * @return {string|null}\n */\n var getMinError = function() {\n return minError;\n };\n\n /**\n * Store the error string to display if trying to drag an event\n * later than the maximum allowed date.\n *\n * @param {string} message The error message\n */\n var setMaxError = function(message) {\n maxError = message;\n };\n\n /**\n * Get the error message for a maximum time start violation.\n *\n * @return {string|null}\n */\n var getMaxError = function() {\n return maxError;\n };\n\n /**\n * Reset all of the stored values.\n */\n var clearAll = function() {\n setEventId(null);\n setDurationDays(null);\n setMinTimestart(null);\n setMaxTimestart(null);\n setMinError(null);\n setMaxError(null);\n };\n\n return {\n setEventId: setEventId,\n getEventId: getEventId,\n hasEventId: hasEventId,\n setDurationDays: setDurationDays,\n getDurationDays: getDurationDays,\n setMinTimestart: setMinTimestart,\n getMinTimestart: getMinTimestart,\n hasMinTimestart: hasMinTimestart,\n setMaxTimestart: setMaxTimestart,\n getMaxTimestart: getMaxTimestart,\n hasMaxTimestart: hasMaxTimestart,\n setMinError: setMinError,\n getMinError: getMinError,\n setMaxError: setMaxError,\n getMaxError: getMaxError,\n clearAll: clearAll\n };\n});\n"],"file":"drag_drop_data_store.min.js"}
\ No newline at end of file
+{"version":3,"file":"drag_drop_data_store.min.js","sources":["../src/drag_drop_data_store.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 .\n\n/**\n * A javascript module to store calendar drag and drop data.\n *\n * This module is unfortunately required because of the limitations\n * of the HTML5 drag and drop API and it's ability to provide data\n * between the different stages of the drag/drop lifecycle.\n *\n * @module core_calendar/drag_drop_data_store\n * @copyright 2017 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n /* @var {int|null} eventId The id of the event being dragged */\n var eventId = null;\n /* @var {int|null} durationDays How many days the event spans */\n var durationDays = null;\n /* @var {int|null} minTimestart The earliest valid timestart */\n var minTimestart = null;\n /* @var {int|null} maxTimestart The latest valid tiemstart */\n var maxTimestart = null;\n /* @var {string|null} minError Error message for min timestamp violation */\n var minError = null;\n /* @var {string|null} maxError Error message for max timestamp violation */\n var maxError = null;\n\n /**\n * Store the id of the event being dragged.\n *\n * @param {int} id The event id\n */\n var setEventId = function(id) {\n eventId = id;\n };\n\n /**\n * Get the stored event id.\n *\n * @return {int|null}\n */\n var getEventId = function() {\n return eventId;\n };\n\n /**\n * Check if the store has an event id.\n *\n * @return {bool}\n */\n var hasEventId = function() {\n return eventId !== null;\n };\n\n /**\n * Store the duration (in days) of the event being dragged.\n *\n * @param {int} days Number of days the event spans\n */\n var setDurationDays = function(days) {\n durationDays = days;\n };\n\n /**\n * Get the stored number of days.\n *\n * @return {int|null}\n */\n var getDurationDays = function() {\n return durationDays;\n };\n\n /**\n * Store the minimum timestart valid for an event being dragged.\n *\n * @param {int} timestamp The unix timstamp\n */\n var setMinTimestart = function(timestamp) {\n minTimestart = timestamp;\n };\n\n /**\n * Get the minimum valid timestart.\n *\n * @return {int|null}\n */\n var getMinTimestart = function() {\n return minTimestart;\n };\n\n /**\n * Check if a minimum timestamp is set.\n *\n * @return {bool}\n */\n var hasMinTimestart = function() {\n return minTimestart !== null;\n };\n\n /**\n * Store the maximum timestart valid for an event being dragged.\n *\n * @param {int} timestamp The unix timstamp\n */\n var setMaxTimestart = function(timestamp) {\n maxTimestart = timestamp;\n };\n\n /**\n * Get the maximum valid timestart.\n *\n * @return {int|null}\n */\n var getMaxTimestart = function() {\n return maxTimestart;\n };\n\n /**\n * Check if a maximum timestamp is set.\n *\n * @return {bool}\n */\n var hasMaxTimestart = function() {\n return maxTimestart !== null;\n };\n\n /**\n * Store the error string to display if trying to drag an event\n * earlier than the minimum allowed date.\n *\n * @param {string} message The error message\n */\n var setMinError = function(message) {\n minError = message;\n };\n\n /**\n * Get the error message for a minimum time start violation.\n *\n * @return {string|null}\n */\n var getMinError = function() {\n return minError;\n };\n\n /**\n * Store the error string to display if trying to drag an event\n * later than the maximum allowed date.\n *\n * @param {string} message The error message\n */\n var setMaxError = function(message) {\n maxError = message;\n };\n\n /**\n * Get the error message for a maximum time start violation.\n *\n * @return {string|null}\n */\n var getMaxError = function() {\n return maxError;\n };\n\n /**\n * Reset all of the stored values.\n */\n var clearAll = function() {\n setEventId(null);\n setDurationDays(null);\n setMinTimestart(null);\n setMaxTimestart(null);\n setMinError(null);\n setMaxError(null);\n };\n\n return {\n setEventId: setEventId,\n getEventId: getEventId,\n hasEventId: hasEventId,\n setDurationDays: setDurationDays,\n getDurationDays: getDurationDays,\n setMinTimestart: setMinTimestart,\n getMinTimestart: getMinTimestart,\n hasMinTimestart: hasMinTimestart,\n setMaxTimestart: setMaxTimestart,\n getMaxTimestart: getMaxTimestart,\n hasMaxTimestart: hasMaxTimestart,\n setMinError: setMinError,\n getMinError: getMinError,\n setMaxError: setMaxError,\n getMaxError: getMaxError,\n clearAll: clearAll\n };\n});\n"],"names":["define","eventId","durationDays","minTimestart","maxTimestart","minError","maxError","setEventId","id","setDurationDays","days","setMinTimestart","timestamp","setMaxTimestart","setMinError","message","setMaxError","getEventId","hasEventId","getDurationDays","getMinTimestart","hasMinTimestart","getMaxTimestart","hasMaxTimestart","getMinError","getMaxError","clearAll"],"mappings":";;;;;;;;;;;AA0BAA,4CAAO,IAAI,eAEHC,QAAU,KAEVC,aAAe,KAEfC,aAAe,KAEfC,aAAe,KAEfC,SAAW,KAEXC,SAAW,KAOXC,WAAa,SAASC,IACtBP,QAAUO,IA0BVC,gBAAkB,SAASC,MAC3BR,aAAeQ,MAiBfC,gBAAkB,SAASC,WAC3BT,aAAeS,WA0BfC,gBAAkB,SAASD,WAC3BR,aAAeQ,WA2BfE,YAAc,SAASC,SACvBV,SAAWU,SAkBXC,YAAc,SAASD,SACvBT,SAAWS,eAwBR,CACHR,WAAYA,WACZU,WAzIa,kBACNhB,SAyIPiB,WAjIa,kBACM,OAAZjB,SAiIPQ,gBAAiBA,gBACjBU,gBAjHkB,kBACXjB,cAiHPS,gBAAiBA,gBACjBS,gBAjGkB,kBACXjB,cAiGPkB,gBAzFkB,kBACM,OAAjBlB,cAyFPU,gBAAiBA,gBACjBS,gBAzEkB,kBACXlB,cAyEPmB,gBAjEkB,kBACM,OAAjBnB,cAiEPU,YAAaA,YACbU,YAhDc,kBACPnB,UAgDPW,YAAaA,YACbS,YA/Bc,kBACPnB,UA+BPoB,SAzBW,WACXnB,WAAW,MACXE,gBAAgB,MAChBE,gBAAgB,MAChBE,gBAAgB,MAChBC,YAAY,MACZE,YAAY"}
\ No newline at end of file
diff --git a/calendar/amd/build/event_form.min.js b/calendar/amd/build/event_form.min.js
index 5f3070cca33..401384ed73c 100644
--- a/calendar/amd/build/event_form.min.js
+++ b/calendar/amd/build/event_form.min.js
@@ -1,2 +1,10 @@
-define ("core_calendar/event_form",["jquery","core_calendar/repository"],function(a,b){var c={EVENT_GROUP_COURSE_ID:"[name=\"groupcourseid\"]",EVENT_GROUP_ID:"[name=\"groupid\"]",SELECT_OPTION:"option"},d=function(d){var e=d.find(c.EVENT_GROUP_COURSE_ID),f=function(b){var e=d.find(c.EVENT_GROUP_ID),f=e.find(c.SELECT_OPTION),g=a(b);f.remove();e.prop("disabled",!1);g.each(function(b,c){a(e).append(a("").attr("value",c.id).text(c.name))})};e.on("change",function(){var a=d.find(c.EVENT_GROUP_COURSE_ID).val();b.getCourseGroupsData(a).then(function(a){return f(a)}).catch(Notification.exception)})};return{init:function init(b){var c=a("#"+b);d(c)}}});
-//# sourceMappingURL=event_form.min.js.map
+/**
+ * A javascript module to enhance the event form.
+ *
+ * @module core_calendar/event_form
+ * @copyright 2017 Ryan Wyllie
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/event_form",["jquery","core_calendar/repository"],(function($,CalendarRepository){var SELECTORS_EVENT_GROUP_COURSE_ID='[name="groupcourseid"]',SELECTORS_EVENT_GROUP_ID='[name="groupid"]',SELECTORS_SELECT_OPTION="option",addCourseGroupSelectListeners=function(formElement){var courseGroupSelect=formElement.find(SELECTORS_EVENT_GROUP_COURSE_ID);courseGroupSelect.on("change",(function(){var courseId=formElement.find(SELECTORS_EVENT_GROUP_COURSE_ID).val();CalendarRepository.getCourseGroupsData(courseId).then((function(groups){return function(groups){var groupSelect=formElement.find(SELECTORS_EVENT_GROUP_ID),groupSelectOptions=groupSelect.find(SELECTORS_SELECT_OPTION),courseGroups=$(groups);groupSelectOptions.remove(),groupSelect.prop("disabled",!1),courseGroups.each((function(id,group){$(groupSelect).append($("").attr("value",group.id).text(group.name))}))}(groups)})).catch(Notification.exception)}))};return{init:function(formId){var formElement=$("#"+formId);addCourseGroupSelectListeners(formElement)}}}));
+
+//# sourceMappingURL=event_form.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/event_form.min.js.map b/calendar/amd/build/event_form.min.js.map
index cc0bda06ac3..901d1783599 100644
--- a/calendar/amd/build/event_form.min.js.map
+++ b/calendar/amd/build/event_form.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/event_form.js"],"names":["define","$","CalendarRepository","SELECTORS","EVENT_GROUP_COURSE_ID","EVENT_GROUP_ID","SELECT_OPTION","addCourseGroupSelectListeners","formElement","courseGroupSelect","find","loadGroupSelectOptions","groups","groupSelect","groupSelectOptions","courseGroups","remove","prop","each","id","group","append","attr","text","name","on","courseId","val","getCourseGroupsData","then","catch","Notification","exception","init","formId"],"mappings":"AAsBAA,OAAM,4BAAC,CAAC,QAAD,CAAW,0BAAX,CAAD,CAAyC,SAASC,CAAT,CAAYC,CAAZ,CAAgC,IAEvEC,CAAAA,CAAS,CAAG,CACZC,qBAAqB,CAAE,0BADX,CAEZC,cAAc,CAAE,oBAFJ,CAGZC,aAAa,CAAE,QAHH,CAF2D,CAgBvEC,CAA6B,CAAG,SAASC,CAAT,CAAsB,IAClDC,CAAAA,CAAiB,CAAGD,CAAW,CAACE,IAAZ,CAAiBP,CAAS,CAACC,qBAA3B,CAD8B,CAGlDO,CAAsB,CAAG,SAASC,CAAT,CAAiB,CAC1C,GAAIC,CAAAA,CAAW,CAAGL,CAAW,CAACE,IAAZ,CAAiBP,CAAS,CAACE,cAA3B,CAAlB,CACIS,CAAkB,CAAGD,CAAW,CAACH,IAAZ,CAAiBP,CAAS,CAACG,aAA3B,CADzB,CAEIS,CAAY,CAAGd,CAAC,CAACW,CAAD,CAFpB,CAKAE,CAAkB,CAACE,MAAnB,GACAH,CAAW,CAACI,IAAZ,CAAiB,UAAjB,KACAF,CAAY,CAACG,IAAb,CAAkB,SAASC,CAAT,CAAaC,CAAb,CAAoB,CAClCnB,CAAC,CAACY,CAAD,CAAD,CAAeQ,MAAf,CAAsBpB,CAAC,CAAC,mBAAD,CAAD,CAAuBqB,IAAvB,CAA4B,OAA5B,CAAqCF,CAAK,CAACD,EAA3C,EAA+CI,IAA/C,CAAoDH,CAAK,CAACI,IAA1D,CAAtB,CACH,CAFD,CAGH,CAdqD,CAiBtDf,CAAiB,CAACgB,EAAlB,CAAqB,QAArB,CAA+B,UAAW,CACtC,GAAIC,CAAAA,CAAQ,CAAGlB,CAAW,CAACE,IAAZ,CAAiBP,CAAS,CAACC,qBAA3B,EAAkDuB,GAAlD,EAAf,CACAzB,CAAkB,CAAC0B,mBAAnB,CAAuCF,CAAvC,EACKG,IADL,CACU,SAASjB,CAAT,CAAiB,CACnB,MAAOD,CAAAA,CAAsB,CAACC,CAAD,CAChC,CAHL,EAIKkB,KAJL,CAIWC,YAAY,CAACC,SAJxB,CAKH,CAPD,CAQH,CAzC0E,CAsD3E,MAAO,CACHC,IAAI,CANG,QAAPA,CAAAA,IAAO,CAASC,CAAT,CAAiB,CACxB,GAAI1B,CAAAA,CAAW,CAAGP,CAAC,CAAC,IAAMiC,CAAP,CAAnB,CACA3B,CAA6B,CAACC,CAAD,CAChC,CAEM,CAGV,CAzDK,CAAN","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 .\n\n/**\n * A javascript module to enhance the event form.\n *\n * @module core_calendar/event_form\n * @copyright 2017 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core_calendar/repository'], function($, CalendarRepository) {\n\n var SELECTORS = {\n EVENT_GROUP_COURSE_ID: '[name=\"groupcourseid\"]',\n EVENT_GROUP_ID: '[name=\"groupid\"]',\n SELECT_OPTION: 'option'\n };\n\n /**\n * Listen for when the user changes the group course when configuring\n * a group event and filter the options in the group select to only\n * show the groups available within the course the user has selected.\n *\n * @method addCourseGroupSelectListeners\n * @param {object} formElement The root form element\n */\n var addCourseGroupSelectListeners = function(formElement) {\n var courseGroupSelect = formElement.find(SELECTORS.EVENT_GROUP_COURSE_ID);\n\n var loadGroupSelectOptions = function(groups) {\n var groupSelect = formElement.find(SELECTORS.EVENT_GROUP_ID),\n groupSelectOptions = groupSelect.find(SELECTORS.SELECT_OPTION),\n courseGroups = $(groups);\n\n // Let's clear all options first.\n groupSelectOptions.remove();\n groupSelect.prop(\"disabled\", false);\n courseGroups.each(function(id, group) {\n $(groupSelect).append($(\"\").attr(\"value\", group.id).text(group.name));\n });\n };\n\n // If the user choose a course in the selector do a WS request to get groups.\n courseGroupSelect.on('change', function() {\n var courseId = formElement.find(SELECTORS.EVENT_GROUP_COURSE_ID).val();\n CalendarRepository.getCourseGroupsData(courseId)\n .then(function(groups) {\n return loadGroupSelectOptions(groups);\n })\n .catch(Notification.exception);\n });\n };\n\n /**\n * Initialise all of the form enhancements.\n *\n * @method init\n * @param {string} formId The value of the form's id attribute\n */\n var init = function(formId) {\n var formElement = $('#' + formId);\n addCourseGroupSelectListeners(formElement);\n };\n\n return {\n init: init,\n };\n});\n"],"file":"event_form.min.js"}
\ No newline at end of file
+{"version":3,"file":"event_form.min.js","sources":["../src/event_form.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 .\n\n/**\n * A javascript module to enhance the event form.\n *\n * @module core_calendar/event_form\n * @copyright 2017 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core_calendar/repository'], function($, CalendarRepository) {\n\n var SELECTORS = {\n EVENT_GROUP_COURSE_ID: '[name=\"groupcourseid\"]',\n EVENT_GROUP_ID: '[name=\"groupid\"]',\n SELECT_OPTION: 'option'\n };\n\n /**\n * Listen for when the user changes the group course when configuring\n * a group event and filter the options in the group select to only\n * show the groups available within the course the user has selected.\n *\n * @method addCourseGroupSelectListeners\n * @param {object} formElement The root form element\n */\n var addCourseGroupSelectListeners = function(formElement) {\n var courseGroupSelect = formElement.find(SELECTORS.EVENT_GROUP_COURSE_ID);\n\n var loadGroupSelectOptions = function(groups) {\n var groupSelect = formElement.find(SELECTORS.EVENT_GROUP_ID),\n groupSelectOptions = groupSelect.find(SELECTORS.SELECT_OPTION),\n courseGroups = $(groups);\n\n // Let's clear all options first.\n groupSelectOptions.remove();\n groupSelect.prop(\"disabled\", false);\n courseGroups.each(function(id, group) {\n $(groupSelect).append($(\"\").attr(\"value\", group.id).text(group.name));\n });\n };\n\n // If the user choose a course in the selector do a WS request to get groups.\n courseGroupSelect.on('change', function() {\n var courseId = formElement.find(SELECTORS.EVENT_GROUP_COURSE_ID).val();\n CalendarRepository.getCourseGroupsData(courseId)\n .then(function(groups) {\n return loadGroupSelectOptions(groups);\n })\n .catch(Notification.exception);\n });\n };\n\n /**\n * Initialise all of the form enhancements.\n *\n * @method init\n * @param {string} formId The value of the form's id attribute\n */\n var init = function(formId) {\n var formElement = $('#' + formId);\n addCourseGroupSelectListeners(formElement);\n };\n\n return {\n init: init,\n };\n});\n"],"names":["define","$","CalendarRepository","SELECTORS","addCourseGroupSelectListeners","formElement","courseGroupSelect","find","on","courseId","val","getCourseGroupsData","then","groups","groupSelect","groupSelectOptions","courseGroups","remove","prop","each","id","group","append","attr","text","name","loadGroupSelectOptions","catch","Notification","exception","init","formId"],"mappings":";;;;;;;AAsBAA,kCAAO,CAAC,SAAU,6BAA6B,SAASC,EAAGC,wBAEnDC,gCACuB,yBADvBA,yBAEgB,mBAFhBA,wBAGe,SAWfC,8BAAgC,SAASC,iBACrCC,kBAAoBD,YAAYE,KAAKJ,iCAgBzCG,kBAAkBE,GAAG,UAAU,eACvBC,SAAWJ,YAAYE,KAAKJ,iCAAiCO,MACjER,mBAAmBS,oBAAoBF,UAClCG,MAAK,SAASC,eAjBM,SAASA,YAC9BC,YAAcT,YAAYE,KAAKJ,0BAC/BY,mBAAqBD,YAAYP,KAAKJ,yBACtCa,aAAef,EAAEY,QAGrBE,mBAAmBE,SACnBH,YAAYI,KAAK,YAAY,GAC7BF,aAAaG,MAAK,SAASC,GAAIC,OAC3BpB,EAAEa,aAAaQ,OAAOrB,EAAE,qBAAqBsB,KAAK,QAASF,MAAMD,IAAII,KAAKH,MAAMI,UASrEC,CAAuBb,WAEjCc,MAAMC,aAAaC,qBAezB,CACHC,KANO,SAASC,YACZ1B,YAAcJ,EAAE,IAAM8B,QAC1B3B,8BAA8BC"}
\ No newline at end of file
diff --git a/calendar/amd/build/events.min.js b/calendar/amd/build/events.min.js
index 38ceacbea3e..f1e4bd89da6 100644
--- a/calendar/amd/build/events.min.js
+++ b/calendar/amd/build/events.min.js
@@ -1,2 +1,10 @@
-define ("core_calendar/events",[],function(){return{created:"calendar-events:created",deleted:"calendar-events:deleted",deleteAll:"calendar-events:delete_all",updated:"calendar-events:updated",editEvent:"calendar-events:edit_event",editActionEvent:"calendar-events:edit_action_event",eventMoved:"calendar-events:event_moved",dayChanged:"calendar-events:day_changed",monthChanged:"calendar-events:month_changed",moveEvent:"calendar-events:move_event",filterChanged:"calendar-events:filter_changed",courseChanged:"calendar-events:course_changed",viewUpdated:"calendar-events:view_updated"}});
-//# sourceMappingURL=events.min.js.map
+/**
+ * Contain the events the calendar component can fire.
+ *
+ * @module core_calendar/events
+ * @copyright 2017 Simey Lameze
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/events",[],(function(){return{created:"calendar-events:created",deleted:"calendar-events:deleted",deleteAll:"calendar-events:delete_all",updated:"calendar-events:updated",editEvent:"calendar-events:edit_event",editActionEvent:"calendar-events:edit_action_event",eventMoved:"calendar-events:event_moved",dayChanged:"calendar-events:day_changed",monthChanged:"calendar-events:month_changed",moveEvent:"calendar-events:move_event",filterChanged:"calendar-events:filter_changed",courseChanged:"calendar-events:course_changed",viewUpdated:"calendar-events:view_updated"}}));
+
+//# sourceMappingURL=events.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/events.min.js.map b/calendar/amd/build/events.min.js.map
index d1a10baf980..9f0441077e5 100644
--- a/calendar/amd/build/events.min.js.map
+++ b/calendar/amd/build/events.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/events.js"],"names":["define","created","deleted","deleteAll","updated","editEvent","editActionEvent","eventMoved","dayChanged","monthChanged","moveEvent","filterChanged","courseChanged","viewUpdated"],"mappings":"AAsBAA,OAAM,wBAAC,EAAD,CAAK,UAAW,CAClB,MAAO,CACHC,OAAO,CAAE,yBADN,CAEHC,OAAO,CAAE,yBAFN,CAGHC,SAAS,CAAE,4BAHR,CAIHC,OAAO,CAAE,yBAJN,CAKHC,SAAS,CAAE,4BALR,CAMHC,eAAe,CAAE,mCANd,CAOHC,UAAU,CAAE,6BAPT,CAQHC,UAAU,CAAE,6BART,CASHC,YAAY,CAAE,+BATX,CAUHC,SAAS,CAAE,4BAVR,CAWHC,aAAa,CAAE,gCAXZ,CAYHC,aAAa,CAAE,gCAZZ,CAaHC,WAAW,CAAE,8BAbV,CAeV,CAhBK,CAAN","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 .\n\n/**\n * Contain the events the calendar component can fire.\n *\n * @module core_calendar/events\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n created: 'calendar-events:created',\n deleted: 'calendar-events:deleted',\n deleteAll: 'calendar-events:delete_all',\n updated: 'calendar-events:updated',\n editEvent: 'calendar-events:edit_event',\n editActionEvent: 'calendar-events:edit_action_event',\n eventMoved: 'calendar-events:event_moved',\n dayChanged: 'calendar-events:day_changed',\n monthChanged: 'calendar-events:month_changed',\n moveEvent: 'calendar-events:move_event',\n filterChanged: 'calendar-events:filter_changed',\n courseChanged: 'calendar-events:course_changed',\n viewUpdated: 'calendar-events:view_updated',\n };\n});\n"],"file":"events.min.js"}
\ No newline at end of file
+{"version":3,"file":"events.min.js","sources":["../src/events.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 .\n\n/**\n * Contain the events the calendar component can fire.\n *\n * @module core_calendar/events\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n created: 'calendar-events:created',\n deleted: 'calendar-events:deleted',\n deleteAll: 'calendar-events:delete_all',\n updated: 'calendar-events:updated',\n editEvent: 'calendar-events:edit_event',\n editActionEvent: 'calendar-events:edit_action_event',\n eventMoved: 'calendar-events:event_moved',\n dayChanged: 'calendar-events:day_changed',\n monthChanged: 'calendar-events:month_changed',\n moveEvent: 'calendar-events:move_event',\n filterChanged: 'calendar-events:filter_changed',\n courseChanged: 'calendar-events:course_changed',\n viewUpdated: 'calendar-events:view_updated',\n };\n});\n"],"names":["define","created","deleted","deleteAll","updated","editEvent","editActionEvent","eventMoved","dayChanged","monthChanged","moveEvent","filterChanged","courseChanged","viewUpdated"],"mappings":";;;;;;;AAsBAA,8BAAO,IAAI,iBACA,CACHC,QAAS,0BACTC,QAAS,0BACTC,UAAW,6BACXC,QAAS,0BACTC,UAAW,6BACXC,gBAAiB,oCACjBC,WAAY,8BACZC,WAAY,8BACZC,aAAc,gCACdC,UAAW,6BACXC,cAAe,iCACfC,cAAe,iCACfC,YAAa"}
\ No newline at end of file
diff --git a/calendar/amd/build/export.min.js b/calendar/amd/build/export.min.js
index 16e156dbd93..800216fa6fa 100644
--- a/calendar/amd/build/export.min.js
+++ b/calendar/amd/build/export.min.js
@@ -1,2 +1,11 @@
-define ("core_calendar/export",["exports","core/copy_to_clipboard"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;var b={copyUrlId:"copyexporturl"};a.init=function init(){var a=document.getElementById(b.copyUrlId);a.removeAttribute("disabled");a.focus()}});
-//# sourceMappingURL=export.min.js.map
+define("core_calendar/export",["exports","core/copy_to_clipboard"],(function(_exports,_copy_to_clipboard){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0;
+/**
+ * A javascript module to enhance the calendar export form.
+ *
+ * @module core_calendar/export
+ * @copyright 2021 Jun Pataleta
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+const selectors_copyUrlId="copyexporturl";_exports.init=()=>{const copyUrl=document.getElementById(selectors_copyUrlId);copyUrl.removeAttribute("disabled"),copyUrl.focus()}}));
+
+//# sourceMappingURL=export.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/export.min.js.map b/calendar/amd/build/export.min.js.map
index e5d2c8f4f2b..994ab043961 100644
--- a/calendar/amd/build/export.min.js.map
+++ b/calendar/amd/build/export.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/export.js"],"names":["selectors","copyUrlId","init","copyUrl","document","getElementById","removeAttribute","focus"],"mappings":"+JA8BMA,CAAAA,CAAS,CAAG,CACdC,SAAS,CAAE,eADG,C,QASE,QAAPC,CAAAA,IAAO,EAAM,CAEtB,GAAMC,CAAAA,CAAO,CAAGC,QAAQ,CAACC,cAAT,CAAwBL,CAAS,CAACC,SAAlC,CAAhB,CACAE,CAAO,CAACG,eAAR,CAAwB,UAAxB,EACAH,CAAO,CAACI,KAAR,EACH,C","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 .\n\n/**\n * A javascript module to enhance the calendar export form.\n *\n * @module core_calendar/export\n * @copyright 2021 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport 'core/copy_to_clipboard';\n\n/**\n * Selectors for the calendar export page.\n *\n * @property {string} copyUrlId The element ID of the Copy URL button.\n */\nconst selectors = {\n copyUrlId: 'copyexporturl',\n};\n\n/**\n * Initialises the calendar export JS module.\n *\n * @method init\n */\nexport const init = () => {\n // Enable the copy URL button and focus on it.\n const copyUrl = document.getElementById(selectors.copyUrlId);\n copyUrl.removeAttribute('disabled');\n copyUrl.focus();\n};\n"],"file":"export.min.js"}
\ No newline at end of file
+{"version":3,"file":"export.min.js","sources":["../src/export.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 .\n\n/**\n * A javascript module to enhance the calendar export form.\n *\n * @module core_calendar/export\n * @copyright 2021 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport 'core/copy_to_clipboard';\n\n/**\n * Selectors for the calendar export page.\n *\n * @property {string} copyUrlId The element ID of the Copy URL button.\n */\nconst selectors = {\n copyUrlId: 'copyexporturl',\n};\n\n/**\n * Initialises the calendar export JS module.\n *\n * @method init\n */\nexport const init = () => {\n // Enable the copy URL button and focus on it.\n const copyUrl = document.getElementById(selectors.copyUrlId);\n copyUrl.removeAttribute('disabled');\n copyUrl.focus();\n};\n"],"names":["selectors","copyUrl","document","getElementById","removeAttribute","focus"],"mappings":";;;;;;;;MA8BMA,oBACS,8BAQK,WAEVC,QAAUC,SAASC,eAAeH,qBACxCC,QAAQG,gBAAgB,YACxBH,QAAQI"}
\ No newline at end of file
diff --git a/calendar/amd/build/manage_subscriptions.min.js b/calendar/amd/build/manage_subscriptions.min.js
index e758241bcba..bccc950f25e 100644
--- a/calendar/amd/build/manage_subscriptions.min.js
+++ b/calendar/amd/build/manage_subscriptions.min.js
@@ -1,2 +1,11 @@
-function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core_calendar/manage_subscriptions",["exports","core_calendar/selectors","core_calendar/repository","core/modal_factory","core/modal_events","core/notification","core/prefetch","core/str","core/local/inplace_editable/events"],function(a,b,c,d,e,f,g,h,i){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=k(b);c=k(c);d=k(d);e=k(e);g=function(a){return a&&a.__esModule?a:{default:a}}(g);function j(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;j=function(){return a};return a}function k(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=j();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function l(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 m(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){l(h,d,e,f,g,"next",a)}function g(a){l(h,d,e,f,g,"throw",a)}f(void 0)})}}var n=function(a){return parseInt(a.closest("tr").dataset.subid)},o=function(a){return a.closest("tr").dataset.subname},p=function(a){return document.querySelector("tr[data-subid=\"".concat(a,"\"]"))},q=function(a,b){var c=o(a);return d.create({type:d.types.SAVE_CANCEL,title:(0,h.get_string)("confirmation","admin"),body:(0,h.get_string)(b,"calendar",c),buttons:{save:(0,h.get_string)("yes")}}).then(function(b){b.getRoot().on(e.hidden,function(){a.focus()});b.show();return b})},r=function(){var a=m(regeneratorRuntime.mark(function a(b,c){var d,e,g;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:d=o(b);if(!c.status){a.next=7;break}a.next=4;return(0,h.get_string)("subscriptionremoved","calendar",d);case 4:a.t0=a.sent;a.next=8;break;case 7:a.t0=c.warnings[0].message;case 8:e=a.t0;g=c.status?"info":"error";return a.abrupt("return",(0,f.addNotification)({message:e,type:g}));case 11:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}(),s=function(){document.addEventListener("click",function(a){var d=a.target.closest(b.actions.deleteSubscription);if(d){a.preventDefault();var g=q(d,"confirmsubscriptiondelete");g.then(function(a){a.getRoot().on(e.save,function(){var a=n(d);c.deleteSubscription(a).then(function(b){var c=r(d,b);return c.then(function(){var b=p(a);return b.remove()})}).catch(f.displayException)});return a}).catch(f.displayException)}});document.addEventListener(i.eventTypes.elementUpdated,function(a){var b=a.target;if("core_calendar"==b.getAttribute("data-component")){(0,f.fetchNotifications)()}})},t=function(){g.default.prefetchStrings("moodle",["yes"]);g.default.prefetchStrings("core_admin",["confirmation"]);g.default.prefetchStrings("core_calendar",["confirmsubscriptiondelete","subscriptionremoved"]);s()};a.init=t});
-//# sourceMappingURL=manage_subscriptions.min.js.map
+define("core_calendar/manage_subscriptions",["exports","core_calendar/selectors","core_calendar/repository","core/modal_factory","core/modal_events","core/notification","core/prefetch","core/str","core/local/inplace_editable/events"],(function(_exports,CalendarSelectors,CalendarRepository,Modal,ModalEvents,_notification,_prefetch,_str,_events){var 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}
+/**
+ * A module to handle Delete/Update operations of the manage subscription page.
+ *
+ * @module core_calendar/manage_subscriptions
+ * @copyright 2021 Huong Nguyen
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since 4.0
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,CalendarSelectors=_interopRequireWildcard(CalendarSelectors),CalendarRepository=_interopRequireWildcard(CalendarRepository),Modal=_interopRequireWildcard(Modal),ModalEvents=_interopRequireWildcard(ModalEvents),_prefetch=(obj=_prefetch)&&obj.__esModule?obj:{default:obj};const getSubscriptionName=element=>element.closest("tr").dataset.subname,registerEventListeners=()=>{document.addEventListener("click",(e=>{const deleteAction=e.target.closest(CalendarSelectors.actions.deleteSubscription);if(deleteAction){e.preventDefault();((element,messageCode)=>{const subscriptionName=getSubscriptionName(element);return Modal.create({type:Modal.types.SAVE_CANCEL,title:(0,_str.get_string)("confirmation","admin"),body:(0,_str.get_string)(messageCode,"calendar",subscriptionName),buttons:{save:(0,_str.get_string)("yes")}}).then((modal=>(modal.getRoot().on(ModalEvents.hidden,(()=>{element.focus()})),modal.show(),modal)))})(deleteAction,"confirmsubscriptiondelete").then((modal=>(modal.getRoot().on(ModalEvents.save,(()=>{const subscriptionId=parseInt(deleteAction.closest("tr").dataset.subid);CalendarRepository.deleteSubscription(subscriptionId).then((data=>{const response=(async(element,data)=>{const subscriptionName=getSubscriptionName(element),message=data.status?await(0,_str.get_string)("subscriptionremoved","calendar",subscriptionName):data.warnings[0].message,type=data.status?"info":"error";return(0,_notification.addNotification)({message:message,type:type})})(deleteAction,data);return response.then((()=>{const subscriptionRow=(subscriptionId=>document.querySelector('tr[data-subid="'.concat(subscriptionId,'"]')))(subscriptionId);return subscriptionRow.remove()}))})).catch(_notification.displayException)})),modal))).catch(_notification.displayException)}})),document.addEventListener(_events.eventTypes.elementUpdated,(e=>{"core_calendar"==e.target.getAttribute("data-component")&&(0,_notification.fetchNotifications)()}))};_exports.init=()=>{_prefetch.default.prefetchStrings("moodle",["yes"]),_prefetch.default.prefetchStrings("core_admin",["confirmation"]),_prefetch.default.prefetchStrings("core_calendar",["confirmsubscriptiondelete","subscriptionremoved"]),registerEventListeners()}}));
+
+//# sourceMappingURL=manage_subscriptions.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/manage_subscriptions.min.js.map b/calendar/amd/build/manage_subscriptions.min.js.map
index dc3d8601192..cc6f51151b5 100644
--- a/calendar/amd/build/manage_subscriptions.min.js.map
+++ b/calendar/amd/build/manage_subscriptions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/manage_subscriptions.js"],"names":["getSubscriptionId","element","parseInt","closest","dataset","subid","getSubscriptionName","subname","getSubscriptionRow","subscriptionId","document","querySelector","createModal","messageCode","subscriptionName","Modal","create","type","types","SAVE_CANCEL","title","body","buttons","save","then","modal","getRoot","on","ModalEvents","hidden","focus","show","responseHandlerForDelete","data","status","warnings","message","registerEventListeners","addEventListener","e","deleteAction","target","CalendarSelectors","actions","deleteSubscription","preventDefault","modalPromise","CalendarRepository","response","subscriptionRow","remove","catch","displayException","eventTypes","elementUpdated","inplaceEditable","getAttribute","init","Prefetch","prefetchStrings"],"mappings":"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","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 .\n\n/**\n * A module to handle Delete/Update operations of the manage subscription page.\n *\n * @module core_calendar/manage_subscriptions\n * @copyright 2021 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\n\nimport * as CalendarSelectors from 'core_calendar/selectors';\nimport * as CalendarRepository from 'core_calendar/repository';\nimport * as Modal from 'core/modal_factory';\nimport * as ModalEvents from 'core/modal_events';\nimport {displayException, addNotification, fetchNotifications} from 'core/notification';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\nimport {eventTypes} from 'core/local/inplace_editable/events';\n\n/**\n * Get subscription id for given element.\n *\n * @param {HTMLElement} element update/delete link\n * @return {Number}\n */\nconst getSubscriptionId = element => {\n return parseInt(element.closest('tr').dataset.subid);\n};\n\n/**\n * Get subscription name for given element.\n *\n * @param {HTMLElement} element update/delete link\n * @return {String}\n */\nconst getSubscriptionName = element => {\n return element.closest('tr').dataset.subname;\n};\n\n/**\n * Get subscription table row for subscription id.\n *\n * @param {string} subscriptionId Subscription id\n * @return {Element}\n */\nconst getSubscriptionRow = subscriptionId => {\n return document.querySelector(`tr[data-subid=\"${subscriptionId}\"]`);\n};\n\n/**\n * Create modal.\n *\n * @param {HTMLElement} element\n * @param {string} messageCode Message code.\n * @return {promise} Promise for modal\n */\nconst createModal = (element, messageCode) => {\n const subscriptionName = getSubscriptionName(element);\n return Modal.create({\n type: Modal.types.SAVE_CANCEL,\n title: getString('confirmation', 'admin'),\n body: getString(messageCode, 'calendar', subscriptionName),\n buttons: {\n save: getString('yes')\n },\n }).then(modal => {\n modal.getRoot().on(ModalEvents.hidden, () => {\n element.focus();\n });\n modal.show();\n return modal;\n });\n};\n\n/**\n * Response handler for delete action.\n *\n * @param {HTMLElement} element\n * @param {Object} data\n * @return {Promise}\n */\nconst responseHandlerForDelete = async(element, data) => {\n const subscriptionName = getSubscriptionName(element);\n const message = data.status ? await getString('subscriptionremoved', 'calendar', subscriptionName) : data.warnings[0].message;\n const type = data.status ? 'info' : 'error';\n return addNotification({message, type});\n};\n\n/**\n * Register events for update/delete links.\n */\nconst registerEventListeners = () => {\n document.addEventListener('click', e => {\n const deleteAction = e.target.closest(CalendarSelectors.actions.deleteSubscription);\n if (deleteAction) {\n e.preventDefault();\n const modalPromise = createModal(deleteAction, 'confirmsubscriptiondelete');\n modalPromise.then(modal => {\n modal.getRoot().on(ModalEvents.save, () => {\n const subscriptionId = getSubscriptionId(deleteAction);\n CalendarRepository.deleteSubscription(subscriptionId).then(data => {\n const response = responseHandlerForDelete(deleteAction, data);\n return response.then(() => {\n const subscriptionRow = getSubscriptionRow(subscriptionId);\n return subscriptionRow.remove();\n });\n }).catch(displayException);\n });\n\n return modal;\n }).catch(displayException);\n }\n });\n\n document.addEventListener(eventTypes.elementUpdated, e => {\n const inplaceEditable = e.target;\n if (inplaceEditable.getAttribute('data-component') == 'core_calendar') {\n fetchNotifications();\n }\n });\n};\n\n/**\n * Initialises.\n */\nexport const init = () => {\n Prefetch.prefetchStrings('moodle', ['yes']);\n Prefetch.prefetchStrings('core_admin', ['confirmation']);\n Prefetch.prefetchStrings('core_calendar', ['confirmsubscriptiondelete', 'subscriptionremoved']);\n registerEventListeners();\n};\n"],"file":"manage_subscriptions.min.js"}
\ No newline at end of file
+{"version":3,"file":"manage_subscriptions.min.js","sources":["../src/manage_subscriptions.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 .\n\n/**\n * A module to handle Delete/Update operations of the manage subscription page.\n *\n * @module core_calendar/manage_subscriptions\n * @copyright 2021 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\n\nimport * as CalendarSelectors from 'core_calendar/selectors';\nimport * as CalendarRepository from 'core_calendar/repository';\nimport * as Modal from 'core/modal_factory';\nimport * as ModalEvents from 'core/modal_events';\nimport {displayException, addNotification, fetchNotifications} from 'core/notification';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\nimport {eventTypes} from 'core/local/inplace_editable/events';\n\n/**\n * Get subscription id for given element.\n *\n * @param {HTMLElement} element update/delete link\n * @return {Number}\n */\nconst getSubscriptionId = element => {\n return parseInt(element.closest('tr').dataset.subid);\n};\n\n/**\n * Get subscription name for given element.\n *\n * @param {HTMLElement} element update/delete link\n * @return {String}\n */\nconst getSubscriptionName = element => {\n return element.closest('tr').dataset.subname;\n};\n\n/**\n * Get subscription table row for subscription id.\n *\n * @param {string} subscriptionId Subscription id\n * @return {Element}\n */\nconst getSubscriptionRow = subscriptionId => {\n return document.querySelector(`tr[data-subid=\"${subscriptionId}\"]`);\n};\n\n/**\n * Create modal.\n *\n * @param {HTMLElement} element\n * @param {string} messageCode Message code.\n * @return {promise} Promise for modal\n */\nconst createModal = (element, messageCode) => {\n const subscriptionName = getSubscriptionName(element);\n return Modal.create({\n type: Modal.types.SAVE_CANCEL,\n title: getString('confirmation', 'admin'),\n body: getString(messageCode, 'calendar', subscriptionName),\n buttons: {\n save: getString('yes')\n },\n }).then(modal => {\n modal.getRoot().on(ModalEvents.hidden, () => {\n element.focus();\n });\n modal.show();\n return modal;\n });\n};\n\n/**\n * Response handler for delete action.\n *\n * @param {HTMLElement} element\n * @param {Object} data\n * @return {Promise}\n */\nconst responseHandlerForDelete = async(element, data) => {\n const subscriptionName = getSubscriptionName(element);\n const message = data.status ? await getString('subscriptionremoved', 'calendar', subscriptionName) : data.warnings[0].message;\n const type = data.status ? 'info' : 'error';\n return addNotification({message, type});\n};\n\n/**\n * Register events for update/delete links.\n */\nconst registerEventListeners = () => {\n document.addEventListener('click', e => {\n const deleteAction = e.target.closest(CalendarSelectors.actions.deleteSubscription);\n if (deleteAction) {\n e.preventDefault();\n const modalPromise = createModal(deleteAction, 'confirmsubscriptiondelete');\n modalPromise.then(modal => {\n modal.getRoot().on(ModalEvents.save, () => {\n const subscriptionId = getSubscriptionId(deleteAction);\n CalendarRepository.deleteSubscription(subscriptionId).then(data => {\n const response = responseHandlerForDelete(deleteAction, data);\n return response.then(() => {\n const subscriptionRow = getSubscriptionRow(subscriptionId);\n return subscriptionRow.remove();\n });\n }).catch(displayException);\n });\n\n return modal;\n }).catch(displayException);\n }\n });\n\n document.addEventListener(eventTypes.elementUpdated, e => {\n const inplaceEditable = e.target;\n if (inplaceEditable.getAttribute('data-component') == 'core_calendar') {\n fetchNotifications();\n }\n });\n};\n\n/**\n * Initialises.\n */\nexport const init = () => {\n Prefetch.prefetchStrings('moodle', ['yes']);\n Prefetch.prefetchStrings('core_admin', ['confirmation']);\n Prefetch.prefetchStrings('core_calendar', ['confirmsubscriptiondelete', 'subscriptionremoved']);\n registerEventListeners();\n};\n"],"names":["getSubscriptionName","element","closest","dataset","subname","registerEventListeners","document","addEventListener","e","deleteAction","target","CalendarSelectors","actions","deleteSubscription","preventDefault","messageCode","subscriptionName","Modal","create","type","types","SAVE_CANCEL","title","body","buttons","save","then","modal","getRoot","on","ModalEvents","hidden","focus","show","createModal","subscriptionId","parseInt","subid","CalendarRepository","data","response","async","message","status","warnings","responseHandlerForDelete","subscriptionRow","querySelector","getSubscriptionRow","remove","catch","displayException","eventTypes","elementUpdated","getAttribute","prefetchStrings"],"mappings":";;;;;;;;sWAiDMA,oBAAsBC,SACjBA,QAAQC,QAAQ,MAAMC,QAAQC,QAuDnCC,uBAAyB,KAC3BC,SAASC,iBAAiB,SAASC,UACzBC,aAAeD,EAAEE,OAAOR,QAAQS,kBAAkBC,QAAQC,uBAC5DJ,aAAc,CACdD,EAAEM,iBAvCM,EAACb,QAASc,qBACpBC,iBAAmBhB,oBAAoBC,gBACtCgB,MAAMC,OAAO,CAChBC,KAAMF,MAAMG,MAAMC,YAClBC,OAAO,mBAAU,eAAgB,SACjCC,MAAM,mBAAUR,YAAa,WAAYC,kBACzCQ,QAAS,CACLC,MAAM,mBAAU,UAErBC,MAAKC,QACJA,MAAMC,UAAUC,GAAGC,YAAYC,QAAQ,KACnC9B,QAAQ+B,WAEZL,MAAMM,OACCN,UA0BkBO,CAAYzB,aAAc,6BAClCiB,MAAKC,QACdA,MAAMC,UAAUC,GAAGC,YAAYL,MAAM,WAC3BU,eAzEfC,SAyEkD3B,aAzEjCP,QAAQ,MAAMC,QAAQkC,OA0E9BC,mBAAmBzB,mBAAmBsB,gBAAgBT,MAAKa,aACjDC,SApBGC,OAAMxC,QAASsC,cACtCvB,iBAAmBhB,oBAAoBC,SACvCyC,QAAUH,KAAKI,aAAe,mBAAU,sBAAuB,WAAY3B,kBAAoBuB,KAAKK,SAAS,GAAGF,QAChHvB,KAAOoB,KAAKI,OAAS,OAAS,eAC7B,iCAAgB,CAACD,QAAAA,QAASvB,KAAAA,QAgBI0B,CAAyBpC,aAAc8B,aACjDC,SAASd,MAAK,WACXoB,gBA1DPX,CAAAA,gBAChB7B,SAASyC,uCAAgCZ,sBAyDAa,CAAmBb,uBACpCW,gBAAgBG,eAE5BC,MAAMC,mCAGNxB,SACRuB,MAAMC,oCAIjB7C,SAASC,iBAAiB6C,mBAAWC,gBAAgB7C,IAEK,iBAD9BA,EAAEE,OACN4C,aAAa,4EASrB,uBACPC,gBAAgB,SAAU,CAAC,0BAC3BA,gBAAgB,aAAc,CAAC,mCAC/BA,gBAAgB,gBAAiB,CAAC,4BAA6B,wBACxElD"}
\ No newline at end of file
diff --git a/calendar/amd/build/modal_delete.min.js b/calendar/amd/build/modal_delete.min.js
index 77dbc028a3a..6fc0e83a839 100644
--- a/calendar/amd/build/modal_delete.min.js
+++ b/calendar/amd/build/modal_delete.min.js
@@ -1,2 +1,10 @@
-define ("core_calendar/modal_delete",["jquery","core/notification","core/custom_interaction_events","core/modal","core/modal_events","core/modal_registry","core_calendar/events"],function(a,b,c,d,f,g,h){var i=!1,j={DELETE_ONE_BUTTON:"[data-action=\"deleteone\"]",DELETE_ALL_BUTTON:"[data-action=\"deleteall\"]",CANCEL_BUTTON:"[data-action=\"cancel\"]"},k=function(a){d.call(this,a);this.setRemoveOnClose(!0)};k.TYPE="core_calendar-modal_delete";k.prototype=Object.create(d.prototype);k.prototype.constructor=k;k.prototype.registerEventListeners=function(){d.prototype.registerEventListeners.call(this);this.getModal().on(c.events.activate,j.DELETE_ONE_BUTTON,function(b,c){var d=a.Event(f.save);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this));this.getModal().on(c.events.activate,j.DELETE_ALL_BUTTON,function(b,c){var d=a.Event(h.deleteAll);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this));this.getModal().on(c.events.activate,j.CANCEL_BUTTON,function(b,c){var d=a.Event(f.cancel);this.getRoot().trigger(d,this);if(!d.isDefaultPrevented()){this.hide();c.originalEvent.preventDefault()}}.bind(this))};if(!i){g.register(k.TYPE,k,"calendar/event_delete_modal");i=!0}return k});
-//# sourceMappingURL=modal_delete.min.js.map
+/**
+ * Contain the logic for the delete modal.
+ *
+ * @module core_calendar/modal_delete
+ * @copyright 2017 Andrew Nicols
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/modal_delete",["jquery","core/notification","core/custom_interaction_events","core/modal","core/modal_events","core/modal_registry","core_calendar/events"],(function($,Notification,CustomEvents,Modal,ModalEvents,ModalRegistry,CalendarEvents){var registered=!1,SELECTORS_DELETE_ONE_BUTTON='[data-action="deleteone"]',SELECTORS_DELETE_ALL_BUTTON='[data-action="deleteall"]',SELECTORS_CANCEL_BUTTON='[data-action="cancel"]',ModalDelete=function(root){Modal.call(this,root),this.setRemoveOnClose(!0)};return ModalDelete.TYPE="core_calendar-modal_delete",(ModalDelete.prototype=Object.create(Modal.prototype)).constructor=ModalDelete,ModalDelete.prototype.registerEventListeners=function(){Modal.prototype.registerEventListeners.call(this),this.getModal().on(CustomEvents.events.activate,SELECTORS_DELETE_ONE_BUTTON,function(e,data){var saveEvent=$.Event(ModalEvents.save);this.getRoot().trigger(saveEvent,this),saveEvent.isDefaultPrevented()||(this.hide(),data.originalEvent.preventDefault())}.bind(this)),this.getModal().on(CustomEvents.events.activate,SELECTORS_DELETE_ALL_BUTTON,function(e,data){var saveEvent=$.Event(CalendarEvents.deleteAll);this.getRoot().trigger(saveEvent,this),saveEvent.isDefaultPrevented()||(this.hide(),data.originalEvent.preventDefault())}.bind(this)),this.getModal().on(CustomEvents.events.activate,SELECTORS_CANCEL_BUTTON,function(e,data){var cancelEvent=$.Event(ModalEvents.cancel);this.getRoot().trigger(cancelEvent,this),cancelEvent.isDefaultPrevented()||(this.hide(),data.originalEvent.preventDefault())}.bind(this))},registered||(ModalRegistry.register(ModalDelete.TYPE,ModalDelete,"calendar/event_delete_modal"),registered=!0),ModalDelete}));
+
+//# sourceMappingURL=modal_delete.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/modal_delete.min.js.map b/calendar/amd/build/modal_delete.min.js.map
index 0d14145174b..8aee0d38d16 100644
--- a/calendar/amd/build/modal_delete.min.js.map
+++ b/calendar/amd/build/modal_delete.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/modal_delete.js"],"names":["define","$","Notification","CustomEvents","Modal","ModalEvents","ModalRegistry","CalendarEvents","registered","SELECTORS","DELETE_ONE_BUTTON","DELETE_ALL_BUTTON","CANCEL_BUTTON","ModalDelete","root","call","setRemoveOnClose","TYPE","prototype","Object","create","constructor","registerEventListeners","getModal","on","events","activate","e","data","saveEvent","Event","save","getRoot","trigger","isDefaultPrevented","hide","originalEvent","preventDefault","bind","deleteAll","cancelEvent","cancel","register"],"mappings":"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","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 .\n\n/**\n * Contain the logic for the delete modal.\n *\n * @module core_calendar/modal_delete\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_events',\n 'core/modal_registry',\n 'core_calendar/events',\n],\nfunction(\n $,\n Notification,\n CustomEvents,\n Modal,\n ModalEvents,\n ModalRegistry,\n CalendarEvents\n) {\n\n var registered = false;\n var SELECTORS = {\n DELETE_ONE_BUTTON: '[data-action=\"deleteone\"]',\n DELETE_ALL_BUTTON: '[data-action=\"deleteall\"]',\n CANCEL_BUTTON: '[data-action=\"cancel\"]',\n };\n\n /**\n * Constructor for the Modal.\n *\n * @class\n * @param {object} root The root jQuery element for the modal\n */\n var ModalDelete = function(root) {\n Modal.call(this, root);\n\n this.setRemoveOnClose(true);\n };\n\n ModalDelete.TYPE = 'core_calendar-modal_delete';\n ModalDelete.prototype = Object.create(Modal.prototype);\n ModalDelete.prototype.constructor = ModalDelete;\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n */\n ModalDelete.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.DELETE_ONE_BUTTON, function(e, data) {\n var saveEvent = $.Event(ModalEvents.save);\n this.getRoot().trigger(saveEvent, this);\n\n if (!saveEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.DELETE_ALL_BUTTON, function(e, data) {\n var saveEvent = $.Event(CalendarEvents.deleteAll);\n this.getRoot().trigger(saveEvent, this);\n\n if (!saveEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.CANCEL_BUTTON, function(e, data) {\n var cancelEvent = $.Event(ModalEvents.cancel);\n this.getRoot().trigger(cancelEvent, this);\n\n if (!cancelEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n };\n\n // Automatically register with the modal registry the first time this module is imported so that you can create modals\n // of this type using the modal factory.\n if (!registered) {\n ModalRegistry.register(ModalDelete.TYPE, ModalDelete, 'calendar/event_delete_modal');\n registered = true;\n }\n\n return ModalDelete;\n});\n"],"file":"modal_delete.min.js"}
\ No newline at end of file
+{"version":3,"file":"modal_delete.min.js","sources":["../src/modal_delete.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 .\n\n/**\n * Contain the logic for the delete modal.\n *\n * @module core_calendar/modal_delete\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_events',\n 'core/modal_registry',\n 'core_calendar/events',\n],\nfunction(\n $,\n Notification,\n CustomEvents,\n Modal,\n ModalEvents,\n ModalRegistry,\n CalendarEvents\n) {\n\n var registered = false;\n var SELECTORS = {\n DELETE_ONE_BUTTON: '[data-action=\"deleteone\"]',\n DELETE_ALL_BUTTON: '[data-action=\"deleteall\"]',\n CANCEL_BUTTON: '[data-action=\"cancel\"]',\n };\n\n /**\n * Constructor for the Modal.\n *\n * @class\n * @param {object} root The root jQuery element for the modal\n */\n var ModalDelete = function(root) {\n Modal.call(this, root);\n\n this.setRemoveOnClose(true);\n };\n\n ModalDelete.TYPE = 'core_calendar-modal_delete';\n ModalDelete.prototype = Object.create(Modal.prototype);\n ModalDelete.prototype.constructor = ModalDelete;\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n */\n ModalDelete.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.DELETE_ONE_BUTTON, function(e, data) {\n var saveEvent = $.Event(ModalEvents.save);\n this.getRoot().trigger(saveEvent, this);\n\n if (!saveEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.DELETE_ALL_BUTTON, function(e, data) {\n var saveEvent = $.Event(CalendarEvents.deleteAll);\n this.getRoot().trigger(saveEvent, this);\n\n if (!saveEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n\n this.getModal().on(CustomEvents.events.activate, SELECTORS.CANCEL_BUTTON, function(e, data) {\n var cancelEvent = $.Event(ModalEvents.cancel);\n this.getRoot().trigger(cancelEvent, this);\n\n if (!cancelEvent.isDefaultPrevented()) {\n this.hide();\n data.originalEvent.preventDefault();\n }\n }.bind(this));\n };\n\n // Automatically register with the modal registry the first time this module is imported so that you can create modals\n // of this type using the modal factory.\n if (!registered) {\n ModalRegistry.register(ModalDelete.TYPE, ModalDelete, 'calendar/event_delete_modal');\n registered = true;\n }\n\n return ModalDelete;\n});\n"],"names":["define","$","Notification","CustomEvents","Modal","ModalEvents","ModalRegistry","CalendarEvents","registered","SELECTORS","ModalDelete","root","call","this","setRemoveOnClose","TYPE","prototype","Object","create","constructor","registerEventListeners","getModal","on","events","activate","e","data","saveEvent","Event","save","getRoot","trigger","isDefaultPrevented","hide","originalEvent","preventDefault","bind","deleteAll","cancelEvent","cancel","register"],"mappings":";;;;;;;AAsBAA,oCAAO,CACH,SACA,oBACA,iCACA,aACA,oBACA,sBACA,yBAEJ,SACIC,EACAC,aACAC,aACAC,MACAC,YACAC,cACAC,oBAGIC,YAAa,EACbC,4BACmB,4BADnBA,4BAEmB,4BAFnBA,wBAGe,yBASfC,YAAc,SAASC,MACvBP,MAAMQ,KAAKC,KAAMF,WAEZG,kBAAiB,WAG1BJ,YAAYK,KAAO,8BACnBL,YAAYM,UAAYC,OAAOC,OAAOd,MAAMY,YACtBG,YAAcT,YAOpCA,YAAYM,UAAUI,uBAAyB,WAE3ChB,MAAMY,UAAUI,uBAAuBR,KAAKC,WAEvCQ,WAAWC,GAAGnB,aAAaoB,OAAOC,SAAUf,4BAA6B,SAASgB,EAAGC,UAClFC,UAAY1B,EAAE2B,MAAMvB,YAAYwB,WAC/BC,UAAUC,QAAQJ,UAAWd,MAE7Bc,UAAUK,4BACNC,OACLP,KAAKQ,cAAcC,mBAEzBC,KAAKvB,YAEFQ,WAAWC,GAAGnB,aAAaoB,OAAOC,SAAUf,4BAA6B,SAASgB,EAAGC,UAClFC,UAAY1B,EAAE2B,MAAMrB,eAAe8B,gBAClCP,UAAUC,QAAQJ,UAAWd,MAE7Bc,UAAUK,4BACNC,OACLP,KAAKQ,cAAcC,mBAEzBC,KAAKvB,YAEFQ,WAAWC,GAAGnB,aAAaoB,OAAOC,SAAUf,wBAAyB,SAASgB,EAAGC,UAC9EY,YAAcrC,EAAE2B,MAAMvB,YAAYkC,aACjCT,UAAUC,QAAQO,YAAazB,MAE/ByB,YAAYN,4BACRC,OACLP,KAAKQ,cAAcC,mBAEzBC,KAAKvB,QAKNL,aACDF,cAAckC,SAAS9B,YAAYK,KAAML,YAAa,+BACtDF,YAAa,GAGVE"}
\ No newline at end of file
diff --git a/calendar/amd/build/modal_event_form.min.js b/calendar/amd/build/modal_event_form.min.js
index 1e89f7f1131..b9cf446f6b6 100644
--- a/calendar/amd/build/modal_event_form.min.js
+++ b/calendar/amd/build/modal_event_form.min.js
@@ -1,2 +1,10 @@
-define ("core_calendar/modal_event_form",["jquery","core_form/events","core/str","core/notification","core/templates","core/custom_interaction_events","core/modal","core/modal_registry","core/fragment","core_calendar/events","core_calendar/repository"],function(a,b,c,d,e,f,g,h,i,j,k){var l=!1,m={SAVE_BUTTON:"[data-action=\"save\"]",LOADING_ICON_CONTAINER:"[data-region=\"loading-icon-container\"]"},n=function(a){g.call(this,a);this.eventId=null;this.startTime=null;this.courseId=null;this.categoryId=null;this.contextId=null;this.reloadingBody=!1;this.reloadingTitle=!1;this.saveButton=this.getFooter().find(m.SAVE_BUTTON)};n.TYPE="core_calendar-modal_event_form";n.prototype=Object.create(g.prototype);n.prototype.constructor=n;n.prototype.setContextId=function(a){this.contextId=a};n.prototype.getContextId=function(){return this.contextId};n.prototype.setCourseId=function(a){this.courseId=a};n.prototype.getCourseId=function(){return this.courseId};n.prototype.setCategoryId=function(a){this.categoryId=a};n.prototype.getCategoryId=function(){return this.categoryId};n.prototype.hasCourseId=function(){return null!==this.courseId};n.prototype.hasCategoryId=function(){return null!==this.categoryId};n.prototype.setEventId=function(a){this.eventId=a};n.prototype.getEventId=function(){return this.eventId};n.prototype.hasEventId=function(){return null!==this.eventId};n.prototype.setStartTime=function(a){this.startTime=a};n.prototype.getStartTime=function(){return this.startTime};n.prototype.hasStartTime=function(){return null!==this.startTime};n.prototype.getForm=function(){return this.getBody().find("form")};n.prototype.disableButtons=function(){this.saveButton.prop("disabled",!0)};n.prototype.enableButtons=function(){this.saveButton.prop("disabled",!1)};n.prototype.reloadTitleContent=function(){if(this.reloadingTitle){return this.titlePromise}this.reloadingTitle=!0;if(this.hasEventId()){this.titlePromise=c.get_string("editevent","calendar")}else{this.titlePromise=c.get_string("newevent","calendar")}this.titlePromise.then(function(a){this.setTitle(a);return a}.bind(this)).always(function(){this.reloadingTitle=!1}.bind(this)).fail(d.exception);return this.titlePromise};n.prototype.reloadBodyContent=function(a){if(this.reloadingBody){return this.bodyPromise}this.reloadingBody=!0;this.disableButtons();var b={};if(this.hasEventId()){b.eventid=this.getEventId()}if(this.hasStartTime()){b.starttime=this.getStartTime()}if(this.hasCourseId()){b.courseid=this.getCourseId()}if(this.hasCategoryId()){b.categoryid=this.getCategoryId()}if("undefined"!=typeof a){b.formdata=a}this.bodyPromise=i.loadFragment("calendar","event_form",this.getContextId(),b);this.setBody(this.bodyPromise);this.bodyPromise.then(function(){this.enableButtons()}.bind(this)).fail(d.exception).always(function(){this.reloadingBody=!1}.bind(this)).fail(d.exception);return this.bodyPromise};n.prototype.reloadAllContent=function(){return a.when(this.reloadTitleContent(),this.reloadBodyContent())};n.prototype.show=function(){this.reloadAllContent();g.prototype.show.call(this)};n.prototype.hide=function(){g.prototype.hide.call(this);this.setEventId(null);this.setStartTime(null);this.setCourseId(null);this.setCategoryId(null)};n.prototype.getFormData=function(){return this.getForm().serialize()};n.prototype.save=function(){var b,c=this.saveButton.find(m.LOADING_ICON_CONTAINER);b=this.getForm().find("[aria-invalid=\"true\"]");if(b.length){b.first().focus();return Promise.resolve()}c.removeClass("hidden");this.disableButtons();var e=this.getFormData();return k.submitCreateUpdateForm(e).then(function(b){if(b.validationerror){this.reloadBodyContent(e)}else{var c=this.hasEventId();this.hide();if(c){a("body").trigger(j.updated,[b.event])}else{a("body").trigger(j.created,[b.event])}}}.bind(this)).always(function(){c.addClass("hidden");this.enableButtons()}.bind(this)).fail(d.exception)};n.prototype.registerEventListeners=function(){g.prototype.registerEventListeners.call(this);this.getModal().on(f.events.activate,m.SAVE_BUTTON,function(a,b){this.getForm().submit();b.originalEvent.preventDefault();a.stopPropagation()}.bind(this));this.getModal().on("submit",function(a){b.notifyFormSubmittedByJavascript(this.getForm()[0]);this.save();a.preventDefault();a.stopPropagation()}.bind(this))};if(!l){h.register(n.TYPE,n,"calendar/modal_event_form");l=!0}return n});
-//# sourceMappingURL=modal_event_form.min.js.map
+/**
+ * Contain the logic for the quick add or update event modal.
+ *
+ * @module core_calendar/modal_quick_add_event
+ * @copyright 2017 Ryan Wyllie
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/modal_event_form",["jquery","core_form/events","core/str","core/notification","core/templates","core/custom_interaction_events","core/modal","core/modal_registry","core/fragment","core_calendar/events","core_calendar/repository"],(function($,FormEvents,Str,Notification,Templates,CustomEvents,Modal,ModalRegistry,Fragment,CalendarEvents,Repository){var registered=!1,SELECTORS_SAVE_BUTTON='[data-action="save"]',SELECTORS_LOADING_ICON_CONTAINER='[data-region="loading-icon-container"]',ModalEventForm=function(root){Modal.call(this,root),this.eventId=null,this.startTime=null,this.courseId=null,this.categoryId=null,this.contextId=null,this.reloadingBody=!1,this.reloadingTitle=!1,this.saveButton=this.getFooter().find(SELECTORS_SAVE_BUTTON)};return ModalEventForm.TYPE="core_calendar-modal_event_form",(ModalEventForm.prototype=Object.create(Modal.prototype)).constructor=ModalEventForm,ModalEventForm.prototype.setContextId=function(id){this.contextId=id},ModalEventForm.prototype.getContextId=function(){return this.contextId},ModalEventForm.prototype.setCourseId=function(id){this.courseId=id},ModalEventForm.prototype.getCourseId=function(){return this.courseId},ModalEventForm.prototype.setCategoryId=function(id){this.categoryId=id},ModalEventForm.prototype.getCategoryId=function(){return this.categoryId},ModalEventForm.prototype.hasCourseId=function(){return null!==this.courseId},ModalEventForm.prototype.hasCategoryId=function(){return null!==this.categoryId},ModalEventForm.prototype.setEventId=function(id){this.eventId=id},ModalEventForm.prototype.getEventId=function(){return this.eventId},ModalEventForm.prototype.hasEventId=function(){return null!==this.eventId},ModalEventForm.prototype.setStartTime=function(time){this.startTime=time},ModalEventForm.prototype.getStartTime=function(){return this.startTime},ModalEventForm.prototype.hasStartTime=function(){return null!==this.startTime},ModalEventForm.prototype.getForm=function(){return this.getBody().find("form")},ModalEventForm.prototype.disableButtons=function(){this.saveButton.prop("disabled",!0)},ModalEventForm.prototype.enableButtons=function(){this.saveButton.prop("disabled",!1)},ModalEventForm.prototype.reloadTitleContent=function(){return this.reloadingTitle||(this.reloadingTitle=!0,this.hasEventId()?this.titlePromise=Str.get_string("editevent","calendar"):this.titlePromise=Str.get_string("newevent","calendar"),this.titlePromise.then(function(string){return this.setTitle(string),string}.bind(this)).always(function(){this.reloadingTitle=!1}.bind(this)).fail(Notification.exception)),this.titlePromise},ModalEventForm.prototype.reloadBodyContent=function(formData){if(this.reloadingBody)return this.bodyPromise;this.reloadingBody=!0,this.disableButtons();var args={};return this.hasEventId()&&(args.eventid=this.getEventId()),this.hasStartTime()&&(args.starttime=this.getStartTime()),this.hasCourseId()&&(args.courseid=this.getCourseId()),this.hasCategoryId()&&(args.categoryid=this.getCategoryId()),void 0!==formData&&(args.formdata=formData),this.bodyPromise=Fragment.loadFragment("calendar","event_form",this.getContextId(),args),this.setBody(this.bodyPromise),this.bodyPromise.then(function(){this.enableButtons()}.bind(this)).fail(Notification.exception).always(function(){this.reloadingBody=!1}.bind(this)).fail(Notification.exception),this.bodyPromise},ModalEventForm.prototype.reloadAllContent=function(){return $.when(this.reloadTitleContent(),this.reloadBodyContent())},ModalEventForm.prototype.show=function(){this.reloadAllContent(),Modal.prototype.show.call(this)},ModalEventForm.prototype.hide=function(){Modal.prototype.hide.call(this),this.setEventId(null),this.setStartTime(null),this.setCourseId(null),this.setCategoryId(null)},ModalEventForm.prototype.getFormData=function(){return this.getForm().serialize()},ModalEventForm.prototype.save=function(){var invalid,loadingContainer=this.saveButton.find(SELECTORS_LOADING_ICON_CONTAINER);if((invalid=this.getForm().find('[aria-invalid="true"]')).length)return invalid.first().focus(),Promise.resolve();loadingContainer.removeClass("hidden"),this.disableButtons();var formData=this.getFormData();return Repository.submitCreateUpdateForm(formData).then(function(response){if(response.validationerror)this.reloadBodyContent(formData);else{var isExisting=this.hasEventId();this.hide(),isExisting?$("body").trigger(CalendarEvents.updated,[response.event]):$("body").trigger(CalendarEvents.created,[response.event])}}.bind(this)).always(function(){loadingContainer.addClass("hidden"),this.enableButtons()}.bind(this)).fail(Notification.exception)},ModalEventForm.prototype.registerEventListeners=function(){Modal.prototype.registerEventListeners.call(this),this.getModal().on(CustomEvents.events.activate,SELECTORS_SAVE_BUTTON,function(e,data){this.getForm().submit(),data.originalEvent.preventDefault(),e.stopPropagation()}.bind(this)),this.getModal().on("submit",function(e){FormEvents.notifyFormSubmittedByJavascript(this.getForm()[0]),this.save(),e.preventDefault(),e.stopPropagation()}.bind(this))},registered||(ModalRegistry.register(ModalEventForm.TYPE,ModalEventForm,"calendar/modal_event_form"),registered=!0),ModalEventForm}));
+
+//# sourceMappingURL=modal_event_form.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/modal_event_form.min.js.map b/calendar/amd/build/modal_event_form.min.js.map
index cfbeb62f908..e0b9e917c2e 100644
--- a/calendar/amd/build/modal_event_form.min.js.map
+++ b/calendar/amd/build/modal_event_form.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/modal_event_form.js"],"names":["define","$","FormEvents","Str","Notification","Templates","CustomEvents","Modal","ModalRegistry","Fragment","CalendarEvents","Repository","registered","SELECTORS","SAVE_BUTTON","LOADING_ICON_CONTAINER","ModalEventForm","root","call","eventId","startTime","courseId","categoryId","contextId","reloadingBody","reloadingTitle","saveButton","getFooter","find","TYPE","prototype","Object","create","constructor","setContextId","id","getContextId","setCourseId","getCourseId","setCategoryId","getCategoryId","hasCourseId","hasCategoryId","setEventId","getEventId","hasEventId","setStartTime","time","getStartTime","hasStartTime","getForm","getBody","disableButtons","prop","enableButtons","reloadTitleContent","titlePromise","get_string","then","string","setTitle","bind","always","fail","exception","reloadBodyContent","formData","bodyPromise","args","eventid","starttime","courseid","categoryid","formdata","loadFragment","setBody","reloadAllContent","when","show","hide","getFormData","serialize","save","invalid","loadingContainer","length","first","focus","Promise","resolve","removeClass","submitCreateUpdateForm","response","validationerror","isExisting","trigger","updated","event","created","addClass","registerEventListeners","getModal","on","events","activate","e","data","submit","originalEvent","preventDefault","stopPropagation","notifyFormSubmittedByJavascript","register"],"mappings":"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","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 .\n\n/**\n * Contain the logic for the quick add or update event modal.\n *\n * @module core_calendar/modal_quick_add_event\n * @copyright 2017 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core_form/events',\n 'core/str',\n 'core/notification',\n 'core/templates',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_registry',\n 'core/fragment',\n 'core_calendar/events',\n 'core_calendar/repository'\n],\nfunction(\n $,\n FormEvents,\n Str,\n Notification,\n Templates,\n CustomEvents,\n Modal,\n ModalRegistry,\n Fragment,\n CalendarEvents,\n Repository\n) {\n var registered = false;\n var SELECTORS = {\n SAVE_BUTTON: '[data-action=\"save\"]',\n LOADING_ICON_CONTAINER: '[data-region=\"loading-icon-container\"]',\n };\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var ModalEventForm = function(root) {\n Modal.call(this, root);\n this.eventId = null;\n this.startTime = null;\n this.courseId = null;\n this.categoryId = null;\n this.contextId = null;\n this.reloadingBody = false;\n this.reloadingTitle = false;\n this.saveButton = this.getFooter().find(SELECTORS.SAVE_BUTTON);\n };\n\n ModalEventForm.TYPE = 'core_calendar-modal_event_form';\n ModalEventForm.prototype = Object.create(Modal.prototype);\n ModalEventForm.prototype.constructor = ModalEventForm;\n\n /**\n * Set the context id to the given value.\n *\n * @method setContextId\n * @param {Number} id The event id\n */\n ModalEventForm.prototype.setContextId = function(id) {\n this.contextId = id;\n };\n\n /**\n * Retrieve the current context id, if any.\n *\n * @method getContextId\n * @return {Number|null} The event id\n */\n ModalEventForm.prototype.getContextId = function() {\n return this.contextId;\n };\n\n /**\n * Set the course id to the given value.\n *\n * @method setCourseId\n * @param {int} id The event id\n */\n ModalEventForm.prototype.setCourseId = function(id) {\n this.courseId = id;\n };\n\n /**\n * Retrieve the current course id, if any.\n *\n * @method getCourseId\n * @return {int|null} The event id\n */\n ModalEventForm.prototype.getCourseId = function() {\n return this.courseId;\n };\n\n /**\n * Set the category id to the given value.\n *\n * @method setCategoryId\n * @param {int} id The event id\n */\n ModalEventForm.prototype.setCategoryId = function(id) {\n this.categoryId = id;\n };\n\n /**\n * Retrieve the current category id, if any.\n *\n * @method getCategoryId\n * @return {int|null} The event id\n */\n ModalEventForm.prototype.getCategoryId = function() {\n return this.categoryId;\n };\n\n /**\n * Check if the modal has an course id.\n *\n * @method hasCourseId\n * @return {bool}\n */\n ModalEventForm.prototype.hasCourseId = function() {\n return this.courseId !== null;\n };\n\n /**\n * Check if the modal has an category id.\n *\n * @method hasCategoryId\n * @return {bool}\n */\n ModalEventForm.prototype.hasCategoryId = function() {\n return this.categoryId !== null;\n };\n\n /**\n * Set the event id to the given value.\n *\n * @method setEventId\n * @param {int} id The event id\n */\n ModalEventForm.prototype.setEventId = function(id) {\n this.eventId = id;\n };\n\n /**\n * Retrieve the current event id, if any.\n *\n * @method getEventId\n * @return {int|null} The event id\n */\n ModalEventForm.prototype.getEventId = function() {\n return this.eventId;\n };\n\n /**\n * Check if the modal has an event id.\n *\n * @method hasEventId\n * @return {bool}\n */\n ModalEventForm.prototype.hasEventId = function() {\n return this.eventId !== null;\n };\n\n /**\n * Set the start time to the given value.\n *\n * @method setStartTime\n * @param {int} time The start time\n */\n ModalEventForm.prototype.setStartTime = function(time) {\n this.startTime = time;\n };\n\n /**\n * Retrieve the current start time, if any.\n *\n * @method getStartTime\n * @return {int|null} The start time\n */\n ModalEventForm.prototype.getStartTime = function() {\n return this.startTime;\n };\n\n /**\n * Check if the modal has start time.\n *\n * @method hasStartTime\n * @return {bool}\n */\n ModalEventForm.prototype.hasStartTime = function() {\n return this.startTime !== null;\n };\n\n /**\n * Get the form element from the modal.\n *\n * @method getForm\n * @return {object}\n */\n ModalEventForm.prototype.getForm = function() {\n return this.getBody().find('form');\n };\n\n /**\n * Disable the buttons in the footer.\n *\n * @method disableButtons\n */\n ModalEventForm.prototype.disableButtons = function() {\n this.saveButton.prop('disabled', true);\n };\n\n /**\n * Enable the buttons in the footer.\n *\n * @method enableButtons\n */\n ModalEventForm.prototype.enableButtons = function() {\n this.saveButton.prop('disabled', false);\n };\n\n /**\n * Reload the title for the modal to the appropriate value\n * depending on whether we are creating a new event or\n * editing an existing event.\n *\n * @method reloadTitleContent\n * @return {object} A promise resolved with the new title text\n */\n ModalEventForm.prototype.reloadTitleContent = function() {\n if (this.reloadingTitle) {\n return this.titlePromise;\n }\n\n this.reloadingTitle = true;\n\n if (this.hasEventId()) {\n this.titlePromise = Str.get_string('editevent', 'calendar');\n } else {\n this.titlePromise = Str.get_string('newevent', 'calendar');\n }\n\n this.titlePromise.then(function(string) {\n this.setTitle(string);\n return string;\n }.bind(this))\n .always(function() {\n this.reloadingTitle = false;\n return;\n }.bind(this))\n .fail(Notification.exception);\n\n return this.titlePromise;\n };\n\n /**\n * Send a request to the server to get the event_form in a fragment\n * and render the result in the body of the modal.\n *\n * If serialised form data is provided then it will be sent in the\n * request to the server to have the form rendered with the data. This\n * is used when the form had a server side error and we need the server\n * to re-render it for us to display the error to the user.\n *\n * @method reloadBodyContent\n * @param {string} formData The serialised form data\n * @return {object} A promise resolved with the fragment html and js from\n */\n ModalEventForm.prototype.reloadBodyContent = function(formData) {\n if (this.reloadingBody) {\n return this.bodyPromise;\n }\n\n this.reloadingBody = true;\n this.disableButtons();\n\n var args = {};\n\n if (this.hasEventId()) {\n args.eventid = this.getEventId();\n }\n\n if (this.hasStartTime()) {\n args.starttime = this.getStartTime();\n }\n\n if (this.hasCourseId()) {\n args.courseid = this.getCourseId();\n }\n\n if (this.hasCategoryId()) {\n args.categoryid = this.getCategoryId();\n }\n\n if (typeof formData !== 'undefined') {\n args.formdata = formData;\n }\n\n this.bodyPromise = Fragment.loadFragment('calendar', 'event_form', this.getContextId(), args);\n\n this.setBody(this.bodyPromise);\n\n this.bodyPromise.then(function() {\n this.enableButtons();\n return;\n }.bind(this))\n .fail(Notification.exception)\n .always(function() {\n this.reloadingBody = false;\n return;\n }.bind(this))\n .fail(Notification.exception);\n\n return this.bodyPromise;\n };\n\n /**\n * Reload both the title and body content.\n *\n * @method reloadAllContent\n * @return {object} promise\n */\n ModalEventForm.prototype.reloadAllContent = function() {\n return $.when(this.reloadTitleContent(), this.reloadBodyContent());\n };\n\n /**\n * Kick off a reload the modal content before showing it. This\n * is to allow us to re-use the same modal for creating and\n * editing different events within the page.\n *\n * We do the reload when showing the modal rather than hiding it\n * to save a request to the server if the user closes the modal\n * and never re-opens it.\n *\n * @method show\n */\n ModalEventForm.prototype.show = function() {\n this.reloadAllContent();\n Modal.prototype.show.call(this);\n };\n\n /**\n * Clear the event id from the modal when it's closed so\n * that it is loaded fresh next time it's displayed.\n *\n * The event id will be set by the calling code if it wants\n * to edit a specific event.\n *\n * @method hide\n */\n ModalEventForm.prototype.hide = function() {\n Modal.prototype.hide.call(this);\n this.setEventId(null);\n this.setStartTime(null);\n this.setCourseId(null);\n this.setCategoryId(null);\n };\n\n /**\n * Get the serialised form data.\n *\n * @method getFormData\n * @return {string} serialised form data\n */\n ModalEventForm.prototype.getFormData = function() {\n return this.getForm().serialize();\n };\n\n /**\n * Send the form data to the server to create or update\n * an event.\n *\n * If there is a server side validation error then we re-request the\n * rendered form (with the data) from the server in order to get the\n * server side errors to display.\n *\n * On success the modal is hidden and the page is reloaded so that the\n * new event will display.\n *\n * @method save\n * @return {object} A promise\n */\n ModalEventForm.prototype.save = function() {\n var invalid,\n loadingContainer = this.saveButton.find(SELECTORS.LOADING_ICON_CONTAINER);\n\n // Now the change events have run, see if there are any \"invalid\" form fields.\n invalid = this.getForm().find('[aria-invalid=\"true\"]');\n\n // If we found invalid fields, focus on the first one and do not submit via ajax.\n if (invalid.length) {\n invalid.first().focus();\n return Promise.resolve();\n }\n\n loadingContainer.removeClass('hidden');\n this.disableButtons();\n\n var formData = this.getFormData();\n // Send the form data to the server for processing.\n return Repository.submitCreateUpdateForm(formData)\n .then(function(response) {\n if (response.validationerror) {\n // If there was a server side validation error then\n // we need to re-request the rendered form from the server\n // in order to display the error for the user.\n this.reloadBodyContent(formData);\n return;\n } else {\n // Check whether this was a new event or not.\n // The hide function unsets the form data so grab this before the hide.\n var isExisting = this.hasEventId();\n\n // No problemo! Our work here is done.\n this.hide();\n\n // Trigger the appropriate calendar event so that the view can be updated.\n if (isExisting) {\n $('body').trigger(CalendarEvents.updated, [response.event]);\n } else {\n $('body').trigger(CalendarEvents.created, [response.event]);\n }\n }\n\n return;\n }.bind(this))\n .always(function() {\n // Regardless of success or error we should always stop\n // the loading icon and re-enable the buttons.\n loadingContainer.addClass('hidden');\n this.enableButtons();\n\n return;\n }.bind(this))\n .fail(Notification.exception);\n };\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n * @fires event:uploadStarted\n * @fires event:formSubmittedByJavascript\n */\n ModalEventForm.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n // When the user clicks the save button we trigger the form submission. We need to\n // trigger an actual submission because there is some JS code in the form that is\n // listening for this event and doing some stuff (e.g. saving draft areas etc).\n this.getModal().on(CustomEvents.events.activate, SELECTORS.SAVE_BUTTON, function(e, data) {\n this.getForm().submit();\n data.originalEvent.preventDefault();\n e.stopPropagation();\n }.bind(this));\n\n // Catch the submit event before it is actually processed by the browser and\n // prevent the submission. We'll take it from here.\n this.getModal().on('submit', function(e) {\n FormEvents.notifyFormSubmittedByJavascript(this.getForm()[0]);\n\n this.save();\n\n // Stop the form from actually submitting and prevent it's\n // propagation because we have already handled the event.\n e.preventDefault();\n e.stopPropagation();\n }.bind(this));\n };\n\n // Automatically register with the modal registry the first time this module is imported so that you can create modals\n // of this type using the modal factory.\n if (!registered) {\n ModalRegistry.register(ModalEventForm.TYPE, ModalEventForm, 'calendar/modal_event_form');\n registered = true;\n }\n\n return ModalEventForm;\n});\n"],"file":"modal_event_form.min.js"}
\ No newline at end of file
+{"version":3,"file":"modal_event_form.min.js","sources":["../src/modal_event_form.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 .\n\n/**\n * Contain the logic for the quick add or update event modal.\n *\n * @module core_calendar/modal_quick_add_event\n * @copyright 2017 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core_form/events',\n 'core/str',\n 'core/notification',\n 'core/templates',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_registry',\n 'core/fragment',\n 'core_calendar/events',\n 'core_calendar/repository'\n],\nfunction(\n $,\n FormEvents,\n Str,\n Notification,\n Templates,\n CustomEvents,\n Modal,\n ModalRegistry,\n Fragment,\n CalendarEvents,\n Repository\n) {\n var registered = false;\n var SELECTORS = {\n SAVE_BUTTON: '[data-action=\"save\"]',\n LOADING_ICON_CONTAINER: '[data-region=\"loading-icon-container\"]',\n };\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var ModalEventForm = function(root) {\n Modal.call(this, root);\n this.eventId = null;\n this.startTime = null;\n this.courseId = null;\n this.categoryId = null;\n this.contextId = null;\n this.reloadingBody = false;\n this.reloadingTitle = false;\n this.saveButton = this.getFooter().find(SELECTORS.SAVE_BUTTON);\n };\n\n ModalEventForm.TYPE = 'core_calendar-modal_event_form';\n ModalEventForm.prototype = Object.create(Modal.prototype);\n ModalEventForm.prototype.constructor = ModalEventForm;\n\n /**\n * Set the context id to the given value.\n *\n * @method setContextId\n * @param {Number} id The event id\n */\n ModalEventForm.prototype.setContextId = function(id) {\n this.contextId = id;\n };\n\n /**\n * Retrieve the current context id, if any.\n *\n * @method getContextId\n * @return {Number|null} The event id\n */\n ModalEventForm.prototype.getContextId = function() {\n return this.contextId;\n };\n\n /**\n * Set the course id to the given value.\n *\n * @method setCourseId\n * @param {int} id The event id\n */\n ModalEventForm.prototype.setCourseId = function(id) {\n this.courseId = id;\n };\n\n /**\n * Retrieve the current course id, if any.\n *\n * @method getCourseId\n * @return {int|null} The event id\n */\n ModalEventForm.prototype.getCourseId = function() {\n return this.courseId;\n };\n\n /**\n * Set the category id to the given value.\n *\n * @method setCategoryId\n * @param {int} id The event id\n */\n ModalEventForm.prototype.setCategoryId = function(id) {\n this.categoryId = id;\n };\n\n /**\n * Retrieve the current category id, if any.\n *\n * @method getCategoryId\n * @return {int|null} The event id\n */\n ModalEventForm.prototype.getCategoryId = function() {\n return this.categoryId;\n };\n\n /**\n * Check if the modal has an course id.\n *\n * @method hasCourseId\n * @return {bool}\n */\n ModalEventForm.prototype.hasCourseId = function() {\n return this.courseId !== null;\n };\n\n /**\n * Check if the modal has an category id.\n *\n * @method hasCategoryId\n * @return {bool}\n */\n ModalEventForm.prototype.hasCategoryId = function() {\n return this.categoryId !== null;\n };\n\n /**\n * Set the event id to the given value.\n *\n * @method setEventId\n * @param {int} id The event id\n */\n ModalEventForm.prototype.setEventId = function(id) {\n this.eventId = id;\n };\n\n /**\n * Retrieve the current event id, if any.\n *\n * @method getEventId\n * @return {int|null} The event id\n */\n ModalEventForm.prototype.getEventId = function() {\n return this.eventId;\n };\n\n /**\n * Check if the modal has an event id.\n *\n * @method hasEventId\n * @return {bool}\n */\n ModalEventForm.prototype.hasEventId = function() {\n return this.eventId !== null;\n };\n\n /**\n * Set the start time to the given value.\n *\n * @method setStartTime\n * @param {int} time The start time\n */\n ModalEventForm.prototype.setStartTime = function(time) {\n this.startTime = time;\n };\n\n /**\n * Retrieve the current start time, if any.\n *\n * @method getStartTime\n * @return {int|null} The start time\n */\n ModalEventForm.prototype.getStartTime = function() {\n return this.startTime;\n };\n\n /**\n * Check if the modal has start time.\n *\n * @method hasStartTime\n * @return {bool}\n */\n ModalEventForm.prototype.hasStartTime = function() {\n return this.startTime !== null;\n };\n\n /**\n * Get the form element from the modal.\n *\n * @method getForm\n * @return {object}\n */\n ModalEventForm.prototype.getForm = function() {\n return this.getBody().find('form');\n };\n\n /**\n * Disable the buttons in the footer.\n *\n * @method disableButtons\n */\n ModalEventForm.prototype.disableButtons = function() {\n this.saveButton.prop('disabled', true);\n };\n\n /**\n * Enable the buttons in the footer.\n *\n * @method enableButtons\n */\n ModalEventForm.prototype.enableButtons = function() {\n this.saveButton.prop('disabled', false);\n };\n\n /**\n * Reload the title for the modal to the appropriate value\n * depending on whether we are creating a new event or\n * editing an existing event.\n *\n * @method reloadTitleContent\n * @return {object} A promise resolved with the new title text\n */\n ModalEventForm.prototype.reloadTitleContent = function() {\n if (this.reloadingTitle) {\n return this.titlePromise;\n }\n\n this.reloadingTitle = true;\n\n if (this.hasEventId()) {\n this.titlePromise = Str.get_string('editevent', 'calendar');\n } else {\n this.titlePromise = Str.get_string('newevent', 'calendar');\n }\n\n this.titlePromise.then(function(string) {\n this.setTitle(string);\n return string;\n }.bind(this))\n .always(function() {\n this.reloadingTitle = false;\n return;\n }.bind(this))\n .fail(Notification.exception);\n\n return this.titlePromise;\n };\n\n /**\n * Send a request to the server to get the event_form in a fragment\n * and render the result in the body of the modal.\n *\n * If serialised form data is provided then it will be sent in the\n * request to the server to have the form rendered with the data. This\n * is used when the form had a server side error and we need the server\n * to re-render it for us to display the error to the user.\n *\n * @method reloadBodyContent\n * @param {string} formData The serialised form data\n * @return {object} A promise resolved with the fragment html and js from\n */\n ModalEventForm.prototype.reloadBodyContent = function(formData) {\n if (this.reloadingBody) {\n return this.bodyPromise;\n }\n\n this.reloadingBody = true;\n this.disableButtons();\n\n var args = {};\n\n if (this.hasEventId()) {\n args.eventid = this.getEventId();\n }\n\n if (this.hasStartTime()) {\n args.starttime = this.getStartTime();\n }\n\n if (this.hasCourseId()) {\n args.courseid = this.getCourseId();\n }\n\n if (this.hasCategoryId()) {\n args.categoryid = this.getCategoryId();\n }\n\n if (typeof formData !== 'undefined') {\n args.formdata = formData;\n }\n\n this.bodyPromise = Fragment.loadFragment('calendar', 'event_form', this.getContextId(), args);\n\n this.setBody(this.bodyPromise);\n\n this.bodyPromise.then(function() {\n this.enableButtons();\n return;\n }.bind(this))\n .fail(Notification.exception)\n .always(function() {\n this.reloadingBody = false;\n return;\n }.bind(this))\n .fail(Notification.exception);\n\n return this.bodyPromise;\n };\n\n /**\n * Reload both the title and body content.\n *\n * @method reloadAllContent\n * @return {object} promise\n */\n ModalEventForm.prototype.reloadAllContent = function() {\n return $.when(this.reloadTitleContent(), this.reloadBodyContent());\n };\n\n /**\n * Kick off a reload the modal content before showing it. This\n * is to allow us to re-use the same modal for creating and\n * editing different events within the page.\n *\n * We do the reload when showing the modal rather than hiding it\n * to save a request to the server if the user closes the modal\n * and never re-opens it.\n *\n * @method show\n */\n ModalEventForm.prototype.show = function() {\n this.reloadAllContent();\n Modal.prototype.show.call(this);\n };\n\n /**\n * Clear the event id from the modal when it's closed so\n * that it is loaded fresh next time it's displayed.\n *\n * The event id will be set by the calling code if it wants\n * to edit a specific event.\n *\n * @method hide\n */\n ModalEventForm.prototype.hide = function() {\n Modal.prototype.hide.call(this);\n this.setEventId(null);\n this.setStartTime(null);\n this.setCourseId(null);\n this.setCategoryId(null);\n };\n\n /**\n * Get the serialised form data.\n *\n * @method getFormData\n * @return {string} serialised form data\n */\n ModalEventForm.prototype.getFormData = function() {\n return this.getForm().serialize();\n };\n\n /**\n * Send the form data to the server to create or update\n * an event.\n *\n * If there is a server side validation error then we re-request the\n * rendered form (with the data) from the server in order to get the\n * server side errors to display.\n *\n * On success the modal is hidden and the page is reloaded so that the\n * new event will display.\n *\n * @method save\n * @return {object} A promise\n */\n ModalEventForm.prototype.save = function() {\n var invalid,\n loadingContainer = this.saveButton.find(SELECTORS.LOADING_ICON_CONTAINER);\n\n // Now the change events have run, see if there are any \"invalid\" form fields.\n invalid = this.getForm().find('[aria-invalid=\"true\"]');\n\n // If we found invalid fields, focus on the first one and do not submit via ajax.\n if (invalid.length) {\n invalid.first().focus();\n return Promise.resolve();\n }\n\n loadingContainer.removeClass('hidden');\n this.disableButtons();\n\n var formData = this.getFormData();\n // Send the form data to the server for processing.\n return Repository.submitCreateUpdateForm(formData)\n .then(function(response) {\n if (response.validationerror) {\n // If there was a server side validation error then\n // we need to re-request the rendered form from the server\n // in order to display the error for the user.\n this.reloadBodyContent(formData);\n return;\n } else {\n // Check whether this was a new event or not.\n // The hide function unsets the form data so grab this before the hide.\n var isExisting = this.hasEventId();\n\n // No problemo! Our work here is done.\n this.hide();\n\n // Trigger the appropriate calendar event so that the view can be updated.\n if (isExisting) {\n $('body').trigger(CalendarEvents.updated, [response.event]);\n } else {\n $('body').trigger(CalendarEvents.created, [response.event]);\n }\n }\n\n return;\n }.bind(this))\n .always(function() {\n // Regardless of success or error we should always stop\n // the loading icon and re-enable the buttons.\n loadingContainer.addClass('hidden');\n this.enableButtons();\n\n return;\n }.bind(this))\n .fail(Notification.exception);\n };\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n * @fires event:uploadStarted\n * @fires event:formSubmittedByJavascript\n */\n ModalEventForm.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n // When the user clicks the save button we trigger the form submission. We need to\n // trigger an actual submission because there is some JS code in the form that is\n // listening for this event and doing some stuff (e.g. saving draft areas etc).\n this.getModal().on(CustomEvents.events.activate, SELECTORS.SAVE_BUTTON, function(e, data) {\n this.getForm().submit();\n data.originalEvent.preventDefault();\n e.stopPropagation();\n }.bind(this));\n\n // Catch the submit event before it is actually processed by the browser and\n // prevent the submission. We'll take it from here.\n this.getModal().on('submit', function(e) {\n FormEvents.notifyFormSubmittedByJavascript(this.getForm()[0]);\n\n this.save();\n\n // Stop the form from actually submitting and prevent it's\n // propagation because we have already handled the event.\n e.preventDefault();\n e.stopPropagation();\n }.bind(this));\n };\n\n // Automatically register with the modal registry the first time this module is imported so that you can create modals\n // of this type using the modal factory.\n if (!registered) {\n ModalRegistry.register(ModalEventForm.TYPE, ModalEventForm, 'calendar/modal_event_form');\n registered = true;\n }\n\n return ModalEventForm;\n});\n"],"names":["define","$","FormEvents","Str","Notification","Templates","CustomEvents","Modal","ModalRegistry","Fragment","CalendarEvents","Repository","registered","SELECTORS","ModalEventForm","root","call","this","eventId","startTime","courseId","categoryId","contextId","reloadingBody","reloadingTitle","saveButton","getFooter","find","TYPE","prototype","Object","create","constructor","setContextId","id","getContextId","setCourseId","getCourseId","setCategoryId","getCategoryId","hasCourseId","hasCategoryId","setEventId","getEventId","hasEventId","setStartTime","time","getStartTime","hasStartTime","getForm","getBody","disableButtons","prop","enableButtons","reloadTitleContent","titlePromise","get_string","then","string","setTitle","bind","always","fail","exception","reloadBodyContent","formData","bodyPromise","args","eventid","starttime","courseid","categoryid","formdata","loadFragment","setBody","reloadAllContent","when","show","hide","getFormData","serialize","save","invalid","loadingContainer","length","first","focus","Promise","resolve","removeClass","submitCreateUpdateForm","response","validationerror","isExisting","trigger","updated","event","created","addClass","registerEventListeners","getModal","on","events","activate","e","data","submit","originalEvent","preventDefault","stopPropagation","notifyFormSubmittedByJavascript","register"],"mappings":"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"}
\ No newline at end of file
diff --git a/calendar/amd/build/month_navigation_drag_drop.min.js b/calendar/amd/build/month_navigation_drag_drop.min.js
index 884ee1b0480..23bcd300b5b 100644
--- a/calendar/amd/build/month_navigation_drag_drop.min.js
+++ b/calendar/amd/build/month_navigation_drag_drop.min.js
@@ -1,2 +1,15 @@
-define ("core_calendar/month_navigation_drag_drop",["jquery","core_calendar/drag_drop_data_store"],function(a,b){var c={DRAGGABLE:"[draggable=\"true\"][data-region=\"event-item\"]",DROP_ZONE:"[data-drop-zone=\"nav-link\"]"},d="bg-primary text-white",e="drop-target",f=!1,g=null,h=null,i=function(a,b){if(b){a.addClass(d)}else{a.removeClass(d)}},j=function(){h.find(c.DROP_ZONE).addClass(e)},k=function(){h.find(c.DROP_ZONE).removeClass(e)},l=function(b){var d=a(b.target).closest(c.DROP_ZONE);return d.length?d:null},m=function(b){var d=a(b.target).closest(c.DRAGGABLE);if(d.length){j()}},n=function(a){if(!b.hasEventId()){return}a.preventDefault();var c=l(a);if(!c){return}if(!b.hasEventId()){return}if(!g){g=setTimeout(function(){c.click();g=null},1e3)}i(c,!0);k()},o=function(a){if(!b.hasEventId()){return}var c=l(a);if(!c){return}if(g){clearTimeout(g);g=null}i(c,!1);j();a.preventDefault()},p=function(a){if(!b.hasEventId()){return}k();var c=l(a);if(!c){return}i(c,!1);a.preventDefault()};return{init:function init(c){if(!f){document.addEventListener("dragstart",m,!1);document.addEventListener("dragover",n,!1);document.addEventListener("dragleave",o,!1);document.addEventListener("drop",p,!1);document.addEventListener("dragend",k,!1);f=!0}h=a(c);if(b.hasEventId()){j()}}}});
-//# sourceMappingURL=month_navigation_drag_drop.min.js.map
+/**
+ * A javascript module to handle calendar drag and drop in the calendar
+ * month view navigation.
+ *
+ * This code is run each time the calendar month view is re-rendered. We
+ * only register the event handlers once per page load so that the in place
+ * DOM updates that happen on month change don't continue to register handlers.
+ *
+ * @module core_calendar/month_navigation_drag_drop
+ * @copyright 2017 Ryan Wyllie
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/month_navigation_drag_drop",["jquery","core_calendar/drag_drop_data_store"],(function($,DataStore){var SELECTORS_DRAGGABLE='[draggable="true"][data-region="event-item"]',SELECTORS_DROP_ZONE='[data-drop-zone="nav-link"]',registered=!1,hoverTimer=null,root=null,updateHoverState=function(target,hovered){hovered?target.addClass("bg-primary text-white"):target.removeClass("bg-primary text-white")},addDropZoneIndicator=function(){root.find(SELECTORS_DROP_ZONE).addClass("drop-target")},removeDropZoneIndicator=function(){root.find(SELECTORS_DROP_ZONE).removeClass("drop-target")},getTargetFromEvent=function(e){var target=$(e.target).closest(SELECTORS_DROP_ZONE);return target.length?target:null},dragstartHandler=function(e){$(e.target).closest(SELECTORS_DRAGGABLE).length&&addDropZoneIndicator()},dragoverHandler=function(e){if(DataStore.hasEventId()){e.preventDefault();var target=getTargetFromEvent(e);target&&DataStore.hasEventId()&&(hoverTimer||(hoverTimer=setTimeout((function(){target.click(),hoverTimer=null}),1e3)),updateHoverState(target,!0),removeDropZoneIndicator())}},dragleaveHandler=function(e){if(DataStore.hasEventId()){var target=getTargetFromEvent(e);target&&(hoverTimer&&(clearTimeout(hoverTimer),hoverTimer=null),updateHoverState(target,!1),addDropZoneIndicator(),e.preventDefault())}},dropHandler=function(e){if(DataStore.hasEventId()){removeDropZoneIndicator();var target=getTargetFromEvent(e);target&&(updateHoverState(target,!1),e.preventDefault())}};return{init:function(rootElement){registered||(document.addEventListener("dragstart",dragstartHandler,!1),document.addEventListener("dragover",dragoverHandler,!1),document.addEventListener("dragleave",dragleaveHandler,!1),document.addEventListener("drop",dropHandler,!1),document.addEventListener("dragend",removeDropZoneIndicator,!1),registered=!0),root=$(rootElement),DataStore.hasEventId()&&addDropZoneIndicator()}}}));
+
+//# sourceMappingURL=month_navigation_drag_drop.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/month_navigation_drag_drop.min.js.map b/calendar/amd/build/month_navigation_drag_drop.min.js.map
index 3bbc5f3cb11..d10b3363d11 100644
--- a/calendar/amd/build/month_navigation_drag_drop.min.js.map
+++ b/calendar/amd/build/month_navigation_drag_drop.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/month_navigation_drag_drop.js"],"names":["define","$","DataStore","SELECTORS","DRAGGABLE","DROP_ZONE","HOVER_CLASS","TARGET_CLASS","registered","hoverTimer","root","updateHoverState","target","hovered","addClass","removeClass","addDropZoneIndicator","find","removeDropZoneIndicator","getTargetFromEvent","e","closest","length","dragstartHandler","eventElement","dragoverHandler","hasEventId","preventDefault","setTimeout","click","dragleaveHandler","clearTimeout","dropHandler","init","rootElement","document","addEventListener"],"mappings":"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","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 .\n\n/**\n * A javascript module to handle calendar drag and drop in the calendar\n * month view navigation.\n *\n * This code is run each time the calendar month view is re-rendered. We\n * only register the event handlers once per page load so that the in place\n * DOM updates that happen on month change don't continue to register handlers.\n *\n * @module core_calendar/month_navigation_drag_drop\n * @copyright 2017 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core_calendar/drag_drop_data_store',\n ],\n function(\n $,\n DataStore\n ) {\n\n var SELECTORS = {\n DRAGGABLE: '[draggable=\"true\"][data-region=\"event-item\"]',\n DROP_ZONE: '[data-drop-zone=\"nav-link\"]',\n };\n var HOVER_CLASS = 'bg-primary text-white';\n var TARGET_CLASS = 'drop-target';\n var HOVER_TIME = 1000; // 1 second hover to change month.\n\n // We store some static variables at the module level because this\n // module is called each time the calendar month view is reloaded but\n // we want some actions to only occur ones.\n\n /* @var {bool} registered If the event listeners have been added */\n var registered = false;\n /* @var {int} hoverTimer The timeout id of any timeout waiting for hover */\n var hoverTimer = null;\n /* @var {object} root The root nav element we're operating on */\n var root = null;\n\n /**\n * Add or remove the appropriate styling to indicate whether\n * the drop target is being hovered over.\n *\n * @param {object} target The target drop zone element\n * @param {bool} hovered If the element is hovered over ot not\n */\n var updateHoverState = function(target, hovered) {\n if (hovered) {\n target.addClass(HOVER_CLASS);\n } else {\n target.removeClass(HOVER_CLASS);\n }\n };\n\n /**\n * Add some styling to the UI to indicate that the nav links\n * are an acceptable drop target.\n */\n var addDropZoneIndicator = function() {\n root.find(SELECTORS.DROP_ZONE).addClass(TARGET_CLASS);\n };\n\n /**\n * Remove the styling from the nav links.\n */\n var removeDropZoneIndicator = function() {\n root.find(SELECTORS.DROP_ZONE).removeClass(TARGET_CLASS);\n };\n\n /**\n * Get the drop zone target from the event, if one is found.\n *\n * @param {event} e Javascript event\n * @return {object|null}\n */\n var getTargetFromEvent = function(e) {\n var target = $(e.target).closest(SELECTORS.DROP_ZONE);\n return (target.length) ? target : null;\n };\n\n /**\n * This will add a visual indicator to the calendar UI to\n * indicate which nav link is a valid drop zone.\n *\n * @param {Event} e\n */\n var dragstartHandler = function(e) {\n // Make sure the drag event is for a calendar event.\n var eventElement = $(e.target).closest(SELECTORS.DRAGGABLE);\n\n if (eventElement.length) {\n addDropZoneIndicator();\n }\n };\n\n /**\n * Update the hover state of the target nav element when\n * the user is dragging an event over it.\n *\n * This will add a visual indicator to the calendar UI to\n * indicate which nav link is being hovered.\n *\n * @param {event} e The dragover event\n */\n var dragoverHandler = function(e) {\n // Ignore dragging of non calendar events.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n e.preventDefault();\n var target = getTargetFromEvent(e);\n\n if (!target) {\n return;\n }\n\n // If we're not draggin a calendar event then\n // ignore it.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n if (!hoverTimer) {\n hoverTimer = setTimeout(function() {\n target.click();\n hoverTimer = null;\n }, HOVER_TIME);\n }\n\n updateHoverState(target, true);\n removeDropZoneIndicator();\n };\n\n /**\n * Update the hover state of the target nav element that was\n * previously dragged over but has is no longer a drag target.\n *\n * This will remove the visual indicator from the calendar UI\n * that was added by the dragoverHandler.\n *\n * @param {event} e The dragstart event\n */\n var dragleaveHandler = function(e) {\n // Ignore dragging of non calendar events.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n var target = getTargetFromEvent(e);\n\n if (!target) {\n return;\n }\n\n if (hoverTimer) {\n clearTimeout(hoverTimer);\n hoverTimer = null;\n }\n\n updateHoverState(target, false);\n addDropZoneIndicator();\n e.preventDefault();\n };\n\n /**\n * Remove the visual indicator from the calendar UI that was\n * added by the dragoverHandler.\n *\n * @param {event} e The drop event\n */\n var dropHandler = function(e) {\n // Ignore dragging of non calendar events.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n removeDropZoneIndicator();\n var target = getTargetFromEvent(e);\n\n if (!target) {\n return;\n }\n\n updateHoverState(target, false);\n e.preventDefault();\n };\n\n return {\n /**\n * Initialise the event handlers for the drag events.\n *\n * @param {object} rootElement The element containing calendar nav links\n */\n init: function(rootElement) {\n // Only register the handlers once on the first load.\n if (!registered) {\n // These handlers are only added the first time the module\n // is loaded because we don't want to have a new listener\n // added each time the \"init\" function is called otherwise we'll\n // end up with lots of stale handlers.\n document.addEventListener('dragstart', dragstartHandler, false);\n document.addEventListener('dragover', dragoverHandler, false);\n document.addEventListener('dragleave', dragleaveHandler, false);\n document.addEventListener('drop', dropHandler, false);\n document.addEventListener('dragend', removeDropZoneIndicator, false);\n registered = true;\n }\n\n // Update the module variable to operate on the given\n // root element.\n root = $(rootElement);\n\n // If we're currently dragging then add the indicators.\n if (DataStore.hasEventId()) {\n addDropZoneIndicator();\n }\n },\n };\n});\n"],"file":"month_navigation_drag_drop.min.js"}
\ No newline at end of file
+{"version":3,"file":"month_navigation_drag_drop.min.js","sources":["../src/month_navigation_drag_drop.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 .\n\n/**\n * A javascript module to handle calendar drag and drop in the calendar\n * month view navigation.\n *\n * This code is run each time the calendar month view is re-rendered. We\n * only register the event handlers once per page load so that the in place\n * DOM updates that happen on month change don't continue to register handlers.\n *\n * @module core_calendar/month_navigation_drag_drop\n * @copyright 2017 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core_calendar/drag_drop_data_store',\n ],\n function(\n $,\n DataStore\n ) {\n\n var SELECTORS = {\n DRAGGABLE: '[draggable=\"true\"][data-region=\"event-item\"]',\n DROP_ZONE: '[data-drop-zone=\"nav-link\"]',\n };\n var HOVER_CLASS = 'bg-primary text-white';\n var TARGET_CLASS = 'drop-target';\n var HOVER_TIME = 1000; // 1 second hover to change month.\n\n // We store some static variables at the module level because this\n // module is called each time the calendar month view is reloaded but\n // we want some actions to only occur ones.\n\n /* @var {bool} registered If the event listeners have been added */\n var registered = false;\n /* @var {int} hoverTimer The timeout id of any timeout waiting for hover */\n var hoverTimer = null;\n /* @var {object} root The root nav element we're operating on */\n var root = null;\n\n /**\n * Add or remove the appropriate styling to indicate whether\n * the drop target is being hovered over.\n *\n * @param {object} target The target drop zone element\n * @param {bool} hovered If the element is hovered over ot not\n */\n var updateHoverState = function(target, hovered) {\n if (hovered) {\n target.addClass(HOVER_CLASS);\n } else {\n target.removeClass(HOVER_CLASS);\n }\n };\n\n /**\n * Add some styling to the UI to indicate that the nav links\n * are an acceptable drop target.\n */\n var addDropZoneIndicator = function() {\n root.find(SELECTORS.DROP_ZONE).addClass(TARGET_CLASS);\n };\n\n /**\n * Remove the styling from the nav links.\n */\n var removeDropZoneIndicator = function() {\n root.find(SELECTORS.DROP_ZONE).removeClass(TARGET_CLASS);\n };\n\n /**\n * Get the drop zone target from the event, if one is found.\n *\n * @param {event} e Javascript event\n * @return {object|null}\n */\n var getTargetFromEvent = function(e) {\n var target = $(e.target).closest(SELECTORS.DROP_ZONE);\n return (target.length) ? target : null;\n };\n\n /**\n * This will add a visual indicator to the calendar UI to\n * indicate which nav link is a valid drop zone.\n *\n * @param {Event} e\n */\n var dragstartHandler = function(e) {\n // Make sure the drag event is for a calendar event.\n var eventElement = $(e.target).closest(SELECTORS.DRAGGABLE);\n\n if (eventElement.length) {\n addDropZoneIndicator();\n }\n };\n\n /**\n * Update the hover state of the target nav element when\n * the user is dragging an event over it.\n *\n * This will add a visual indicator to the calendar UI to\n * indicate which nav link is being hovered.\n *\n * @param {event} e The dragover event\n */\n var dragoverHandler = function(e) {\n // Ignore dragging of non calendar events.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n e.preventDefault();\n var target = getTargetFromEvent(e);\n\n if (!target) {\n return;\n }\n\n // If we're not draggin a calendar event then\n // ignore it.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n if (!hoverTimer) {\n hoverTimer = setTimeout(function() {\n target.click();\n hoverTimer = null;\n }, HOVER_TIME);\n }\n\n updateHoverState(target, true);\n removeDropZoneIndicator();\n };\n\n /**\n * Update the hover state of the target nav element that was\n * previously dragged over but has is no longer a drag target.\n *\n * This will remove the visual indicator from the calendar UI\n * that was added by the dragoverHandler.\n *\n * @param {event} e The dragstart event\n */\n var dragleaveHandler = function(e) {\n // Ignore dragging of non calendar events.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n var target = getTargetFromEvent(e);\n\n if (!target) {\n return;\n }\n\n if (hoverTimer) {\n clearTimeout(hoverTimer);\n hoverTimer = null;\n }\n\n updateHoverState(target, false);\n addDropZoneIndicator();\n e.preventDefault();\n };\n\n /**\n * Remove the visual indicator from the calendar UI that was\n * added by the dragoverHandler.\n *\n * @param {event} e The drop event\n */\n var dropHandler = function(e) {\n // Ignore dragging of non calendar events.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n removeDropZoneIndicator();\n var target = getTargetFromEvent(e);\n\n if (!target) {\n return;\n }\n\n updateHoverState(target, false);\n e.preventDefault();\n };\n\n return {\n /**\n * Initialise the event handlers for the drag events.\n *\n * @param {object} rootElement The element containing calendar nav links\n */\n init: function(rootElement) {\n // Only register the handlers once on the first load.\n if (!registered) {\n // These handlers are only added the first time the module\n // is loaded because we don't want to have a new listener\n // added each time the \"init\" function is called otherwise we'll\n // end up with lots of stale handlers.\n document.addEventListener('dragstart', dragstartHandler, false);\n document.addEventListener('dragover', dragoverHandler, false);\n document.addEventListener('dragleave', dragleaveHandler, false);\n document.addEventListener('drop', dropHandler, false);\n document.addEventListener('dragend', removeDropZoneIndicator, false);\n registered = true;\n }\n\n // Update the module variable to operate on the given\n // root element.\n root = $(rootElement);\n\n // If we're currently dragging then add the indicators.\n if (DataStore.hasEventId()) {\n addDropZoneIndicator();\n }\n },\n };\n});\n"],"names":["define","$","DataStore","SELECTORS","registered","hoverTimer","root","updateHoverState","target","hovered","addClass","removeClass","addDropZoneIndicator","find","removeDropZoneIndicator","getTargetFromEvent","e","closest","length","dragstartHandler","dragoverHandler","hasEventId","preventDefault","setTimeout","click","dragleaveHandler","clearTimeout","dropHandler","init","rootElement","document","addEventListener"],"mappings":";;;;;;;;;;;;AA2BAA,kDAAO,CACK,SACA,uCAEJ,SACIC,EACAC,eAGJC,oBACW,+CADXA,oBAEW,8BAWXC,YAAa,EAEbC,WAAa,KAEbC,KAAO,KASPC,iBAAmB,SAASC,OAAQC,SAChCA,QACAD,OAAOE,SAxBG,yBA0BVF,OAAOG,YA1BG,0BAkCdC,qBAAuB,WACvBN,KAAKO,KAAKV,qBAAqBO,SAlChB,gBAwCfI,wBAA0B,WAC1BR,KAAKO,KAAKV,qBAAqBQ,YAzChB,gBAkDfI,mBAAqB,SAASC,OAC1BR,OAASP,EAAEe,EAAER,QAAQS,QAAQd,4BACzBK,OAAOU,OAAUV,OAAS,MASlCW,iBAAmB,SAASH,GAETf,EAAEe,EAAER,QAAQS,QAAQd,qBAEtBe,QACbN,wBAaJQ,gBAAkB,SAASJ,MAEtBd,UAAUmB,cAIfL,EAAEM,qBACEd,OAASO,mBAAmBC,GAE3BR,QAMAN,UAAUmB,eAIVhB,aACDA,WAAakB,YAAW,WACpBf,OAAOgB,QACPnB,WAAa,OApGR,MAwGbE,iBAAiBC,QAAQ,GACzBM,6BAYAW,iBAAmB,SAAST,MAEvBd,UAAUmB,kBAIXb,OAASO,mBAAmBC,GAE3BR,SAIDH,aACAqB,aAAarB,YACbA,WAAa,MAGjBE,iBAAiBC,QAAQ,GACzBI,uBACAI,EAAEM,oBASFK,YAAc,SAASX,MAElBd,UAAUmB,cAIfP,8BACIN,OAASO,mBAAmBC,GAE3BR,SAILD,iBAAiBC,QAAQ,GACzBQ,EAAEM,0BAGC,CAMHM,KAAM,SAASC,aAENzB,aAKD0B,SAASC,iBAAiB,YAAaZ,kBAAkB,GACzDW,SAASC,iBAAiB,WAAYX,iBAAiB,GACvDU,SAASC,iBAAiB,YAAaN,kBAAkB,GACzDK,SAASC,iBAAiB,OAAQJ,aAAa,GAC/CG,SAASC,iBAAiB,UAAWjB,yBAAyB,GAC9DV,YAAa,GAKjBE,KAAOL,EAAE4B,aAGL3B,UAAUmB,cACVT"}
\ No newline at end of file
diff --git a/calendar/amd/build/month_view_drag_drop.min.js b/calendar/amd/build/month_view_drag_drop.min.js
index cdee1100f20..fb27b574fb9 100644
--- a/calendar/amd/build/month_view_drag_drop.min.js
+++ b/calendar/amd/build/month_view_drag_drop.min.js
@@ -1,2 +1,11 @@
-define ("core_calendar/month_view_drag_drop",["jquery","core/notification","core/str","core_calendar/events","core_calendar/drag_drop_data_store"],function(a,b,c,d,f){var g={ROOT:"[data-region='calendar']",DRAGGABLE:"[draggable=\"true\"][data-region=\"event-item\"]",DROP_ZONE:"[data-drop-zone=\"month-view-day\"]",WEEK:"[data-region=\"month-view-week\"]"},h="bg-faded",i="bg-danger text-white",j="bg-primary text-white",k=h+" "+i+" "+j,l=!1,m=function(b){var c=a(b.target).closest(g.DROP_ZONE);return c.length?c:null},n=function(a){var b=a.attr("data-day-timestamp"),c=f.getMinTimestart(),d=f.getMaxTimestart();if(c&&c>b){return!1}if(d&&db){return f.getMinError()}if(d&&d
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/month_view_drag_drop",["jquery","core/notification","core/str","core_calendar/events","core_calendar/drag_drop_data_store"],(function($,Notification,Str,CalendarEvents,DataStore){var SELECTORS_ROOT="[data-region='calendar']",SELECTORS_DRAGGABLE='[draggable="true"][data-region="event-item"]',SELECTORS_DROP_ZONE='[data-drop-zone="month-view-day"]',SELECTORS_WEEK='[data-region="month-view-week"]',ALL_CLASSES="bg-faded bg-danger text-white bg-primary text-white",registered=!1,getDropZoneFromEvent=function(e){var dropZone=$(e.target).closest(SELECTORS_DROP_ZONE);return dropZone.length?dropZone:null},isValidDropZone=function(dropZone){var dropTimestamp=dropZone.attr("data-day-timestamp"),minTimestart=DataStore.getMinTimestart(),maxTimestart=DataStore.getMaxTimestart();return!(minTimestart&&minTimestart>dropTimestamp)&&!(maxTimestart&&maxTimestart0){var nextDropZone=dropZone.next();if(!nextDropZone.length){var nextWeek=dropZone.closest(SELECTORS_WEEK).next();nextWeek.length&&(nextDropZone=nextWeek.children(SELECTORS_DROP_ZONE).first())}nextDropZone.length&&updateHoverState(nextDropZone,hovered,count)}},updateAllDropZonesState=function(){$(SELECTORS_ROOT).find(SELECTORS_DROP_ZONE).each((function(index,dropZone){dropZone=$(dropZone),isValidDropZone(dropZone)||updateHoverState(dropZone,!1)}))},dragstartHandler=function(e){var draggableElement=$(e.target).closest(SELECTORS_DRAGGABLE);if(draggableElement.length){var eventId=draggableElement.find("[data-event-id]").attr("data-event-id"),minTimestart=draggableElement.attr("data-min-day-timestamp"),maxTimestart=draggableElement.attr("data-max-day-timestamp"),minError=draggableElement.attr("data-min-day-error"),maxError=draggableElement.attr("data-max-day-error"),duration=$(SELECTORS_ROOT+' [data-event-id="'+eventId+'"]').length;DataStore.setEventId(eventId),DataStore.setDurationDays(duration),minTimestart&&DataStore.setMinTimestart(minTimestart),maxTimestart&&DataStore.setMaxTimestart(maxTimestart),minError&&DataStore.setMinError(minError),maxError&&DataStore.setMaxError(maxError),e.dataTransfer.effectAllowed="move",e.dataTransfer.dropEffect="move",e.dataTransfer.setData("text/plain",eventId),e.dropEffect="move",updateAllDropZonesState()}},dragoverHandler=function(e){if(DataStore.hasEventId()){e.preventDefault();var dropZone=getDropZoneFromEvent(e);dropZone&&updateHoverState(dropZone,!0)}},dragleaveHandler=function(e){if(DataStore.hasEventId()){var dropZone=getDropZoneFromEvent(e);dropZone&&(updateHoverState(dropZone,!1),e.preventDefault())}},dropHandler=function(e){if(DataStore.hasEventId()){var dropZone=getDropZoneFromEvent(e);if(!dropZone)return DataStore.clearAll(),void clearAllDropZonesState();if(isValidDropZone(dropZone)){var eventId=DataStore.getEventId(),eventElement=$(SELECTORS_ROOT+' [data-event-id="'+eventId+'"]'),origin=null;eventElement.length&&(origin=eventElement.closest(SELECTORS_DROP_ZONE)),$("body").trigger(CalendarEvents.moveEvent,[eventId,origin,dropZone])}else{var message=function(dropZone){var dropTimestamp=dropZone.attr("data-day-timestamp"),minTimestart=DataStore.getMinTimestart(),maxTimestart=DataStore.getMaxTimestart();return minTimestart&&minTimestart>dropTimestamp?DataStore.getMinError():maxTimestart&&maxTimestart.\n\n/**\n * A javascript module to handle calendar drag and drop in the calendar\n * month view.\n *\n * @module core_calendar/month_view_drag_drop\n * @copyright 2017 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/notification',\n 'core/str',\n 'core_calendar/events',\n 'core_calendar/drag_drop_data_store'\n ],\n function(\n $,\n Notification,\n Str,\n CalendarEvents,\n DataStore\n ) {\n\n var SELECTORS = {\n ROOT: \"[data-region='calendar']\",\n DRAGGABLE: '[draggable=\"true\"][data-region=\"event-item\"]',\n DROP_ZONE: '[data-drop-zone=\"month-view-day\"]',\n WEEK: '[data-region=\"month-view-week\"]',\n };\n var INVALID_DROP_ZONE_CLASS = 'bg-faded';\n var INVALID_HOVER_CLASS = 'bg-danger text-white';\n var VALID_HOVER_CLASS = 'bg-primary text-white';\n var ALL_CLASSES = INVALID_DROP_ZONE_CLASS + ' ' + INVALID_HOVER_CLASS + ' ' + VALID_HOVER_CLASS;\n /* @var {bool} registered If the event listeners have been added */\n var registered = false;\n\n /**\n * Get the correct drop zone element from the given javascript\n * event.\n *\n * @param {event} e The javascript event\n * @return {object|null}\n */\n var getDropZoneFromEvent = function(e) {\n var dropZone = $(e.target).closest(SELECTORS.DROP_ZONE);\n return (dropZone.length) ? dropZone : null;\n };\n\n /**\n * Determine if the given dropzone element is within the acceptable\n * time range.\n *\n * The drop zone timestamp is midnight on that day so we should check\n * that the event's acceptable timestart value\n *\n * @param {object} dropZone The drop zone day from the calendar\n * @return {bool}\n */\n var isValidDropZone = function(dropZone) {\n var dropTimestamp = dropZone.attr('data-day-timestamp');\n var minTimestart = DataStore.getMinTimestart();\n var maxTimestart = DataStore.getMaxTimestart();\n\n if (minTimestart && minTimestart > dropTimestamp) {\n return false;\n }\n\n if (maxTimestart && maxTimestart < dropTimestamp) {\n return false;\n }\n\n return true;\n };\n\n /**\n * Get the error string to display for a given drop zone element\n * if it is invalid.\n *\n * @param {object} dropZone The drop zone day from the calendar\n * @return {string}\n */\n var getDropZoneError = function(dropZone) {\n var dropTimestamp = dropZone.attr('data-day-timestamp');\n var minTimestart = DataStore.getMinTimestart();\n var maxTimestart = DataStore.getMaxTimestart();\n\n if (minTimestart && minTimestart > dropTimestamp) {\n return DataStore.getMinError();\n }\n\n if (maxTimestart && maxTimestart < dropTimestamp) {\n return DataStore.getMaxError();\n }\n\n return null;\n };\n\n /**\n * Remove all of the styling from each of the drop zones in the calendar.\n */\n var clearAllDropZonesState = function() {\n $(SELECTORS.ROOT).find(SELECTORS.DROP_ZONE).each(function(index, dropZone) {\n dropZone = $(dropZone);\n dropZone.removeClass(ALL_CLASSES);\n });\n };\n\n /**\n * Update the hover state for the event in the calendar to reflect\n * which days the event will be moved to.\n *\n * If the drop zone is not being hovered then it will apply some\n * styling to reflect whether the drop zone is a valid or invalid\n * drop place for the current dragging event.\n *\n * This funciton supports events spanning multiple days and will\n * recurse to highlight (or remove highlight) each of the days\n * that the event will be moved to.\n *\n * For example: An event with a duration of 3 days will have\n * 3 days highlighted when it's dragged elsewhere in the calendar.\n * The current drag target and the 2 days following it (including\n * wrapping to the next week if necessary).\n *\n * @param {string|object} dropZone The drag target element\n * @param {bool} hovered If the target is hovered or not\n * @param {Number} count How many days to highlight (default to duration)\n */\n var updateHoverState = function(dropZone, hovered, count) {\n if (typeof count === 'undefined') {\n // This is how many days we need to highlight.\n count = DataStore.getDurationDays();\n }\n\n var valid = isValidDropZone(dropZone);\n dropZone.removeClass(ALL_CLASSES);\n\n if (hovered) {\n\n if (valid) {\n dropZone.addClass(VALID_HOVER_CLASS);\n } else {\n dropZone.addClass(INVALID_HOVER_CLASS);\n }\n } else {\n dropZone.removeClass(VALID_HOVER_CLASS + ' ' + INVALID_HOVER_CLASS);\n\n if (!valid) {\n dropZone.addClass(INVALID_DROP_ZONE_CLASS);\n }\n }\n\n count--;\n\n // If we've still got days to highlight then we should\n // find the next day.\n if (count > 0) {\n var nextDropZone = dropZone.next();\n\n // If there are no more days in this week then we\n // need to move down to the next week in the calendar.\n if (!nextDropZone.length) {\n var nextWeek = dropZone.closest(SELECTORS.WEEK).next();\n\n if (nextWeek.length) {\n nextDropZone = nextWeek.children(SELECTORS.DROP_ZONE).first();\n }\n }\n\n // If we found another day then let's recursively\n // update it's hover state.\n if (nextDropZone.length) {\n updateHoverState(nextDropZone, hovered, count);\n }\n }\n };\n\n /**\n * Find all of the calendar event drop zones in the calendar and update the display\n * for the user to indicate which zones are valid and invalid.\n */\n var updateAllDropZonesState = function() {\n $(SELECTORS.ROOT).find(SELECTORS.DROP_ZONE).each(function(index, dropZone) {\n dropZone = $(dropZone);\n\n if (!isValidDropZone(dropZone)) {\n updateHoverState(dropZone, false);\n }\n });\n };\n\n\n /**\n * Set up the module level variables to track which event is being\n * dragged and how many days it spans.\n *\n * @param {event} e The dragstart event\n */\n var dragstartHandler = function(e) {\n var target = $(e.target);\n var draggableElement = target.closest(SELECTORS.DRAGGABLE);\n\n if (!draggableElement.length) {\n return;\n }\n\n var eventElement = draggableElement.find('[data-event-id]');\n var eventId = eventElement.attr('data-event-id');\n var minTimestart = draggableElement.attr('data-min-day-timestamp');\n var maxTimestart = draggableElement.attr('data-max-day-timestamp');\n var minError = draggableElement.attr('data-min-day-error');\n var maxError = draggableElement.attr('data-max-day-error');\n var eventsSelector = SELECTORS.ROOT + ' [data-event-id=\"' + eventId + '\"]';\n var duration = $(eventsSelector).length;\n\n DataStore.setEventId(eventId);\n DataStore.setDurationDays(duration);\n\n if (minTimestart) {\n DataStore.setMinTimestart(minTimestart);\n }\n\n if (maxTimestart) {\n DataStore.setMaxTimestart(maxTimestart);\n }\n\n if (minError) {\n DataStore.setMinError(minError);\n }\n\n if (maxError) {\n DataStore.setMaxError(maxError);\n }\n\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.dropEffect = \"move\";\n // Firefox requires a value to be set here or the drag won't\n // work and the dragover handler won't fire.\n e.dataTransfer.setData('text/plain', eventId);\n e.dropEffect = \"move\";\n\n updateAllDropZonesState();\n };\n\n /**\n * Update the hover state of the target day element when\n * the user is dragging an event over it.\n *\n * This will add a visual indicator to the calendar UI to\n * indicate which day(s) the event will be moved to.\n *\n * @param {event} e The dragstart event\n */\n var dragoverHandler = function(e) {\n // Ignore dragging of non calendar events.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n e.preventDefault();\n\n var dropZone = getDropZoneFromEvent(e);\n\n if (!dropZone) {\n return;\n }\n\n updateHoverState(dropZone, true);\n };\n\n /**\n * Update the hover state of the target day element that was\n * previously dragged over but has is no longer a drag target.\n *\n * This will remove the visual indicator from the calendar UI\n * that was added by the dragoverHandler.\n *\n * @param {event} e The dragstart event\n */\n var dragleaveHandler = function(e) {\n // Ignore dragging of non calendar events.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n var dropZone = getDropZoneFromEvent(e);\n\n if (!dropZone) {\n return;\n }\n\n updateHoverState(dropZone, false);\n e.preventDefault();\n };\n\n /**\n * Determines the event element, origin day, and destination day\n * once the user drops the calendar event. These three bits of data\n * are provided as the payload to the \"moveEvent\" calendar javascript\n * event that is fired.\n *\n * This will remove the visual indicator from the calendar UI\n * that was added by the dragoverHandler.\n *\n * @param {event} e The dragstart event\n */\n var dropHandler = function(e) {\n // Ignore dragging of non calendar events.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n var dropZone = getDropZoneFromEvent(e);\n\n if (!dropZone) {\n DataStore.clearAll();\n clearAllDropZonesState();\n return;\n }\n\n if (isValidDropZone(dropZone)) {\n var eventId = DataStore.getEventId();\n var eventElementSelector = SELECTORS.ROOT + ' [data-event-id=\"' + eventId + '\"]';\n var eventElement = $(eventElementSelector);\n var origin = null;\n\n if (eventElement.length) {\n origin = eventElement.closest(SELECTORS.DROP_ZONE);\n }\n\n $('body').trigger(CalendarEvents.moveEvent, [eventId, origin, dropZone]);\n } else {\n // If the drop zone is not valid then there is not need for us to\n // try to process it. Instead we can just show an error to the user.\n var message = getDropZoneError(dropZone);\n Str.get_string('errorinvaliddate', 'calendar').then(function(string) {\n Notification.exception({\n name: string,\n message: message || string\n });\n });\n }\n\n DataStore.clearAll();\n clearAllDropZonesState();\n\n e.preventDefault();\n };\n\n /**\n * Clear the data store and remove the drag indicators from the UI\n * when the drag event has finished.\n */\n var dragendHandler = function() {\n DataStore.clearAll();\n clearAllDropZonesState();\n };\n\n /**\n * Re-render the drop zones in the new month to highlight\n * which areas are or aren't acceptable to drop the calendar\n * event.\n */\n var calendarMonthChangedHandler = function() {\n updateAllDropZonesState();\n };\n\n return {\n /**\n * Initialise the event handlers for the drag events.\n */\n init: function() {\n if (!registered) {\n // These handlers are only added the first time the module\n // is loaded because we don't want to have a new listener\n // added each time the \"init\" function is called otherwise we'll\n // end up with lots of stale handlers.\n document.addEventListener('dragstart', dragstartHandler, false);\n document.addEventListener('dragover', dragoverHandler, false);\n document.addEventListener('dragleave', dragleaveHandler, false);\n document.addEventListener('drop', dropHandler, false);\n document.addEventListener('dragend', dragendHandler, false);\n $('body').on(CalendarEvents.monthChanged, calendarMonthChangedHandler);\n registered = true;\n }\n },\n };\n});\n"],"file":"month_view_drag_drop.min.js"}
\ No newline at end of file
+{"version":3,"file":"month_view_drag_drop.min.js","sources":["../src/month_view_drag_drop.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 .\n\n/**\n * A javascript module to handle calendar drag and drop in the calendar\n * month view.\n *\n * @module core_calendar/month_view_drag_drop\n * @copyright 2017 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/notification',\n 'core/str',\n 'core_calendar/events',\n 'core_calendar/drag_drop_data_store'\n ],\n function(\n $,\n Notification,\n Str,\n CalendarEvents,\n DataStore\n ) {\n\n var SELECTORS = {\n ROOT: \"[data-region='calendar']\",\n DRAGGABLE: '[draggable=\"true\"][data-region=\"event-item\"]',\n DROP_ZONE: '[data-drop-zone=\"month-view-day\"]',\n WEEK: '[data-region=\"month-view-week\"]',\n };\n var INVALID_DROP_ZONE_CLASS = 'bg-faded';\n var INVALID_HOVER_CLASS = 'bg-danger text-white';\n var VALID_HOVER_CLASS = 'bg-primary text-white';\n var ALL_CLASSES = INVALID_DROP_ZONE_CLASS + ' ' + INVALID_HOVER_CLASS + ' ' + VALID_HOVER_CLASS;\n /* @var {bool} registered If the event listeners have been added */\n var registered = false;\n\n /**\n * Get the correct drop zone element from the given javascript\n * event.\n *\n * @param {event} e The javascript event\n * @return {object|null}\n */\n var getDropZoneFromEvent = function(e) {\n var dropZone = $(e.target).closest(SELECTORS.DROP_ZONE);\n return (dropZone.length) ? dropZone : null;\n };\n\n /**\n * Determine if the given dropzone element is within the acceptable\n * time range.\n *\n * The drop zone timestamp is midnight on that day so we should check\n * that the event's acceptable timestart value\n *\n * @param {object} dropZone The drop zone day from the calendar\n * @return {bool}\n */\n var isValidDropZone = function(dropZone) {\n var dropTimestamp = dropZone.attr('data-day-timestamp');\n var minTimestart = DataStore.getMinTimestart();\n var maxTimestart = DataStore.getMaxTimestart();\n\n if (minTimestart && minTimestart > dropTimestamp) {\n return false;\n }\n\n if (maxTimestart && maxTimestart < dropTimestamp) {\n return false;\n }\n\n return true;\n };\n\n /**\n * Get the error string to display for a given drop zone element\n * if it is invalid.\n *\n * @param {object} dropZone The drop zone day from the calendar\n * @return {string}\n */\n var getDropZoneError = function(dropZone) {\n var dropTimestamp = dropZone.attr('data-day-timestamp');\n var minTimestart = DataStore.getMinTimestart();\n var maxTimestart = DataStore.getMaxTimestart();\n\n if (minTimestart && minTimestart > dropTimestamp) {\n return DataStore.getMinError();\n }\n\n if (maxTimestart && maxTimestart < dropTimestamp) {\n return DataStore.getMaxError();\n }\n\n return null;\n };\n\n /**\n * Remove all of the styling from each of the drop zones in the calendar.\n */\n var clearAllDropZonesState = function() {\n $(SELECTORS.ROOT).find(SELECTORS.DROP_ZONE).each(function(index, dropZone) {\n dropZone = $(dropZone);\n dropZone.removeClass(ALL_CLASSES);\n });\n };\n\n /**\n * Update the hover state for the event in the calendar to reflect\n * which days the event will be moved to.\n *\n * If the drop zone is not being hovered then it will apply some\n * styling to reflect whether the drop zone is a valid or invalid\n * drop place for the current dragging event.\n *\n * This funciton supports events spanning multiple days and will\n * recurse to highlight (or remove highlight) each of the days\n * that the event will be moved to.\n *\n * For example: An event with a duration of 3 days will have\n * 3 days highlighted when it's dragged elsewhere in the calendar.\n * The current drag target and the 2 days following it (including\n * wrapping to the next week if necessary).\n *\n * @param {string|object} dropZone The drag target element\n * @param {bool} hovered If the target is hovered or not\n * @param {Number} count How many days to highlight (default to duration)\n */\n var updateHoverState = function(dropZone, hovered, count) {\n if (typeof count === 'undefined') {\n // This is how many days we need to highlight.\n count = DataStore.getDurationDays();\n }\n\n var valid = isValidDropZone(dropZone);\n dropZone.removeClass(ALL_CLASSES);\n\n if (hovered) {\n\n if (valid) {\n dropZone.addClass(VALID_HOVER_CLASS);\n } else {\n dropZone.addClass(INVALID_HOVER_CLASS);\n }\n } else {\n dropZone.removeClass(VALID_HOVER_CLASS + ' ' + INVALID_HOVER_CLASS);\n\n if (!valid) {\n dropZone.addClass(INVALID_DROP_ZONE_CLASS);\n }\n }\n\n count--;\n\n // If we've still got days to highlight then we should\n // find the next day.\n if (count > 0) {\n var nextDropZone = dropZone.next();\n\n // If there are no more days in this week then we\n // need to move down to the next week in the calendar.\n if (!nextDropZone.length) {\n var nextWeek = dropZone.closest(SELECTORS.WEEK).next();\n\n if (nextWeek.length) {\n nextDropZone = nextWeek.children(SELECTORS.DROP_ZONE).first();\n }\n }\n\n // If we found another day then let's recursively\n // update it's hover state.\n if (nextDropZone.length) {\n updateHoverState(nextDropZone, hovered, count);\n }\n }\n };\n\n /**\n * Find all of the calendar event drop zones in the calendar and update the display\n * for the user to indicate which zones are valid and invalid.\n */\n var updateAllDropZonesState = function() {\n $(SELECTORS.ROOT).find(SELECTORS.DROP_ZONE).each(function(index, dropZone) {\n dropZone = $(dropZone);\n\n if (!isValidDropZone(dropZone)) {\n updateHoverState(dropZone, false);\n }\n });\n };\n\n\n /**\n * Set up the module level variables to track which event is being\n * dragged and how many days it spans.\n *\n * @param {event} e The dragstart event\n */\n var dragstartHandler = function(e) {\n var target = $(e.target);\n var draggableElement = target.closest(SELECTORS.DRAGGABLE);\n\n if (!draggableElement.length) {\n return;\n }\n\n var eventElement = draggableElement.find('[data-event-id]');\n var eventId = eventElement.attr('data-event-id');\n var minTimestart = draggableElement.attr('data-min-day-timestamp');\n var maxTimestart = draggableElement.attr('data-max-day-timestamp');\n var minError = draggableElement.attr('data-min-day-error');\n var maxError = draggableElement.attr('data-max-day-error');\n var eventsSelector = SELECTORS.ROOT + ' [data-event-id=\"' + eventId + '\"]';\n var duration = $(eventsSelector).length;\n\n DataStore.setEventId(eventId);\n DataStore.setDurationDays(duration);\n\n if (minTimestart) {\n DataStore.setMinTimestart(minTimestart);\n }\n\n if (maxTimestart) {\n DataStore.setMaxTimestart(maxTimestart);\n }\n\n if (minError) {\n DataStore.setMinError(minError);\n }\n\n if (maxError) {\n DataStore.setMaxError(maxError);\n }\n\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.dropEffect = \"move\";\n // Firefox requires a value to be set here or the drag won't\n // work and the dragover handler won't fire.\n e.dataTransfer.setData('text/plain', eventId);\n e.dropEffect = \"move\";\n\n updateAllDropZonesState();\n };\n\n /**\n * Update the hover state of the target day element when\n * the user is dragging an event over it.\n *\n * This will add a visual indicator to the calendar UI to\n * indicate which day(s) the event will be moved to.\n *\n * @param {event} e The dragstart event\n */\n var dragoverHandler = function(e) {\n // Ignore dragging of non calendar events.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n e.preventDefault();\n\n var dropZone = getDropZoneFromEvent(e);\n\n if (!dropZone) {\n return;\n }\n\n updateHoverState(dropZone, true);\n };\n\n /**\n * Update the hover state of the target day element that was\n * previously dragged over but has is no longer a drag target.\n *\n * This will remove the visual indicator from the calendar UI\n * that was added by the dragoverHandler.\n *\n * @param {event} e The dragstart event\n */\n var dragleaveHandler = function(e) {\n // Ignore dragging of non calendar events.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n var dropZone = getDropZoneFromEvent(e);\n\n if (!dropZone) {\n return;\n }\n\n updateHoverState(dropZone, false);\n e.preventDefault();\n };\n\n /**\n * Determines the event element, origin day, and destination day\n * once the user drops the calendar event. These three bits of data\n * are provided as the payload to the \"moveEvent\" calendar javascript\n * event that is fired.\n *\n * This will remove the visual indicator from the calendar UI\n * that was added by the dragoverHandler.\n *\n * @param {event} e The dragstart event\n */\n var dropHandler = function(e) {\n // Ignore dragging of non calendar events.\n if (!DataStore.hasEventId()) {\n return;\n }\n\n var dropZone = getDropZoneFromEvent(e);\n\n if (!dropZone) {\n DataStore.clearAll();\n clearAllDropZonesState();\n return;\n }\n\n if (isValidDropZone(dropZone)) {\n var eventId = DataStore.getEventId();\n var eventElementSelector = SELECTORS.ROOT + ' [data-event-id=\"' + eventId + '\"]';\n var eventElement = $(eventElementSelector);\n var origin = null;\n\n if (eventElement.length) {\n origin = eventElement.closest(SELECTORS.DROP_ZONE);\n }\n\n $('body').trigger(CalendarEvents.moveEvent, [eventId, origin, dropZone]);\n } else {\n // If the drop zone is not valid then there is not need for us to\n // try to process it. Instead we can just show an error to the user.\n var message = getDropZoneError(dropZone);\n Str.get_string('errorinvaliddate', 'calendar').then(function(string) {\n Notification.exception({\n name: string,\n message: message || string\n });\n });\n }\n\n DataStore.clearAll();\n clearAllDropZonesState();\n\n e.preventDefault();\n };\n\n /**\n * Clear the data store and remove the drag indicators from the UI\n * when the drag event has finished.\n */\n var dragendHandler = function() {\n DataStore.clearAll();\n clearAllDropZonesState();\n };\n\n /**\n * Re-render the drop zones in the new month to highlight\n * which areas are or aren't acceptable to drop the calendar\n * event.\n */\n var calendarMonthChangedHandler = function() {\n updateAllDropZonesState();\n };\n\n return {\n /**\n * Initialise the event handlers for the drag events.\n */\n init: function() {\n if (!registered) {\n // These handlers are only added the first time the module\n // is loaded because we don't want to have a new listener\n // added each time the \"init\" function is called otherwise we'll\n // end up with lots of stale handlers.\n document.addEventListener('dragstart', dragstartHandler, false);\n document.addEventListener('dragover', dragoverHandler, false);\n document.addEventListener('dragleave', dragleaveHandler, false);\n document.addEventListener('drop', dropHandler, false);\n document.addEventListener('dragend', dragendHandler, false);\n $('body').on(CalendarEvents.monthChanged, calendarMonthChangedHandler);\n registered = true;\n }\n },\n };\n});\n"],"names":["define","$","Notification","Str","CalendarEvents","DataStore","SELECTORS","ALL_CLASSES","INVALID_DROP_ZONE_CLASS","registered","getDropZoneFromEvent","e","dropZone","target","closest","length","isValidDropZone","dropTimestamp","attr","minTimestart","getMinTimestart","maxTimestart","getMaxTimestart","clearAllDropZonesState","find","each","index","removeClass","updateHoverState","hovered","count","getDurationDays","valid","addClass","VALID_HOVER_CLASS","nextDropZone","next","nextWeek","children","first","updateAllDropZonesState","dragstartHandler","draggableElement","eventId","minError","maxError","duration","setEventId","setDurationDays","setMinTimestart","setMaxTimestart","setMinError","setMaxError","dataTransfer","effectAllowed","dropEffect","setData","dragoverHandler","hasEventId","preventDefault","dragleaveHandler","dropHandler","clearAll","getEventId","eventElement","origin","trigger","moveEvent","message","getMinError","getMaxError","getDropZoneError","get_string","then","string","exception","name","dragendHandler","calendarMonthChangedHandler","init","document","addEventListener","on","monthChanged"],"mappings":"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"}
\ No newline at end of file
diff --git a/calendar/amd/build/popover.min.js b/calendar/amd/build/popover.min.js
index 763a06aacdc..e66571e8fbe 100644
--- a/calendar/amd/build/popover.min.js
+++ b/calendar/amd/build/popover.min.js
@@ -1,2 +1,11 @@
-function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core_calendar/popover",["theme_boost/popover","jquery","core_calendar/selectors"],function(a,b,c){"use strict";b=function(a){return a&&a.__esModule?a:{default:a}}(b);c=e(c);function d(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;d=function(){return a};return a}function e(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=d();if(b&&b.has(a)){return b.get(a)}var c={},e=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var f in a){if(Object.prototype.hasOwnProperty.call(a,f)){var g=e?Object.getOwnPropertyDescriptor(a,f):null;if(g&&(g.get||g.set)){Object.defineProperty(c,f,g)}else{c[f]=a[f]}}}c.default=a;if(b){b.set(a,c)}return c}var f=function(a){return"none"===window.getComputedStyle(a.querySelector(c.elements.dateContent)).display},g=new Map,h=function(a){if(!g.has(a)){var d=(0,b.default)(a);d.popover({trigger:"manual",placement:"top",html:!0,content:function(){var a=d.find(c.elements.dateContent),e=(0,b.default)("
");if(source.length){const temptContent=source.find(".hidden").clone(!1);content.html(temptContent.html())}return content.html()}}),isPopoverConfigured.set(target,!0)}var dateContainer;dateContainer=target,"none"===window.getComputedStyle(dateContainer.querySelector(CalendarSelectors.elements.dateContent)).display&&((0,_jquery.default)(target).popover("show"),target.addEventListener("mouseleave",hidePopover),target.addEventListener("focusout",hidePopover))},hidePopover=e=>{const target=e.target,dateContainer=e.target.closest(CalendarSelectors.elements.dateContainer);if(dateContainer&&isPopoverConfigured.has(dateContainer)){const isTargetActive=target.contains(document.activeElement),isTargetHover=target.matches(":hover");isTargetActive||isTargetHover||((0,_jquery.default)(dateContainer).popover("hide"),dateContainer.removeEventListener("mouseleave",hidePopover),dateContainer.removeEventListener("focusout",hidePopover))}};let listenersRegistered=!1;listenersRegistered||((()=>{const showPopoverHandler=e=>{const dateContainer=e.target.closest(CalendarSelectors.elements.dateContainer);dateContainer&&(e.preventDefault(),showPopover(dateContainer))};document.addEventListener("mouseover",showPopoverHandler),document.addEventListener("focusin",showPopoverHandler)})(),listenersRegistered=!0)}));
+
+//# sourceMappingURL=popover.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/popover.min.js.map b/calendar/amd/build/popover.min.js.map
index b0926bd8490..0eea6d29076 100644
--- a/calendar/amd/build/popover.min.js.map
+++ b/calendar/amd/build/popover.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/popover.js"],"names":["isPopoverAvailable","dateContainer","window","getComputedStyle","querySelector","CalendarSelectors","elements","dateContent","display","isPopoverConfigured","Map","showPopover","target","has","dateEle","popover","trigger","placement","html","content","source","find","length","temptContent","clone","set","addEventListener","hidePopover","e","closest","isTargetActive","contains","document","activeElement","isTargetHover","matches","removeEventListener","registerEventListeners","showPopoverHandler","preventDefault","listenersRegistered"],"mappings":"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","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 .\n\n/**\n * Javascript popover for the `core_calendar` subsystem.\n *\n * @module core_calendar/popover\n * @copyright 2021 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\n\nimport 'theme_boost/popover';\nimport jQuery from 'jquery';\nimport * as CalendarSelectors from 'core_calendar/selectors';\n\n/**\n * Check if we are allowing to enable the popover or not.\n * @param {Element} dateContainer\n * @returns {boolean}\n */\nconst isPopoverAvailable = (dateContainer) => {\n return window.getComputedStyle(dateContainer.querySelector(CalendarSelectors.elements.dateContent)).display === 'none';\n};\n\nconst isPopoverConfigured = new Map();\n\nconst showPopover = target => {\n if (!isPopoverConfigured.has(target)) {\n const dateEle = jQuery(target);\n dateEle.popover({\n trigger: 'manual',\n placement: 'top',\n html: true,\n content: () => {\n const source = dateEle.find(CalendarSelectors.elements.dateContent);\n const content = jQuery('
');\n if (source.length) {\n const temptContent = source.find('.hidden').clone(false);\n content.html(temptContent.html());\n }\n return content.html();\n }\n });\n\n isPopoverConfigured.set(target, true);\n }\n\n if (isPopoverAvailable(target)) {\n jQuery(target).popover('show');\n target.addEventListener('mouseleave', hidePopover);\n target.addEventListener('focusout', hidePopover);\n }\n};\n\nconst hidePopover = e => {\n const target = e.target;\n const dateContainer = e.target.closest(CalendarSelectors.elements.dateContainer);\n if (!dateContainer) {\n return;\n }\n if (isPopoverConfigured.has(dateContainer)) {\n const isTargetActive = target.contains(document.activeElement);\n const isTargetHover = target.matches(':hover');\n if (!isTargetActive && !isTargetHover) {\n jQuery(dateContainer).popover('hide');\n dateContainer.removeEventListener('mouseleave', hidePopover);\n dateContainer.removeEventListener('focusout', hidePopover);\n }\n }\n};\n\n/**\n * Register events for date container.\n */\nconst registerEventListeners = () => {\n const showPopoverHandler = (e) => {\n const dateContainer = e.target.closest(CalendarSelectors.elements.dateContainer);\n if (!dateContainer) {\n return;\n }\n\n e.preventDefault();\n showPopover(dateContainer);\n };\n\n document.addEventListener('mouseover', showPopoverHandler);\n document.addEventListener('focusin', showPopoverHandler);\n};\n\nlet listenersRegistered = false;\nif (!listenersRegistered) {\n registerEventListeners();\n listenersRegistered = true;\n}\n"],"file":"popover.min.js"}
\ No newline at end of file
+{"version":3,"file":"popover.min.js","sources":["../src/popover.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 .\n\n/**\n * Javascript popover for the `core_calendar` subsystem.\n *\n * @module core_calendar/popover\n * @copyright 2021 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\n\nimport 'theme_boost/popover';\nimport jQuery from 'jquery';\nimport * as CalendarSelectors from 'core_calendar/selectors';\n\n/**\n * Check if we are allowing to enable the popover or not.\n * @param {Element} dateContainer\n * @returns {boolean}\n */\nconst isPopoverAvailable = (dateContainer) => {\n return window.getComputedStyle(dateContainer.querySelector(CalendarSelectors.elements.dateContent)).display === 'none';\n};\n\nconst isPopoverConfigured = new Map();\n\nconst showPopover = target => {\n if (!isPopoverConfigured.has(target)) {\n const dateEle = jQuery(target);\n dateEle.popover({\n trigger: 'manual',\n placement: 'top',\n html: true,\n content: () => {\n const source = dateEle.find(CalendarSelectors.elements.dateContent);\n const content = jQuery('
');\n if (source.length) {\n const temptContent = source.find('.hidden').clone(false);\n content.html(temptContent.html());\n }\n return content.html();\n }\n });\n\n isPopoverConfigured.set(target, true);\n }\n\n if (isPopoverAvailable(target)) {\n jQuery(target).popover('show');\n target.addEventListener('mouseleave', hidePopover);\n target.addEventListener('focusout', hidePopover);\n }\n};\n\nconst hidePopover = e => {\n const target = e.target;\n const dateContainer = e.target.closest(CalendarSelectors.elements.dateContainer);\n if (!dateContainer) {\n return;\n }\n if (isPopoverConfigured.has(dateContainer)) {\n const isTargetActive = target.contains(document.activeElement);\n const isTargetHover = target.matches(':hover');\n if (!isTargetActive && !isTargetHover) {\n jQuery(dateContainer).popover('hide');\n dateContainer.removeEventListener('mouseleave', hidePopover);\n dateContainer.removeEventListener('focusout', hidePopover);\n }\n }\n};\n\n/**\n * Register events for date container.\n */\nconst registerEventListeners = () => {\n const showPopoverHandler = (e) => {\n const dateContainer = e.target.closest(CalendarSelectors.elements.dateContainer);\n if (!dateContainer) {\n return;\n }\n\n e.preventDefault();\n showPopover(dateContainer);\n };\n\n document.addEventListener('mouseover', showPopoverHandler);\n document.addEventListener('focusin', showPopoverHandler);\n};\n\nlet listenersRegistered = false;\nif (!listenersRegistered) {\n registerEventListeners();\n listenersRegistered = true;\n}\n"],"names":["isPopoverConfigured","Map","showPopover","target","has","dateEle","popover","trigger","placement","html","content","source","find","CalendarSelectors","elements","dateContent","length","temptContent","clone","set","dateContainer","window","getComputedStyle","querySelector","display","addEventListener","hidePopover","e","closest","isTargetActive","contains","document","activeElement","isTargetHover","matches","removeEventListener","listenersRegistered","showPopoverHandler","preventDefault","registerEventListeners"],"mappings":";;;;;;;;wgCAqCMA,oBAAsB,IAAIC,IAE1BC,YAAcC,aACXH,oBAAoBI,IAAID,QAAS,OAC5BE,SAAU,mBAAOF,QACvBE,QAAQC,QAAQ,CACZC,QAAS,SACTC,UAAW,MACXC,MAAM,EACNC,QAAS,WACCC,OAASN,QAAQO,KAAKC,kBAAkBC,SAASC,aACjDL,SAAU,mBAAO,YACnBC,OAAOK,OAAQ,OACTC,aAAeN,OAAOC,KAAK,WAAWM,OAAM,GAClDR,QAAQD,KAAKQ,aAAaR,eAEvBC,QAAQD,UAIvBT,oBAAoBmB,IAAIhB,QAAQ,GAxBZiB,IAAAA,cAAAA,cA2BDjB,OA1ByF,SAAzGkB,OAAOC,iBAAiBF,cAAcG,cAAcV,kBAAkBC,SAASC,cAAcS,8BA2BzFrB,QAAQG,QAAQ,QACvBH,OAAOsB,iBAAiB,aAAcC,aACtCvB,OAAOsB,iBAAiB,WAAYC,eAItCA,YAAcC,UACVxB,OAASwB,EAAExB,OACXiB,cAAgBO,EAAExB,OAAOyB,QAAQf,kBAAkBC,SAASM,kBAC7DA,eAGDpB,oBAAoBI,IAAIgB,eAAgB,OAClCS,eAAiB1B,OAAO2B,SAASC,SAASC,eAC1CC,cAAgB9B,OAAO+B,QAAQ,UAChCL,gBAAmBI,oCACbb,eAAed,QAAQ,QAC9Bc,cAAce,oBAAoB,aAAcT,aAChDN,cAAce,oBAAoB,WAAYT,oBAuBtDU,qBAAsB,EACrBA,sBAhB0B,YACrBC,mBAAsBV,UAClBP,cAAgBO,EAAExB,OAAOyB,QAAQf,kBAAkBC,SAASM,eAC7DA,gBAILO,EAAEW,iBACFpC,YAAYkB,iBAGhBW,SAASN,iBAAiB,YAAaY,oBACvCN,SAASN,iBAAiB,UAAWY,qBAKrCE,GACAH,qBAAsB"}
\ No newline at end of file
diff --git a/calendar/amd/build/repository.min.js b/calendar/amd/build/repository.min.js
index 16d63c76132..4e890eaf9b8 100644
--- a/calendar/amd/build/repository.min.js
+++ b/calendar/amd/build/repository.min.js
@@ -1,2 +1,10 @@
-define ("core_calendar/repository",["exports","core/ajax"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.deleteSubscription=a.getCourseGroupsData=a.getCalendarUpcomingData=a.updateEventStartDay=a.getCalendarDayData=a.getCalendarMonthData=a.submitCreateUpdateForm=a.getEventById=a.deleteEvent=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);var c=function(a){var c=1
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.updateEventStartDay=_exports.submitCreateUpdateForm=_exports.getEventById=_exports.getCourseGroupsData=_exports.getCalendarUpcomingData=_exports.getCalendarMonthData=_exports.getCalendarDayData=_exports.deleteSubscription=_exports.deleteEvent=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.deleteEvent=function(eventId){let deleteSeries=arguments.length>1&&void 0!==arguments[1]&&arguments[1];const request={methodname:"core_calendar_delete_calendar_events",args:{events:[{eventid:eventId,repeat:deleteSeries}]}};return _ajax.default.call([request])[0]};_exports.getEventById=eventId=>{const request={methodname:"core_calendar_get_calendar_event_by_id",args:{eventid:eventId}};return _ajax.default.call([request])[0]};_exports.submitCreateUpdateForm=formData=>{const request={methodname:"core_calendar_submit_create_update_form",args:{formdata:formData}};return _ajax.default.call([request])[0]};_exports.getCalendarMonthData=function(year,month,courseId,categoryId,includeNavigation,mini){let day=arguments.length>6&&void 0!==arguments[6]?arguments[6]:1,view=arguments.length>7&&void 0!==arguments[7]?arguments[7]:"month";const request={methodname:"core_calendar_get_calendar_monthly_view",args:{year:year,month:month,courseid:courseId,categoryid:categoryId,includenavigation:includeNavigation,mini:mini,day:day,view:view}};return _ajax.default.call([request])[0]};_exports.getCalendarDayData=(year,month,day,courseId,categoryId)=>{const request={methodname:"core_calendar_get_calendar_day_view",args:{year:year,month:month,day:day,courseid:courseId,categoryid:categoryId}};return _ajax.default.call([request])[0]};_exports.updateEventStartDay=(eventId,dayTimestamp)=>{const request={methodname:"core_calendar_update_event_start_day",args:{eventid:eventId,daytimestamp:dayTimestamp}};return _ajax.default.call([request])[0]};_exports.getCalendarUpcomingData=(courseId,categoryId)=>{const request={methodname:"core_calendar_get_calendar_upcoming_view",args:{courseid:courseId,categoryid:categoryId}};return _ajax.default.call([request])[0]};_exports.getCourseGroupsData=courseId=>{const request={methodname:"core_group_get_course_groups",args:{courseid:courseId}};return _ajax.default.call([request])[0]};_exports.deleteSubscription=subscriptionId=>{const request={methodname:"core_calendar_delete_subscription",args:{subscriptionid:subscriptionId}};return _ajax.default.call([request])[0]}}));
+
+//# sourceMappingURL=repository.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/repository.min.js.map b/calendar/amd/build/repository.min.js.map
index 88b6c8317f8..d20225f269a 100644
--- a/calendar/amd/build/repository.min.js.map
+++ b/calendar/amd/build/repository.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/repository.js"],"names":["deleteEvent","eventId","deleteSeries","Ajax","call","methodname","args","events","eventid","repeat","getEventById","submitCreateUpdateForm","formData","formdata","getCalendarMonthData","year","month","courseId","categoryId","includeNavigation","mini","day","view","courseid","categoryid","includenavigation","getCalendarDayData","updateEventStartDay","dayTimestamp","daytimestamp","getCalendarUpcomingData","getCourseGroupsData","deleteSubscription","subscriptionId","subscriptionid"],"mappings":"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","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 .\n\n/**\n * A javascript module to handle calendar ajax actions.\n *\n * @module core_calendar/repository\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\n\n/**\n * Delete a calendar event.\n *\n * @method deleteEvent\n * @param {number} eventId The event id.\n * @param {boolean} deleteSeries Whether to delete all events in the series\n * @return {promise} Resolved with requested calendar event\n */\nexport const deleteEvent = (eventId, deleteSeries = false) => {\n const request = {\n methodname: 'core_calendar_delete_calendar_events',\n args: {\n events: [{\n eventid: eventId,\n repeat: deleteSeries,\n }]\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Get a calendar event by id.\n *\n * @method getEventById\n * @param {number} eventId The event id.\n * @return {promise} Resolved with requested calendar event\n */\nexport const getEventById = (eventId) => {\n\n const request = {\n methodname: 'core_calendar_get_calendar_event_by_id',\n args: {\n eventid: eventId\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Submit the form data for the event form.\n *\n * @method submitCreateUpdateForm\n * @param {string} formData The URL encoded values from the form\n * @return {promise} Resolved with the new or edited event\n */\nexport const submitCreateUpdateForm = (formData) => {\n const request = {\n methodname: 'core_calendar_submit_create_update_form',\n args: {\n formdata: formData\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Get calendar data for the month view.\n *\n * @method getCalendarMonthData\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} courseId The course id.\n * @param {number} categoryId The category id.\n * @param {boolean} includeNavigation Whether to include navigation.\n * @param {boolean} mini Whether the month is in mini view.\n * @param {number} day Day (optional)\n * @param {string} view The calendar view mode.\n * @return {promise} Resolved with the month view data.\n */\nexport const getCalendarMonthData = (year, month, courseId, categoryId, includeNavigation, mini, day = 1, view = 'month') => {\n const request = {\n methodname: 'core_calendar_get_calendar_monthly_view',\n args: {\n year,\n month,\n courseid: courseId,\n categoryid: categoryId,\n includenavigation: includeNavigation,\n mini,\n day,\n view,\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Get calendar data for the day view.\n *\n * @method getCalendarDayData\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} day Day\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @return {promise} Resolved with the day view data.\n */\nexport const getCalendarDayData = (year, month, day, courseId, categoryId) => {\n const request = {\n methodname: 'core_calendar_get_calendar_day_view',\n args: {\n year,\n month,\n day,\n courseid: courseId,\n categoryid: categoryId,\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Change the start day for the given event id. The day timestamp\n * only has to be any time during the target day because only the\n * date information is extracted, the time of the day is ignored.\n *\n * @param {int} eventId The id of the event to update\n * @param {int} dayTimestamp A timestamp for some time during the target day\n * @return {promise}\n */\nexport const updateEventStartDay = (eventId, dayTimestamp) => {\n const request = {\n methodname: 'core_calendar_update_event_start_day',\n args: {\n eventid: eventId,\n daytimestamp: dayTimestamp\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Get calendar upcoming data.\n *\n * @method getCalendarUpcomingData\n * @param {number} courseId The course id.\n * @param {number} categoryId The category id.\n * @return {promise} Resolved with the month view data.\n */\nexport const getCalendarUpcomingData = (courseId, categoryId) => {\n const request = {\n methodname: 'core_calendar_get_calendar_upcoming_view',\n args: {\n courseid: courseId,\n categoryid: categoryId,\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Get the groups by course id.\n *\n * @param {Number} courseId The course id to fetch the groups from.\n * @return {promise} Resolved with the course groups.\n */\nexport const getCourseGroupsData = (courseId) => {\n const request = {\n methodname: 'core_group_get_course_groups',\n args: {\n courseid: courseId\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Delete calendar subscription by id.\n *\n * @param {Number} subscriptionId The subscription id\n * @return {promise}\n */\nexport const deleteSubscription = (subscriptionId) => {\n const request = {\n methodname: 'core_calendar_delete_subscription',\n args: {\n subscriptionid: subscriptionId\n }\n };\n\n return Ajax.call([request])[0];\n};\n"],"file":"repository.min.js"}
\ No newline at end of file
+{"version":3,"file":"repository.min.js","sources":["../src/repository.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 .\n\n/**\n * A javascript module to handle calendar ajax actions.\n *\n * @module core_calendar/repository\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\n\n/**\n * Delete a calendar event.\n *\n * @method deleteEvent\n * @param {number} eventId The event id.\n * @param {boolean} deleteSeries Whether to delete all events in the series\n * @return {promise} Resolved with requested calendar event\n */\nexport const deleteEvent = (eventId, deleteSeries = false) => {\n const request = {\n methodname: 'core_calendar_delete_calendar_events',\n args: {\n events: [{\n eventid: eventId,\n repeat: deleteSeries,\n }]\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Get a calendar event by id.\n *\n * @method getEventById\n * @param {number} eventId The event id.\n * @return {promise} Resolved with requested calendar event\n */\nexport const getEventById = (eventId) => {\n\n const request = {\n methodname: 'core_calendar_get_calendar_event_by_id',\n args: {\n eventid: eventId\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Submit the form data for the event form.\n *\n * @method submitCreateUpdateForm\n * @param {string} formData The URL encoded values from the form\n * @return {promise} Resolved with the new or edited event\n */\nexport const submitCreateUpdateForm = (formData) => {\n const request = {\n methodname: 'core_calendar_submit_create_update_form',\n args: {\n formdata: formData\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Get calendar data for the month view.\n *\n * @method getCalendarMonthData\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} courseId The course id.\n * @param {number} categoryId The category id.\n * @param {boolean} includeNavigation Whether to include navigation.\n * @param {boolean} mini Whether the month is in mini view.\n * @param {number} day Day (optional)\n * @param {string} view The calendar view mode.\n * @return {promise} Resolved with the month view data.\n */\nexport const getCalendarMonthData = (year, month, courseId, categoryId, includeNavigation, mini, day = 1, view = 'month') => {\n const request = {\n methodname: 'core_calendar_get_calendar_monthly_view',\n args: {\n year,\n month,\n courseid: courseId,\n categoryid: categoryId,\n includenavigation: includeNavigation,\n mini,\n day,\n view,\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Get calendar data for the day view.\n *\n * @method getCalendarDayData\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} day Day\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @return {promise} Resolved with the day view data.\n */\nexport const getCalendarDayData = (year, month, day, courseId, categoryId) => {\n const request = {\n methodname: 'core_calendar_get_calendar_day_view',\n args: {\n year,\n month,\n day,\n courseid: courseId,\n categoryid: categoryId,\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Change the start day for the given event id. The day timestamp\n * only has to be any time during the target day because only the\n * date information is extracted, the time of the day is ignored.\n *\n * @param {int} eventId The id of the event to update\n * @param {int} dayTimestamp A timestamp for some time during the target day\n * @return {promise}\n */\nexport const updateEventStartDay = (eventId, dayTimestamp) => {\n const request = {\n methodname: 'core_calendar_update_event_start_day',\n args: {\n eventid: eventId,\n daytimestamp: dayTimestamp\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Get calendar upcoming data.\n *\n * @method getCalendarUpcomingData\n * @param {number} courseId The course id.\n * @param {number} categoryId The category id.\n * @return {promise} Resolved with the month view data.\n */\nexport const getCalendarUpcomingData = (courseId, categoryId) => {\n const request = {\n methodname: 'core_calendar_get_calendar_upcoming_view',\n args: {\n courseid: courseId,\n categoryid: categoryId,\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Get the groups by course id.\n *\n * @param {Number} courseId The course id to fetch the groups from.\n * @return {promise} Resolved with the course groups.\n */\nexport const getCourseGroupsData = (courseId) => {\n const request = {\n methodname: 'core_group_get_course_groups',\n args: {\n courseid: courseId\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Delete calendar subscription by id.\n *\n * @param {Number} subscriptionId The subscription id\n * @return {promise}\n */\nexport const deleteSubscription = (subscriptionId) => {\n const request = {\n methodname: 'core_calendar_delete_subscription',\n args: {\n subscriptionid: subscriptionId\n }\n };\n\n return Ajax.call([request])[0];\n};\n"],"names":["eventId","deleteSeries","request","methodname","args","events","eventid","repeat","Ajax","call","formData","formdata","year","month","courseId","categoryId","includeNavigation","mini","day","view","courseid","categoryid","includenavigation","dayTimestamp","daytimestamp","subscriptionId","subscriptionid"],"mappings":";;;;;;;yYAgC2B,SAACA,aAASC,2EAC3BC,QAAU,CACZC,WAAY,uCACZC,KAAM,CACFC,OAAQ,CAAC,CACLC,QAASN,QACTO,OAAQN,wBAKbO,cAAKC,KAAK,CAACP,UAAU,0BAUHF,gBAEnBE,QAAU,CACZC,WAAY,yCACZC,KAAM,CACFE,QAASN,iBAIVQ,cAAKC,KAAK,CAACP,UAAU,oCAUOQ,iBAC7BR,QAAU,CACZC,WAAY,0CACZC,KAAM,CACFO,SAAUD,kBAIXF,cAAKC,KAAK,CAACP,UAAU,kCAiBI,SAACU,KAAMC,MAAOC,SAAUC,WAAYC,kBAAmBC,UAAMC,2DAAM,EAAGC,4DAAO,cACvGjB,QAAU,CACZC,WAAY,0CACZC,KAAM,CACFQ,KAAAA,KACAC,MAAAA,MACAO,SAAUN,SACVO,WAAYN,WACZO,kBAAmBN,kBACnBC,KAAAA,KACAC,IAAAA,IACAC,KAAAA,cAIDX,cAAKC,KAAK,CAACP,UAAU,gCAcE,CAACU,KAAMC,MAAOK,IAAKJ,SAAUC,oBACrDb,QAAU,CACZC,WAAY,sCACZC,KAAM,CACFQ,KAAAA,KACAC,MAAAA,MACAK,IAAAA,IACAE,SAAUN,SACVO,WAAYN,oBAIbP,cAAKC,KAAK,CAACP,UAAU,iCAYG,CAACF,QAASuB,sBACnCrB,QAAU,CACZC,WAAY,uCACZC,KAAM,CACFE,QAASN,QACTwB,aAAcD,sBAIff,cAAKC,KAAK,CAACP,UAAU,qCAWO,CAACY,SAAUC,oBACxCb,QAAU,CACZC,WAAY,2CACZC,KAAM,CACFgB,SAAUN,SACVO,WAAYN,oBAIbP,cAAKC,KAAK,CAACP,UAAU,iCASIY,iBAC1BZ,QAAU,CACZC,WAAY,+BACZC,KAAM,CACFgB,SAAUN,kBAIXN,cAAKC,KAAK,CAACP,UAAU,gCASGuB,uBACzBvB,QAAU,CACZC,WAAY,oCACZC,KAAM,CACFsB,eAAgBD,wBAIjBjB,cAAKC,KAAK,CAACP,UAAU"}
\ No newline at end of file
diff --git a/calendar/amd/build/selectors.min.js b/calendar/amd/build/selectors.min.js
index aabd57706a3..70fa21dea38 100644
--- a/calendar/amd/build/selectors.min.js
+++ b/calendar/amd/build/selectors.min.js
@@ -1,2 +1,10 @@
-define ("core_calendar/selectors",[],function(){return{eventFilterItem:"[data-action='filter-event-type']",eventType:{site:"[data-eventtype-site]",category:"[data-eventtype-category]",course:"[data-eventtype-course]",group:"[data-eventtype-group]",user:"[data-eventtype-user]",other:"[data-eventtype-other]"},popoverType:{site:"[data-popover-eventtype-site]",category:"[data-popover-eventtype-category]",course:"[data-popover-eventtype-course]",group:"[data-popover-eventtype-group]",user:"[data-popover-eventtype-user]",other:"[data-popover-eventtype-other]"},calendarPeriods:{month:"[data-period='month']"},courseSelector:"select[name=\"course\"]",viewSelector:"div[data-region=\"view-selector\"]",actions:{create:"[data-action=\"new-event-button\"]",edit:"[data-action=\"edit\"]",remove:"[data-action=\"delete\"]",viewEvent:"[data-action=\"view-event\"]",deleteSubscription:"[data-action=\"delete-subscription\"]"},elements:{courseSelector:"select[name=\"course\"]",dateContainer:".clickable.hasevent",dateContent:"[data-region=\"day-content\"]",monthDetailed:".calendarmonth.calendartable"},today:".today",day:"[data-region=\"day\"]",calendarMain:"[data-region=\"calendar\"]",wrapper:".calendarwrapper",eventItem:"[data-type=\"event\"]",links:{navLink:".calendarwrapper .arrow_link",eventLink:"[data-region='event-item']",miniDayLink:"[data-region='mini-day-link']"},containers:{loadingIcon:"[data-region=\"overlay-icon-container\"]"},mainCalendar:".maincalendar .heightcontainer",fullCalendarView:"page-calendar-view"}});
-//# sourceMappingURL=selectors.min.js.map
+/**
+ * This module is responsible for the calendar filter.
+ *
+ * @module core_calendar/calendar_selectors
+ * @copyright 2017 Andrew Nicols
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/selectors",[],(function(){return{eventFilterItem:"[data-action='filter-event-type']",eventType:{site:"[data-eventtype-site]",category:"[data-eventtype-category]",course:"[data-eventtype-course]",group:"[data-eventtype-group]",user:"[data-eventtype-user]",other:"[data-eventtype-other]"},popoverType:{site:"[data-popover-eventtype-site]",category:"[data-popover-eventtype-category]",course:"[data-popover-eventtype-course]",group:"[data-popover-eventtype-group]",user:"[data-popover-eventtype-user]",other:"[data-popover-eventtype-other]"},calendarPeriods:{month:"[data-period='month']"},courseSelector:'select[name="course"]',viewSelector:'div[data-region="view-selector"]',actions:{create:'[data-action="new-event-button"]',edit:'[data-action="edit"]',remove:'[data-action="delete"]',viewEvent:'[data-action="view-event"]',deleteSubscription:'[data-action="delete-subscription"]'},elements:{courseSelector:'select[name="course"]',dateContainer:".clickable.hasevent",dateContent:'[data-region="day-content"]',monthDetailed:".calendarmonth.calendartable"},today:".today",day:'[data-region="day"]',calendarMain:'[data-region="calendar"]',wrapper:".calendarwrapper",eventItem:'[data-type="event"]',links:{navLink:".calendarwrapper .arrow_link",eventLink:"[data-region='event-item']",miniDayLink:"[data-region='mini-day-link']"},containers:{loadingIcon:'[data-region="overlay-icon-container"]'},mainCalendar:".maincalendar .heightcontainer",fullCalendarView:"page-calendar-view"}}));
+
+//# sourceMappingURL=selectors.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/selectors.min.js.map b/calendar/amd/build/selectors.min.js.map
index 432b56eab52..6a3984a1cfc 100644
--- a/calendar/amd/build/selectors.min.js.map
+++ b/calendar/amd/build/selectors.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/selectors.js"],"names":["define","eventFilterItem","eventType","site","category","course","group","user","other","popoverType","calendarPeriods","month","courseSelector","viewSelector","actions","create","edit","remove","viewEvent","deleteSubscription","elements","dateContainer","dateContent","monthDetailed","today","day","calendarMain","wrapper","eventItem","links","navLink","eventLink","miniDayLink","containers","loadingIcon","mainCalendar","fullCalendarView"],"mappings":"AAsBAA,OAAM,2BAAC,EAAD,CAAK,UAAW,CAClB,MAAO,CACHC,eAAe,CAAE,mCADd,CAEHC,SAAS,CAAE,CACPC,IAAI,CAAE,uBADC,CAEPC,QAAQ,CAAE,2BAFH,CAGPC,MAAM,CAAE,yBAHD,CAIPC,KAAK,CAAE,wBAJA,CAKPC,IAAI,CAAE,uBALC,CAMPC,KAAK,CAAE,wBANA,CAFR,CAUHC,WAAW,CAAE,CACTN,IAAI,CAAE,+BADG,CAETC,QAAQ,CAAE,mCAFD,CAGTC,MAAM,CAAE,iCAHC,CAITC,KAAK,CAAE,gCAJE,CAKTC,IAAI,CAAE,+BALG,CAMTC,KAAK,CAAE,gCANE,CAVV,CAkBHE,eAAe,CAAE,CACbC,KAAK,CAAE,uBADM,CAlBd,CAqBHC,cAAc,CAAE,yBArBb,CAsBHC,YAAY,CAAE,oCAtBX,CAuBHC,OAAO,CAAE,CACLC,MAAM,CAAE,oCADH,CAELC,IAAI,CAAE,wBAFD,CAGLC,MAAM,CAAE,0BAHH,CAILC,SAAS,CAAE,8BAJN,CAKLC,kBAAkB,CAAE,uCALf,CAvBN,CA8BHC,QAAQ,CAAE,CACNR,cAAc,CAAE,yBADV,CAENS,aAAa,CAAE,qBAFT,CAGNC,WAAW,CAAE,+BAHP,CAINC,aAAa,CAAE,8BAJT,CA9BP,CAoCHC,KAAK,CAAE,QApCJ,CAqCHC,GAAG,CAAE,uBArCF,CAsCHC,YAAY,CAAE,4BAtCX,CAuCHC,OAAO,CAAE,kBAvCN,CAwCHC,SAAS,CAAE,uBAxCR,CAyCHC,KAAK,CAAE,CACHC,OAAO,CAAE,8BADN,CAEHC,SAAS,CAAE,4BAFR,CAGHC,WAAW,CAAE,+BAHV,CAzCJ,CA8CHC,UAAU,CAAE,CACRC,WAAW,CAAE,0CADL,CA9CT,CAiDHC,YAAY,CAAE,gCAjDX,CAkDHC,gBAAgB,CAAE,oBAlDf,CAoDV,CArDK,CAAN","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 .\n\n/**\n * This module is responsible for the calendar filter.\n *\n * @module core_calendar/calendar_selectors\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n eventFilterItem: \"[data-action='filter-event-type']\",\n eventType: {\n site: \"[data-eventtype-site]\",\n category: \"[data-eventtype-category]\",\n course: \"[data-eventtype-course]\",\n group: \"[data-eventtype-group]\",\n user: \"[data-eventtype-user]\",\n other: \"[data-eventtype-other]\",\n },\n popoverType: {\n site: \"[data-popover-eventtype-site]\",\n category: \"[data-popover-eventtype-category]\",\n course: \"[data-popover-eventtype-course]\",\n group: \"[data-popover-eventtype-group]\",\n user: \"[data-popover-eventtype-user]\",\n other: \"[data-popover-eventtype-other]\",\n },\n calendarPeriods: {\n month: \"[data-period='month']\",\n },\n courseSelector: 'select[name=\"course\"]',\n viewSelector: 'div[data-region=\"view-selector\"]',\n actions: {\n create: '[data-action=\"new-event-button\"]',\n edit: '[data-action=\"edit\"]',\n remove: '[data-action=\"delete\"]',\n viewEvent: '[data-action=\"view-event\"]',\n deleteSubscription: '[data-action=\"delete-subscription\"]',\n },\n elements: {\n courseSelector: 'select[name=\"course\"]',\n dateContainer: '.clickable.hasevent',\n dateContent: '[data-region=\"day-content\"]',\n monthDetailed: '.calendarmonth.calendartable',\n },\n today: '.today',\n day: '[data-region=\"day\"]',\n calendarMain: '[data-region=\"calendar\"]',\n wrapper: '.calendarwrapper',\n eventItem: '[data-type=\"event\"]',\n links: {\n navLink: '.calendarwrapper .arrow_link',\n eventLink: \"[data-region='event-item']\",\n miniDayLink: \"[data-region='mini-day-link']\",\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n mainCalendar: '.maincalendar .heightcontainer',\n fullCalendarView: 'page-calendar-view',\n };\n});\n"],"file":"selectors.min.js"}
\ No newline at end of file
+{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 .\n\n/**\n * This module is responsible for the calendar filter.\n *\n * @module core_calendar/calendar_selectors\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n eventFilterItem: \"[data-action='filter-event-type']\",\n eventType: {\n site: \"[data-eventtype-site]\",\n category: \"[data-eventtype-category]\",\n course: \"[data-eventtype-course]\",\n group: \"[data-eventtype-group]\",\n user: \"[data-eventtype-user]\",\n other: \"[data-eventtype-other]\",\n },\n popoverType: {\n site: \"[data-popover-eventtype-site]\",\n category: \"[data-popover-eventtype-category]\",\n course: \"[data-popover-eventtype-course]\",\n group: \"[data-popover-eventtype-group]\",\n user: \"[data-popover-eventtype-user]\",\n other: \"[data-popover-eventtype-other]\",\n },\n calendarPeriods: {\n month: \"[data-period='month']\",\n },\n courseSelector: 'select[name=\"course\"]',\n viewSelector: 'div[data-region=\"view-selector\"]',\n actions: {\n create: '[data-action=\"new-event-button\"]',\n edit: '[data-action=\"edit\"]',\n remove: '[data-action=\"delete\"]',\n viewEvent: '[data-action=\"view-event\"]',\n deleteSubscription: '[data-action=\"delete-subscription\"]',\n },\n elements: {\n courseSelector: 'select[name=\"course\"]',\n dateContainer: '.clickable.hasevent',\n dateContent: '[data-region=\"day-content\"]',\n monthDetailed: '.calendarmonth.calendartable',\n },\n today: '.today',\n day: '[data-region=\"day\"]',\n calendarMain: '[data-region=\"calendar\"]',\n wrapper: '.calendarwrapper',\n eventItem: '[data-type=\"event\"]',\n links: {\n navLink: '.calendarwrapper .arrow_link',\n eventLink: \"[data-region='event-item']\",\n miniDayLink: \"[data-region='mini-day-link']\",\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n mainCalendar: '.maincalendar .heightcontainer',\n fullCalendarView: 'page-calendar-view',\n };\n});\n"],"names":["define","eventFilterItem","eventType","site","category","course","group","user","other","popoverType","calendarPeriods","month","courseSelector","viewSelector","actions","create","edit","remove","viewEvent","deleteSubscription","elements","dateContainer","dateContent","monthDetailed","today","day","calendarMain","wrapper","eventItem","links","navLink","eventLink","miniDayLink","containers","loadingIcon","mainCalendar","fullCalendarView"],"mappings":";;;;;;;AAsBAA,iCAAO,IAAI,iBACA,CACHC,gBAAiB,oCACjBC,UAAW,CACPC,KAAM,wBACNC,SAAU,4BACVC,OAAQ,0BACRC,MAAO,yBACPC,KAAM,wBACNC,MAAO,0BAEXC,YAAa,CACTN,KAAM,gCACNC,SAAU,oCACVC,OAAQ,kCACRC,MAAO,iCACPC,KAAM,gCACNC,MAAO,kCAEXE,gBAAiB,CACbC,MAAO,yBAEXC,eAAgB,wBAChBC,aAAc,mCACdC,QAAS,CACLC,OAAQ,mCACRC,KAAM,uBACNC,OAAQ,yBACRC,UAAW,6BACXC,mBAAoB,uCAExBC,SAAU,CACNR,eAAgB,wBAChBS,cAAe,sBACfC,YAAa,8BACbC,cAAe,gCAEnBC,MAAO,SACPC,IAAK,sBACLC,aAAc,2BACdC,QAAS,mBACTC,UAAW,sBACXC,MAAO,CACHC,QAAS,+BACTC,UAAW,6BACXC,YAAa,iCAEjBC,WAAY,CACRC,YAAa,0CAEjBC,aAAc,iCACdC,iBAAkB"}
\ No newline at end of file
diff --git a/calendar/amd/build/summary_modal.min.js b/calendar/amd/build/summary_modal.min.js
index dcba8cd4e5e..8d8df71f258 100644
--- a/calendar/amd/build/summary_modal.min.js
+++ b/calendar/amd/build/summary_modal.min.js
@@ -1,2 +1,10 @@
-define ("core_calendar/summary_modal",["jquery","core/str","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","core/modal_factory","core/modal_events","core_calendar/repository","core_calendar/events","core_calendar/crud"],function(a,b,c,d,e,f,g,h,i,j,k){var l=!1,m={ROOT:"[data-region='summary-modal-container']",EDIT_BUTTON:"[data-action=\"edit\"]",DELETE_BUTTON:"[data-action=\"delete\"]"},n=function(a){e.call(this,a)};n.TYPE="core_calendar-event_summary";n.prototype=Object.create(e.prototype);n.prototype.constructor=n;n.prototype.getEditButton=function(){if("undefined"==typeof this.editButton){this.editButton=this.getFooter().find(m.EDIT_BUTTON)}return this.editButton};n.prototype.getDeleteButton=function(){if("undefined"==typeof this.deleteButton){this.deleteButton=this.getFooter().find(m.DELETE_BUTTON)}return this.deleteButton};n.prototype.getEventId=function(){return this.getBody().find(m.ROOT).attr("data-event-id")};n.prototype.getEventTitle=function(){return this.getBody().find(m.ROOT).attr("data-event-title")};n.prototype.getEventCount=function(){return this.getBody().find(m.ROOT).attr("data-event-count")};n.prototype.getEditUrl=function(){return this.getBody().find(m.ROOT).attr("data-edit-url")};n.prototype.isActionEvent=function(){return"true"==this.getBody().find(m.ROOT).attr("data-action-event")};n.prototype.registerEventListeners=function(){e.prototype.registerEventListeners.call(this);M.util.js_pending("core_calendar/summary_modal:registerEventListeners:bodyRendered");this.getRoot().on(h.bodyRendered,function(){this.getModal().data({eventTitle:this.getEventTitle(),eventId:this.getEventId(),eventCount:this.getEventCount()}).attr("data-type","event");k.registerRemove(this.getModal());M.util.js_complete("core_calendar/summary_modal:registerEventListeners:bodyRendered")}.bind(this));a("body").on(j.deleted,function(){this.hide()}.bind(this));d.define(this.getEditButton(),[d.events.activate]);this.getEditButton().on(d.events.activate,function(b,c){if(this.isActionEvent()){a("body").trigger(j.editActionEvent,[this.getEditUrl()])}else{a("body").trigger(j.editEvent,[this.getEventId()])}this.hide();b.preventDefault();b.stopPropagation();c.originalEvent.preventDefault();c.originalEvent.stopPropagation()}.bind(this))};if(!l){f.register(n.TYPE,n,"core_calendar/event_summary_modal");l=!0}return n});
-//# sourceMappingURL=summary_modal.min.js.map
+/**
+ * A javascript module to handle summary modal.
+ *
+ * @module core_calendar/summary_modal
+ * @copyright 2017 Simey Lameze
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_calendar/summary_modal",["jquery","core/str","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","core/modal_factory","core/modal_events","core_calendar/repository","core_calendar/events","core_calendar/crud"],(function($,Str,Notification,CustomEvents,Modal,ModalRegistry,ModalFactory,ModalEvents,CalendarRepository,CalendarEvents,CalendarCrud){var registered=!1,SELECTORS_ROOT="[data-region='summary-modal-container']",SELECTORS_EDIT_BUTTON='[data-action="edit"]',SELECTORS_DELETE_BUTTON='[data-action="delete"]',ModalEventSummary=function(root){Modal.call(this,root)};return ModalEventSummary.TYPE="core_calendar-event_summary",(ModalEventSummary.prototype=Object.create(Modal.prototype)).constructor=ModalEventSummary,ModalEventSummary.prototype.getEditButton=function(){return void 0===this.editButton&&(this.editButton=this.getFooter().find(SELECTORS_EDIT_BUTTON)),this.editButton},ModalEventSummary.prototype.getDeleteButton=function(){return void 0===this.deleteButton&&(this.deleteButton=this.getFooter().find(SELECTORS_DELETE_BUTTON)),this.deleteButton},ModalEventSummary.prototype.getEventId=function(){return this.getBody().find(SELECTORS_ROOT).attr("data-event-id")},ModalEventSummary.prototype.getEventTitle=function(){return this.getBody().find(SELECTORS_ROOT).attr("data-event-title")},ModalEventSummary.prototype.getEventCount=function(){return this.getBody().find(SELECTORS_ROOT).attr("data-event-count")},ModalEventSummary.prototype.getEditUrl=function(){return this.getBody().find(SELECTORS_ROOT).attr("data-edit-url")},ModalEventSummary.prototype.isActionEvent=function(){return"true"==this.getBody().find(SELECTORS_ROOT).attr("data-action-event")},ModalEventSummary.prototype.registerEventListeners=function(){Modal.prototype.registerEventListeners.call(this),M.util.js_pending("core_calendar/summary_modal:registerEventListeners:bodyRendered"),this.getRoot().on(ModalEvents.bodyRendered,function(){this.getModal().data({eventTitle:this.getEventTitle(),eventId:this.getEventId(),eventCount:this.getEventCount()}).attr("data-type","event"),CalendarCrud.registerRemove(this.getModal()),M.util.js_complete("core_calendar/summary_modal:registerEventListeners:bodyRendered")}.bind(this)),$("body").on(CalendarEvents.deleted,function(){this.hide()}.bind(this)),CustomEvents.define(this.getEditButton(),[CustomEvents.events.activate]),this.getEditButton().on(CustomEvents.events.activate,function(e,data){this.isActionEvent()?$("body").trigger(CalendarEvents.editActionEvent,[this.getEditUrl()]):$("body").trigger(CalendarEvents.editEvent,[this.getEventId()]),this.hide(),e.preventDefault(),e.stopPropagation(),data.originalEvent.preventDefault(),data.originalEvent.stopPropagation()}.bind(this))},registered||(ModalRegistry.register(ModalEventSummary.TYPE,ModalEventSummary,"core_calendar/event_summary_modal"),registered=!0),ModalEventSummary}));
+
+//# sourceMappingURL=summary_modal.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/summary_modal.min.js.map b/calendar/amd/build/summary_modal.min.js.map
index bfc856849dd..423c4ada941 100644
--- a/calendar/amd/build/summary_modal.min.js.map
+++ b/calendar/amd/build/summary_modal.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/summary_modal.js"],"names":["define","$","Str","Notification","CustomEvents","Modal","ModalRegistry","ModalFactory","ModalEvents","CalendarRepository","CalendarEvents","CalendarCrud","registered","SELECTORS","ROOT","EDIT_BUTTON","DELETE_BUTTON","ModalEventSummary","root","call","TYPE","prototype","Object","create","constructor","getEditButton","editButton","getFooter","find","getDeleteButton","deleteButton","getEventId","getBody","attr","getEventTitle","getEventCount","getEditUrl","isActionEvent","registerEventListeners","M","util","js_pending","getRoot","on","bodyRendered","getModal","data","eventTitle","eventId","eventCount","registerRemove","js_complete","bind","deleted","hide","events","activate","e","trigger","editActionEvent","editEvent","preventDefault","stopPropagation","originalEvent","register"],"mappings":"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","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 .\n\n/**\n * A javascript module to handle summary modal.\n *\n * @module core_calendar/summary_modal\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_registry',\n 'core/modal_factory',\n 'core/modal_events',\n 'core_calendar/repository',\n 'core_calendar/events',\n 'core_calendar/crud',\n],\nfunction(\n $,\n Str,\n Notification,\n CustomEvents,\n Modal,\n ModalRegistry,\n ModalFactory,\n ModalEvents,\n CalendarRepository,\n CalendarEvents,\n CalendarCrud\n) {\n\n var registered = false;\n var SELECTORS = {\n ROOT: \"[data-region='summary-modal-container']\",\n EDIT_BUTTON: '[data-action=\"edit\"]',\n DELETE_BUTTON: '[data-action=\"delete\"]',\n };\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var ModalEventSummary = function(root) {\n Modal.call(this, root);\n };\n\n ModalEventSummary.TYPE = 'core_calendar-event_summary';\n ModalEventSummary.prototype = Object.create(Modal.prototype);\n ModalEventSummary.prototype.constructor = ModalEventSummary;\n\n /**\n * Get the edit button element from the footer. The button is cached\n * as it's not expected to change.\n *\n * @method getEditButton\n * @return {object} button element\n */\n ModalEventSummary.prototype.getEditButton = function() {\n if (typeof this.editButton == 'undefined') {\n this.editButton = this.getFooter().find(SELECTORS.EDIT_BUTTON);\n }\n\n return this.editButton;\n };\n\n /**\n * Get the delete button element from the footer. The button is cached\n * as it's not expected to change.\n *\n * @method getDeleteButton\n * @return {object} button element\n */\n ModalEventSummary.prototype.getDeleteButton = function() {\n if (typeof this.deleteButton == 'undefined') {\n this.deleteButton = this.getFooter().find(SELECTORS.DELETE_BUTTON);\n }\n\n return this.deleteButton;\n };\n\n /**\n * Get the id for the event being shown in this modal. This value is\n * not cached because it will change depending on which event is\n * being displayed.\n *\n * @method getEventId\n * @return {int}\n */\n ModalEventSummary.prototype.getEventId = function() {\n return this.getBody().find(SELECTORS.ROOT).attr('data-event-id');\n };\n\n /**\n * Get the title for the event being shown in this modal. This value is\n * not cached because it will change depending on which event is\n * being displayed.\n *\n * @method getEventTitle\n * @return {String}\n */\n ModalEventSummary.prototype.getEventTitle = function() {\n return this.getBody().find(SELECTORS.ROOT).attr('data-event-title');\n };\n\n /**\n * Get the number of events in the series for the event being shown in\n * this modal. This value is not cached because it will change\n * depending on which event is being displayed.\n *\n * @method getEventCount\n * @return {int}\n */\n ModalEventSummary.prototype.getEventCount = function() {\n return this.getBody().find(SELECTORS.ROOT).attr('data-event-count');\n };\n\n /**\n * Get the url for the event being shown in this modal.\n *\n * @method getEventUrl\n * @return {String}\n */\n ModalEventSummary.prototype.getEditUrl = function() {\n return this.getBody().find(SELECTORS.ROOT).attr('data-edit-url');\n };\n\n /**\n * Is this an action event.\n *\n * @method getEventUrl\n * @return {String}\n */\n ModalEventSummary.prototype.isActionEvent = function() {\n return (this.getBody().find(SELECTORS.ROOT).attr('data-action-event') == 'true');\n };\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n */\n ModalEventSummary.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n // We have to wait for the modal to finish rendering in order to ensure that\n // the data-event-title property is available to use as the modal title.\n M.util.js_pending('core_calendar/summary_modal:registerEventListeners:bodyRendered');\n this.getRoot().on(ModalEvents.bodyRendered, function() {\n this.getModal().data({\n eventTitle: this.getEventTitle(),\n eventId: this.getEventId(),\n eventCount: this.getEventCount(),\n })\n .attr('data-type', 'event');\n CalendarCrud.registerRemove(this.getModal());\n M.util.js_complete('core_calendar/summary_modal:registerEventListeners:bodyRendered');\n }.bind(this));\n\n $('body').on(CalendarEvents.deleted, function() {\n // Close the dialogue on delete.\n this.hide();\n }.bind(this));\n\n CustomEvents.define(this.getEditButton(), [\n CustomEvents.events.activate\n ]);\n\n this.getEditButton().on(CustomEvents.events.activate, function(e, data) {\n if (this.isActionEvent()) {\n // Action events cannot be edited on the event form and must be redirected to the module UI.\n $('body').trigger(CalendarEvents.editActionEvent, [this.getEditUrl()]);\n } else {\n // When the edit button is clicked we fire an event for the calendar UI to handle.\n // We don't care how the UI chooses to handle it.\n $('body').trigger(CalendarEvents.editEvent, [this.getEventId()]);\n }\n\n // There is nothing else for us to do so let's hide.\n this.hide();\n\n // We've handled this event so no need to propagate it.\n e.preventDefault();\n e.stopPropagation();\n data.originalEvent.preventDefault();\n data.originalEvent.stopPropagation();\n }.bind(this));\n };\n\n // Automatically register with the modal registry the first time this module is imported so that you can create modals\n // of this type using the modal factory.\n if (!registered) {\n ModalRegistry.register(ModalEventSummary.TYPE, ModalEventSummary, 'core_calendar/event_summary_modal');\n registered = true;\n }\n\n return ModalEventSummary;\n});\n"],"file":"summary_modal.min.js"}
\ No newline at end of file
+{"version":3,"file":"summary_modal.min.js","sources":["../src/summary_modal.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 .\n\n/**\n * A javascript module to handle summary modal.\n *\n * @module core_calendar/summary_modal\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_registry',\n 'core/modal_factory',\n 'core/modal_events',\n 'core_calendar/repository',\n 'core_calendar/events',\n 'core_calendar/crud',\n],\nfunction(\n $,\n Str,\n Notification,\n CustomEvents,\n Modal,\n ModalRegistry,\n ModalFactory,\n ModalEvents,\n CalendarRepository,\n CalendarEvents,\n CalendarCrud\n) {\n\n var registered = false;\n var SELECTORS = {\n ROOT: \"[data-region='summary-modal-container']\",\n EDIT_BUTTON: '[data-action=\"edit\"]',\n DELETE_BUTTON: '[data-action=\"delete\"]',\n };\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var ModalEventSummary = function(root) {\n Modal.call(this, root);\n };\n\n ModalEventSummary.TYPE = 'core_calendar-event_summary';\n ModalEventSummary.prototype = Object.create(Modal.prototype);\n ModalEventSummary.prototype.constructor = ModalEventSummary;\n\n /**\n * Get the edit button element from the footer. The button is cached\n * as it's not expected to change.\n *\n * @method getEditButton\n * @return {object} button element\n */\n ModalEventSummary.prototype.getEditButton = function() {\n if (typeof this.editButton == 'undefined') {\n this.editButton = this.getFooter().find(SELECTORS.EDIT_BUTTON);\n }\n\n return this.editButton;\n };\n\n /**\n * Get the delete button element from the footer. The button is cached\n * as it's not expected to change.\n *\n * @method getDeleteButton\n * @return {object} button element\n */\n ModalEventSummary.prototype.getDeleteButton = function() {\n if (typeof this.deleteButton == 'undefined') {\n this.deleteButton = this.getFooter().find(SELECTORS.DELETE_BUTTON);\n }\n\n return this.deleteButton;\n };\n\n /**\n * Get the id for the event being shown in this modal. This value is\n * not cached because it will change depending on which event is\n * being displayed.\n *\n * @method getEventId\n * @return {int}\n */\n ModalEventSummary.prototype.getEventId = function() {\n return this.getBody().find(SELECTORS.ROOT).attr('data-event-id');\n };\n\n /**\n * Get the title for the event being shown in this modal. This value is\n * not cached because it will change depending on which event is\n * being displayed.\n *\n * @method getEventTitle\n * @return {String}\n */\n ModalEventSummary.prototype.getEventTitle = function() {\n return this.getBody().find(SELECTORS.ROOT).attr('data-event-title');\n };\n\n /**\n * Get the number of events in the series for the event being shown in\n * this modal. This value is not cached because it will change\n * depending on which event is being displayed.\n *\n * @method getEventCount\n * @return {int}\n */\n ModalEventSummary.prototype.getEventCount = function() {\n return this.getBody().find(SELECTORS.ROOT).attr('data-event-count');\n };\n\n /**\n * Get the url for the event being shown in this modal.\n *\n * @method getEventUrl\n * @return {String}\n */\n ModalEventSummary.prototype.getEditUrl = function() {\n return this.getBody().find(SELECTORS.ROOT).attr('data-edit-url');\n };\n\n /**\n * Is this an action event.\n *\n * @method getEventUrl\n * @return {String}\n */\n ModalEventSummary.prototype.isActionEvent = function() {\n return (this.getBody().find(SELECTORS.ROOT).attr('data-action-event') == 'true');\n };\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n */\n ModalEventSummary.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n // We have to wait for the modal to finish rendering in order to ensure that\n // the data-event-title property is available to use as the modal title.\n M.util.js_pending('core_calendar/summary_modal:registerEventListeners:bodyRendered');\n this.getRoot().on(ModalEvents.bodyRendered, function() {\n this.getModal().data({\n eventTitle: this.getEventTitle(),\n eventId: this.getEventId(),\n eventCount: this.getEventCount(),\n })\n .attr('data-type', 'event');\n CalendarCrud.registerRemove(this.getModal());\n M.util.js_complete('core_calendar/summary_modal:registerEventListeners:bodyRendered');\n }.bind(this));\n\n $('body').on(CalendarEvents.deleted, function() {\n // Close the dialogue on delete.\n this.hide();\n }.bind(this));\n\n CustomEvents.define(this.getEditButton(), [\n CustomEvents.events.activate\n ]);\n\n this.getEditButton().on(CustomEvents.events.activate, function(e, data) {\n if (this.isActionEvent()) {\n // Action events cannot be edited on the event form and must be redirected to the module UI.\n $('body').trigger(CalendarEvents.editActionEvent, [this.getEditUrl()]);\n } else {\n // When the edit button is clicked we fire an event for the calendar UI to handle.\n // We don't care how the UI chooses to handle it.\n $('body').trigger(CalendarEvents.editEvent, [this.getEventId()]);\n }\n\n // There is nothing else for us to do so let's hide.\n this.hide();\n\n // We've handled this event so no need to propagate it.\n e.preventDefault();\n e.stopPropagation();\n data.originalEvent.preventDefault();\n data.originalEvent.stopPropagation();\n }.bind(this));\n };\n\n // Automatically register with the modal registry the first time this module is imported so that you can create modals\n // of this type using the modal factory.\n if (!registered) {\n ModalRegistry.register(ModalEventSummary.TYPE, ModalEventSummary, 'core_calendar/event_summary_modal');\n registered = true;\n }\n\n return ModalEventSummary;\n});\n"],"names":["define","$","Str","Notification","CustomEvents","Modal","ModalRegistry","ModalFactory","ModalEvents","CalendarRepository","CalendarEvents","CalendarCrud","registered","SELECTORS","ModalEventSummary","root","call","this","TYPE","prototype","Object","create","constructor","getEditButton","editButton","getFooter","find","getDeleteButton","deleteButton","getEventId","getBody","attr","getEventTitle","getEventCount","getEditUrl","isActionEvent","registerEventListeners","M","util","js_pending","getRoot","on","bodyRendered","getModal","data","eventTitle","eventId","eventCount","registerRemove","js_complete","bind","deleted","hide","events","activate","e","trigger","editActionEvent","editEvent","preventDefault","stopPropagation","originalEvent","register"],"mappings":";;;;;;;AAsBAA,qCAAO,CACH,SACA,WACA,oBACA,iCACA,aACA,sBACA,qBACA,oBACA,2BACA,uBACA,uBAEJ,SACIC,EACAC,IACAC,aACAC,aACAC,MACAC,cACAC,aACAC,YACAC,mBACAC,eACAC,kBAGIC,YAAa,EACbC,eACM,0CADNA,sBAEa,uBAFbA,wBAGe,yBAQfC,kBAAoB,SAASC,MAC7BV,MAAMW,KAAKC,KAAMF,cAGrBD,kBAAkBI,KAAO,+BACzBJ,kBAAkBK,UAAYC,OAAOC,OAAOhB,MAAMc,YACtBG,YAAcR,kBAS1CA,kBAAkBK,UAAUI,cAAgB,uBACV,IAAnBN,KAAKO,kBACPA,WAAaP,KAAKQ,YAAYC,KAAKb,wBAGrCI,KAAKO,YAUhBV,kBAAkBK,UAAUQ,gBAAkB,uBACV,IAArBV,KAAKW,oBACPA,aAAeX,KAAKQ,YAAYC,KAAKb,0BAGvCI,KAAKW,cAWhBd,kBAAkBK,UAAUU,WAAa,kBAC9BZ,KAAKa,UAAUJ,KAAKb,gBAAgBkB,KAAK,kBAWpDjB,kBAAkBK,UAAUa,cAAgB,kBACjCf,KAAKa,UAAUJ,KAAKb,gBAAgBkB,KAAK,qBAWpDjB,kBAAkBK,UAAUc,cAAgB,kBACjChB,KAAKa,UAAUJ,KAAKb,gBAAgBkB,KAAK,qBASpDjB,kBAAkBK,UAAUe,WAAa,kBAC9BjB,KAAKa,UAAUJ,KAAKb,gBAAgBkB,KAAK,kBASpDjB,kBAAkBK,UAAUgB,cAAgB,iBACiC,QAAjElB,KAAKa,UAAUJ,KAAKb,gBAAgBkB,KAAK,sBAQrDjB,kBAAkBK,UAAUiB,uBAAyB,WAEjD/B,MAAMc,UAAUiB,uBAAuBpB,KAAKC,MAI5CoB,EAAEC,KAAKC,WAAW,wEACbC,UAAUC,GAAGjC,YAAYkC,aAAc,gBACnCC,WAAWC,KAAK,CACjBC,WAAY5B,KAAKe,gBACjBc,QAAS7B,KAAKY,aACdkB,WAAY9B,KAAKgB,kBAEpBF,KAAK,YAAa,SACnBpB,aAAaqC,eAAe/B,KAAK0B,YACjCN,EAAEC,KAAKW,YAAY,oEACrBC,KAAKjC,OAEPhB,EAAE,QAAQwC,GAAG/B,eAAeyC,QAAS,gBAE5BC,QACPF,KAAKjC,OAEPb,aAAaJ,OAAOiB,KAAKM,gBAAiB,CACtCnB,aAAaiD,OAAOC,gBAGnB/B,gBAAgBkB,GAAGrC,aAAaiD,OAAOC,SAAU,SAASC,EAAGX,MAC1D3B,KAAKkB,gBAELlC,EAAE,QAAQuD,QAAQ9C,eAAe+C,gBAAiB,CAACxC,KAAKiB,eAIxDjC,EAAE,QAAQuD,QAAQ9C,eAAegD,UAAW,CAACzC,KAAKY,oBAIjDuB,OAGLG,EAAEI,iBACFJ,EAAEK,kBACFhB,KAAKiB,cAAcF,iBACnBf,KAAKiB,cAAcD,mBACrBV,KAAKjC,QAKNL,aACDN,cAAcwD,SAAShD,kBAAkBI,KAAMJ,kBAAmB,qCAClEF,YAAa,GAGVE"}
\ No newline at end of file
diff --git a/calendar/amd/build/view_manager.min.js b/calendar/amd/build/view_manager.min.js
index 32f1f9f048a..797eb83e456 100644
--- a/calendar/amd/build/view_manager.min.js
+++ b/calendar/amd/build/view_manager.min.js
@@ -1,2 +1,10 @@
-function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core_calendar/view_manager",["exports","jquery","core/templates","core/notification","core_calendar/repository","core_calendar/events","core_calendar/selectors","core/modal_factory","core/modal_events","core_calendar/summary_modal","core/custom_interaction_events","core/str","core/pending","core/prefetch"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=a.reloadCurrentUpcoming=a.updateUrl=a.changeDay=a.reloadCurrentDay=a.refreshDayContent=a.reloadCurrentMonth=a.changeMonth=a.refreshMonthContent=a.registerEventListenersForMonthDetailed=a.foldDayEvents=void 0;b=q(b);c=q(c);d=q(d);e=p(e);f=q(f);g=p(g);h=q(h);i=q(i);j=q(j);k=q(k);m=q(m);function o(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;o=function(){return a};return a}function p(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=o();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function q(a){return a&&a.__esModule?a:{default:a}}var r=function(){var a=(0,b.default)(g.elements.monthDetailed),c=a.find(g.day);if(0===c.length){return}c.each(function(){var a=(0,b.default)(this),c="".concat(g.elements.dateContent," ul li[data-event-eventtype]"),d="".concat(g.elements.dateContent," ul li[data-event-filtered=\"true\"]"),e="".concat(g.elements.dateContent," [data-action=\"view-more-events\"]"),f=a.find(c);if(0===f.length){return}var h=a.find(d),i=h.length,j=f.length-i,k=1;f.each(function(){var a=(0,b.default)(this),c="true"!==a.attr("data-event-filtered"),d=j===5?0:1;if(c){if(k>5-d){a.attr("data-event-folded","true");a.hide()}else{a.attr("data-event-folded","false");a.show();k++}}else{a.attr("data-event-folded","false")}});var m=a.find(e);if(j>5){m.show();(0,l.get_string)("moreevents","calendar",j-5+1).then(function(a){var b=m.find("strong a");m.attr("data-event-folded","false");b.text(a);return a}).fail()}else{m.hide()}})};a.foldDayEvents=r;var s=function(a){var c="".concat(f.default.viewUpdated);(0,b.default)("body").on(c,function(a){r(a)});r();(0,b.default)("body").on(f.default.filterChanged,function(c,d){var e=(0,b.default)(g.elements.monthDetailed),f=new m.default(a),h=e.find(g.eventType[d.type]),i=b.default.Deferred();if(d.hidden){i.then(function(){h.attr("data-event-filtered","true");return h.hide().promise()}).fail()}else{i.then(function(){h.attr("data-event-filtered","false");return h.show().promise()}).fail()}i.then(function(){r()}).always(f.resolve).fail();i.resolve()})};a.registerEventListenersForMonthDetailed=s;var t=function(a){a=(0,b.default)(a);a.on("click",g.links.eventLink,function(a){var b=a.target,c=null,d=null,e=new m.default("core_calendar/view_manager:eventLink:click");if(b.matches(g.actions.viewEvent)){c=b}else{c=b.closest(g.actions.viewEvent)}if(c){d=c.dataset.eventId}else{d=b.querySelector(g.actions.viewEvent).dataset.eventId}if(d){a.preventDefault();a.stopPropagation();F(d).then(e.resolve).catch()}else{e.resolve()}});a.on("click",g.links.navLink,function(b){var c=a.find(g.wrapper),d=c.data("view"),e=c.data("courseid"),f=c.data("categoryid"),h=b.currentTarget;if("month"===d||"monthblock"===d){v(a,h.href,h.dataset.year,h.dataset.month,e,f,h.dataset.day);b.preventDefault()}else if("day"===d){z(a,h.href,h.dataset.year,h.dataset.month,h.dataset.day,e,f);b.preventDefault()}});var c=a.find(g.viewSelector);k.default.define(c,[k.default.events.activate]);c.on(k.default.events.activate,function(b){b.preventDefault();var c=b.target;if(c.classList.contains("active")){return}var e=c.dataset.view,f=c.dataset.year,g=c.dataset.month,h=c.dataset.day,i=c.dataset.courseid,j=c.dataset.categoryid;if("month"==e){u(a,f,g,i,j,a,"core_calendar/calendar_month",h).then(function(){A("?view=month")}).fail(d.default.exception)}else if("day"==e){x(a,f,g,h,i,j,a,"core_calendar/calendar_day").then(function(){A("?view=day")}).fail(d.default.exception)}else if("upcoming"==e){D(a,i,j,a,"core_calendar/calendar_upcoming").then(function(){A("?view=upcoming")}).fail(d.default.exception)}})},u=function(a,b,h,i,j){var k=5
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.updateUrl=_exports.reloadCurrentUpcoming=_exports.reloadCurrentMonth=_exports.reloadCurrentDay=_exports.registerEventListenersForMonthDetailed=_exports.refreshMonthContent=_exports.refreshDayContent=_exports.init=_exports.foldDayEvents=_exports.changeMonth=_exports.changeDay=void 0,_jquery=_interopRequireDefault(_jquery),_templates=_interopRequireDefault(_templates),_notification=_interopRequireDefault(_notification),CalendarRepository=_interopRequireWildcard(CalendarRepository),_events=_interopRequireDefault(_events),CalendarSelectors=_interopRequireWildcard(CalendarSelectors),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_summary_modal=_interopRequireDefault(_summary_modal),_custom_interaction_events=_interopRequireDefault(_custom_interaction_events),_pending=_interopRequireDefault(_pending);const foldDayEvents=()=>{const days=(0,_jquery.default)(CalendarSelectors.elements.monthDetailed).find(CalendarSelectors.day);0!==days.length&&days.each((function(){const dayContainer=(0,_jquery.default)(this),eventsSelector="".concat(CalendarSelectors.elements.dateContent," ul li[data-event-eventtype]"),filteredEventsSelector="".concat(CalendarSelectors.elements.dateContent,' ul li[data-event-filtered="true"]'),moreEventsSelector="".concat(CalendarSelectors.elements.dateContent,' [data-action="view-more-events"]'),events=dayContainer.find(eventsSelector);if(0===events.length)return;const numberOfFiltered=dayContainer.find(filteredEventsSelector).length,numberOfEvents=events.length-numberOfFiltered;let count=1;events.each((function(){const event=(0,_jquery.default)(this);"true"!==event.attr("data-event-filtered")?count>5-(5===numberOfEvents?0:1)?(event.attr("data-event-folded","true"),event.hide()):(event.attr("data-event-folded","false"),event.show(),count++):event.attr("data-event-folded","false")}));const moreEventsLink=dayContainer.find(moreEventsSelector);if(numberOfEvents>5){const numberOfHiddenEvents=numberOfEvents-5+1;moreEventsLink.show(),(0,_str.get_string)("moreevents","calendar",numberOfHiddenEvents).then((str=>{const link=moreEventsLink.find("strong a");return moreEventsLink.attr("data-event-folded","false"),link.text(str),str})).fail()}else moreEventsLink.hide()}))};_exports.foldDayEvents=foldDayEvents;const registerEventListenersForMonthDetailed=pendingId=>{const events="".concat(_events.default.viewUpdated);(0,_jquery.default)("body").on(events,(function(e){foldDayEvents()})),foldDayEvents(),(0,_jquery.default)("body").on(_events.default.filterChanged,(function(e,data){const root=(0,_jquery.default)(CalendarSelectors.elements.monthDetailed),pending=new _pending.default(pendingId),target=root.find(CalendarSelectors.eventType[data.type]),transitionPromise=_jquery.default.Deferred();data.hidden?transitionPromise.then((function(){return target.attr("data-event-filtered","true"),target.hide().promise()})).fail():transitionPromise.then((function(){return target.attr("data-event-filtered","false"),target.show().promise()})).fail(),transitionPromise.then((function(){foldDayEvents()})).always(pending.resolve).fail(),transitionPromise.resolve()}))};_exports.registerEventListenersForMonthDetailed=registerEventListenersForMonthDetailed;const refreshMonthContent=function(root,year,month,courseId,categoryId){let target=arguments.length>5&&void 0!==arguments[5]?arguments[5]:null,template=arguments.length>6&&void 0!==arguments[6]?arguments[6]:"",day=arguments.length>7&&void 0!==arguments[7]?arguments[7]:1;startLoading(root),target=target||root.find(CalendarSelectors.wrapper),template=template||root.attr("data-template"),M.util.js_pending([root.get("id"),year,month,courseId].join("-"));const includenavigation=root.data("includenavigation"),mini=root.data("mini"),viewMode=target.data("view");return CalendarRepository.getCalendarMonthData(year,month,courseId,categoryId,includenavigation,mini,day,viewMode).then((context=>_templates.default.render(template,context))).then(((html,js)=>_templates.default.replaceNode(target,html,js))).then((()=>{document.querySelector("body").dispatchEvent(new CustomEvent(_events.default.viewUpdated))})).always((()=>(M.util.js_complete([root.get("id"),year,month,courseId].join("-")),stopLoading(root)))).fail(_notification.default.exception)};_exports.refreshMonthContent=refreshMonthContent;const changeMonth=function(root,url,year,month,courseId,categoryId){let day=arguments.length>6&&void 0!==arguments[6]?arguments[6]:1;return refreshMonthContent(root,year,month,courseId,categoryId,null,"",day).then((function(){url.length&&"#"!==url&&updateUrl(url);for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++)args[_key]=arguments[_key];return args})).then((function(){(0,_jquery.default)("body").trigger(_events.default.monthChanged,[year,month,courseId,categoryId]);for(var _len2=arguments.length,args=new Array(_len2),_key2=0;_key2<_len2;_key2++)args[_key2]=arguments[_key2];return args}))};_exports.changeMonth=changeMonth;_exports.reloadCurrentMonth=function(root){let courseId=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,categoryId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;const year=root.find(CalendarSelectors.wrapper).data("year"),month=root.find(CalendarSelectors.wrapper).data("month"),day=root.find(CalendarSelectors.wrapper).data("day");return courseId=courseId||root.find(CalendarSelectors.wrapper).data("courseid"),categoryId=categoryId||root.find(CalendarSelectors.wrapper).data("categoryid"),refreshMonthContent(root,year,month,courseId,categoryId,null,"",day).then((function(){(0,_jquery.default)("body").trigger(_events.default.courseChanged,[year,month,courseId,categoryId]);for(var _len3=arguments.length,args=new Array(_len3),_key3=0;_key3<_len3;_key3++)args[_key3]=arguments[_key3];return args}))};const refreshDayContent=function(root,year,month,day,courseId,categoryId){let target=arguments.length>6&&void 0!==arguments[6]?arguments[6]:null,template=arguments.length>7&&void 0!==arguments[7]?arguments[7]:"";startLoading(root),target&&0!=target.length||(target=root.find(CalendarSelectors.wrapper)),template=template||root.attr("data-template"),M.util.js_pending([root.get("id"),year,month,day,courseId,categoryId].join("-"));const includenavigation=root.data("includenavigation");return CalendarRepository.getCalendarDayData(year,month,day,courseId,categoryId,includenavigation).then((context=>(context.viewingday=!0,context.showviewselector=!0,_templates.default.render(template,context)))).then(((html,js)=>_templates.default.replaceNode(target,html,js))).then((()=>{document.querySelector("body").dispatchEvent(new CustomEvent(_events.default.viewUpdated))})).always((()=>(M.util.js_complete([root.get("id"),year,month,day,courseId,categoryId].join("-")),stopLoading(root)))).fail(_notification.default.exception)};_exports.refreshDayContent=refreshDayContent;_exports.reloadCurrentDay=function(root){let courseId=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,categoryId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;const wrapper=root.find(CalendarSelectors.wrapper),year=wrapper.data("year"),month=wrapper.data("month"),day=wrapper.data("day");return courseId=courseId||root.find(CalendarSelectors.wrapper).data("courseid"),categoryId=categoryId||root.find(CalendarSelectors.wrapper).data("categoryid"),refreshDayContent(root,year,month,day,courseId,categoryId)};const changeDay=(root,url,year,month,day,courseId,categoryId)=>refreshDayContent(root,year,month,day,courseId,categoryId).then((function(){url.length&&"#"!==url&&updateUrl(url);for(var _len4=arguments.length,args=new Array(_len4),_key4=0;_key4<_len4;_key4++)args[_key4]=arguments[_key4];return args})).then((function(){(0,_jquery.default)("body").trigger(_events.default.dayChanged,[year,month,courseId,categoryId]);for(var _len5=arguments.length,args=new Array(_len5),_key5=0;_key5<_len5;_key5++)args[_key5]=arguments[_key5];return args}));_exports.changeDay=changeDay;const updateUrl=url=>{document.getElementById(CalendarSelectors.fullCalendarView)&&window.history.pushState({},"",url)};_exports.updateUrl=updateUrl;const startLoading=root=>{root.find(CalendarSelectors.containers.loadingIcon).removeClass("hidden")},stopLoading=root=>{root.find(CalendarSelectors.containers.loadingIcon).addClass("hidden")},reloadCurrentUpcoming=function(root){let courseId=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,categoryId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,target=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,template=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"";return startLoading(root),target=target||root.find(CalendarSelectors.wrapper),template=template||root.attr("data-template"),courseId=courseId||root.find(CalendarSelectors.wrapper).data("courseid"),categoryId=categoryId||root.find(CalendarSelectors.wrapper).data("categoryid"),CalendarRepository.getCalendarUpcomingData(courseId,categoryId).then((context=>(context.viewingupcoming=!0,context.showviewselector=!0,_templates.default.render(template,context)))).then(((html,js)=>_templates.default.replaceNode(target,html,js))).then((()=>{document.querySelector("body").dispatchEvent(new CustomEvent(_events.default.viewUpdated))})).always((function(){return stopLoading(root)})).fail(_notification.default.exception)};_exports.reloadCurrentUpcoming=reloadCurrentUpcoming;const renderEventSummaryModal=eventId=>{const pendingPromise=new _pending.default("core_calendar/view_manager:renderEventSummaryModal");return CalendarRepository.getEventById(eventId).then((getEventResponse=>{if(!getEventResponse.event)throw new Error("Error encountered while trying to fetch calendar event with ID: "+eventId);return getEventResponse.event})).then((eventData=>{const modalParams={title:eventData.name,type:_summary_modal.default.TYPE,body:_templates.default.render("core_calendar/event_summary_body",eventData),templateContext:{canedit:eventData.canedit,candelete:eventData.candelete,headerclasses:(eventType=eventData.normalisedeventtype,"calendar_event_"+eventType),isactionevent:eventData.isactionevent,url:eventData.url,action:eventData.action}};var eventType;return _modal_factory.default.create(modalParams)})).then((modal=>(modal.getRoot().on(_modal_events.default.hidden,(function(){modal.destroy()})),modal.show(),modal))).then((modal=>(pendingPromise.resolve(),modal))).catch(_notification.default.exception)};_exports.init=(root,view)=>{(0,_prefetch.prefetchStrings)("calendar",["moreevents"]),foldDayEvents(),(root=>{(root=(0,_jquery.default)(root)).on("click",CalendarSelectors.links.eventLink,(e=>{const target=e.target;let eventLink=null,eventId=null;const pendingPromise=new _pending.default("core_calendar/view_manager:eventLink:click");eventLink=target.matches(CalendarSelectors.actions.viewEvent)?target:target.closest(CalendarSelectors.actions.viewEvent),eventId=eventLink?eventLink.dataset.eventId:target.querySelector(CalendarSelectors.actions.viewEvent).dataset.eventId,eventId?(e.preventDefault(),e.stopPropagation(),renderEventSummaryModal(eventId).then(pendingPromise.resolve).catch()):pendingPromise.resolve()})),root.on("click",CalendarSelectors.links.navLink,(e=>{const wrapper=root.find(CalendarSelectors.wrapper),view=wrapper.data("view"),courseId=wrapper.data("courseid"),categoryId=wrapper.data("categoryid"),link=e.currentTarget;"month"===view||"monthblock"===view?(changeMonth(root,link.href,link.dataset.year,link.dataset.month,courseId,categoryId,link.dataset.day),e.preventDefault()):"day"===view&&(changeDay(root,link.href,link.dataset.year,link.dataset.month,link.dataset.day,courseId,categoryId),e.preventDefault())}));const viewSelector=root.find(CalendarSelectors.viewSelector);_custom_interaction_events.default.define(viewSelector,[_custom_interaction_events.default.events.activate]),viewSelector.on(_custom_interaction_events.default.events.activate,(e=>{e.preventDefault();const option=e.target;if(option.classList.contains("active"))return;const view=option.dataset.view,year=option.dataset.year,month=option.dataset.month,day=option.dataset.day,courseId=option.dataset.courseid,categoryId=option.dataset.categoryid;"month"==view?refreshMonthContent(root,year,month,courseId,categoryId,root,"core_calendar/calendar_month",day).then((()=>{updateUrl("?view=month")})).fail(_notification.default.exception):"day"==view?refreshDayContent(root,year,month,day,courseId,categoryId,root,"core_calendar/calendar_day").then((()=>{updateUrl("?view=day")})).fail(_notification.default.exception):"upcoming"==view&&reloadCurrentUpcoming(root,courseId,categoryId,root,"core_calendar/calendar_upcoming").then((()=>{updateUrl("?view=upcoming")})).fail(_notification.default.exception)}))})(root);const calendarTable=root.find(CalendarSelectors.elements.monthDetailed);if(calendarTable.length){"month-detailed-".concat(calendarTable.id,"-filterChanged");registerEventListenersForMonthDetailed(calendarTable)}}}));
+
+//# sourceMappingURL=view_manager.min.js.map
\ No newline at end of file
diff --git a/calendar/amd/build/view_manager.min.js.map b/calendar/amd/build/view_manager.min.js.map
index 3c0751a2060..87f2fd128be 100644
--- a/calendar/amd/build/view_manager.min.js.map
+++ b/calendar/amd/build/view_manager.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/view_manager.js"],"names":["foldDayEvents","root","CalendarSelectors","elements","monthDetailed","days","find","day","length","each","dayContainer","eventsSelector","dateContent","filteredEventsSelector","moreEventsSelector","events","filteredEvents","numberOfFiltered","numberOfEvents","count","event","isNotFiltered","attr","offset","hide","show","moreEventsLink","then","str","link","text","fail","registerEventListenersForMonthDetailed","pendingId","CalendarEvents","viewUpdated","on","e","filterChanged","data","pending","Pending","target","eventType","type","transitionPromise","$","Deferred","hidden","promise","always","resolve","registerEventListeners","links","eventLink","eventId","pendingPromise","matches","actions","viewEvent","closest","dataset","querySelector","preventDefault","stopPropagation","renderEventSummaryModal","catch","navLink","wrapper","view","courseId","categoryId","currentTarget","changeMonth","href","year","month","changeDay","viewSelector","CustomEvents","define","activate","option","classList","contains","courseid","categoryid","refreshMonthContent","updateUrl","Notification","exception","refreshDayContent","reloadCurrentUpcoming","template","startLoading","M","util","js_pending","get","join","includenavigation","mini","viewMode","CalendarRepository","getCalendarMonthData","context","Templates","render","html","js","replaceNode","document","dispatchEvent","CustomEvent","js_complete","stopLoading","url","args","trigger","monthChanged","reloadCurrentMonth","courseChanged","getCalendarDayData","viewingday","showviewselector","reloadCurrentDay","dayChanged","viewingFullCalendar","getElementById","fullCalendarView","window","history","pushState","loadingIconContainer","containers","loadingIcon","removeClass","addClass","getCalendarUpcomingData","viewingupcoming","getEventTypeClassFromType","getEventById","getEventResponse","Error","eventData","modalParams","title","name","SummaryModal","TYPE","body","templateContext","canedit","candelete","headerclasses","normalisedeventtype","isactionevent","action","ModalFactory","create","modal","getRoot","ModalEvents","destroy","init","calendarTable","id"],"mappings":"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","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 .\n\n/**\n * A javascript module to handler calendar view changes.\n *\n * @module core_calendar/view_manager\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport Templates from 'core/templates';\nimport Notification from 'core/notification';\nimport * as CalendarRepository from 'core_calendar/repository';\nimport CalendarEvents from 'core_calendar/events';\nimport * as CalendarSelectors from 'core_calendar/selectors';\nimport ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport SummaryModal from 'core_calendar/summary_modal';\nimport CustomEvents from 'core/custom_interaction_events';\nimport {get_string as getString} from 'core/str';\nimport Pending from 'core/pending';\nimport {prefetchStrings} from 'core/prefetch';\n\n/**\n * Limit number of events per day\n *\n */\nconst LIMIT_DAY_EVENTS = 5;\n\n/**\n * Hide day events if more than 5.\n *\n */\nexport const foldDayEvents = () => {\n const root = $(CalendarSelectors.elements.monthDetailed);\n const days = root.find(CalendarSelectors.day);\n if (days.length === 0) {\n return;\n }\n days.each(function() {\n const dayContainer = $(this);\n const eventsSelector = `${CalendarSelectors.elements.dateContent} ul li[data-event-eventtype]`;\n const filteredEventsSelector = `${CalendarSelectors.elements.dateContent} ul li[data-event-filtered=\"true\"]`;\n const moreEventsSelector = `${CalendarSelectors.elements.dateContent} [data-action=\"view-more-events\"]`;\n const events = dayContainer.find(eventsSelector);\n if (events.length === 0) {\n return;\n }\n\n const filteredEvents = dayContainer.find(filteredEventsSelector);\n const numberOfFiltered = filteredEvents.length;\n const numberOfEvents = events.length - numberOfFiltered;\n\n let count = 1;\n events.each(function() {\n const event = $(this);\n const isNotFiltered = event.attr('data-event-filtered') !== 'true';\n const offset = (numberOfEvents === LIMIT_DAY_EVENTS) ? 0 : 1;\n if (isNotFiltered) {\n if (count > LIMIT_DAY_EVENTS - offset) {\n event.attr('data-event-folded', 'true');\n event.hide();\n } else {\n event.attr('data-event-folded', 'false');\n event.show();\n count++;\n }\n } else {\n // It's being filtered out.\n event.attr('data-event-folded', 'false');\n }\n });\n\n const moreEventsLink = dayContainer.find(moreEventsSelector);\n if (numberOfEvents > LIMIT_DAY_EVENTS) {\n const numberOfHiddenEvents = numberOfEvents - LIMIT_DAY_EVENTS + 1;\n moreEventsLink.show();\n getString('moreevents', 'calendar', numberOfHiddenEvents).then(str => {\n const link = moreEventsLink.find('strong a');\n moreEventsLink.attr('data-event-folded', 'false');\n link.text(str);\n return str;\n }).fail();\n } else {\n moreEventsLink.hide();\n }\n });\n};\n\n/**\n * Register and handle month calendar events.\n *\n * @param {string} pendingId pending id.\n */\nexport const registerEventListenersForMonthDetailed = (pendingId) => {\n const events = `${CalendarEvents.viewUpdated}`;\n $('body').on(events, function(e) {\n foldDayEvents(e);\n });\n foldDayEvents();\n $('body').on(CalendarEvents.filterChanged, function(e, data) {\n const root = $(CalendarSelectors.elements.monthDetailed);\n const pending = new Pending(pendingId);\n const target = root.find(CalendarSelectors.eventType[data.type]);\n const transitionPromise = $.Deferred();\n if (data.hidden) {\n transitionPromise.then(function() {\n target.attr('data-event-filtered', 'true');\n return target.hide().promise();\n }).fail();\n } else {\n transitionPromise.then(function() {\n target.attr('data-event-filtered', 'false');\n return target.show().promise();\n }).fail();\n }\n\n transitionPromise.then(function() {\n foldDayEvents();\n return;\n })\n .always(pending.resolve)\n .fail();\n\n transitionPromise.resolve();\n });\n};\n\n/**\n * Register event listeners for the module.\n *\n * @param {object} root The root element.\n */\nconst registerEventListeners = (root) => {\n root = $(root);\n\n // Bind click events to event links.\n root.on('click', CalendarSelectors.links.eventLink, (e) => {\n const target = e.target;\n let eventLink = null;\n let eventId = null;\n const pendingPromise = new Pending('core_calendar/view_manager:eventLink:click');\n\n if (target.matches(CalendarSelectors.actions.viewEvent)) {\n eventLink = target;\n } else {\n eventLink = target.closest(CalendarSelectors.actions.viewEvent);\n }\n\n if (eventLink) {\n eventId = eventLink.dataset.eventId;\n } else {\n eventId = target.querySelector(CalendarSelectors.actions.viewEvent).dataset.eventId;\n }\n\n if (eventId) {\n // A link was found. Show the modal.\n\n e.preventDefault();\n // We've handled the event so stop it from bubbling\n // and causing the day click handler to fire.\n e.stopPropagation();\n\n renderEventSummaryModal(eventId)\n .then(pendingPromise.resolve)\n .catch();\n } else {\n pendingPromise.resolve();\n }\n });\n\n root.on('click', CalendarSelectors.links.navLink, (e) => {\n const wrapper = root.find(CalendarSelectors.wrapper);\n const view = wrapper.data('view');\n const courseId = wrapper.data('courseid');\n const categoryId = wrapper.data('categoryid');\n const link = e.currentTarget;\n\n if (view === 'month' || view === 'monthblock') {\n changeMonth(root, link.href, link.dataset.year, link.dataset.month, courseId, categoryId, link.dataset.day);\n e.preventDefault();\n } else if (view === 'day') {\n changeDay(root, link.href, link.dataset.year, link.dataset.month, link.dataset.day, courseId, categoryId);\n e.preventDefault();\n }\n });\n\n const viewSelector = root.find(CalendarSelectors.viewSelector);\n CustomEvents.define(viewSelector, [CustomEvents.events.activate]);\n viewSelector.on(\n CustomEvents.events.activate,\n (e) => {\n e.preventDefault();\n\n const option = e.target;\n if (option.classList.contains('active')) {\n return;\n }\n\n const view = option.dataset.view,\n year = option.dataset.year,\n month = option.dataset.month,\n day = option.dataset.day,\n courseId = option.dataset.courseid,\n categoryId = option.dataset.categoryid;\n\n if (view == 'month') {\n refreshMonthContent(root, year, month, courseId, categoryId, root, 'core_calendar/calendar_month', day)\n .then(() => {\n updateUrl('?view=month');\n }).fail(Notification.exception);\n } else if (view == 'day') {\n refreshDayContent(root, year, month, day, courseId, categoryId, root, 'core_calendar/calendar_day')\n .then(() => {\n updateUrl('?view=day');\n }).fail(Notification.exception);\n } else if (view == 'upcoming') {\n reloadCurrentUpcoming(root, courseId, categoryId, root, 'core_calendar/calendar_upcoming')\n .then(() => {\n updateUrl('?view=upcoming');\n }).fail(Notification.exception);\n }\n }\n );\n};\n\n/**\n * Refresh the month content.\n *\n * @param {object} root The root element.\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} courseId The id of the course whose events are shown\n * @param {number} categoryId The id of the category whose events are shown\n * @param {object} target The element being replaced. If not specified, the calendarwrapper is used.\n * @param {string} template The template to be rendered.\n * @param {number} day Day (optional)\n * @return {promise}\n */\nexport const refreshMonthContent = (root, year, month, courseId, categoryId, target = null, template = '', day = 1) => {\n startLoading(root);\n\n target = target || root.find(CalendarSelectors.wrapper);\n template = template || root.attr('data-template');\n M.util.js_pending([root.get('id'), year, month, courseId].join('-'));\n const includenavigation = root.data('includenavigation');\n const mini = root.data('mini');\n const viewMode = target.data('view');\n return CalendarRepository.getCalendarMonthData(year, month, courseId, categoryId, includenavigation, mini, day, viewMode)\n .then(context => {\n return Templates.render(template, context);\n })\n .then((html, js) => {\n return Templates.replaceNode(target, html, js);\n })\n .then(() => {\n document.querySelector('body').dispatchEvent(new CustomEvent(CalendarEvents.viewUpdated));\n return;\n })\n .always(() => {\n M.util.js_complete([root.get('id'), year, month, courseId].join('-'));\n return stopLoading(root);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Handle changes to the current calendar view.\n *\n * @param {object} root The container element\n * @param {string} url The calendar url to be shown\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} courseId The id of the course whose events are shown\n * @param {number} categoryId The id of the category whose events are shown\n * @param {number} day Day (optional)\n * @return {promise}\n */\nexport const changeMonth = (root, url, year, month, courseId, categoryId, day = 1) => {\n return refreshMonthContent(root, year, month, courseId, categoryId, null, '', day)\n .then((...args) => {\n if (url.length && url !== '#') {\n updateUrl(url);\n }\n return args;\n })\n .then((...args) => {\n $('body').trigger(CalendarEvents.monthChanged, [year, month, courseId, categoryId]);\n return args;\n });\n};\n\n/**\n * Reload the current month view data.\n *\n * @param {object} root The container element.\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @return {promise}\n */\nexport const reloadCurrentMonth = (root, courseId = 0, categoryId = 0) => {\n const year = root.find(CalendarSelectors.wrapper).data('year');\n const month = root.find(CalendarSelectors.wrapper).data('month');\n const day = root.find(CalendarSelectors.wrapper).data('day');\n\n courseId = courseId || root.find(CalendarSelectors.wrapper).data('courseid');\n categoryId = categoryId || root.find(CalendarSelectors.wrapper).data('categoryid');\n\n return refreshMonthContent(root, year, month, courseId, categoryId, null, '', day).\n then((...args) => {\n $('body').trigger(CalendarEvents.courseChanged, [year, month, courseId, categoryId]);\n return args;\n });\n};\n\n\n/**\n * Refresh the day content.\n *\n * @param {object} root The root element.\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} day Day\n * @param {number} courseId The id of the course whose events are shown\n * @param {number} categoryId The id of the category whose events are shown\n * @param {object} target The element being replaced. If not specified, the calendarwrapper is used.\n * @param {string} template The template to be rendered.\n *\n * @return {promise}\n */\nexport const refreshDayContent = (root, year, month, day, courseId, categoryId, target = null, template = '') => {\n startLoading(root);\n\n if (!target || target.length == 0){\n target = root.find(CalendarSelectors.wrapper);\n }\n template = template || root.attr('data-template');\n M.util.js_pending([root.get('id'), year, month, day, courseId, categoryId].join('-'));\n const includenavigation = root.data('includenavigation');\n return CalendarRepository.getCalendarDayData(year, month, day, courseId, categoryId, includenavigation)\n .then((context) => {\n context.viewingday = true;\n context.showviewselector = true;\n return Templates.render(template, context);\n })\n .then((html, js) => {\n return Templates.replaceNode(target, html, js);\n })\n .then(() => {\n document.querySelector('body').dispatchEvent(new CustomEvent(CalendarEvents.viewUpdated));\n return;\n })\n .always(() => {\n M.util.js_complete([root.get('id'), year, month, day, courseId, categoryId].join('-'));\n return stopLoading(root);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Reload the current day view data.\n *\n * @param {object} root The container element.\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @return {promise}\n */\nexport const reloadCurrentDay = (root, courseId = 0, categoryId = 0) => {\n const wrapper = root.find(CalendarSelectors.wrapper);\n const year = wrapper.data('year');\n const month = wrapper.data('month');\n const day = wrapper.data('day');\n\n courseId = courseId || root.find(CalendarSelectors.wrapper).data('courseid');\n categoryId = categoryId || root.find(CalendarSelectors.wrapper).data('categoryid');\n\n return refreshDayContent(root, year, month, day, courseId, categoryId);\n};\n\n/**\n * Handle changes to the current calendar view.\n *\n * @param {object} root The root element.\n * @param {String} url The calendar url to be shown\n * @param {Number} year Year\n * @param {Number} month Month\n * @param {Number} day Day\n * @param {Number} courseId The id of the course whose events are shown\n * @param {Number} categoryId The id of the category whose events are shown\n * @return {promise}\n */\nexport const changeDay = (root, url, year, month, day, courseId, categoryId) => {\n return refreshDayContent(root, year, month, day, courseId, categoryId)\n .then((...args) => {\n if (url.length && url !== '#') {\n updateUrl(url);\n }\n return args;\n })\n .then((...args) => {\n $('body').trigger(CalendarEvents.dayChanged, [year, month, courseId, categoryId]);\n return args;\n });\n};\n\n/**\n * Update calendar URL.\n *\n * @param {String} url The calendar url to be updated.\n */\nexport const updateUrl = (url) => {\n const viewingFullCalendar = document.getElementById(CalendarSelectors.fullCalendarView);\n\n // We want to update the url only if the user is viewing the full calendar.\n if (viewingFullCalendar) {\n window.history.pushState({}, '', url);\n }\n};\n\n/**\n * Set the element state to loading.\n *\n * @param {object} root The container element\n * @method startLoading\n */\nconst startLoading = (root) => {\n const loadingIconContainer = root.find(CalendarSelectors.containers.loadingIcon);\n\n loadingIconContainer.removeClass('hidden');\n};\n\n/**\n * Remove the loading state from the element.\n *\n * @param {object} root The container element\n * @method stopLoading\n */\nconst stopLoading = (root) => {\n const loadingIconContainer = root.find(CalendarSelectors.containers.loadingIcon);\n\n loadingIconContainer.addClass('hidden');\n};\n\n/**\n * Reload the current month view data.\n *\n * @param {object} root The container element.\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @param {object} target The element being replaced. If not specified, the calendarwrapper is used.\n * @param {string} template The template to be rendered.\n * @return {promise}\n */\nexport const reloadCurrentUpcoming = (root, courseId = 0, categoryId = 0, target = null, template = '') => {\n startLoading(root);\n\n target = target || root.find(CalendarSelectors.wrapper);\n template = template || root.attr('data-template');\n courseId = courseId || root.find(CalendarSelectors.wrapper).data('courseid');\n categoryId = categoryId || root.find(CalendarSelectors.wrapper).data('categoryid');\n\n return CalendarRepository.getCalendarUpcomingData(courseId, categoryId)\n .then((context) => {\n context.viewingupcoming = true;\n context.showviewselector = true;\n return Templates.render(template, context);\n })\n .then((html, js) => {\n return Templates.replaceNode(target, html, js);\n })\n .then(() => {\n document.querySelector('body').dispatchEvent(new CustomEvent(CalendarEvents.viewUpdated));\n return;\n })\n .always(function() {\n return stopLoading(root);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Get the CSS class to apply for the given event type.\n *\n * @param {string} eventType The calendar event type\n * @return {string}\n */\nconst getEventTypeClassFromType = (eventType) => {\n return 'calendar_event_' + eventType;\n};\n\n/**\n * Render the event summary modal.\n *\n * @param {Number} eventId The calendar event id.\n * @returns {Promise}\n */\nconst renderEventSummaryModal = (eventId) => {\n const pendingPromise = new Pending('core_calendar/view_manager:renderEventSummaryModal');\n\n // Calendar repository promise.\n return CalendarRepository.getEventById(eventId)\n .then((getEventResponse) => {\n if (!getEventResponse.event) {\n throw new Error('Error encountered while trying to fetch calendar event with ID: ' + eventId);\n }\n\n return getEventResponse.event;\n })\n .then(eventData => {\n // Build the modal parameters from the event data.\n const modalParams = {\n title: eventData.name,\n type: SummaryModal.TYPE,\n body: Templates.render('core_calendar/event_summary_body', eventData),\n templateContext: {\n canedit: eventData.canedit,\n candelete: eventData.candelete,\n headerclasses: getEventTypeClassFromType(eventData.normalisedeventtype),\n isactionevent: eventData.isactionevent,\n url: eventData.url,\n action: eventData.action\n }\n };\n\n // Create the modal.\n return ModalFactory.create(modalParams);\n })\n .then(modal => {\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n // Finally, render the modal!\n modal.show();\n\n return modal;\n })\n .then(modal => {\n pendingPromise.resolve();\n\n return modal;\n })\n .catch(Notification.exception);\n};\n\nexport const init = (root, view) => {\n prefetchStrings('calendar', ['moreevents']);\n foldDayEvents();\n registerEventListeners(root, view);\n const calendarTable = root.find(CalendarSelectors.elements.monthDetailed);\n if (calendarTable.length) {\n const pendingId = `month-detailed-${calendarTable.id}-filterChanged`;\n registerEventListenersForMonthDetailed(calendarTable, pendingId);\n }\n};\n"],"file":"view_manager.min.js"}
\ No newline at end of file
+{"version":3,"file":"view_manager.min.js","sources":["../src/view_manager.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 .\n\n/**\n * A javascript module to handler calendar view changes.\n *\n * @module core_calendar/view_manager\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport Templates from 'core/templates';\nimport Notification from 'core/notification';\nimport * as CalendarRepository from 'core_calendar/repository';\nimport CalendarEvents from 'core_calendar/events';\nimport * as CalendarSelectors from 'core_calendar/selectors';\nimport ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport SummaryModal from 'core_calendar/summary_modal';\nimport CustomEvents from 'core/custom_interaction_events';\nimport {get_string as getString} from 'core/str';\nimport Pending from 'core/pending';\nimport {prefetchStrings} from 'core/prefetch';\n\n/**\n * Limit number of events per day\n *\n */\nconst LIMIT_DAY_EVENTS = 5;\n\n/**\n * Hide day events if more than 5.\n *\n */\nexport const foldDayEvents = () => {\n const root = $(CalendarSelectors.elements.monthDetailed);\n const days = root.find(CalendarSelectors.day);\n if (days.length === 0) {\n return;\n }\n days.each(function() {\n const dayContainer = $(this);\n const eventsSelector = `${CalendarSelectors.elements.dateContent} ul li[data-event-eventtype]`;\n const filteredEventsSelector = `${CalendarSelectors.elements.dateContent} ul li[data-event-filtered=\"true\"]`;\n const moreEventsSelector = `${CalendarSelectors.elements.dateContent} [data-action=\"view-more-events\"]`;\n const events = dayContainer.find(eventsSelector);\n if (events.length === 0) {\n return;\n }\n\n const filteredEvents = dayContainer.find(filteredEventsSelector);\n const numberOfFiltered = filteredEvents.length;\n const numberOfEvents = events.length - numberOfFiltered;\n\n let count = 1;\n events.each(function() {\n const event = $(this);\n const isNotFiltered = event.attr('data-event-filtered') !== 'true';\n const offset = (numberOfEvents === LIMIT_DAY_EVENTS) ? 0 : 1;\n if (isNotFiltered) {\n if (count > LIMIT_DAY_EVENTS - offset) {\n event.attr('data-event-folded', 'true');\n event.hide();\n } else {\n event.attr('data-event-folded', 'false');\n event.show();\n count++;\n }\n } else {\n // It's being filtered out.\n event.attr('data-event-folded', 'false');\n }\n });\n\n const moreEventsLink = dayContainer.find(moreEventsSelector);\n if (numberOfEvents > LIMIT_DAY_EVENTS) {\n const numberOfHiddenEvents = numberOfEvents - LIMIT_DAY_EVENTS + 1;\n moreEventsLink.show();\n getString('moreevents', 'calendar', numberOfHiddenEvents).then(str => {\n const link = moreEventsLink.find('strong a');\n moreEventsLink.attr('data-event-folded', 'false');\n link.text(str);\n return str;\n }).fail();\n } else {\n moreEventsLink.hide();\n }\n });\n};\n\n/**\n * Register and handle month calendar events.\n *\n * @param {string} pendingId pending id.\n */\nexport const registerEventListenersForMonthDetailed = (pendingId) => {\n const events = `${CalendarEvents.viewUpdated}`;\n $('body').on(events, function(e) {\n foldDayEvents(e);\n });\n foldDayEvents();\n $('body').on(CalendarEvents.filterChanged, function(e, data) {\n const root = $(CalendarSelectors.elements.monthDetailed);\n const pending = new Pending(pendingId);\n const target = root.find(CalendarSelectors.eventType[data.type]);\n const transitionPromise = $.Deferred();\n if (data.hidden) {\n transitionPromise.then(function() {\n target.attr('data-event-filtered', 'true');\n return target.hide().promise();\n }).fail();\n } else {\n transitionPromise.then(function() {\n target.attr('data-event-filtered', 'false');\n return target.show().promise();\n }).fail();\n }\n\n transitionPromise.then(function() {\n foldDayEvents();\n return;\n })\n .always(pending.resolve)\n .fail();\n\n transitionPromise.resolve();\n });\n};\n\n/**\n * Register event listeners for the module.\n *\n * @param {object} root The root element.\n */\nconst registerEventListeners = (root) => {\n root = $(root);\n\n // Bind click events to event links.\n root.on('click', CalendarSelectors.links.eventLink, (e) => {\n const target = e.target;\n let eventLink = null;\n let eventId = null;\n const pendingPromise = new Pending('core_calendar/view_manager:eventLink:click');\n\n if (target.matches(CalendarSelectors.actions.viewEvent)) {\n eventLink = target;\n } else {\n eventLink = target.closest(CalendarSelectors.actions.viewEvent);\n }\n\n if (eventLink) {\n eventId = eventLink.dataset.eventId;\n } else {\n eventId = target.querySelector(CalendarSelectors.actions.viewEvent).dataset.eventId;\n }\n\n if (eventId) {\n // A link was found. Show the modal.\n\n e.preventDefault();\n // We've handled the event so stop it from bubbling\n // and causing the day click handler to fire.\n e.stopPropagation();\n\n renderEventSummaryModal(eventId)\n .then(pendingPromise.resolve)\n .catch();\n } else {\n pendingPromise.resolve();\n }\n });\n\n root.on('click', CalendarSelectors.links.navLink, (e) => {\n const wrapper = root.find(CalendarSelectors.wrapper);\n const view = wrapper.data('view');\n const courseId = wrapper.data('courseid');\n const categoryId = wrapper.data('categoryid');\n const link = e.currentTarget;\n\n if (view === 'month' || view === 'monthblock') {\n changeMonth(root, link.href, link.dataset.year, link.dataset.month, courseId, categoryId, link.dataset.day);\n e.preventDefault();\n } else if (view === 'day') {\n changeDay(root, link.href, link.dataset.year, link.dataset.month, link.dataset.day, courseId, categoryId);\n e.preventDefault();\n }\n });\n\n const viewSelector = root.find(CalendarSelectors.viewSelector);\n CustomEvents.define(viewSelector, [CustomEvents.events.activate]);\n viewSelector.on(\n CustomEvents.events.activate,\n (e) => {\n e.preventDefault();\n\n const option = e.target;\n if (option.classList.contains('active')) {\n return;\n }\n\n const view = option.dataset.view,\n year = option.dataset.year,\n month = option.dataset.month,\n day = option.dataset.day,\n courseId = option.dataset.courseid,\n categoryId = option.dataset.categoryid;\n\n if (view == 'month') {\n refreshMonthContent(root, year, month, courseId, categoryId, root, 'core_calendar/calendar_month', day)\n .then(() => {\n updateUrl('?view=month');\n }).fail(Notification.exception);\n } else if (view == 'day') {\n refreshDayContent(root, year, month, day, courseId, categoryId, root, 'core_calendar/calendar_day')\n .then(() => {\n updateUrl('?view=day');\n }).fail(Notification.exception);\n } else if (view == 'upcoming') {\n reloadCurrentUpcoming(root, courseId, categoryId, root, 'core_calendar/calendar_upcoming')\n .then(() => {\n updateUrl('?view=upcoming');\n }).fail(Notification.exception);\n }\n }\n );\n};\n\n/**\n * Refresh the month content.\n *\n * @param {object} root The root element.\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} courseId The id of the course whose events are shown\n * @param {number} categoryId The id of the category whose events are shown\n * @param {object} target The element being replaced. If not specified, the calendarwrapper is used.\n * @param {string} template The template to be rendered.\n * @param {number} day Day (optional)\n * @return {promise}\n */\nexport const refreshMonthContent = (root, year, month, courseId, categoryId, target = null, template = '', day = 1) => {\n startLoading(root);\n\n target = target || root.find(CalendarSelectors.wrapper);\n template = template || root.attr('data-template');\n M.util.js_pending([root.get('id'), year, month, courseId].join('-'));\n const includenavigation = root.data('includenavigation');\n const mini = root.data('mini');\n const viewMode = target.data('view');\n return CalendarRepository.getCalendarMonthData(year, month, courseId, categoryId, includenavigation, mini, day, viewMode)\n .then(context => {\n return Templates.render(template, context);\n })\n .then((html, js) => {\n return Templates.replaceNode(target, html, js);\n })\n .then(() => {\n document.querySelector('body').dispatchEvent(new CustomEvent(CalendarEvents.viewUpdated));\n return;\n })\n .always(() => {\n M.util.js_complete([root.get('id'), year, month, courseId].join('-'));\n return stopLoading(root);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Handle changes to the current calendar view.\n *\n * @param {object} root The container element\n * @param {string} url The calendar url to be shown\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} courseId The id of the course whose events are shown\n * @param {number} categoryId The id of the category whose events are shown\n * @param {number} day Day (optional)\n * @return {promise}\n */\nexport const changeMonth = (root, url, year, month, courseId, categoryId, day = 1) => {\n return refreshMonthContent(root, year, month, courseId, categoryId, null, '', day)\n .then((...args) => {\n if (url.length && url !== '#') {\n updateUrl(url);\n }\n return args;\n })\n .then((...args) => {\n $('body').trigger(CalendarEvents.monthChanged, [year, month, courseId, categoryId]);\n return args;\n });\n};\n\n/**\n * Reload the current month view data.\n *\n * @param {object} root The container element.\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @return {promise}\n */\nexport const reloadCurrentMonth = (root, courseId = 0, categoryId = 0) => {\n const year = root.find(CalendarSelectors.wrapper).data('year');\n const month = root.find(CalendarSelectors.wrapper).data('month');\n const day = root.find(CalendarSelectors.wrapper).data('day');\n\n courseId = courseId || root.find(CalendarSelectors.wrapper).data('courseid');\n categoryId = categoryId || root.find(CalendarSelectors.wrapper).data('categoryid');\n\n return refreshMonthContent(root, year, month, courseId, categoryId, null, '', day).\n then((...args) => {\n $('body').trigger(CalendarEvents.courseChanged, [year, month, courseId, categoryId]);\n return args;\n });\n};\n\n\n/**\n * Refresh the day content.\n *\n * @param {object} root The root element.\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} day Day\n * @param {number} courseId The id of the course whose events are shown\n * @param {number} categoryId The id of the category whose events are shown\n * @param {object} target The element being replaced. If not specified, the calendarwrapper is used.\n * @param {string} template The template to be rendered.\n *\n * @return {promise}\n */\nexport const refreshDayContent = (root, year, month, day, courseId, categoryId, target = null, template = '') => {\n startLoading(root);\n\n if (!target || target.length == 0){\n target = root.find(CalendarSelectors.wrapper);\n }\n template = template || root.attr('data-template');\n M.util.js_pending([root.get('id'), year, month, day, courseId, categoryId].join('-'));\n const includenavigation = root.data('includenavigation');\n return CalendarRepository.getCalendarDayData(year, month, day, courseId, categoryId, includenavigation)\n .then((context) => {\n context.viewingday = true;\n context.showviewselector = true;\n return Templates.render(template, context);\n })\n .then((html, js) => {\n return Templates.replaceNode(target, html, js);\n })\n .then(() => {\n document.querySelector('body').dispatchEvent(new CustomEvent(CalendarEvents.viewUpdated));\n return;\n })\n .always(() => {\n M.util.js_complete([root.get('id'), year, month, day, courseId, categoryId].join('-'));\n return stopLoading(root);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Reload the current day view data.\n *\n * @param {object} root The container element.\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @return {promise}\n */\nexport const reloadCurrentDay = (root, courseId = 0, categoryId = 0) => {\n const wrapper = root.find(CalendarSelectors.wrapper);\n const year = wrapper.data('year');\n const month = wrapper.data('month');\n const day = wrapper.data('day');\n\n courseId = courseId || root.find(CalendarSelectors.wrapper).data('courseid');\n categoryId = categoryId || root.find(CalendarSelectors.wrapper).data('categoryid');\n\n return refreshDayContent(root, year, month, day, courseId, categoryId);\n};\n\n/**\n * Handle changes to the current calendar view.\n *\n * @param {object} root The root element.\n * @param {String} url The calendar url to be shown\n * @param {Number} year Year\n * @param {Number} month Month\n * @param {Number} day Day\n * @param {Number} courseId The id of the course whose events are shown\n * @param {Number} categoryId The id of the category whose events are shown\n * @return {promise}\n */\nexport const changeDay = (root, url, year, month, day, courseId, categoryId) => {\n return refreshDayContent(root, year, month, day, courseId, categoryId)\n .then((...args) => {\n if (url.length && url !== '#') {\n updateUrl(url);\n }\n return args;\n })\n .then((...args) => {\n $('body').trigger(CalendarEvents.dayChanged, [year, month, courseId, categoryId]);\n return args;\n });\n};\n\n/**\n * Update calendar URL.\n *\n * @param {String} url The calendar url to be updated.\n */\nexport const updateUrl = (url) => {\n const viewingFullCalendar = document.getElementById(CalendarSelectors.fullCalendarView);\n\n // We want to update the url only if the user is viewing the full calendar.\n if (viewingFullCalendar) {\n window.history.pushState({}, '', url);\n }\n};\n\n/**\n * Set the element state to loading.\n *\n * @param {object} root The container element\n * @method startLoading\n */\nconst startLoading = (root) => {\n const loadingIconContainer = root.find(CalendarSelectors.containers.loadingIcon);\n\n loadingIconContainer.removeClass('hidden');\n};\n\n/**\n * Remove the loading state from the element.\n *\n * @param {object} root The container element\n * @method stopLoading\n */\nconst stopLoading = (root) => {\n const loadingIconContainer = root.find(CalendarSelectors.containers.loadingIcon);\n\n loadingIconContainer.addClass('hidden');\n};\n\n/**\n * Reload the current month view data.\n *\n * @param {object} root The container element.\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @param {object} target The element being replaced. If not specified, the calendarwrapper is used.\n * @param {string} template The template to be rendered.\n * @return {promise}\n */\nexport const reloadCurrentUpcoming = (root, courseId = 0, categoryId = 0, target = null, template = '') => {\n startLoading(root);\n\n target = target || root.find(CalendarSelectors.wrapper);\n template = template || root.attr('data-template');\n courseId = courseId || root.find(CalendarSelectors.wrapper).data('courseid');\n categoryId = categoryId || root.find(CalendarSelectors.wrapper).data('categoryid');\n\n return CalendarRepository.getCalendarUpcomingData(courseId, categoryId)\n .then((context) => {\n context.viewingupcoming = true;\n context.showviewselector = true;\n return Templates.render(template, context);\n })\n .then((html, js) => {\n return Templates.replaceNode(target, html, js);\n })\n .then(() => {\n document.querySelector('body').dispatchEvent(new CustomEvent(CalendarEvents.viewUpdated));\n return;\n })\n .always(function() {\n return stopLoading(root);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Get the CSS class to apply for the given event type.\n *\n * @param {string} eventType The calendar event type\n * @return {string}\n */\nconst getEventTypeClassFromType = (eventType) => {\n return 'calendar_event_' + eventType;\n};\n\n/**\n * Render the event summary modal.\n *\n * @param {Number} eventId The calendar event id.\n * @returns {Promise}\n */\nconst renderEventSummaryModal = (eventId) => {\n const pendingPromise = new Pending('core_calendar/view_manager:renderEventSummaryModal');\n\n // Calendar repository promise.\n return CalendarRepository.getEventById(eventId)\n .then((getEventResponse) => {\n if (!getEventResponse.event) {\n throw new Error('Error encountered while trying to fetch calendar event with ID: ' + eventId);\n }\n\n return getEventResponse.event;\n })\n .then(eventData => {\n // Build the modal parameters from the event data.\n const modalParams = {\n title: eventData.name,\n type: SummaryModal.TYPE,\n body: Templates.render('core_calendar/event_summary_body', eventData),\n templateContext: {\n canedit: eventData.canedit,\n candelete: eventData.candelete,\n headerclasses: getEventTypeClassFromType(eventData.normalisedeventtype),\n isactionevent: eventData.isactionevent,\n url: eventData.url,\n action: eventData.action\n }\n };\n\n // Create the modal.\n return ModalFactory.create(modalParams);\n })\n .then(modal => {\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n // Finally, render the modal!\n modal.show();\n\n return modal;\n })\n .then(modal => {\n pendingPromise.resolve();\n\n return modal;\n })\n .catch(Notification.exception);\n};\n\nexport const init = (root, view) => {\n prefetchStrings('calendar', ['moreevents']);\n foldDayEvents();\n registerEventListeners(root, view);\n const calendarTable = root.find(CalendarSelectors.elements.monthDetailed);\n if (calendarTable.length) {\n const pendingId = `month-detailed-${calendarTable.id}-filterChanged`;\n registerEventListenersForMonthDetailed(calendarTable, pendingId);\n }\n};\n"],"names":["foldDayEvents","days","CalendarSelectors","elements","monthDetailed","find","day","length","each","dayContainer","this","eventsSelector","dateContent","filteredEventsSelector","moreEventsSelector","events","numberOfFiltered","numberOfEvents","count","event","attr","hide","show","moreEventsLink","numberOfHiddenEvents","then","str","link","text","fail","registerEventListenersForMonthDetailed","pendingId","CalendarEvents","viewUpdated","on","e","filterChanged","data","root","pending","Pending","target","eventType","type","transitionPromise","$","Deferred","hidden","promise","always","resolve","refreshMonthContent","year","month","courseId","categoryId","template","startLoading","wrapper","M","util","js_pending","get","join","includenavigation","mini","viewMode","CalendarRepository","getCalendarMonthData","context","Templates","render","html","js","replaceNode","document","querySelector","dispatchEvent","CustomEvent","js_complete","stopLoading","Notification","exception","changeMonth","url","updateUrl","args","trigger","monthChanged","courseChanged","refreshDayContent","getCalendarDayData","viewingday","showviewselector","changeDay","dayChanged","getElementById","fullCalendarView","window","history","pushState","containers","loadingIcon","removeClass","addClass","reloadCurrentUpcoming","getCalendarUpcomingData","viewingupcoming","renderEventSummaryModal","eventId","pendingPromise","getEventById","getEventResponse","Error","eventData","modalParams","title","name","SummaryModal","TYPE","body","templateContext","canedit","candelete","headerclasses","normalisedeventtype","isactionevent","action","ModalFactory","create","modal","getRoot","ModalEvents","destroy","catch","view","links","eventLink","matches","actions","viewEvent","closest","dataset","preventDefault","stopPropagation","navLink","currentTarget","href","viewSelector","define","CustomEvents","activate","option","classList","contains","courseid","categoryid","registerEventListeners","calendarTable","id"],"mappings":"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"}
\ No newline at end of file
diff --git a/contentbank/amd/build/actions.min.js b/contentbank/amd/build/actions.min.js
index c6587fd187e..27eee3f2867 100644
--- a/contentbank/amd/build/actions.min.js
+++ b/contentbank/amd/build/actions.min.js
@@ -1,2 +1,10 @@
-define ("core_contentbank/actions",["jquery","core/ajax","core/notification","core/str","core/templates","core/url","core/modal_factory","core/modal_events"],function(a,b,c,d,e,f,g,h){var l={DELETE_CONTENT:"[data-action=\"deletecontent\"]",RENAME_CONTENT:"[data-action=\"renamecontent\"]",SET_CONTENT_VISIBILITY:"[data-action=\"setcontentvisibility\"]"},m=function(){this.registerEvents()};m.prototype.registerEvents=function(){a(l.DELETE_CONTENT).click(function(b){b.preventDefault();var e=a(this).data("contentname"),f=a(this).data("uses"),j=a(this).data("contentid"),k=a(this).data("contextid"),l="";d.get_strings([{key:"deletecontent",component:"core_contentbank"},{key:"deletecontentconfirm",component:"core_contentbank",param:{name:e}},{key:"deletecontentconfirmlinked",component:"core_contentbank"},{key:"delete",component:"core"}]).then(function(a){var b=a[0],c=a[1];if(0
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define("core_contentbank/actions",["jquery","core/ajax","core/notification","core/str","core/templates","core/url","core/modal_factory","core/modal_events"],(function($,Ajax,Notification,Str,Templates,Url,ModalFactory,ModalEvents){var ACTIONS_DELETE_CONTENT='[data-action="deletecontent"]',ACTIONS_RENAME_CONTENT='[data-action="renamecontent"]',ACTIONS_SET_CONTENT_VISIBILITY='[data-action="setcontentvisibility"]',Actions=function(){this.registerEvents()};return Actions.prototype.registerEvents=function(){$(ACTIONS_DELETE_CONTENT).click((function(e){e.preventDefault();var contentname=$(this).data("contentname"),contentuses=$(this).data("uses"),contentid=$(this).data("contentid"),contextid=$(this).data("contextid"),strings=[{key:"deletecontent",component:"core_contentbank"},{key:"deletecontentconfirm",component:"core_contentbank",param:{name:contentname}},{key:"deletecontentconfirmlinked",component:"core_contentbank"},{key:"delete",component:"core"}],deleteButtonText="";Str.get_strings(strings).then((function(langStrings){var modalTitle=langStrings[0],modalContent=langStrings[1];return contentuses>0&&(modalContent+=" "+langStrings[2]),deleteButtonText=langStrings[3],ModalFactory.create({title:modalTitle,body:modalContent,type:ModalFactory.types.SAVE_CANCEL,large:!0})})).done((function(modal){modal.setSaveButtonText(deleteButtonText),modal.getRoot().on(ModalEvents.save,(function(){return function(contentid,contextid){var request={methodname:"core_contentbank_delete_content",args:{contentids:{contentid:contentid}}},requestType="success";Ajax.call([request])[0].then((function(data){return data.result?"contentdeleted":(requestType="error","contentnotdeleted")})).done((function(message){var params={contextid:contextid};"success"==requestType?params.statusmsg=message:params.errormsg=message,window.location.href=Url.relativeUrl("contentbank/index.php",params,!1)})).fail(Notification.exception)}(contentid,contextid)})),modal.getRoot().on(ModalEvents.hidden,(function(){modal.destroy()})),modal.show()})).catch(Notification.exception)})),$(ACTIONS_RENAME_CONTENT).click((function(e){e.preventDefault();var contentname=$(this).data("contentname"),contentid=$(this).data("contentid"),saveButtonText="";Str.get_strings([{key:"renamecontent",component:"core_contentbank"},{key:"rename",component:"core_contentbank"}]).then((function(langStrings){var modalTitle=langStrings[0];return saveButtonText=langStrings[1],ModalFactory.create({title:modalTitle,body:Templates.render("core_contentbank/renamecontent",{contentid:contentid,name:contentname}),type:ModalFactory.types.SAVE_CANCEL})})).then((function(modal){modal.setSaveButtonText(saveButtonText),modal.getRoot().on(ModalEvents.save,(function(e){var newname=$("#newname").val().trim();if(newname)!function(contentid,name){var request={methodname:"core_contentbank_rename_content",args:{contentid:contentid,name:name}},requestType="success";Ajax.call([request])[0].then((function(data){return data.result?"contentrenamed":(requestType="error",data.warnings[0].message)})).then((function(message){var params=null;"success"==requestType?(params={id:contentid,statusmsg:message},window.location.href=Url.relativeUrl("contentbank/view.php",params,!1)):(Notification.addNotification({message:message,type:"error"}),Notification.fetchNotifications())})).catch(Notification.exception)}(contentid,newname);else{Str.get_strings([{key:"error"},{key:"emptynamenotallowed",component:"core_contentbank"}]).then((function(langStrings){Notification.alert(langStrings[0],langStrings[1])})).catch(Notification.exception),e.preventDefault()}})),modal.getRoot().on(ModalEvents.hidden,(function(){modal.destroy()})),modal.show()})).catch(Notification.exception)})),$(ACTIONS_SET_CONTENT_VISIBILITY).click((function(e){e.preventDefault(),function(contentid,visibility){var request={methodname:"core_contentbank_set_content_visibility",args:{contentid:contentid,visibility:visibility}},requestType="success";Ajax.call([request])[0].then((function(data){return data.result?"contentvisibilitychanged":(requestType="error",data.warnings[0].message)})).then((function(message){var params=null;"success"==requestType?(params={id:contentid,statusmsg:message},window.location.href=Url.relativeUrl("contentbank/view.php",params,!1)):(Notification.addNotification({message:message,type:"error"}),Notification.fetchNotifications())})).catch(Notification.exception)}($(this).data("contentid"),$(this).data("visibility"))}))},{init:function(){return new Actions}}}));
+
+//# sourceMappingURL=actions.min.js.map
\ No newline at end of file
diff --git a/contentbank/amd/build/actions.min.js.map b/contentbank/amd/build/actions.min.js.map
index 5f0ae5d73a9..838fd731c85 100644
--- a/contentbank/amd/build/actions.min.js.map
+++ b/contentbank/amd/build/actions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/actions.js"],"names":["define","$","Ajax","Notification","Str","Templates","Url","ModalFactory","ModalEvents","ACTIONS","DELETE_CONTENT","RENAME_CONTENT","SET_CONTENT_VISIBILITY","Actions","registerEvents","prototype","click","e","preventDefault","contentname","data","contentuses","contentid","contextid","deleteButtonText","get_strings","key","component","param","name","then","langStrings","modalTitle","modalContent","create","title","body","type","types","SAVE_CANCEL","large","done","modal","setSaveButtonText","getRoot","on","save","deleteContent","hidden","destroy","show","catch","exception","saveButtonText","render","newname","val","trim","renameContent","alert","visibility","setContentVisibility","requestType","call","methodname","args","contentids","result","message","params","statusmsg","errormsg","window","location","href","relativeUrl","fail","warnings","id","addNotification","fetchNotifications"],"mappings":"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","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 .\n\n/**\n * Module to manage content bank actions, such as delete or rename.\n *\n * @module core_contentbank/actions\n * @copyright 2020 Sara Arjona \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'core/templates',\n 'core/url',\n 'core/modal_factory',\n 'core/modal_events'],\nfunction($, Ajax, Notification, Str, Templates, Url, ModalFactory, ModalEvents) {\n\n /**\n * List of action selectors.\n *\n * @type {{DELETE_CONTENT: string}}\n */\n var ACTIONS = {\n DELETE_CONTENT: '[data-action=\"deletecontent\"]',\n RENAME_CONTENT: '[data-action=\"renamecontent\"]',\n SET_CONTENT_VISIBILITY: '[data-action=\"setcontentvisibility\"]',\n };\n\n /**\n * Actions class.\n */\n var Actions = function() {\n this.registerEvents();\n };\n\n /**\n * Register event listeners.\n */\n Actions.prototype.registerEvents = function() {\n $(ACTIONS.DELETE_CONTENT).click(function(e) {\n e.preventDefault();\n\n var contentname = $(this).data('contentname');\n var contentuses = $(this).data('uses');\n var contentid = $(this).data('contentid');\n var contextid = $(this).data('contextid');\n\n var strings = [\n {\n key: 'deletecontent',\n component: 'core_contentbank'\n },\n {\n key: 'deletecontentconfirm',\n component: 'core_contentbank',\n param: {\n name: contentname,\n }\n },\n {\n key: 'deletecontentconfirmlinked',\n component: 'core_contentbank',\n },\n {\n key: 'delete',\n component: 'core'\n },\n ];\n\n var deleteButtonText = '';\n Str.get_strings(strings).then(function(langStrings) {\n var modalTitle = langStrings[0];\n var modalContent = langStrings[1];\n if (contentuses > 0) {\n modalContent += ' ' + langStrings[2];\n }\n deleteButtonText = langStrings[3];\n\n return ModalFactory.create({\n title: modalTitle,\n body: modalContent,\n type: ModalFactory.types.SAVE_CANCEL,\n large: true\n });\n }).done(function(modal) {\n modal.setSaveButtonText(deleteButtonText);\n modal.getRoot().on(ModalEvents.save, function() {\n // The action is now confirmed, sending an action for it.\n return deleteContent(contentid, contextid);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n // Show the modal.\n modal.show();\n\n return;\n }).catch(Notification.exception);\n });\n\n $(ACTIONS.RENAME_CONTENT).click(function(e) {\n e.preventDefault();\n\n var contentname = $(this).data('contentname');\n var contentid = $(this).data('contentid');\n\n var strings = [\n {\n key: 'renamecontent',\n component: 'core_contentbank'\n },\n {\n key: 'rename',\n component: 'core_contentbank'\n },\n ];\n\n var saveButtonText = '';\n Str.get_strings(strings).then(function(langStrings) {\n var modalTitle = langStrings[0];\n saveButtonText = langStrings[1];\n\n return ModalFactory.create({\n title: modalTitle,\n body: Templates.render('core_contentbank/renamecontent', {'contentid': contentid, 'name': contentname}),\n type: ModalFactory.types.SAVE_CANCEL\n });\n }).then(function(modal) {\n modal.setSaveButtonText(saveButtonText);\n modal.getRoot().on(ModalEvents.save, function(e) {\n // The action is now confirmed, sending an action for it.\n var newname = $(\"#newname\").val().trim();\n if (newname) {\n renameContent(contentid, newname);\n } else {\n var errorStrings = [\n {\n key: 'error',\n },\n {\n key: 'emptynamenotallowed',\n component: 'core_contentbank',\n },\n ];\n Str.get_strings(errorStrings).then(function(langStrings) {\n Notification.alert(langStrings[0], langStrings[1]);\n }).catch(Notification.exception);\n e.preventDefault();\n }\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n // Show the modal.\n modal.show();\n\n return;\n }).catch(Notification.exception);\n });\n\n $(ACTIONS.SET_CONTENT_VISIBILITY).click(function(e) {\n e.preventDefault();\n\n var contentid = $(this).data('contentid');\n var visibility = $(this).data('visibility');\n\n setContentVisibility(contentid, visibility);\n });\n };\n\n /**\n * Delete content from the content bank.\n *\n * @param {int} contentid The content to delete.\n * @param {int} contextid The contextid where the content belongs.\n */\n function deleteContent(contentid, contextid) {\n var request = {\n methodname: 'core_contentbank_delete_content',\n args: {\n contentids: {contentid}\n }\n };\n\n var requestType = 'success';\n Ajax.call([request])[0].then(function(data) {\n if (data.result) {\n return 'contentdeleted';\n }\n requestType = 'error';\n return 'contentnotdeleted';\n\n }).done(function(message) {\n var params = {\n contextid: contextid\n };\n if (requestType == 'success') {\n params.statusmsg = message;\n } else {\n params.errormsg = message;\n }\n // Redirect to the main content bank page and display the message as a notification.\n window.location.href = Url.relativeUrl('contentbank/index.php', params, false);\n }).fail(Notification.exception);\n }\n\n /**\n * Rename content in the content bank.\n *\n * @param {int} contentid The content to rename.\n * @param {string} name The new name for the content.\n */\n function renameContent(contentid, name) {\n var request = {\n methodname: 'core_contentbank_rename_content',\n args: {\n contentid: contentid,\n name: name\n }\n };\n var requestType = 'success';\n Ajax.call([request])[0].then(function(data) {\n if (data.result) {\n return 'contentrenamed';\n }\n requestType = 'error';\n return data.warnings[0].message;\n\n }).then(function(message) {\n var params = null;\n if (requestType == 'success') {\n params = {\n id: contentid,\n statusmsg: message\n };\n // Redirect to the content view page and display the message as a notification.\n window.location.href = Url.relativeUrl('contentbank/view.php', params, false);\n } else {\n // Fetch error notifications.\n Notification.addNotification({\n message: message,\n type: 'error'\n });\n Notification.fetchNotifications();\n }\n return;\n }).catch(Notification.exception);\n }\n\n /**\n * Set content visibility in the content bank.\n *\n * @param {int} contentid The content to modify\n * @param {int} visibility The new visibility value\n */\n function setContentVisibility(contentid, visibility) {\n var request = {\n methodname: 'core_contentbank_set_content_visibility',\n args: {\n contentid: contentid,\n visibility: visibility\n }\n };\n var requestType = 'success';\n Ajax.call([request])[0].then(function(data) {\n if (data.result) {\n return 'contentvisibilitychanged';\n }\n requestType = 'error';\n return data.warnings[0].message;\n\n }).then(function(message) {\n var params = null;\n if (requestType == 'success') {\n params = {\n id: contentid,\n statusmsg: message\n };\n // Redirect to the content view page and display the message as a notification.\n window.location.href = Url.relativeUrl('contentbank/view.php', params, false);\n } else {\n // Fetch error notifications.\n Notification.addNotification({\n message: message,\n type: 'error'\n });\n Notification.fetchNotifications();\n }\n return;\n }).catch(Notification.exception);\n }\n\n return /** @alias module:core_contentbank/actions */ {\n // Public variables and functions.\n\n /**\n * Initialise the contentbank actions.\n *\n * @method init\n * @return {Actions}\n */\n 'init': function() {\n return new Actions();\n }\n };\n});\n"],"file":"actions.min.js"}
\ No newline at end of file
+{"version":3,"file":"actions.min.js","sources":["../src/actions.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 .\n\n/**\n * Module to manage content bank actions, such as delete or rename.\n *\n * @module core_contentbank/actions\n * @copyright 2020 Sara Arjona \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/ajax',\n 'core/notification',\n 'core/str',\n 'core/templates',\n 'core/url',\n 'core/modal_factory',\n 'core/modal_events'],\nfunction($, Ajax, Notification, Str, Templates, Url, ModalFactory, ModalEvents) {\n\n /**\n * List of action selectors.\n *\n * @type {{DELETE_CONTENT: string}}\n */\n var ACTIONS = {\n DELETE_CONTENT: '[data-action=\"deletecontent\"]',\n RENAME_CONTENT: '[data-action=\"renamecontent\"]',\n SET_CONTENT_VISIBILITY: '[data-action=\"setcontentvisibility\"]',\n };\n\n /**\n * Actions class.\n */\n var Actions = function() {\n this.registerEvents();\n };\n\n /**\n * Register event listeners.\n */\n Actions.prototype.registerEvents = function() {\n $(ACTIONS.DELETE_CONTENT).click(function(e) {\n e.preventDefault();\n\n var contentname = $(this).data('contentname');\n var contentuses = $(this).data('uses');\n var contentid = $(this).data('contentid');\n var contextid = $(this).data('contextid');\n\n var strings = [\n {\n key: 'deletecontent',\n component: 'core_contentbank'\n },\n {\n key: 'deletecontentconfirm',\n component: 'core_contentbank',\n param: {\n name: contentname,\n }\n },\n {\n key: 'deletecontentconfirmlinked',\n component: 'core_contentbank',\n },\n {\n key: 'delete',\n component: 'core'\n },\n ];\n\n var deleteButtonText = '';\n Str.get_strings(strings).then(function(langStrings) {\n var modalTitle = langStrings[0];\n var modalContent = langStrings[1];\n if (contentuses > 0) {\n modalContent += ' ' + langStrings[2];\n }\n deleteButtonText = langStrings[3];\n\n return ModalFactory.create({\n title: modalTitle,\n body: modalContent,\n type: ModalFactory.types.SAVE_CANCEL,\n large: true\n });\n }).done(function(modal) {\n modal.setSaveButtonText(deleteButtonText);\n modal.getRoot().on(ModalEvents.save, function() {\n // The action is now confirmed, sending an action for it.\n return deleteContent(contentid, contextid);\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n // Show the modal.\n modal.show();\n\n return;\n }).catch(Notification.exception);\n });\n\n $(ACTIONS.RENAME_CONTENT).click(function(e) {\n e.preventDefault();\n\n var contentname = $(this).data('contentname');\n var contentid = $(this).data('contentid');\n\n var strings = [\n {\n key: 'renamecontent',\n component: 'core_contentbank'\n },\n {\n key: 'rename',\n component: 'core_contentbank'\n },\n ];\n\n var saveButtonText = '';\n Str.get_strings(strings).then(function(langStrings) {\n var modalTitle = langStrings[0];\n saveButtonText = langStrings[1];\n\n return ModalFactory.create({\n title: modalTitle,\n body: Templates.render('core_contentbank/renamecontent', {'contentid': contentid, 'name': contentname}),\n type: ModalFactory.types.SAVE_CANCEL\n });\n }).then(function(modal) {\n modal.setSaveButtonText(saveButtonText);\n modal.getRoot().on(ModalEvents.save, function(e) {\n // The action is now confirmed, sending an action for it.\n var newname = $(\"#newname\").val().trim();\n if (newname) {\n renameContent(contentid, newname);\n } else {\n var errorStrings = [\n {\n key: 'error',\n },\n {\n key: 'emptynamenotallowed',\n component: 'core_contentbank',\n },\n ];\n Str.get_strings(errorStrings).then(function(langStrings) {\n Notification.alert(langStrings[0], langStrings[1]);\n }).catch(Notification.exception);\n e.preventDefault();\n }\n });\n\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n // Show the modal.\n modal.show();\n\n return;\n }).catch(Notification.exception);\n });\n\n $(ACTIONS.SET_CONTENT_VISIBILITY).click(function(e) {\n e.preventDefault();\n\n var contentid = $(this).data('contentid');\n var visibility = $(this).data('visibility');\n\n setContentVisibility(contentid, visibility);\n });\n };\n\n /**\n * Delete content from the content bank.\n *\n * @param {int} contentid The content to delete.\n * @param {int} contextid The contextid where the content belongs.\n */\n function deleteContent(contentid, contextid) {\n var request = {\n methodname: 'core_contentbank_delete_content',\n args: {\n contentids: {contentid}\n }\n };\n\n var requestType = 'success';\n Ajax.call([request])[0].then(function(data) {\n if (data.result) {\n return 'contentdeleted';\n }\n requestType = 'error';\n return 'contentnotdeleted';\n\n }).done(function(message) {\n var params = {\n contextid: contextid\n };\n if (requestType == 'success') {\n params.statusmsg = message;\n } else {\n params.errormsg = message;\n }\n // Redirect to the main content bank page and display the message as a notification.\n window.location.href = Url.relativeUrl('contentbank/index.php', params, false);\n }).fail(Notification.exception);\n }\n\n /**\n * Rename content in the content bank.\n *\n * @param {int} contentid The content to rename.\n * @param {string} name The new name for the content.\n */\n function renameContent(contentid, name) {\n var request = {\n methodname: 'core_contentbank_rename_content',\n args: {\n contentid: contentid,\n name: name\n }\n };\n var requestType = 'success';\n Ajax.call([request])[0].then(function(data) {\n if (data.result) {\n return 'contentrenamed';\n }\n requestType = 'error';\n return data.warnings[0].message;\n\n }).then(function(message) {\n var params = null;\n if (requestType == 'success') {\n params = {\n id: contentid,\n statusmsg: message\n };\n // Redirect to the content view page and display the message as a notification.\n window.location.href = Url.relativeUrl('contentbank/view.php', params, false);\n } else {\n // Fetch error notifications.\n Notification.addNotification({\n message: message,\n type: 'error'\n });\n Notification.fetchNotifications();\n }\n return;\n }).catch(Notification.exception);\n }\n\n /**\n * Set content visibility in the content bank.\n *\n * @param {int} contentid The content to modify\n * @param {int} visibility The new visibility value\n */\n function setContentVisibility(contentid, visibility) {\n var request = {\n methodname: 'core_contentbank_set_content_visibility',\n args: {\n contentid: contentid,\n visibility: visibility\n }\n };\n var requestType = 'success';\n Ajax.call([request])[0].then(function(data) {\n if (data.result) {\n return 'contentvisibilitychanged';\n }\n requestType = 'error';\n return data.warnings[0].message;\n\n }).then(function(message) {\n var params = null;\n if (requestType == 'success') {\n params = {\n id: contentid,\n statusmsg: message\n };\n // Redirect to the content view page and display the message as a notification.\n window.location.href = Url.relativeUrl('contentbank/view.php', params, false);\n } else {\n // Fetch error notifications.\n Notification.addNotification({\n message: message,\n type: 'error'\n });\n Notification.fetchNotifications();\n }\n return;\n }).catch(Notification.exception);\n }\n\n return /** @alias module:core_contentbank/actions */ {\n // Public variables and functions.\n\n /**\n * Initialise the contentbank actions.\n *\n * @method init\n * @return {Actions}\n */\n 'init': function() {\n return new Actions();\n }\n };\n});\n"],"names":["define","$","Ajax","Notification","Str","Templates","Url","ModalFactory","ModalEvents","ACTIONS","Actions","registerEvents","prototype","click","e","preventDefault","contentname","this","data","contentuses","contentid","contextid","strings","key","component","param","name","deleteButtonText","get_strings","then","langStrings","modalTitle","modalContent","create","title","body","type","types","SAVE_CANCEL","large","done","modal","setSaveButtonText","getRoot","on","save","request","methodname","args","contentids","requestType","call","result","message","params","statusmsg","errormsg","window","location","href","relativeUrl","fail","exception","deleteContent","hidden","destroy","show","catch","saveButtonText","render","newname","val","trim","warnings","id","addNotification","fetchNotifications","renameContent","alert","visibility","setContentVisibility"],"mappings":"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"}
\ No newline at end of file
diff --git a/contentbank/amd/build/search.min.js b/contentbank/amd/build/search.min.js
index 8309c2460c1..677143eb438 100644
--- a/contentbank/amd/build/search.min.js
+++ b/contentbank/amd/build/search.min.js
@@ -1,2 +1,10 @@
-define ("core_contentbank/search",["exports","jquery","core_contentbank/selectors","core/str","core/pending","core/utils"],function(a,b,c,d,e,f){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=g(b);c=g(c);e=g(e);function g(a){return a&&a.__esModule?a:{default:a}}function h(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 i(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var i=a.apply(b,c);function f(a){h(i,d,e,f,g,"next",a)}function g(a){h(i,d,e,f,g,"throw",a)}f(void 0)})}}var j=function(){var a=new e.default,d=(0,b.default)(c.default.regions.contentbank);k(d);a.resolve()};a.init=j;var k=function(a){var b=a.find(c.default.elements.searchinput)[0];a.on("click",c.default.actions.search,function(c){c.preventDefault();l(a,b.value)});a.on("click",c.default.actions.clearSearch,function(c){c.preventDefault();b.value="";b.focus();l(a,b.value)});b.addEventListener("input",(0,f.debounce)(function(){l(a,b.value)},300))},l=function(){var a=i(regeneratorRuntime.mark(function a(b,e){var f,g,h,i;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:f=b.find(c.default.actions.clearSearch)[0];g=b.find(c.default.elements.cbnavbarbreadcrumb)[0];h=b.find(c.default.elements.cbnavbartotalsearch)[0];i=m(b,e);if(!(0"+a.substr(d,b.length)+""+a.substr(d+b.length)}}return c}});
-//# sourceMappingURL=search.min.js.map
+define("core_contentbank/search",["exports","jquery","core_contentbank/selectors","core/str","core/pending","core/utils"],(function(_exports,_jquery,_selectors,_str,_pending,_utils){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
+/**
+ * Search methods for finding contents in the content bank.
+ *
+ * @module core_contentbank/search
+ * @copyright 2020 Sara Arjona
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),_selectors=_interopRequireDefault(_selectors),_pending=_interopRequireDefault(_pending);_exports.init=()=>{const pendingPromise=new _pending.default,root=(0,_jquery.default)(_selectors.default.regions.contentbank);registerListenerEvents(root),pendingPromise.resolve()};const registerListenerEvents=root=>{const searchInput=root.find(_selectors.default.elements.searchinput)[0];root.on("click",_selectors.default.actions.search,(function(e){e.preventDefault(),toggleSearchResultsView(root,searchInput.value)})),root.on("click",_selectors.default.actions.clearSearch,(function(e){e.preventDefault(),searchInput.value="",searchInput.focus(),toggleSearchResultsView(root,searchInput.value)})),searchInput.addEventListener("input",(0,_utils.debounce)((()=>{toggleSearchResultsView(root,searchInput.value)}),300))},toggleSearchResultsView=async(body,searchQuery)=>{const clearSearchButton=body.find(_selectors.default.actions.clearSearch)[0],navbarBreadcrumb=body.find(_selectors.default.elements.cbnavbarbreadcrumb)[0],navbarTotal=body.find(_selectors.default.elements.cbnavbartotalsearch)[0],filteredContents=filterContents(body,searchQuery);searchQuery.length>0?(clearSearchButton.classList.remove("d-none"),navbarBreadcrumb.classList.add("d-none"),navbarTotal.innerHTML=await(0,_str.get_string)("itemsfound","core_contentbank",filteredContents.length),navbarTotal.classList.remove("d-none")):(clearSearchButton.classList.add("d-none"),navbarBreadcrumb.classList.remove("d-none"),navbarTotal.classList.add("d-none"))},filterContents=(body,searchTerm)=>{const contents=Array.from(body.find(_selectors.default.elements.listitem)),searchResults=[];return contents.forEach((content=>{const contentName=content.getAttribute("data-name");if(""===searchTerm||contentName.toLowerCase().includes(searchTerm.toLowerCase())){searchResults.push(content);content.querySelector(_selectors.default.regions.cbcontentname).innerHTML=highlight(contentName,searchTerm),content.classList.remove("d-none")}else content.classList.add("d-none")})),searchResults},highlight=(text,highlightText)=>{let result=text;if(""!==highlightText){const pos=text.toLowerCase().indexOf(highlightText.toLowerCase());pos>-1&&(result=text.substr(0,pos)+''+text.substr(pos,highlightText.length)+""+text.substr(pos+highlightText.length))}return result}}));
+
+//# sourceMappingURL=search.min.js.map
\ No newline at end of file
diff --git a/contentbank/amd/build/search.min.js.map b/contentbank/amd/build/search.min.js.map
index d618defb07e..f1f44cb4aca 100644
--- a/contentbank/amd/build/search.min.js.map
+++ b/contentbank/amd/build/search.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/search.js"],"names":["init","pendingPromise","Pending","root","selectors","regions","contentbank","registerListenerEvents","resolve","searchInput","find","elements","searchinput","on","actions","search","e","preventDefault","toggleSearchResultsView","value","clearSearch","focus","addEventListener","body","searchQuery","clearSearchButton","navbarBreadcrumb","cbnavbarbreadcrumb","navbarTotal","cbnavbartotalsearch","filteredContents","filterContents","length","classList","remove","add","innerHTML","searchTerm","contents","Array","from","listitem","searchResults","forEach","content","contentName","getAttribute","toLowerCase","includes","push","contentNameElement","querySelector","cbcontentname","highlight","text","highlightText","result","pos","indexOf","substr"],"mappings":"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","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 .\n\n/**\n * Search methods for finding contents in the content bank.\n *\n * @module core_contentbank/search\n * @copyright 2020 Sara Arjona \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport selectors from 'core_contentbank/selectors';\nimport {get_string as getString} from 'core/str';\nimport Pending from 'core/pending';\nimport {debounce} from 'core/utils';\n\n/**\n * Set up the search.\n *\n * @method init\n */\nexport const init = () => {\n const pendingPromise = new Pending();\n\n const root = $(selectors.regions.contentbank);\n registerListenerEvents(root);\n\n pendingPromise.resolve();\n};\n\n/**\n * Register contentbank search related event listeners.\n *\n * @method registerListenerEvents\n * @param {Object} root The root element for the contentbank.\n */\nconst registerListenerEvents = (root) => {\n\n const searchInput = root.find(selectors.elements.searchinput)[0];\n\n root.on('click', selectors.actions.search, function(e) {\n e.preventDefault();\n toggleSearchResultsView(root, searchInput.value);\n });\n\n root.on('click', selectors.actions.clearSearch, function(e) {\n e.preventDefault();\n searchInput.value = \"\";\n searchInput.focus();\n toggleSearchResultsView(root, searchInput.value);\n });\n\n // The search input is also triggered.\n searchInput.addEventListener('input', debounce(() => {\n // Display the search results.\n toggleSearchResultsView(root, searchInput.value);\n }, 300));\n\n};\n\n/**\n * Toggle (display/hide) the search results depending on the value of the search query.\n *\n * @method toggleSearchResultsView\n * @param {HTMLElement} body The root element for the contentbank.\n * @param {String} searchQuery The search query.\n */\nconst toggleSearchResultsView = async(body, searchQuery) => {\n const clearSearchButton = body.find(selectors.actions.clearSearch)[0];\n\n const navbarBreadcrumb = body.find(selectors.elements.cbnavbarbreadcrumb)[0];\n const navbarTotal = body.find(selectors.elements.cbnavbartotalsearch)[0];\n // Update the results.\n const filteredContents = filterContents(body, searchQuery);\n if (searchQuery.length > 0) {\n // As the search query is present, search results should be displayed.\n\n // Display the \"clear\" search button in the activity chooser search bar.\n clearSearchButton.classList.remove('d-none');\n\n // Change the cb-navbar to display total items found.\n navbarBreadcrumb.classList.add('d-none');\n navbarTotal.innerHTML = await getString('itemsfound', 'core_contentbank', filteredContents.length);\n navbarTotal.classList.remove('d-none');\n } else {\n // As search query is not present, the search results should be removed.\n\n // Hide the \"clear\" search button in the activity chooser search bar.\n clearSearchButton.classList.add('d-none');\n\n // Display again the breadcrumb in the navbar.\n navbarBreadcrumb.classList.remove('d-none');\n navbarTotal.classList.add('d-none');\n }\n};\n\n/**\n * Return the list of contents which have a name that matches the given search term.\n *\n * @method filterContents\n * @param {HTMLElement} body The root element for the contentbank.\n * @param {String} searchTerm The search term to match.\n * @return {Array}\n */\nconst filterContents = (body, searchTerm) => {\n const contents = Array.from(body.find(selectors.elements.listitem));\n const searchResults = [];\n contents.forEach((content) => {\n const contentName = content.getAttribute('data-name');\n if (searchTerm === '' || contentName.toLowerCase().includes(searchTerm.toLowerCase())) {\n // The content matches the search criteria so it should be displayed and hightlighted.\n searchResults.push(content);\n const contentNameElement = content.querySelector(selectors.regions.cbcontentname);\n contentNameElement.innerHTML = highlight(contentName, searchTerm);\n content.classList.remove('d-none');\n } else {\n content.classList.add('d-none');\n }\n });\n\n return searchResults;\n};\n\n/**\n * Highlight a given string in a text.\n *\n * @method highlight\n * @param {String} text The whole text.\n * @param {String} highlightText The piece of text to highlight.\n * @return {String}\n */\nconst highlight = (text, highlightText) => {\n let result = text;\n if (highlightText !== '') {\n const pos = text.toLowerCase().indexOf(highlightText.toLowerCase());\n if (pos > -1) {\n result = text.substr(0, pos) + '' + text.substr(pos, highlightText.length) + '' +\n text.substr(pos + highlightText.length);\n }\n }\n\n return result;\n};\n"],"file":"search.min.js"}
\ No newline at end of file
+{"version":3,"file":"search.min.js","sources":["../src/search.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 .\n\n/**\n * Search methods for finding contents in the content bank.\n *\n * @module core_contentbank/search\n * @copyright 2020 Sara Arjona \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport selectors from 'core_contentbank/selectors';\nimport {get_string as getString} from 'core/str';\nimport Pending from 'core/pending';\nimport {debounce} from 'core/utils';\n\n/**\n * Set up the search.\n *\n * @method init\n */\nexport const init = () => {\n const pendingPromise = new Pending();\n\n const root = $(selectors.regions.contentbank);\n registerListenerEvents(root);\n\n pendingPromise.resolve();\n};\n\n/**\n * Register contentbank search related event listeners.\n *\n * @method registerListenerEvents\n * @param {Object} root The root element for the contentbank.\n */\nconst registerListenerEvents = (root) => {\n\n const searchInput = root.find(selectors.elements.searchinput)[0];\n\n root.on('click', selectors.actions.search, function(e) {\n e.preventDefault();\n toggleSearchResultsView(root, searchInput.value);\n });\n\n root.on('click', selectors.actions.clearSearch, function(e) {\n e.preventDefault();\n searchInput.value = \"\";\n searchInput.focus();\n toggleSearchResultsView(root, searchInput.value);\n });\n\n // The search input is also triggered.\n searchInput.addEventListener('input', debounce(() => {\n // Display the search results.\n toggleSearchResultsView(root, searchInput.value);\n }, 300));\n\n};\n\n/**\n * Toggle (display/hide) the search results depending on the value of the search query.\n *\n * @method toggleSearchResultsView\n * @param {HTMLElement} body The root element for the contentbank.\n * @param {String} searchQuery The search query.\n */\nconst toggleSearchResultsView = async(body, searchQuery) => {\n const clearSearchButton = body.find(selectors.actions.clearSearch)[0];\n\n const navbarBreadcrumb = body.find(selectors.elements.cbnavbarbreadcrumb)[0];\n const navbarTotal = body.find(selectors.elements.cbnavbartotalsearch)[0];\n // Update the results.\n const filteredContents = filterContents(body, searchQuery);\n if (searchQuery.length > 0) {\n // As the search query is present, search results should be displayed.\n\n // Display the \"clear\" search button in the activity chooser search bar.\n clearSearchButton.classList.remove('d-none');\n\n // Change the cb-navbar to display total items found.\n navbarBreadcrumb.classList.add('d-none');\n navbarTotal.innerHTML = await getString('itemsfound', 'core_contentbank', filteredContents.length);\n navbarTotal.classList.remove('d-none');\n } else {\n // As search query is not present, the search results should be removed.\n\n // Hide the \"clear\" search button in the activity chooser search bar.\n clearSearchButton.classList.add('d-none');\n\n // Display again the breadcrumb in the navbar.\n navbarBreadcrumb.classList.remove('d-none');\n navbarTotal.classList.add('d-none');\n }\n};\n\n/**\n * Return the list of contents which have a name that matches the given search term.\n *\n * @method filterContents\n * @param {HTMLElement} body The root element for the contentbank.\n * @param {String} searchTerm The search term to match.\n * @return {Array}\n */\nconst filterContents = (body, searchTerm) => {\n const contents = Array.from(body.find(selectors.elements.listitem));\n const searchResults = [];\n contents.forEach((content) => {\n const contentName = content.getAttribute('data-name');\n if (searchTerm === '' || contentName.toLowerCase().includes(searchTerm.toLowerCase())) {\n // The content matches the search criteria so it should be displayed and hightlighted.\n searchResults.push(content);\n const contentNameElement = content.querySelector(selectors.regions.cbcontentname);\n contentNameElement.innerHTML = highlight(contentName, searchTerm);\n content.classList.remove('d-none');\n } else {\n content.classList.add('d-none');\n }\n });\n\n return searchResults;\n};\n\n/**\n * Highlight a given string in a text.\n *\n * @method highlight\n * @param {String} text The whole text.\n * @param {String} highlightText The piece of text to highlight.\n * @return {String}\n */\nconst highlight = (text, highlightText) => {\n let result = text;\n if (highlightText !== '') {\n const pos = text.toLowerCase().indexOf(highlightText.toLowerCase());\n if (pos > -1) {\n result = text.substr(0, pos) + '' + text.substr(pos, highlightText.length) + '' +\n text.substr(pos + highlightText.length);\n }\n }\n\n return result;\n};\n"],"names":["pendingPromise","Pending","root","selectors","regions","contentbank","registerListenerEvents","resolve","searchInput","find","elements","searchinput","on","actions","search","e","preventDefault","toggleSearchResultsView","value","clearSearch","focus","addEventListener","async","body","searchQuery","clearSearchButton","navbarBreadcrumb","cbnavbarbreadcrumb","navbarTotal","cbnavbartotalsearch","filteredContents","filterContents","length","classList","remove","add","innerHTML","searchTerm","contents","Array","from","listitem","searchResults","forEach","content","contentName","getAttribute","toLowerCase","includes","push","querySelector","cbcontentname","highlight","text","highlightText","result","pos","indexOf","substr"],"mappings":";;;;;;;gOAkCoB,WACVA,eAAiB,IAAIC,iBAErBC,MAAO,mBAAEC,mBAAUC,QAAQC,aACjCC,uBAAuBJ,MAEvBF,eAAeO,iBASbD,uBAA0BJ,aAEtBM,YAAcN,KAAKO,KAAKN,mBAAUO,SAASC,aAAa,GAE9DT,KAAKU,GAAG,QAAST,mBAAUU,QAAQC,QAAQ,SAASC,GAChDA,EAAEC,iBACFC,wBAAwBf,KAAMM,YAAYU,UAG9ChB,KAAKU,GAAG,QAAST,mBAAUU,QAAQM,aAAa,SAASJ,GACrDA,EAAEC,iBACFR,YAAYU,MAAQ,GACpBV,YAAYY,QACZH,wBAAwBf,KAAMM,YAAYU,UAI9CV,YAAYa,iBAAiB,SAAS,oBAAS,KAE3CJ,wBAAwBf,KAAMM,YAAYU,SAC3C,OAWDD,wBAA0BK,MAAMC,KAAMC,qBAClCC,kBAAoBF,KAAKd,KAAKN,mBAAUU,QAAQM,aAAa,GAE7DO,iBAAmBH,KAAKd,KAAKN,mBAAUO,SAASiB,oBAAoB,GACpEC,YAAcL,KAAKd,KAAKN,mBAAUO,SAASmB,qBAAqB,GAEhEC,iBAAmBC,eAAeR,KAAMC,aAC1CA,YAAYQ,OAAS,GAIrBP,kBAAkBQ,UAAUC,OAAO,UAGnCR,iBAAiBO,UAAUE,IAAI,UAC/BP,YAAYQ,gBAAkB,mBAAU,aAAc,mBAAoBN,iBAAiBE,QAC3FJ,YAAYK,UAAUC,OAAO,YAK7BT,kBAAkBQ,UAAUE,IAAI,UAGhCT,iBAAiBO,UAAUC,OAAO,UAClCN,YAAYK,UAAUE,IAAI,YAY5BJ,eAAiB,CAACR,KAAMc,oBACpBC,SAAWC,MAAMC,KAAKjB,KAAKd,KAAKN,mBAAUO,SAAS+B,WACnDC,cAAgB,UACtBJ,SAASK,SAASC,gBACRC,YAAcD,QAAQE,aAAa,gBACtB,KAAfT,YAAqBQ,YAAYE,cAAcC,SAASX,WAAWU,eAAgB,CAEnFL,cAAcO,KAAKL,SACQA,QAAQM,cAAc/C,mBAAUC,QAAQ+C,eAChDf,UAAYgB,UAAUP,YAAaR,YACtDO,QAAQX,UAAUC,OAAO,eAEzBU,QAAQX,UAAUE,IAAI,aAIvBO,eAWLU,UAAY,CAACC,KAAMC,qBACjBC,OAASF,QACS,KAAlBC,cAAsB,OAChBE,IAAMH,KAAKN,cAAcU,QAAQH,cAAcP,eACjDS,KAAO,IACPD,OAASF,KAAKK,OAAO,EAAGF,KAAO,2BAA6BH,KAAKK,OAAOF,IAAKF,cAActB,QAAU,UACjGqB,KAAKK,OAAOF,IAAMF,cAActB,gBAIrCuB"}
\ No newline at end of file
diff --git a/contentbank/amd/build/selectors.min.js b/contentbank/amd/build/selectors.min.js
index 933ee3057e1..d049bae5028 100644
--- a/contentbank/amd/build/selectors.min.js
+++ b/contentbank/amd/build/selectors.min.js
@@ -1,2 +1,11 @@
-define ("core_contentbank/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;var b=function(a,b){return"[data-".concat(a,"=\"").concat(b,"\"]")},c={regions:{cbcontentname:b("region","cb-content-name"),contentbank:b("region","contentbank"),filearea:b("region","filearea")},actions:{search:b("action","searchcontent"),clearSearch:b("action","clearsearch"),viewgrid:b("action","viewgrid"),viewlist:b("action","viewlist"),sortname:b("action","sortname"),sortuses:b("action","sortuses"),sortdate:b("action","sortdate"),sortsize:b("action","sortsize"),sorttype:b("action","sorttype"),sortauthor:b("action","sortauthor")},elements:{listitem:".cb-listitem",heading:".cb-heading",cell:".cb-column",cbnavbarbreadcrumb:".cb-navbar-breadbrumb",cbnavbartotalsearch:".cb-navbar-totalsearch",searchinput:"#searchinput",sortbutton:".cb-btnsort"}};a.default=c;return a.default});
-//# sourceMappingURL=selectors.min.js.map
+define("core_contentbank/selectors",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;
+/**
+ * Define all of the selectors we will be using on the contentbank interface.
+ *
+ * @module core_contentbank/selectors
+ * @copyright 2020 Sara Arjona
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+const getDataSelector=(name,value)=>"[data-".concat(name,'="').concat(value,'"]');var _default={regions:{cbcontentname:getDataSelector("region","cb-content-name"),contentbank:getDataSelector("region","contentbank"),filearea:getDataSelector("region","filearea")},actions:{search:getDataSelector("action","searchcontent"),clearSearch:getDataSelector("action","clearsearch"),viewgrid:getDataSelector("action","viewgrid"),viewlist:getDataSelector("action","viewlist"),sortname:getDataSelector("action","sortname"),sortuses:getDataSelector("action","sortuses"),sortdate:getDataSelector("action","sortdate"),sortsize:getDataSelector("action","sortsize"),sorttype:getDataSelector("action","sorttype"),sortauthor:getDataSelector("action","sortauthor")},elements:{listitem:".cb-listitem",heading:".cb-heading",cell:".cb-column",cbnavbarbreadcrumb:".cb-navbar-breadbrumb",cbnavbartotalsearch:".cb-navbar-totalsearch",searchinput:"#searchinput",sortbutton:".cb-btnsort"}};return _exports.default=_default,_exports.default}));
+
+//# sourceMappingURL=selectors.min.js.map
\ No newline at end of file
diff --git a/contentbank/amd/build/selectors.min.js.map b/contentbank/amd/build/selectors.min.js.map
index fd743ed665d..76acba8662c 100644
--- a/contentbank/amd/build/selectors.min.js.map
+++ b/contentbank/amd/build/selectors.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/selectors.js"],"names":["getDataSelector","name","value","regions","cbcontentname","contentbank","filearea","actions","search","clearSearch","viewgrid","viewlist","sortname","sortuses","sortdate","sortsize","sorttype","sortauthor","elements","listitem","heading","cell","cbnavbarbreadcrumb","cbnavbartotalsearch","searchinput","sortbutton"],"mappings":"+IA+BMA,CAAAA,CAAe,CAAG,SAACC,CAAD,CAAOC,CAAP,CAAiB,CACrC,sBAAgBD,CAAhB,eAAyBC,CAAzB,OACH,C,GAEc,CACXC,OAAO,CAAE,CACLC,aAAa,CAAEJ,CAAe,CAAC,QAAD,CAAW,iBAAX,CADzB,CAELK,WAAW,CAAEL,CAAe,CAAC,QAAD,CAAW,aAAX,CAFvB,CAGLM,QAAQ,CAAEN,CAAe,CAAC,QAAD,CAAW,UAAX,CAHpB,CADE,CAMXO,OAAO,CAAE,CACLC,MAAM,CAAER,CAAe,CAAC,QAAD,CAAW,eAAX,CADlB,CAELS,WAAW,CAAET,CAAe,CAAC,QAAD,CAAW,aAAX,CAFvB,CAGLU,QAAQ,CAAEV,CAAe,CAAC,QAAD,CAAW,UAAX,CAHpB,CAILW,QAAQ,CAAEX,CAAe,CAAC,QAAD,CAAW,UAAX,CAJpB,CAKLY,QAAQ,CAAEZ,CAAe,CAAC,QAAD,CAAW,UAAX,CALpB,CAMLa,QAAQ,CAAEb,CAAe,CAAC,QAAD,CAAW,UAAX,CANpB,CAOLc,QAAQ,CAAEd,CAAe,CAAC,QAAD,CAAW,UAAX,CAPpB,CAQLe,QAAQ,CAAEf,CAAe,CAAC,QAAD,CAAW,UAAX,CARpB,CASLgB,QAAQ,CAAEhB,CAAe,CAAC,QAAD,CAAW,UAAX,CATpB,CAULiB,UAAU,CAAEjB,CAAe,CAAC,QAAD,CAAW,YAAX,CAVtB,CANE,CAkBXkB,QAAQ,CAAE,CACNC,QAAQ,CAAE,cADJ,CAENC,OAAO,CAAE,aAFH,CAGNC,IAAI,CAAE,YAHA,CAINC,kBAAkB,CAAE,uBAJd,CAKNC,mBAAmB,CAAE,wBALf,CAMNC,WAAW,CAAE,cANP,CAONC,UAAU,CAAE,aAPN,CAlBC,C","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 .\n\n/**\n * Define all of the selectors we will be using on the contentbank interface.\n *\n * @module core_contentbank/selectors\n * @copyright 2020 Sara Arjona \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * A small helper function to build queryable data selectors.\n *\n * @method getDataSelector\n * @param {String} name\n * @param {String} value\n * @return {string}\n */\nconst getDataSelector = (name, value) => {\n return `[data-${name}=\"${value}\"]`;\n};\n\nexport default {\n regions: {\n cbcontentname: getDataSelector('region', 'cb-content-name'),\n contentbank: getDataSelector('region', 'contentbank'),\n filearea: getDataSelector('region', 'filearea')\n },\n actions: {\n search: getDataSelector('action', 'searchcontent'),\n clearSearch: getDataSelector('action', 'clearsearch'),\n viewgrid: getDataSelector('action', 'viewgrid'),\n viewlist: getDataSelector('action', 'viewlist'),\n sortname: getDataSelector('action', 'sortname'),\n sortuses: getDataSelector('action', 'sortuses'),\n sortdate: getDataSelector('action', 'sortdate'),\n sortsize: getDataSelector('action', 'sortsize'),\n sorttype: getDataSelector('action', 'sorttype'),\n sortauthor: getDataSelector('action', 'sortauthor'),\n },\n elements: {\n listitem: '.cb-listitem',\n heading: '.cb-heading',\n cell: '.cb-column',\n cbnavbarbreadcrumb: '.cb-navbar-breadbrumb',\n cbnavbartotalsearch: '.cb-navbar-totalsearch',\n searchinput: '#searchinput',\n sortbutton: '.cb-btnsort'\n },\n};\n"],"file":"selectors.min.js"}
\ No newline at end of file
+{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 .\n\n/**\n * Define all of the selectors we will be using on the contentbank interface.\n *\n * @module core_contentbank/selectors\n * @copyright 2020 Sara Arjona \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * A small helper function to build queryable data selectors.\n *\n * @method getDataSelector\n * @param {String} name\n * @param {String} value\n * @return {string}\n */\nconst getDataSelector = (name, value) => {\n return `[data-${name}=\"${value}\"]`;\n};\n\nexport default {\n regions: {\n cbcontentname: getDataSelector('region', 'cb-content-name'),\n contentbank: getDataSelector('region', 'contentbank'),\n filearea: getDataSelector('region', 'filearea')\n },\n actions: {\n search: getDataSelector('action', 'searchcontent'),\n clearSearch: getDataSelector('action', 'clearsearch'),\n viewgrid: getDataSelector('action', 'viewgrid'),\n viewlist: getDataSelector('action', 'viewlist'),\n sortname: getDataSelector('action', 'sortname'),\n sortuses: getDataSelector('action', 'sortuses'),\n sortdate: getDataSelector('action', 'sortdate'),\n sortsize: getDataSelector('action', 'sortsize'),\n sorttype: getDataSelector('action', 'sorttype'),\n sortauthor: getDataSelector('action', 'sortauthor'),\n },\n elements: {\n listitem: '.cb-listitem',\n heading: '.cb-heading',\n cell: '.cb-column',\n cbnavbarbreadcrumb: '.cb-navbar-breadbrumb',\n cbnavbartotalsearch: '.cb-navbar-totalsearch',\n searchinput: '#searchinput',\n sortbutton: '.cb-btnsort'\n },\n};\n"],"names":["getDataSelector","name","value","regions","cbcontentname","contentbank","filearea","actions","search","clearSearch","viewgrid","viewlist","sortname","sortuses","sortdate","sortsize","sorttype","sortauthor","elements","listitem","heading","cell","cbnavbarbreadcrumb","cbnavbartotalsearch","searchinput","sortbutton"],"mappings":";;;;;;;;MA+BMA,gBAAkB,CAACC,KAAMC,wBACXD,kBAASC,yBAGd,CACXC,QAAS,CACLC,cAAeJ,gBAAgB,SAAU,mBACzCK,YAAaL,gBAAgB,SAAU,eACvCM,SAAUN,gBAAgB,SAAU,aAExCO,QAAS,CACLC,OAAQR,gBAAgB,SAAU,iBAClCS,YAAaT,gBAAgB,SAAU,eACvCU,SAAUV,gBAAgB,SAAU,YACpCW,SAAUX,gBAAgB,SAAU,YACpCY,SAAUZ,gBAAgB,SAAU,YACpCa,SAAUb,gBAAgB,SAAU,YACpCc,SAAUd,gBAAgB,SAAU,YACpCe,SAAUf,gBAAgB,SAAU,YACpCgB,SAAUhB,gBAAgB,SAAU,YACpCiB,WAAYjB,gBAAgB,SAAU,eAE1CkB,SAAU,CACNC,SAAU,eACVC,QAAS,cACTC,KAAM,aACNC,mBAAoB,wBACpBC,oBAAqB,yBACrBC,YAAa,eACbC,WAAY"}
\ No newline at end of file
diff --git a/contentbank/amd/build/sort.min.js b/contentbank/amd/build/sort.min.js
index 6a84c9b320b..1c17f64ebb7 100644
--- a/contentbank/amd/build/sort.min.js
+++ b/contentbank/amd/build/sort.min.js
@@ -1,2 +1,10 @@
-define ("core_contentbank/sort",["exports","./selectors","core/str","core/prefetch","core/ajax","core/notification"],function(a,b,c,d,e,f){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=g(b);d=g(d);e=g(e);f=g(f);function g(a){return a&&a.__esModule?a:{default:a}}var h=function(){var a=document.querySelector(b.default.regions.contentbank);d.default.prefetchStrings("contentbank",["contentname","uses","lastmodified","size","type","author"]);d.default.prefetchStrings("moodle",["sortbyx","sortbyxreverse"]);i(a)};a.init=h;var i=function(a){a.addEventListener("click",function(c){var d=a.querySelector(b.default.actions.viewlist),e=a.querySelector(b.default.actions.viewgrid),f=a.querySelector(b.default.regions.filearea),g=f.querySelectorAll(b.default.elements.listitem);if(c.target.closest(b.default.actions.viewgrid)){a.classList.remove("view-list");a.classList.add("view-grid");if(f&&g){f.setAttribute("role","list");g.forEach(function(a){a.setAttribute("role","listitem");a.querySelectorAll(b.default.elements.cell).forEach(function(a){return a.removeAttribute("role")})});var h=f.querySelector(b.default.elements.heading);h.removeAttribute("role");h.querySelectorAll(b.default.elements.cell).forEach(function(a){return a.removeAttribute("role")})}e.classList.add("active");d.classList.remove("active");j(!1);return}if(c.target.closest(b.default.actions.viewlist)){a.classList.remove("view-grid");a.classList.add("view-list");if(f&&g){f.setAttribute("role","table");g.forEach(function(a){a.setAttribute("role","row");a.querySelectorAll(b.default.elements.cell).forEach(function(a){return a.setAttribute("role","cell")})});var i=f.querySelector(b.default.elements.heading);i.setAttribute("role","row");i.querySelectorAll(b.default.elements.cell).forEach(function(a){return a.setAttribute("role","columnheader")})}d.classList.add("active");e.classList.remove("active");j(!0);return}if(f&&g){var l=c.target.closest(b.default.actions.sortname);if(l){var n=k(a,l);m(f,g,"data-file",n);return}var o=c.target.closest(b.default.actions.sortuses);if(o){var p=k(a,o);m(f,g,"data-uses",p);return}var q=c.target.closest(b.default.actions.sortdate);if(q){var r=k(a,q);m(f,g,"data-timemodified",r);return}var s=c.target.closest(b.default.actions.sortsize);if(s){var t=k(a,s);m(f,g,"data-bytes",t);return}var u=c.target.closest(b.default.actions.sorttype);if(u){var v=k(a,u);m(f,g,"data-type",v);return}var w=c.target.closest(b.default.actions.sortauthor);if(w){var x=k(a,w);m(f,g,"data-author",x)}}})},j=function(a){if(!1===a){a=null}var b={methodname:"core_user_update_user_preferences",args:{preferences:[{type:"core_contentbank_view_list",value:a}]}};return e.default.call([b])[0].catch(f.default.exception)},k=function(a,c){var d=a.querySelectorAll(b.default.elements.sortbutton);d.forEach(function(a){if(a!==c){a.classList.remove("dir-asc");a.classList.remove("dir-desc");a.classList.add("dir-none");a.closest(b.default.elements.cell).setAttribute("aria-sort","none");l(a,!1)}});var e=!0;if(c.classList.contains("dir-none")){c.classList.remove("dir-none");c.classList.add("dir-asc");c.closest(b.default.elements.cell).setAttribute("aria-sort","ascending")}else if(c.classList.contains("dir-asc")){c.classList.remove("dir-asc");c.classList.add("dir-desc");c.closest(b.default.elements.cell).setAttribute("aria-sort","descending");e=!1}else if(c.classList.contains("dir-desc")){c.classList.remove("dir-desc");c.classList.add("dir-asc");c.closest(b.default.elements.cell).setAttribute("aria-sort","ascending")}l(c,e);return e},l=function(a,b){var d=b?"sortbyxreverse":"sortbyx";return(0,c.get_string)(a.dataset.string,"contentbank").then(function(a){return(0,c.get_string)(d,"core",a)}).then(function(b){a.setAttribute("title",b);return b}).catch()},m=function(a,b,c,d){var e=[].slice.call(b).sort(function(e,a){var b=e.getAttribute(c),f=a.getAttribute(c);if(!isNaN(b)){b=parseInt(b);f=parseInt(f)}if(d){return b>f?1:-1}else{return b
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_selectors=_interopRequireDefault(_selectors),_prefetch=_interopRequireDefault(_prefetch),_ajax=_interopRequireDefault(_ajax),_notification=_interopRequireDefault(_notification);_exports.init=()=>{const contentBank=document.querySelector(_selectors.default.regions.contentbank);_prefetch.default.prefetchStrings("contentbank",["contentname","uses","lastmodified","size","type","author"]),_prefetch.default.prefetchStrings("moodle",["sortbyx","sortbyxreverse"]),registerListenerEvents(contentBank)};const registerListenerEvents=contentBank=>{contentBank.addEventListener("click",(e=>{const viewList=contentBank.querySelector(_selectors.default.actions.viewlist),viewGrid=contentBank.querySelector(_selectors.default.actions.viewgrid),fileArea=contentBank.querySelector(_selectors.default.regions.filearea),shownItems=fileArea.querySelectorAll(_selectors.default.elements.listitem);if(e.target.closest(_selectors.default.actions.viewgrid)){if(contentBank.classList.remove("view-list"),contentBank.classList.add("view-grid"),fileArea&&shownItems){fileArea.setAttribute("role","list"),shownItems.forEach((listItem=>{listItem.setAttribute("role","listitem"),listItem.querySelectorAll(_selectors.default.elements.cell).forEach((cell=>cell.removeAttribute("role")))}));const heading=fileArea.querySelector(_selectors.default.elements.heading);heading.removeAttribute("role"),heading.querySelectorAll(_selectors.default.elements.cell).forEach((cell=>cell.removeAttribute("role")))}return viewGrid.classList.add("active"),viewList.classList.remove("active"),void setViewListPreference(!1)}if(e.target.closest(_selectors.default.actions.viewlist)){if(contentBank.classList.remove("view-grid"),contentBank.classList.add("view-list"),fileArea&&shownItems){fileArea.setAttribute("role","table"),shownItems.forEach((listItem=>{listItem.setAttribute("role","row"),listItem.querySelectorAll(_selectors.default.elements.cell).forEach((cell=>cell.setAttribute("role","cell")))}));const heading=fileArea.querySelector(_selectors.default.elements.heading);heading.setAttribute("role","row"),heading.querySelectorAll(_selectors.default.elements.cell).forEach((cell=>cell.setAttribute("role","columnheader")))}return viewList.classList.add("active"),viewGrid.classList.remove("active"),void setViewListPreference(!0)}if(fileArea&&shownItems){const sortByName=e.target.closest(_selectors.default.actions.sortname);if(sortByName){const ascending=updateSortButtons(contentBank,sortByName);return void updateSortOrder(fileArea,shownItems,"data-file",ascending)}const sortByUses=e.target.closest(_selectors.default.actions.sortuses);if(sortByUses){const ascending=updateSortButtons(contentBank,sortByUses);return void updateSortOrder(fileArea,shownItems,"data-uses",ascending)}const sortByDate=e.target.closest(_selectors.default.actions.sortdate);if(sortByDate){const ascending=updateSortButtons(contentBank,sortByDate);return void updateSortOrder(fileArea,shownItems,"data-timemodified",ascending)}const sortBySize=e.target.closest(_selectors.default.actions.sortsize);if(sortBySize){const ascending=updateSortButtons(contentBank,sortBySize);return void updateSortOrder(fileArea,shownItems,"data-bytes",ascending)}const sortByType=e.target.closest(_selectors.default.actions.sorttype);if(sortByType){const ascending=updateSortButtons(contentBank,sortByType);return void updateSortOrder(fileArea,shownItems,"data-type",ascending)}const sortByAuthor=e.target.closest(_selectors.default.actions.sortauthor);if(sortByAuthor){const ascending=updateSortButtons(contentBank,sortByAuthor);updateSortOrder(fileArea,shownItems,"data-author",ascending)}}else;}))},setViewListPreference=function(viewList){!1===viewList&&(viewList=null);const request={methodname:"core_user_update_user_preferences",args:{preferences:[{type:"core_contentbank_view_list",value:viewList}]}};return _ajax.default.call([request])[0].catch(_notification.default.exception)},updateSortButtons=(contentBank,sortButton)=>{contentBank.querySelectorAll(_selectors.default.elements.sortbutton).forEach((button=>{button!==sortButton&&(button.classList.remove("dir-asc"),button.classList.remove("dir-desc"),button.classList.add("dir-none"),button.closest(_selectors.default.elements.cell).setAttribute("aria-sort","none"),updateButtonTitle(button,!1))}));let ascending=!0;return sortButton.classList.contains("dir-none")?(sortButton.classList.remove("dir-none"),sortButton.classList.add("dir-asc"),sortButton.closest(_selectors.default.elements.cell).setAttribute("aria-sort","ascending")):sortButton.classList.contains("dir-asc")?(sortButton.classList.remove("dir-asc"),sortButton.classList.add("dir-desc"),sortButton.closest(_selectors.default.elements.cell).setAttribute("aria-sort","descending"),ascending=!1):sortButton.classList.contains("dir-desc")&&(sortButton.classList.remove("dir-desc"),sortButton.classList.add("dir-asc"),sortButton.closest(_selectors.default.elements.cell).setAttribute("aria-sort","ascending")),updateButtonTitle(sortButton,ascending),ascending},updateButtonTitle=(button,ascending)=>{const sortString=ascending?"sortbyxreverse":"sortbyx";return(0,_str.get_string)(button.dataset.string,"contentbank").then((columnName=>(0,_str.get_string)(sortString,"core",columnName))).then((sortByString=>(button.setAttribute("title",sortByString),sortByString))).catch()},updateSortOrder=(fileArea,itemList,attribute,ascending)=>{[].slice.call(itemList).sort((function(a,b){let aa=a.getAttribute(attribute),bb=b.getAttribute(attribute);return isNaN(aa)||(aa=parseInt(aa),bb=parseInt(bb)),ascending?aa>bb?1:-1:aafileArea.appendChild(listItem)))}}));
+
+//# sourceMappingURL=sort.min.js.map
\ No newline at end of file
diff --git a/contentbank/amd/build/sort.min.js.map b/contentbank/amd/build/sort.min.js.map
index d0e992b7860..2bd1546a85b 100644
--- a/contentbank/amd/build/sort.min.js.map
+++ b/contentbank/amd/build/sort.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/sort.js"],"names":["init","contentBank","document","querySelector","selectors","regions","contentbank","Prefetch","prefetchStrings","registerListenerEvents","addEventListener","e","viewList","actions","viewlist","viewGrid","viewgrid","fileArea","filearea","shownItems","querySelectorAll","elements","listitem","target","closest","classList","remove","add","setAttribute","forEach","listItem","cell","removeAttribute","heading","setViewListPreference","sortByName","sortname","ascending","updateSortButtons","updateSortOrder","sortByUses","sortuses","sortByDate","sortdate","sortBySize","sortsize","sortByType","sorttype","sortByAuthor","sortauthor","request","methodname","args","preferences","type","value","Ajax","call","catch","Notification","exception","sortButton","sortButtons","sortbutton","button","updateButtonTitle","contains","sortString","dataset","string","then","columnName","sortByString","itemList","attribute","sortList","slice","sort","a","b","aa","getAttribute","bb","isNaN","parseInt","appendChild"],"mappings":"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","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 .\n\n/**\n * Content bank UI actions.\n *\n * @module core_contentbank/sort\n * @copyright 2020 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport selectors from './selectors';\nimport {get_string as getString} from 'core/str';\nimport Prefetch from 'core/prefetch';\nimport Ajax from 'core/ajax';\nimport Notification from 'core/notification';\n\n/**\n * Set up the contentbank views.\n *\n * @method init\n */\nexport const init = () => {\n const contentBank = document.querySelector(selectors.regions.contentbank);\n Prefetch.prefetchStrings('contentbank', ['contentname', 'uses', 'lastmodified', 'size', 'type', 'author']);\n Prefetch.prefetchStrings('moodle', ['sortbyx', 'sortbyxreverse']);\n registerListenerEvents(contentBank);\n};\n\n/**\n * Register contentbank related event listeners.\n *\n * @method registerListenerEvents\n * @param {HTMLElement} contentBank The DOM node of the content bank\n */\nconst registerListenerEvents = (contentBank) => {\n\n contentBank.addEventListener('click', e => {\n const viewList = contentBank.querySelector(selectors.actions.viewlist);\n const viewGrid = contentBank.querySelector(selectors.actions.viewgrid);\n const fileArea = contentBank.querySelector(selectors.regions.filearea);\n const shownItems = fileArea.querySelectorAll(selectors.elements.listitem);\n\n // View as Grid button.\n if (e.target.closest(selectors.actions.viewgrid)) {\n contentBank.classList.remove('view-list');\n contentBank.classList.add('view-grid');\n if (fileArea && shownItems) {\n fileArea.setAttribute('role', 'list');\n shownItems.forEach(listItem => {\n listItem.setAttribute('role', 'listitem');\n listItem.querySelectorAll(selectors.elements.cell).forEach(cell => cell.removeAttribute('role'));\n });\n\n const heading = fileArea.querySelector(selectors.elements.heading);\n heading.removeAttribute('role');\n heading.querySelectorAll(selectors.elements.cell).forEach(cell => cell.removeAttribute('role'));\n }\n viewGrid.classList.add('active');\n viewList.classList.remove('active');\n setViewListPreference(false);\n\n return;\n }\n\n // View as List button.\n if (e.target.closest(selectors.actions.viewlist)) {\n contentBank.classList.remove('view-grid');\n contentBank.classList.add('view-list');\n if (fileArea && shownItems) {\n fileArea.setAttribute('role', 'table');\n shownItems.forEach(listItem => {\n listItem.setAttribute('role', 'row');\n listItem.querySelectorAll(selectors.elements.cell).forEach(cell => cell.setAttribute('role', 'cell'));\n });\n\n const heading = fileArea.querySelector(selectors.elements.heading);\n heading.setAttribute('role', 'row');\n heading.querySelectorAll(selectors.elements.cell).forEach(cell => cell.setAttribute('role', 'columnheader'));\n }\n viewList.classList.add('active');\n viewGrid.classList.remove('active');\n setViewListPreference(true);\n\n return;\n }\n\n if (fileArea && shownItems) {\n\n // Sort by file name alphabetical\n const sortByName = e.target.closest(selectors.actions.sortname);\n if (sortByName) {\n const ascending = updateSortButtons(contentBank, sortByName);\n updateSortOrder(fileArea, shownItems, 'data-file', ascending);\n return;\n }\n\n // Sort by uses.\n const sortByUses = e.target.closest(selectors.actions.sortuses);\n if (sortByUses) {\n const ascending = updateSortButtons(contentBank, sortByUses);\n updateSortOrder(fileArea, shownItems, 'data-uses', ascending);\n return;\n }\n\n // Sort by date.\n const sortByDate = e.target.closest(selectors.actions.sortdate);\n if (sortByDate) {\n const ascending = updateSortButtons(contentBank, sortByDate);\n updateSortOrder(fileArea, shownItems, 'data-timemodified', ascending);\n return;\n }\n\n // Sort by size.\n const sortBySize = e.target.closest(selectors.actions.sortsize);\n if (sortBySize) {\n const ascending = updateSortButtons(contentBank, sortBySize);\n updateSortOrder(fileArea, shownItems, 'data-bytes', ascending);\n return;\n }\n\n // Sort by type.\n const sortByType = e.target.closest(selectors.actions.sorttype);\n if (sortByType) {\n const ascending = updateSortButtons(contentBank, sortByType);\n updateSortOrder(fileArea, shownItems, 'data-type', ascending);\n return;\n }\n\n // Sort by author.\n const sortByAuthor = e.target.closest(selectors.actions.sortauthor);\n if (sortByAuthor) {\n const ascending = updateSortButtons(contentBank, sortByAuthor);\n updateSortOrder(fileArea, shownItems, 'data-author', ascending);\n }\n return;\n }\n });\n};\n\n\n/**\n * Set the contentbank user preference in list view\n *\n * @param {Bool} viewList view ContentBank as list.\n * @return {Promise} Repository promise.\n */\nconst setViewListPreference = function(viewList) {\n\n // If the given status is not hidden, the preference has to be deleted with a null value.\n if (viewList === false) {\n viewList = null;\n }\n\n const request = {\n methodname: 'core_user_update_user_preferences',\n args: {\n preferences: [\n {\n type: 'core_contentbank_view_list',\n value: viewList\n }\n ]\n }\n };\n\n return Ajax.call([request])[0].catch(Notification.exception);\n};\n\n/**\n * Update the sort button view.\n *\n * @method updateSortButtons\n * @param {HTMLElement} contentBank The DOM node of the contentbank button\n * @param {HTMLElement} sortButton The DOM node of the sort button\n * @return {Bool} sort ascending\n */\nconst updateSortButtons = (contentBank, sortButton) => {\n const sortButtons = contentBank.querySelectorAll(selectors.elements.sortbutton);\n\n sortButtons.forEach((button) => {\n if (button !== sortButton) {\n button.classList.remove('dir-asc');\n button.classList.remove('dir-desc');\n button.classList.add('dir-none');\n\n button.closest(selectors.elements.cell).setAttribute('aria-sort', 'none');\n\n updateButtonTitle(button, false);\n }\n });\n\n let ascending = true;\n\n if (sortButton.classList.contains('dir-none')) {\n sortButton.classList.remove('dir-none');\n sortButton.classList.add('dir-asc');\n sortButton.closest(selectors.elements.cell).setAttribute('aria-sort', 'ascending');\n } else if (sortButton.classList.contains('dir-asc')) {\n sortButton.classList.remove('dir-asc');\n sortButton.classList.add('dir-desc');\n sortButton.closest(selectors.elements.cell).setAttribute('aria-sort', 'descending');\n ascending = false;\n } else if (sortButton.classList.contains('dir-desc')) {\n sortButton.classList.remove('dir-desc');\n sortButton.classList.add('dir-asc');\n sortButton.closest(selectors.elements.cell).setAttribute('aria-sort', 'ascending');\n }\n\n updateButtonTitle(sortButton, ascending);\n\n return ascending;\n};\n\n/**\n * Update the button title.\n *\n * @method updateButtonTitle\n * @param {HTMLElement} button Button to update\n * @param {Bool} ascending Sort direction\n * @return {Promise} string promise\n */\nconst updateButtonTitle = (button, ascending) => {\n\n const sortString = (ascending ? 'sortbyxreverse' : 'sortbyx');\n\n return getString(button.dataset.string, 'contentbank')\n .then(columnName => {\n return getString(sortString, 'core', columnName);\n })\n .then(sortByString => {\n button.setAttribute('title', sortByString);\n return sortByString;\n })\n .catch();\n};\n\n/**\n * Update the sort order of the itemlist and update the DOM\n *\n * @method updateSortOrder\n * @param {HTMLElement} fileArea the Dom container for the itemlist\n * @param {Array} itemList Nodelist of Dom elements\n * @param {String} attribute the attribut to sort on\n * @param {Bool} ascending Sort Ascending\n */\nconst updateSortOrder = (fileArea, itemList, attribute, ascending) => {\n const sortList = [].slice.call(itemList).sort(function(a, b) {\n\n let aa = a.getAttribute(attribute);\n let bb = b.getAttribute(attribute);\n if (!isNaN(aa)) {\n aa = parseInt(aa);\n bb = parseInt(bb);\n }\n\n if (ascending) {\n return aa > bb ? 1 : -1;\n } else {\n return aa < bb ? 1 : -1;\n }\n });\n sortList.forEach(listItem => fileArea.appendChild(listItem));\n};\n"],"file":"sort.min.js"}
\ No newline at end of file
+{"version":3,"file":"sort.min.js","sources":["../src/sort.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 .\n\n/**\n * Content bank UI actions.\n *\n * @module core_contentbank/sort\n * @copyright 2020 Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport selectors from './selectors';\nimport {get_string as getString} from 'core/str';\nimport Prefetch from 'core/prefetch';\nimport Ajax from 'core/ajax';\nimport Notification from 'core/notification';\n\n/**\n * Set up the contentbank views.\n *\n * @method init\n */\nexport const init = () => {\n const contentBank = document.querySelector(selectors.regions.contentbank);\n Prefetch.prefetchStrings('contentbank', ['contentname', 'uses', 'lastmodified', 'size', 'type', 'author']);\n Prefetch.prefetchStrings('moodle', ['sortbyx', 'sortbyxreverse']);\n registerListenerEvents(contentBank);\n};\n\n/**\n * Register contentbank related event listeners.\n *\n * @method registerListenerEvents\n * @param {HTMLElement} contentBank The DOM node of the content bank\n */\nconst registerListenerEvents = (contentBank) => {\n\n contentBank.addEventListener('click', e => {\n const viewList = contentBank.querySelector(selectors.actions.viewlist);\n const viewGrid = contentBank.querySelector(selectors.actions.viewgrid);\n const fileArea = contentBank.querySelector(selectors.regions.filearea);\n const shownItems = fileArea.querySelectorAll(selectors.elements.listitem);\n\n // View as Grid button.\n if (e.target.closest(selectors.actions.viewgrid)) {\n contentBank.classList.remove('view-list');\n contentBank.classList.add('view-grid');\n if (fileArea && shownItems) {\n fileArea.setAttribute('role', 'list');\n shownItems.forEach(listItem => {\n listItem.setAttribute('role', 'listitem');\n listItem.querySelectorAll(selectors.elements.cell).forEach(cell => cell.removeAttribute('role'));\n });\n\n const heading = fileArea.querySelector(selectors.elements.heading);\n heading.removeAttribute('role');\n heading.querySelectorAll(selectors.elements.cell).forEach(cell => cell.removeAttribute('role'));\n }\n viewGrid.classList.add('active');\n viewList.classList.remove('active');\n setViewListPreference(false);\n\n return;\n }\n\n // View as List button.\n if (e.target.closest(selectors.actions.viewlist)) {\n contentBank.classList.remove('view-grid');\n contentBank.classList.add('view-list');\n if (fileArea && shownItems) {\n fileArea.setAttribute('role', 'table');\n shownItems.forEach(listItem => {\n listItem.setAttribute('role', 'row');\n listItem.querySelectorAll(selectors.elements.cell).forEach(cell => cell.setAttribute('role', 'cell'));\n });\n\n const heading = fileArea.querySelector(selectors.elements.heading);\n heading.setAttribute('role', 'row');\n heading.querySelectorAll(selectors.elements.cell).forEach(cell => cell.setAttribute('role', 'columnheader'));\n }\n viewList.classList.add('active');\n viewGrid.classList.remove('active');\n setViewListPreference(true);\n\n return;\n }\n\n if (fileArea && shownItems) {\n\n // Sort by file name alphabetical\n const sortByName = e.target.closest(selectors.actions.sortname);\n if (sortByName) {\n const ascending = updateSortButtons(contentBank, sortByName);\n updateSortOrder(fileArea, shownItems, 'data-file', ascending);\n return;\n }\n\n // Sort by uses.\n const sortByUses = e.target.closest(selectors.actions.sortuses);\n if (sortByUses) {\n const ascending = updateSortButtons(contentBank, sortByUses);\n updateSortOrder(fileArea, shownItems, 'data-uses', ascending);\n return;\n }\n\n // Sort by date.\n const sortByDate = e.target.closest(selectors.actions.sortdate);\n if (sortByDate) {\n const ascending = updateSortButtons(contentBank, sortByDate);\n updateSortOrder(fileArea, shownItems, 'data-timemodified', ascending);\n return;\n }\n\n // Sort by size.\n const sortBySize = e.target.closest(selectors.actions.sortsize);\n if (sortBySize) {\n const ascending = updateSortButtons(contentBank, sortBySize);\n updateSortOrder(fileArea, shownItems, 'data-bytes', ascending);\n return;\n }\n\n // Sort by type.\n const sortByType = e.target.closest(selectors.actions.sorttype);\n if (sortByType) {\n const ascending = updateSortButtons(contentBank, sortByType);\n updateSortOrder(fileArea, shownItems, 'data-type', ascending);\n return;\n }\n\n // Sort by author.\n const sortByAuthor = e.target.closest(selectors.actions.sortauthor);\n if (sortByAuthor) {\n const ascending = updateSortButtons(contentBank, sortByAuthor);\n updateSortOrder(fileArea, shownItems, 'data-author', ascending);\n }\n return;\n }\n });\n};\n\n\n/**\n * Set the contentbank user preference in list view\n *\n * @param {Bool} viewList view ContentBank as list.\n * @return {Promise} Repository promise.\n */\nconst setViewListPreference = function(viewList) {\n\n // If the given status is not hidden, the preference has to be deleted with a null value.\n if (viewList === false) {\n viewList = null;\n }\n\n const request = {\n methodname: 'core_user_update_user_preferences',\n args: {\n preferences: [\n {\n type: 'core_contentbank_view_list',\n value: viewList\n }\n ]\n }\n };\n\n return Ajax.call([request])[0].catch(Notification.exception);\n};\n\n/**\n * Update the sort button view.\n *\n * @method updateSortButtons\n * @param {HTMLElement} contentBank The DOM node of the contentbank button\n * @param {HTMLElement} sortButton The DOM node of the sort button\n * @return {Bool} sort ascending\n */\nconst updateSortButtons = (contentBank, sortButton) => {\n const sortButtons = contentBank.querySelectorAll(selectors.elements.sortbutton);\n\n sortButtons.forEach((button) => {\n if (button !== sortButton) {\n button.classList.remove('dir-asc');\n button.classList.remove('dir-desc');\n button.classList.add('dir-none');\n\n button.closest(selectors.elements.cell).setAttribute('aria-sort', 'none');\n\n updateButtonTitle(button, false);\n }\n });\n\n let ascending = true;\n\n if (sortButton.classList.contains('dir-none')) {\n sortButton.classList.remove('dir-none');\n sortButton.classList.add('dir-asc');\n sortButton.closest(selectors.elements.cell).setAttribute('aria-sort', 'ascending');\n } else if (sortButton.classList.contains('dir-asc')) {\n sortButton.classList.remove('dir-asc');\n sortButton.classList.add('dir-desc');\n sortButton.closest(selectors.elements.cell).setAttribute('aria-sort', 'descending');\n ascending = false;\n } else if (sortButton.classList.contains('dir-desc')) {\n sortButton.classList.remove('dir-desc');\n sortButton.classList.add('dir-asc');\n sortButton.closest(selectors.elements.cell).setAttribute('aria-sort', 'ascending');\n }\n\n updateButtonTitle(sortButton, ascending);\n\n return ascending;\n};\n\n/**\n * Update the button title.\n *\n * @method updateButtonTitle\n * @param {HTMLElement} button Button to update\n * @param {Bool} ascending Sort direction\n * @return {Promise} string promise\n */\nconst updateButtonTitle = (button, ascending) => {\n\n const sortString = (ascending ? 'sortbyxreverse' : 'sortbyx');\n\n return getString(button.dataset.string, 'contentbank')\n .then(columnName => {\n return getString(sortString, 'core', columnName);\n })\n .then(sortByString => {\n button.setAttribute('title', sortByString);\n return sortByString;\n })\n .catch();\n};\n\n/**\n * Update the sort order of the itemlist and update the DOM\n *\n * @method updateSortOrder\n * @param {HTMLElement} fileArea the Dom container for the itemlist\n * @param {Array} itemList Nodelist of Dom elements\n * @param {String} attribute the attribut to sort on\n * @param {Bool} ascending Sort Ascending\n */\nconst updateSortOrder = (fileArea, itemList, attribute, ascending) => {\n const sortList = [].slice.call(itemList).sort(function(a, b) {\n\n let aa = a.getAttribute(attribute);\n let bb = b.getAttribute(attribute);\n if (!isNaN(aa)) {\n aa = parseInt(aa);\n bb = parseInt(bb);\n }\n\n if (ascending) {\n return aa > bb ? 1 : -1;\n } else {\n return aa < bb ? 1 : -1;\n }\n });\n sortList.forEach(listItem => fileArea.appendChild(listItem));\n};\n"],"names":["contentBank","document","querySelector","selectors","regions","contentbank","prefetchStrings","registerListenerEvents","addEventListener","e","viewList","actions","viewlist","viewGrid","viewgrid","fileArea","filearea","shownItems","querySelectorAll","elements","listitem","target","closest","classList","remove","add","setAttribute","forEach","listItem","cell","removeAttribute","heading","setViewListPreference","sortByName","sortname","ascending","updateSortButtons","updateSortOrder","sortByUses","sortuses","sortByDate","sortdate","sortBySize","sortsize","sortByType","sorttype","sortByAuthor","sortauthor","request","methodname","args","preferences","type","value","Ajax","call","catch","Notification","exception","sortButton","sortbutton","button","updateButtonTitle","contains","sortString","dataset","string","then","columnName","sortByString","itemList","attribute","slice","sort","a","b","aa","getAttribute","bb","isNaN","parseInt","appendChild"],"mappings":"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"}
\ No newline at end of file
diff --git a/contentbank/amd/build/upload.min.js b/contentbank/amd/build/upload.min.js
index 9df927d217c..7183b10dda7 100644
--- a/contentbank/amd/build/upload.min.js
+++ b/contentbank/amd/build/upload.min.js
@@ -1,2 +1,10 @@
-define ("core_contentbank/upload",["exports","core_form/modalform","core/str"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.initModal=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);a.initModal=function initModal(a,d,f,g){var h=document.querySelector(a);h.addEventListener("click",function(a){a.preventDefault();var e=new b.default({formClass:d,args:{contextid:f,id:g},modalConfig:{title:(0,c.get_string)("upload","contentbank")},returnFocus:a.target});e.addEventListener(e.events.FORM_SUBMITTED,function(a){document.location=a.detail.returnurl});e.show()})}});
-//# sourceMappingURL=upload.min.js.map
+define("core_contentbank/upload",["exports","core_form/modalform","core/str"],(function(_exports,_modalform,_str){var obj;
+/**
+ * Module to handle AJAX interactions with content bank upload files.
+ *
+ * @module core_contentbank/upload
+ * @copyright 2021 Sara Arjona
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.initModal=void 0,_modalform=(obj=_modalform)&&obj.__esModule?obj:{default:obj};_exports.initModal=(elementSelector,formClass,contextId,contentId)=>{document.querySelector(elementSelector).addEventListener("click",(function(e){e.preventDefault();const form=new _modalform.default({formClass:formClass,args:{contextid:contextId,id:contentId},modalConfig:{title:(0,_str.get_string)("upload","contentbank")},returnFocus:e.target});form.addEventListener(form.events.FORM_SUBMITTED,(event=>{document.location=event.detail.returnurl})),form.show()}))}}));
+
+//# sourceMappingURL=upload.min.js.map
\ No newline at end of file
diff --git a/contentbank/amd/build/upload.min.js.map b/contentbank/amd/build/upload.min.js.map
index c14d2d706d4..6d9dd313580 100644
--- a/contentbank/amd/build/upload.min.js.map
+++ b/contentbank/amd/build/upload.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/upload.js"],"names":["initModal","elementSelector","formClass","contextId","contentId","element","document","querySelector","addEventListener","e","preventDefault","form","ModalForm","args","contextid","id","modalConfig","title","returnFocus","target","events","FORM_SUBMITTED","event","location","detail","returnurl","show"],"mappings":"gLAsBA,uD,YAWyB,QAAZA,CAAAA,SAAY,CAACC,CAAD,CAAkBC,CAAlB,CAA6BC,CAA7B,CAAwCC,CAAxC,CAAsD,CAC3E,GAAMC,CAAAA,CAAO,CAAGC,QAAQ,CAACC,aAAT,CAAuBN,CAAvB,CAAhB,CACAI,CAAO,CAACG,gBAAR,CAAyB,OAAzB,CAAkC,SAASC,CAAT,CAAY,CAC1CA,CAAC,CAACC,cAAF,GACA,GAAMC,CAAAA,CAAI,CAAG,GAAIC,UAAJ,CAAc,CACvBV,SAAS,CAATA,CADuB,CAEvBW,IAAI,CAAE,CACFC,SAAS,CAAEX,CADT,CAEFY,EAAE,CAAEX,CAFF,CAFiB,CAMvBY,WAAW,CAAE,CAACC,KAAK,CAAE,iBAAU,QAAV,CAAoB,aAApB,CAAR,CANU,CAOvBC,WAAW,CAAET,CAAC,CAACU,MAPQ,CAAd,CAAb,CASAR,CAAI,CAACH,gBAAL,CAAsBG,CAAI,CAACS,MAAL,CAAYC,cAAlC,CAAkD,SAACC,CAAD,CAAW,CACzDhB,QAAQ,CAACiB,QAAT,CAAoBD,CAAK,CAACE,MAAN,CAAaC,SACpC,CAFD,EAGAd,CAAI,CAACe,IAAL,EACH,CAfD,CAgBH,C","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 .\n\n/**\n * Module to handle AJAX interactions with content bank upload files.\n *\n * @module core_contentbank/upload\n * @copyright 2021 Sara Arjona \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport ModalForm from 'core_form/modalform';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Initialize upload files to the content bank form as Modal form.\n *\n * @param {String} elementSelector\n * @param {String} formClass\n * @param {Integer} contextId\n * @param {Integer} contentId\n */\nexport const initModal = (elementSelector, formClass, contextId, contentId) => {\n const element = document.querySelector(elementSelector);\n element.addEventListener('click', function(e) {\n e.preventDefault();\n const form = new ModalForm({\n formClass,\n args: {\n contextid: contextId,\n id: contentId,\n },\n modalConfig: {title: getString('upload', 'contentbank')},\n returnFocus: e.target,\n });\n form.addEventListener(form.events.FORM_SUBMITTED, (event) => {\n document.location = event.detail.returnurl;\n });\n form.show();\n });\n};\n"],"file":"upload.min.js"}
\ No newline at end of file
+{"version":3,"file":"upload.min.js","sources":["../src/upload.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 .\n\n/**\n * Module to handle AJAX interactions with content bank upload files.\n *\n * @module core_contentbank/upload\n * @copyright 2021 Sara Arjona \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport ModalForm from 'core_form/modalform';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Initialize upload files to the content bank form as Modal form.\n *\n * @param {String} elementSelector\n * @param {String} formClass\n * @param {Integer} contextId\n * @param {Integer} contentId\n */\nexport const initModal = (elementSelector, formClass, contextId, contentId) => {\n const element = document.querySelector(elementSelector);\n element.addEventListener('click', function(e) {\n e.preventDefault();\n const form = new ModalForm({\n formClass,\n args: {\n contextid: contextId,\n id: contentId,\n },\n modalConfig: {title: getString('upload', 'contentbank')},\n returnFocus: e.target,\n });\n form.addEventListener(form.events.FORM_SUBMITTED, (event) => {\n document.location = event.detail.returnurl;\n });\n form.show();\n });\n};\n"],"names":["elementSelector","formClass","contextId","contentId","document","querySelector","addEventListener","e","preventDefault","form","ModalForm","args","contextid","id","modalConfig","title","returnFocus","target","events","FORM_SUBMITTED","event","location","detail","returnurl","show"],"mappings":";;;;;;;wKAiCyB,CAACA,gBAAiBC,UAAWC,UAAWC,aAC7CC,SAASC,cAAcL,iBAC/BM,iBAAiB,SAAS,SAASC,GACvCA,EAAEC,uBACIC,KAAO,IAAIC,mBAAU,CACvBT,UAAAA,UACAU,KAAM,CACFC,UAAWV,UACXW,GAAIV,WAERW,YAAa,CAACC,OAAO,mBAAU,SAAU,gBACzCC,YAAaT,EAAEU,SAEnBR,KAAKH,iBAAiBG,KAAKS,OAAOC,gBAAiBC,QAC/ChB,SAASiB,SAAWD,MAAME,OAAOC,aAErCd,KAAKe"}
\ No newline at end of file
diff --git a/course/amd/build/actions.min.js b/course/amd/build/actions.min.js
index b8206bb69df..fce3583c2d3 100644
--- a/course/amd/build/actions.min.js
+++ b/course/amd/build/actions.min.js
@@ -1,2 +1,11 @@
-function _defineProperty(a,b,c){if(b in a){Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0})}else{a[b]=c}return a}define ("core_course/actions",["jquery","core/ajax","core/templates","core/notification","core/str","core/url","core/yui","core/modal_factory","core/modal_events","core/key_codes","core/log","core_courseformat/courseeditor","core/event_dispatcher","core_course/events"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n){var o=["moveSection","moveCm","addSection","deleteSection"],p=l.getCurrentCourseEditor(),q,r={EDITINPROGRESS:"editinprogress",SECTIONDRAGGABLE:"sectiondraggable",EDITINGMOVE:"editing_move"},s={ACTIVITYLI:"li.activity",ACTIONAREA:".actions",ACTIVITYACTION:"a.cm-edit-action",MENU:".moodle-actionmenu[data-enhance=moodle-core-actionmenu]",TOGGLE:".toggle-display,.dropdown-toggle",SECTIONLI:"li.section",SECTIONACTIONMENU:".section_action_menu",ADDSECTIONS:".changenumsections [data-add-sections]",SECTIONBADGES:"[data-region=\"sectionbadges\"]"};g.use("moodle-course-coursebase",function(){var a=M.course.format.get_section_selector();if(a){s.SECTIONLI=a}});var t=function(a,b,c,d){if(!(c instanceof Element)&&c.get!==void 0){c=c.get(0)}return m.dispatchEvent(a,b,c,d)},u=function(a){var b=a.get(0);if(b.dataset.id){return b.dataset.id}var c;g.use("moodle-course-util",function(a){c=a.Moodle.core_course.util.cm.getId(a.Node(b))});return c},v=function(a){var b;g.use("moodle-course-util",function(c){b=c.Moodle.core_course.util.cm.getName(c.Node(a.get(0)))});var c=p.state,d=u(a);if(!b&&c&&d){var e;b=null===(e=c.cm.get(d))||void 0===e?void 0:e.name}return b},w=function(a){a.addClass(r.EDITINPROGRESS);var b=a.find(s.ACTIONAREA).get(0);if(b){var c=M.util.add_spinner(g,g.Node(b));c.show();if(a.data("id")!==void 0){p.dispatch("cmLock",[a.data("id")],!0)}return c}return null},x=function(a){a.addClass(r.EDITINPROGRESS);var b=a.find(s.SECTIONACTIONMENU).get(0);if(b){var c=M.util.add_spinner(g,g.Node(b));c.show();if(a.data("id")!==void 0){p.dispatch("sectionLock",[a.data("id")],!0)}return c}return null},y=function(a){var b=a.get(0),c=M.util.add_lightbox(g,g.Node(b));if("section"==b.dataset.for&&b.dataset.id){p.dispatch("sectionLock",[b.dataset.id],!0);c.setAttribute("data-state","section");c.setAttribute("data-state-id",b.dataset.id)}c.show();return c},z=function(a,b,c){window.setTimeout(function(){a.removeClass(r.EDITINPROGRESS);if(b){b.hide()}if(a.data("id")!==void 0){var c="section"===a.data("for")?"sectionLock":"cmLock";p.dispatch(c,[a.data("id")],!1)}},c)},A=function(a,b){if(a){window.setTimeout(function(){a.hide();if(a.getAttribute("data-state")){p.dispatch("".concat(a.getAttribute("data-state"),"Lock"),[a.getAttribute("data-state-id")],!1)}},b)}},B=function(a){g.use("moodle-course-coursebase",function(){M.course.coursebase.invoke_function("setup_for_resource","#"+a)});if(M.core.actionmenu&&M.core.actionmenu.newDOMNode){M.core.actionmenu.newDOMNode(g.one("#"+a))}},C=function(b,c){var d=a("#"+b),e="[data-action="+c+"]";if("groupsseparate"===c||"groupsvisible"===c||"groupsnone"===c){e="[data-action=groupsseparate],[data-action=groupsvisible],[data-action=groupsnone]"}if(d.find(e).is(":visible")){d.find(e).focus()}else{d.find(s.MENU).find(s.TOGGLE).focus()}},D=function(b){var c=a("a:visible"),d=!1,e=null;c.each(function(){if(a.contains(b[0],this)){d=!0}else if(d){e=this;return!1}return!0});return e},E=function(c,e,f){var g=f.attr("data-action"),h=w(c),i=b.call([{methodname:"core_course_edit_module",args:{id:e,action:g,sectionreturn:f.attr("data-sectionreturn")?f.attr("data-sectionreturn"):0}}],!0),j;if("duplicate"===g){j=y(f.closest(s.SECTIONLI))}a.when.apply(a,i).done(function(b){var d=D(c);c.replaceWith(b);var f=[];a("
"+b+"
").find(s.ACTIVITYLI).each(function(b){B(a(this).attr("id"));if(0===b){C(a(this).attr("id"),g);d=null}f.push(u(a(this)))});if(d){d.focus()}z(c,h,400);A(j,400);c.trigger(a.Event("coursemoduleedited",{ajaxreturn:b,action:g}));p.dispatch("legacyActivityAction",g,e,f)}).fail(function(b){z(c,h);A(j);var f=a.Event("coursemoduleeditfailed",{exception:b,action:g});c.trigger(f);if(!f.isDefaultPrevented()){d.exception(b)}})},F=function(c,d,e){if(e===void 0){e=p.sectionReturn}var f=a(c),g=w(f),h=b.call([{methodname:"core_course_get_module",args:{id:d,sectionreturn:e}}],!0);return new Promise(function(b,c){a.when.apply(a,h).done(function(a){z(f,g,400);L(a);b(a)}).fail(function(){z(f,g);c()})})},G=function(a,b){var c=a.attr("class").match(/modtype_([^\s]*)/)[1],f=v(a);e.get_string("pluginname",c).done(function(a){e.get_strings([{key:"confirm",component:"core"},{key:null===f?"deletechecktype":"deletechecktypename",param:{type:a,name:f}},{key:"yes"},{key:"no"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],b)})})},H=function(a,b){e.get_strings([{key:"confirm"},{key:"yes"},{key:"no"}]).done(function(c){d.confirm(c[0],a,c[1],c[2],b)})},I=function(a,b,f,g,h){return e.get_strings([{key:f,component:g}]).then(function(d){a.find("span.menu-action-text").html(d[0]);return c.renderPix(b,"core")}).then(function(b){a.find(".icon").replaceWith(b);a.attr("data-action",h)}).catch(d.exception)},J=function(b,c,d,e,f){var g=c.attr("data-action");if("hide"===g||"show"===g){if("hide"===g){b.addClass("hidden");O(b[0],"hiddenfromstudents",!0);I(c,"i/show","showfromothers","format_"+e,"show")}else{O(b[0],"hiddenfromstudents",!1);b.removeClass("hidden");I(c,"i/hide","hidefromothers","format_"+e,"hide")}if(d.modules!==void 0){for(var h in d.modules){L(d.modules[h])}}if(d.section_availability!==void 0){b.find(".section_availability").first().replaceWith(d.section_availability)}var k=p.state.section.get(f);if(k!==void 0){p.dispatch("sectionState",[f])}}else if("setmarker"===g){var i=a(s.SECTIONLI+".current"),j=i.find(s.SECTIONACTIONMENU+" a[data-action=removemarker]");i.removeClass("current");I(j,"i/marker","highlight","core","setmarker");b.addClass("current");I(c,"i/marked","highlightoff","core","removemarker");p.dispatch("legacySectionAction",g,f);O(b[0],"highlighted",!0)}else if("removemarker"===g){b.removeClass("current");I(c,"i/marker","highlight","core","setmarker");p.dispatch("legacySectionAction",g,f);O(b[0],"highlighted",!1)}},K=function(a){var b=document.getElementById(a);if(!b||!b.contains(document.activeElement)){return}if(b.querySelector(s.ACTIONAREA).contains(document.activeElement)){return"".concat(s.ACTIONAREA," [tabindex=\"0\"]")}if(document.activeElement.id){return"#".concat(document.activeElement.id)}},L=function(b){a("
');modalBody.find("label").html(strNumberSections),ModalFactory.create({title:modalTitle,type:ModalFactory.types.SAVE_CANCEL,body:modalBody.html()},trigger).done((function(modal){var numSections=$(modal.getBody()).find("#add_section_numsections"),addSections=function(){""+parseInt(numSections.val())===numSections.val()&&parseInt(numSections.val())>=1&&(document.location=trigger.attr("href")+"&numsections="+parseInt(numSections.val()))};modal.setSaveButtonText(modalTitle),modal.getRoot().on(ModalEvents.shown,(function(){numSections.focus().select().on("keydown",(function(e){e.keyCode===KeyCodes.enter&&addSections()}))})),modal.getRoot().on(ModalEvents.save,(function(e){e.preventDefault(),addSections()}))}))}))},replaceSectionActionItem:function(sectionelement,selector,image,stringname,stringcomponent,newaction){log.debug("replaceSectionActionItem() is deprecated and will be removed.");var actionitem=sectionelement.find(SELECTOR.SECTIONACTIONMENU+" "+selector);replaceActionItem(actionitem,image,stringname,stringcomponent,newaction)},refreshModule:refreshModule,refreshSection:function(element,sectionid,sectionreturn){void 0===sectionreturn&&(sectionreturn=courseeditor.sectionReturn);const sectionElement=$(element),promises=ajax.call([{methodname:"core_course_edit_section",args:{id:sectionid,action:"refresh",sectionreturn:sectionreturn}}],!0);var spinner=addSectionSpinner(sectionElement);return new Promise(((resolve,reject)=>{$.when.apply($,promises).done((dataencoded=>{removeSpinner(sectionElement,spinner);const data=$.parseJSON(dataencoded),newSectionElement=$(data.content);sectionElement.replaceWith(newSectionElement),$("".concat(SELECTOR.SECTIONLI,"#").concat(sectionid," ").concat(SELECTOR.ACTIVITYLI)).each(((index,activity)=>{initActionMenu(activity.data("id"))}));dispatchEvent(CourseEvents.sectionRefreshed,{ajaxreturn:data,action:"refresh",newSectionElement:newSectionElement.get(0)},newSectionElement).defaultPrevented||defaultEditSectionHandler(newSectionElement,$(SELECTOR.SECTIONLI+"#"+sectionid),data,formatname,sectionid),resolve(data)})).fail((ex=>{dispatchEvent("coursesectionrefreshfailed",{exception:ex,action:"refresh"},sectionElement).defaultPrevented||notification.exception(ex),reject()}))}))}}}));
+
+//# sourceMappingURL=actions.min.js.map
\ No newline at end of file
diff --git a/course/amd/build/actions.min.js.map b/course/amd/build/actions.min.js.map
index bab3b1c0b20..b1e72f90df5 100644
--- a/course/amd/build/actions.min.js.map
+++ b/course/amd/build/actions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/actions.js"],"names":["define","$","ajax","templates","notification","str","url","Y","ModalFactory","ModalEvents","KeyCodes","log","editor","EventDispatcher","CourseEvents","componentActions","courseeditor","getCurrentCourseEditor","formatname","CSS","EDITINPROGRESS","SECTIONDRAGGABLE","EDITINGMOVE","SELECTOR","ACTIVITYLI","ACTIONAREA","ACTIVITYACTION","MENU","TOGGLE","SECTIONLI","SECTIONACTIONMENU","ADDSECTIONS","SECTIONBADGES","use","courseformatselector","M","course","format","get_section_selector","dispatchEvent","eventName","detail","container","options","Element","get","getModuleId","element","item","dataset","id","Moodle","core_course","util","cm","getId","Node","getModuleName","name","getName","state","cmid","addActivitySpinner","activity","addClass","actionarea","find","spinner","add_spinner","show","data","dispatch","addSectionSpinner","sectionelement","addSectionLightbox","lightbox","add_lightbox","for","setAttribute","removeSpinner","delay","window","setTimeout","removeClass","hide","mutation","removeLightbox","getAttribute","initActionMenu","elementid","coursebase","invoke_function","core","actionmenu","newDOMNode","one","focusActionItem","elementId","action","mainelement","selector","is","focus","findNextFocusable","mainElement","tabables","isInside","foundElement","each","contains","editModule","moduleElement","target","attr","promises","call","methodname","args","sectionreturn","closest","when","apply","done","elementToFocus","replaceWith","affectedids","index","push","trigger","Event","ajaxreturn","fail","ex","e","exception","isDefaultPrevented","refreshModule","sectionReturn","activityElement","Promise","resolve","reject","replaceActivityHtmlWith","confirmDeleteModule","onconfirm","modtypename","match","modulename","get_string","pluginname","get_strings","key","component","param","type","s","confirm","confirmEditSection","message","replaceActionItem","actionitem","image","stringname","stringcomponent","newaction","then","strings","html","renderPix","pixhtml","catch","defaultEditSectionHandler","sectionElement","actionItem","courseformat","sectionid","setSectionBadge","modules","i","section_availability","first","section","oldmarker","oldActionItem","getActivityFocusedElement","document","getElementById","activeElement","querySelector","activityHTML","focusedPath","newItem","editSection","supportComponents","includes","dataencoded","parseJSON","badgetype","add","sectionbadges","render","js","prependNodeContents","badge","remove","register_module","set_visibility_resource_ui","getDOMNode","updateMovedCmState","params","updateMovedSectionState","addMutations","legacyActivityAction","statemanager","setReadOnly","locked","cmlist","reduce","current","delete","legacySectionAction","forEach","initCoursePage","on","keyCode","moduleId","preventDefault","sectionId","isExecuted","itemid","strNumberSections","modalTitle","newSections","modalBody","create","title","types","SAVE_CANCEL","body","modal","numSections","getBody","addSections","parseInt","val","location","setSaveButtonText","getRoot","shown","select","enter","save","replaceSectionActionItem","debug","refreshSection","newSectionElement","content","event","sectionRefreshed","defaultPrevented"],"mappings":"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","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 .\n\n/**\n * Various actions on modules and sections in the editing mode - hiding, duplicating, deleting, etc.\n *\n * @module core_course/actions\n * @copyright 2016 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.3\n */\ndefine(\n [\n 'jquery',\n 'core/ajax',\n 'core/templates',\n 'core/notification',\n 'core/str',\n 'core/url',\n 'core/yui',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/key_codes',\n 'core/log',\n 'core_courseformat/courseeditor',\n 'core/event_dispatcher',\n 'core_course/events'\n ],\n function(\n $,\n ajax,\n templates,\n notification,\n str,\n url,\n Y,\n ModalFactory,\n ModalEvents,\n KeyCodes,\n log,\n editor,\n EventDispatcher,\n CourseEvents\n ) {\n\n // Eventually, core_courseformat/local/content/actions will handle all actions for\n // component compatible formats and the default actions.js won't be necessary anymore.\n // Meanwhile, we filter the migrated actions.\n const componentActions = ['moveSection', 'moveCm', 'addSection', 'deleteSection'];\n\n // The course reactive instance.\n const courseeditor = editor.getCurrentCourseEditor();\n\n // The current course format name (loaded on init).\n let formatname;\n\n var CSS = {\n EDITINPROGRESS: 'editinprogress',\n SECTIONDRAGGABLE: 'sectiondraggable',\n EDITINGMOVE: 'editing_move'\n };\n var SELECTOR = {\n ACTIVITYLI: 'li.activity',\n ACTIONAREA: '.actions',\n ACTIVITYACTION: 'a.cm-edit-action',\n MENU: '.moodle-actionmenu[data-enhance=moodle-core-actionmenu]',\n TOGGLE: '.toggle-display,.dropdown-toggle',\n SECTIONLI: 'li.section',\n SECTIONACTIONMENU: '.section_action_menu',\n ADDSECTIONS: '.changenumsections [data-add-sections]',\n SECTIONBADGES: '[data-region=\"sectionbadges\"]',\n };\n\n Y.use('moodle-course-coursebase', function() {\n var courseformatselector = M.course.format.get_section_selector();\n if (courseformatselector) {\n SELECTOR.SECTIONLI = courseformatselector;\n }\n });\n\n /**\n * Dispatch event wrapper.\n *\n * Old jQuery events will be replaced by native events gradually.\n *\n * @method dispatchEvent\n * @param {String} eventName The name of the event\n * @param {Object} detail Any additional details to pass into the eveent\n * @param {Node|HTMLElement} container The point at which to dispatch the event\n * @param {Object} options\n * @param {Boolean} options.bubbles Whether to bubble up the DOM\n * @param {Boolean} options.cancelable Whether preventDefault() can be called\n * @param {Boolean} options.composed Whether the event can bubble across the ShadowDOM boundary\n * @returns {CustomEvent}\n */\n const dispatchEvent = function(eventName, detail, container, options) {\n // Most actions still uses jQuery node instead of regular HTMLElement.\n if (!(container instanceof Element) && container.get !== undefined) {\n container = container.get(0);\n }\n return EventDispatcher.dispatchEvent(eventName, detail, container, options);\n };\n\n /**\n * Wrapper for Y.Moodle.core_course.util.cm.getId\n *\n * @param {JQuery} element\n * @returns {Integer}\n */\n var getModuleId = function(element) {\n // Check if we have a data-id first.\n const item = element.get(0);\n if (item.dataset.id) {\n return item.dataset.id;\n }\n // Use YUI way if data-id is not present.\n let id;\n Y.use('moodle-course-util', function(Y) {\n id = Y.Moodle.core_course.util.cm.getId(Y.Node(item));\n });\n return id;\n };\n\n /**\n * Wrapper for Y.Moodle.core_course.util.cm.getName\n *\n * @param {JQuery} element\n * @returns {String}\n */\n var getModuleName = function(element) {\n var name;\n Y.use('moodle-course-util', function(Y) {\n name = Y.Moodle.core_course.util.cm.getName(Y.Node(element.get(0)));\n });\n // Check if we have the name in the course state.\n const state = courseeditor.state;\n const cmid = getModuleId(element);\n if (!name && state && cmid) {\n name = state.cm.get(cmid)?.name;\n }\n return name;\n };\n\n /**\n * Wrapper for M.util.add_spinner for an activity\n *\n * @param {JQuery} activity\n * @returns {Node}\n */\n var addActivitySpinner = function(activity) {\n activity.addClass(CSS.EDITINPROGRESS);\n var actionarea = activity.find(SELECTOR.ACTIONAREA).get(0);\n if (actionarea) {\n var spinner = M.util.add_spinner(Y, Y.Node(actionarea));\n spinner.show();\n // Lock the activity state element.\n if (activity.data('id') !== undefined) {\n courseeditor.dispatch('cmLock', [activity.data('id')], true);\n }\n return spinner;\n }\n return null;\n };\n\n /**\n * Wrapper for M.util.add_spinner for a section\n *\n * @param {JQuery} sectionelement\n * @returns {Node}\n */\n var addSectionSpinner = function(sectionelement) {\n sectionelement.addClass(CSS.EDITINPROGRESS);\n var actionarea = sectionelement.find(SELECTOR.SECTIONACTIONMENU).get(0);\n if (actionarea) {\n var spinner = M.util.add_spinner(Y, Y.Node(actionarea));\n spinner.show();\n // Lock the section state element.\n if (sectionelement.data('id') !== undefined) {\n courseeditor.dispatch('sectionLock', [sectionelement.data('id')], true);\n }\n return spinner;\n }\n return null;\n };\n\n /**\n * Wrapper for M.util.add_lightbox\n *\n * @param {JQuery} sectionelement\n * @returns {Node}\n */\n var addSectionLightbox = function(sectionelement) {\n const item = sectionelement.get(0);\n var lightbox = M.util.add_lightbox(Y, Y.Node(item));\n if (item.dataset.for == 'section' && item.dataset.id) {\n courseeditor.dispatch('sectionLock', [item.dataset.id], true);\n lightbox.setAttribute('data-state', 'section');\n lightbox.setAttribute('data-state-id', item.dataset.id);\n }\n lightbox.show();\n return lightbox;\n };\n\n /**\n * Removes the spinner element\n *\n * @param {JQuery} element\n * @param {Node} spinner\n * @param {Number} delay\n */\n var removeSpinner = function(element, spinner, delay) {\n window.setTimeout(function() {\n element.removeClass(CSS.EDITINPROGRESS);\n if (spinner) {\n spinner.hide();\n }\n // Unlock the state element.\n if (element.data('id') !== undefined) {\n const mutation = (element.data('for') === 'section') ? 'sectionLock' : 'cmLock';\n courseeditor.dispatch(mutation, [element.data('id')], false);\n }\n }, delay);\n };\n\n /**\n * Removes the lightbox element\n *\n * @param {Node} lightbox lighbox YUI element returned by addSectionLightbox\n * @param {Number} delay\n */\n var removeLightbox = function(lightbox, delay) {\n if (lightbox) {\n window.setTimeout(function() {\n lightbox.hide();\n // Unlock state if necessary.\n if (lightbox.getAttribute('data-state')) {\n courseeditor.dispatch(\n `${lightbox.getAttribute('data-state')}Lock`,\n [lightbox.getAttribute('data-state-id')],\n false\n );\n }\n }, delay);\n }\n };\n\n /**\n * Initialise action menu for the element (section or module)\n *\n * @param {String} elementid CSS id attribute of the element\n */\n var initActionMenu = function(elementid) {\n // Initialise action menu in the new activity.\n Y.use('moodle-course-coursebase', function() {\n M.course.coursebase.invoke_function('setup_for_resource', '#' + elementid);\n });\n if (M.core.actionmenu && M.core.actionmenu.newDOMNode) {\n M.core.actionmenu.newDOMNode(Y.one('#' + elementid));\n }\n };\n\n /**\n * Returns focus to the element that was clicked or \"Edit\" link if element is no longer visible.\n *\n * @param {String} elementId CSS id attribute of the element\n * @param {String} action data-action property of the element that was clicked\n */\n var focusActionItem = function(elementId, action) {\n var mainelement = $('#' + elementId);\n var selector = '[data-action=' + action + ']';\n if (action === 'groupsseparate' || action === 'groupsvisible' || action === 'groupsnone') {\n // New element will have different data-action.\n selector = '[data-action=groupsseparate],[data-action=groupsvisible],[data-action=groupsnone]';\n }\n if (mainelement.find(selector).is(':visible')) {\n mainelement.find(selector).focus();\n } else {\n // Element not visible, focus the \"Edit\" link.\n mainelement.find(SELECTOR.MENU).find(SELECTOR.TOGGLE).focus();\n }\n };\n\n /**\n * Find next after the element\n *\n * @param {JQuery} mainElement element that is about to be deleted\n * @returns {JQuery}\n */\n var findNextFocusable = function(mainElement) {\n var tabables = $(\"a:visible\");\n var isInside = false;\n var foundElement = null;\n tabables.each(function() {\n if ($.contains(mainElement[0], this)) {\n isInside = true;\n } else if (isInside) {\n foundElement = this;\n return false; // Returning false in .each() is equivalent to \"break;\" inside the loop in php.\n }\n return true;\n });\n return foundElement;\n };\n\n /**\n * Performs an action on a module (moving, deleting, duplicating, hiding, etc.)\n *\n * @param {JQuery} moduleElement activity element we perform action on\n * @param {Number} cmid\n * @param {JQuery} target the element (menu item) that was clicked\n */\n var editModule = function(moduleElement, cmid, target) {\n var action = target.attr('data-action');\n var spinner = addActivitySpinner(moduleElement);\n var promises = ajax.call([{\n methodname: 'core_course_edit_module',\n args: {id: cmid,\n action: action,\n sectionreturn: target.attr('data-sectionreturn') ? target.attr('data-sectionreturn') : 0\n }\n }], true);\n\n var lightbox;\n if (action === 'duplicate') {\n lightbox = addSectionLightbox(target.closest(SELECTOR.SECTIONLI));\n }\n $.when.apply($, promises)\n .done(function(data) {\n var elementToFocus = findNextFocusable(moduleElement);\n moduleElement.replaceWith(data);\n let affectedids = [];\n // Initialise action menu for activity(ies) added as a result of this.\n $('