first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
/**
* Encapsules the behavior for creating a tool type from a cartridge URL
* in Moodle. Manages the UI while operations are occuring.
*
* See template: mod_lti/cartridge_registration_form
*
* @module mod_lti/cartridge_registration_form
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define("mod_lti/cartridge_registration_form",["jquery","core/ajax","core/notification","mod_lti/tool_type","mod_lti/events","mod_lti/keys","core/str"],(function($,ajax,notification,toolType,ltiEvents,KEYS,str){var SELECTORS_CONSUMER_KEY="#registration-key",SELECTORS_SHARED_SECRET="#registration-secret",SELECTORS_REGISTRATION_FORM="#cartridge-registration-form",SELECTORS_REGISTRATION_SUBMIT_BUTTON="#cartridge-registration-submit",SELECTORS_REGISTRATION_CANCEL_BUTTON="#cartridge-registration-cancel",getSubmitButton=function(){return $(SELECTORS_REGISTRATION_SUBMIT_BUTTON)},submitCartridgeURL=function(){if(getSubmitButton().hasClass("loading"))return!1;var url=$(SELECTORS_REGISTRATION_FORM).attr("data-cartridge-url");if(""===url)return!1;getSubmitButton().addClass("loading");var consumerKey=$(SELECTORS_CONSUMER_KEY).val(),sharedSecret=$(SELECTORS_SHARED_SECRET).val(),promise=toolType.create({cartridgeurl:url,key:consumerKey,secret:sharedSecret});return promise.done((function(){str.get_string("successfullycreatedtooltype","mod_lti").done((function(s){$(document).trigger(ltiEvents.NEW_TOOL_TYPE),$(document).trigger(ltiEvents.STOP_CARTRIDGE_REGISTRATION),$(document).trigger(ltiEvents.REGISTRATION_FEEDBACK,{message:s})})).fail(notification.exception)})).fail((function(){str.get_string("failedtocreatetooltype","mod_lti").done((function(s){$(document).trigger(ltiEvents.NEW_TOOL_TYPE),$(document).trigger(ltiEvents.STOP_CARTRIDGE_REGISTRATION),$(document).trigger(ltiEvents.REGISTRATION_FEEDBACK,{message:s,error:!0})})).fail(notification.exception)})).always((function(){getSubmitButton().removeClass("loading")})),promise},registerEventListeners=function(){$(SELECTORS_REGISTRATION_FORM).submit((function(e){e.preventDefault(),submitCartridgeURL()}));var cancelButton=$(SELECTORS_REGISTRATION_CANCEL_BUTTON);cancelButton.click((function(e){e.preventDefault(),$(document).trigger(ltiEvents.STOP_CARTRIDGE_REGISTRATION)})),cancelButton.keypress((function(e){e.metaKey||e.shiftKey||e.altKey||e.ctrlKey||e.keyCode!=KEYS.ENTER&&e.keyCode!=KEYS.SPACE||(e.preventDefault(),cancelButton.click())}))};return{init:function(){registerEventListeners()}}}));
//# sourceMappingURL=cartridge_registration_form.min.js.map
File diff suppressed because one or more lines are too long
+14
View File
@@ -0,0 +1,14 @@
/**
* Launches the modal dialogue that contains the iframe that sends the Content-Item selection request to an
* LTI tool provider that supports Content-Item type message.
*
* See template: mod_lti/contentitem
*
* @module mod_lti/contentitem
* @copyright 2016 Jun Pataleta <jun@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.2
*/
define("mod_lti/contentitem",["jquery","core/notification","core/str","core/templates","mod_lti/form-field","core/modal","core/modal_events"],(function($,notification,str,templates,FormField,Modal,ModalEvents){var dialogue,doneCallback,contentItem={init:function(url,postData,cb){doneCallback=cb;var context={url:url,postData:postData},bodyPromise=templates.render("mod_lti/contentitem",context);if(dialogue)return dialogue.setBody(bodyPromise),void dialogue.show();str.get_string("selectcontent","lti").then((function(title){return Modal.create({title:title,body:bodyPromise,large:!0,show:!0})})).then((function(modal){dialogue=modal,modal.getRoot().on(ModalEvents.hidden,(function(){modal.setBody(""),notification.fetchNotifications()}))})).catch(notification.exception)}},ltiFormFields=[new FormField("name",FormField.TYPES.TEXT,!1,""),new FormField("introeditor",FormField.TYPES.EDITOR,!1,""),new FormField("toolurl",FormField.TYPES.TEXT,!0,""),new FormField("securetoolurl",FormField.TYPES.TEXT,!0,""),new FormField("instructorchoiceacceptgrades",FormField.TYPES.CHECKBOX,!0,!0),new FormField("instructorchoicesendname",FormField.TYPES.CHECKBOX,!0,!0),new FormField("instructorchoicesendemailaddr",FormField.TYPES.CHECKBOX,!0,!0),new FormField("instructorcustomparameters",FormField.TYPES.TEXT,!0,""),new FormField("icon",FormField.TYPES.TEXT,!0,""),new FormField("secureicon",FormField.TYPES.TEXT,!0,""),new FormField("launchcontainer",FormField.TYPES.SELECT,!0,0),new FormField("grade_modgrade_point",FormField.TYPES.TEXT,!1,""),new FormField("lineitemresourceid",FormField.TYPES.TEXT,!0,""),new FormField("lineitemtag",FormField.TYPES.TEXT,!0,""),new FormField("lineitemsubreviewurl",FormField.TYPES.TEXT,!0,""),new FormField("lineitemsubreviewparams",FormField.TYPES.TEXT,!0,"")];const hideElement=e=>{e.setAttribute("hidden","true"),e.setAttribute("aria-hidden","true"),e.setAttribute("tab-index","-1")},showElement=e=>{e.removeAttribute("hidden"),e.setAttribute("aria-hidden","false"),e.setAttribute("tab-index","1")};return window.processContentItemReturnData=function(returnData){var index;if(dialogue&&dialogue.hide(),returnData.multiple){for(index in ltiFormFields)ltiFormFields[index].setFieldValue("name"===ltiFormFields[index].name?"item":null);var variants=[];returnData.multiple.forEach((function(v){variants.push((config=>{const variant={};return["name","toolurl","securetoolurl","instructorcustomparameters","icon","secureicon","launchcontainer","lineitemresourceid","lineitemtag","lineitemsubreviewurl","lineitemsubreviewparams"].forEach((function(name){variant[name]=config[name]||""})),variant["introeditor[text]"]=config.introeditor?config.introeditor.text:"",variant["introeditor[format]"]=config.introeditor?config.introeditor.format:"",1===config.instructorchoiceacceptgrades?(variant.instructorchoiceacceptgrades="1",variant["grade[modgrade_point]"]=config.grade_modgrade_point||"100"):variant.instructorchoiceacceptgrades="0",variant})(v))})),async function(items){const form=document.querySelector("#region-main-box form"),toolArea=form.querySelector('[data-attribute="dynamic-import"]'),buttonGroup=form.querySelector("#fgroup_id_buttonar"),submitAndLaunch=form.querySelector("#id_submitbutton");Array.from(form.children).forEach(hideElement),hideElement(submitAndLaunch);const{html:html,js:js}=await templates.renderForPromise("mod_lti/tool_deeplinking_results",{items:items});await templates.replaceNodeContents(toolArea,html,js),showElement(toolArea),showElement(buttonGroup)}(returnData.multiple);const submitAndCourse=document.querySelector("#id_submitbutton2");submitAndCourse.onclick=e=>{e.preventDefault(),submitAndCourse.disabled=!0;const fd=new FormData(document.querySelector("#region-main-box form")),backToCourse=()=>{document.querySelector("#id_cancel").click()};variants.reduce(((promise,variant)=>{Object.entries(variant).forEach((entry=>fd.set(entry[0],entry[1])));const body=new URLSearchParams(fd),doPost=()=>fetch(document.location.pathname,{method:"post",body:body});return promise.then(doPost).catch(doPost)}),Promise.resolve()).then(backToCourse).catch(backToCourse)}}else{for(index in ltiFormFields){var field=ltiFormFields[index],value=null;void 0!==returnData[field.name]&&(value=returnData[field.name]),field.setFieldValue(value)}field.setFieldValue(value),document.querySelector("#id_selectcontentindicator").innerHTML=returnData.selectcontentindicator}doneCallback&&doneCallback(returnData)},contentItem}));
//# sourceMappingURL=contentitem.min.js.map
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
/**
* Processes the result of LTI tool creation from a Content-Item message type.
*
* @module mod_lti/contentitem_return
* @copyright 2016 Jun Pataleta <jun@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.2
*/
define("mod_lti/contentitem_return",["jquery"],(function($){return{init:function(returnData){$(window).ready((function(){window!=top?parent.processContentItemReturnData(returnData):window.processContentItemReturnData(returnData)}))}}}));
//# sourceMappingURL=contentitem_return.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"contentitem_return.min.js","sources":["../src/contentitem_return.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 * Processes the result of LTI tool creation from a Content-Item message type.\n *\n * @module mod_lti/contentitem_return\n * @copyright 2016 Jun Pataleta <jun@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.2\n */\ndefine(['jquery'], function($) {\n return {\n /**\n * Init function.\n *\n * @param {string} returnData The returned data.\n */\n init: function(returnData) {\n // Make sure the window has loaded before we perform processing.\n $(window).ready(function() {\n if (window != top) {\n // Send return data to be processed by the parent window.\n parent.processContentItemReturnData(returnData);\n } else {\n window.processContentItemReturnData(returnData);\n }\n });\n }\n };\n});\n"],"names":["define","$","init","returnData","window","ready","top","parent","processContentItemReturnData"],"mappings":";;;;;;;;AAuBAA,oCAAO,CAAC,WAAW,SAASC,SACjB,CAMHC,KAAM,SAASC,YAEXF,EAAEG,QAAQC,OAAM,WACRD,QAAUE,IAEVC,OAAOC,6BAA6BL,YAEpCC,OAAOI,6BAA6BL"}
+3
View File
@@ -0,0 +1,3 @@
define("mod_lti/course_tools_list",["exports","core/notification","core/pending","core/ajax","core/toast","core/str","core_table/dynamic","core_table/local/dynamic/selectors","./repository"],(function(_exports,_notification,_pending,_ajax,_toast,_str,_dynamic,Selectors,_repository){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.init=void 0,_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending),_ajax=_interopRequireDefault(_ajax),Selectors=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}(Selectors);_exports.init=()=>{document.addEventListener("click",(event=>{const courseToolDelete=event.target.closest('[data-action="course-tool-delete"]');if(courseToolDelete){event.preventDefault();const deleteBodyStringId=courseToolDelete.dataset.courseToolUsage>0?"deletecoursetoolwithusageconfirm":"deletecoursetoolconfirm",requiredStrings=[{key:"deletecoursetool",component:"mod_lti",param:courseToolDelete.dataset.courseToolName},{key:deleteBodyStringId,component:"mod_lti",param:courseToolDelete.dataset.courseToolName},{key:"delete",component:"core",param:courseToolDelete.dataset.courseToolName},{key:"coursetooldeleted",component:"mod_lti",param:courseToolDelete.dataset.courseToolName}],triggerElement=courseToolDelete.closest(".dropdown").querySelector(".dropdown-toggle");(0,_str.getStrings)(requiredStrings).then((_ref=>{let[modalTitle,modalBody,deleteLabel]=_ref;return _notification.default.deleteCancelPromise(modalTitle,modalBody,deleteLabel,{triggerElement:triggerElement})})).then((()=>{const pendingPromise=new _pending.default("mod_lti/course_tools:delete"),request={methodname:"mod_lti_delete_course_tool_type",args:{tooltypeid:courseToolDelete.dataset.courseToolId}};return _ajax.default.call([request])[0].then((0,_toast.add)((0,_str.getString)("coursetooldeleted","mod_lti",courseToolDelete.dataset.courseToolName))).then((()=>{const tableRoot=triggerElement.closest(Selectors.main.region);return(0,_dynamic.refreshTableContent)(tableRoot)})).then(pendingPromise.resolve).catch(_notification.default.exception)})).catch((()=>{}))}const courseShowInActivityChooser=event.target.closest('[data-action="showinactivitychooser-toggle"]');if(courseShowInActivityChooser){const showInActivityChooserStateToggle="0"===courseShowInActivityChooser.dataset.state?1:0;return(0,_repository.toggleShowInActivityChooser)(courseShowInActivityChooser.dataset.id,courseShowInActivityChooser.dataset.courseid,showInActivityChooserStateToggle)}}))}}));
//# sourceMappingURL=course_tools_list.min.js.map
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
/**
* Select course categories for LTI tool.
*
* @module mod_lti/coursecategory
* @copyright 2023 Jackson D'souza <jackson.dsouza@catalyst-eu.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.3
*/
define("mod_lti/coursecategory",[],(function(){function getParents(elem){const parents=[];for(;elem&&elem!==document;elem=elem.parentNode)elem.classList.contains("accordion-group")&&parents.push(elem);return parents}return document.addEventListener("click",(event=>{const checkedbox=event.target.closest(".lticoursecategories");if(checkedbox){const checkboxstatus=checkedbox.checked,categorycontainer=document.querySelector("#collapse"+checkedbox.value);if(categorycontainer){const categorycontainercheckbox=categorycontainer.querySelectorAll('input[type="checkbox"]');for(let i=0;i<categorycontainercheckbox.length;i++)categorycontainercheckbox[i].checked=checkboxstatus}const ltitreecheckbox=document.querySelector(".modltitree").querySelectorAll('input[type="checkbox"]');let listvalue="";for(let i=0;i<ltitreecheckbox.length;i++)ltitreecheckbox[i].checked&&(listvalue=0==listvalue.length?ltitreecheckbox[i].value:listvalue+","+ltitreecheckbox[i].value);document.querySelector('input[name="lti_coursecategories"]').value=listvalue}})),{init:function(selectedcategories){if(selectedcategories.length){const separator=",",values=selectedcategories.split(separator);for(let i=0;i<values.length;i++){const categoryid=document.getElementById("cat-"+values[i]);0!==categoryid.value&&(categoryid.checked=!0);getParents(categoryid).forEach((function(element){const elem=element.querySelector("a.accordion-toggle"),elembody=element.querySelector(".accordion-body");elem&&elem.classList.contains("collapsed")&&elem.classList.remove("collapsed"),elembody&&(elembody.classList.remove("collapse"),elembody.classList.add("show"))}))}}}}}));
//# sourceMappingURL=coursecategory.min.js.map
File diff suppressed because one or more lines are too long
+13
View File
@@ -0,0 +1,13 @@
/**
* Provides a list of events that can be triggered in the LTI management
* page.
*
* @module mod_lti/events
* @class events
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define("mod_lti/events",[],(function(){return{NEW_TOOL_TYPE:"lti.tool.type.new",START_EXTERNAL_REGISTRATION:"lti.registration.external.start",STOP_EXTERNAL_REGISTRATION:"lti.registration.external.stop",START_CARTRIDGE_REGISTRATION:"lti.registration.cartridge.start",STOP_CARTRIDGE_REGISTRATION:"lti.registration.cartridge.stop",REGISTRATION_FEEDBACK:"lti.registration.feedback",CAPABILITIES_AGREE:"lti.tool.type.capabilities.agree",CAPABILITIES_DECLINE:"lti.tool.type.capabilities.decline"}}));
//# sourceMappingURL=events.min.js.map
+1
View File
@@ -0,0 +1 @@
{"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 <http://www.gnu.org/licenses/>.\n\n/**\n * Provides a list of events that can be triggered in the LTI management\n * page.\n *\n * @module mod_lti/events\n * @class events\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([], function() {\n return /** @alias module:mod_lti/events */ {\n NEW_TOOL_TYPE: 'lti.tool.type.new',\n START_EXTERNAL_REGISTRATION: 'lti.registration.external.start',\n STOP_EXTERNAL_REGISTRATION: 'lti.registration.external.stop',\n START_CARTRIDGE_REGISTRATION: 'lti.registration.cartridge.start',\n STOP_CARTRIDGE_REGISTRATION: 'lti.registration.cartridge.stop',\n REGISTRATION_FEEDBACK: 'lti.registration.feedback',\n CAPABILITIES_AGREE: 'lti.tool.type.capabilities.agree',\n CAPABILITIES_DECLINE: 'lti.tool.type.capabilities.decline',\n };\n});\n"],"names":["define","NEW_TOOL_TYPE","START_EXTERNAL_REGISTRATION","STOP_EXTERNAL_REGISTRATION","START_CARTRIDGE_REGISTRATION","STOP_CARTRIDGE_REGISTRATION","REGISTRATION_FEEDBACK","CAPABILITIES_AGREE","CAPABILITIES_DECLINE"],"mappings":";;;;;;;;;;AAyBAA,wBAAO,IAAI,iBACoC,CACvCC,cAAe,oBACfC,4BAA6B,kCAC7BC,2BAA4B,iCAC5BC,6BAA8B,mCAC9BC,4BAA6B,kCAC7BC,sBAAuB,4BACvBC,mBAAoB,mCACpBC,qBAAsB"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+14
View File
@@ -0,0 +1,14 @@
/**
* Handles the return params from the external registration page after it
* redirects back to Moodle.
*
* See also: mod/lti/externalregistrationreturn.php
*
* @module mod_lti/external_registration_return
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define("mod_lti/external_registration_return",[],(function(){return{init:function(message,error,id,status){window.parent&&window.parent.triggerExternalRegistrationComplete({message:message,error:error,id:id,status:status})}}}));
//# sourceMappingURL=external_registration_return.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"external_registration_return.min.js","sources":["../src/external_registration_return.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 * Handles the return params from the external registration page after it\n * redirects back to Moodle.\n *\n * See also: mod/lti/externalregistrationreturn.php\n *\n * @module mod_lti/external_registration_return\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([], function() {\n return {\n\n /**\n * If this was rendered in an iframe then trigger the external registration\n * complete behaviour in the parent page and provide the params returned from\n * the external registration page.\n *\n * @param {String} message The registration message from the external registration page\n * @param {String} error The registration error message from the external registration page, if\n * there was an error.\n * @param {Integer} id The tool proxy id for the external registration.\n * @param {String} status Whether the external registration was successful or not.\n */\n init: function(message, error, id, status) {\n if (window.parent) {\n window.parent.triggerExternalRegistrationComplete({\n message: message,\n error: error,\n id: id,\n status: status\n });\n }\n }\n };\n});\n"],"names":["define","init","message","error","id","status","window","parent","triggerExternalRegistrationComplete"],"mappings":";;;;;;;;;;;AA0BAA,8CAAO,IAAI,iBACA,CAaHC,KAAM,SAASC,QAASC,MAAOC,GAAIC,QAC3BC,OAAOC,QACPD,OAAOC,OAAOC,oCAAoC,CAC9CN,QAASA,QACTC,MAAOA,MACPC,GAAIA,GACJC,OAAQA"}
+11
View File
@@ -0,0 +1,11 @@
/**
* A module that enables the setting of form field values on the client side.
*
* @module mod_lti/form-field
* @copyright 2016 Jun Pataleta <jun@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.2
*/
define("mod_lti/form-field",["jquery"],(function($){var FormField=function(name,type,resetIfUndefined,defaultValue){this.name=name,this.id="id_"+this.name,this.selector="#"+this.id,this.type=type,this.resetIfUndefined=resetIfUndefined,this.defaultValue=defaultValue};return FormField.TYPES={TEXT:1,SELECT:2,CHECKBOX:3,EDITOR:4},FormField.prototype.setFieldValue=function(value){if(null===value){if(!this.resetIfUndefined)return;value=this.defaultValue}switch(this.type){case FormField.TYPES.CHECKBOX:value?$(this.selector).prop("checked",!0):$(this.selector).prop("checked",!1);break;case FormField.TYPES.EDITOR:if(void 0!==value.text){var attoEditor=$(this.selector+"editable");attoEditor.length?attoEditor.html(value.text):"undefined"!=typeof tinyMCE&&("3"==tinyMCE.majorVersion?tinyMCE.execInstanceCommand(this.id,"mceInsertContent",!1,value.text):tinyMCE.get(this.id).setContent(value.text)),$(this.selector).val(value.text)}break;default:$(this.selector).val(value)}},FormField}));
//# sourceMappingURL=form-field.min.js.map
File diff suppressed because one or more lines are too long
+12
View File
@@ -0,0 +1,12 @@
/**
* A list of keys and their keycodes that are used by the LTI modules.
*
* @module mod_lti/keys
* @class keys
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define("mod_lti/keys",[],(function(){return{ENTER:13,SPACE:32}}));
//# sourceMappingURL=keys.min.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"keys.min.js","sources":["../src/keys.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 * A list of keys and their keycodes that are used by the LTI modules.\n *\n * @module mod_lti/keys\n * @class keys\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([], function() {\n return /** @alias module:mod_lti/keys */ {\n ENTER: 13,\n SPACE: 32\n };\n});\n"],"names":["define","ENTER","SPACE"],"mappings":";;;;;;;;;AAwBAA,sBAAO,IAAI,iBACkC,CACrCC,MAAO,GACPC,MAAO"}
+3
View File
@@ -0,0 +1,3 @@
define("mod_lti/mod_form",["exports","mod_lti/contentitem"],(function(_exports,_contentitem){var obj;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_contentitem=(obj=_contentitem)&&obj.__esModule?obj:{default:obj};var _default={init:courseId=>{const contentItemButton=document.querySelector('[name="selectcontent"]');contentItemButton&&contentItemButton.addEventListener("click",(()=>{const contentItemUrl=contentItemButton.getAttribute("data-contentitemurl"),contentItemId=document.querySelector("#hidden_typeid").value;if(contentItemId){const title=document.querySelector("#id_name").value.trim(),text=document.querySelector("#id_introeditor").value.trim(),postData={id:contentItemId,course:courseId,title:title,text:text};_contentitem.default.init(contentItemUrl,postData,(returnData=>{if(!returnData.multiple){const allowGrades=document.querySelector("#id_instructorchoiceacceptgrades");let allowGradesChangeEvent=new Event("change");if(allowGrades.dispatchEvent(allowGradesChangeEvent),allowGrades.checked){const gradeType=document.querySelector("#id_grade_modgrade_type");gradeType.value="point";let gradeTypeChangeEvent=new Event("change");gradeType.dispatchEvent(gradeTypeChangeEvent)}}}))}}))}};return _exports.default=_default,_exports.default}));
//# sourceMappingURL=mod_form.min.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"mod_form.min.js","sources":["../src/mod_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 <http://www.gnu.org/licenses/>.\n\n/**\n * Event handlers for the mod_lti mod_form.\n *\n * @module mod_lti/mod_form\n * @copyright 2023 Jake Dallimore <jrhdallimore@gmail.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n\"use strict\";\n\nimport ContentItem from 'mod_lti/contentitem';\n\n/**\n * Initialise module.\n *\n * @param {int} courseId the course id.\n */\nconst init = (courseId) => {\n const contentItemButton = document.querySelector('[name=\"selectcontent\"]');\n\n if (!contentItemButton) {\n return;\n }\n\n contentItemButton.addEventListener('click', () => {\n const contentItemUrl = contentItemButton.getAttribute('data-contentitemurl');\n const contentItemId = document.querySelector('#hidden_typeid').value;\n if (contentItemId) {\n const title = document.querySelector('#id_name').value.trim();\n const text = document.querySelector('#id_introeditor').value.trim();\n const postData = {\n id: contentItemId,\n course: courseId,\n title: title,\n text: text\n };\n\n // The callback below is called after the content item has been returned and processed.\n ContentItem.init(contentItemUrl, postData, (returnData) => {\n if (!returnData.multiple) {\n // The state of the grade checkbox has already been set by processContentItemReturnData() but that\n // hasn't fired the click/change event required by formslib to show/hide the dependent grade fields.\n // Fire it now.\n const allowGrades = document.querySelector('#id_instructorchoiceacceptgrades');\n let allowGradesChangeEvent = new Event('change');\n allowGrades.dispatchEvent(allowGradesChangeEvent);\n\n // If the tool is set to accept grades, make sure \"Point\" is selected.\n if (allowGrades.checked) {\n const gradeType = document.querySelector('#id_grade_modgrade_type');\n gradeType.value = \"point\";\n let gradeTypeChangeEvent = new Event('change');\n gradeType.dispatchEvent(gradeTypeChangeEvent);\n }\n }\n });\n }\n });\n};\n\nexport default {\n init: init\n};\n"],"names":["init","courseId","contentItemButton","document","querySelector","addEventListener","contentItemUrl","getAttribute","contentItemId","value","title","trim","text","postData","id","course","returnData","multiple","allowGrades","allowGradesChangeEvent","Event","dispatchEvent","checked","gradeType","gradeTypeChangeEvent"],"mappings":"oQA2Ee,CACXA,KA5CUC,iBACJC,kBAAoBC,SAASC,cAAc,0BAE5CF,mBAILA,kBAAkBG,iBAAiB,SAAS,WAClCC,eAAiBJ,kBAAkBK,aAAa,uBAChDC,cAAgBL,SAASC,cAAc,kBAAkBK,SAC3DD,cAAe,OACTE,MAAQP,SAASC,cAAc,YAAYK,MAAME,OACjDC,KAAOT,SAASC,cAAc,mBAAmBK,MAAME,OACvDE,SAAW,CACbC,GAAIN,cACJO,OAAQd,SACRS,MAAOA,MACPE,KAAMA,2BAIEZ,KAAKM,eAAgBO,UAAWG,iBACnCA,WAAWC,SAAU,OAIhBC,YAAcf,SAASC,cAAc,wCACvCe,uBAAyB,IAAIC,MAAM,aACvCF,YAAYG,cAAcF,wBAGtBD,YAAYI,QAAS,OACfC,UAAYpB,SAASC,cAAc,2BACzCmB,UAAUd,MAAQ,YACde,qBAAuB,IAAIJ,MAAM,UACrCG,UAAUF,cAAcG"}
+10
View File
@@ -0,0 +1,10 @@
define("mod_lti/repository",["exports","core/ajax"],(function(_exports,_ajax){var obj;
/**
* Module to handle AJAX interactions.
*
* @module mod_lti/repository
* @copyright 2023 Ilya Tregubov <ilya.a.tregubov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.toggleShowInActivityChooser=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.toggleShowInActivityChooser=(tooltypeid,courseid,showinactivitychooser)=>_ajax.default.call([{methodname:"mod_lti_toggle_showinactivitychooser",args:{tooltypeid:tooltypeid,courseid:courseid,showinactivitychooser:showinactivitychooser}}])[0]}));
//# sourceMappingURL=repository.min.js.map
+1
View File
@@ -0,0 +1 @@
{"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 <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle AJAX interactions.\n *\n * @module mod_lti/repository\n * @copyright 2023 Ilya Tregubov <ilya.a.tregubov@gmail.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Toggle coursevisible of a tool\n *\n * @param {Number} tooltypeid Too type id\n * @param {Number} courseid Course ID\n * @param {Number} showinactivitychooser showinactivitychooser state\n * @return {Promise}\n */\nexport const toggleShowInActivityChooser = (\n tooltypeid,\n courseid,\n showinactivitychooser,\n) => Ajax.call([{\n methodname: 'mod_lti_toggle_showinactivitychooser',\n args: {\n tooltypeid,\n courseid,\n showinactivitychooser,\n },\n}])[0];\n"],"names":["tooltypeid","courseid","showinactivitychooser","Ajax","call","methodname","args"],"mappings":";;;;;;;kMAiC2C,CACvCA,WACAC,SACAC,wBACCC,cAAKC,KAAK,CAAC,CACZC,WAAY,uCACZC,KAAM,CACFN,WAAAA,WACAC,SAAAA,SACAC,sBAAAA,0BAEJ"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
/**
* Provides an interface for a tool proxy in the Moodle server.
*
* @module mod_lti/tool_proxy
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define("mod_lti/tool_proxy",["core/ajax","core/notification"],(function(ajax,notification){return{query:function(args){var request={methodname:"mod_lti_get_tool_proxies",args:args||{}},promise=ajax.call([request])[0];return promise.fail(notification.exception),promise},delete:function(id){var request={methodname:"mod_lti_delete_tool_proxy",args:{id:id}},promise=ajax.call([request])[0];return promise.fail(notification.exception),promise},create:function(args){var request={methodname:"mod_lti_create_tool_proxy",args:args};return ajax.call([request])[0]}}}));
//# sourceMappingURL=tool_proxy.min.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"tool_proxy.min.js","sources":["../src/tool_proxy.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 * Provides an interface for a tool proxy in the Moodle server.\n *\n * @module mod_lti/tool_proxy\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(['core/ajax', 'core/notification'], function(ajax, notification) {\n return {\n /**\n * Get a list of tool types from Moodle for the given\n * search args.\n *\n * See also:\n * mod/lti/classes/external.php get_tool_types_parameters()\n *\n * @method query\n * @public\n * @param {Object} args Search parameters\n * @return {Promise} jQuery Deferred object\n */\n query: function(args) {\n var request = {\n methodname: 'mod_lti_get_tool_proxies',\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 * Delete a tool proxy from Moodle.\n *\n * @method delete\n * @public\n * @param {Integer} id Tool proxy ID\n * @return {Promise} jQuery Deferred object\n */\n 'delete': function(id) {\n var request = {\n methodname: 'mod_lti_delete_tool_proxy',\n args: {\n id: id\n }\n };\n\n var promise = ajax.call([request])[0];\n\n promise.fail(notification.exception);\n\n return promise;\n },\n\n /**\n * Create a tool proxy in Moodle.\n *\n * The promise will fail if the proxy cannot be created, so you must handle the fail result.\n *\n * See mod/lti/classes/external.php create_tool_proxy_parameters\n *\n * @method create\n * @public\n * @param {Object} args Tool proxy properties\n * @return {Promise} jQuery Deferred object\n */\n create: function(args) {\n var request = {\n methodname: 'mod_lti_create_tool_proxy',\n args: args\n };\n\n var promise = ajax.call([request])[0];\n\n return promise;\n }\n };\n});\n"],"names":["define","ajax","notification","query","args","request","methodname","promise","call","fail","exception","id","create"],"mappings":";;;;;;;;AAuBAA,4BAAO,CAAC,YAAa,sBAAsB,SAASC,KAAMC,oBAC/C,CAaHC,MAAO,SAASC,UACRC,QAAU,CACVC,WAAY,2BACZF,KAAMA,MAAQ,IAGdG,QAAUN,KAAKO,KAAK,CAACH,UAAU,UAEnCE,QAAQE,KAAKP,aAAaQ,WAEnBH,gBAUD,SAASI,QACXN,QAAU,CACVC,WAAY,4BACZF,KAAM,CACFO,GAAIA,KAIRJ,QAAUN,KAAKO,KAAK,CAACH,UAAU,UAEnCE,QAAQE,KAAKP,aAAaQ,WAEnBH,SAeXK,OAAQ,SAASR,UACTC,QAAU,CACVC,WAAY,4BACZF,KAAMA,aAGIH,KAAKO,KAAK,CAACH,UAAU"}
+14
View File
@@ -0,0 +1,14 @@
/**
* Controls all of the behaviour and interaction with a tool type card. These are
* listed on the LTI tool type management page.
*
* See template: mod_lti/tool_proxy_card
*
* @module mod_lti/tool_proxy_card_controller
* @copyright 2016 John Okely <john@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define("mod_lti/tool_proxy_card_controller",["jquery","core/ajax","core/notification","core/templates","mod_lti/tool_proxy","mod_lti/events","mod_lti/keys","core/str"],(function($,ajax,notification,templates,toolProxy,ltiEvents,KEYS,str){var SELECTORS_DELETE_BUTTON=".delete",SELECTORS_ACTIVATE_BUTTON=".tool-card-footer a.activate",getTypeId=function(element){return element.attr("data-proxy-id")},clearAllAnnouncements=function(element){element.removeClass("announcement loading success fail capabilities")},stopLoading=function(element){element.removeClass("announcement loading")},deleteType=function(element){var promise=$.Deferred(),typeId=getTypeId(element);return function(element){clearAllAnnouncements(element),element.addClass("announcement loading")}(element),""===typeId?$.Deferred().resolve():(str.get_strings([{key:"delete",component:"mod_lti"},{key:"delete_confirmation",component:"mod_lti"},{key:"delete",component:"mod_lti"},{key:"cancel",component:"core"}]).done((function(strs){notification.confirm(strs[0],strs[1],strs[2],strs[3],(function(){toolProxy.delete(typeId).done((function(){stopLoading(element),function(element){var promise=$.Deferred();return clearAllAnnouncements(element),element.addClass("announcement success"),setTimeout((function(){element.removeClass("announcement success"),promise.resolve()}),2e3),promise}(element).done((function(){element.remove(),promise.resolve()})).fail(notification.exception)})).fail((function(error){!function(element){var promise=$.Deferred();clearAllAnnouncements(element),element.addClass("announcement fail"),setTimeout((function(){element.removeClass("announcement fail"),promise.resolve()}),2e3)}(element),promise.reject(error)}))}),(function(){stopLoading(element),promise.resolve()}))})).fail((function(error){stopLoading(element),notification.exception(error),promise.reject(error)})),promise)},registerEventListeners=function(element){var deleteButton=function(element){return element.find(SELECTORS_DELETE_BUTTON)}(element);deleteButton.click((function(e){e.preventDefault(),deleteType(element)})),deleteButton.keypress((function(e){e.metaKey||e.shiftKey||e.altKey||e.ctrlKey||e.keyCode!=KEYS.ENTER&&e.keyCode!=KEYS.SPACE||(e.preventDefault(),deleteButton.click())}));var activateButton=function(element){return element.find(SELECTORS_ACTIVATE_BUTTON)}(element);activateButton.click((function(e){e.preventDefault(),function(element){var data={proxyid:getTypeId(element)};$(document).trigger(ltiEvents.START_EXTERNAL_REGISTRATION,data)}(element)})),activateButton.keypress((function(e){e.metaKey||e.shiftKey||e.altKey||e.ctrlKey||e.keyCode!=KEYS.ENTER&&e.keyCode!=KEYS.SPACE||(e.preventDefault(),activateButton.click())}))};return{init:function(element){registerEventListeners(element)}}}));
//# sourceMappingURL=tool_proxy_card_controller.min.js.map
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
/**
* Provides an interface for a tool type in the Moodle server.
*
* @module mod_lti/tool_type
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define("mod_lti/tool_type",["core/ajax","core/notification"],(function(ajax,notification){return{query:function(args){var request={methodname:"mod_lti_get_tool_types",args:args||{}},promise=ajax.call([request])[0];return promise.fail(notification.exception),promise},create:function(args){var request={methodname:"mod_lti_create_tool_type",args:args};return ajax.call([request])[0]},update:function(args){var request={methodname:"mod_lti_update_tool_type",args:args},promise=ajax.call([request])[0];return promise.fail(notification.exception),promise},delete:function(id){var request={methodname:"mod_lti_delete_tool_type",args:{id:id}},promise=ajax.call([request])[0];return promise.fail(notification.exception),promise},getFromToolProxyId:function(id){return this.query({toolproxyid:id})},isCartridge:function(url){var request={methodname:"mod_lti_is_cartridge",args:{url:url}};return ajax.call([request])[0]},constants:{state:{configured:1,pending:2,rejected:3}}}}));
//# sourceMappingURL=tool_type.min.js.map
File diff suppressed because one or more lines are too long
+12
View File
@@ -0,0 +1,12 @@
define("mod_lti/tool_types_and_proxies",["exports","core/ajax"],(function(_exports,_ajax){var obj;
/**
* Provides an interface for external tools in the Moodle server.
*
* @module mod_lti/tool_types_and_proxies
* @class tool_types_and_proxies
* @copyright 2020 Andrew Madden <andrewmadden@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.0
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.query=_exports.count=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.query=args=>{const request={methodname:"mod_lti_get_tool_types_and_proxies",args:args||{}};return _ajax.default.call([request])[0]};_exports.count=args=>{const request={methodname:"mod_lti_get_tool_types_and_proxies_count",args:args||{}};return _ajax.default.call([request])[0]}}));
//# sourceMappingURL=tool_types_and_proxies.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"tool_types_and_proxies.min.js","sources":["../src/tool_types_and_proxies.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 * Provides an interface for external tools in the Moodle server.\n *\n * @module mod_lti/tool_types_and_proxies\n * @class tool_types_and_proxies\n * @copyright 2020 Andrew Madden <andrewmadden@catalyst-au.net>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\nimport ajax from 'core/ajax';\n\n/**\n * Get a list of LTI tool types and tool proxies from Moodle for the given\n * search args.\n *\n * See also:\n * mod/lti/classes/external.php get_tool_types_and_proxies()\n *\n * @method query\n * @public\n * @param {Object} args Search parameters\n * @return {Promise} Promise that will be resolved when the ajax call returns.\n */\nexport const query = (args) => {\n const request = {\n methodname: 'mod_lti_get_tool_types_and_proxies',\n args: args || {}\n };\n\n return ajax.call([request])[0];\n};\n\n/**\n * Get a count of LTI tool types and tool proxies from Moodle for the given\n * search args.\n *\n * See also:\n * mod/lti/classes/external.php get_tool_types_and_proxies_count()\n *\n * @method count\n * @public\n * @param {Object} args Search parameters\n * @return {Promise} Promise that will be resolved when the ajax call returns.\n */\nexport const count = (args) => {\n const request = {\n methodname: 'mod_lti_get_tool_types_and_proxies_count',\n args: args || {}\n };\n\n return ajax.call([request])[0];\n};\n"],"names":["args","request","methodname","ajax","call"],"mappings":";;;;;;;;;qKAsCsBA,aACZC,QAAU,CACZC,WAAY,qCACZF,KAAMA,MAAQ,WAGXG,cAAKC,KAAK,CAACH,UAAU,mBAeVD,aACZC,QAAU,CACZC,WAAY,2CACZF,KAAMA,MAAQ,WAGXG,cAAKC,KAAK,CAACH,UAAU"}
@@ -0,0 +1,214 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Encapsules the behavior for creating a tool type from a cartridge URL
* in Moodle. Manages the UI while operations are occuring.
*
* See template: mod_lti/cartridge_registration_form
*
* @module mod_lti/cartridge_registration_form
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define(['jquery', 'core/ajax', 'core/notification', 'mod_lti/tool_type', 'mod_lti/events', 'mod_lti/keys', 'core/str'],
function($, ajax, notification, toolType, ltiEvents, KEYS, str) {
var SELECTORS = {
CARTRIDGE_URL: '#cartridge-url',
CONSUMER_KEY: '#registration-key',
SHARED_SECRET: '#registration-secret',
REGISTRATION_FORM: '#cartridge-registration-form',
REGISTRATION_SUBMIT_BUTTON: '#cartridge-registration-submit',
REGISTRATION_CANCEL_BUTTON: '#cartridge-registration-cancel',
};
/**
* Return the URL the user entered for the cartridge.
*
* @method getCartridgeURL
* @private
* @return {String}
*/
var getCartridgeURL = function() {
return $(SELECTORS.REGISTRATION_FORM).attr('data-cartridge-url');
};
/**
* Return the submit button element.
*
* @method getSubmitButton
* @private
* @return {JQuery} jQuery object
*/
var getSubmitButton = function() {
return $(SELECTORS.REGISTRATION_SUBMIT_BUTTON);
};
/**
* Return the cancel button element.
*
* @method getCancelButton
* @private
* @return {JQuery} jQuery object
*/
var getCancelButton = function() {
return $(SELECTORS.REGISTRATION_CANCEL_BUTTON);
};
/**
* Return the value that the user entered for the consumer key.
*
* @method getConsumerKey
* @private
* @return {String} the value entered for consumer key.
*/
var getConsumerKey = function() {
return $(SELECTORS.CONSUMER_KEY).val();
};
/**
* Return the value that the user entered for the shared secret.
*
* @method getSharedSecret
* @private
* @return {String} the value entered for shared secret
*/
var getSharedSecret = function() {
return $(SELECTORS.SHARED_SECRET).val();
};
/**
* Trigger a visual loading indicator.
*
* @method startLoading
* @private
*/
var startLoading = function() {
getSubmitButton().addClass('loading');
};
/**
* Stop the visual loading indicator.
*
* @method stopLoading
* @private
*/
var stopLoading = function() {
getSubmitButton().removeClass('loading');
};
/**
* Check if the page is currently loading.
*
* @method isLoading
* @private
* @return {Boolean}
*/
var isLoading = function() {
return getSubmitButton().hasClass('loading');
};
/**
* Create a tool type from the cartridge URL that the user input. This will
* send an ajax request to the Moodle server to create the Type. The request will
* include the consumer key and secret, if any.
*
* On success the page will be re-rendered to take the user back to the original
* page with the list of tools and an alert notifying them of success.
*
* @method submitCartridgeURL
* @private
* @return {Promise} jQuery Deferred object
*/
var submitCartridgeURL = function() {
if (isLoading()) {
return false;
}
var url = getCartridgeURL();
// No URL? Do nothing.
if (url === "") {
return false;
}
startLoading();
var consumerKey = getConsumerKey();
var sharedSecret = getSharedSecret();
var promise = toolType.create({cartridgeurl: url, key: consumerKey, secret: sharedSecret});
promise.done(function() {
str.get_string('successfullycreatedtooltype', 'mod_lti').done(function(s) {
$(document).trigger(ltiEvents.NEW_TOOL_TYPE);
$(document).trigger(ltiEvents.STOP_CARTRIDGE_REGISTRATION);
$(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, {
message: s
});
}).fail(notification.exception);
}).fail(function() {
str.get_string('failedtocreatetooltype', 'mod_lti').done(function(s) {
$(document).trigger(ltiEvents.NEW_TOOL_TYPE);
$(document).trigger(ltiEvents.STOP_CARTRIDGE_REGISTRATION);
$(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, {
message: s,
error: true
});
}).fail(notification.exception);
}).always(function() {
stopLoading();
});
return promise;
};
/**
* Sets up the listeners for user interaction on the page.
*
* @method registerEventListeners
* @private
*/
var registerEventListeners = function() {
var form = $(SELECTORS.REGISTRATION_FORM);
form.submit(function(e) {
e.preventDefault();
submitCartridgeURL();
});
var cancelButton = getCancelButton();
cancelButton.click(function(e) {
e.preventDefault();
$(document).trigger(ltiEvents.STOP_CARTRIDGE_REGISTRATION);
});
cancelButton.keypress(function(e) {
if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {
if (e.keyCode == KEYS.ENTER || e.keyCode == KEYS.SPACE) {
e.preventDefault();
cancelButton.click();
}
}
});
};
return /** @alias module:mod_lti/cartridge_registration_form */ {
/**
* Initialise this module.
*/
init: function() {
registerEventListeners();
}
};
});
+243
View File
@@ -0,0 +1,243 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Launches the modal dialogue that contains the iframe that sends the Content-Item selection request to an
* LTI tool provider that supports Content-Item type message.
*
* See template: mod_lti/contentitem
*
* @module mod_lti/contentitem
* @copyright 2016 Jun Pataleta <jun@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.2
*/
define(
[
'jquery',
'core/notification',
'core/str',
'core/templates',
'mod_lti/form-field',
'core/modal',
'core/modal_events'
],
function($, notification, str, templates, FormField, Modal, ModalEvents) {
var dialogue;
var doneCallback;
var contentItem = {
/**
* Init function.
*
* @param {string} url The URL for the content item selection.
* @param {object} postData The data to be sent for the content item selection request.
* @param {Function} cb The callback to run once the content item has been processed.
*/
init: function(url, postData, cb) {
doneCallback = cb;
var context = {
url: url,
postData: postData
};
var bodyPromise = templates.render('mod_lti/contentitem', context);
if (dialogue) {
// Set dialogue body.
dialogue.setBody(bodyPromise);
// Display the dialogue.
dialogue.show();
return;
}
str.get_string('selectcontent', 'lti').then(function(title) {
return Modal.create({
title: title,
body: bodyPromise,
large: true,
show: true,
});
}).then(function(modal) {
dialogue = modal;
// On hide handler.
modal.getRoot().on(ModalEvents.hidden, function() {
// Empty modal contents when it's hidden.
modal.setBody('');
// Fetch notifications.
notification.fetchNotifications();
});
return;
}).catch(notification.exception);
}
};
/**
* Array of form fields for LTI tool configuration.
*/
var ltiFormFields = [
new FormField('name', FormField.TYPES.TEXT, false, ''),
new FormField('introeditor', FormField.TYPES.EDITOR, false, ''),
new FormField('toolurl', FormField.TYPES.TEXT, true, ''),
new FormField('securetoolurl', FormField.TYPES.TEXT, true, ''),
new FormField('instructorchoiceacceptgrades', FormField.TYPES.CHECKBOX, true, true),
new FormField('instructorchoicesendname', FormField.TYPES.CHECKBOX, true, true),
new FormField('instructorchoicesendemailaddr', FormField.TYPES.CHECKBOX, true, true),
new FormField('instructorcustomparameters', FormField.TYPES.TEXT, true, ''),
new FormField('icon', FormField.TYPES.TEXT, true, ''),
new FormField('secureicon', FormField.TYPES.TEXT, true, ''),
new FormField('launchcontainer', FormField.TYPES.SELECT, true, 0),
new FormField('grade_modgrade_point', FormField.TYPES.TEXT, false, ''),
new FormField('lineitemresourceid', FormField.TYPES.TEXT, true, ''),
new FormField('lineitemtag', FormField.TYPES.TEXT, true, ''),
new FormField('lineitemsubreviewurl', FormField.TYPES.TEXT, true, ''),
new FormField('lineitemsubreviewparams', FormField.TYPES.TEXT, true, '')
];
/**
* Hide the element, including aria and tab index.
* @param {HTMLElement} e the element to be hidden.
*/
const hideElement = (e) => {
e.setAttribute('hidden', 'true');
e.setAttribute('aria-hidden', 'true');
e.setAttribute('tab-index', '-1');
};
/**
* Show the element, including aria and tab index (set to 1).
* @param {HTMLElement} e the element to be shown.
*/
const showElement = (e) => {
e.removeAttribute('hidden');
e.setAttribute('aria-hidden', 'false');
e.setAttribute('tab-index', '1');
};
/**
* When more than one item needs to be added, the UI is simplified
* to just list the items to be added. Form is hidden and the only
* options is (save and return to course) or cancel.
* This function injects the summary to the form page, and hides
* the unneeded elements.
* @param {Object[]} items items to be added to the course.
*/
const showMultipleSummaryAndHideForm = async function(items) {
const form = document.querySelector('#region-main-box form');
const toolArea = form.querySelector('[data-attribute="dynamic-import"]');
const buttonGroup = form.querySelector('#fgroup_id_buttonar');
const submitAndLaunch = form.querySelector('#id_submitbutton');
Array.from(form.children).forEach(hideElement);
hideElement(submitAndLaunch);
const {html, js} = await templates.renderForPromise('mod_lti/tool_deeplinking_results',
{items: items});
await templates.replaceNodeContents(toolArea, html, js);
showElement(toolArea);
showElement(buttonGroup);
};
/**
* Transforms config values aimed at populating the lti mod form to JSON variant
* which are used to insert more than one activity modules in one submit
* by applying variation to the submitted form.
* See /course/modedit.php.
* @private
* @param {Object} config transforms a config to an actual form data to be posted.
* @return {Object} variant that will be used to modify form values on submit.
*/
var configToVariant = (config) => {
const variant = {};
['name', 'toolurl', 'securetoolurl', 'instructorcustomparameters', 'icon', 'secureicon',
'launchcontainer', 'lineitemresourceid', 'lineitemtag', 'lineitemsubreviewurl',
'lineitemsubreviewparams'].forEach(
function(name) {
variant[name] = config[name] || '';
}
);
variant['introeditor[text]'] = config.introeditor ? config.introeditor.text : '';
variant['introeditor[format]'] = config.introeditor ? config.introeditor.format : '';
if (config.instructorchoiceacceptgrades === 1) {
variant.instructorchoiceacceptgrades = '1';
variant['grade[modgrade_point]'] = config.grade_modgrade_point || '100';
} else {
variant.instructorchoiceacceptgrades = '0';
}
return variant;
};
/**
* Window function that can be called from mod_lti/contentitem_return to close the dialogue and process the return data.
* If the return data contains more than one item, the form will not be populated with item data
* but rather hidden, and the item data will be added to a single input field used to create multiple
* instances in one request.
*
* @param {object} returnData The fetched configuration data from the Content-Item selection dialogue.
*/
window.processContentItemReturnData = function(returnData) {
if (dialogue) {
dialogue.hide();
}
var index;
if (returnData.multiple) {
for (index in ltiFormFields) {
// Name is required, so putting a placeholder as it will not be used
// in multi-items add.
ltiFormFields[index].setFieldValue(ltiFormFields[index].name === 'name' ? 'item' : null);
}
var variants = [];
returnData.multiple.forEach(function(v) {
variants.push(configToVariant(v));
});
showMultipleSummaryAndHideForm(returnData.multiple);
const submitAndCourse = document.querySelector('#id_submitbutton2');
submitAndCourse.onclick = (e) => {
e.preventDefault();
submitAndCourse.disabled = true;
const fd = new FormData(document.querySelector('#region-main-box form'));
const postVariant = (promise, variant) => {
Object.entries(variant).forEach((entry) => fd.set(entry[0], entry[1]));
const body = new URLSearchParams(fd);
const doPost = () => fetch(document.location.pathname, {method: 'post', body});
return promise.then(doPost).catch(doPost);
};
const backToCourse = () => {
document.querySelector("#id_cancel").click();
};
variants.reduce(postVariant, Promise.resolve()).then(backToCourse).catch(backToCourse);
};
} else {
// Populate LTI configuration fields from return data.
for (index in ltiFormFields) {
var field = ltiFormFields[index];
var value = null;
if (typeof returnData[field.name] !== 'undefined') {
value = returnData[field.name];
}
field.setFieldValue(value);
}
field.setFieldValue(value);
// Update the UI element which signifies content has been selected.
document.querySelector("#id_selectcontentindicator").innerHTML = returnData.selectcontentindicator;
}
if (doneCallback) {
doneCallback(returnData);
}
};
return contentItem;
}
);
+43
View File
@@ -0,0 +1,43 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Processes the result of LTI tool creation from a Content-Item message type.
*
* @module mod_lti/contentitem_return
* @copyright 2016 Jun Pataleta <jun@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.2
*/
define(['jquery'], function($) {
return {
/**
* Init function.
*
* @param {string} returnData The returned data.
*/
init: function(returnData) {
// Make sure the window has loaded before we perform processing.
$(window).ready(function() {
if (window != top) {
// Send return data to be processed by the parent window.
parent.processContentItemReturnData(returnData);
} else {
window.processContentItemReturnData(returnData);
}
});
}
};
});
+93
View File
@@ -0,0 +1,93 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Course LTI External tools list management.
*
* @module mod_lti/course_tools_list
* @copyright 2023 Jake Dallimore <jrhdallimore@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
import Notification from 'core/notification';
import Pending from 'core/pending';
import Ajax from 'core/ajax';
import {add as addToast} from 'core/toast';
import {getString, getStrings} from 'core/str';
import {refreshTableContent} from 'core_table/dynamic';
import * as Selectors from 'core_table/local/dynamic/selectors';
import {toggleShowInActivityChooser} from "./repository";
/**
* Initialise module.
*/
export const init = () => {
document.addEventListener('click', event => {
const courseToolDelete = event.target.closest('[data-action="course-tool-delete"]');
if (courseToolDelete) {
event.preventDefault();
// A different message is used in the modal if the tool has usages within the course.
const usage = courseToolDelete.dataset.courseToolUsage;
const deleteBodyStringId = usage > 0 ? 'deletecoursetoolwithusageconfirm' : 'deletecoursetoolconfirm';
const requiredStrings = [
{key: 'deletecoursetool', component: 'mod_lti', param: courseToolDelete.dataset.courseToolName},
{key: deleteBodyStringId, component: 'mod_lti', param: courseToolDelete.dataset.courseToolName},
{key: 'delete', component: 'core', param: courseToolDelete.dataset.courseToolName},
{key: 'coursetooldeleted', component: 'mod_lti', param: courseToolDelete.dataset.courseToolName}
];
// Use triggerElement to return focus to the action menu toggle.
const triggerElement = courseToolDelete.closest('.dropdown').querySelector('.dropdown-toggle');
getStrings(requiredStrings).then(([modalTitle, modalBody, deleteLabel]) => {
return Notification.deleteCancelPromise(
modalTitle,
modalBody,
deleteLabel,
{triggerElement});
}).then(() => {
const pendingPromise = new Pending('mod_lti/course_tools:delete');
const request = {
methodname: 'mod_lti_delete_course_tool_type',
args: {tooltypeid: courseToolDelete.dataset.courseToolId}
};
return Ajax.call([request])[0]
.then(addToast(getString('coursetooldeleted', 'mod_lti', courseToolDelete.dataset.courseToolName)))
.then(() => {
const tableRoot = triggerElement.closest(Selectors.main.region);
return refreshTableContent(tableRoot);
})
.then(pendingPromise.resolve)
.catch(Notification.exception);
}).catch(() => {
return;
});
}
const courseShowInActivityChooser = event.target.closest('[data-action="showinactivitychooser-toggle"]');
if (courseShowInActivityChooser) {
const showInActivityChooserStateToggle = courseShowInActivityChooser.dataset.state === "0" ? 1 : 0;
return toggleShowInActivityChooser(
courseShowInActivityChooser.dataset.id,
courseShowInActivityChooser.dataset.courseid,
showInActivityChooserStateToggle,
);
}
});
};
+118
View File
@@ -0,0 +1,118 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Select course categories for LTI tool.
*
* @module mod_lti/coursecategory
* @copyright 2023 Jackson D'souza <jackson.dsouza@catalyst-eu.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.3
*/
define([], function() {
document.addEventListener('click', event => {
const checkedbox = event.target.closest(".lticoursecategories");
if (checkedbox) {
// Get checkbox status.
const checkboxstatus = checkedbox.checked;
// Check / Uncheck all child category checkboxes based on selected checkbox status.
const categorycontainer = document.querySelector('#collapse' + checkedbox.value);
if (categorycontainer) {
const categorycontainercheckbox = categorycontainer.querySelectorAll('input[type="checkbox"]');
for (let i = 0; i < categorycontainercheckbox.length; i++) {
categorycontainercheckbox[i].checked = checkboxstatus;
}
}
const lticategorytree = document.querySelector('.modltitree');
const ltitreecheckbox = lticategorytree.querySelectorAll('input[type="checkbox"]');
let listvalue = '';
for (let i = 0; i < ltitreecheckbox.length; i++) {
if (ltitreecheckbox[i].checked) {
if (listvalue.length == 0) {
listvalue = ltitreecheckbox[i].value;
} else {
listvalue = listvalue + ',' + ltitreecheckbox[i].value;
}
}
}
document.querySelector('input[name="lti_coursecategories"]').value = listvalue;
}
});
/**
* Get parent elements with class = accordion.
*
* @method getParents
* @private
* @param {string} elem DOM element.
* @return {array} Parent elements.
*/
function getParents(elem) {
// Set up a parent array
const parents = [];
// Push each parent element to the array
for (; elem && elem !== document; elem = elem.parentNode) {
if (elem.classList.contains('accordion-group')) {
parents.push(elem);
}
}
// Return our parent array
return parents;
}
return /** @alias module:mod_lti/coursecategory */ {
/**
* Initialise this module.
* Loop through checkbox form elements starting with #cat-{N} and set it to checked
* if {N} is found in the Selected category(s) list. Show / Hide the parent UL element.
*
* @param {string} selectedcategories Selected category(s).
*/
init: function(selectedcategories) {
if (selectedcategories.length) {
const separator = ",";
const values = selectedcategories.split(separator);
for (let i = 0; i < values.length; i++) {
const categoryid = document.getElementById("cat-" + values[i]);
if (categoryid.value !== 0) {
categoryid.checked = true;
}
const parents = getParents(categoryid);
parents.forEach(function(element) {
const elem = element.querySelector('a.accordion-toggle');
const elembody = element.querySelector('.accordion-body');
if (elem && elem.classList.contains('collapsed')) {
elem.classList.remove('collapsed');
}
if (elembody) {
elembody.classList.remove('collapse');
elembody.classList.add('show');
}
});
}
}
}
};
});
+37
View File
@@ -0,0 +1,37 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Provides a list of events that can be triggered in the LTI management
* page.
*
* @module mod_lti/events
* @class events
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define([], function() {
return /** @alias module:mod_lti/events */ {
NEW_TOOL_TYPE: 'lti.tool.type.new',
START_EXTERNAL_REGISTRATION: 'lti.registration.external.start',
STOP_EXTERNAL_REGISTRATION: 'lti.registration.external.stop',
START_CARTRIDGE_REGISTRATION: 'lti.registration.cartridge.start',
STOP_CARTRIDGE_REGISTRATION: 'lti.registration.cartridge.stop',
REGISTRATION_FEEDBACK: 'lti.registration.feedback',
CAPABILITIES_AGREE: 'lti.tool.type.capabilities.agree',
CAPABILITIES_DECLINE: 'lti.tool.type.capabilities.decline',
};
});
+639
View File
@@ -0,0 +1,639 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Encapsules the behavior for creating a tool type and tool proxy from a
* registration url in Moodle.
*
* Manages the UI while operations are occuring, including rendering external
* registration page within the iframe.
*
* See template: mod_lti/external_registration
*
* @module mod_lti/external_registration
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/events',
'mod_lti/tool_proxy', 'mod_lti/tool_type', 'mod_lti/keys', 'core/str'],
function($, ajax, notification, templates, ltiEvents, toolProxy, toolType, KEYS, str) {
var SELECTORS = {
EXTERNAL_REGISTRATION_CONTAINER: '#external-registration-page-container',
EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER: '#external-registration-template-container',
EXTERNAL_REGISTRATION_CANCEL_BUTTON: '#cancel-external-registration',
TOOL_TYPE_CAPABILITIES_CONTAINER: '#tool-type-capabilities-container',
TOOL_TYPE_CAPABILITIES_TEMPLATE_CONTAINER: '#tool-type-capabilities-template-container',
CAPABILITIES_AGREE_CONTAINER: '.capabilities-container',
};
/**
* Return the external registration cancel button element. This button is
* the cancel button that appears while the iframe is rendered.
*
* @method getExternalRegistrationCancelButton
* @private
* @return {JQuery} jQuery object
*/
var getExternalRegistrationCancelButton = function() {
return $(SELECTORS.EXTERNAL_REGISTRATION_CANCEL_BUTTON);
};
/**
* Return the container that holds all elements for the external registration, including
* the cancel button and the iframe.
*
* @method getExternalRegistrationContainer
* @private
* @return {JQuery} jQuery object
*/
var getExternalRegistrationContainer = function() {
return $(SELECTORS.EXTERNAL_REGISTRATION_CONTAINER);
};
/**
* Return the container that holds the external registration page template. It should
* be the iframe.
*
* @method getExternalRegistrationTemplateContainer
* @private
* @return {JQuery} jQuery object
*/
var getExternalRegistrationTemplateContainer = function() {
return $(SELECTORS.EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER);
};
/**
* Return the container that holds the elements for displaying the list of capabilities
* that this tool type requires. This container wraps the loading indicator and the template
* container.
*
* @method getToolTypeCapabilitiesContainer
* @private
* @return {JQuery} jQuery object
*/
var getToolTypeCapabilitiesContainer = function() {
return $(SELECTORS.TOOL_TYPE_CAPABILITIES_CONTAINER);
};
/**
* Return the container that holds the template that lists the capabilities that the
* tool type will require.
*
* @method getToolTypeCapabilitiesTemplateContainer
* @private
* @return {JQuery} jQuery object
*/
var getToolTypeCapabilitiesTemplateContainer = function() {
return $(SELECTORS.TOOL_TYPE_CAPABILITIES_TEMPLATE_CONTAINER);
};
/**
* Triggers a visual indicator to show that the capabilities section is loading.
*
* @method startLoadingCapabilitiesContainer
* @private
*/
var startLoadingCapabilitiesContainer = function() {
getToolTypeCapabilitiesContainer().addClass('loading');
};
/**
* Removes the visual indicator that shows the capabilities section is loading.
*
* @method stopLoadingCapabilitiesContainer
* @private
*/
var stopLoadingCapabilitiesContainer = function() {
getToolTypeCapabilitiesContainer().removeClass('loading');
};
/**
* Adds a visual indicator that shows the cancel button is loading.
*
* @method startLoadingCancel
* @private
*/
var startLoadingCancel = function() {
getExternalRegistrationCancelButton().addClass('loading');
};
/**
* Adds a visual indicator that shows the cancel button is loading.
*
* @method startLoadingCancel
* @private
*/
var stopLoadingCancel = function() {
getExternalRegistrationCancelButton().removeClass('loading');
};
/**
* Stops displaying the tool type capabilities container.
*
* @method hideToolTypeCapabilitiesContainer
* @private
*/
var hideToolTypeCapabilitiesContainer = function() {
getToolTypeCapabilitiesContainer().addClass('hidden');
};
/**
* Displays the tool type capabilities container.
*
* @method showToolTypeCapabilitiesContainer
* @private
*/
var showToolTypeCapabilitiesContainer = function() {
getToolTypeCapabilitiesContainer().removeClass('hidden');
};
/**
* Stops displaying the external registration content.
*
* @method hideExternalRegistrationContent
* @private
*/
var hideExternalRegistrationContent = function() {
getExternalRegistrationContainer().addClass('hidden');
};
/**
* Displays the external registration content.
*
* @method showExternalRegistrationContent
* @private
*/
var showExternalRegistrationContent = function() {
getExternalRegistrationContainer().removeClass('hidden');
};
/**
* Save the given tool proxy id on the DOM.
*
* @method setToolProxyId
* @private
* @param {Integer} id Tool proxy ID
*/
var setToolProxyId = function(id) {
var button = getExternalRegistrationCancelButton();
button.attr('data-tool-proxy-id', id);
};
/**
* Return the saved tool proxy id.
*
* @method getToolProxyId
* @private
* @return {String} Tool proxy ID
*/
var getToolProxyId = function() {
var button = getExternalRegistrationCancelButton();
return button.attr('data-tool-proxy-id');
};
/**
* Remove the saved tool proxy id.
*
* @method clearToolProxyId
* @private
*/
var clearToolProxyId = function() {
var button = getExternalRegistrationCancelButton();
button.removeAttr('data-tool-proxy-id');
};
/**
* Returns true if a tool proxy id has been recorded.
*
* @method hasToolProxyId
* @private
* @return {Boolean}
*/
var hasToolProxyId = function() {
return getToolProxyId() ? true : false;
};
/**
* Checks if this process has created a tool proxy within
* Moodle yet.
*
* @method hasCreatedToolProxy
* @private
* @return {Boolean}
*/
var hasCreatedToolProxy = function() {
var button = getExternalRegistrationCancelButton();
return button.attr('data-tool-proxy-new') && hasToolProxyId();
};
/**
* Records that this process has created a tool proxy.
*
* @method setProxyAsNew
* @private
* @return {Boolean}
*/
var setProxyAsNew = function() {
var button = getExternalRegistrationCancelButton();
return button.attr('data-tool-proxy-new', "new");
};
/**
* Records that this process has not created a tool proxy.
*
* @method setProxyAsOld
* @private
* @return {Boolean}
*/
var setProxyAsOld = function() {
var button = getExternalRegistrationCancelButton();
return button.removeAttr('data-tool-proxy-new');
};
/**
* Gets the external registration request required to be sent to the external
* registration page using a form.
*
* See mod_lti/tool_proxy_registration_form template.
*
* @method getRegistrationRequest
* @private
* @param {Integer} id Tool Proxy ID
* @return {Promise} jQuery Deferred object
*/
var getRegistrationRequest = function(id) {
var request = {
methodname: 'mod_lti_get_tool_proxy_registration_request',
args: {
id: id
}
};
return ajax.call([request])[0];
};
/**
* Cancel an in progress external registration. This will perform any necessary
* clean up of tool proxies and return the page section back to the home section.
*
* @method cancelRegistration
* @private
* @return {Promise} jQuery Deferred object
*/
var cancelRegistration = function() {
startLoadingCancel();
var promise = $.Deferred();
// If we've created a proxy as part of this process then
// we need to delete it to clean up the data in the back end.
if (hasCreatedToolProxy()) {
var id = getToolProxyId();
toolProxy.delete(id).done(function() {
promise.resolve();
}).fail(function(failure) {
promise.reject(failure);
});
} else {
promise.resolve();
}
promise.done(function() {
// Return to the original page.
finishExternalRegistration();
stopLoadingCancel();
}).fail(function(failure) {
notification.exception(failure);
finishExternalRegistration();
stopLoadingCancel();
str.get_string('failedtodeletetoolproxy', 'mod_lti').done(function(s) {
var feedback = {
message: s,
error: true
};
$(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, feedback);
}).fail(notification.exception);
});
return promise;
};
/**
* Load the external registration template and render it in the DOM and display it.
*
* @method renderExternalRegistrationWindow
* @private
* @param {Object} registrationRequest
* @return {Promise} jQuery Deferred object
*/
var renderExternalRegistrationWindow = function(registrationRequest) {
var promise = templates.render('mod_lti/tool_proxy_registration_form', registrationRequest);
promise.done(function(html, js) {
// Show the external registration page in an iframe.
var container = getExternalRegistrationTemplateContainer();
container.append(html);
templates.runTemplateJS(js);
container.find('form').submit();
showExternalRegistrationContent();
}).fail(notification.exception);
return promise;
};
/**
* Send a request to Moodle server to set the state of the tool type to configured (active).
*
* @method setTypeStatusActive
* @private
* @param {Object} typeData A set of data representing a type, as returned by a request to get a type
* from the Moodle server.
* @return {Promise} jQuery Deferred object
*/
var setTypeStatusActive = function(typeData) {
return toolType.update({
id: typeData.id,
state: toolType.constants.state.configured
});
};
/**
* Render and display an agreement page for the user to acknowledge the list of capabilities
* (groups of data) that the external tool requires in order to work. If the user agrees then
* we will activate the tool so that it is immediately available. If they don't agree then
* the tool remains in a pending state within Moodle until agreement is given.
*
* @method promptForToolTypeCapabilitiesAgreement
* @private
* @param {Object} typeData A set of data representing a type, as returned by a request to get a type
* from the Moodle server.
* @return {Promise} jQuery Deferred object
*/
var promptForToolTypeCapabilitiesAgreement = function(typeData) {
var promise = $.Deferred();
templates.render('mod_lti/tool_type_capabilities_agree', typeData).done(function(html, js) {
var container = getToolTypeCapabilitiesTemplateContainer();
hideExternalRegistrationContent();
showToolTypeCapabilitiesContainer();
templates.replaceNodeContents(container, html, js);
var choiceContainer = container.find(SELECTORS.CAPABILITIES_AGREE_CONTAINER);
// The user agrees to allow the tool to use the groups of data so we can go
// ahead and activate it for them so that it can be used straight away.
choiceContainer.on(ltiEvents.CAPABILITIES_AGREE, function() {
startLoadingCapabilitiesContainer();
setTypeStatusActive(typeData).always(function() {
stopLoadingCapabilitiesContainer();
container.empty();
promise.resolve();
});
});
// The user declines to let the tool use the data. In this case we leave
// the tool as pending and they can delete it using the main screen if they
// wish.
choiceContainer.on(ltiEvents.CAPABILITIES_DECLINE, function() {
container.empty();
promise.resolve();
});
}).fail(promise.reject);
promise.done(function() {
hideToolTypeCapabilitiesContainer();
}).fail(notification.exception);
return promise;
};
/**
* Send a request to the Moodle server to create a tool proxy using the registration URL the user
* has provided. The proxy is required for the external registration page to work correctly.
*
* After the proxy is created the external registration page is rendered within an iframe for the user
* to complete the registration in the external page.
*
* If the tool proxy creation fails then we redirect the page section back to the home section and
* display the error, rather than rendering the external registration page.
*
* @method createAndRegisterToolProxy
* @private
* @param {String} url Tool registration URL to register
* @return {Promise} jQuery Deferred object
*/
var createAndRegisterToolProxy = function(url) {
var promise = $.Deferred();
if (!url || url === "") {
// No URL has been input so do nothing.
promise.resolve();
} else {
// A tool proxy needs to exist before the external page is rendered because
// the external page sends requests back to Moodle for information that is stored
// in the proxy.
toolProxy.create({regurl: url})
.done(function(result) {
// Note that it's a new proxy so we will always clean it up.
setProxyAsNew();
promise = registerProxy(result.id);
})
.fail(function(exception) {
// Clean up.
cancelRegistration();
// Let the user know what the error is.
var feedback = {
message: exception.message,
error: true
};
$(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, feedback);
promise.reject(exception);
});
}
return promise;
};
/**
* Loads the window to register a proxy, given an ID.
*
* @method registerProxy
* @private
* @param {Integer} id Proxy id to register
* @return {Promise} jQuery Deferred object to fail or resolve
*/
var registerProxy = function(id) {
var promise = $.Deferred();
// Save the id on the DOM to cleanup later.
setToolProxyId(id);
// There is a specific set of data needed to send to the external registration page
// in a form, so let's get it from our server.
getRegistrationRequest(id)
.done(function(registrationRequest) {
renderExternalRegistrationWindow(registrationRequest)
.done(function() {
promise.resolve();
})
.fail(promise.fail);
})
.fail(promise.fail);
return promise;
};
/**
* Complete the registration process, clean up any left over data and
* trigger the appropriate events.
*
* @method finishExternalRegistration
* @private
*/
var finishExternalRegistration = function() {
if (hasToolProxyId()) {
clearToolProxyId();
}
setProxyAsOld(false);
hideExternalRegistrationContent();
var container = getExternalRegistrationTemplateContainer();
container.empty();
$(document).trigger(ltiEvents.STOP_EXTERNAL_REGISTRATION);
};
/**
* Sets up the listeners for user interaction on the page.
*
* @method registerEventListeners
* @private
*/
var registerEventListeners = function() {
$(document).on(ltiEvents.START_EXTERNAL_REGISTRATION, function(event, data) {
if (!data) {
return;
}
if (data.url) {
createAndRegisterToolProxy(data.url);
}
if (data.proxyid) {
registerProxy(data.proxyid);
}
});
var cancelExternalRegistrationButton = getExternalRegistrationCancelButton();
cancelExternalRegistrationButton.click(function(e) {
e.preventDefault();
cancelRegistration();
});
cancelExternalRegistrationButton.keypress(function(e) {
if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {
if (e.keyCode == KEYS.ENTER || e.keyCode == KEYS.SPACE) {
e.preventDefault();
cancelRegistration();
}
}
});
// This is gross but necessary due to isolated jQuery scopes between
// child iframe and parent windows. There is no other way to communicate.
//
// This function gets called by the moodle page that received the redirect
// from the external registration page and handles the external page's returned
// parameters.
//
// See AMD module mod_lti/external_registration_return.
window.triggerExternalRegistrationComplete = function(data) {
var promise = $.Deferred();
var feedback = {
message: "",
error: false
};
if (data.status == "success") {
str.get_string('successfullycreatedtooltype', 'mod_lti').done(function(s) {
feedback.message = s;
}).fail(notification.exception);
// Trigger appropriate events when we've completed the necessary requests.
promise.done(function() {
finishExternalRegistration();
$(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, feedback);
$(document).trigger(ltiEvents.NEW_TOOL_TYPE);
}).fail(notification.exception);
// We should have created a tool proxy by this point.
if (hasCreatedToolProxy()) {
var proxyId = getToolProxyId();
// We need the list of types that are linked to this proxy. We're assuming it'll
// only be one because this process creates a one-to-one type->proxy.
toolType.getFromToolProxyId(proxyId).done(function(types) {
if (types && types.length) {
// There should only be one result.
var typeData = types[0];
// Check if the external tool required access to any Moodle data (users, courses etc).
if (typeData.hascapabilitygroups) {
// If it did then we ask the user to agree to those groups before the type is
// activated (i.e. can be used in Moodle).
promptForToolTypeCapabilitiesAgreement(typeData).always(function() {
promise.resolve();
});
} else {
promise.resolve();
}
} else {
promise.resolve();
}
}).fail(function() {
promise.resolve();
});
}
} else {
// Anything other than success is failure.
feedback.message = data.error;
feedback.error = true;
// Cancel registration to clean up any proxies and tools that were
// created.
promise.done(function() {
cancelRegistration().always(function() {
$(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, feedback);
});
}).fail(notification.exception);
promise.resolve();
}
return promise;
};
};
return {
/**
* Initialise this module.
*/
init: function() {
registerEventListeners();
}
};
});
@@ -0,0 +1,52 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Handles the return params from the external registration page after it
* redirects back to Moodle.
*
* See also: mod/lti/externalregistrationreturn.php
*
* @module mod_lti/external_registration_return
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define([], function() {
return {
/**
* If this was rendered in an iframe then trigger the external registration
* complete behaviour in the parent page and provide the params returned from
* the external registration page.
*
* @param {String} message The registration message from the external registration page
* @param {String} error The registration error message from the external registration page, if
* there was an error.
* @param {Integer} id The tool proxy id for the external registration.
* @param {String} status Whether the external registration was successful or not.
*/
init: function(message, error, id, status) {
if (window.parent) {
window.parent.triggerExternalRegistrationComplete({
message: message,
error: error,
id: id,
status: status
});
}
}
};
});
+111
View File
@@ -0,0 +1,111 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* A module that enables the setting of form field values on the client side.
*
* @module mod_lti/form-field
* @copyright 2016 Jun Pataleta <jun@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.2
*/
define(['jquery'],
function($) {
/**
* Form field class.
*
* @param {string} name Field name.
* @param {number} type The field type.
* @param {boolean} resetIfUndefined Flag to reset the field to the default value if undefined in the return data.
* @param {string|number|boolean} defaultValue The default value to use for the field.
* @constructor
*/
var FormField = function(name, type, resetIfUndefined, defaultValue) {
this.name = name;
this.id = 'id_' + this.name;
this.selector = '#' + this.id;
this.type = type;
this.resetIfUndefined = resetIfUndefined;
this.defaultValue = defaultValue;
};
/**
* Form field types.
*
* @type {{TEXT: number, SELECT: number, CHECKBOX: number, EDITOR: number}}
*/
FormField.TYPES = {
TEXT: 1,
SELECT: 2,
CHECKBOX: 3,
EDITOR: 4
};
/**
* Sets the values for a form field.
*
* @param {string|boolean|number} value The value to be set into the field.
*/
FormField.prototype.setFieldValue = function(value) {
if (value === null) {
if (this.resetIfUndefined) {
value = this.defaultValue;
} else {
// No need set the field value if value is null and there's no need to reset the field.
return;
}
}
switch (this.type) {
case FormField.TYPES.CHECKBOX:
if (value) {
$(this.selector).prop('checked', true);
} else {
$(this.selector).prop('checked', false);
}
break;
case FormField.TYPES.EDITOR:
if (typeof value.text !== 'undefined') {
/* global tinyMCE:false */
// Set text in editor's editable content, if applicable.
// Check if it is an Atto editor.
var attoEditor = $(this.selector + 'editable');
if (attoEditor.length) {
attoEditor.html(value.text);
} else if (typeof tinyMCE !== 'undefined') {
// If the editor is not Atto, try to fallback to TinyMCE.
if (tinyMCE.majorVersion == "3") {
// Tiny 3.
tinyMCE.execInstanceCommand(this.id, 'mceInsertContent', false, value.text);
} else {
// Tiny 4+.
tinyMCE.get(this.id).setContent(value.text);
}
}
// Set text to actual editor text area.
$(this.selector).val(value.text);
}
break;
default:
$(this.selector).val(value);
break;
}
};
return FormField;
}
);
+30
View File
@@ -0,0 +1,30 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* A list of keys and their keycodes that are used by the LTI modules.
*
* @module mod_lti/keys
* @class keys
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define([], function() {
return /** @alias module:mod_lti/keys */ {
ENTER: 13,
SPACE: 32
};
});
+78
View File
@@ -0,0 +1,78 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Event handlers for the mod_lti mod_form.
*
* @module mod_lti/mod_form
* @copyright 2023 Jake Dallimore <jrhdallimore@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
import ContentItem from 'mod_lti/contentitem';
/**
* Initialise module.
*
* @param {int} courseId the course id.
*/
const init = (courseId) => {
const contentItemButton = document.querySelector('[name="selectcontent"]');
if (!contentItemButton) {
return;
}
contentItemButton.addEventListener('click', () => {
const contentItemUrl = contentItemButton.getAttribute('data-contentitemurl');
const contentItemId = document.querySelector('#hidden_typeid').value;
if (contentItemId) {
const title = document.querySelector('#id_name').value.trim();
const text = document.querySelector('#id_introeditor').value.trim();
const postData = {
id: contentItemId,
course: courseId,
title: title,
text: text
};
// The callback below is called after the content item has been returned and processed.
ContentItem.init(contentItemUrl, postData, (returnData) => {
if (!returnData.multiple) {
// The state of the grade checkbox has already been set by processContentItemReturnData() but that
// hasn't fired the click/change event required by formslib to show/hide the dependent grade fields.
// Fire it now.
const allowGrades = document.querySelector('#id_instructorchoiceacceptgrades');
let allowGradesChangeEvent = new Event('change');
allowGrades.dispatchEvent(allowGradesChangeEvent);
// If the tool is set to accept grades, make sure "Point" is selected.
if (allowGrades.checked) {
const gradeType = document.querySelector('#id_grade_modgrade_type');
gradeType.value = "point";
let gradeTypeChangeEvent = new Event('change');
gradeType.dispatchEvent(gradeTypeChangeEvent);
}
}
});
}
});
};
export default {
init: init
};
+45
View File
@@ -0,0 +1,45 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Module to handle AJAX interactions.
*
* @module mod_lti/repository
* @copyright 2023 Ilya Tregubov <ilya.a.tregubov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Ajax from 'core/ajax';
/**
* Toggle coursevisible of a tool
*
* @param {Number} tooltypeid Too type id
* @param {Number} courseid Course ID
* @param {Number} showinactivitychooser showinactivitychooser state
* @return {Promise}
*/
export const toggleShowInActivityChooser = (
tooltypeid,
courseid,
showinactivitychooser,
) => Ajax.call([{
methodname: 'mod_lti_toggle_showinactivitychooser',
args: {
tooltypeid,
courseid,
showinactivitychooser,
},
}])[0];
+696
View File
@@ -0,0 +1,696 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Controls all of the behaviour and interaction with a tool type card. These are
* listed on the LTI tool type management page.
*
* See template: mod_lti/tool_card
*
* @module mod_lti/tool_card_controller
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'core/modal',
'mod_lti/tool_type', 'mod_lti/events', 'mod_lti/keys',
'core/str'],
function($, ajax, notification, templates, Modal, toolType, ltiEvents, KEYS, str) {
var SELECTORS = {
DELETE_BUTTON: '.delete',
NAME_ELEMENT: '.name',
DESCRIPTION_ELEMENT: '.description',
CAPABILITIES_CONTAINER: '.capabilities-container',
ACTIVATE_BUTTON: '.tool-card-footer a.activate',
};
// Timeout in seconds.
var ANNOUNCEMENT_TIMEOUT = 2000;
/**
* Return the delete button element.
*
* @method getDeleteButton
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {JQuery} jQuery object
*/
var getDeleteButton = function(element) {
return element.find(SELECTORS.DELETE_BUTTON);
};
/**
* Return the element representing the tool type name.
*
* @method getNameElement
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {JQuery} jQuery object
*/
var getNameElement = function(element) {
return element.find(SELECTORS.NAME_ELEMENT);
};
/**
* Return the element representing the tool type description.
*
* @method getDescriptionElement
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {JQuery} jQuery object
*/
var getDescriptionElement = function(element) {
return element.find(SELECTORS.DESCRIPTION_ELEMENT);
};
/**
* Return the activate button for the type.
*
* @method getActivateButton
* @private
* @param {Object} element jQuery object representing the tool card.
* @return {Object} jQuery object
*/
var getActivateButton = function(element) {
return element.find(SELECTORS.ACTIVATE_BUTTON);
};
/**
* Checks if the type card has an activate button.
*
* @method hasActivateButton
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {Boolean} true if has active buton
*/
var hasActivateButton = function(element) {
return getActivateButton(element).length ? true : false;
};
/**
* Return the element that contains the capabilities approval for
* the user.
*
* @method getCapabilitiesContainer
* @private
* @param {Object} element jQuery object representing the tool card.
* @return {Object} The element
*/
var getCapabilitiesContainer = function(element) {
return element.find(SELECTORS.CAPABILITIES_CONTAINER);
};
/**
* Checks if the tool type has capabilities that need approval. If it
* does then the container will be present.
*
* @method hasCapabilitiesContainer
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {Boolean} true if has capbilities.
*/
var hasCapabilitiesContainer = function(element) {
return getCapabilitiesContainer(element).length ? true : false;
};
/**
* Get the type id.
*
* @method getTypeId
* @private
* @param {Object} element jQuery object representing the tool card.
* @return {String} Type ID
*/
var getTypeId = function(element) {
return element.attr('data-type-id');
};
/**
* Stop any announcement currently visible on the card.
*
* @method clearAllAnnouncements
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var clearAllAnnouncements = function(element) {
element.removeClass('announcement loading success fail capabilities');
};
/**
* Show the loading announcement.
*
* @method startLoading
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var startLoading = function(element) {
clearAllAnnouncements(element);
element.addClass('announcement loading');
};
/**
* Hide the loading announcement.
*
* @method stopLoading
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var stopLoading = function(element) {
element.removeClass('announcement loading');
};
/**
* Show the success announcement. The announcement is only
* visible for 2 seconds.
*
* @method announceSuccess
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {Promise} jQuery Deferred object
*/
var announceSuccess = function(element) {
var promise = $.Deferred();
clearAllAnnouncements(element);
element.addClass('announcement success');
setTimeout(function() {
element.removeClass('announcement success');
promise.resolve();
}, ANNOUNCEMENT_TIMEOUT);
return promise;
};
/**
* Show the failure announcement. The announcement is only
* visible for 2 seconds.
*
* @method announceFailure
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {Promise} jQuery Deferred object
*/
var announceFailure = function(element) {
var promise = $.Deferred();
clearAllAnnouncements(element);
element.addClass('announcement fail');
setTimeout(function() {
element.removeClass('announcement fail');
promise.resolve();
}, ANNOUNCEMENT_TIMEOUT);
return promise;
};
/**
* Delete the tool type from the Moodle server. Triggers a success
* or failure announcement depending on the result.
*
* @method deleteType
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {Promise} jQuery Deferred object
*/
var deleteType = function(element) {
var promise = $.Deferred();
var typeId = getTypeId(element);
startLoading(element);
if (typeId === "") {
return $.Deferred().resolve();
}
str.get_strings([
{
key: 'delete',
component: 'mod_lti'
},
{
key: 'delete_confirmation',
component: 'mod_lti'
},
{
key: 'delete',
component: 'mod_lti'
},
{
key: 'cancel',
component: 'core'
},
])
.done(function(strs) {
notification.confirm(strs[0], strs[1], strs[2], strs[3], function() {
toolType.delete(typeId)
.done(function() {
stopLoading(element);
announceSuccess(element)
.done(function() {
element.remove();
})
.fail(notification.exception)
.always(function() {
// Always resolve because even if the announcement fails the type was deleted.
promise.resolve();
});
})
.fail(function(error) {
announceFailure(element);
promise.reject(error);
});
}, function() {
stopLoading(element);
promise.resolve();
});
})
.fail(function(error) {
stopLoading(element);
notification.exception(error);
promise.reject(error);
});
return promise;
};
/**
* Save a given value in a data attribute on the element.
*
* @method setValueSnapshot
* @private
* @param {JQuery} element jQuery object representing the element.
* @param {String} value to be saved.
*/
var setValueSnapshot = function(element, value) {
element.attr('data-val-snapshot', value);
};
/**
* Return the saved value from the element.
*
* @method getValueSnapshot
* @private
* @param {JQuery} element jQuery object representing the element.
* @return {String} the saved value.
*/
var getValueSnapshot = function(element) {
return element.attr('data-val-snapshot');
};
/**
* Save the current value of the tool description.
*
* @method snapshotDescription
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var snapshotDescription = function(element) {
var descriptionElement = getDescriptionElement(element);
if (descriptionElement.hasClass('loading')) {
return;
}
var description = descriptionElement.text().trim();
setValueSnapshot(descriptionElement, description);
};
/**
* Send a request to update the description value for this tool
* in the Moodle server.
*
* @method updateDescription
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {Promise} jQuery Deferred object
*/
var updateDescription = function(element) {
var typeId = getTypeId(element);
// Return early if we don't have an id because it's
// required to save the changes.
if (typeId === "") {
return $.Deferred().resolve();
}
var descriptionElement = getDescriptionElement(element);
// Return early if we're already saving a value.
if (descriptionElement.hasClass('loading')) {
return $.Deferred().resolve();
}
var description = descriptionElement.text().trim();
var snapshotVal = getValueSnapshot(descriptionElement);
// If the value hasn't change then don't bother sending the
// update request.
if (snapshotVal == description) {
return $.Deferred().resolve();
}
descriptionElement.addClass('loading');
var promise = toolType.update({id: typeId, description: description});
promise.done(function(type) {
descriptionElement.removeClass('loading');
// Make sure the text is updated with the description from the
// server, just in case the update didn't work.
descriptionElement.text(type.description);
}).fail(notification.exception);
// Probably need to handle failures better so that we can revert
// the value in the input for the user.
promise.fail(function() {
descriptionElement.removeClass('loading');
});
return promise;
};
/**
* Save the current value of the tool name.
*
* @method snapshotName
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var snapshotName = function(element) {
var nameElement = getNameElement(element);
if (nameElement.hasClass('loading')) {
return;
}
var name = nameElement.text().trim();
setValueSnapshot(nameElement, name);
};
/**
* Send a request to update the name value for this tool
* in the Moodle server.
*
* @method updateName
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {Promise} jQuery Deferred object
*/
var updateName = function(element) {
var typeId = getTypeId(element);
// Return if we don't have an id.
if (typeId === "") {
return $.Deferred().resolve();
}
var nameElement = getNameElement(element);
// Return if we're already saving.
if (nameElement.hasClass('loading')) {
return $.Deferred().resolve();
}
var name = nameElement.text().trim();
var snapshotVal = getValueSnapshot(nameElement);
// If the value hasn't change then don't bother sending the
// update request.
if (snapshotVal == name) {
return $.Deferred().resolve();
}
nameElement.addClass('loading');
var promise = toolType.update({id: typeId, name: name});
promise.done(function(type) {
nameElement.removeClass('loading');
// Make sure the text is updated with the name from the
// server, just in case the update didn't work.
nameElement.text(type.name);
});
// Probably need to handle failures better so that we can revert
// the value in the input for the user.
promise.fail(function() {
nameElement.removeClass('loading');
});
return promise;
};
/**
* Send a request to update the state for this tool to be configured (active)
* in the Moodle server. A success or failure announcement is triggered depending
* on the result.
*
* @method setStatusActive
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {Promise} jQuery Deferred object
*/
var setStatusActive = function(element) {
var id = getTypeId(element);
// Return if we don't have an id.
if (id === "") {
return $.Deferred().resolve();
}
startLoading(element);
var promise = toolType.update({
id: id,
state: toolType.constants.state.configured
});
promise.then(function(toolTypeData) {
stopLoading(element);
announceSuccess(element);
return toolTypeData;
}).then(function(toolTypeData) {
return templates.render('mod_lti/tool_card', toolTypeData);
}).then(function(html, js) {
templates.replaceNode(element, html, js);
return;
}).catch(function() {
stopLoading(element);
announceFailure(element);
});
return promise;
};
/**
* Show the capabilities approval screen to show which groups of data this
* type requires access to in Moodle (if any).
*
* @method displayCapabilitiesApproval
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var displayCapabilitiesApproval = function(element) {
element.addClass('announcement capabilities');
};
/**
* Hide the capabilities approval screen.
*
* @method hideCapabilitiesApproval
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var hideCapabilitiesApproval = function(element) {
element.removeClass('announcement capabilities');
};
/**
* The user wishes to activate this tool so show them the capabilities that
* they need to agree to or if there are none then set the tool type's state
* to active.
*
* @method activateToolType
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var activateToolType = function(element) {
if (hasCapabilitiesContainer(element)) {
displayCapabilitiesApproval(element);
} else {
setStatusActive(element);
}
};
/**
* Sets up the listeners for user interaction on this tool type card.
*
* @method registerEventListeners
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var registerEventListeners = function(element) {
var deleteButton = getDeleteButton(element);
deleteButton.click(function(e) {
e.preventDefault();
deleteType(element);
});
deleteButton.keypress(function(e) {
if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {
if (e.keyCode == KEYS.ENTER || e.keyCode == KEYS.SPACE) {
e.preventDefault();
deleteButton.click();
}
}
});
var descriptionElement = getDescriptionElement(element);
descriptionElement.focus(function(e) {
e.preventDefault();
// Save a copy of the current value for the description so that
// we can check if the user has changed it before sending a request to
// the server.
snapshotDescription(element);
});
descriptionElement.blur(function(e) {
e.preventDefault();
updateDescription(element);
});
descriptionElement.keypress(function(e) {
if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {
if (e.keyCode == KEYS.ENTER) {
e.preventDefault();
descriptionElement.blur();
}
}
});
var nameElement = getNameElement(element);
nameElement.focus(function(e) {
e.preventDefault();
// Save a copy of the current value for the name so that
// we can check if the user has changed it before sending a request to
// the server.
snapshotName(element);
});
nameElement.blur(function(e) {
e.preventDefault();
updateName(element);
});
nameElement.keypress(function(e) {
if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {
if (e.keyCode == KEYS.ENTER) {
e.preventDefault();
nameElement.blur();
}
}
});
// Only pending tool type cards have an activate button.
if (hasActivateButton(element)) {
var activateButton = getActivateButton(element);
activateButton.click(function(e) {
e.preventDefault();
activateToolType(element);
});
activateButton.keypress(function(e) {
if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {
if (e.keyCode == KEYS.ENTER || e.keyCode == KEYS.SPACE) {
e.preventDefault();
activateButton.click();
}
}
});
}
if (hasCapabilitiesContainer(element)) {
var capabilitiesContainer = getCapabilitiesContainer(element);
capabilitiesContainer.on(ltiEvents.CAPABILITIES_AGREE, function() {
setStatusActive(element);
});
capabilitiesContainer.on(ltiEvents.CAPABILITIES_DECLINE, function() {
hideCapabilitiesApproval(element);
});
}
};
/**
* Sets up the templates for the tool configuration modal on this tool type card.
*
* @method registerModal
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var registerModal = function(element) {
const configurationLink = element.find('#' + element.data('uniqid') + '-' + element.data('deploymentid'));
if (!configurationLink.length) {
return;
}
const trigger = configurationLink.get(0);
trigger.addEventListener('click', (e) => {
e.preventDefault();
var context = {
'uniqid': element.data('uniqid'),
'platformid': element.data('platformid'),
'clientid': element.data('clientid'),
'deploymentid': element.data('deploymentid'),
'urls': {
'publickeyset': element.data('publickeyseturl'),
'accesstoken': element.data('accesstokenurl'),
'authrequest': element.data('authrequesturl')
}
};
var bodyPromise = templates.render('mod_lti/tool_config_modal_body', context);
var mailTo = 'mailto:?subject=' + encodeURIComponent(element.data('mailtosubject')) +
'&body=' + encodeURIComponent(element.data('platformidstr')) + ':%20' +
encodeURIComponent(element.data('platformid')) + '%0D%0A' +
encodeURIComponent(element.data('clientidstr')) + ':%20' +
encodeURIComponent(element.data('clientid')) + '%0D%0A' +
encodeURIComponent(element.data('deploymentidstr')) + ':%20' +
encodeURIComponent(element.data('deploymentid')) + '%0D%0A' +
encodeURIComponent(element.data('publickeyseturlstr')) + ':%20' +
encodeURIComponent(element.data('publickeyseturl')) + '%0D%0A' +
encodeURIComponent(element.data('accesstokenurlstr')) + ':%20' +
encodeURIComponent(element.data('accesstokenurl')) + '%0D%0A' +
encodeURIComponent(element.data('authrequesturlstr')) + ':%20' +
encodeURIComponent(element.data('authrequesturl')) + '%0D%0A';
context = {
'mailto': mailTo
};
var footerPromise = templates.render('mod_lti/tool_config_modal_footer', context);
Modal.create({
large: true,
title: element.data('modaltitle'),
body: bodyPromise,
footer: footerPromise,
show: true
});
});
};
return /** @alias module:mod_lti/tool_card_controller */ {
/**
* Initialise this module.
*
* @param {JQuery} element jQuery object representing the tool card.
*/
init: function(element) {
registerEventListeners(element);
registerModal(element);
}
};
});
@@ -0,0 +1,528 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Standard Ajax wrapper for Moodle. It calls the central Ajax script,
* which can call any existing webservice using the current session.
* In addition, it can batch multiple requests and return multiple responses.
*
* @module mod_lti/tool_configure_controller
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define(['jquery', 'core/ajax', 'core/paged_content_factory', 'core/notification', 'core/templates', 'mod_lti/events',
'mod_lti/keys', 'mod_lti/tool_types_and_proxies', 'mod_lti/tool_type', 'mod_lti/tool_proxy', 'core/str', 'core/config'],
function($, ajax,
pagedContentFactory, notification, templates, ltiEvents, KEYS,
toolTypesAndProxies, toolType, toolProxy, str, config) {
var SELECTORS = {
EXTERNAL_REGISTRATION_CONTAINER: '#external-registration-container',
EXTERNAL_REGISTRATION_PAGE_CONTAINER: '#external-registration-page-container',
EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER: '#external-registration-template-container',
CARTRIDGE_REGISTRATION_CONTAINER: '#cartridge-registration-container',
CARTRIDGE_REGISTRATION_FORM: '#cartridge-registration-form',
ADD_TOOL_FORM: '#add-tool-form',
TOOL_CARD_CONTAINER: '#tool-card-container',
TOOL_LIST_CONTAINER: '#tool-list-container',
TOOL_CREATE_BUTTON: '#tool-create-button',
TOOL_CREATE_LTILEGACY_BUTTON: '#tool-createltilegacy-button',
REGISTRATION_CHOICE_CONTAINER: '#registration-choice-container',
TOOL_URL: '#tool-url'
};
/**
* Get the tool list container element.
*
* @method getToolListContainer
* @private
* @return {Object} jQuery object
*/
var getToolListContainer = function() {
return $(SELECTORS.TOOL_LIST_CONTAINER);
};
/**
* Get the tool card container element.
*
* @method getToolCardContainer
* @private
* @return {Object} jQuery object
*/
const getToolCardContainer = function() {
return $(SELECTORS.TOOL_CARD_CONTAINER);
};
/**
* Get the external registration container element.
*
* @method getExternalRegistrationContainer
* @private
* @return {Object} jQuery object
*/
var getExternalRegistrationContainer = function() {
return $(SELECTORS.EXTERNAL_REGISTRATION_CONTAINER);
};
/**
* Get the cartridge registration container element.
*
* @method getCartridgeRegistrationContainer
* @private
* @return {Object} jQuery object
*/
var getCartridgeRegistrationContainer = function() {
return $(SELECTORS.CARTRIDGE_REGISTRATION_CONTAINER);
};
/**
* Get the registration choice container element.
*
* @method getRegistrationChoiceContainer
* @private
* @return {Object} jQuery object
*/
var getRegistrationChoiceContainer = function() {
return $(SELECTORS.REGISTRATION_CHOICE_CONTAINER);
};
/**
* Close the LTI Advantage Registration IFrame.
*
* @private
* @param {Object} e post message event sent from the registration frame.
*/
var closeLTIAdvRegistration = function(e) {
if (e.data && 'org.imsglobal.lti.close' === e.data.subject) {
$(SELECTORS.EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER).empty();
hideExternalRegistration();
showRegistrationChoices();
showToolList();
showRegistrationChoices();
reloadToolList();
}
};
/**
* Load the external registration template and render it in the DOM and display it.
*
* @method initiateRegistration
* @private
* @param {String} url where to send the registration request
*/
var initiateRegistration = function(url) {
// Show the external registration page in an iframe.
$(SELECTORS.EXTERNAL_REGISTRATION_PAGE_CONTAINER).removeClass('hidden');
var container = $(SELECTORS.EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER);
container.append($("<iframe src='startltiadvregistration.php?url="
+ encodeURIComponent(url) + "&sesskey=" + config.sesskey + "'></iframe>"));
showExternalRegistration();
window.addEventListener("message", closeLTIAdvRegistration, false);
};
/**
* Get the tool type URL.
*
* @method getToolURL
* @private
* @return {String} the tool type url
*/
var getToolURL = function() {
return $(SELECTORS.TOOL_URL).val();
};
/**
* Hide the external registration container.
*
* @method hideExternalRegistration
* @private
*/
var hideExternalRegistration = function() {
getExternalRegistrationContainer().addClass('hidden');
};
/**
* Hide the cartridge registration container.
*
* @method hideCartridgeRegistration
* @private
*/
var hideCartridgeRegistration = function() {
getCartridgeRegistrationContainer().addClass('hidden');
};
/**
* Hide the registration choice container.
*
* @method hideRegistrationChoices
* @private
*/
var hideRegistrationChoices = function() {
getRegistrationChoiceContainer().addClass('hidden');
};
/**
* Display the external registration panel and hides the other
* panels.
*
* @method showExternalRegistration
* @private
*/
var showExternalRegistration = function() {
hideCartridgeRegistration();
hideRegistrationChoices();
getExternalRegistrationContainer().removeClass('hidden');
screenReaderAnnounce(getExternalRegistrationContainer());
};
/**
* Display the cartridge registration panel and hides the other
* panels.
*
* @method showCartridgeRegistration
* @param {String} url
* @private
*/
var showCartridgeRegistration = function(url) {
hideExternalRegistration();
hideRegistrationChoices();
// Don't save the key and secret from the last tool.
var container = getCartridgeRegistrationContainer();
container.find('input').val('');
container.removeClass('hidden');
container.find(SELECTORS.CARTRIDGE_REGISTRATION_FORM).attr('data-cartridge-url', url);
screenReaderAnnounce(container);
};
/**
* Display the registration choices panel and hides the other
* panels.
*
* @method showRegistrationChoices
* @private
*/
var showRegistrationChoices = function() {
hideExternalRegistration();
hideCartridgeRegistration();
getRegistrationChoiceContainer().removeClass('hidden');
screenReaderAnnounce(getRegistrationChoiceContainer());
};
/**
* JAWS does not notice visibility changes with aria-live.
* Remove and add the content back to force it to read it out.
* This function can be removed once JAWS supports visibility.
*
* @method screenReaderAnnounce
* @param {Object} element
* @private
*/
var screenReaderAnnounce = function(element) {
var children = element.children().detach();
children.appendTo(element);
};
/**
* Hides the list of tool types.
*
* @method hideToolList
* @private
*/
var hideToolList = function() {
getToolListContainer().addClass('hidden');
};
/**
* Display the list of tool types.
*
* @method hideToolList
* @private
*/
var showToolList = function() {
getToolListContainer().removeClass('hidden');
};
/**
* Display the registration feedback alert and hide the other panels.
*
* @method showRegistrationFeedback
* @param {Object} data
* @private
*/
var showRegistrationFeedback = function(data) {
var type = data.error ? 'error' : 'success';
notification.addNotification({
message: data.message,
type: type
});
};
/**
* Show the loading animation
*
* @method startLoading
* @private
* @param {Object} element jQuery object
*/
var startLoading = function(element) {
element.addClass("loading");
};
/**
* Hide the loading animation
*
* @method stopLoading
* @private
* @param {Object} element jQuery object
*/
var stopLoading = function(element) {
element.removeClass("loading");
};
/**
* Refresh the list of tool types and render the new ones.
*
* @method reloadToolList
* @private
*/
var reloadToolList = function() {
// Behat tests should wait for the tool list to load.
M.util.js_pending('reloadToolList');
const cardContainer = getToolCardContainer();
const listContainer = getToolListContainer();
const limit = 60;
// Get initial data with zero limit and offset.
fetchToolCount().done(function(data) {
pagedContentFactory.createWithTotalAndLimit(
data.count,
limit,
function(pagesData) {
return pagesData.map(function(pageData) {
return fetchToolData(pageData.limit, pageData.offset)
.then(function(data) {
return renderToolData(data);
});
});
},
{
'showFirstLast': true
})
.done(function(html, js) {
// Add the paged content into the page.
templates.replaceNodeContents(cardContainer, html, js);
})
.always(function() {
stopLoading(listContainer);
M.util.js_complete('reloadToolList');
});
});
startLoading(listContainer);
};
/**
* Fetch the count of tool type and proxy datasets.
*
* @return {*|void}
*/
const fetchToolCount = function() {
return toolTypesAndProxies.count({'orphanedonly': true})
.done(function(data) {
return data;
}).catch(function(error) {
// Add debug message, then return empty data.
notification.exception(error);
return {
'count': 0
};
});
};
/**
* Fetch the data for tool type and proxy cards.
*
* @param {number} limit Maximum number of datasets to get.
* @param {number} offset Offset count for fetching the data.
* @return {*|void}
*/
const fetchToolData = function(limit, offset) {
const args = {'orphanedonly': true};
// Only add limit and offset to args if they are integers and not null, otherwise defaults will be used.
if (limit !== null && !Number.isNaN(limit)) {
args.limit = limit;
}
if (offset !== null && !Number.isNaN(offset)) {
args.offset = offset;
}
return toolTypesAndProxies.query(args)
.done(function(data) {
return data;
}).catch(function(error) {
// Add debug message, then return empty data.
notification.exception(error);
return {
'types': [],
'proxies': [],
'limit': limit,
'offset': offset
};
});
};
/**
* Render Tool and Proxy cards from data.
*
* @param {Object} data Contains arrays of data objects to populate cards.
* @return {*}
*/
const renderToolData = function(data) {
const context = {
tools: data.types,
proxies: data.proxies,
};
return templates.render('mod_lti/tool_list', context)
.done(function(html, js) {
return {html, js};
}
);
};
/**
* Start the LTI Advantage registration.
*
* @method addLTIAdvTool
* @private
*/
var addLTIAdvTool = function() {
var url = getToolURL().trim();
if (url) {
$(SELECTORS.TOOL_URL).val('');
hideToolList();
initiateRegistration(url);
}
};
/**
* Trigger appropriate registration process process for the user input
* URL. It can either be a cartridge or a registration url.
*
* @method addLTILegacyTool
* @private
* @return {Promise} jQuery Deferred object
*/
var addLTILegacyTool = function() {
var url = getToolURL().trim();
if (url === "") {
return $.Deferred().resolve();
}
var toolButton = $(SELECTORS.TOOL_CREATE_LTILEGACY_BUTTON);
startLoading(toolButton);
var promise = toolType.isCartridge(url);
promise.always(function() {
stopLoading(toolButton);
});
promise.done(function(result) {
if (result.iscartridge) {
$(SELECTORS.TOOL_URL).val('');
$(document).trigger(ltiEvents.START_CARTRIDGE_REGISTRATION, url);
} else {
$(document).trigger(ltiEvents.START_EXTERNAL_REGISTRATION, {url: url});
}
});
promise.fail(function() {
str.get_string('errorbadurl', 'mod_lti')
.done(function(s) {
$(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, {
message: s,
error: true
});
})
.fail(notification.exception);
});
return promise;
};
/**
* Sets up the listeners for user interaction on the page.
*
* @method registerEventListeners
* @private
*/
var registerEventListeners = function() {
// These are events fired by the registration processes. Either
// the cartridge registration or the external registration url.
$(document).on(ltiEvents.NEW_TOOL_TYPE, function() {
reloadToolList();
});
$(document).on(ltiEvents.START_EXTERNAL_REGISTRATION, function() {
showExternalRegistration();
$(SELECTORS.TOOL_URL).val('');
hideToolList();
});
$(document).on(ltiEvents.STOP_EXTERNAL_REGISTRATION, function() {
showToolList();
showRegistrationChoices();
});
$(document).on(ltiEvents.START_CARTRIDGE_REGISTRATION, function(event, url) {
showCartridgeRegistration(url);
});
$(document).on(ltiEvents.STOP_CARTRIDGE_REGISTRATION, function() {
getCartridgeRegistrationContainer().find(SELECTORS.CARTRIDGE_REGISTRATION_FORM).removeAttr('data-cartridge-url');
showRegistrationChoices();
});
$(document).on(ltiEvents.REGISTRATION_FEEDBACK, function(event, data) {
showRegistrationFeedback(data);
});
var addLegacyButton = $(SELECTORS.TOOL_CREATE_LTILEGACY_BUTTON);
addLegacyButton.click(function(e) {
e.preventDefault();
addLTILegacyTool();
});
var addLTIButton = $(SELECTORS.TOOL_CREATE_BUTTON);
addLTIButton.click(function(e) {
e.preventDefault();
addLTIAdvTool();
});
};
return /** @alias module:mod_lti/cartridge_registration_form */ {
/**
* Initialise this module.
*/
init: function() {
registerEventListeners();
reloadToolList();
}
};
});
+96
View File
@@ -0,0 +1,96 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Provides an interface for a tool proxy in the Moodle server.
*
* @module mod_lti/tool_proxy
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define(['core/ajax', 'core/notification'], function(ajax, notification) {
return {
/**
* Get a list of tool types from Moodle for the given
* search args.
*
* See also:
* mod/lti/classes/external.php get_tool_types_parameters()
*
* @method query
* @public
* @param {Object} args Search parameters
* @return {Promise} jQuery Deferred object
*/
query: function(args) {
var request = {
methodname: 'mod_lti_get_tool_proxies',
args: args || {}
};
var promise = ajax.call([request])[0];
promise.fail(notification.exception);
return promise;
},
/**
* Delete a tool proxy from Moodle.
*
* @method delete
* @public
* @param {Integer} id Tool proxy ID
* @return {Promise} jQuery Deferred object
*/
'delete': function(id) {
var request = {
methodname: 'mod_lti_delete_tool_proxy',
args: {
id: id
}
};
var promise = ajax.call([request])[0];
promise.fail(notification.exception);
return promise;
},
/**
* Create a tool proxy in Moodle.
*
* The promise will fail if the proxy cannot be created, so you must handle the fail result.
*
* See mod/lti/classes/external.php create_tool_proxy_parameters
*
* @method create
* @public
* @param {Object} args Tool proxy properties
* @return {Promise} jQuery Deferred object
*/
create: function(args) {
var request = {
methodname: 'mod_lti_create_tool_proxy',
args: args
};
var promise = ajax.call([request])[0];
return promise;
}
};
});
@@ -0,0 +1,282 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Controls all of the behaviour and interaction with a tool type card. These are
* listed on the LTI tool type management page.
*
* See template: mod_lti/tool_proxy_card
*
* @module mod_lti/tool_proxy_card_controller
* @copyright 2016 John Okely <john@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/tool_proxy', 'mod_lti/events', 'mod_lti/keys',
'core/str'],
function($, ajax, notification, templates, toolProxy, ltiEvents, KEYS, str) {
var SELECTORS = {
DELETE_BUTTON: '.delete',
CAPABILITIES_CONTAINER: '.capabilities-container',
ACTIVATE_BUTTON: '.tool-card-footer a.activate',
};
// Timeout in seconds.
var ANNOUNCEMENT_TIMEOUT = 2000;
/**
* Return the delete button element.
*
* @method getDeleteButton
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {JQuery} jQuery object
*/
var getDeleteButton = function(element) {
return element.find(SELECTORS.DELETE_BUTTON);
};
/**
* Return the activate button for the type.
*
* @method getActivateButton
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {JQuery} jQuery object
*/
var getActivateButton = function(element) {
return element.find(SELECTORS.ACTIVATE_BUTTON);
};
/**
* Get the type id.
*
* @method getTypeId
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {String} Type ID
*/
var getTypeId = function(element) {
return element.attr('data-proxy-id');
};
/**
* Stop any announcement currently visible on the card.
*
* @method clearAllAnnouncements
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var clearAllAnnouncements = function(element) {
element.removeClass('announcement loading success fail capabilities');
};
/**
* Show the loading announcement.
*
* @method startLoading
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var startLoading = function(element) {
clearAllAnnouncements(element);
element.addClass('announcement loading');
};
/**
* Hide the loading announcement.
*
* @method stopLoading
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var stopLoading = function(element) {
element.removeClass('announcement loading');
};
/**
* Show the success announcement. The announcement is only
* visible for 2 seconds.
*
* @method announceSuccess
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {Promise} jQuery Deferred object
*/
var announceSuccess = function(element) {
var promise = $.Deferred();
clearAllAnnouncements(element);
element.addClass('announcement success');
setTimeout(function() {
element.removeClass('announcement success');
promise.resolve();
}, ANNOUNCEMENT_TIMEOUT);
return promise;
};
/**
* Show the failure announcement. The announcement is only
* visible for 2 seconds.
*
* @method announceFailure
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {Promise} jQuery Deferred object
*/
var announceFailure = function(element) {
var promise = $.Deferred();
clearAllAnnouncements(element);
element.addClass('announcement fail');
setTimeout(function() {
element.removeClass('announcement fail');
promise.resolve();
}, ANNOUNCEMENT_TIMEOUT);
return promise;
};
/**
* Delete the tool type from the Moodle server. Triggers a success
* or failure announcement depending on the result.
*
* @method deleteType
* @private
* @param {JQuery} element jQuery object representing the tool card.
* @return {Promise} jQuery Deferred object
*/
var deleteType = function(element) {
var promise = $.Deferred();
var typeId = getTypeId(element);
startLoading(element);
if (typeId === "") {
return $.Deferred().resolve();
}
str.get_strings([
{
key: 'delete',
component: 'mod_lti'
},
{
key: 'delete_confirmation',
component: 'mod_lti'
},
{
key: 'delete',
component: 'mod_lti'
},
{
key: 'cancel',
component: 'core'
},
])
.done(function(strs) {
notification.confirm(strs[0], strs[1], strs[2], strs[3], function() {
toolProxy.delete(typeId)
.done(function() {
stopLoading(element);
announceSuccess(element)
.done(function() {
element.remove();
promise.resolve();
})
.fail(notification.exception);
})
.fail(function(error) {
announceFailure(element);
promise.reject(error);
});
}, function() {
stopLoading(element);
promise.resolve();
});
})
.fail(function(error) {
stopLoading(element);
notification.exception(error);
promise.reject(error);
});
return promise;
};
/**
* The user wishes to activate this tool so show them the capabilities that
* they need to agree to or if there are none then set the tool type's state
* to active.
*
* @method activateToolType
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var activateToolType = function(element) {
var data = {proxyid: getTypeId(element)};
$(document).trigger(ltiEvents.START_EXTERNAL_REGISTRATION, data);
};
/**
* Sets up the listeners for user interaction on this tool type card.
*
* @method registerEventListeners
* @private
* @param {JQuery} element jQuery object representing the tool card.
*/
var registerEventListeners = function(element) {
var deleteButton = getDeleteButton(element);
deleteButton.click(function(e) {
e.preventDefault();
deleteType(element);
});
deleteButton.keypress(function(e) {
if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {
if (e.keyCode == KEYS.ENTER || e.keyCode == KEYS.SPACE) {
e.preventDefault();
deleteButton.click();
}
}
});
var activateButton = getActivateButton(element);
activateButton.click(function(e) {
e.preventDefault();
activateToolType(element);
});
activateButton.keypress(function(e) {
if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {
if (e.keyCode == KEYS.ENTER || e.keyCode == KEYS.SPACE) {
e.preventDefault();
activateButton.click();
}
}
});
};
return /** @alias module:mod_lti/tool_card_controller */ {
/**
* Initialise this module.
*
* @param {JQuery} element jQuery object representing the tool card.
*/
init: function(element) {
registerEventListeners(element);
}
};
});
+169
View File
@@ -0,0 +1,169 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Provides an interface for a tool type in the Moodle server.
*
* @module mod_lti/tool_type
* @copyright 2015 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define(['core/ajax', 'core/notification'], function(ajax, notification) {
return {
/**
* Get a list of tool types from Moodle for the given
* search args.
*
* See also:
* mod/lti/classes/external.php get_tool_types_parameters()
*
* @method query
* @public
* @param {Object} args Search parameters
* @return {Promise} jQuery Deferred object
*/
query: function(args) {
var request = {
methodname: 'mod_lti_get_tool_types',
args: args || {}
};
var promise = ajax.call([request])[0];
promise.fail(notification.exception);
return promise;
},
/**
* Create a tool type in Moodle.
*
* The promise will fail if the URL is not a cartridge, so you must handle the fail result.
*
* See also:
* mod/lti/classes/external.php create_tool_type_parameters()
*
* @method create
* @public
* @param {Object} args Tool type properties
* @return {Promise} jQuery Deferred object
*/
create: function(args) {
var request = {
methodname: 'mod_lti_create_tool_type',
args: args
};
var promise = ajax.call([request])[0];
return promise;
},
/**
* Update a tool type in Moodle.
*
* See also:
* mod/lti/classes/external.php update_tool_type_parameters()
*
* @method update
* @public
* @param {Object} args Tool type properties
* @return {Promise} jQuery Deferred object
*/
update: function(args) {
var request = {
methodname: 'mod_lti_update_tool_type',
args: args
};
var promise = ajax.call([request])[0];
promise.fail(notification.exception);
return promise;
},
/**
* Delete a tool type from Moodle.
*
* @method delete
* @public
* @param {Integer} id Tool type ID
* @return {Promise} jQuery Deferred object
*/
'delete': function(id) {
var request = {
methodname: 'mod_lti_delete_tool_type',
args: {
id: id
}
};
var promise = ajax.call([request])[0];
promise.fail(notification.exception);
return promise;
},
/**
* Get a list of tool types from Moodle for the given
* tool proxy id.
*
* @method query
* @public
* @param {Integer} id Tool type ID
* @return {Promise} jQuery Deferred object
*/
getFromToolProxyId: function(id) {
return this.query({toolproxyid: id});
},
/**
* Check if the given URL is a cartridge URL.
*
* The promise will fail if the URL is unreachable, so you must handle the fail result.
*
* @method isCartridge
* @public
* @param {String} url
* @return {Promise} jQuery Deferred object
*/
isCartridge: function(url) {
var request = {
methodname: 'mod_lti_is_cartridge',
args: {
url: url
}
};
var promise = ajax.call([request])[0];
return promise;
},
/**
* Tool type constants.
*/
constants: {
state: {
configured: 1,
pending: 2,
rejected: 3
},
}
};
});
+67
View File
@@ -0,0 +1,67 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Provides an interface for external tools in the Moodle server.
*
* @module mod_lti/tool_types_and_proxies
* @class tool_types_and_proxies
* @copyright 2020 Andrew Madden <andrewmadden@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.0
*/
import ajax from 'core/ajax';
/**
* Get a list of LTI tool types and tool proxies from Moodle for the given
* search args.
*
* See also:
* mod/lti/classes/external.php get_tool_types_and_proxies()
*
* @method query
* @public
* @param {Object} args Search parameters
* @return {Promise} Promise that will be resolved when the ajax call returns.
*/
export const query = (args) => {
const request = {
methodname: 'mod_lti_get_tool_types_and_proxies',
args: args || {}
};
return ajax.call([request])[0];
};
/**
* Get a count of LTI tool types and tool proxies from Moodle for the given
* search args.
*
* See also:
* mod/lti/classes/external.php get_tool_types_and_proxies_count()
*
* @method count
* @public
* @param {Object} args Search parameters
* @return {Promise} Promise that will be resolved when the ajax call returns.
*/
export const count = (args) => {
const request = {
methodname: 'mod_lti_get_tool_types_and_proxies_count',
args: args || {}
};
return ajax.call([request])[0];
};