AutorÃa | Ultima modificación | Ver Log |
{"version":3,"file":"external_registration.min.js","sources":["../src/external_registration.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Encapsules the behavior for creating a tool type and tool proxy from a\n * registration url in Moodle.\n *\n * Manages the UI while operations are occuring, including rendering external\n * registrati
on page within the iframe.\n *\n * See template: mod_lti/external_registration\n *\n * @module mod_lti/external_registration\n * @copyright 2015 Ryan Wyllie <ryan@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.1\n */\ndefine(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/events',\n 'mod_lti/tool_proxy', 'mod_lti/tool_type', 'mod_lti/keys', 'core/str'],\n function($, ajax, notification, templates, ltiEvents, toolProxy, toolType, KEYS, str) {\n\n var SELECTORS = {\n EXTERNAL_REGISTRATION_CONTAINER: '#external-registration-page-container',\n EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER: '#external-registration-template-container',\n EXTERNAL_REGISTRATION_CANCEL_BUTTON: '#cancel-external-registration',\n TOOL_TYPE_CAPABILITIES_CONTAINER: '#tool-type-capabilities-container',\n TOOL_TYPE_CAPABILITIES_TEMPLATE_CONTAINER: '#tool-type-capabilities-template-container',\n CAPABILI
TIES_AGREE_CONTAINER: '.capabilities-container',\n };\n\n /**\n * Return the external registration cancel button element. This button is\n * the cancel button that appears while the iframe is rendered.\n *\n * @method getExternalRegistrationCancelButton\n * @private\n * @return {JQuery} jQuery object\n */\n var getExternalRegistrationCancelButton = function() {\n return $(SELECTORS.EXTERNAL_REGISTRATION_CANCEL_BUTTON);\n };\n\n /**\n * Return the container that holds all elements for the external registration, including\n * the cancel button and the iframe.\n *\n * @method getExternalRegistrationContainer\n * @private\n * @return {JQuery} jQuery object\n */\n var getExternalRegistrationContainer = function() {\n return $(SELECTORS.EXTERNAL_REGISTRATION_CONTAINER);\n };\n\n /**\n * Return the container that holds the external registration page template. It should\n * be the iframe.\n *\n * @method get
ExternalRegistrationTemplateContainer\n * @private\n * @return {JQuery} jQuery object\n */\n var getExternalRegistrationTemplateContainer = function() {\n return $(SELECTORS.EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER);\n };\n\n /**\n * Return the container that holds the elements for displaying the list of capabilities\n * that this tool type requires. This container wraps the loading indicator and the template\n * container.\n *\n * @method getToolTypeCapabilitiesContainer\n * @private\n * @return {JQuery} jQuery object\n */\n var getToolTypeCapabilitiesContainer = function() {\n return $(SELECTORS.TOOL_TYPE_CAPABILITIES_CONTAINER);\n };\n\n /**\n * Return the container that holds the template that lists the capabilities that the\n * tool type will require.\n *\n * @method getToolTypeCapabilitiesTemplateContainer\n * @private\n * @return {JQuery} jQuery object\n */\n var getToolTypeCapabilitiesTemplateCo
ntainer = function() {\n return $(SELECTORS.TOOL_TYPE_CAPABILITIES_TEMPLATE_CONTAINER);\n };\n\n /**\n * Triggers a visual indicator to show that the capabilities section is loading.\n *\n * @method startLoadingCapabilitiesContainer\n * @private\n */\n var startLoadingCapabilitiesContainer = function() {\n getToolTypeCapabilitiesContainer().addClass('loading');\n };\n\n /**\n * Removes the visual indicator that shows the capabilities section is loading.\n *\n * @method stopLoadingCapabilitiesContainer\n * @private\n */\n var stopLoadingCapabilitiesContainer = function() {\n getToolTypeCapabilitiesContainer().removeClass('loading');\n };\n\n /**\n * Adds a visual indicator that shows the cancel button is loading.\n *\n * @method startLoadingCancel\n * @private\n */\n var startLoadingCancel = function() {\n getExternalRegistrationCancelButton().addClass('loading');\n };\n\n /**\n * Adds
a visual indicator that shows the cancel button is loading.\n *\n * @method startLoadingCancel\n * @private\n */\n var stopLoadingCancel = function() {\n getExternalRegistrationCancelButton().removeClass('loading');\n };\n\n /**\n * Stops displaying the tool type capabilities container.\n *\n * @method hideToolTypeCapabilitiesContainer\n * @private\n */\n var hideToolTypeCapabilitiesContainer = function() {\n getToolTypeCapabilitiesContainer().addClass('hidden');\n };\n\n /**\n * Displays the tool type capabilities container.\n *\n * @method showToolTypeCapabilitiesContainer\n * @private\n */\n var showToolTypeCapabilitiesContainer = function() {\n getToolTypeCapabilitiesContainer().removeClass('hidden');\n };\n\n /**\n * Stops displaying the external registration content.\n *\n * @method hideExternalRegistrationContent\n * @private\n */\n var hideExternalRegistrationContent = functi
on() {\n getExternalRegistrationContainer().addClass('hidden');\n };\n\n /**\n * Displays the external registration content.\n *\n * @method showExternalRegistrationContent\n * @private\n */\n var showExternalRegistrationContent = function() {\n getExternalRegistrationContainer().removeClass('hidden');\n };\n\n /**\n * Save the given tool proxy id on the DOM.\n *\n * @method setToolProxyId\n * @private\n * @param {Integer} id Tool proxy ID\n */\n var setToolProxyId = function(id) {\n var button = getExternalRegistrationCancelButton();\n button.attr('data-tool-proxy-id', id);\n };\n\n /**\n * Return the saved tool proxy id.\n *\n * @method getToolProxyId\n * @private\n * @return {String} Tool proxy ID\n */\n var getToolProxyId = function() {\n var button = getExternalRegistrationCancelButton();\n return button.attr('data-tool-proxy-id');\n };\n\n /**\n * Remove the
saved tool proxy id.\n *\n * @method clearToolProxyId\n * @private\n */\n var clearToolProxyId = function() {\n var button = getExternalRegistrationCancelButton();\n button.removeAttr('data-tool-proxy-id');\n };\n\n /**\n * Returns true if a tool proxy id has been recorded.\n *\n * @method hasToolProxyId\n * @private\n * @return {Boolean}\n */\n var hasToolProxyId = function() {\n return getToolProxyId() ? true : false;\n };\n\n /**\n * Checks if this process has created a tool proxy within\n * Moodle yet.\n *\n * @method hasCreatedToolProxy\n * @private\n * @return {Boolean}\n */\n var hasCreatedToolProxy = function() {\n var button = getExternalRegistrationCancelButton();\n return button.attr('data-tool-proxy-new') && hasToolProxyId();\n };\n\n /**\n * Records that this process has created a tool proxy.\n *\n * @method setProxyAsNew\n * @private\n * @return
{Boolean}\n */\n var setProxyAsNew = function() {\n var button = getExternalRegistrationCancelButton();\n return button.attr('data-tool-proxy-new', \"new\");\n };\n\n /**\n * Records that this process has not created a tool proxy.\n *\n * @method setProxyAsOld\n * @private\n * @return {Boolean}\n */\n var setProxyAsOld = function() {\n var button = getExternalRegistrationCancelButton();\n return button.removeAttr('data-tool-proxy-new');\n };\n\n /**\n * Gets the external registration request required to be sent to the external\n * registration page using a form.\n *\n * See mod_lti/tool_proxy_registration_form template.\n *\n * @method getRegistrationRequest\n * @private\n * @param {Integer} id Tool Proxy ID\n * @return {Promise} jQuery Deferred object\n */\n var getRegistrationRequest = function(id) {\n var request = {\n methodname: 'mod_lti_get_tool_proxy_registration_reque
st',\n args: {\n id: id\n }\n };\n\n return ajax.call([request])[0];\n };\n\n /**\n * Cancel an in progress external registration. This will perform any necessary\n * clean up of tool proxies and return the page section back to the home section.\n *\n * @method cancelRegistration\n * @private\n * @return {Promise} jQuery Deferred object\n */\n var cancelRegistration = function() {\n startLoadingCancel();\n var promise = $.Deferred();\n\n // If we've created a proxy as part of this process then\n // we need to delete it to clean up the data in the back end.\n if (hasCreatedToolProxy()) {\n var id = getToolProxyId();\n toolProxy.delete(id).done(function() {\n promise.resolve();\n }).fail(function(failure) {\n promise.reject(failure);\n });\n } else {\n promise.resolve();\n }\n\n promis
e.done(function() {\n // Return to the original page.\n finishExternalRegistration();\n stopLoadingCancel();\n }).fail(function(failure) {\n notification.exception(failure);\n finishExternalRegistration();\n stopLoadingCancel();\n str.get_string('failedtodeletetoolproxy', 'mod_lti').done(function(s) {\n var feedback = {\n message: s,\n error: true\n };\n $(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, feedback);\n }).fail(notification.exception);\n });\n\n return promise;\n };\n\n /**\n * Load the external registration template and render it in the DOM and display it.\n *\n * @method renderExternalRegistrationWindow\n * @private\n * @param {Object} registrationRequest\n * @return {Promise} jQuery Deferred object\n */\n var renderExternalRegistrationWindow = function(registration
Request) {\n var promise = templates.render('mod_lti/tool_proxy_registration_form', registrationRequest);\n\n promise.done(function(html, js) {\n // Show the external registration page in an iframe.\n var container = getExternalRegistrationTemplateContainer();\n container.append(html);\n templates.runTemplateJS(js);\n\n container.find('form').submit();\n showExternalRegistrationContent();\n }).fail(notification.exception);\n\n return promise;\n };\n\n /**\n * Send a request to Moodle server to set the state of the tool type to configured (active).\n *\n * @method setTypeStatusActive\n * @private\n * @param {Object} typeData A set of data representing a type, as returned by a request to get a type\n * from the Moodle server.\n * @return {Promise} jQuery Deferred object\n */\n var setTypeStatusActive = function(typeData) {\n return toolType.update({\n
id: typeData.id,\n state: toolType.constants.state.configured\n });\n };\n\n /**\n * Render and display an agreement page for the user to acknowledge the list of capabilities\n * (groups of data) that the external tool requires in order to work. If the user agrees then\n * we will activate the tool so that it is immediately available. If they don't agree then\n * the tool remains in a pending state within Moodle until agreement is given.\n *\n * @method promptForToolTypeCapabilitiesAgreement\n * @private\n * @param {Object} typeData A set of data representing a type, as returned by a request to get a type\n * from the Moodle server.\n * @return {Promise} jQuery Deferred object\n */\n var promptForToolTypeCapabilitiesAgreement = function(typeData) {\n var promise = $.Deferred();\n\n templates.render('mod_lti/tool_type_capabilities_agree', typeData).done(function(html, js) {\n var container = get
ToolTypeCapabilitiesTemplateContainer();\n\n hideExternalRegistrationContent();\n showToolTypeCapabilitiesContainer();\n\n templates.replaceNodeContents(container, html, js);\n\n var choiceContainer = container.find(SELECTORS.CAPABILITIES_AGREE_CONTAINER);\n\n // The user agrees to allow the tool to use the groups of data so we can go\n // ahead and activate it for them so that it can be used straight away.\n choiceContainer.on(ltiEvents.CAPABILITIES_AGREE, function() {\n startLoadingCapabilitiesContainer();\n setTypeStatusActive(typeData).always(function() {\n stopLoadingCapabilitiesContainer();\n container.empty();\n promise.resolve();\n });\n });\n\n // The user declines to let the tool use the data. In this case we leave\n // the tool as pending and they can delete it using the main screen if the
y\n // wish.\n choiceContainer.on(ltiEvents.CAPABILITIES_DECLINE, function() {\n container.empty();\n promise.resolve();\n });\n }).fail(promise.reject);\n\n promise.done(function() {\n hideToolTypeCapabilitiesContainer();\n }).fail(notification.exception);\n\n return promise;\n };\n\n /**\n * Send a request to the Moodle server to create a tool proxy using the registration URL the user\n * has provided. The proxy is required for the external registration page to work correctly.\n *\n * After the proxy is created the external registration page is rendered within an iframe for the user\n * to complete the registration in the external page.\n *\n * If the tool proxy creation fails then we redirect the page section back to the home section and\n * display the error, rather than rendering the external registration page.\n *\n * @method createAndRegisterToolProxy\n
* @private\n * @param {String} url Tool registration URL to register\n * @return {Promise} jQuery Deferred object\n */\n var createAndRegisterToolProxy = function(url) {\n var promise = $.Deferred();\n\n if (!url || url === \"\") {\n // No URL has been input so do nothing.\n promise.resolve();\n } else {\n // A tool proxy needs to exist before the external page is rendered because\n // the external page sends requests back to Moodle for information that is stored\n // in the proxy.\n toolProxy.create({regurl: url})\n .done(function(result) {\n // Note that it's a new proxy so we will always clean it up.\n setProxyAsNew();\n promise = registerProxy(result.id);\n })\n .fail(function(exception) {\n // Clean up.\n cancelRegistration();\n
// Let the user know what the error is.\n var feedback = {\n message: exception.message,\n error: true\n };\n $(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, feedback);\n promise.reject(exception);\n });\n }\n\n return promise;\n };\n\n /**\n * Loads the window to register a proxy, given an ID.\n *\n * @method registerProxy\n * @private\n * @param {Integer} id Proxy id to register\n * @return {Promise} jQuery Deferred object to fail or resolve\n */\n var registerProxy = function(id) {\n var promise = $.Deferred();\n // Save the id on the DOM to cleanup later.\n setToolProxyId(id);\n\n // There is a specific set of data needed to send to the external registration page\n // in a form, so let's get it from our server.\n getRegistrationReques
t(id)\n .done(function(registrationRequest) {\n renderExternalRegistrationWindow(registrationRequest)\n .done(function() {\n promise.resolve();\n })\n .fail(promise.fail);\n })\n .fail(promise.fail);\n\n return promise;\n };\n\n /**\n * Complete the registration process, clean up any left over data and\n * trigger the appropriate events.\n *\n * @method finishExternalRegistration\n * @private\n */\n var finishExternalRegistration = function() {\n if (hasToolProxyId()) {\n clearToolProxyId();\n }\n setProxyAsOld(false);\n\n hideExternalRegistrationContent();\n var container = getExternalRegistrationTemplateContainer();\n container.empty();\n\n $(document).trigger(ltiEvents.STOP_EXTERNAL_REGISTRATION);\n };\n\n /**\n * Sets up the listeners for
user interaction on the page.\n *\n * @method registerEventListeners\n * @private\n */\n var registerEventListeners = function() {\n\n $(document).on(ltiEvents.START_EXTERNAL_REGISTRATION, function(event, data) {\n if (!data) {\n return;\n }\n if (data.url) {\n createAndRegisterToolProxy(data.url);\n }\n if (data.proxyid) {\n registerProxy(data.proxyid);\n }\n });\n\n var cancelExternalRegistrationButton = getExternalRegistrationCancelButton();\n cancelExternalRegistrationButton.click(function(e) {\n e.preventDefault();\n cancelRegistration();\n });\n cancelExternalRegistrationButton.keypress(function(e) {\n if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {\n if (e.keyCode == KEYS.ENTER || e.keyCode == KEYS.SPACE) {\n e.prev
entDefault();\n cancelRegistration();\n }\n }\n });\n\n // This is gross but necessary due to isolated jQuery scopes between\n // child iframe and parent windows. There is no other way to communicate.\n //\n // This function gets called by the moodle page that received the redirect\n // from the external registration page and handles the external page's returned\n // parameters.\n //\n // See AMD module mod_lti/external_registration_return.\n window.triggerExternalRegistrationComplete = function(data) {\n var promise = $.Deferred();\n var feedback = {\n message: \"\",\n error: false\n };\n\n if (data.status == \"success\") {\n str.get_string('successfullycreatedtooltype', 'mod_lti').done(function(s) {\n feedback.message = s;\n }).fail(notification.exception);\n\n
// Trigger appropriate events when we've completed the necessary requests.\n promise.done(function() {\n finishExternalRegistration();\n $(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, feedback);\n $(document).trigger(ltiEvents.NEW_TOOL_TYPE);\n }).fail(notification.exception);\n\n // We should have created a tool proxy by this point.\n if (hasCreatedToolProxy()) {\n var proxyId = getToolProxyId();\n\n // We need the list of types that are linked to this proxy. We're assuming it'll\n // only be one because this process creates a one-to-one type->proxy.\n toolType.getFromToolProxyId(proxyId).done(function(types) {\n if (types && types.length) {\n // There should only be one result.\n var typeData = types[0];\n\n
// Check if the external tool required access to any Moodle data (users, courses etc).\n if (typeData.hascapabilitygroups) {\n // If it did then we ask the user to agree to those groups before the type is\n // activated (i.e. can be used in Moodle).\n promptForToolTypeCapabilitiesAgreement(typeData).always(function() {\n promise.resolve();\n });\n } else {\n promise.resolve();\n }\n } else {\n promise.resolve();\n }\n }).fail(function() {\n promise.resolve();\n });\n }\n } else {\n // Anything other than success is failure.\n feedback.message = data.er
ror;\n feedback.error = true;\n\n // Cancel registration to clean up any proxies and tools that were\n // created.\n promise.done(function() {\n cancelRegistration().always(function() {\n $(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, feedback);\n });\n }).fail(notification.exception);\n\n promise.resolve();\n }\n\n return promise;\n };\n };\n\n return {\n\n /**\n * Initialise this module.\n */\n init: function() {\n registerEventListeners();\n }\n };\n});\n"],"names":["define","$","ajax","notification","templates","ltiEvents","toolProxy","toolType","KEYS","str","SELECTORS","getExternalRegistrationCancelButton","getExternalRegistrationContainer","getExternalRegistrationTemplateContainer","getToolTypeCapabilitiesContainer","stopLoadingCancel","removeClass","hideExternalR
egistrationContent","addClass","getToolProxyId","attr","hasToolProxyId","hasCreatedToolProxy","cancelRegistration","promise","Deferred","id","delete","done","resolve","fail","failure","reject","finishExternalRegistration","exception","get_string","s","feedback","message","error","document","trigger","REGISTRATION_FEEDBACK","renderExternalRegistrationWindow","registrationRequest","render","html","js","container","append","runTemplateJS","find","submit","promptForToolTypeCapabilitiesAgreement","typeData","replaceNodeContents","choiceContainer","on","CAPABILITIES_AGREE","update","state","constants","configured","setTypeStatusActive","always","empty","CAPABILITIES_DECLINE","createAndRegisterToolProxy","url","create","regurl","result","registerProxy","setToolProxyId","request","methodname","args","call","getRegistrationRequest","removeAttr","STOP_EXTERNAL_REGISTRATION","init","START_EXTERNAL_REGISTRATION","event","data","proxyid","cancelExternalRegistrationButton","click","e","preventDefault","keypress","metaKey"
,"shiftKey","altKey","ctrlKey","keyCode","ENTER","SPACE","window","triggerExternalRegistrationComplete","status","NEW_TOOL_TYPE","proxyId","getFromToolProxyId","types","length","hascapabilitygroups","registerEventListeners"],"mappings":"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"}