diff --git a/lib/amd/build/notification.min.js b/lib/amd/build/notification.min.js index f03cbbb04a0..cf10e4f6da8 100644 --- a/lib/amd/build/notification.min.js +++ b/lib/amd/build/notification.min.js @@ -1 +1 @@ -define(["core/yui","jquery","core/log"],function(a,b,c){var d={types:{success:"core/notification_success",info:"core/notification_info",warning:"core/notification_warning",error:"core/notification_error"},fieldName:"user-notifications",fetchNotifications:function(){require(["core/ajax"],function(a){var b=a.call([{methodname:"core_fetch_notifications",args:{contextid:d.contextid}}]);b[0].done(d.addNotifications)})},addNotifications:function(a){a||(a=[]),b.each(a,function(a,b){d.renderNotification(b.template,b.variables)})},setupTargetRegion:function(){var a=b("#"+d.fieldName);if(!a.length){var c=b("").attr("id",d.fieldName);return a=b("#region-main"),a.length?a.prepend(c):(a=b('[role="main"]'),a.length?a.prepend(c):(a=b("body"),a.prepend(c)))}},addNotification:function(a){var c=d.types.error;return a=b.extend({closebutton:!0,announce:!0,type:"error"},a),a.template?(c=a.template,delete a.template):a.type&&("undefined"!=typeof d.types[a.type]&&(c=d.types[a.type]),delete a.type),d.renderNotification(c,a)},renderNotification:function(a,e){return"undefined"!=typeof e.message&&e.message?void require(["core/templates"],function(c){c.render(a,e).done(function(a,e){b("#"+d.fieldName).prepend(a),c.runTemplateJS(e)}).fail(d.exception)}):void c.debug("Notification received without content. Skipping.")},alert:function(b,c,d){a.use("moodle-core-notification-alert",function(){var a=new M.core.alert({title:b,message:c,yesLabel:d});a.show()})},confirm:function(b,c,d,e,f){a.use("moodle-core-notification-confirm",function(){var a=new M.core.confirm({title:b,question:c,yesLabel:d,noLabel:e});a.on("complete-yes",function(){f()}),a.show()})},exception:function(b){b.backtrace&&(b.lineNumber=b.backtrace[0].line,b.fileName=b.backtrace[0].file,b.fileName="..."+b.fileName.substr(b.fileName.length-20),b.stack=b.debuginfo,b.name=b.errorcode),a.use("moodle-core-notification-exception",function(){var a=new M.core.exception(b);a.show()})}};return{init:function(a,b){d.contextid=a,d.setupTargetRegion(),d.addNotifications(b),d.fetchNotifications()},fetchNotifications:d.fetchNotifications,addNotification:d.addNotification,alert:d.alert,confirm:d.confirm,exception:d.exception}}); \ No newline at end of file +define(["core/yui","jquery","core/log"],function(a,b,c){var d={types:{success:"core/notification_success",info:"core/notification_info",warning:"core/notification_warning",error:"core/notification_error"},fieldName:"user-notifications",fetchNotifications:function(){require(["core/ajax"],function(a){var b=a.call([{methodname:"core_fetch_notifications",args:{contextid:d.contextid}}]);b[0].done(d.addNotifications)})},addNotifications:function(a){a||(a=[]),b.each(a,function(a,b){d.renderNotification(b.template,b.variables)})},setupTargetRegion:function(){var a=b("#"+d.fieldName);if(!a.length){var c=b("").attr("id",d.fieldName);return a=b("#region-main"),a.length?a.prepend(c):(a=b('[role="main"]'),a.length?a.prepend(c):(a=b("body"),a.prepend(c)))}},addNotification:function(a){var c=d.types.error;return a=b.extend({closebutton:!0,announce:!0,type:"error"},a),a.template?(c=a.template,delete a.template):a.type&&("undefined"!=typeof d.types[a.type]&&(c=d.types[a.type]),delete a.type),d.renderNotification(c,a)},renderNotification:function(a,e){return"undefined"!=typeof e.message&&e.message?void require(["core/templates"],function(c){c.render(a,e).done(function(a,e){b("#"+d.fieldName).prepend(a),c.runTemplateJS(e)}).fail(d.exception)}):void c.debug("Notification received without content. Skipping.")},alert:function(b,c,d){a.use("moodle-core-notification-alert",function(){var a=new M.core.alert({title:b,message:c,yesLabel:d});a.show()})},confirm:function(b,c,d,e,f,g){a.use("moodle-core-notification-confirm",function(){var a=new M.core.confirm({title:b,question:c,yesLabel:d,noLabel:e});a.on("complete-yes",function(){f()}),g&&a.on("complete-no",function(){g()}),a.show()})},exception:function(b){b.backtrace&&(b.lineNumber=b.backtrace[0].line,b.fileName=b.backtrace[0].file,b.fileName="..."+b.fileName.substr(b.fileName.length-20),b.stack=b.debuginfo,b.name=b.errorcode),a.use("moodle-core-notification-exception",function(){var a=new M.core.exception(b);a.show()})}};return{init:function(a,b){d.contextid=a,d.setupTargetRegion(),d.addNotifications(b),d.fetchNotifications()},fetchNotifications:d.fetchNotifications,addNotification:d.addNotification,alert:d.alert,confirm:d.confirm,exception:d.exception}}); \ No newline at end of file diff --git a/lib/amd/src/notification.js b/lib/amd/src/notification.js index da34f43461e..a887c8e24bb 100644 --- a/lib/amd/src/notification.js +++ b/lib/amd/src/notification.js @@ -137,7 +137,7 @@ function(Y, $, log) { }); }, - confirm: function(title, question, yesLabel, noLabel, callback) { + confirm: function(title, question, yesLabel, noLabel, yesCallback, noCallback) { // Here we are wrapping YUI. This allows us to start transitioning, but // wait for a good alternative without having inconsistent dialogues. Y.use('moodle-core-notification-confirm', function () { @@ -149,8 +149,13 @@ function(Y, $, log) { }); modal.on('complete-yes', function() { - callback(); + yesCallback(); }); + if (noCallback) { + modal.on('complete-no', function() { + noCallback(); + }); + } modal.show(); }); }, @@ -225,7 +230,8 @@ function(Y, $, log) { * @param {string} question * @param {string} yesLabel * @param {string} noLabel - * @param {function} callback + * @param {function} yesCallback + * @param {function} noCallback Optional parameter to be called if the user presses cancel. */ confirm: notificationModule.confirm, diff --git a/mod/lti/amd/build/external_registration.min.js b/mod/lti/amd/build/external_registration.min.js index b3d9e0fff94..6b58c4c2db6 100644 --- a/mod/lti/amd/build/external_registration.min.js +++ b/mod/lti/amd/build/external_registration.min.js @@ -1 +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(a,b,c,d,e,f,g,h,i){var j={REGISTRATION_URL:"#external-registration-url",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"},k=function(){return a(j.EXTERNAL_REGISTRATION_CONTAINER).attr("data-registration-url")},l=function(){return a(j.EXTERNAL_REGISTRATION_CANCEL_BUTTON)},m=function(){return a(j.EXTERNAL_REGISTRATION_CONTAINER)},n=function(){return a(j.EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER)},o=function(){return a(j.TOOL_TYPE_CAPABILITIES_CONTAINER)},p=function(){return a(j.TOOL_TYPE_CAPABILITIES_TEMPLATE_CONTAINER)},q=function(){o().addClass("loading")},r=function(){o().removeClass("loading")},s=function(){l().addClass("loading")},t=function(){l().removeClass("loading")},u=function(){o().addClass("hidden")},v=function(){o().removeClass("hidden")},w=function(){m().addClass("hidden")},x=function(){m().removeClass("hidden")},y=function(a){var b=l();b.attr("data-tool-proxy-id",a)},z=function(){var a=l();return a.attr("data-tool-proxy-id")},A=function(){var a=l();a.removeAttr("data-tool-proxy-id")},B=function(){return z()?!0:!1},C=function(a){var c={methodname:"mod_lti_get_tool_proxy_registration_request",args:{id:a}};return b.call([c])[0]},D=function(){s();var b=a.Deferred();if(B()){var d=z();f["delete"](d).done(function(){b.resolve()}).fail(function(a){b.reject(a)})}else b.resolve();return b.done(function(){I(),t()}).fail(function(b){c.exception(b),I(),t(),i.get_strings([{key:"error",component:"moodle"},{key:"failedtodeletetoolproxy",component:"mod_lti"}]).done(function(b){var c={status:b[0],message:b[1],error:!0};a(document).trigger(e.REGISTRATION_FEEDBACK,c)}).fail(c.exception)}),b},E=function(a){var b=d.render("mod_lti/tool_proxy_registration_form",a);return b.done(function(a,b){var c=n();c.append(a),d.runTemplateJS(b),c.find("form").submit(),x()}).fail(c.exception),b},F=function(a){return g.update({id:a.id,state:g.constants.state.configured})},G=function(b){var f=a.Deferred();return d.render("mod_lti/tool_type_capabilities_agree",b).done(function(a,c){var g=p();w(),v(),d.replaceNodeContents(g,a,c);var h=g.find(j.CAPABILITIES_AGREE_CONTAINER);h.on(e.CAPABILITIES_AGREE,function(){q(),F(b).always(function(){r(),g.empty(),f.resolve()})}),h.on(e.CAPABILITIES_DECLINE,function(){g.empty(),f.resolve()})}).fail(f.reject),f.done(function(){u()}).fail(c.exception),f},H=function(){var b=a.Deferred(),c=k();return""===c?b.resolve():f.create({regurl:c}).done(function(a){var c=a.id,d=a.regurl;y(c),C(c).done(function(a){a.reg_url=d,E(a).done(function(){b.resolve()}).fail(b.fail)}).fail(b.fail)}).fail(function(c){D(),a(document).trigger(e.REGISTRATION_FEEDBACK,{status:"error",message:c.message,error:!0}),b.reject(c)}),b},I=function(){B()&&A(),w();var b=n();b.empty(),a(document).trigger(e.STOP_EXTERNAL_REGISTRATION)},J=function(){a(document).on(e.START_EXTERNAL_REGISTRATION,function(){H()});var b=l();b.click(function(a){a.preventDefault(),D()}),b.keypress(function(a){a.metaKey||a.shiftKey||a.altKey||a.ctrlKey||(a.keyCode==h.ENTER||a.keyCode==h.SPACE)&&(a.preventDefault(),D())}),window.triggerExternalRegistrationComplete=function(b){var d=a.Deferred(),f={status:b.status,message:"",error:!1};if("success"==b.status){if(i.get_strings([{key:"success",component:"moodle"},{key:"successfullycreatedtooltype",component:"mod_lti"}]).done(function(a){f.status=a[0],f.message=a[1]}).fail(c.exception),d.done(function(){I(),a(document).trigger(e.REGISTRATION_FEEDBACK,f),a(document).trigger(e.NEW_TOOL_TYPE)}).fail(c.exception),B()){var h=z();g.getFromToolProxyId(h).done(function(a){if(a&&a.length){var b=a[0];b.hascapabilitygroups?G(b).always(function(){d.resolve()}):d.resolve()}else d.resolve()}).fail(function(){d.resolve()})}}else f.message=b.error,f.error=!0,d.done(function(){D().always(function(){a(document).trigger(e.REGISTRATION_FEEDBACK,f)})}).fail(c.exception),d.resolve();return d}};return{init:function(){J()}}}); \ No newline at end of file +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(a,b,c,d,e,f,g,h,i){var j={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"},k=function(){return a(j.EXTERNAL_REGISTRATION_CANCEL_BUTTON)},l=function(){return a(j.EXTERNAL_REGISTRATION_CONTAINER)},m=function(){return a(j.EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER)},n=function(){return a(j.TOOL_TYPE_CAPABILITIES_CONTAINER)},o=function(){return a(j.TOOL_TYPE_CAPABILITIES_TEMPLATE_CONTAINER)},p=function(){n().addClass("loading")},q=function(){n().removeClass("loading")},r=function(){k().addClass("loading")},s=function(){k().removeClass("loading")},t=function(){n().addClass("hidden")},u=function(){n().removeClass("hidden")},v=function(){l().addClass("hidden")},w=function(){l().removeClass("hidden")},x=function(a){var b=k();b.attr("data-tool-proxy-id",a)},y=function(){var a=k();return a.attr("data-tool-proxy-id")},z=function(){var a=k();a.removeAttr("data-tool-proxy-id")},A=function(){return y()?!0:!1},B=function(){var a=k();return a.attr("data-tool-proxy-new")&&A()},C=function(){var a=k();return a.attr("data-tool-proxy-new","new")},D=function(){var a=k();return a.removeAttr("data-tool-proxy-new")},E=function(a){var c={methodname:"mod_lti_get_tool_proxy_registration_request",args:{id:a}};return b.call([c])[0]},F=function(){r();var b=a.Deferred();if(B()){var d=y();f["delete"](d).done(function(){b.resolve()}).fail(function(a){b.reject(a)})}else b.resolve();return b.done(function(){L(),s()}).fail(function(b){c.exception(b),L(),s(),i.get_strings([{key:"error",component:"moodle"},{key:"failedtodeletetoolproxy",component:"mod_lti"}]).done(function(b){var c={status:b[0],message:b[1],error:!0};a(document).trigger(e.REGISTRATION_FEEDBACK,c)}).fail(c.exception)}),b},G=function(a){var b=d.render("mod_lti/tool_proxy_registration_form",a);return b.done(function(a,b){var c=m();c.append(a),d.runTemplateJS(b),c.find("form").submit(),w()}).fail(c.exception),b},H=function(a){return g.update({id:a.id,state:g.constants.state.configured})},I=function(b){var f=a.Deferred();return d.render("mod_lti/tool_type_capabilities_agree",b).done(function(a,c){var g=o();v(),u(),d.replaceNodeContents(g,a,c);var h=g.find(j.CAPABILITIES_AGREE_CONTAINER);h.on(e.CAPABILITIES_AGREE,function(){p(),H(b).always(function(){q(),g.empty(),f.resolve()})}),h.on(e.CAPABILITIES_DECLINE,function(){g.empty(),f.resolve()})}).fail(f.reject),f.done(function(){t()}).fail(c.exception),f},J=function(b){var d=a.Deferred();return b&&""!==b?f.create({regurl:b}).done(function(a){C(),d=K(a.id)}).fail(function(b){F(),i.get_string("error","moodle").done(function(c){var d={status:c,message:b.message,error:!0};a(document).trigger(e.REGISTRATION_FEEDBACK,d)}).fail(c.exception),d.reject(b)}):d.resolve(),d},K=function(b){var c=a.Deferred();return x(b),E(b).done(function(a){G(a).done(function(){c.resolve()}).fail(c.fail)}).fail(c.fail),c},L=function(){A()&&z(),D(!1),v();var b=m();b.empty(),a(document).trigger(e.STOP_EXTERNAL_REGISTRATION)},M=function(){a(document).on(e.START_EXTERNAL_REGISTRATION,function(a,b){b&&(b.url&&J(b.url),b.proxyid&&K(b.proxyid))});var b=k();b.click(function(a){a.preventDefault(),F()}),b.keypress(function(a){a.metaKey||a.shiftKey||a.altKey||a.ctrlKey||(a.keyCode==h.ENTER||a.keyCode==h.SPACE)&&(a.preventDefault(),F())}),window.triggerExternalRegistrationComplete=function(b){var d=a.Deferred(),f={status:b.status,message:"",error:!1};if("success"==b.status){if(i.get_strings([{key:"success",component:"moodle"},{key:"successfullycreatedtooltype",component:"mod_lti"}]).done(function(a){f.status=a[0],f.message=a[1]}).fail(c.exception),d.done(function(){L(),a(document).trigger(e.REGISTRATION_FEEDBACK,f),a(document).trigger(e.NEW_TOOL_TYPE)}).fail(c.exception),B()){var h=y();g.getFromToolProxyId(h).done(function(a){if(a&&a.length){var b=a[0];b.hascapabilitygroups?I(b).always(function(){d.resolve()}):d.resolve()}else d.resolve()}).fail(function(){d.resolve()})}}else f.message=b.error,f.error=!0,d.done(function(){F().always(function(){a(document).trigger(e.REGISTRATION_FEEDBACK,f)})}).fail(c.exception),d.resolve();return d}};return{init:function(){M()}}}); \ No newline at end of file diff --git a/mod/lti/amd/build/tool_card_controller.min.js b/mod/lti/amd/build/tool_card_controller.min.js index d1c8e68fa39..716195b1b7a 100644 --- a/mod/lti/amd/build/tool_card_controller.min.js +++ b/mod/lti/amd/build/tool_card_controller.min.js @@ -1 +1 @@ -define(["jquery","core/ajax","core/notification","core/templates","mod_lti/tool_type","mod_lti/events","mod_lti/keys"],function(a,b,c,d,e,f,g){var h={DELETE_BUTTON:".delete",NAME_ELEMENT:".name",DESCRIPTION_ELEMENT:".description",CAPABILITIES_CONTAINER:".capabilities-container",ACTIVATE_BUTTON:".tool-card-footer a.activate"},i=2e3,j=function(a){return a.find(h.DELETE_BUTTON)},k=function(a){return a.find(h.NAME_ELEMENT)},l=function(a){return a.find(h.DESCRIPTION_ELEMENT)},m=function(a){return a.find(h.ACTIVATE_BUTTON)},n=function(a){return m(a).length?!0:!1},o=function(a){return a.find(h.CAPABILITIES_CONTAINER)},p=function(a){return o(a).length?!0:!1},q=function(a){return a.attr("data-type-id")},r=function(a){a.removeClass("announcement loading success fail capabilities")},s=function(a){r(a),a.addClass("announcement loading")},t=function(a){a.removeClass("announcement loading")},u=function(b){var c=a.Deferred();return r(b),b.addClass("announcement success"),setTimeout(function(){b.removeClass("announcement success"),c.resolve()},i),c},v=function(b){var c=a.Deferred();return r(b),b.addClass("announcement fail"),setTimeout(function(){b.removeClass("announcement fail"),c.resolve()},i),c},w=function(b){var d=q(b);if(""===d)return a.Deferred().resolve();s(b);var f=e["delete"](d);return f.done(function(){t(b),u(b).done(function(){b.remove()}).fail(c.exception)}),f.fail(function(){v(b)}),f},x=function(a,b){a.attr("data-val-snapshot",b)},y=function(a){return a.attr("data-val-snapshot")},z=function(a){var b=l(a);if(!b.hasClass("loading")){var c=b.text().trim();x(b,c)}},A=function(b){var d=q(b);if(""===d)return a.Deferred().resolve();var f=l(b);if(f.hasClass("loading"))return a.Deferred().resolve();var g=f.text().trim(),h=y(f);if(h==g)return a.Deferred().resolve();f.addClass("loading");var i=e.update({id:d,description:g});return i.done(function(a){f.removeClass("loading"),f.text(a.description)}).fail(c.exception),i.fail(function(){f.removeClass("loading")}),i},B=function(a){var b=k(a);if(!b.hasClass("loading")){var c=b.text().trim();x(b,c)}},C=function(b){var c=q(b);if(""===c)return a.Deferred().resolve();var d=k(b);if(d.hasClass("loading"))return a.Deferred().resolve();var f=d.text().trim(),g=y(d);if(g==f)return a.Deferred().resolve();d.addClass("loading");var h=e.update({id:c,name:f});return h.done(function(a){d.removeClass("loading"),d.text(a.name)}),h.fail(function(){d.removeClass("loading")}),h},D=function(b){var c=q(b);if(""===c)return a.Deferred().resolve();s(b);var f=e.update({id:c,state:e.constants.state.configured});return f.done(function(c){t(b);var e=u(b),f=d.render("mod_lti/tool_card",c);a.when(f,e).then(function(a){var c=a[0],e=a[1];d.replaceNode(b,c,e)})}),f.fail(function(){t(b),v(b)}),f},E=function(a){a.addClass("announcement capabilities")},F=function(a){a.removeClass("announcement capabilities")},G=function(a){p(a)?E(a):D(a)},H=function(a){var b=j(a);b.click(function(b){b.preventDefault(),w(a)}),b.keypress(function(a){a.metaKey||a.shiftKey||a.altKey||a.ctrlKey||(a.keyCode==g.ENTER||a.keyCode==g.SPACE)&&(a.preventDefault(),b.click())});var c=l(a);c.focus(function(b){b.preventDefault(),z(a)}),c.blur(function(b){b.preventDefault(),A(a)}),c.keypress(function(a){a.metaKey||a.shiftKey||a.altKey||a.ctrlKey||a.keyCode==g.ENTER&&(a.preventDefault(),c.blur())});var d=k(a);if(d.focus(function(b){b.preventDefault(),B(a)}),d.blur(function(b){b.preventDefault(),C(a)}),d.keypress(function(a){a.metaKey||a.shiftKey||a.altKey||a.ctrlKey||a.keyCode==g.ENTER&&(a.preventDefault(),d.blur())}),n(a)){var e=m(a);e.click(function(b){b.preventDefault(),G(a)}),e.keypress(function(a){a.metaKey||a.shiftKey||a.altKey||a.ctrlKey||(a.keyCode==g.ENTER||a.keyCode==g.SPACE)&&(a.preventDefault(),e.click())})}if(p(a)){var h=o(a);h.on(f.CAPABILITIES_AGREE,function(){D(a)}),h.on(f.CAPABILITIES_DECLINE,function(){F(a)})}};return{init:function(a){H(a)}}}); \ No newline at end of file +define(["jquery","core/ajax","core/notification","core/templates","mod_lti/tool_type","mod_lti/events","mod_lti/keys","core/str"],function(a,b,c,d,e,f,g,h){var i={DELETE_BUTTON:".delete",NAME_ELEMENT:".name",DESCRIPTION_ELEMENT:".description",CAPABILITIES_CONTAINER:".capabilities-container",ACTIVATE_BUTTON:".tool-card-footer a.activate"},j=2e3,k=function(a){return a.find(i.DELETE_BUTTON)},l=function(a){return a.find(i.NAME_ELEMENT)},m=function(a){return a.find(i.DESCRIPTION_ELEMENT)},n=function(a){return a.find(i.ACTIVATE_BUTTON)},o=function(a){return n(a).length?!0:!1},p=function(a){return a.find(i.CAPABILITIES_CONTAINER)},q=function(a){return p(a).length?!0:!1},r=function(a){return a.attr("data-type-id")},s=function(a){a.removeClass("announcement loading success fail capabilities")},t=function(a){s(a),a.addClass("announcement loading")},u=function(a){a.removeClass("announcement loading")},v=function(b){var c=a.Deferred();return s(b),b.addClass("announcement success"),setTimeout(function(){b.removeClass("announcement success"),c.resolve()},j),c},w=function(b){var c=a.Deferred();return s(b),b.addClass("announcement fail"),setTimeout(function(){b.removeClass("announcement fail"),c.resolve()},j),c},x=function(b){var d=a.Deferred(),f=r(b);return t(b),""===f?a.Deferred().resolve():(h.get_strings([{key:"delete",component:"mod_lti"},{key:"delete_confirmation",component:"mod_lti"},{key:"delete",component:"mod_lti"},{key:"cancel",component:"core"}]).done(function(a){c.confirm(a[0],a[1],a[2],a[3],function(){e["delete"](f).done(function(){u(b),v(b).done(function(){b.remove()}).fail(c.exception).always(function(){d.resolve()})}).fail(function(a){w(b),d.reject(a)})},function(){u(b),d.resolve()})}).fail(function(a){u(b),c.exception(a),d.reject(a)}),d)},y=function(a,b){a.attr("data-val-snapshot",b)},z=function(a){return a.attr("data-val-snapshot")},A=function(a){var b=m(a);if(!b.hasClass("loading")){var c=b.text().trim();y(b,c)}},B=function(b){var d=r(b);if(""===d)return a.Deferred().resolve();var f=m(b);if(f.hasClass("loading"))return a.Deferred().resolve();var g=f.text().trim(),h=z(f);if(h==g)return a.Deferred().resolve();f.addClass("loading");var i=e.update({id:d,description:g});return i.done(function(a){f.removeClass("loading"),f.text(a.description)}).fail(c.exception),i.fail(function(){f.removeClass("loading")}),i},C=function(a){var b=l(a);if(!b.hasClass("loading")){var c=b.text().trim();y(b,c)}},D=function(b){var c=r(b);if(""===c)return a.Deferred().resolve();var d=l(b);if(d.hasClass("loading"))return a.Deferred().resolve();var f=d.text().trim(),g=z(d);if(g==f)return a.Deferred().resolve();d.addClass("loading");var h=e.update({id:c,name:f});return h.done(function(a){d.removeClass("loading"),d.text(a.name)}),h.fail(function(){d.removeClass("loading")}),h},E=function(b){var c=r(b);if(""===c)return a.Deferred().resolve();t(b);var f=e.update({id:c,state:e.constants.state.configured});return f.done(function(c){u(b);var e=v(b),f=d.render("mod_lti/tool_card",c);a.when(f,e).then(function(a){var c=a[0],e=a[1];d.replaceNode(b,c,e)})}),f.fail(function(){u(b),w(b)}),f},F=function(a){a.addClass("announcement capabilities")},G=function(a){a.removeClass("announcement capabilities")},H=function(a){q(a)?F(a):E(a)},I=function(a){var b=k(a);b.click(function(b){b.preventDefault(),x(a)}),b.keypress(function(a){a.metaKey||a.shiftKey||a.altKey||a.ctrlKey||(a.keyCode==g.ENTER||a.keyCode==g.SPACE)&&(a.preventDefault(),b.click())});var c=m(a);c.focus(function(b){b.preventDefault(),A(a)}),c.blur(function(b){b.preventDefault(),B(a)}),c.keypress(function(a){a.metaKey||a.shiftKey||a.altKey||a.ctrlKey||a.keyCode==g.ENTER&&(a.preventDefault(),c.blur())});var d=l(a);if(d.focus(function(b){b.preventDefault(),C(a)}),d.blur(function(b){b.preventDefault(),D(a)}),d.keypress(function(a){a.metaKey||a.shiftKey||a.altKey||a.ctrlKey||a.keyCode==g.ENTER&&(a.preventDefault(),d.blur())}),o(a)){var e=n(a);e.click(function(b){b.preventDefault(),H(a)}),e.keypress(function(a){a.metaKey||a.shiftKey||a.altKey||a.ctrlKey||(a.keyCode==g.ENTER||a.keyCode==g.SPACE)&&(a.preventDefault(),e.click())})}if(q(a)){var h=p(a);h.on(f.CAPABILITIES_AGREE,function(){E(a)}),h.on(f.CAPABILITIES_DECLINE,function(){G(a)})}};return{init:function(a){I(a)}}}); \ No newline at end of file diff --git a/mod/lti/amd/build/tool_configure_controller.min.js b/mod/lti/amd/build/tool_configure_controller.min.js index a3bdb5c70a1..e0b00e9a7df 100644 --- a/mod/lti/amd/build/tool_configure_controller.min.js +++ b/mod/lti/amd/build/tool_configure_controller.min.js @@ -1 +1 @@ -define(["jquery","core/ajax","core/notification","core/templates","mod_lti/events","mod_lti/keys","mod_lti/tool_type"],function(a,b,c,d,e,f,g){var h={REGISTRATION_FEEDBACK_CONTAINER:"#registration-feedback-container",EXTERNAL_REGISTRATION_CONTAINER:"#external-registration-container",EXTERNAL_REGISTRATION_PAGE_CONTAINER:"#external-registration-page-container",CARTRIDGE_REGISTRATION_CONTAINER:"#cartridge-registration-container",CARTRIDGE_REGISTRATION_FORM:"#cartridge-registration-form",ADD_TOOL_FORM:"#add-tool-form",TOOL_LIST_CONTAINER:"#tool-list-container",TOOL_CREATE_BUTTON:"#tool-create-button",REGISTRATION_CHOICE_CONTAINER:"#registration-choice-container",TOOL_URL:"#tool-url"},i=function(){return a(h.TOOL_CREATE_BUTTON)},j=function(){return a(h.REGISTRATION_FEEDBACK_CONTAINER)},k=function(){return a(h.TOOL_LIST_CONTAINER)},l=function(){return a(h.EXTERNAL_REGISTRATION_CONTAINER)},m=function(){return a(h.CARTRIDGE_REGISTRATION_CONTAINER)},n=function(){return a(h.REGISTRATION_CHOICE_CONTAINER)},o=function(){return a(h.TOOL_URL).val()},p=function(){l().addClass("hidden")},q=function(){m().addClass("hidden")},r=function(){n().addClass("hidden")},s=function(a){q(),r(),l().removeClass("hidden"),l().find(h.EXTERNAL_REGISTRATION_PAGE_CONTAINER).attr("data-registration-url",a),u(l())},t=function(a){p(),r(),m().removeClass("hidden"),m().find(h.CARTRIDGE_REGISTRATION_FORM).attr("data-cartridge-url",a),u(m())},u=function(a){var b=a.children().clone(!0,!0);a.empty(),a.append(b)},v=function(){y()||(p(),q(),n().removeClass("hidden"),u(n()))},w=function(){k().addClass("hidden")},x=function(){k().removeClass("hidden")},y=function(){return a.trim(j().html())},z=function(a){d.render("mod_lti/registration_feedback",a).done(function(a){p(),q(),r();var b=j();b.append(a)}).fail(c.exception)},A=function(){var a=j();a.empty(),v()},B=function(a){a.addClass("loading")},C=function(a){a.removeClass("loading")},D=function(){var a=k();B(a),g.query().done(function(b){d.render("mod_lti/tool_list",{tools:b}).done(function(b,c){a.empty(),a.append(b),d.runTemplateJS(c)}).fail(c.exception)}).fail(c.exception).always(function(){C(a)})},E=function(){var b=o();if(""===b)return a.Deferred().resolve();var d=i();B(d);var f=g.isCartridge(b);return f.always(function(){C(d)}),f.done(function(c){c.iscartridge?(a(h.TOOL_URL).val(""),a(document).trigger(e.START_CARTRIDGE_REGISTRATION,b)):(s(b),a(h.TOOL_URL).val(""),a(document).trigger(e.START_EXTERNAL_REGISTRATION),w())}),f.fail(c.exception),f},F=function(){a(document).on(e.NEW_TOOL_TYPE,function(){D()}),a(document).on(e.STOP_EXTERNAL_REGISTRATION,function(){x(),v()}),a(document).on(e.START_CARTRIDGE_REGISTRATION,function(a,b){t(b)}),a(document).on(e.STOP_CARTRIDGE_REGISTRATION,function(){m().find(h.CARTRIDGE_REGISTRATION_FORM).removeAttr("data-cartridge-url"),v()}),a(document).on(e.REGISTRATION_FEEDBACK,function(a,b){z(b)});var b=a(h.ADD_TOOL_FORM);b.submit(function(a){a.preventDefault(),E()});var c=j();c.click(function(a){a.preventDefault(),A()}),c.keypress(function(a){a.metaKey||a.shiftKey||a.altKey||a.ctrlKey||(a.keyCode==f.ENTER||a.keyCode==f.SPACE)&&(a.preventDefault(),A())})};return{init:function(){F(),D()}}}); \ No newline at end of file +define(["jquery","core/ajax","core/notification","core/templates","mod_lti/events","mod_lti/keys","mod_lti/tool_type","mod_lti/tool_proxy","core/str"],function(a,b,c,d,e,f,g,h,i){var j={EXTERNAL_REGISTRATION_CONTAINER:"#external-registration-container",EXTERNAL_REGISTRATION_PAGE_CONTAINER:"#external-registration-page-container",CARTRIDGE_REGISTRATION_CONTAINER:"#cartridge-registration-container",CARTRIDGE_REGISTRATION_FORM:"#cartridge-registration-form",ADD_TOOL_FORM:"#add-tool-form",TOOL_LIST_CONTAINER:"#tool-list-container",TOOL_CREATE_BUTTON:"#tool-create-button",REGISTRATION_CHOICE_CONTAINER:"#registration-choice-container",TOOL_URL:"#tool-url"},k=function(){return a(j.TOOL_CREATE_BUTTON)},l=function(){return a(j.TOOL_LIST_CONTAINER)},m=function(){return a(j.EXTERNAL_REGISTRATION_CONTAINER)},n=function(){return a(j.CARTRIDGE_REGISTRATION_CONTAINER)},o=function(){return a(j.REGISTRATION_CHOICE_CONTAINER)},p=function(){return a(j.TOOL_URL).val()},q=function(){m().addClass("hidden")},r=function(){n().addClass("hidden")},s=function(){o().addClass("hidden")},t=function(){r(),s(),m().removeClass("hidden"),v(m())},u=function(a){q(),s(),n().removeClass("hidden"),n().find(j.CARTRIDGE_REGISTRATION_FORM).attr("data-cartridge-url",a),v(n())},v=function(a){var b=a.children().clone(!0,!0);a.empty(),a.append(b)},w=function(){q(),r(),o().removeClass("hidden"),v(o())},x=function(){l().addClass("hidden")},y=function(){l().removeClass("hidden")},z=function(a){var b=a.error?"error":"success";c.addNotification({message:"

"+a.status+"

"+a.message+"

",type:b})},A=function(a){a.addClass("loading")},B=function(a){a.removeClass("loading")},C=function(){var b=a.Deferred(),e=l();A(e),a.when(g.query(),h.query({orphanedonly:!0})).done(function(a,c){d.render("mod_lti/tool_list",{tools:a,proxies:c}).done(function(a,c){e.empty(),e.append(a),d.runTemplateJS(c),b.resolve()}).fail(b.reject)}).fail(b.reject),b.fail(c.exception).always(function(){B(e)})},D=function(){var b=a.trim(p());if(""===b)return a.Deferred().resolve();var d=k();A(d);var f=g.isCartridge(b);return f.always(function(){B(d)}),f.done(function(c){c.iscartridge?(a(j.TOOL_URL).val(""),a(document).trigger(e.START_CARTRIDGE_REGISTRATION,b)):a(document).trigger(e.START_EXTERNAL_REGISTRATION,{url:b})}),f.fail(function(){i.get_strings([{key:"error",component:"moodle"},{key:"errorbadurl",component:"mod_lti"}]).done(function(b){a(document).trigger(e.REGISTRATION_FEEDBACK,{status:b[0],message:b[1],error:!0})}).fail(c.exception)}),f},E=function(){a(document).on(e.NEW_TOOL_TYPE,function(){C()}),a(document).on(e.START_EXTERNAL_REGISTRATION,function(){t(),a(j.TOOL_URL).val(""),x()}),a(document).on(e.STOP_EXTERNAL_REGISTRATION,function(){y(),w()}),a(document).on(e.START_CARTRIDGE_REGISTRATION,function(a,b){u(b)}),a(document).on(e.STOP_CARTRIDGE_REGISTRATION,function(){n().find(j.CARTRIDGE_REGISTRATION_FORM).removeAttr("data-cartridge-url"),w()}),a(document).on(e.REGISTRATION_FEEDBACK,function(a,b){z(b)});var b=a(j.ADD_TOOL_FORM);b.submit(function(a){a.preventDefault(),D()})};return{init:function(){E(),C()}}}); \ No newline at end of file diff --git a/mod/lti/amd/build/tool_proxy.min.js b/mod/lti/amd/build/tool_proxy.min.js index 7e2826f9980..f7db8dcd1ec 100644 --- a/mod/lti/amd/build/tool_proxy.min.js +++ b/mod/lti/amd/build/tool_proxy.min.js @@ -1 +1 @@ -define(["core/ajax","core/notification"],function(a,b){return{"delete":function(c){var d={methodname:"mod_lti_delete_tool_proxy",args:{id:c}},e=a.call([d])[0];return e.fail(b.exception),e},create:function(c){var d={methodname:"mod_lti_create_tool_proxy",args:c},e=a.call([d])[0];return e.fail(b.exception),e}}}); \ No newline at end of file +define(["core/ajax","core/notification"],function(a,b){return{query:function(c){var d={methodname:"mod_lti_get_tool_proxies",args:c||{}},e=a.call([d])[0];return e.fail(b.exception),e},"delete":function(c){var d={methodname:"mod_lti_delete_tool_proxy",args:{id:c}},e=a.call([d])[0];return e.fail(b.exception),e},create:function(c){var d={methodname:"mod_lti_create_tool_proxy",args:c},e=a.call([d])[0];return e.fail(b.exception),e}}}); \ No newline at end of file diff --git a/mod/lti/amd/build/tool_proxy_card_controller.min.js b/mod/lti/amd/build/tool_proxy_card_controller.min.js new file mode 100644 index 00000000000..cb52434beee --- /dev/null +++ b/mod/lti/amd/build/tool_proxy_card_controller.min.js @@ -0,0 +1 @@ +define(["jquery","core/ajax","core/notification","core/templates","mod_lti/tool_proxy","mod_lti/events","mod_lti/keys","core/str"],function(a,b,c,d,e,f,g,h){var i={DELETE_BUTTON:".delete",CAPABILITIES_CONTAINER:".capabilities-container",ACTIVATE_BUTTON:".tool-card-footer a.activate"},j=2e3,k=function(a){return a.find(i.DELETE_BUTTON)},l=function(a){return a.find(i.ACTIVATE_BUTTON)},m=function(a){return a.attr("data-proxy-id")},n=function(a){a.removeClass("announcement loading success fail capabilities")},o=function(a){n(a),a.addClass("announcement loading")},p=function(a){a.removeClass("announcement loading")},q=function(b){var c=a.Deferred();return n(b),b.addClass("announcement success"),setTimeout(function(){b.removeClass("announcement success"),c.resolve()},j),c},r=function(b){var c=a.Deferred();return n(b),b.addClass("announcement fail"),setTimeout(function(){b.removeClass("announcement fail"),c.resolve()},j),c},s=function(b){var d=a.Deferred(),f=m(b);return o(b),""===f?a.Deferred().resolve():(h.get_strings([{key:"delete",component:"mod_lti"},{key:"delete_confirmation",component:"mod_lti"},{key:"delete",component:"mod_lti"},{key:"cancel",component:"core"}]).done(function(a){c.confirm(a[0],a[1],a[2],a[3],function(){e["delete"](f).done(function(){p(b),q(b).done(function(){b.remove(),d.resolve()}).fail(c.exception)}).fail(function(a){r(b),d.reject(a)})},function(){p(b),d.resolve()})}).fail(function(a){p(b),c.exception(a),d.reject(a)}),d)},t=function(b){var c={proxyid:m(b)};a(document).trigger(f.START_EXTERNAL_REGISTRATION,c)},u=function(a){var b=k(a);b.click(function(b){b.preventDefault(),s(a)}),b.keypress(function(a){a.metaKey||a.shiftKey||a.altKey||a.ctrlKey||(a.keyCode==g.ENTER||a.keyCode==g.SPACE)&&(a.preventDefault(),b.click())});var c=l(a);c.click(function(b){b.preventDefault(),t(a)}),c.keypress(function(a){a.metaKey||a.shiftKey||a.altKey||a.ctrlKey||(a.keyCode==g.ENTER||a.keyCode==g.SPACE)&&(a.preventDefault(),c.click())})};return{init:function(a){u(a)}}}); \ No newline at end of file diff --git a/mod/lti/amd/build/tool_type.min.js b/mod/lti/amd/build/tool_type.min.js index befef5e682f..bc969350cf8 100644 --- a/mod/lti/amd/build/tool_type.min.js +++ b/mod/lti/amd/build/tool_type.min.js @@ -1 +1 @@ -define(["core/ajax","core/notification"],function(a,b){return{query:function(c){var d={methodname:"mod_lti_get_tool_types",args:c||{}},e=a.call([d])[0];return e.fail(b.exception),e},create:function(c){var d={methodname:"mod_lti_create_tool_type",args:c},e=a.call([d])[0];return e.fail(b.exception),e},update:function(c){var d={methodname:"mod_lti_update_tool_type",args:c},e=a.call([d])[0];return e.fail(b.exception),e},"delete":function(c){var d={methodname:"mod_lti_delete_tool_type",args:{id:c}},e=a.call([d])[0];return e.fail(b.exception),e},getFromToolProxyId:function(a){return this.query({toolproxyid:a})},isCartridge:function(c){var d={methodname:"mod_lti_is_cartridge",args:{url:c}},e=a.call([d])[0];return e.fail(b.exception),e},constants:{state:{configured:1,pending:2,rejected:3}}}}); \ No newline at end of file +define(["core/ajax","core/notification"],function(a,b){return{query:function(c){var d={methodname:"mod_lti_get_tool_types",args:c||{}},e=a.call([d])[0];return e.fail(b.exception),e},create:function(c){var d={methodname:"mod_lti_create_tool_type",args:c},e=a.call([d])[0];return e.fail(b.exception),e},update:function(c){var d={methodname:"mod_lti_update_tool_type",args:c},e=a.call([d])[0];return e.fail(b.exception),e},"delete":function(c){var d={methodname:"mod_lti_delete_tool_type",args:{id:c}},e=a.call([d])[0];return e.fail(b.exception),e},getFromToolProxyId:function(a){return this.query({toolproxyid:a})},isCartridge:function(b){var c={methodname:"mod_lti_is_cartridge",args:{url:b}},d=a.call([c])[0];return d},constants:{state:{configured:1,pending:2,rejected:3}}}}); \ No newline at end of file diff --git a/mod/lti/amd/src/external_registration.js b/mod/lti/amd/src/external_registration.js index cfffbc24ee3..4b65abfd76f 100644 --- a/mod/lti/amd/src/external_registration.js +++ b/mod/lti/amd/src/external_registration.js @@ -34,7 +34,6 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e function($, ajax, notification, templates, ltiEvents, toolProxy, toolType, KEYS, str) { var SELECTORS = { - REGISTRATION_URL: '#external-registration-url', EXTERNAL_REGISTRATION_CONTAINER: '#external-registration-page-container', EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER: '#external-registration-template-container', EXTERNAL_REGISTRATION_CANCEL_BUTTON: '#cancel-external-registration', @@ -43,17 +42,6 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e CAPABILITIES_AGREE_CONTAINER: '.capabilities-container', }; - /** - * Return the URL the user entered for the registration. - * - * @method getRegistrationURL - * @private - * @return string - */ - var getRegistrationURL = function() { - return $(SELECTORS.EXTERNAL_REGISTRATION_CONTAINER).attr('data-registration-url'); - }; - /** * Return the external registration cancel button element. This button is * the cancel button that appears while the iframe is rendered. @@ -230,6 +218,17 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e button.removeAttr('data-tool-proxy-id'); }; + /** + * Returns true if a tool proxy id has been recorded. + * + * @method hasToolProxyId + * @private + * @return bool + */ + var hasToolProxyId = function() { + return getToolProxyId() ? true : false; + }; + /** * Checks if this process has created a tool proxy within * Moodle yet. @@ -239,7 +238,32 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e * @return bool */ var hasCreatedToolProxy = function() { - return getToolProxyId() ? true : false; + var button = getExternalRegistrationCancelButton(); + return button.attr('data-tool-proxy-new') && hasToolProxyId(); + }; + + /** + * Records that this process has created a tool proxy. + * + * @method setProxyAsNew + * @private + * @return bool + */ + 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 bool + */ + var setProxyAsOld = function() { + var button = getExternalRegistrationCancelButton(); + return button.removeAttr('data-tool-proxy-new'); }; /** @@ -412,53 +436,76 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e * 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 submitExternalRegistration + * @method createAndRegisterToolProxy * @private + * @param url Tool registration URL to register * @return object jQuery Deferred object */ - var submitExternalRegistration = function() { + var createAndRegisterToolProxy = function(url) { var promise = $.Deferred(); - var url = getRegistrationURL(); - if (url === "") { + if (!url || url === "") { // No URL has been input so do nothing. promise.resolve(); } else { - // A tool proxy needs to exists before the external page is rendered because + // 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) { - var id = result.id; - var regURL = result.regurl; - - // 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) { - - registrationRequest.reg_url = regURL; - renderExternalRegistrationWindow(registrationRequest).done(function() { - - promise.resolve(); - - }).fail(promise.fail); - - }).fail(promise.fail); - - }).fail(function(exception) { - // Clean up. - cancelRegistration(); - // Let the user know what the error is. - $(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, {status: 'error', message: exception.message, error: true}); - promise.reject(exception); - }); + 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. + str.get_string('error', 'moodle') + .done(function (s) { + var feedback = { + status: s, + message: exception.message, + error: true + }; + $(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, feedback); + }) + .fail(notification.exception); + promise.reject(exception); + }); } return promise; }; + /** + * Loads the window to register a proxy, given an ID. + * + * @method registerProxy + * @private + * @param id Proxy id to register + * @return 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. @@ -467,9 +514,10 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e * @private */ var finishExternalRegistration = function() { - if (hasCreatedToolProxy()) { + if (hasToolProxyId()) { clearToolProxyId(); } + setProxyAsOld(false); hideExternalRegistrationContent(); var container = getExternalRegistrationTemplateContainer(); @@ -486,9 +534,17 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e */ var registerEventListeners = function() { - $(document).on(ltiEvents.START_EXTERNAL_REGISTRATION, function() { - submitExternalRegistration(); - }); + $(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) { diff --git a/mod/lti/amd/src/tool_card_controller.js b/mod/lti/amd/src/tool_card_controller.js index 1f0a222437a..19b4c48561a 100644 --- a/mod/lti/amd/src/tool_card_controller.js +++ b/mod/lti/amd/src/tool_card_controller.js @@ -26,8 +26,9 @@ * @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_type', 'mod_lti/events', 'mod_lti/keys'], - function($, ajax, notification, templates, toolType, ltiEvents, KEYS) { +define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/tool_type', 'mod_lti/events', 'mod_lti/keys', + 'core/str'], + function($, ajax, notification, templates, toolType, ltiEvents, KEYS, str) { var SELECTORS = { DELETE_BUTTON: '.delete', @@ -226,23 +227,61 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/t * @return object jQuery Deferred object */ var deleteType = function(element) { + var promise = $.Deferred(); var typeId = getTypeId(element); + startLoading(element); if (typeId === "") { return $.Deferred().resolve(); } - startLoading(element); - var promise = toolType.delete(typeId); - - promise.done(function() { - stopLoading(element); - announceSuccess(element).done(function() { - element.remove(); - }).fail(notification.exception); - }); - - promise.fail(function() { announceFailure(element); }); + 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; }; diff --git a/mod/lti/amd/src/tool_configure_controller.js b/mod/lti/amd/src/tool_configure_controller.js index 39a63f87127..9277df4da03 100644 --- a/mod/lti/amd/src/tool_configure_controller.js +++ b/mod/lti/amd/src/tool_configure_controller.js @@ -25,11 +25,11 @@ * @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/keys', 'mod_lti/tool_type'], - function($, ajax, notification, templates, ltiEvents, KEYS, toolType) { +define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/events', 'mod_lti/keys', 'mod_lti/tool_type', + 'mod_lti/tool_proxy', 'core/str'], + function($, ajax, notification, templates, ltiEvents, KEYS, toolType, toolProxy, str) { var SELECTORS = { - REGISTRATION_FEEDBACK_CONTAINER: '#registration-feedback-container', EXTERNAL_REGISTRATION_CONTAINER: '#external-registration-container', EXTERNAL_REGISTRATION_PAGE_CONTAINER: '#external-registration-page-container', CARTRIDGE_REGISTRATION_CONTAINER: '#cartridge-registration-container', @@ -52,17 +52,6 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e return $(SELECTORS.TOOL_CREATE_BUTTON); }; - /** - * Get the registration feedback container element. - * - * @method getRegistrationFeedbackContainer - * @private - * @return object jQuery object - */ - var getRegistrationFeedbackContainer = function() { - return $(SELECTORS.REGISTRATION_FEEDBACK_CONTAINER); - }; - /** * Get the tool list container element. * @@ -155,11 +144,10 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e * @method showExternalRegistration * @private */ - var showExternalRegistration = function(url) { + var showExternalRegistration = function() { hideCartridgeRegistration(); hideRegistrationChoices(); getExternalRegistrationContainer().removeClass('hidden'); - getExternalRegistrationContainer().find(SELECTORS.EXTERNAL_REGISTRATION_PAGE_CONTAINER).attr('data-registration-url', url); screenReaderAnnounce(getExternalRegistrationContainer()); }; @@ -200,13 +188,6 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e * @private */ var showRegistrationChoices = function() { - if (isRegistrationFeedbackVisible()) { - // If the registration feedback is visible then we don't need - // to do anything because it will display this content when it's - // closed. - return; - } - hideExternalRegistration(); hideCartridgeRegistration(); getRegistrationChoiceContainer().removeClass('hidden'); @@ -233,17 +214,6 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e getToolListContainer().removeClass('hidden'); }; - /** - * Check if the registration feedback is being displayed. - * - * @method isRegistrationFeedbackVisible - * @private - * @return bool - */ - var isRegistrationFeedbackVisible = function() { - return $.trim(getRegistrationFeedbackContainer().html()); - }; - /** * Display the registration feedback alert and hide the other panels. * @@ -251,27 +221,11 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e * @private */ var showRegistrationFeedback = function(data) { - templates.render('mod_lti/registration_feedback', data).done(function(html) { - hideExternalRegistration(); - hideCartridgeRegistration(); - hideRegistrationChoices(); - - var container = getRegistrationFeedbackContainer(); - container.append(html); - }).fail(notification.exception); - }; - - /** - * Hide the registration feedback alert and restore the choices panel. - * - * @method showRegistrationFeedback - * @private - */ - var clearRegistrationFeedback = function() { - var container = getRegistrationFeedbackContainer(); - container.empty(); - - showRegistrationChoices(); + var type = data.error ? 'error' : 'success'; + notification.addNotification({ + message: '

' + data.status + '

' + data.message + '

', + type: type + }); }; /** @@ -303,16 +257,29 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e * @private */ var reloadToolList = function() { + var promise = $.Deferred(); var container = getToolListContainer(); startLoading(container); - toolType.query().done(function(types) { - templates.render('mod_lti/tool_list', {tools: types}).done(function(html, js) { - container.empty(); - container.append(html); - templates.runTemplateJS(js); - }).fail(notification.exception); - }).fail(notification.exception).always(function() { stopLoading(container); }); + $.when( + toolType.query(), + toolProxy.query({'orphanedonly': true}) + ) + .done(function(types, proxies) { + templates.render('mod_lti/tool_list', {tools: types, proxies: proxies}) + .done(function(html, js) { + container.empty(); + container.append(html); + templates.runTemplateJS(js); + promise.resolve(); + }).fail(promise.reject); + }) + .fail(promise.reject); + + promise.fail(notification.exception) + .always(function () { + stopLoading(container); + }); }; /** @@ -324,7 +291,7 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e * @return object jQuery deferred object */ var addTool = function() { - var url = getToolURL(); + var url = $.trim(getToolURL()); if (url === "") { return $.Deferred().resolve(); @@ -342,14 +309,22 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e $(SELECTORS.TOOL_URL).val(''); $(document).trigger(ltiEvents.START_CARTRIDGE_REGISTRATION, url); } else { - showExternalRegistration(url); - $(SELECTORS.TOOL_URL).val(''); - $(document).trigger(ltiEvents.START_EXTERNAL_REGISTRATION); - hideToolList(); + $(document).trigger(ltiEvents.START_EXTERNAL_REGISTRATION, {url: url}); } }); - promise.fail(notification.exception); + promise.fail(function () { + str.get_strings([{key: 'error', component: 'moodle'}, + {key: 'errorbadurl', component: 'mod_lti'}]) + .done(function (s) { + $(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, { + status: s[0], + message: s[1], + error: true + }); + }) + .fail(notification.exception); + }); return promise; }; @@ -368,6 +343,12 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e reloadToolList(); }); + $(document).on(ltiEvents.START_EXTERNAL_REGISTRATION, function() { + showExternalRegistration(); + $(SELECTORS.TOOL_URL).val(''); + hideToolList(); + }); + $(document).on(ltiEvents.STOP_EXTERNAL_REGISTRATION, function() { showToolList(); showRegistrationChoices(); @@ -392,19 +373,6 @@ define(['jquery', 'core/ajax', 'core/notification', 'core/templates', 'mod_lti/e addTool(); }); - var feedbackContainer = getRegistrationFeedbackContainer(); - feedbackContainer.click(function(e) { - e.preventDefault(); - clearRegistrationFeedback(); - }); - feedbackContainer.keypress(function(e) { - if (!e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) { - if (e.keyCode == KEYS.ENTER || e.keyCode == KEYS.SPACE) { - e.preventDefault(); - clearRegistrationFeedback(); - } - } - }); }; return /** @alias module:mod_lti/cartridge_registration_form */ { diff --git a/mod/lti/amd/src/tool_proxy.js b/mod/lti/amd/src/tool_proxy.js index 97d97fd0442..8bc62b3edb6 100644 --- a/mod/lti/amd/src/tool_proxy.js +++ b/mod/lti/amd/src/tool_proxy.js @@ -25,6 +25,30 @@ */ define(['core/ajax', 'core/notification'], function(ajax, notification) { return /** @alias module:mod_lti/tool_proxy */ { + /** + * 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 Search parameters + * @return object 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. * diff --git a/mod/lti/amd/src/tool_proxy_card_controller.js b/mod/lti/amd/src/tool_proxy_card_controller.js new file mode 100644 index 00000000000..c2b1a250f8e --- /dev/null +++ b/mod/lti/amd/src/tool_proxy_card_controller.js @@ -0,0 +1,284 @@ +// 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 . + +/** + * 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 + * @class tool_card_controller + * @package mod_lti + * @copyright 2016 John Okely + * @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 object jQuery object representing the tool card. + * @return object jQuery object + */ + var getDeleteButton = function(element) { + return element.find(SELECTORS.DELETE_BUTTON); + }; + + /** + * Return the activate button for the type. + * + * @method getActivateButton + * @private + * @param object jQuery object representing the tool card. + * @return object jQuery object + */ + var getActivateButton = function(element) { + return element.find(SELECTORS.ACTIVATE_BUTTON); + }; + + /** + * Get the type id. + * + * @method getTypeId + * @private + * @param object 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 object 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 object jQuery object representing the tool card. + */ + var startLoading = function(element) { + clearAllAnnouncements(element); + element.addClass('announcement loading'); + }; + + /** + * Hide the loading announcement. + * + * @method stopLoading + * @private + * @param object 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 object jQuery object representing the tool card. + * @return object 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 object jQuery object representing the tool card. + * @return object 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 object jQuery object representing the tool card. + * @return object 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 object 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 object 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 object jQuery object representing the tool card. + */ + init: function(element) { + registerEventListeners(element); + } + }; +}); diff --git a/mod/lti/amd/src/tool_type.js b/mod/lti/amd/src/tool_type.js index d8605bcdb1d..15efac6d738 100644 --- a/mod/lti/amd/src/tool_type.js +++ b/mod/lti/amd/src/tool_type.js @@ -137,6 +137,8 @@ define(['core/ajax', 'core/notification'], function(ajax, notification) { /** * 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 @@ -152,8 +154,6 @@ define(['core/ajax', 'core/notification'], function(ajax, notification) { var promise = ajax.call([request])[0]; - promise.fail(notification.exception); - return promise; }, diff --git a/mod/lti/classes/external.php b/mod/lti/classes/external.php index ff58cd51ecd..fca7c77906d 100644 --- a/mod/lti/classes/external.php +++ b/mod/lti/classes/external.php @@ -42,12 +42,12 @@ require_once($CFG->dirroot . '/mod/lti/locallib.php'); class mod_lti_external extends external_api { /** - * Returns description of a tool type + * Returns structure be used for returning a tool type from a web service. * * @return external_function_parameters * @since Moodle 3.1 */ - private static function get_tool_type_return_parameters() { + private static function tool_type_return_structure() { return new external_single_structure( array( 'id' => new external_value(PARAM_INT, 'Tool type id'), @@ -90,7 +90,7 @@ class mod_lti_external extends external_api { * @return external_function_parameters * @since Moodle 3.1 */ - private static function get_tool_proxy_return_parameters() { + private static function tool_proxy_return_structure() { return new external_function_parameters( array( 'id' => new external_value(PARAM_INT, 'Tool proxy id'), @@ -113,6 +113,59 @@ class mod_lti_external extends external_api { * Returns description of method parameters * * @return external_function_parameters + * @since Moodle 3.1 + */ + public static function get_tool_proxies_parameters() { + return new external_function_parameters( + array( + 'orphanedonly' => new external_value(PARAM_BOOL, 'Orphaned tool types only', VALUE_DEFAULT, 0) + ) + ); + } + + /** + * Returns the tool types. + * + * @param bool $orphanedonly Retrieve only tool proxies that do not have a corresponding tool type + * @return array of tool types + * @since Moodle 3.1 + * @throws moodle_exception + */ + public static function get_tool_proxies($orphanedonly) { + global $PAGE; + $params = self::validate_parameters(self::get_tool_proxies_parameters(), + array( + 'orphanedonly' => $orphanedonly + )); + $orphanedonly = $params['orphanedonly']; + + $proxies = array(); + $context = context_system::instance(); + + self::validate_context($context); + require_capability('moodle/site:config', $context); + + $proxies = lti_get_tool_proxies($orphanedonly); + + return array_map('serialise_tool_proxy', $proxies); + } + + /** + * Returns description of method result value. + * + * @return external_description + * @since Moodle 3.1 + */ + public static function get_tool_proxies_returns() { + return new external_multiple_structure( + self::tool_type_return_structure() + ); + } + + /** + * Returns description of method parameters. + * + * @return external_function_parameters * @since Moodle 3.0 */ public static function get_tool_launch_data_parameters() { @@ -495,7 +548,7 @@ class mod_lti_external extends external_api { * @since Moodle 3.1 */ public static function create_tool_proxy_returns() { - return self::get_tool_proxy_return_parameters(); + return self::tool_proxy_return_structure(); } /** @@ -545,7 +598,7 @@ class mod_lti_external extends external_api { * @since Moodle 3.1 */ public static function delete_tool_proxy_returns() { - return self::get_tool_proxy_return_parameters(); + return self::tool_proxy_return_structure(); } /** @@ -598,6 +651,7 @@ class mod_lti_external extends external_api { 'lti_version' => new external_value(PARAM_ALPHANUMEXT, 'LTI version'), 'reg_key' => new external_value(PARAM_TEXT, 'Tool proxy registration key'), 'reg_password' => new external_value(PARAM_TEXT, 'Tool proxy registration password'), + 'reg_url' => new external_value(PARAM_TEXT, 'Tool proxy registration url'), 'tc_profile_url' => new external_value(PARAM_URL, 'Tool consumers profile URL'), 'launch_presentation_return_url' => new external_value(PARAM_URL, 'URL to redirect on registration completion'), ) @@ -657,7 +711,7 @@ class mod_lti_external extends external_api { */ public static function get_tool_types_returns() { return new external_multiple_structure( - self::get_tool_type_return_parameters() + self::tool_type_return_structure() ); } @@ -745,7 +799,7 @@ class mod_lti_external extends external_api { * @since Moodle 3.1 */ public static function create_tool_type_returns() { - return self::get_tool_type_return_parameters(); + return self::tool_type_return_structure(); } /** @@ -828,7 +882,7 @@ class mod_lti_external extends external_api { * @since Moodle 3.1 */ public static function update_tool_type_returns() { - return self::get_tool_type_return_parameters(); + return self::tool_type_return_structure(); } /** diff --git a/mod/lti/classes/output/renderer.php b/mod/lti/classes/output/renderer.php index f49d46542b0..b94178da9f7 100644 --- a/mod/lti/classes/output/renderer.php +++ b/mod/lti/classes/output/renderer.php @@ -56,6 +56,7 @@ class renderer extends plugin_renderer_base { * @return string html for the page */ public function render_external_registration_return_page($page) { - return ''; + $data = $page->export_for_template($this); + return parent::render_from_template('mod_lti/external_registration_return', $data); } } diff --git a/mod/lti/db/services.php b/mod/lti/db/services.php index 9099df54264..02d24ad5c02 100644 --- a/mod/lti/db/services.php +++ b/mod/lti/db/services.php @@ -54,12 +54,21 @@ $functions = array( 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) ), + 'mod_lti_get_tool_proxies' => array( + 'classname' => 'mod_lti_external', + 'methodname' => 'get_tool_proxies', + 'description' => 'Get a list of the tool proxies', + 'type' => 'read', + 'capabilities' => 'moodle/site:config', + 'ajax' => true + ), + 'mod_lti_create_tool_proxy' => array( 'classname' => 'mod_lti_external', 'methodname' => 'create_tool_proxy', 'description' => 'Create a tool proxy', 'type' => 'write', - 'capabilities' => 'mod/lti:manage', + 'capabilities' => 'moodle/site:config', 'ajax' => true ), @@ -68,7 +77,7 @@ $functions = array( 'methodname' => 'delete_tool_proxy', 'description' => 'Delete a tool proxy', 'type' => 'write', - 'capabilities' => 'mod/lti:manage', + 'capabilities' => 'moodle/site:config', 'ajax' => true ), @@ -77,7 +86,7 @@ $functions = array( 'methodname' => 'get_tool_proxy_registration_request', 'description' => 'Get a registration request for a tool proxy', 'type' => 'read', - 'capabilities' => 'mod/lti:manage', + 'capabilities' => 'moodle/site:config', 'ajax' => true ), @@ -86,7 +95,7 @@ $functions = array( 'methodname' => 'get_tool_types', 'description' => 'Get a list of the tool types', 'type' => 'read', - 'capabilities' => 'mod/lti:manage', + 'capabilities' => 'moodle/site:config', 'ajax' => true ), @@ -95,7 +104,7 @@ $functions = array( 'methodname' => 'create_tool_type', 'description' => 'Create a tool type', 'type' => 'write', - 'capabilities' => 'mod/lti:manage', + 'capabilities' => 'moodle/site:config', 'ajax' => true ), @@ -104,7 +113,7 @@ $functions = array( 'methodname' => 'update_tool_type', 'description' => 'Update a tool type', 'type' => 'write', - 'capabilities' => 'mod/lti:manage', + 'capabilities' => 'moodle/site:config', 'ajax' => true ), @@ -113,7 +122,7 @@ $functions = array( 'methodname' => 'delete_tool_type', 'description' => 'Delete a tool type', 'type' => 'write', - 'capabilities' => 'mod/lti:manage', + 'capabilities' => 'moodle/site:config', 'ajax' => true ), @@ -122,7 +131,7 @@ $functions = array( 'methodname' => 'is_cartridge', 'description' => 'Determine if the given url is for a cartridge', 'type' => 'read', - 'capabilities' => 'mod/lti:manage', + 'capabilities' => 'moodle/site:config', 'ajax' => true ), ); diff --git a/mod/lti/externalregistrationreturn.php b/mod/lti/externalregistrationreturn.php index 8ccb4504659..b6c8fc1a938 100644 --- a/mod/lti/externalregistrationreturn.php +++ b/mod/lti/externalregistrationreturn.php @@ -42,7 +42,13 @@ $pageurl = new moodle_url('/mod/lti/externalregistrationreturn.php'); $PAGE->set_context($systemcontext); $PAGE->set_url($pageurl); $PAGE->set_pagelayout('maintenance'); -echo $OUTPUT->header(); +$output = $PAGE->get_renderer('mod_lti'); +echo $output->header(); + $params = array('message' => s($msg), 'error' => s($err), 'id' => $id, 'status' => s($status)); + +$page = new \mod_lti\output\external_registration_return_page(); +echo $output->render($page); + $PAGE->requires->js_call_amd('mod_lti/external_registration_return', 'init', $params); -echo $OUTPUT->footer(); +echo $output->footer(); diff --git a/mod/lti/lang/en/lti.php b/mod/lti/lang/en/lti.php index 926f21370ff..5f992f0f475 100644 --- a/mod/lti/lang/en/lti.php +++ b/mod/lti/lang/en/lti.php @@ -162,6 +162,7 @@ $string['embed_no_blocks'] = 'Embed, without blocks'; $string['enableemailnotification'] = 'Send notification emails'; $string['enableemailnotification_help'] = 'If enabled, students will receive email notification when their tool submissions are graded.'; $string['enterkeyandsecret'] = 'Enter your consumer key and shared secret'; +$string['errorbadurl'] = 'URL is not a valid tool URL or cartridge.'; $string['errormisconfig'] = 'Misconfigured tool. Please ask your Moodle administrator to fix the configuration of the tool.'; $string['existing_window'] = 'Existing window'; $string['extensions'] = 'LTI extension services'; diff --git a/mod/lti/locallib.php b/mod/lti/locallib.php index cd4d7ac14a2..d6e64e90b56 100644 --- a/mod/lti/locallib.php +++ b/mod/lti/locallib.php @@ -302,6 +302,7 @@ function lti_build_registration_request($toolproxy) { $requestparams['lti_version'] = 'LTI-2p0'; $requestparams['reg_key'] = $key; $requestparams['reg_password'] = $secret; + $requestparams['reg_url'] = $toolproxy->regurl; // Add the profile URL. $profileservice = lti_get_service_by_name('profile'); @@ -1623,6 +1624,30 @@ function lti_get_tool_proxy($id) { return $toolproxy; } +/** + * Returns lti tool proxies. + * + * @param bool $orphanedonly Only retrieves tool proxies that have no type associated with them + * @return array of basicLTI types + */ +function lti_get_tool_proxies($orphanedonly) { + global $DB; + + if ($orphanedonly) { + $tools = $DB->get_records('lti_types'); + $usedproxyids = array_values($DB->get_fieldset_select('lti_types', 'toolproxyid', 'toolproxyid IS NOT NULL')); + $proxies = $DB->get_records('lti_tool_proxies', null, 'state DESC, timemodified DESC'); + foreach ($proxies as $key => $value) { + if (in_array($value->id, $usedproxyids)) { + unset($proxies[$key]); + } + } + return $proxies; + } else { + return $DB->get_records('lti_tool_proxies', null, 'state DESC, timemodified DESC'); + } +} + /** * Generates some of the tool proxy configuration based on the admin configuration details * @@ -2273,6 +2298,19 @@ function get_tool_type_edit_url(stdClass $type) { return $url->out(); } +/** + * Returns the edit url for the given tool proxy. + * + * @param stdClass $proxy The tool proxy + * + * @return string The url to edit the tool type + */ +function get_tool_proxy_edit_url(stdClass $proxy) { + $url = new moodle_url('/mod/lti/registersettings.php', + array('action' => 'update', 'id' => $proxy->id, 'sesskey' => sesskey(), 'returnto' => 'toolconfigure')); + return $url->out(); +} + /** * Returns the course url for the given tool type * @@ -2294,7 +2332,7 @@ function get_tool_type_course_url(stdClass $type) { * * @param stdClass $type The tool type * - * @return string The url to the course of the tool type + * @return string The urls of the tool type */ function get_tool_type_urls(stdClass $type) { $courseurl = get_tool_type_course_url($type); @@ -2311,6 +2349,24 @@ function get_tool_type_urls(stdClass $type) { return $urls; } +/** + * Returns the icon and edit urls for the tool proxy. + * + * @param stdClass $proxy The tool proxy + * + * @return string The urls of the tool proxy + */ +function get_tool_proxy_urls(stdClass $proxy) { + global $OUTPUT; + + $urls = array( + 'icon' => $OUTPUT->pix_url('icon', 'lti')->out(), + 'edit' => get_tool_proxy_edit_url($proxy), + ); + + return $urls; +} + /** * Returns information on the current state of the tool type * @@ -2432,6 +2488,34 @@ function serialise_tool_type(stdClass $type) { ); } +/** + * Serialises this tool proxy. + * + * @param stdClass $proxy The tool proxy + * + * @return array An array of values representing this type + */ +function serialise_tool_proxy(stdClass $proxy) { + return array( + 'id' => $proxy->id, + 'name' => $proxy->name, + 'description' => $proxy->regurl . ' You will need to activate this proxy before adding a description', + 'urls' => get_tool_proxy_urls($proxy), + 'state' => array( + 'text' => get_string('pending', 'mod_lti'), + 'pending' => true, + 'configured' => false, + 'rejected' => false, + 'unknown' => false + ), + 'hascapabilitygroups' => true, + 'capabilitygroups' => array(), + 'courseid' => 0, + 'instanceids' => array(), + 'instancecount' => 0 + ); +} + /** * Loads the cartridge information into the tool type, if the launch url is for a cartridge file * diff --git a/mod/lti/styles.css b/mod/lti/styles.css index e15d26acc87..66a23e0f6d5 100644 --- a/mod/lti/styles.css +++ b/mod/lti/styles.css @@ -48,21 +48,22 @@ min-height: 800px; } -#external-registration-container .registration-loading-container { +.loading-screen { text-align: center; padding: 3em; } -#external-registration-container .registration-loading-container .loading-text, #external-registration-container .registration-loading-container .loader { +.loading-screen .loading-text { font-size: 2em; } -#external-registration-container .registration-loading-container .loader { +.loading-screen .loader { margin-left: auto; margin-right: auto; margin-bottom: 1em; height: 2em; width: 2em; + font-size: 2em; } #registration-submit { @@ -70,7 +71,7 @@ } #registration-form-container { - min-height: 230px; + min-height: 260px; } #registration-form-container .well { @@ -93,14 +94,6 @@ margin-top: 20px; } -#registration-feedback-container { - cursor: pointer; -} - -#registration-feedback-container h4 { - text-transform: capitalize; -} - #tool-type-capabilities-container .registration-loading-container { display: none; } @@ -325,6 +318,7 @@ .tool-card-body .description { max-height: 100px; + word-wrap: break-word; } .tool-card-footer { diff --git a/mod/lti/templates/external_registration.mustache b/mod/lti/templates/external_registration.mustache index ba7268d1075..6be87467849 100644 --- a/mod/lti/templates/external_registration.mustache +++ b/mod/lti/templates/external_registration.mustache @@ -41,9 +41,9 @@