diff --git a/course/format/classes/output/local/content/bulkedittools.php b/course/format/classes/output/local/content/bulkedittools.php index eb749435aa6..43263861500 100644 --- a/course/format/classes/output/local/content/bulkedittools.php +++ b/course/format/classes/output/local/content/bulkedittools.php @@ -16,6 +16,7 @@ namespace core_courseformat\output\local\content; +use core\moodlenet\utilities; use core\output\named_templatable; use core_courseformat\base as course_format; use core_courseformat\output\local\courseformat_named_templatable; @@ -131,6 +132,18 @@ class bulkedittools implements named_templatable, renderable { ]; } + $usercanshare = utilities::can_user_share($context, $user->id, 'course'); + if ($usercanshare) { + $controls['sharetomoodlenet'] = [ + 'id' => 'cmShareToMoodleNet', + 'icon' => 'i/share', + 'action' => 'cmShareToMoodleNet', + 'name' => get_string('moodlenet:sharetomoodlenet'), + 'title' => get_string('moodlenet:sharetomoodlenet'), + 'bulk' => 'cm', + ]; + } + return $controls; } diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 321dcd21a2e..43c10c3978d 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -1392,7 +1392,9 @@ $string['moodlenet:issuerisnotenabled'] = 'MoodleNet issuer is not enabled'; $string['moodlenet:issuerisnotset'] = 'MoodleNet issuer is not set at site administration'; $string['moodlenet:nosharedresources'] = 'There are no shared resources to display at this time'; $string['moodlenet:outboundsettings'] = 'MoodleNet outbound settings'; -$string['moodlenet:sharenotice'] = 'You are sharing this to MoodleNet as a {$a}'; +$string['moodlenet:sharenotice'] = 'This {$a->type} is being shared with MoodleNet as a {$a->sharetype}'; +$string['moodlenet:sharenoticepartial'] = 'The selected activities are being shared with MoodleNet as a {$a}'; +$string['moodlenet:sharenoticepartialactivitynumber'] = '{$a} activities will be included in the course'; $string['moodlenet:sharefailtitle'] = 'Something went wrong'; $string['moodlenet:sharefailtext'] = 'There was an error sharing your content to MoodleNet.
Please try again later.'; $string['moodlenet:sharefailtextwithsitesupport'] = 'There was an error sharing your content to MoodleNet.
Please try again later or contact site support.'; diff --git a/lib/amd/build/moodlenet/authorize.min.js b/lib/amd/build/moodlenet/authorize.min.js new file mode 100644 index 00000000000..a5ed6b0553f --- /dev/null +++ b/lib/amd/build/moodlenet/authorize.min.js @@ -0,0 +1,11 @@ +define("core/moodlenet/authorize",["exports","core/notification","core/moodlenet/service","core/moodlenet/send_resource"],(function(_exports,_notification,MoodleNetService,_send_resource){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.handleAuthorization=void 0,MoodleNetService=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} +/** + * MoodleNet authorization. + * + * @module core/moodlenet/authorize + * @copyright 2023 Huong Nguyen + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since 4.3 + */(MoodleNetService);const handleAuthorization=(issuerId,courseId,resourceId,shareFormat)=>MoodleNetService.authorizationCheck(issuerId,courseId).then((async data=>data.status?(0,_send_resource.sendToMoodleNet)(issuerId,resourceId,shareFormat):(window.moodleNetAuthorize=(error,errorDescription)=>{""===error?handleAuthorization(issuerId,courseId,resourceId,shareFormat):"access_denied"!==error&&(0,_notification.alert)("Authorization error","Error: "+error+"

Error description: "+errorDescription,"Cancel")},window.open(data.loginurl,"moodlenet_auth","location=0,status=0,width=".concat(550,",height=").concat(550,",scrollbars=yes"))))).catch(_notification.exception);_exports.handleAuthorization=handleAuthorization})); + +//# sourceMappingURL=authorize.min.js.map \ No newline at end of file diff --git a/lib/amd/build/moodlenet/authorize.min.js.map b/lib/amd/build/moodlenet/authorize.min.js.map new file mode 100644 index 00000000000..ed0c616e449 --- /dev/null +++ b/lib/amd/build/moodlenet/authorize.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"authorize.min.js","sources":["../../src/moodlenet/authorize.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * MoodleNet authorization.\n *\n * @module core/moodlenet/authorize\n * @copyright 2023 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.3\n */\n\nimport {alert as displayAlert, exception as displayException} from 'core/notification';\nimport * as MoodleNetService from 'core/moodlenet/service';\nimport {sendToMoodleNet} from 'core/moodlenet/send_resource';\n\n/**\n * Handle authorization with MoodleNet server.\n *\n * @param {int} issuerId The OAuth 2 issuer ID.\n * @param {int} courseId Course id.\n * @param {int} resourceId Resource id.\n * @param {int} shareFormat Share format.\n * @return {promise}\n */\nexport const handleAuthorization = (issuerId, courseId, resourceId, shareFormat) => {\n const windowSizeWidth = 550;\n const windowSizeHeight = 550;\n\n // Check if the user is authorized with MoodleNet or not.\n return MoodleNetService.authorizationCheck(issuerId, courseId).then(async(data) => {\n if (!data.status) {\n // Not yet authorized.\n // Declare moodleNetAuthorize variable, so we can call it later in the callback.\n window.moodleNetAuthorize = (error, errorDescription) => {\n // This will be called by the callback after the authorization is successful.\n if (error === '') {\n handleAuthorization(issuerId, courseId, resourceId, shareFormat);\n } else if (error !== 'access_denied') {\n displayAlert(\n 'Authorization error',\n 'Error: ' + error + '

Error description: ' + errorDescription,\n 'Cancel'\n );\n }\n };\n // Open the login url of the OAuth 2 issuer for user to login into MoodleNet and authorize.\n return window.open(data.loginurl, 'moodlenet_auth',\n `location=0,status=0,width=${windowSizeWidth},height=${windowSizeHeight},scrollbars=yes`);\n } else {\n // Already authorized.\n return sendToMoodleNet(issuerId, resourceId, shareFormat);\n }\n }).catch(displayException);\n};\n"],"names":["handleAuthorization","issuerId","courseId","resourceId","shareFormat","MoodleNetService","authorizationCheck","then","async","data","status","window","moodleNetAuthorize","error","errorDescription","open","loginurl","catch","displayException"],"mappings":";;;;;;;;8BAqCaA,oBAAsB,CAACC,SAAUC,SAAUC,WAAYC,cAKzDC,iBAAiBC,mBAAmBL,SAAUC,UAAUK,MAAKC,MAAAA,MAC3DC,KAAKC,QAoBC,kCAAgBT,SAAUE,WAAYC,cAjB7CO,OAAOC,mBAAqB,CAACC,MAAOC,oBAElB,KAAVD,MACAb,oBAAoBC,SAAUC,SAAUC,WAAYC,aACnC,kBAAVS,+BAEH,sBACA,UAAYA,MAAQ,8BAAgCC,iBACpD,WAKLH,OAAOI,KAAKN,KAAKO,SAAU,qDArBlB,uBACC,2BA0BtBC,MAAMC"} \ No newline at end of file diff --git a/lib/amd/build/moodlenet/events.min.js b/lib/amd/build/moodlenet/events.min.js new file mode 100644 index 00000000000..c3dad1edbd2 --- /dev/null +++ b/lib/amd/build/moodlenet/events.min.js @@ -0,0 +1,3 @@ +define("core/moodlenet/events",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;return _exports.default={MOODLENET_SHARE_STARTED:"moodlenet-share-started"},_exports.default})); + +//# sourceMappingURL=events.min.js.map \ No newline at end of file diff --git a/lib/amd/build/moodlenet/events.min.js.map b/lib/amd/build/moodlenet/events.min.js.map new file mode 100644 index 00000000000..1a3e4e4d96a --- /dev/null +++ b/lib/amd/build/moodlenet/events.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"events.min.js","sources":["../../src/moodlenet/events.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * MoodleNet events.\n *\n * @module core/moodlenet/events\n * @copyright 2023 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.3\n */\n\nexport default {\n MOODLENET_SHARE_STARTED: 'moodlenet-share-started',\n};\n"],"names":["MOODLENET_SHARE_STARTED"],"mappings":"uKAwBe,CACXA,wBAAyB"} \ No newline at end of file diff --git a/lib/amd/build/moodlenet/mutations.min.js b/lib/amd/build/moodlenet/mutations.min.js new file mode 100644 index 00000000000..b4170c68d64 --- /dev/null +++ b/lib/amd/build/moodlenet/mutations.min.js @@ -0,0 +1,3 @@ +define("core/moodlenet/mutations",["exports","core_courseformat/local/courseeditor/mutations","core_courseformat/courseeditor","core_courseformat/local/content/actions","core/pubsub","core/moodlenet/send_resource","core/moodlenet/events"],(function(_exports,_mutations,_courseeditor,_actions,_pubsub,_send_resource,_events){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_mutations=_interopRequireDefault(_mutations),_actions=_interopRequireDefault(_actions),_events=_interopRequireDefault(_events);class MoodleNetMutations extends _mutations.default{constructor(){var obj,key,value;super(...arguments),value=async function(stateManager,cmIds){this.cmLock(stateManager,cmIds,!0),(0,_send_resource.handleModal)("partial","resource",cmIds),this.cmLock(stateManager,cmIds,!1),(0,_pubsub.subscribe)(_events.default.MOODLENET_SHARE_STARTED,(()=>{this.bulkReset(stateManager)}))},(key="shareToMoodleNet")in(obj=this)?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value}}_exports.init=()=>{(0,_courseeditor.getCurrentCourseEditor)().addMutations(new MoodleNetMutations),_actions.default.addActions({cmShareToMoodleNet:"shareToMoodleNet"})}})); + +//# sourceMappingURL=mutations.min.js.map \ No newline at end of file diff --git a/lib/amd/build/moodlenet/mutations.min.js.map b/lib/amd/build/moodlenet/mutations.min.js.map new file mode 100644 index 00000000000..d558041af21 --- /dev/null +++ b/lib/amd/build/moodlenet/mutations.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"mutations.min.js","sources":["../../src/moodlenet/mutations.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * MoodleNet mutations.\n * An instance of this class will be used to add custom mutations to the course editor.\n *\n * @module core/moodlenet/mutations\n * @copyright 2023 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.3\n */\n\nimport DefaultMutations from 'core_courseformat/local/courseeditor/mutations';\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\nimport CourseActions from 'core_courseformat/local/content/actions';\nimport {subscribe} from 'core/pubsub';\nimport {handleModal} from 'core/moodlenet/send_resource';\nimport MoodleNetEvents from 'core/moodlenet/events';\n\nclass MoodleNetMutations extends DefaultMutations {\n\n /**\n * Share to MoodleNet.\n *\n * @param {StateManager} stateManager the current state manager\n * @param {array} cmIds Course module ids.\n */\n shareToMoodleNet = async function(stateManager, cmIds) {\n this.cmLock(stateManager, cmIds, true);\n handleModal('partial', 'resource', cmIds);\n this.cmLock(stateManager, cmIds, false);\n subscribe(MoodleNetEvents.MOODLENET_SHARE_STARTED, () => {\n // Only clear the selection if the user starts the sharing.\n this.bulkReset(stateManager);\n });\n };\n}\n\n/**\n * Initialize.\n */\nexport const init = () => {\n const courseEditor = getCurrentCourseEditor();\n courseEditor.addMutations(new MoodleNetMutations());\n // Add direct mutation content actions.\n CourseActions.addActions({\n cmShareToMoodleNet: 'shareToMoodleNet'\n });\n};\n"],"names":["MoodleNetMutations","DefaultMutations","async","stateManager","cmIds","cmLock","MoodleNetEvents","MOODLENET_SHARE_STARTED","bulkReset","addMutations","addActions","cmShareToMoodleNet"],"mappings":"ymBAgCMA,2BAA2BC,6EAQVC,eAAeC,aAAcC,YACvCC,OAAOF,aAAcC,OAAO,kCACrB,UAAW,WAAYA,YAC9BC,OAAOF,aAAcC,OAAO,yBACvBE,gBAAgBC,yBAAyB,UAE1CC,UAAUL,4KAQP,MACK,0CACRM,aAAa,IAAIT,qCAEhBU,WAAW,CACrBC,mBAAoB"} \ No newline at end of file diff --git a/lib/amd/build/moodlenet/send_resource.min.js b/lib/amd/build/moodlenet/send_resource.min.js index 35129e6200f..4d65a4a9acf 100644 --- a/lib/amd/build/moodlenet/send_resource.min.js +++ b/lib/amd/build/moodlenet/send_resource.min.js @@ -1,4 +1,4 @@ -define("core/moodlenet/send_resource",["exports","core/config","core/notification","core/str","core/prefetch","core/templates","core/moodlenet/service","core/moodlenet/send_activity_modal"],(function(_exports,_config,_notification,_str,_prefetch,Templates,MoodleNetService,_send_activity_modal){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} +define("core/moodlenet/send_resource",["exports","core/config","core/notification","core/str","core/prefetch","core/templates","core/pubsub","core/moodlenet/service","core/moodlenet/send_activity_modal","core/moodlenet/authorize","core/moodlenet/events"],(function(_exports,_config,_notification,_str,_prefetch,Templates,_pubsub,MoodleNetService,_send_activity_modal,MoodleNetAuthorize,_events){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} /** * A module to handle Share operations of the MoodleNet. * @@ -6,6 +6,6 @@ define("core/moodlenet/send_resource",["exports","core/config","core/notificatio * @copyright 2023 Huong Nguyen * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since 4.2 - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_config=_interopRequireDefault(_config),_prefetch=_interopRequireDefault(_prefetch),Templates=_interopRequireWildcard(Templates),MoodleNetService=_interopRequireWildcard(MoodleNetService),_send_activity_modal=_interopRequireDefault(_send_activity_modal);let currentModal,siteSupportUrl,issuerId,courseId,resourceId,shareFormat,type,listenersRegistered=!1;const responseFromMoodleNet=function(status){let resourceUrl=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";const $modal=currentModal.getModal(),modal=$modal[0];modal.querySelector(".modal-header").classList.add("no-border"),currentModal.setBody(Templates.render("core/moodlenet/send_activity_modal_done",{success:status,sitesupporturl:siteSupportUrl})),status&&(currentModal.setFooter(Templates.render("core/moodlenet/send_activity_modal_footer_view",{resourseurl:resourceUrl})),currentModal.showFooter())},handleAuthorization=issuerId=>MoodleNetService.authorizationCheck(issuerId,courseId).then((data=>data.status?((issuerId,resourceId,shareFormat)=>{const modal=currentModal.getModal()[0];let infoPromise;modal.querySelector(".modal-header").classList.remove("no-border"),modal.querySelector(".modal-header").classList.add("no-header-text"),currentModal.setBody(Templates.render("core/moodlenet/send_activity_modal_packaging",{})),currentModal.hideFooter(),"activity"===type?infoPromise=MoodleNetService.sendActivity(issuerId,resourceId,shareFormat):"course"===type&&(infoPromise=MoodleNetService.sendCourse(issuerId,resourceId,shareFormat)),infoPromise.then((async data=>{const status=data.status,resourceUrl=data.resourceurl;return responseFromMoodleNet(status,resourceUrl)})).catch(_notification.exception)})(issuerId,resourceId,shareFormat):(window.moodleNetAuthorize=(error,errorDescription)=>{""===error?handleAuthorization(issuerId):"access_denied"!==error&&(0,_notification.alert)("Authorization error","Error: "+error+"

Error description: "+errorDescription,"Cancel")},window.open(data.loginurl,"moodlenet_auth","location=0,status=0,width=".concat(550,",height=").concat(550,",scrollbars=yes"))))).catch(_notification.exception),registerEventListeners=()=>{document.addEventListener("click",(e=>{const shareAction=e.target.closest('[data-action="sendtomoodlenet"]'),sendAction=e.target.closest('.moodlenet-action-buttons [data-action="share"]');if(shareAction){e.preventDefault(),type=shareAction.getAttribute("data-type");const shareType=shareAction.getAttribute("data-sharetype");Promise.resolve(type).then((type=>{if("activity"===type)return MoodleNetService.getActivityInformation(_config.default.contextInstanceId);if("course"===type)return MoodleNetService.getCourseInformation(_config.default.contextInstanceId);throw new Error("Unknown type ".concat(type))})).then((data=>(async(data,shareType)=>data.status?(siteSupportUrl=data.supportpageurl,issuerId=data.issuerid,_send_activity_modal.default.create({templateContext:{activitytype:data.type,activityname:data.name,sharetype:await(0,_str.getString)("moodlenet:sharetype".concat(shareType),"moodle"),server:data.server}})):(0,_notification.addNotification)({message:data.warnings[0].message,type:"error"}))(data,shareType))).then((modal=>(currentModal=modal,currentModal))).catch(_notification.exception)}sendAction&&(e.preventDefault(),courseId=_config.default.courseId,resourceId=_config.default.contextInstanceId,shareFormat=0,handleAuthorization(issuerId))}))};_exports.init=()=>{listenersRegistered||(_prefetch.default.prefetchTemplates(["core/moodlenet/send_activity_modal_base","core/moodlenet/send_activity_modal_packaging","core/moodlenet/send_activity_modal_done","core/moodlenet/send_activity_modal_footer_view"]),registerEventListeners(),listenersRegistered=!0)}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.sendToMoodleNet=_exports.init=_exports.handleModal=void 0,_config=_interopRequireDefault(_config),_prefetch=_interopRequireDefault(_prefetch),Templates=_interopRequireWildcard(Templates),MoodleNetService=_interopRequireWildcard(MoodleNetService),_send_activity_modal=_interopRequireDefault(_send_activity_modal),MoodleNetAuthorize=_interopRequireWildcard(MoodleNetAuthorize),_events=_interopRequireDefault(_events);let currentModal,siteSupportUrl,issuerId,courseId,resourceId,shareFormat,type,selectedCmIds,listenersRegistered=!1;_exports.sendToMoodleNet=(issuerId,resourceId,shareFormat)=>{const modal=currentModal.getModal()[0];let infoPromise;modal.querySelector(".modal-header").classList.remove("no-border"),modal.querySelector(".modal-header").classList.add("no-header-text"),currentModal.setBody(Templates.render("core/moodlenet/send_activity_modal_packaging",{})),currentModal.hideFooter(),"activity"===type?infoPromise=MoodleNetService.sendActivity(issuerId,resourceId,shareFormat):"course"===type?infoPromise=MoodleNetService.sendCourse(issuerId,resourceId,shareFormat):"partial"===type&&(infoPromise=selectedCmIds.length>1?MoodleNetService.sendPartialCourse(issuerId,resourceId,selectedCmIds,shareFormat):MoodleNetService.sendActivity(issuerId,selectedCmIds[0],shareFormat)),infoPromise.then((async data=>{const status=data.status,resourceUrl=data.resourceurl;return responseFromMoodleNet(status,resourceUrl)})).catch(_notification.exception)};const responseFromMoodleNet=function(status){let resourceUrl=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";const $modal=currentModal.getModal(),modal=$modal[0];modal.querySelector(".modal-header").classList.add("no-border"),currentModal.setBody(Templates.render("core/moodlenet/send_activity_modal_done",{success:status,sitesupporturl:siteSupportUrl})),status&&(currentModal.setFooter(Templates.render("core/moodlenet/send_activity_modal_footer_view",{resourseurl:resourceUrl})),currentModal.showFooter())},renderModal=async(data,shareType,selectedActivities)=>{if(data.status){siteSupportUrl=data.supportpageurl,issuerId=data.issuerid;let modalConfig={templateContext:{activitytype:data.type,activityname:data.name,server:data.server}};const sharetype=await(0,_str.getString)("moodlenet:sharetype"+shareType,"moodle");return selectedActivities.length>0&&(selectedCmIds=selectedActivities),selectedActivities.length>1?(modalConfig.templateContext.fullsharing=!1,modalConfig.templateContext.selectedactivitiesnotice=await(0,_str.getString)("moodlenet:sharenoticepartialactivitynumber","moodle",selectedActivities.length),modalConfig.templateContext.sharenotice=await(0,_str.getString)("moodlenet:sharenoticepartial","moodle",sharetype)):(modalConfig.templateContext.fullsharing=!0,"partial"===type&&1==selectedActivities.length?modalConfig.templateContext.sharenotice=await(0,_str.getString)("moodlenet:sharenotice","moodle",{type:"activity",sharetype:sharetype}):modalConfig.templateContext.sharenotice=await(0,_str.getString)("moodlenet:sharenotice","moodle",{type:type,sharetype:sharetype})),_send_activity_modal.default.create(modalConfig)}return(0,_notification.addNotification)({message:data.warnings[0].message,type:"error"})},handleModal=function(shareActionType,shareType){let selectedActivities=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];const resourceId=_config.default.contextInstanceId;type=shareActionType,Promise.resolve(type).then((type=>{if("activity"===type)return MoodleNetService.getActivityInformation(resourceId);if("course"===type)return MoodleNetService.getCourseInformation(resourceId);if("partial"===type)return selectedActivities.length>1?MoodleNetService.getCourseInformation(resourceId):MoodleNetService.getActivityInformation(selectedActivities[0]);throw new Error("Unknown type ".concat(type))})).then((data=>renderModal(data,shareType,selectedActivities))).then((modal=>(currentModal=modal,currentModal))).catch(_notification.exception)};_exports.handleModal=handleModal;_exports.init=()=>{listenersRegistered||(_prefetch.default.prefetchTemplates(["core/moodlenet/send_activity_modal_base","core/moodlenet/send_activity_modal_packaging","core/moodlenet/send_activity_modal_done","core/moodlenet/send_activity_modal_footer_view","core/moodlenet/send_activity_modal_footer_share","core/moodlenet/send_course_modal_base"]),document.addEventListener("click",(e=>{const shareAction=e.target.closest('[data-action="sendtomoodlenet"]'),sendAction=e.target.closest('.moodlenet-action-buttons [data-action="share"]');if(shareAction){e.preventDefault(),type=shareAction.getAttribute("data-type");const shareType=shareAction.getAttribute("data-sharetype");handleModal(shareAction.getAttribute("data-type"),shareType)}sendAction&&(e.preventDefault(),(0,_pubsub.publish)(_events.default.MOODLENET_SHARE_STARTED,{}),courseId=_config.default.courseId,resourceId=_config.default.contextInstanceId,shareFormat=0,MoodleNetAuthorize.handleAuthorization(issuerId,courseId,resourceId,0))})),listenersRegistered=!0)}})); //# sourceMappingURL=send_resource.min.js.map \ No newline at end of file diff --git a/lib/amd/build/moodlenet/send_resource.min.js.map b/lib/amd/build/moodlenet/send_resource.min.js.map index ddf0ffda330..7ec57771bf6 100644 --- a/lib/amd/build/moodlenet/send_resource.min.js.map +++ b/lib/amd/build/moodlenet/send_resource.min.js.map @@ -1 +1 @@ -{"version":3,"file":"send_resource.min.js","sources":["../../src/moodlenet/send_resource.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A module to handle Share operations of the MoodleNet.\n *\n * @module core/moodlenet/send_resource\n * @copyright 2023 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.2\n */\n\nimport Config from 'core/config';\nimport {alert as displayAlert, addNotification, exception as displayException} from 'core/notification';\nimport {getString} from 'core/str';\nimport Prefetch from \"core/prefetch\";\nimport * as Templates from 'core/templates';\nimport * as MoodleNetService from 'core/moodlenet/service';\nimport SendActivityModal from 'core/moodlenet/send_activity_modal';\n\nconst TYPE_ACTIVITY = \"activity\";\nconst TYPE_COURSE = \"course\";\n\nlet listenersRegistered = false;\nlet currentModal;\nlet siteSupportUrl;\nlet issuerId;\nlet courseId;\nlet resourceId;\nlet shareFormat;\nlet type;\n\n/**\n * Handle send to MoodleNet.\n *\n * @param {int} issuerId The OAuth 2 issuer ID.\n * @param {int} resourceId The resource ID, it can be a course or an activity.\n * @param {int} shareFormat The share format.\n */\nconst sendToMoodleNet = (issuerId, resourceId, shareFormat) => {\n const $modal = currentModal.getModal();\n const modal = $modal[0];\n modal.querySelector('.modal-header').classList.remove('no-border');\n modal.querySelector('.modal-header').classList.add('no-header-text');\n\n currentModal.setBody(Templates.render('core/moodlenet/send_activity_modal_packaging', {}));\n currentModal.hideFooter();\n\n let infoPromise;\n if (type === TYPE_ACTIVITY) {\n infoPromise = MoodleNetService.sendActivity(issuerId, resourceId, shareFormat);\n } else if (type === TYPE_COURSE) {\n infoPromise = MoodleNetService.sendCourse(issuerId, resourceId, shareFormat);\n }\n infoPromise.then(async(data) => {\n const status = data.status;\n const resourceUrl = data.resourceurl;\n return responseFromMoodleNet(status, resourceUrl);\n }).catch(displayException);\n};\n\n/**\n * Handle response from MoodleNet.\n *\n * @param {boolean} status Response status. True if successful.\n * @param {String} resourceUrl Resource URL.\n */\nconst responseFromMoodleNet = (status, resourceUrl = '') => {\n const $modal = currentModal.getModal();\n const modal = $modal[0];\n modal.querySelector('.modal-header').classList.add('no-border');\n currentModal.setBody(Templates.render('core/moodlenet/send_activity_modal_done', {\n success: status,\n sitesupporturl: siteSupportUrl,\n }));\n\n if (status) {\n currentModal.setFooter(Templates.render('core/moodlenet/send_activity_modal_footer_view', {\n resourseurl: resourceUrl,\n }));\n currentModal.showFooter();\n }\n};\n\n/**\n * Handle authorization with MoodleNet server.\n *\n * @param {Number} issuerId The OAuth 2 issuer ID.\n * @return {promise}\n */\nconst handleAuthorization = (issuerId) => {\n const windowsizewidth = 550;\n const windowsizeheight = 550;\n\n // Check if the user is authorized with MoodleNet or not.\n return MoodleNetService.authorizationCheck(issuerId, courseId).then((data) => {\n if (!data.status) {\n // Not yet authorized.\n // Declare moodleNetAuthorize variable, so we can call it later in the callback.\n window.moodleNetAuthorize = (error, errorDescription) => {\n // This will be called by the callback after the authorization is successful.\n if (error === '') {\n handleAuthorization(issuerId);\n } else if (error !== 'access_denied') {\n displayAlert(\n 'Authorization error',\n 'Error: ' + error + '

Error description: ' + errorDescription,\n 'Cancel'\n );\n }\n };\n // Open the login url of the OAuth 2 issuer for user to login into MoodleNet and authorize.\n return window.open(data.loginurl, 'moodlenet_auth',\n `location=0,status=0,width=${windowsizewidth},height=${windowsizeheight},scrollbars=yes`);\n } else {\n // Already authorized.\n return sendToMoodleNet(issuerId, resourceId, shareFormat);\n }\n }).catch(displayException);\n};\n\n/**\n * Render the modal to send resource to MoodleNet.\n *\n * @param {object} data The data of the resource to be shared.\n * @param {string} shareType The type of the resource to be shared.\n */\nconst renderModal = async(data, shareType) => {\n if (data.status) {\n siteSupportUrl = data.supportpageurl;\n issuerId = data.issuerid;\n return SendActivityModal.create({\n templateContext: {\n activitytype: data.type,\n activityname: data.name,\n sharetype: await getString(`moodlenet:sharetype${shareType}`, 'moodle'),\n server: data.server,\n }\n });\n } else {\n return addNotification({\n message: data.warnings[0].message,\n type: 'error'\n });\n }\n};\n\n/**\n * Register events.\n */\nconst registerEventListeners = () => {\n document.addEventListener('click', (e) => {\n const shareAction = e.target.closest('[data-action=\"sendtomoodlenet\"]');\n const sendAction = e.target.closest('.moodlenet-action-buttons [data-action=\"share\"]');\n if (shareAction) {\n e.preventDefault();\n type = shareAction.getAttribute('data-type');\n const shareType = shareAction.getAttribute('data-sharetype');\n Promise.resolve(type)\n .then((type) => {\n if (type === TYPE_ACTIVITY) {\n return MoodleNetService.getActivityInformation(Config.contextInstanceId);\n } else if (type === TYPE_COURSE) {\n return MoodleNetService.getCourseInformation(Config.contextInstanceId);\n }\n throw new Error(`Unknown type ${type}`);\n })\n .then((data) => {\n return renderModal(data, shareType);\n })\n .then((modal) => {\n currentModal = modal;\n return currentModal;\n })\n .catch(displayException);\n }\n\n if (sendAction) {\n e.preventDefault();\n courseId = Config.courseId;\n resourceId = Config.contextInstanceId;\n shareFormat = 0;\n handleAuthorization(issuerId);\n }\n });\n};\n\n\n/**\n * Initialize.\n */\nexport const init = () => {\n if (!listenersRegistered) {\n Prefetch.prefetchTemplates([\n 'core/moodlenet/send_activity_modal_base',\n 'core/moodlenet/send_activity_modal_packaging',\n 'core/moodlenet/send_activity_modal_done',\n 'core/moodlenet/send_activity_modal_footer_view',\n ]);\n registerEventListeners();\n listenersRegistered = true;\n }\n};\n"],"names":["currentModal","siteSupportUrl","issuerId","courseId","resourceId","shareFormat","type","listenersRegistered","responseFromMoodleNet","status","resourceUrl","$modal","getModal","modal","querySelector","classList","add","setBody","Templates","render","success","sitesupporturl","setFooter","resourseurl","showFooter","handleAuthorization","MoodleNetService","authorizationCheck","then","data","infoPromise","remove","hideFooter","sendActivity","sendCourse","async","resourceurl","catch","displayException","sendToMoodleNet","window","moodleNetAuthorize","error","errorDescription","open","loginurl","registerEventListeners","document","addEventListener","e","shareAction","target","closest","sendAction","preventDefault","getAttribute","shareType","Promise","resolve","getActivityInformation","Config","contextInstanceId","getCourseInformation","Error","supportpageurl","issuerid","SendActivityModal","create","templateContext","activitytype","activityname","name","sharetype","server","message","warnings","renderModal","prefetchTemplates"],"mappings":";;;;;;;;oVAoCIA,aACAC,eACAC,SACAC,SACAC,WACAC,YACAC,KAPAC,qBAAsB,QA4CpBC,sBAAwB,SAACC,YAAQC,mEAAc,SAC3CC,OAASX,aAAaY,WACtBC,MAAQF,OAAO,GACrBE,MAAMC,cAAc,iBAAiBC,UAAUC,IAAI,aACnDhB,aAAaiB,QAAQC,UAAUC,OAAO,0CAA2C,CAC7EC,QAASX,OACTY,eAAgBpB,kBAGhBQ,SACAT,aAAasB,UAAUJ,UAAUC,OAAO,iDAAkD,CACtFI,YAAab,eAEjBV,aAAawB,eAUfC,oBAAuBvB,UAKlBwB,iBAAiBC,mBAAmBzB,SAAUC,UAAUyB,MAAMC,MAC5DA,KAAKpB,OAzDM,EAACP,SAAUE,WAAYC,qBAErCQ,MADSb,aAAaY,WACP,OAOjBkB,YANJjB,MAAMC,cAAc,iBAAiBC,UAAUgB,OAAO,aACtDlB,MAAMC,cAAc,iBAAiBC,UAAUC,IAAI,kBAEnDhB,aAAaiB,QAAQC,UAAUC,OAAO,+CAAgD,KACtFnB,aAAagC,aA1BK,aA6Bd1B,KACAwB,YAAcJ,iBAAiBO,aAAa/B,SAAUE,WAAYC,aA7BtD,WA8BLC,OACPwB,YAAcJ,iBAAiBQ,WAAWhC,SAAUE,WAAYC,cAEpEyB,YAAYF,MAAKO,MAAAA,aACP1B,OAASoB,KAAKpB,OACdC,YAAcmB,KAAKO,mBAClB5B,sBAAsBC,OAAQC,gBACtC2B,MAAMC,0BA0DMC,CAAgBrC,SAAUE,WAAYC,cAjB7CmC,OAAOC,mBAAqB,CAACC,MAAOC,oBAElB,KAAVD,MACAjB,oBAAoBvB,UACH,kBAAVwC,+BAEH,sBACA,UAAYA,MAAQ,8BAAgCC,iBACpD,WAKLH,OAAOI,KAAKf,KAAKgB,SAAU,qDArBlB,uBACC,2BA0BtBR,MAAMC,yBAgCPQ,uBAAyB,KAC3BC,SAASC,iBAAiB,SAAUC,UAC1BC,YAAcD,EAAEE,OAAOC,QAAQ,mCAC/BC,WAAaJ,EAAEE,OAAOC,QAAQ,sDAChCF,YAAa,CACbD,EAAEK,iBACFhD,KAAO4C,YAAYK,aAAa,mBAC1BC,UAAYN,YAAYK,aAAa,kBAC3CE,QAAQC,QAAQpD,MACXsB,MAAMtB,UA3ID,aA4IEA,YACOoB,iBAAiBiC,uBAAuBC,gBAAOC,mBACnD,GA7IP,WA6IWvD,YACAoB,iBAAiBoC,qBAAqBF,gBAAOC,yBAElD,IAAIE,6BAAsBzD,UAEnCsB,MAAMC,MAxCHM,OAAMN,KAAM2B,YACxB3B,KAAKpB,QACLR,eAAiB4B,KAAKmC,eACtB9D,SAAW2B,KAAKoC,SACTC,6BAAkBC,OAAO,CAC5BC,gBAAiB,CACbC,aAAcxC,KAAKvB,KACnBgE,aAAczC,KAAK0C,KACnBC,gBAAiB,+CAAgChB,WAAa,UAC9DiB,OAAQ5C,KAAK4C,YAId,iCAAgB,CACnBC,QAAS7C,KAAK8C,SAAS,GAAGD,QAC1BpE,KAAM,UA0BSsE,CAAY/C,KAAM2B,aAE5B5B,MAAMf,QACHb,aAAea,MACRb,gBAEVqC,MAAMC,yBAGXe,aACAJ,EAAEK,iBACFnD,SAAWyD,gBAAOzD,SAClBC,WAAawD,gBAAOC,kBACpBxD,YAAc,EACdoB,oBAAoBvB,6BASZ,KACXK,wCACQsE,kBAAkB,CACvB,0CACA,+CACA,0CACA,mDAEJ/B,yBACAvC,qBAAsB"} \ No newline at end of file +{"version":3,"file":"send_resource.min.js","sources":["../../src/moodlenet/send_resource.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A module to handle Share operations of the MoodleNet.\n *\n * @module core/moodlenet/send_resource\n * @copyright 2023 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.2\n */\n\nimport Config from 'core/config';\nimport {addNotification, exception as displayException} from 'core/notification';\nimport {getString} from 'core/str';\nimport Prefetch from \"core/prefetch\";\nimport * as Templates from 'core/templates';\nimport {publish} from 'core/pubsub';\nimport * as MoodleNetService from 'core/moodlenet/service';\nimport SendActivityModal from 'core/moodlenet/send_activity_modal';\nimport * as MoodleNetAuthorize from 'core/moodlenet/authorize';\nimport MoodleNetEvents from 'core/moodlenet/events';\n\nconst TYPE_ACTIVITY = \"activity\";\nconst TYPE_COURSE = \"course\";\nconst TYPE_PARTIAL_COURSE = \"partial\";\n\nlet listenersRegistered = false;\nlet currentModal;\nlet siteSupportUrl;\nlet issuerId;\nlet courseId;\nlet resourceId;\nlet shareFormat;\nlet type;\nlet selectedCmIds;\n\n/**\n * Handle send to MoodleNet.\n *\n * @param {int} issuerId The OAuth 2 issuer ID.\n * @param {int} resourceId The resource ID, it can be a course or an activity.\n * @param {int} shareFormat The share format.\n */\nexport const sendToMoodleNet = (issuerId, resourceId, shareFormat) => {\n const $modal = currentModal.getModal();\n const modal = $modal[0];\n modal.querySelector('.modal-header').classList.remove('no-border');\n modal.querySelector('.modal-header').classList.add('no-header-text');\n\n currentModal.setBody(Templates.render('core/moodlenet/send_activity_modal_packaging', {}));\n currentModal.hideFooter();\n\n let infoPromise;\n if (type === TYPE_ACTIVITY) {\n infoPromise = MoodleNetService.sendActivity(issuerId, resourceId, shareFormat);\n } else if (type === TYPE_COURSE) {\n infoPromise = MoodleNetService.sendCourse(issuerId, resourceId, shareFormat);\n } else if (type === TYPE_PARTIAL_COURSE) {\n if (selectedCmIds.length > 1) {\n infoPromise = MoodleNetService.sendPartialCourse(issuerId, resourceId, selectedCmIds, shareFormat);\n } else {\n infoPromise = MoodleNetService.sendActivity(issuerId, selectedCmIds[0], shareFormat);\n }\n }\n infoPromise.then(async(data) => {\n const status = data.status;\n const resourceUrl = data.resourceurl;\n return responseFromMoodleNet(status, resourceUrl);\n }).catch(displayException);\n};\n\n/**\n * Handle response from MoodleNet.\n *\n * @param {boolean} status Response status. True if successful.\n * @param {String} resourceUrl Resource URL.\n */\nconst responseFromMoodleNet = (status, resourceUrl = '') => {\n const $modal = currentModal.getModal();\n const modal = $modal[0];\n modal.querySelector('.modal-header').classList.add('no-border');\n currentModal.setBody(Templates.render('core/moodlenet/send_activity_modal_done', {\n success: status,\n sitesupporturl: siteSupportUrl,\n }));\n\n if (status) {\n currentModal.setFooter(Templates.render('core/moodlenet/send_activity_modal_footer_view', {\n resourseurl: resourceUrl,\n }));\n currentModal.showFooter();\n }\n};\n\n/**\n * Render the modal to send resource to MoodleNet.\n *\n * @param {object} data The data of the resource to be shared.\n * @param {string} shareType The type of the resource to be shared.\n * @param {array} selectedActivities Selected activities.\n */\nconst renderModal = async(data, shareType, selectedActivities) => {\n if (data.status) {\n siteSupportUrl = data.supportpageurl;\n issuerId = data.issuerid;\n let modalConfig = {\n templateContext: {\n 'activitytype': data.type,\n 'activityname': data.name,\n 'server': data.server,\n }\n };\n const sharetype = await getString('moodlenet:sharetype' + shareType, 'moodle');\n if (selectedActivities.length > 0) {\n selectedCmIds = selectedActivities;\n }\n if (selectedActivities.length > 1) {\n modalConfig.templateContext.fullsharing = false;\n modalConfig.templateContext.selectedactivitiesnotice = await getString('moodlenet:sharenoticepartialactivitynumber',\n 'moodle', selectedActivities.length);\n modalConfig.templateContext.sharenotice = await getString('moodlenet:sharenoticepartial',\n 'moodle', sharetype);\n } else {\n modalConfig.templateContext.fullsharing = true;\n if (type === TYPE_PARTIAL_COURSE && selectedActivities.length == 1) {\n modalConfig.templateContext.sharenotice = await getString('moodlenet:sharenotice',\n 'moodle', {'type': TYPE_ACTIVITY, 'sharetype': sharetype});\n } else {\n modalConfig.templateContext.sharenotice = await getString('moodlenet:sharenotice',\n 'moodle', {'type': type, 'sharetype': sharetype});\n }\n }\n\n return SendActivityModal.create(modalConfig);\n } else {\n return addNotification({\n message: data.warnings[0].message,\n type: 'error'\n });\n }\n};\n\n/**\n * Handle modal.\n * @param {string} shareActionType Share action type.\n * @param {string} shareType Share type.\n * @param {array} selectedActivities Selected activities.\n */\nexport const handleModal = (shareActionType, shareType, selectedActivities = []) => {\n const resourceId = Config.contextInstanceId;\n type = shareActionType;\n\n Promise.resolve(type)\n .then((type) => {\n if (type === TYPE_ACTIVITY) {\n return MoodleNetService.getActivityInformation(resourceId);\n } else if (type === TYPE_COURSE) {\n return MoodleNetService.getCourseInformation(resourceId);\n } else if (type === TYPE_PARTIAL_COURSE) {\n if (selectedActivities.length > 1) {\n // Selected more than one activity.\n return MoodleNetService.getCourseInformation(resourceId);\n } else {\n // Select only one activity. Switch to activity mode.\n return MoodleNetService.getActivityInformation(selectedActivities[0]);\n }\n }\n throw new Error(`Unknown type ${type}`);\n })\n .then((data) => {\n return renderModal(data, shareType, selectedActivities);\n })\n .then((modal) => {\n currentModal = modal;\n return currentModal;\n })\n .catch(displayException);\n};\n\n/**\n * Register events.\n */\nconst registerEventListeners = () => {\n document.addEventListener('click', (e) => {\n const shareAction = e.target.closest('[data-action=\"sendtomoodlenet\"]');\n const sendAction = e.target.closest('.moodlenet-action-buttons [data-action=\"share\"]');\n if (shareAction) {\n e.preventDefault();\n type = shareAction.getAttribute('data-type');\n const shareType = shareAction.getAttribute('data-sharetype');\n handleModal(shareAction.getAttribute('data-type'), shareType);\n }\n\n if (sendAction) {\n e.preventDefault();\n publish(MoodleNetEvents.MOODLENET_SHARE_STARTED, {});\n courseId = Config.courseId;\n resourceId = Config.contextInstanceId;\n shareFormat = 0;\n MoodleNetAuthorize.handleAuthorization(issuerId, courseId, resourceId, shareFormat);\n }\n });\n};\n\n\n/**\n * Initialize.\n */\nexport const init = () => {\n if (!listenersRegistered) {\n Prefetch.prefetchTemplates([\n 'core/moodlenet/send_activity_modal_base',\n 'core/moodlenet/send_activity_modal_packaging',\n 'core/moodlenet/send_activity_modal_done',\n 'core/moodlenet/send_activity_modal_footer_view',\n 'core/moodlenet/send_activity_modal_footer_share',\n 'core/moodlenet/send_course_modal_base',\n ]);\n registerEventListeners();\n listenersRegistered = true;\n }\n};\n"],"names":["currentModal","siteSupportUrl","issuerId","courseId","resourceId","shareFormat","type","selectedCmIds","listenersRegistered","modal","getModal","infoPromise","querySelector","classList","remove","add","setBody","Templates","render","hideFooter","MoodleNetService","sendActivity","sendCourse","length","sendPartialCourse","then","async","status","data","resourceUrl","resourceurl","responseFromMoodleNet","catch","displayException","$modal","success","sitesupporturl","setFooter","resourseurl","showFooter","renderModal","shareType","selectedActivities","supportpageurl","issuerid","modalConfig","templateContext","name","server","sharetype","fullsharing","selectedactivitiesnotice","sharenotice","SendActivityModal","create","message","warnings","handleModal","shareActionType","Config","contextInstanceId","Promise","resolve","getActivityInformation","getCourseInformation","Error","prefetchTemplates","document","addEventListener","e","shareAction","target","closest","sendAction","preventDefault","getAttribute","MoodleNetEvents","MOODLENET_SHARE_STARTED","MoodleNetAuthorize","handleAuthorization"],"mappings":";;;;;;;;yeAwCIA,aACAC,eACAC,SACAC,SACAC,WACAC,YACAC,KACAC,cARAC,qBAAsB,2BAiBK,CAACN,SAAUE,WAAYC,qBAE5CI,MADST,aAAaU,WACP,OAOjBC,YANJF,MAAMG,cAAc,iBAAiBC,UAAUC,OAAO,aACtDL,MAAMG,cAAc,iBAAiBC,UAAUE,IAAI,kBAEnDf,aAAagB,QAAQC,UAAUC,OAAO,+CAAgD,KACtFlB,aAAamB,aA5BK,aA+Bdb,KACAK,YAAcS,iBAAiBC,aAAanB,SAAUE,WAAYC,aA/BtD,WAgCLC,KACPK,YAAcS,iBAAiBE,WAAWpB,SAAUE,WAAYC,aAhC5C,YAiCbC,OAEHK,YADAJ,cAAcgB,OAAS,EACTH,iBAAiBI,kBAAkBtB,SAAUE,WAAYG,cAAeF,aAExEe,iBAAiBC,aAAanB,SAAUK,cAAc,GAAIF,cAGhFM,YAAYc,MAAKC,MAAAA,aACPC,OAASC,KAAKD,OACdE,YAAcD,KAAKE,mBAClBC,sBAAsBJ,OAAQE,gBACtCG,MAAMC,gCASPF,sBAAwB,SAACJ,YAAQE,mEAAc,SAC3CK,OAASlC,aAAaU,WACtBD,MAAQyB,OAAO,GACrBzB,MAAMG,cAAc,iBAAiBC,UAAUE,IAAI,aACnDf,aAAagB,QAAQC,UAAUC,OAAO,0CAA2C,CAC7EiB,QAASR,OACTS,eAAgBnC,kBAGhB0B,SACA3B,aAAaqC,UAAUpB,UAAUC,OAAO,iDAAkD,CACtFoB,YAAaT,eAEjB7B,aAAauC,eAWfC,YAAcd,MAAME,KAAMa,UAAWC,yBACnCd,KAAKD,OAAQ,CACb1B,eAAiB2B,KAAKe,eACtBzC,SAAW0B,KAAKgB,aACZC,YAAc,CACdC,gBAAiB,cACGlB,KAAKtB,kBACLsB,KAAKmB,YACXnB,KAAKoB,eAGjBC,gBAAkB,kBAAU,sBAAwBR,UAAW,iBACjEC,mBAAmBnB,OAAS,IAC5BhB,cAAgBmC,oBAEhBA,mBAAmBnB,OAAS,GAC5BsB,YAAYC,gBAAgBI,aAAc,EAC1CL,YAAYC,gBAAgBK,+BAAiC,kBAAU,6CACnE,SAAUT,mBAAmBnB,QACjCsB,YAAYC,gBAAgBM,kBAAoB,kBAAU,+BACtD,SAAUH,aAEdJ,YAAYC,gBAAgBI,aAAc,EAnG1B,YAoGZ5C,MAA6D,GAA7BoC,mBAAmBnB,OACnDsB,YAAYC,gBAAgBM,kBAAoB,kBAAU,wBACtD,SAAU,MAxGR,qBAwG6CH,YAEnDJ,YAAYC,gBAAgBM,kBAAoB,kBAAU,wBACtD,SAAU,MAAS9C,eAAmB2C,aAI3CI,6BAAkBC,OAAOT,oBAEzB,iCAAgB,CACnBU,QAAS3B,KAAK4B,SAAS,GAAGD,QAC1BjD,KAAM,WAWLmD,YAAc,SAACC,gBAAiBjB,eAAWC,0EAAqB,SACnEtC,WAAauD,gBAAOC,kBAC1BtD,KAAOoD,gBAEPG,QAAQC,QAAQxD,MACXmB,MAAMnB,UAnIO,aAoINA,YACOc,iBAAiB2C,uBAAuB3D,YAC5C,GArIC,WAqIGE,YACAc,iBAAiB4C,qBAAqB5D,YAC1C,GAtIS,YAsILE,YACHoC,mBAAmBnB,OAAS,EAErBH,iBAAiB4C,qBAAqB5D,YAGtCgB,iBAAiB2C,uBAAuBrB,mBAAmB,UAGpE,IAAIuB,6BAAsB3D,UAEnCmB,MAAMG,MACIY,YAAYZ,KAAMa,UAAWC,sBAEvCjB,MAAMhB,QACHT,aAAeS,MACRT,gBAEVgC,MAAMC,yEAgCK,KACXzB,wCACQ0D,kBAAkB,CACvB,0CACA,+CACA,0CACA,iDACA,kDACA,0CAjCRC,SAASC,iBAAiB,SAAUC,UAC1BC,YAAcD,EAAEE,OAAOC,QAAQ,mCAC/BC,WAAaJ,EAAEE,OAAOC,QAAQ,sDAChCF,YAAa,CACbD,EAAEK,iBACFpE,KAAOgE,YAAYK,aAAa,mBAC1BlC,UAAY6B,YAAYK,aAAa,kBAC3ClB,YAAYa,YAAYK,aAAa,aAAclC,WAGnDgC,aACAJ,EAAEK,qCACME,gBAAgBC,wBAAyB,IACjD1E,SAAWwD,gBAAOxD,SAClBC,WAAauD,gBAAOC,kBACpBvD,YAAc,EACdyE,mBAAmBC,oBAAoB7E,SAAUC,SAAUC,WAD7C,OAqBlBI,qBAAsB"} \ No newline at end of file diff --git a/lib/amd/build/moodlenet/service.min.js b/lib/amd/build/moodlenet/service.min.js index 665ec4c9c00..9de4f89b072 100644 --- a/lib/amd/build/moodlenet/service.min.js +++ b/lib/amd/build/moodlenet/service.min.js @@ -6,6 +6,6 @@ define("core/moodlenet/service",["exports","core/ajax"],(function(_exports,_ajax * @copyright 2023 Huong Nguyen * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since 4.2 - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.sendCourse=_exports.sendActivity=_exports.getCourseInformation=_exports.getActivityInformation=_exports.authorizationCheck=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.getActivityInformation=cmId=>{const request={methodname:"core_moodlenet_get_share_info_activity",args:{cmid:cmId}};return _ajax.default.call([request])[0]};_exports.getCourseInformation=courseID=>{const request={methodname:"core_moodlenet_get_shared_course_info",args:{courseid:courseID}};return _ajax.default.call([request])[0]};_exports.sendCourse=(issuerId,courseId,shareFormat)=>{const request={methodname:"core_moodlenet_send_course",args:{issuerid:issuerId,courseid:courseId,shareformat:shareFormat}};return _ajax.default.call([request])[0]};_exports.sendActivity=(issuerId,cmId,shareFormat)=>{const request={methodname:"core_moodlenet_send_activity",args:{issuerid:issuerId,cmid:cmId,shareformat:shareFormat}};return _ajax.default.call([request])[0]};_exports.authorizationCheck=(issuerId,courseId)=>{const request={methodname:"core_moodlenet_auth_check",args:{issuerid:issuerId,courseid:courseId}};return _ajax.default.call([request])[0]}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.sendPartialCourse=_exports.sendCourse=_exports.sendActivity=_exports.getCourseInformation=_exports.getActivityInformation=_exports.authorizationCheck=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.getActivityInformation=cmId=>{const request={methodname:"core_moodlenet_get_share_info_activity",args:{cmid:cmId}};return _ajax.default.call([request])[0]};_exports.getCourseInformation=courseID=>{const request={methodname:"core_moodlenet_get_shared_course_info",args:{courseid:courseID}};return _ajax.default.call([request])[0]};_exports.sendCourse=(issuerId,courseId,shareFormat)=>{const request={methodname:"core_moodlenet_send_course",args:{issuerid:issuerId,courseid:courseId,shareformat:shareFormat}};return _ajax.default.call([request])[0]};_exports.sendActivity=(issuerId,cmId,shareFormat)=>{const request={methodname:"core_moodlenet_send_activity",args:{issuerid:issuerId,cmid:cmId,shareformat:shareFormat}};return _ajax.default.call([request])[0]};_exports.sendPartialCourse=(issuerId,courseId,selectedCmIds,shareFormat)=>{const request={methodname:"core_moodlenet_send_course",args:{issuerid:issuerId,courseid:courseId,shareformat:shareFormat,cmids:selectedCmIds}};return _ajax.default.call([request])[0]};_exports.authorizationCheck=(issuerId,courseId)=>{const request={methodname:"core_moodlenet_auth_check",args:{issuerid:issuerId,courseid:courseId}};return _ajax.default.call([request])[0]}})); //# sourceMappingURL=service.min.js.map \ No newline at end of file diff --git a/lib/amd/build/moodlenet/service.min.js.map b/lib/amd/build/moodlenet/service.min.js.map index 8b86db8aa27..f0fea22d072 100644 --- a/lib/amd/build/moodlenet/service.min.js.map +++ b/lib/amd/build/moodlenet/service.min.js.map @@ -1 +1 @@ -{"version":3,"file":"service.min.js","sources":["../../src/moodlenet/service.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A javascript module to handle MoodleNet ajax actions.\n *\n * @module core/moodlenet/service\n * @copyright 2023 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.2\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Get the activity information by course module id.\n *\n * @param {Integer} cmId The course module id.\n * @return {promise}\n */\nexport const getActivityInformation = (cmId) => {\n const request = {\n methodname: 'core_moodlenet_get_share_info_activity',\n args: {\n cmid: cmId\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n\n/**\n * Get the course information by course module id.\n *\n * @param {Integer} courseID The course id.\n * @return {promise}\n */\nexport const getCourseInformation = (courseID) => {\n const request = {\n methodname: 'core_moodlenet_get_shared_course_info',\n args: {\n courseid: courseID\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Send the course to MoodleNet.\n *\n * @param {Integer} issuerId The OAuth 2 issuer ID.\n * @param {Integer} courseId The course ID.\n * @param {Integer} shareFormat The share format.\n * @return {promise}\n */\nexport const sendCourse = (issuerId, courseId, shareFormat) => {\n const request = {\n methodname: 'core_moodlenet_send_course',\n args: {\n issuerid: issuerId,\n courseid: courseId,\n shareformat: shareFormat,\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Send the activity to Moodlenet.\n *\n * @param {Integer} issuerId The OAuth 2 issuer ID.\n * @param {Integer} cmId The course module ID.\n * @param {Integer} shareFormat The share format.\n * @return {promise}\n */\nexport const sendActivity = (issuerId, cmId, shareFormat) => {\n const request = {\n methodname: 'core_moodlenet_send_activity',\n args: {\n issuerid: issuerId,\n cmid: cmId,\n shareformat: shareFormat,\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Check if the user is already authorized with MoodleNet.\n *\n * @param {Integer} issuerId The OAuth 2 issuer ID.\n * @param {Integer} courseId The course ID.\n * @return {promise}\n */\nexport const authorizationCheck = (issuerId, courseId) => {\n const request = {\n methodname: 'core_moodlenet_auth_check',\n args: {\n issuerid: issuerId,\n courseid: courseId,\n }\n };\n\n return Ajax.call([request])[0];\n};\n"],"names":["cmId","request","methodname","args","cmid","Ajax","call","courseID","courseid","issuerId","courseId","shareFormat","issuerid","shareformat"],"mappings":";;;;;;;;4RAgCuCA,aAC7BC,QAAU,CACZC,WAAY,yCACZC,KAAM,CACFC,KAAMJ,cAIPK,cAAKC,KAAK,CAACL,UAAU,kCAUKM,iBAC3BN,QAAU,CACZC,WAAY,wCACZC,KAAM,CACFK,SAAUD,kBAIXF,cAAKC,KAAK,CAACL,UAAU,wBAWN,CAACQ,SAAUC,SAAUC,qBACrCV,QAAU,CACZC,WAAY,6BACZC,KAAM,CACFS,SAAUH,SACVD,SAAUE,SACVG,YAAaF,qBAIdN,cAAKC,KAAK,CAACL,UAAU,0BAWJ,CAACQ,SAAUT,KAAMW,qBACnCV,QAAU,CACZC,WAAY,+BACZC,KAAM,CACFS,SAAUH,SACVL,KAAMJ,KACNa,YAAaF,qBAIdN,cAAKC,KAAK,CAACL,UAAU,gCAUE,CAACQ,SAAUC,kBACnCT,QAAU,CACZC,WAAY,4BACZC,KAAM,CACFS,SAAUH,SACVD,SAAUE,kBAIXL,cAAKC,KAAK,CAACL,UAAU"} \ No newline at end of file +{"version":3,"file":"service.min.js","sources":["../../src/moodlenet/service.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A javascript module to handle MoodleNet ajax actions.\n *\n * @module core/moodlenet/service\n * @copyright 2023 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.2\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Get the activity information by course module id.\n *\n * @param {Integer} cmId The course module id.\n * @return {promise}\n */\nexport const getActivityInformation = (cmId) => {\n const request = {\n methodname: 'core_moodlenet_get_share_info_activity',\n args: {\n cmid: cmId\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n\n/**\n * Get the course information by course module id.\n *\n * @param {Integer} courseID The course id.\n * @return {promise}\n */\nexport const getCourseInformation = (courseID) => {\n const request = {\n methodname: 'core_moodlenet_get_shared_course_info',\n args: {\n courseid: courseID\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Send the course to MoodleNet.\n *\n * @param {Integer} issuerId The OAuth 2 issuer ID.\n * @param {Integer} courseId The course ID.\n * @param {Integer} shareFormat The share format.\n * @return {promise}\n */\nexport const sendCourse = (issuerId, courseId, shareFormat) => {\n const request = {\n methodname: 'core_moodlenet_send_course',\n args: {\n issuerid: issuerId,\n courseid: courseId,\n shareformat: shareFormat,\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Send the activity to Moodlenet.\n *\n * @param {Integer} issuerId The OAuth 2 issuer ID.\n * @param {Integer} cmId The course module ID.\n * @param {Integer} shareFormat The share format.\n * @return {promise}\n */\nexport const sendActivity = (issuerId, cmId, shareFormat) => {\n const request = {\n methodname: 'core_moodlenet_send_activity',\n args: {\n issuerid: issuerId,\n cmid: cmId,\n shareformat: shareFormat,\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Send the selected activities in a course to MoodleNet.\n *\n * @param {Integer} issuerId The OAuth 2 issuer ID.\n * @param {Integer} courseId The course ID.\n * @param {array} selectedCmIds Course module IDs in the course.\n * @param {Integer} shareFormat The share format.\n * @return {promise}\n */\nexport const sendPartialCourse = (issuerId, courseId, selectedCmIds, shareFormat) => {\n const request = {\n methodname: 'core_moodlenet_send_course',\n args: {\n issuerid: issuerId,\n courseid: courseId,\n shareformat: shareFormat,\n cmids: selectedCmIds,\n }\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Check if the user is already authorized with MoodleNet.\n *\n * @param {Integer} issuerId The OAuth 2 issuer ID.\n * @param {Integer} courseId The course ID.\n * @return {promise}\n */\nexport const authorizationCheck = (issuerId, courseId) => {\n const request = {\n methodname: 'core_moodlenet_auth_check',\n args: {\n issuerid: issuerId,\n courseid: courseId,\n }\n };\n\n return Ajax.call([request])[0];\n};\n"],"names":["cmId","request","methodname","args","cmid","Ajax","call","courseID","courseid","issuerId","courseId","shareFormat","issuerid","shareformat","selectedCmIds","cmids"],"mappings":";;;;;;;;uTAgCuCA,aAC7BC,QAAU,CACZC,WAAY,yCACZC,KAAM,CACFC,KAAMJ,cAIPK,cAAKC,KAAK,CAACL,UAAU,kCAUKM,iBAC3BN,QAAU,CACZC,WAAY,wCACZC,KAAM,CACFK,SAAUD,kBAIXF,cAAKC,KAAK,CAACL,UAAU,wBAWN,CAACQ,SAAUC,SAAUC,qBACrCV,QAAU,CACZC,WAAY,6BACZC,KAAM,CACFS,SAAUH,SACVD,SAAUE,SACVG,YAAaF,qBAIdN,cAAKC,KAAK,CAACL,UAAU,0BAWJ,CAACQ,SAAUT,KAAMW,qBACnCV,QAAU,CACZC,WAAY,+BACZC,KAAM,CACFS,SAAUH,SACVL,KAAMJ,KACNa,YAAaF,qBAIdN,cAAKC,KAAK,CAACL,UAAU,+BAYC,CAACQ,SAAUC,SAAUI,cAAeH,qBAC3DV,QAAU,CACZC,WAAY,6BACZC,KAAM,CACFS,SAAUH,SACVD,SAAUE,SACVG,YAAaF,YACbI,MAAOD,uBAIRT,cAAKC,KAAK,CAACL,UAAU,gCAUE,CAACQ,SAAUC,kBACnCT,QAAU,CACZC,WAAY,4BACZC,KAAM,CACFS,SAAUH,SACVD,SAAUE,kBAIXL,cAAKC,KAAK,CAACL,UAAU"} \ No newline at end of file diff --git a/lib/amd/src/moodlenet/authorize.js b/lib/amd/src/moodlenet/authorize.js new file mode 100644 index 00000000000..d3e29bca02f --- /dev/null +++ b/lib/amd/src/moodlenet/authorize.js @@ -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 . + +/** + * MoodleNet authorization. + * + * @module core/moodlenet/authorize + * @copyright 2023 Huong Nguyen + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since 4.3 + */ + +import {alert as displayAlert, exception as displayException} from 'core/notification'; +import * as MoodleNetService from 'core/moodlenet/service'; +import {sendToMoodleNet} from 'core/moodlenet/send_resource'; + +/** + * Handle authorization with MoodleNet server. + * + * @param {int} issuerId The OAuth 2 issuer ID. + * @param {int} courseId Course id. + * @param {int} resourceId Resource id. + * @param {int} shareFormat Share format. + * @return {promise} + */ +export const handleAuthorization = (issuerId, courseId, resourceId, shareFormat) => { + const windowSizeWidth = 550; + const windowSizeHeight = 550; + + // Check if the user is authorized with MoodleNet or not. + return MoodleNetService.authorizationCheck(issuerId, courseId).then(async(data) => { + if (!data.status) { + // Not yet authorized. + // Declare moodleNetAuthorize variable, so we can call it later in the callback. + window.moodleNetAuthorize = (error, errorDescription) => { + // This will be called by the callback after the authorization is successful. + if (error === '') { + handleAuthorization(issuerId, courseId, resourceId, shareFormat); + } else if (error !== 'access_denied') { + displayAlert( + 'Authorization error', + 'Error: ' + error + '

Error description: ' + errorDescription, + 'Cancel' + ); + } + }; + // Open the login url of the OAuth 2 issuer for user to login into MoodleNet and authorize. + return window.open(data.loginurl, 'moodlenet_auth', + `location=0,status=0,width=${windowSizeWidth},height=${windowSizeHeight},scrollbars=yes`); + } else { + // Already authorized. + return sendToMoodleNet(issuerId, resourceId, shareFormat); + } + }).catch(displayException); +}; diff --git a/lib/amd/src/moodlenet/events.js b/lib/amd/src/moodlenet/events.js new file mode 100644 index 00000000000..90e008d42f9 --- /dev/null +++ b/lib/amd/src/moodlenet/events.js @@ -0,0 +1,27 @@ +// 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 . + +/** + * MoodleNet events. + * + * @module core/moodlenet/events + * @copyright 2023 Huong Nguyen + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since 4.3 + */ + +export default { + MOODLENET_SHARE_STARTED: 'moodlenet-share-started', +}; diff --git a/lib/amd/src/moodlenet/mutations.js b/lib/amd/src/moodlenet/mutations.js new file mode 100644 index 00000000000..90e29f5ed5b --- /dev/null +++ b/lib/amd/src/moodlenet/mutations.js @@ -0,0 +1,62 @@ +// 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 . + +/** + * MoodleNet mutations. + * An instance of this class will be used to add custom mutations to the course editor. + * + * @module core/moodlenet/mutations + * @copyright 2023 Huong Nguyen + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since 4.3 + */ + +import DefaultMutations from 'core_courseformat/local/courseeditor/mutations'; +import {getCurrentCourseEditor} from 'core_courseformat/courseeditor'; +import CourseActions from 'core_courseformat/local/content/actions'; +import {subscribe} from 'core/pubsub'; +import {handleModal} from 'core/moodlenet/send_resource'; +import MoodleNetEvents from 'core/moodlenet/events'; + +class MoodleNetMutations extends DefaultMutations { + + /** + * Share to MoodleNet. + * + * @param {StateManager} stateManager the current state manager + * @param {array} cmIds Course module ids. + */ + shareToMoodleNet = async function(stateManager, cmIds) { + this.cmLock(stateManager, cmIds, true); + handleModal('partial', 'resource', cmIds); + this.cmLock(stateManager, cmIds, false); + subscribe(MoodleNetEvents.MOODLENET_SHARE_STARTED, () => { + // Only clear the selection if the user starts the sharing. + this.bulkReset(stateManager); + }); + }; +} + +/** + * Initialize. + */ +export const init = () => { + const courseEditor = getCurrentCourseEditor(); + courseEditor.addMutations(new MoodleNetMutations()); + // Add direct mutation content actions. + CourseActions.addActions({ + cmShareToMoodleNet: 'shareToMoodleNet' + }); +}; diff --git a/lib/amd/src/moodlenet/send_resource.js b/lib/amd/src/moodlenet/send_resource.js index fff212152e9..a4ee3b1d554 100644 --- a/lib/amd/src/moodlenet/send_resource.js +++ b/lib/amd/src/moodlenet/send_resource.js @@ -23,15 +23,19 @@ */ import Config from 'core/config'; -import {alert as displayAlert, addNotification, exception as displayException} from 'core/notification'; +import {addNotification, exception as displayException} from 'core/notification'; import {getString} from 'core/str'; import Prefetch from "core/prefetch"; import * as Templates from 'core/templates'; +import {publish} from 'core/pubsub'; import * as MoodleNetService from 'core/moodlenet/service'; import SendActivityModal from 'core/moodlenet/send_activity_modal'; +import * as MoodleNetAuthorize from 'core/moodlenet/authorize'; +import MoodleNetEvents from 'core/moodlenet/events'; const TYPE_ACTIVITY = "activity"; const TYPE_COURSE = "course"; +const TYPE_PARTIAL_COURSE = "partial"; let listenersRegistered = false; let currentModal; @@ -41,6 +45,7 @@ let courseId; let resourceId; let shareFormat; let type; +let selectedCmIds; /** * Handle send to MoodleNet. @@ -49,7 +54,7 @@ let type; * @param {int} resourceId The resource ID, it can be a course or an activity. * @param {int} shareFormat The share format. */ -const sendToMoodleNet = (issuerId, resourceId, shareFormat) => { +export const sendToMoodleNet = (issuerId, resourceId, shareFormat) => { const $modal = currentModal.getModal(); const modal = $modal[0]; modal.querySelector('.modal-header').classList.remove('no-border'); @@ -63,6 +68,12 @@ const sendToMoodleNet = (issuerId, resourceId, shareFormat) => { infoPromise = MoodleNetService.sendActivity(issuerId, resourceId, shareFormat); } else if (type === TYPE_COURSE) { infoPromise = MoodleNetService.sendCourse(issuerId, resourceId, shareFormat); + } else if (type === TYPE_PARTIAL_COURSE) { + if (selectedCmIds.length > 1) { + infoPromise = MoodleNetService.sendPartialCourse(issuerId, resourceId, selectedCmIds, shareFormat); + } else { + infoPromise = MoodleNetService.sendActivity(issuerId, selectedCmIds[0], shareFormat); + } } infoPromise.then(async(data) => { const status = data.status; @@ -94,61 +105,46 @@ const responseFromMoodleNet = (status, resourceUrl = '') => { } }; -/** - * Handle authorization with MoodleNet server. - * - * @param {Number} issuerId The OAuth 2 issuer ID. - * @return {promise} - */ -const handleAuthorization = (issuerId) => { - const windowsizewidth = 550; - const windowsizeheight = 550; - - // Check if the user is authorized with MoodleNet or not. - return MoodleNetService.authorizationCheck(issuerId, courseId).then((data) => { - if (!data.status) { - // Not yet authorized. - // Declare moodleNetAuthorize variable, so we can call it later in the callback. - window.moodleNetAuthorize = (error, errorDescription) => { - // This will be called by the callback after the authorization is successful. - if (error === '') { - handleAuthorization(issuerId); - } else if (error !== 'access_denied') { - displayAlert( - 'Authorization error', - 'Error: ' + error + '

Error description: ' + errorDescription, - 'Cancel' - ); - } - }; - // Open the login url of the OAuth 2 issuer for user to login into MoodleNet and authorize. - return window.open(data.loginurl, 'moodlenet_auth', - `location=0,status=0,width=${windowsizewidth},height=${windowsizeheight},scrollbars=yes`); - } else { - // Already authorized. - return sendToMoodleNet(issuerId, resourceId, shareFormat); - } - }).catch(displayException); -}; - /** * Render the modal to send resource to MoodleNet. * * @param {object} data The data of the resource to be shared. * @param {string} shareType The type of the resource to be shared. + * @param {array} selectedActivities Selected activities. */ -const renderModal = async(data, shareType) => { +const renderModal = async(data, shareType, selectedActivities) => { if (data.status) { siteSupportUrl = data.supportpageurl; issuerId = data.issuerid; - return SendActivityModal.create({ + let modalConfig = { templateContext: { - activitytype: data.type, - activityname: data.name, - sharetype: await getString(`moodlenet:sharetype${shareType}`, 'moodle'), - server: data.server, + 'activitytype': data.type, + 'activityname': data.name, + 'server': data.server, } - }); + }; + const sharetype = await getString('moodlenet:sharetype' + shareType, 'moodle'); + if (selectedActivities.length > 0) { + selectedCmIds = selectedActivities; + } + if (selectedActivities.length > 1) { + modalConfig.templateContext.fullsharing = false; + modalConfig.templateContext.selectedactivitiesnotice = await getString('moodlenet:sharenoticepartialactivitynumber', + 'moodle', selectedActivities.length); + modalConfig.templateContext.sharenotice = await getString('moodlenet:sharenoticepartial', + 'moodle', sharetype); + } else { + modalConfig.templateContext.fullsharing = true; + if (type === TYPE_PARTIAL_COURSE && selectedActivities.length == 1) { + modalConfig.templateContext.sharenotice = await getString('moodlenet:sharenotice', + 'moodle', {'type': TYPE_ACTIVITY, 'sharetype': sharetype}); + } else { + modalConfig.templateContext.sharenotice = await getString('moodlenet:sharenotice', + 'moodle', {'type': type, 'sharetype': sharetype}); + } + } + + return SendActivityModal.create(modalConfig); } else { return addNotification({ message: data.warnings[0].message, @@ -157,6 +153,43 @@ const renderModal = async(data, shareType) => { } }; +/** + * Handle modal. + * @param {string} shareActionType Share action type. + * @param {string} shareType Share type. + * @param {array} selectedActivities Selected activities. + */ +export const handleModal = (shareActionType, shareType, selectedActivities = []) => { + const resourceId = Config.contextInstanceId; + type = shareActionType; + + Promise.resolve(type) + .then((type) => { + if (type === TYPE_ACTIVITY) { + return MoodleNetService.getActivityInformation(resourceId); + } else if (type === TYPE_COURSE) { + return MoodleNetService.getCourseInformation(resourceId); + } else if (type === TYPE_PARTIAL_COURSE) { + if (selectedActivities.length > 1) { + // Selected more than one activity. + return MoodleNetService.getCourseInformation(resourceId); + } else { + // Select only one activity. Switch to activity mode. + return MoodleNetService.getActivityInformation(selectedActivities[0]); + } + } + throw new Error(`Unknown type ${type}`); + }) + .then((data) => { + return renderModal(data, shareType, selectedActivities); + }) + .then((modal) => { + currentModal = modal; + return currentModal; + }) + .catch(displayException); +}; + /** * Register events. */ @@ -168,31 +201,16 @@ const registerEventListeners = () => { e.preventDefault(); type = shareAction.getAttribute('data-type'); const shareType = shareAction.getAttribute('data-sharetype'); - Promise.resolve(type) - .then((type) => { - if (type === TYPE_ACTIVITY) { - return MoodleNetService.getActivityInformation(Config.contextInstanceId); - } else if (type === TYPE_COURSE) { - return MoodleNetService.getCourseInformation(Config.contextInstanceId); - } - throw new Error(`Unknown type ${type}`); - }) - .then((data) => { - return renderModal(data, shareType); - }) - .then((modal) => { - currentModal = modal; - return currentModal; - }) - .catch(displayException); + handleModal(shareAction.getAttribute('data-type'), shareType); } if (sendAction) { e.preventDefault(); + publish(MoodleNetEvents.MOODLENET_SHARE_STARTED, {}); courseId = Config.courseId; resourceId = Config.contextInstanceId; shareFormat = 0; - handleAuthorization(issuerId); + MoodleNetAuthorize.handleAuthorization(issuerId, courseId, resourceId, shareFormat); } }); }; @@ -208,6 +226,8 @@ export const init = () => { 'core/moodlenet/send_activity_modal_packaging', 'core/moodlenet/send_activity_modal_done', 'core/moodlenet/send_activity_modal_footer_view', + 'core/moodlenet/send_activity_modal_footer_share', + 'core/moodlenet/send_course_modal_base', ]); registerEventListeners(); listenersRegistered = true; diff --git a/lib/amd/src/moodlenet/service.js b/lib/amd/src/moodlenet/service.js index 9ad9cf69623..11dafb27e7c 100644 --- a/lib/amd/src/moodlenet/service.js +++ b/lib/amd/src/moodlenet/service.js @@ -101,6 +101,29 @@ export const sendActivity = (issuerId, cmId, shareFormat) => { return Ajax.call([request])[0]; }; +/** + * Send the selected activities in a course to MoodleNet. + * + * @param {Integer} issuerId The OAuth 2 issuer ID. + * @param {Integer} courseId The course ID. + * @param {array} selectedCmIds Course module IDs in the course. + * @param {Integer} shareFormat The share format. + * @return {promise} + */ +export const sendPartialCourse = (issuerId, courseId, selectedCmIds, shareFormat) => { + const request = { + methodname: 'core_moodlenet_send_course', + args: { + issuerid: issuerId, + courseid: courseId, + shareformat: shareFormat, + cmids: selectedCmIds, + } + }; + + return Ajax.call([request])[0]; +}; + /** * Check if the user is already authorized with MoodleNet. * diff --git a/lib/classes/external/moodlenet_get_shared_course_info.php b/lib/classes/external/moodlenet_get_shared_course_info.php index 42fc48d426f..656c9324d09 100644 --- a/lib/classes/external/moodlenet_get_shared_course_info.php +++ b/lib/classes/external/moodlenet_get_shared_course_info.php @@ -53,7 +53,7 @@ class moodlenet_get_shared_course_info extends external_api { * @return array */ public static function execute(int $courseid): array { - global $CFG, $USER; + global $USER; [ 'courseid' => $courseid diff --git a/lib/classes/output/icon_system_fontawesome.php b/lib/classes/output/icon_system_fontawesome.php index 99a05c93290..301e9a32798 100644 --- a/lib/classes/output/icon_system_fontawesome.php +++ b/lib/classes/output/icon_system_fontawesome.php @@ -324,6 +324,7 @@ class icon_system_fontawesome extends icon_system_font { 'core:i/section' => 'fa-folder-o', 'core:i/sendmessage' => 'fa-paper-plane', 'core:i/settings' => 'fa-cog', + 'core:i/share' => 'fa-share-square-o', 'core:i/show' => 'fa-eye-slash', 'core:i/siteevent' => 'fa-globe', 'core:i/star' => 'fa-star', diff --git a/lib/navigationlib.php b/lib/navigationlib.php index f28018ff829..cb9167444a8 100644 --- a/lib/navigationlib.php +++ b/lib/navigationlib.php @@ -4638,6 +4638,9 @@ class settings_navigation extends navigation_node { } // MoodleNet links. + if ($this->page->user_is_editing()) { + $this->page->requires->js_call_amd('core/moodlenet/mutations', 'init'); + } $usercanshare = utilities::can_user_share($coursecontext, $USER->id, 'course'); $issuerid = get_config('moodlenet', 'oauthservice'); try { diff --git a/lib/templates/moodlenet/send_activity_modal_base.mustache b/lib/templates/moodlenet/send_activity_modal_base.mustache index 8cba958ecad..44c8a8d67b2 100644 --- a/lib/templates/moodlenet/send_activity_modal_base.mustache +++ b/lib/templates/moodlenet/send_activity_modal_base.mustache @@ -45,8 +45,13 @@
- {{#pix}} e/help, core, {{#str}} moodlenet:sharenotice, moodle, {{sharetype}} {{/str}}{{/pix}} {{#str}} moodlenet:sharenotice, moodle, {{sharetype}} {{/str}} + {{sharenotice}}
+ {{^fullsharing}} +
+ {{selectedactivitiesnotice}} +
+ {{/fullsharing}}