{"version":3,"file":"notification.min.js","sources":["https:\/\/lms.innovativelearning.eu\/lib\/amd\/src\/notification.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 * Notification manager for in-page notifications in Moodle.\n *\n * @module core\/notification\n * @copyright 2015 Damyon Wiese \n * @license http:\/\/www.gnu.org\/copyleft\/gpl.html GNU GPL v3 or later\n * @since 2.9\n *\/\nimport Pending from 'core\/pending';\nimport Log from 'core\/log';\n\nlet currentContextId = M.cfg.contextid;\n\nconst notificationTypes = {\n success: 'core\/notification_success',\n info: 'core\/notification_info',\n warning: 'core\/notification_warning',\n error: 'core\/notification_error',\n};\n\nconst notificationRegionId = 'user-notifications';\n\nconst Selectors = {\n notificationRegion: `#${notificationRegionId}`,\n fallbackRegionParents: [\n '#region-main',\n '[role=\"main\"]',\n 'body',\n ],\n};\n\nconst setupTargetRegion = () => {\n let targetRegion = getNotificationRegion();\n if (targetRegion) {\n return false;\n }\n\n const newRegion = document.createElement('span');\n newRegion.id = notificationRegionId;\n\n return Selectors.fallbackRegionParents.some(selector => {\n const targetRegion = document.querySelector(selector);\n\n if (targetRegion) {\n targetRegion.prepend(newRegion);\n return true;\n }\n\n return false;\n });\n};\n\n\/**\n * A notification object displayed to a user.\n *\n * @typedef {Object} Notification\n * @property {string} message The body of the notification\n * @property {string} type The type of notification to add (error, warning, info, success).\n * @property {Boolean} closebutton Whether to show the close button.\n * @property {Boolean} announce Whether to announce to screen readers.\n *\/\n\n\/**\n * Poll the server for any new notifications.\n *\n * @method\n * @returns {Promise}\n *\/\nexport const fetchNotifications = async() => {\n const Ajax = await import('core\/ajax');\n\n return Ajax.call([{\n methodname: 'core_fetch_notifications',\n args: {\n contextid: currentContextId\n }\n }])[0]\n .then(addNotifications);\n};\n\n\/**\n * Add all of the supplied notifications.\n *\n * @method\n * @param {Notification[]} notifications The list of notificaitons\n * @returns {Promise}\n *\/\nconst addNotifications = notifications => {\n if (!notifications.length) {\n return Promise.resolve();\n }\n\n const pendingPromise = new Pending('core\/notification:addNotifications');\n notifications.forEach(notification => renderNotification(notification.template, notification.variables));\n\n return pendingPromise.resolve();\n};\n\n\/**\n * Add a notification to the page.\n *\n * Note: This does not cause the notification to be added to the session.\n *\n * @method\n * @param {Notification} notification The notification to add.\n * @returns {Promise}\n *\/\nexport const addNotification = notification => {\n const pendingPromise = new Pending('core\/notification:addNotifications');\n\n let template = notificationTypes.error;\n\n notification = {\n closebutton: true,\n announce: true,\n type: 'error',\n ...notification,\n };\n\n if (notification.template) {\n template = notification.template;\n delete notification.template;\n } else if (notification.type) {\n if (typeof notificationTypes[notification.type] !== 'undefined') {\n template = notificationTypes[notification.type];\n }\n delete notification.type;\n }\n\n return renderNotification(template, notification)\n .then(pendingPromise.resolve);\n};\n\nconst renderNotification = async(template, variables) => {\n if (typeof variables.message === 'undefined' || !variables.message) {\n Log.debug('Notification received without content. Skipping.');\n return;\n }\n\n const pendingPromise = new Pending('core\/notification:renderNotification');\n const Templates = await import('core\/templates');\n\n Templates.renderForPromise(template, variables)\n .then(({html, js = ''}) => {\n Templates.prependNodeContents(getNotificationRegion(), html, js);\n\n return;\n })\n .then(pendingPromise.resolve)\n .catch(exception);\n};\n\nconst getNotificationRegion = () => document.querySelector(Selectors.notificationRegion);\n\n\/**\n * Alert dialogue.\n *\n * @method\n * @param {String|Promise} title\n * @param {String|Promise} message\n * @param {String|Promise} cancelText\n * @returns {Promise}\n *\/\nexport const alert = async(title, message, cancelText) => {\n var pendingPromise = new Pending('core\/notification:alert');\n\n const ModalFactory = await import('core\/modal_factory');\n\n return ModalFactory.create({\n type: ModalFactory.types.ALERT,\n body: message,\n title: title,\n buttons: {\n cancel: cancelText,\n },\n removeOnClose: true,\n })\n .then(function(modal) {\n modal.show();\n\n pendingPromise.resolve();\n return modal;\n });\n};\n\n\/**\n * The confirm has now been replaced with a save and cancel dialogue.\n *\n * @method\n * @param {String|Promise} title\n * @param {String|Promise} question\n * @param {String|Promise} saveLabel\n * @param {String|Promise} noLabel\n * @param {String|Promise} saveCallback\n * @param {String|Promise} cancelCallback\n * @returns {Promise}\n *\/\nexport const confirm = (title, question, saveLabel, noLabel, saveCallback, cancelCallback) =>\n saveCancel(title, question, saveLabel, saveCallback, cancelCallback);\n\n\/**\n * The Save and Cancel dialogue helper.\n *\n * @method\n * @param {String|Promise} title\n * @param {String|Promise} question\n * @param {String|Promise} saveLabel\n * @param {String|Promise} saveCallback\n * @param {String|Promise} cancelCallback\n * @param {Object} options\n * @param {HTMLElement} [options.triggerElement=null] The element that triggered the modal (will receive the focus after hidden)\n * @returns {Promise}\n *\/\nexport const saveCancel = async(title, question, saveLabel, saveCallback, cancelCallback, {\n triggerElement = null,\n} = {}) => {\n const pendingPromise = new Pending('core\/notification:confirm');\n\n const [\n ModalFactory,\n ModalEvents,\n ] = await Promise.all([\n import('core\/modal_factory'),\n import('core\/modal_events'),\n ]);\n\n return ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: title,\n body: question,\n buttons: {\n \/\/ Note: The noLabel is no longer supported.\n save: saveLabel,\n },\n removeOnClose: true,\n })\n .then(function(modal) {\n modal.show();\n\n modal.getRoot().on(ModalEvents.save, saveCallback);\n modal.getRoot().on(ModalEvents.cancel, cancelCallback);\n modal.getRoot().on(ModalEvents.hidden, () => triggerElement?.focus());\n pendingPromise.resolve();\n\n return modal;\n });\n};\n\n\/**\n * Add all of the supplied notifications.\n *\n * @param {Promise|String} title The header of the modal\n * @param {Promise|String} question What do we want the user to confirm\n * @param {Promise|String} saveLabel The modal action link text\n * @param {Object} options\n * @param {HTMLElement} [options.triggerElement=null] The element that triggered the modal (will receive the focus after hidden)\n * @return {Promise}\n *\/\nexport const saveCancelPromise = (title, question, saveLabel, {\n triggerElement = null,\n} = {}) => new Promise((resolve, reject) => {\n saveCancel(title, question, saveLabel, resolve, reject, {triggerElement});\n});\n\n\/**\n * Wrap M.core.exception.\n *\n * @method\n * @param {Error} ex\n *\/\nexport const exception = async ex => {\n const pendingPromise = new Pending('core\/notification:displayException');\n\n \/\/ Fudge some parameters.\n if (!ex.stack) {\n ex.stack = '';\n }\n\n if (ex.debuginfo) {\n ex.stack += ex.debuginfo + '\\n';\n }\n\n if (!ex.backtrace && ex.stacktrace) {\n ex.backtrace = ex.stacktrace;\n }\n\n if (ex.backtrace) {\n ex.stack += ex.backtrace;\n const ln = ex.backtrace.match(\/line ([^ ]*) of\/);\n const fn = ex.backtrace.match(\/ of ([^:]*): \/);\n if (ln && ln[1]) {\n ex.lineNumber = ln[1];\n }\n if (fn && fn[1]) {\n ex.fileName = fn[1];\n if (ex.fileName.length > 30) {\n ex.fileName = '...' + ex.fileName.substr(ex.fileName.length - 27);\n }\n }\n }\n\n if (typeof ex.name === 'undefined' && ex.errorcode) {\n ex.name = ex.errorcode;\n }\n\n const Y = await import('core\/yui');\n Y.use('moodle-core-notification-exception', function() {\n var modal = new M.core.exception(ex);\n\n modal.show();\n\n pendingPromise.resolve();\n });\n};\n\n\/**\n * Initialise the page for the suppled context, and displaying the supplied notifications.\n *\n * @method\n * @param {Number} contextId\n * @param {Notification[]} notificationList\n *\/\nexport const init = (contextId, notificationList) => {\n currentContextId = contextId;\n\n \/\/ Setup the message target region if it isn't setup already\n setupTargetRegion();\n\n \/\/ Add provided notifications.\n addNotifications(notificationList);\n};\n\n\/\/ To maintain backwards compatability we export default here.\nexport default {\n init,\n fetchNotifications,\n addNotification,\n alert,\n confirm,\n saveCancel,\n saveCancelPromise,\n exception,\n};\n"],"names":["currentContextId","M","cfg","contextid","notificationTypes","success","info","warning","error","Selectors","notificationRegion","fallbackRegionParents","fetchNotifications","async","call","methodname","args","then","addNotifications","notifications","length","Promise","resolve","pendingPromise","Pending","forEach","notification","renderNotification","template","variables","addNotification","closebutton","announce","type","message","debug","Templates","renderForPromise","_ref","html","js","prependNodeContents","getNotificationRegion","catch","exception","document","querySelector","alert","title","cancelText","ModalFactory","create","types","ALERT","body","buttons","cancel","removeOnClose","modal","show","confirm","question","saveLabel","noLabel","saveCallback","cancelCallback","saveCancel","triggerElement","ModalEvents","all","SAVE_CANCEL","save","getRoot","on","hidden","focus","saveCancelPromise","reject","ex","stack","debuginfo","backtrace","stacktrace","ln","match","fn","lineNumber","fileName","substr","name","errorcode","use","core","init","contextId","notificationList","newRegion","createElement","id","some","selector","targetRegion","prepend","setupTargetRegion"],"mappings":"4oBA0BIA,iBAAmBC,EAAEC,IAAIC,gBAEvBC,kBAAoB,CACtBC,QAAU,4BACVC,KAAU,yBACVC,QAAU,4BACVC,MAAU,2BAKRC,UAAY,CACdC,8BAHyB,sBAIzBC,sBAAuB,CACnB,eACA,gBACA,SAyCKC,mBAAqBC,8lBAGlBC,KAAK,CAAC,CACdC,WAAY,2BACZC,KAAM,CACFb,UAAWH,qBAEf,GACHiB,KAAKC,uEAUJA,iBAAmBC,oBAChBA,cAAcC,cACRC,QAAQC,gBAGbC,eAAiB,IAAIC,iBAAQ,6CACnCL,cAAcM,SAAQC,cAAgBC,mBAAmBD,aAAaE,SAAUF,aAAaG,aAEtFN,eAAeD,WAYbQ,gBAAkBJ,qBACrBH,eAAiB,IAAIC,iBAAQ,0CAE\/BI,SAAWxB,kBAAkBI,aAEjCkB,aAAe,CACXK,aAAgB,EAChBC,UAAgB,EAChBC,KAAgB,WACbP,eAGUE,UACbA,SAAWF,aAAaE,gBACjBF,aAAaE,UACbF,aAAaO,YACgC,IAAzC7B,kBAAkBsB,aAAaO,QACtCL,SAAWxB,kBAAkBsB,aAAaO,cAEvCP,aAAaO,MAGjBN,mBAAmBC,SAAUF,cACnCT,KAAKM,eAAeD,yDAGnBK,mBAAqBd,MAAMe,SAAUC,qBACN,IAAtBA,UAAUK,UAA4BL,UAAUK,iCACnDC,MAAM,0DAIRZ,eAAiB,IAAIC,iBAAQ,wCAC7BY,4mBAENA,UAAUC,iBAAiBT,SAAUC,WACpCZ,MAAKqB,WAACC,KAACA,KAADC,GAAOA,GAAK,SACfJ,UAAUK,oBAAoBC,wBAAyBH,KAAMC,OAIhEvB,KAAKM,eAAeD,SACpBqB,MAAMC,YAGLF,sBAAwB,IAAMG,SAASC,cAAcrC,UAAUC,oBAWxDqC,MAAQlC,MAAMmC,MAAOd,QAASe,kBACnC1B,eAAiB,IAAIC,iBAAQ,iCAE3B0B,koBAECA,aAAaC,OAAO,CACvBlB,KAAMiB,aAAaE,MAAMC,MACzBC,KAAMpB,QACNc,MAAOA,MACPO,QAAS,CACLC,OAAQP,YAEZQ,eAAe,IAElBxC,MAAK,SAASyC,cACXA,MAAMC,OAENpC,eAAeD,UACRoC,qCAgBFE,QAAU,CAACZ,MAAOa,SAAUC,UAAWC,QAASC,aAAcC,iBACnEC,WAAWlB,MAAOa,SAAUC,UAAWE,aAAcC,+CAehDC,WAAarD,eAAMmC,MAAOa,SAAUC,UAAWE,aAAcC,oBAAgBE,eACtFA,eAAiB,6DACjB,SACM5C,eAAiB,IAAIC,iBAAQ,8BAG\/B0B,aACAkB,mBACM\/C,QAAQgD,IAAI,qtCAKfnB,aAAaC,OAAO,CACvBlB,KAAMiB,aAAaE,MAAMkB,YACzBtB,MAAOA,MACPM,KAAMO,SACNN,QAAS,CAELgB,KAAMT,WAEVL,eAAe,IAElBxC,MAAK,SAASyC,cACXA,MAAMC,OAEND,MAAMc,UAAUC,GAAGL,YAAYG,KAAMP,cACrCN,MAAMc,UAAUC,GAAGL,YAAYZ,OAAQS,gBACvCP,MAAMc,UAAUC,GAAGL,YAAYM,QAAQ,IAAMP,MAAAA,sBAAAA,eAAgBQ,UAC7DpD,eAAeD,UAERoC,+CAcFkB,kBAAoB,SAAC5B,MAAOa,SAAUC,eAAWK,eAC1DA,eAAiB,6DACjB,UAAO,IAAI9C,SAAQ,CAACC,QAASuD,UAC7BX,WAAWlB,MAAOa,SAAUC,UAAWxC,QAASuD,OAAQ,CAACV,eAAAA,wEAShDvB,UAAY\/B,MAAAA,WACfU,eAAiB,IAAIC,iBAAQ,yCAG9BsD,GAAGC,QACJD,GAAGC,MAAQ,IAGXD,GAAGE,YACHF,GAAGC,OAASD,GAAGE,UAAY,OAG1BF,GAAGG,WAAaH,GAAGI,aACpBJ,GAAGG,UAAYH,GAAGI,YAGlBJ,GAAGG,UAAW,CACdH,GAAGC,OAASD,GAAGG,gBACTE,GAAKL,GAAGG,UAAUG,MAAM,mBACxBC,GAAKP,GAAGG,UAAUG,MAAM,iBAC1BD,IAAMA,GAAG,KACTL,GAAGQ,WAAaH,GAAG,IAEnBE,IAAMA,GAAG,KACTP,GAAGS,SAAWF,GAAG,GACbP,GAAGS,SAASnE,OAAS,KACrB0D,GAAGS,SAAW,MAAQT,GAAGS,SAASC,OAAOV,GAAGS,SAASnE,OAAS,WAKnD,IAAZ0D,GAAGW,MAAwBX,GAAGY,YACrCZ,GAAGW,KAAOX,GAAGY,6lBAIfC,IAAI,sCAAsC,WAC5B,IAAI1F,EAAE2F,KAAKhD,UAAUkC,IAE3BnB,OAENpC,eAAeD,iDAWVuE,KAAO,CAACC,UAAWC,oBAC5B\/F,iBAAmB8F,UApSG,SACHpD,+BAER,QAGLsD,UAAYnD,SAASoD,cAAc,QACzCD,UAAUE,GAlBe,qBAoBlBzF,UAAUE,sBAAsBwF,MAAKC,iBAClCC,aAAexD,SAASC,cAAcsD,kBAExCC,eACAA,aAAaC,QAAQN,YACd,OAyRfO,GAGArF,iBAAiB6E,mDAIN,CACXF,KAAAA,KACAjF,mBAAAA,mBACAkB,gBAAAA,gBACAiB,MAAAA,MACAa,QAAAA,QACAM,WAAAA,WACAU,kBAAAA,kBACAhC,UAAAA"}