From 3a749678290ea591b4dec6633fb32ec3c48552bc Mon Sep 17 00:00:00 2001 From: Farhan Karmali Date: Thu, 29 Aug 2024 22:48:42 +0530 Subject: [PATCH 1/9] Fix db/install.xml structure for Moodle XMLDB checker --- db/install.xml | 60 +++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/db/install.xml b/db/install.xml index dd2cdd5..48c029f 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,33 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
From 08e692b07afda4fac924ee2b05429ba0ee89d444 Mon Sep 17 00:00:00 2001 From: Farhan Karmali Date: Tue, 3 Sep 2024 17:32:28 +0530 Subject: [PATCH 2/9] Make plugin compatible with privacy provider API --- classes/privacy/provider.php | 85 +++++++++++++++++++++++++++++++++- lang/en/block_sharing_cart.php | 1 + 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index 8c555eb..bc33db0 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -8,8 +8,17 @@ // @codeCoverageIgnoreEnd use core_privacy\local\metadata\collection; +use core_privacy\local\request\approved_contextlist; +use core_privacy\local\request\approved_userlist; +use core_privacy\local\request\contextlist; +use core_privacy\local\request\transform; +use core_privacy\local\request\userlist; +use core_privacy\local\request\writer; -class provider implements \core_privacy\local\metadata\provider +class provider implements + \core_privacy\local\metadata\provider, + \core_privacy\local\request\plugin\provider, + \core_privacy\local\request\core_userlist_provider { public static function get_metadata(collection $collection): collection { @@ -23,8 +32,80 @@ public static function get_metadata(collection $collection): collection 'status' => 'privacy:metadata:sharing_cart_items:status', 'timecreated' => 'privacy:metadata:sharing_cart_items:timecreated', 'timemodified' => 'privacy:metadata:sharing_cart_items:timemodified', - ]); + ], 'privacy:metadata:sharing_cart_items:tabledesc'); return $collection; } + + public static function get_contexts_for_userid(int $userid): contextlist { + $contextlist = new \core_privacy\local\request\contextlist(); + $sql = "SELECT id FROM {context} WHERE contextlevel = 30 AND instanceid = :userid"; + $contextlist->add_from_sql($sql, ['userid' => $userid]); + return $contextlist; + } + + public static function export_user_data(approved_contextlist $contextlist) { + global $DB; + + $user = $contextlist->get_user(); + $sql = 'SELECT * + FROM {block_sharing_cart_items} i + WHERE i.user_id = :userid'; + + $context = \context_user::instance($user->id); + $contextpath = [get_string('pluginname', 'block_sharing_cart')]; + + $recordset = $DB->get_recordset_sql($sql, ['userid' => $user->id]); + foreach ($recordset as $record) { + $data = (object) [ + 'name' => format_string($record->name), + 'timecreated' => transform::datetime($record->timecreated), + ]; + + writer::with_context($context)->export_data(array_merge($contextpath, [ + clean_param($record->idopensesame, PARAM_FILE), + ]), $data); + } + + $recordset->close(); + + } + + public static function delete_data_for_all_users_in_context(\context $context) { + global $DB; + // Only delete data for a user context. + if ($context->contextlevel == CONTEXT_USER) { + $DB->delete_records('block_sharing_cart_items', ['user_id' => $context->instanceid]); + } + + } + + public static function delete_data_for_user(approved_contextlist $contextlist) { + global $DB; + foreach ($contextlist as $context) { + if ($context->contextlevel == CONTEXT_USER && $contextlist->get_user()->id == $context->instanceid) { + $DB->delete_records('block_sharing_cart_items', ['user_id' => $context->instanceid]); + } + } + } + + public static function get_users_in_context(userlist $userlist) { + global $DB; + $context = $userlist->get_context(); + if (!$context instanceof \context_user) { + return; + } + + if ($DB->record_exists('block_sharing_cart_items', ['user_id' => $context->instanceid])) { + $userlist->add_user($context->instanceid); + } + } + + public static function delete_data_for_users(approved_userlist $userlist) { + global $DB; + $context = $userlist->get_context(); + if ($context instanceof \context_user && in_array($context->instanceid, $userlist->get_userids())) { + $DB->delete_records('block_sharing_cart_items', ['user_id' => $context->instanceid]); + } + } } \ No newline at end of file diff --git a/lang/en/block_sharing_cart.php b/lang/en/block_sharing_cart.php index 1e3c12e..e0bc3a1 100644 --- a/lang/en/block_sharing_cart.php +++ b/lang/en/block_sharing_cart.php @@ -81,5 +81,6 @@ $string['privacy:metadata:sharing_cart_items:type'] = 'The type of the item'; $string['privacy:metadata:sharing_cart_items:name'] = 'The name of the item'; $string['privacy:metadata:sharing_cart_items:status'] = 'The status of the item'; +$string['privacy:metadata:sharing_cart_items:tabledesc'] = 'The table that stores sharing cart items'; $string['privacy:metadata:sharing_cart_items:timecreated'] = 'The time this item was created'; $string['privacy:metadata:sharing_cart_items:timemodified'] = 'The time this item was modified'; From fd0ab7a4411eae1bc73d59144269c942aae94f58 Mon Sep 17 00:00:00 2001 From: Halfdan Karlsen Monie Date: Mon, 16 Sep 2024 12:08:35 +0200 Subject: [PATCH 3/9] praxisdigital/moodle-opgaver#448 - Added select all checkbox --- README.md | 38 +++--- amd/build/app/block/element.min.js | 2 +- amd/build/app/block/element.min.js.map | 2 +- amd/build/app/block/item/element.min.js | 2 +- amd/build/app/block/item/element.min.js.map | 2 +- amd/build/app/block/queue/element.min.js.map | 2 +- amd/src/app/block/element.js | 116 ++++++++++++++++--- amd/src/app/block/item/element.js | 11 +- amd/src/app/block/queue/element.js | 1 + block_sharing_cart.php | 4 +- lang/da/block_sharing_cart.php | 4 + lang/en/block_sharing_cart.php | 14 +-- templates/block/content.mustache | 28 +++-- version.php | 2 +- 14 files changed, 160 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 6f15717..38edad7 100644 --- a/README.md +++ b/README.md @@ -37,25 +37,25 @@ Change Log ---------- * 5.0, release 1 2024.08.05 - * Total refactor of the whole plugin: - * Improvements - * Simplified the database structure. - * Code is now much more readable and maintainable. - * All HTML have been moved to mustache templates. - * We now use the Moodle core backup and restore system for sections as well. This means that we can now - restore sections and keep related access restrictions. - * All ajax calls are now done using the Moodle core external functions. - * As everything is now done asynchronously, you should have a much better experience when using the - sharing cart. - Not having to reload the whole page all the time... - * Supports the filter_multilang as well now. - * Changes - * It is no longer possible to move single activities between sections in the sharing cart. - * All backups/restores are now done asynchronously. If you have a lot of adhoc tasks running on your site, - it's also possible to manually run them. - * Old sharing cart items - * Will be converted to the new format when you upgrade the plugin. - * You won't be able to restore these items all at once like before, but you can restore them one by one. - * Old sections will be marked as legacy with a yellow warning icon. + * Total refactor of the whole plugin: + * Improvements + * Simplified the database structure. + * Code is now much more readable and maintainable. + * All HTML have been moved to mustache templates. + * We now use the Moodle core backup and restore system for sections as well. This means that we can now + restore sections and keep related access restrictions. + * All ajax calls are now done using the Moodle core external functions. + * As everything is now done asynchronously, you should have a much better experience when using the + sharing cart. - Not having to reload the whole page all the time... + * Supports the filter_multilang as well now. + * Changes + * It is no longer possible to move single activities between sections in the sharing cart. + * All backups/restores are now done asynchronously. If you have a lot of adhoc tasks running on your site, + it's also possible to manually run them. + * Old sharing cart items + * Will be converted to the new format when you upgrade the plugin. + * You won't be able to restore these items all at once like before, but you can restore them one by one. + * Old sections will be marked as legacy with a yellow warning icon. * 4.4, release 4 2024.02.06 * Added an anonymize userdata checkbox to the confirm modal. * 4.4, release 3 2024.02.05 diff --git a/amd/build/app/block/element.min.js b/amd/build/app/block/element.min.js index 645335e..ad20e44 100644 --- a/amd/build/app/block/element.min.js +++ b/amd/build/app/block/element.min.js @@ -1,3 +1,3 @@ -define("block_sharing_cart/app/block/element",["exports","../../lib/sortablejs","core/modal_factory","core/modal_events","core/str","core/ajax","core/notification"],(function(_exports,_sortablejs,_modal_factory,_modal_events,_str,_ajax,_notification){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classPrivateFieldInitSpec(obj,privateMap,value){!function(obj,privateCollection){if(privateCollection.has(obj))throw new TypeError("Cannot initialize the same private elements twice on an object")}(obj,privateMap),privateMap.set(obj,value)}function _classPrivateFieldGet(receiver,privateMap){return function(receiver,descriptor){if(descriptor.get)return descriptor.get.call(receiver);return descriptor.value}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"get"))}function _classPrivateFieldSet(receiver,privateMap,value){return function(receiver,descriptor,value){if(descriptor.set)descriptor.set.call(receiver,value);else{if(!descriptor.writable)throw new TypeError("attempted to set read only private field");descriptor.value=value}}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"set"),value),value}function _classExtractFieldDescriptor(receiver,privateMap,action){if(!privateMap.has(receiver))throw new TypeError("attempted to "+action+" private field on non-instance");return privateMap.get(receiver)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_sortablejs=_interopRequireDefault(_sortablejs),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_ajax=_interopRequireDefault(_ajax),_notification=_interopRequireDefault(_notification);var _baseFactory=new WeakMap,_element=new WeakMap,_course=new WeakMap,_queue=new WeakMap,_items=new WeakMap,_sortable=new WeakMap,_clipboardItem=new WeakMap,_canBackupUserdata=new WeakMap,_canAnonymizeUserdata=new WeakMap,_showSharingCartBasket=new WeakMap,_draggedCourseModuleId=new WeakMap,_draggedSectionId=new WeakMap;return _exports.default=class{constructor(baseFactory,element,canBackupUserdata,canAnonymizeUserdata,showSharingCartBasket){_classPrivateFieldInitSpec(this,_baseFactory,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_element,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_course,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_queue,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_items,{writable:!0,value:[]}),_classPrivateFieldInitSpec(this,_sortable,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_clipboardItem,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_canBackupUserdata,{writable:!0,value:!1}),_classPrivateFieldInitSpec(this,_canAnonymizeUserdata,{writable:!0,value:!1}),_classPrivateFieldInitSpec(this,_showSharingCartBasket,{writable:!0,value:!1}),_classPrivateFieldInitSpec(this,_draggedCourseModuleId,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_draggedSectionId,{writable:!0,value:null}),_classPrivateFieldSet(this,_baseFactory,baseFactory),_classPrivateFieldSet(this,_element,element),_classPrivateFieldSet(this,_canBackupUserdata,canBackupUserdata),_classPrivateFieldSet(this,_canAnonymizeUserdata,canAnonymizeUserdata),_classPrivateFieldSet(this,_showSharingCartBasket,showSharingCartBasket)}addEventListeners(){return this.setupCourse(),this.setupQueue(),this.setupItems(),this.setupDragAndDrop(),this.setupBulkDelete(),{course:_classPrivateFieldGet(this,_course),queue:_classPrivateFieldGet(this,_queue),block:this}}setupCourse(){const course=document.querySelector(".course-content");_classPrivateFieldSet(this,_course,_classPrivateFieldGet(this,_baseFactory).block().course().element(this,course))}setupQueue(){const queue=document.querySelector(".sharing_cart_queue");_classPrivateFieldSet(this,_queue,_classPrivateFieldGet(this,_baseFactory).block().queue().element(this,queue))}setupItems(){_classPrivateFieldGet(this,_element).querySelectorAll(".sharing_cart_item").forEach((element=>{this.setupItem(element)})),_classPrivateFieldSet(this,_sortable,new _sortablejs.default(_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items"),{dataIdAttr:"data-itemid",onUpdate:()=>{_ajax.default.call([{methodname:"block_sharing_cart_reorder_sharing_cart_items",args:{item_ids:_classPrivateFieldGet(this,_sortable).toArray()},fail:data=>{_notification.default.exception(data)}}])}}))}setupDragAndDrop(){const dropZone=_classPrivateFieldGet(this,_element);dropZone.addEventListener("dragover",(e=>{(_classPrivateFieldGet(this,_draggedSectionId)||_classPrivateFieldGet(this,_draggedCourseModuleId))&&(e.preventDefault(),e.stopPropagation())})),dropZone.addEventListener("dragleave",(e=>{(_classPrivateFieldGet(this,_draggedSectionId)||_classPrivateFieldGet(this,_draggedCourseModuleId))&&(e.preventDefault(),e.stopPropagation())})),dropZone.addEventListener("drop",(async e=>{(_classPrivateFieldGet(this,_draggedSectionId)||_classPrivateFieldGet(this,_draggedCourseModuleId))&&(e.preventDefault(),e.stopPropagation(),_classPrivateFieldGet(this,_draggedSectionId)?await this.addSectionBackupToSharingCart(_classPrivateFieldGet(this,_draggedSectionId)):_classPrivateFieldGet(this,_draggedCourseModuleId)&&await this.addCourseModuleBackupToSharingCart(_classPrivateFieldGet(this,_draggedCourseModuleId)))}))}setupBulkDelete(){const enableBulkDeleteButton=_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_bulk_delete"),disableBulkDeleteButton=_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_cancel_bulk_delete"),bulkDeleteButton=_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_bulk_delete_confirm"),checkboxSelector='.sharing_cart_item input[data-action="bulk_select"][type="checkbox"]';enableBulkDeleteButton.addEventListener("click",(()=>{enableBulkDeleteButton.classList.add("d-none"),disableBulkDeleteButton.classList.remove("d-none"),bulkDeleteButton.classList.remove("d-none"),_classPrivateFieldGet(this,_element).querySelectorAll(checkboxSelector).forEach((checkbox=>{checkbox.classList.remove("d-none"),checkbox.checked=!1}))})),disableBulkDeleteButton.addEventListener("click",(()=>{disableBulkDeleteButton.classList.add("d-none"),bulkDeleteButton.classList.add("d-none"),bulkDeleteButton.disabled=!0,enableBulkDeleteButton.classList.remove("d-none"),_classPrivateFieldGet(this,_element).querySelectorAll(checkboxSelector).forEach((checkbox=>{checkbox.classList.add("d-none"),checkbox.checked=!1}))})),bulkDeleteButton.addEventListener("click",(async()=>{if(bulkDeleteButton.disabled)return;const itemIds=[];_classPrivateFieldGet(this,_element).querySelectorAll(checkboxSelector+":checked").forEach((checkbox=>{itemIds.push(checkbox.value)})),await this.confirmDeleteItems(itemIds)}))}setupItem(element){var _classPrivateFieldGet2;const itemElement=_classPrivateFieldGet(this,_baseFactory).block().item().element(this,element);null===(_classPrivateFieldGet2=_classPrivateFieldGet(this,_element).querySelector(".no-items"))||void 0===_classPrivateFieldGet2||_classPrivateFieldGet2.remove(),_classPrivateFieldGet(this,_items).push(itemElement)}async setClipboard(item){_classPrivateFieldSet(this,_clipboardItem,item),await _classPrivateFieldGet(this,_course).setClipboard(item)}clearClipboard(){_classPrivateFieldSet(this,_clipboardItem,null)}setDraggedSectionId(id){_classPrivateFieldSet(this,_draggedSectionId,id)}setDraggedCourseModuleId(id){_classPrivateFieldSet(this,_draggedCourseModuleId,id)}async removeItemElement(item){var _classPrivateFieldGet4;item.getItemChildrenRecursively().forEach((childItem=>{var _classPrivateFieldGet3;const index=_classPrivateFieldGet(this,_items).findIndex((i=>i.getItemId()===Number.parseInt(childItem.dataset.itemid)));-1!==index&&(_classPrivateFieldGet(this,_items)[index].getItemId()===(null===(_classPrivateFieldGet3=_classPrivateFieldGet(this,_clipboardItem))||void 0===_classPrivateFieldGet3?void 0:_classPrivateFieldGet3.getItemId())&&_classPrivateFieldGet(this,_course).clearClipboard(),_classPrivateFieldGet(this,_items).splice(index,1),childItem.remove())}));const index=_classPrivateFieldGet(this,_items).findIndex((i=>i.getItemId()===item.getItemId()));_classPrivateFieldGet(this,_items)[index].getItemId()===(null===(_classPrivateFieldGet4=_classPrivateFieldGet(this,_clipboardItem))||void 0===_classPrivateFieldGet4?void 0:_classPrivateFieldGet4.getItemId())&&_classPrivateFieldGet(this,_course).clearClipboard(),_classPrivateFieldGet(this,_items).splice(index,1),item.remove(),0===_classPrivateFieldGet(this,_items).length&&(_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items").innerHTML=await(0,_str.get_string)("no_items","block_sharing_cart"))}deleteItem(item){_ajax.default.call([{methodname:"block_sharing_cart_delete_item_from_sharing_cart",args:{item_id:item.getItemId()},done:async deleted=>{deleted?await this.removeItemElement(item):await _notification.default.alert("Failed to delete item")},fail:data=>{_notification.default.exception(data)}}])}deleteItems(itemIds){itemIds=itemIds.map((id=>Number.parseInt(id))),_ajax.default.call([{methodname:"block_sharing_cart_delete_items_from_sharing_cart",args:{item_ids:itemIds},done:async deletedItemIds=>{const items=_classPrivateFieldGet(this,_items).filter((i=>itemIds.includes(i.getItemId())));for(const item of items){deletedItemIds.includes(item.getItemId())?await this.removeItemElement(item):_notification.default.alert('Failed to delete item: "'+item.getItemName()+'"')}document.getElementById("block_sharing_cart_bulk_delete_confirm").disabled=!0},fail:data=>{_notification.default.exception(data)}}])}getElement(){return _classPrivateFieldGet(this,_element)}async createBackupItemToSharingCartModal(itemName,onSave){const strings=await(0,_str.get_strings)([{key:"backup_item",component:"block_sharing_cart"},{key:"into_sharing_cart",component:"block_sharing_cart"},{key:"backup",component:"block_sharing_cart"},{key:"cancel",component:"core"}]),{html:html,js:js}=await _classPrivateFieldGet(this,_baseFactory).moodle().template().renderTemplate("block_sharing_cart/modal/backup_to_sharing_cart_modal_body",{show_user_data_backup:_classPrivateFieldGet(this,_canBackupUserdata),show_anonymize_user_data:_classPrivateFieldGet(this,_canBackupUserdata)&&_classPrivateFieldGet(this,_canAnonymizeUserdata)}),modal=await _modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:strings[0]+': "'+itemName.slice(0,50).trim()+'" '+strings[1],body:html,buttons:{save:strings[2],cancel:strings[3]},removeOnClose:!0});return modal.getRoot().on(_modal_events.default.shown,(()=>_classPrivateFieldGet(this,_baseFactory).moodle().template().runTemplateJS(js))),modal.getRoot().on(_modal_events.default.save,(()=>{var _modalUserdataCheckbo,_modalAnonymizeCheckb;const modalUserdataCheckbox=document.getElementById("modal-userdata-checkbox"),modalAnonymizeCheckbox=document.getElementById("modal-anonymize-checkbox");onSave({users:null!==(_modalUserdataCheckbo=null==modalUserdataCheckbox?void 0:modalUserdataCheckbox.checked)&&void 0!==_modalUserdataCheckbo&&_modalUserdataCheckbo,anonymize:null!==(_modalAnonymizeCheckb=null==modalAnonymizeCheckbox?void 0:modalAnonymizeCheckbox.checked)&&void 0!==_modalAnonymizeCheckb&&_modalAnonymizeCheckb})})),modal}async addSectionBackupToSharingCart(sectionId){const sectionName=_classPrivateFieldGet(this,_course).getSectionName(sectionId);if(0===_classPrivateFieldGet(this,_course).getSectionCourseModules(sectionId).length){const strings=await(0,_str.get_strings)([{key:"no_course_modules_in_section",component:"block_sharing_cart"},{key:"no_course_modules_in_section_description",component:"block_sharing_cart"}]);return void await _notification.default.alert(strings[0],strings[1])}const modal=await this.createBackupItemToSharingCartModal(sectionName,(settings=>{_ajax.default.call([{methodname:"block_sharing_cart_backup_section_into_sharing_cart",args:{section_id:sectionId,settings:settings},done:async data=>{await this.renderItem(data)},fail:data=>{_notification.default.exception(data)}}])}));await modal.show()}async addCourseModuleBackupToSharingCart(courseModuleId){const courseModuleName=_classPrivateFieldGet(this,_course).getCourseModuleName(courseModuleId),modal=await this.createBackupItemToSharingCartModal(courseModuleName,(settings=>{_ajax.default.call([{methodname:"block_sharing_cart_backup_course_module_into_sharing_cart",args:{course_module_id:courseModuleId,settings:settings},done:async data=>{await this.renderItem(data)},fail:data=>{_notification.default.exception(data)}}])}));await modal.show()}async renderItem(item){var _classPrivateFieldGet5,_item$task_id;const existingItemIndex=_classPrivateFieldGet(this,_items).findIndex((i=>i.getItemId()===item.id)),existingItem=null!==(_classPrivateFieldGet5=_classPrivateFieldGet(this,_items)[existingItemIndex])&&void 0!==_classPrivateFieldGet5&&_classPrivateFieldGet5,oldElement=_classPrivateFieldGet(this,_element).querySelector('.sharing_cart_items .sharing_cart_item[data-itemid="'+item.id+'"]');if(existingItem&&oldElement){const element=await _classPrivateFieldGet(this,_baseFactory).moodle().template().createElementFromFragment("block_sharing_cart","item",1,{item_id:item.id});return _classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items").replaceChild(element,oldElement),_classPrivateFieldGet(this,_items)[existingItemIndex]=_classPrivateFieldGet(this,_baseFactory).block().item().element(this,element),void element.querySelectorAll(".sharing_cart_item").forEach((subItem=>{this.setupItem(subItem)}))}const element=await _classPrivateFieldGet(this,_baseFactory).moodle().template().createElementFromTemplate("block_sharing_cart/block/item",{id:item.id,name:item.name,type:item.type,status:0,old_instance_id:item.old_instance_id,status_awaiting:!0,has_run_now:!0,task_id:null!==(_item$task_id=item.task_id)&&void 0!==_item$task_id?_item$task_id:null,status_finished:!1,status_failed:!1,is_module:"section"!==item.type,is_section:"section"===item.type,is_root:!0});_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items").prepend(element),this.setupItem(element)}importItem(item,sectionId,modal){_classPrivateFieldGet(this,_course).clearClipboard();const courseModuleIds=[];if(modal.querySelectorAll('input[type="checkbox"][data-type="coursemodule"]:checked').forEach((checkbox=>{courseModuleIds.push(checkbox.dataset.id)})),item.isSection()&&0===courseModuleIds.length)return modal.querySelectorAll(".form-check-input").forEach((async item=>{item.setCustomValidity(await(0,_str.get_string)("atleast_one_course_module_must_be_included","block_sharing_cart")),item.reportValidity()})),!1;item.isModule()&&courseModuleIds.push(item.getItemOldInstanceId()),_ajax.default.call([{methodname:"block_sharing_cart_restore_item_from_sharing_cart_into_section",args:{item_id:item.getItemId(),section_id:sectionId,course_modules_to_include:courseModuleIds},done:async success=>{success&&await _classPrivateFieldGet(this,_queue).loadQueue(!0)},fail:data=>{_notification.default.exception(data)}}])}async confirmImportBackupFromSharingCart(item,sectionId,e){e.preventDefault(),e.stopPropagation();const strings=await(0,_str.get_strings)([{key:"copy_item",component:"block_sharing_cart"},{key:"into_section",component:"block_sharing_cart"},{key:"import",component:"core"},{key:"cancel",component:"core"}]),sectionName=_classPrivateFieldGet(this,_course).getSectionName(sectionId),{html:html,js:js}=await _classPrivateFieldGet(this,_baseFactory).moodle().template().renderFragment("block_sharing_cart","item_restore_form",1,{item_id:item.getItemId()}),modal=await _modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:strings[0]+': "'+item.getItemName().slice(0,50).trim()+'" '+strings[1]+': "'+sectionName.slice(0,50).trim()+'"',body:html,buttons:{save:strings[2],cancel:strings[3]},removeOnClose:!0});modal.getRoot().on(_modal_events.default.shown,(()=>_classPrivateFieldGet(this,_baseFactory).moodle().template().runTemplateJS(js))),modal.getRoot().on(_modal_events.default.save,this.importItem.bind(this,item,sectionId,modal.getRoot()[0])),await modal.show()}async confirmDeleteItems(itemIds){const strings=await(0,_str.get_strings)([{key:"delete_items",component:"block_sharing_cart"},{key:"confirm_delete_items",component:"block_sharing_cart"},{key:"delete",component:"core"},{key:"cancel",component:"core"}]),modal=await _modal_factory.default.create({type:_modal_factory.default.types.DELETE_CANCEL,title:strings[0],body:strings[1],buttons:{delete:strings[2],cancel:strings[3]},removeOnClose:!0});modal.getRoot().on(_modal_events.default.delete,this.deleteItems.bind(this,itemIds)),await modal.show()}},_exports.default})); +define("block_sharing_cart/app/block/element",["exports","../../lib/sortablejs","core/modal_factory","core/modal_events","core/str","core/ajax","core/notification"],(function(_exports,_sortablejs,_modal_factory,_modal_events,_str,_ajax,_notification){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classPrivateFieldInitSpec(obj,privateMap,value){!function(obj,privateCollection){if(privateCollection.has(obj))throw new TypeError("Cannot initialize the same private elements twice on an object")}(obj,privateMap),privateMap.set(obj,value)}function _classPrivateFieldGet(receiver,privateMap){return function(receiver,descriptor){if(descriptor.get)return descriptor.get.call(receiver);return descriptor.value}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"get"))}function _classPrivateFieldSet(receiver,privateMap,value){return function(receiver,descriptor,value){if(descriptor.set)descriptor.set.call(receiver,value);else{if(!descriptor.writable)throw new TypeError("attempted to set read only private field");descriptor.value=value}}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"set"),value),value}function _classExtractFieldDescriptor(receiver,privateMap,action){if(!privateMap.has(receiver))throw new TypeError("attempted to "+action+" private field on non-instance");return privateMap.get(receiver)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_sortablejs=_interopRequireDefault(_sortablejs),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_ajax=_interopRequireDefault(_ajax),_notification=_interopRequireDefault(_notification);var _baseFactory=new WeakMap,_element=new WeakMap,_course=new WeakMap,_queue=new WeakMap,_items=new WeakMap,_sortable=new WeakMap,_clipboardItem=new WeakMap,_canBackupUserdata=new WeakMap,_canAnonymizeUserdata=new WeakMap,_showSharingCartBasket=new WeakMap,_draggedCourseModuleId=new WeakMap,_draggedSectionId=new WeakMap,_bulkDeleteEnabled=new WeakMap;return _exports.default=class{constructor(baseFactory,element,canBackupUserdata,canAnonymizeUserdata,showSharingCartBasket){_classPrivateFieldInitSpec(this,_baseFactory,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_element,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_course,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_queue,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_items,{writable:!0,value:[]}),_classPrivateFieldInitSpec(this,_sortable,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_clipboardItem,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_canBackupUserdata,{writable:!0,value:!1}),_classPrivateFieldInitSpec(this,_canAnonymizeUserdata,{writable:!0,value:!1}),_classPrivateFieldInitSpec(this,_showSharingCartBasket,{writable:!0,value:!1}),_classPrivateFieldInitSpec(this,_draggedCourseModuleId,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_draggedSectionId,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_bulkDeleteEnabled,{writable:!0,value:!1}),_classPrivateFieldSet(this,_baseFactory,baseFactory),_classPrivateFieldSet(this,_element,element),_classPrivateFieldSet(this,_canBackupUserdata,canBackupUserdata),_classPrivateFieldSet(this,_canAnonymizeUserdata,canAnonymizeUserdata),_classPrivateFieldSet(this,_showSharingCartBasket,showSharingCartBasket)}addEventListeners(){return this.setupCourse(),this.setupQueue(),this.setupItems(),this.setupDragAndDrop(),this.setupBulkDelete(),{course:_classPrivateFieldGet(this,_course),queue:_classPrivateFieldGet(this,_queue),block:this}}setupCourse(){const course=document.querySelector(".course-content");_classPrivateFieldSet(this,_course,_classPrivateFieldGet(this,_baseFactory).block().course().element(this,course))}setupQueue(){const queue=document.querySelector(".sharing_cart_queue");_classPrivateFieldSet(this,_queue,_classPrivateFieldGet(this,_baseFactory).block().queue().element(this,queue))}async setupItems(){const items=_classPrivateFieldGet(this,_element).querySelectorAll(".sharing_cart_item");for(const element of items)await this.setupItem(element);_classPrivateFieldSet(this,_sortable,new _sortablejs.default(_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items"),{dataIdAttr:"data-itemid",onUpdate:()=>{_ajax.default.call([{methodname:"block_sharing_cart_reorder_sharing_cart_items",args:{item_ids:_classPrivateFieldGet(this,_sortable).toArray()},fail:data=>{_notification.default.exception(data)}}])}}))}setupDragAndDrop(){const dropZone=_classPrivateFieldGet(this,_element);dropZone.addEventListener("dragover",(e=>{(_classPrivateFieldGet(this,_draggedSectionId)||_classPrivateFieldGet(this,_draggedCourseModuleId))&&(e.preventDefault(),e.stopPropagation())})),dropZone.addEventListener("dragleave",(e=>{(_classPrivateFieldGet(this,_draggedSectionId)||_classPrivateFieldGet(this,_draggedCourseModuleId))&&(e.preventDefault(),e.stopPropagation())})),dropZone.addEventListener("drop",(async e=>{(_classPrivateFieldGet(this,_draggedSectionId)||_classPrivateFieldGet(this,_draggedCourseModuleId))&&(e.preventDefault(),e.stopPropagation(),_classPrivateFieldGet(this,_draggedSectionId)?await this.addSectionBackupToSharingCart(_classPrivateFieldGet(this,_draggedSectionId)):_classPrivateFieldGet(this,_draggedCourseModuleId)&&await this.addCourseModuleBackupToSharingCart(_classPrivateFieldGet(this,_draggedCourseModuleId)))}))}setupBulkDelete(){const enableBulkDeleteButton=_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_bulk_delete"),disableBulkDeleteButton=_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_cancel_bulk_delete"),bulkDeleteButton=_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_bulk_delete_confirm"),selectAllContainer=_classPrivateFieldGet(this,_element).querySelector("#select_all_container");_classPrivateFieldGet(this,_element).querySelector("#select_all_box").addEventListener("click",(async()=>{const itemCheckboxes=this.getItemCheckboxes(),allSelected=Array.from(itemCheckboxes).every((checkbox=>checkbox.checked));itemCheckboxes.forEach((checkbox=>{checkbox.checked=!allSelected})),itemCheckboxes.forEach((checkbox=>checkbox.addEventListener("change",(async()=>{this.updateSelectAllState()})))),this.updateSelectAllState(),this.updateBulkDeleteButtonState()})),enableBulkDeleteButton.addEventListener("click",(()=>{0!==_classPrivateFieldGet(this,_items).length&&(_classPrivateFieldSet(this,_bulkDeleteEnabled,!0),enableBulkDeleteButton.classList.add("d-none"),disableBulkDeleteButton.classList.remove("d-none"),selectAllContainer.classList.remove("d-none"),bulkDeleteButton.classList.remove("d-none"),this.getItemCheckboxes().forEach((checkbox=>{checkbox.classList.remove("d-none"),checkbox.checked=!1})))})),disableBulkDeleteButton.addEventListener("click",(()=>{disableBulkDeleteButton.classList.add("d-none"),bulkDeleteButton.classList.add("d-none"),bulkDeleteButton.disabled=!0,enableBulkDeleteButton.classList.remove("d-none"),selectAllContainer.classList.add("d-none"),this.getItemCheckboxes().forEach((checkbox=>{checkbox.classList.add("d-none"),checkbox.checked=!1}))})),bulkDeleteButton.addEventListener("click",(async()=>{if(bulkDeleteButton.disabled)return;const itemIds=[];this.getItemCheckboxes().forEach((checkbox=>{checkbox.checked&&itemIds.push(checkbox.value)})),await this.confirmDeleteItems(itemIds)}))}async setupItem(element){var _classPrivateFieldGet2;const itemElement=_classPrivateFieldGet(this,_baseFactory).block().item().element(this,element);if("0"!==itemElement.getStatus()&&this.isBulkDeleteEnabled()){var _checkbox$classList;const checkbox=element.querySelector('input[data-action="bulk_select"][type="checkbox"]');null==checkbox||null===(_checkbox$classList=checkbox.classList)||void 0===_checkbox$classList||_checkbox$classList.remove("d-none")}null===(_classPrivateFieldGet2=_classPrivateFieldGet(this,_element).querySelector(".no-items"))||void 0===_classPrivateFieldGet2||_classPrivateFieldGet2.remove(),_classPrivateFieldGet(this,_items).push(itemElement),this.updateBulkDeleteButtonState(),this.updateSelectAllState()}getItemCheckboxes(){return _classPrivateFieldGet(this,_element).querySelectorAll('.sharing_cart_item:not([data-status="0"]) input[data-action="bulk_select"][type="checkbox"]')}updateBulkDeleteButtonState(){_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_bulk_delete_confirm").disabled=!Array.from(this.getItemCheckboxes()).some((checkbox=>checkbox.checked))}updateSelectAllState(){const selectAllCheckbox=_classPrivateFieldGet(this,_element).querySelector("#select_all_box"),selectAllLabel=_classPrivateFieldGet(this,_element).querySelector("#select_all_label"),itemCheckboxes=this.getItemCheckboxes(),allSelected=Array.from(itemCheckboxes).every((checkbox=>checkbox.checked)),someSelected=Array.from(itemCheckboxes).some((checkbox=>checkbox.checked));(allSelected?(0,_str.get_string)("deselect_all","block_sharing_cart"):(0,_str.get_string)("select_all","block_sharing_cart")).then((str=>{selectAllLabel.textContent=str})),selectAllCheckbox.checked=allSelected,selectAllCheckbox.indeterminate=!allSelected&&someSelected}isBulkDeleteEnabled(){return _classPrivateFieldGet(this,_bulkDeleteEnabled)}async setClipboard(item){_classPrivateFieldSet(this,_clipboardItem,item),await _classPrivateFieldGet(this,_course).setClipboard(item)}clearClipboard(){_classPrivateFieldSet(this,_clipboardItem,null)}setDraggedSectionId(id){_classPrivateFieldSet(this,_draggedSectionId,id)}setDraggedCourseModuleId(id){_classPrivateFieldSet(this,_draggedCourseModuleId,id)}async removeItemElement(item){var _classPrivateFieldGet4;item.getItemChildrenRecursively().forEach((childItem=>{var _classPrivateFieldGet3;const index=_classPrivateFieldGet(this,_items).findIndex((i=>i.getItemId()===Number.parseInt(childItem.dataset.itemid)));-1!==index&&(_classPrivateFieldGet(this,_items)[index].getItemId()===(null===(_classPrivateFieldGet3=_classPrivateFieldGet(this,_clipboardItem))||void 0===_classPrivateFieldGet3?void 0:_classPrivateFieldGet3.getItemId())&&_classPrivateFieldGet(this,_course).clearClipboard(),_classPrivateFieldGet(this,_items).splice(index,1),childItem.remove())}));const index=_classPrivateFieldGet(this,_items).findIndex((i=>i.getItemId()===item.getItemId()));_classPrivateFieldGet(this,_items)[index].getItemId()===(null===(_classPrivateFieldGet4=_classPrivateFieldGet(this,_clipboardItem))||void 0===_classPrivateFieldGet4?void 0:_classPrivateFieldGet4.getItemId())&&_classPrivateFieldGet(this,_course).clearClipboard(),_classPrivateFieldGet(this,_items).splice(index,1),item.remove(),0===_classPrivateFieldGet(this,_items).length&&(_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items").innerHTML=await(0,_str.get_string)("no_items","block_sharing_cart"))}deleteItem(item){_ajax.default.call([{methodname:"block_sharing_cart_delete_item_from_sharing_cart",args:{item_id:item.getItemId()},done:async deleted=>{deleted?await this.removeItemElement(item):await _notification.default.alert("Failed to delete item")},fail:data=>{_notification.default.exception(data)}}])}deleteItems(itemIds){itemIds=itemIds.map((id=>Number.parseInt(id))),_ajax.default.call([{methodname:"block_sharing_cart_delete_items_from_sharing_cart",args:{item_ids:itemIds},done:async deletedItemIds=>{const items=_classPrivateFieldGet(this,_items).filter((i=>itemIds.includes(i.getItemId())));for(const item of items){deletedItemIds.includes(item.getItemId())?await this.removeItemElement(item):_notification.default.alert('Failed to delete item: "'+item.getItemName()+'"')}this.updateSelectAllState(),document.getElementById("block_sharing_cart_bulk_delete_confirm").disabled=!0},fail:data=>{_notification.default.exception(data)}}])}getElement(){return _classPrivateFieldGet(this,_element)}async createBackupItemToSharingCartModal(itemName,onSave){const strings=await(0,_str.get_strings)([{key:"backup_item",component:"block_sharing_cart"},{key:"into_sharing_cart",component:"block_sharing_cart"},{key:"backup",component:"block_sharing_cart"},{key:"cancel",component:"core"}]),{html:html,js:js}=await _classPrivateFieldGet(this,_baseFactory).moodle().template().renderTemplate("block_sharing_cart/modal/backup_to_sharing_cart_modal_body",{show_user_data_backup:_classPrivateFieldGet(this,_canBackupUserdata),show_anonymize_user_data:_classPrivateFieldGet(this,_canBackupUserdata)&&_classPrivateFieldGet(this,_canAnonymizeUserdata)}),modal=await _modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:strings[0]+': "'+itemName.slice(0,50).trim()+'" '+strings[1],body:html,buttons:{save:strings[2],cancel:strings[3]},removeOnClose:!0});return modal.getRoot().on(_modal_events.default.shown,(()=>_classPrivateFieldGet(this,_baseFactory).moodle().template().runTemplateJS(js))),modal.getRoot().on(_modal_events.default.save,(()=>{var _modalUserdataCheckbo,_modalAnonymizeCheckb;const modalUserdataCheckbox=document.getElementById("modal-userdata-checkbox"),modalAnonymizeCheckbox=document.getElementById("modal-anonymize-checkbox");onSave({users:null!==(_modalUserdataCheckbo=null==modalUserdataCheckbox?void 0:modalUserdataCheckbox.checked)&&void 0!==_modalUserdataCheckbo&&_modalUserdataCheckbo,anonymize:null!==(_modalAnonymizeCheckb=null==modalAnonymizeCheckbox?void 0:modalAnonymizeCheckbox.checked)&&void 0!==_modalAnonymizeCheckb&&_modalAnonymizeCheckb})})),modal}async addSectionBackupToSharingCart(sectionId){const sectionName=_classPrivateFieldGet(this,_course).getSectionName(sectionId);if(0===_classPrivateFieldGet(this,_course).getSectionCourseModules(sectionId).length){const strings=await(0,_str.get_strings)([{key:"no_course_modules_in_section",component:"block_sharing_cart"},{key:"no_course_modules_in_section_description",component:"block_sharing_cart"}]);return void await _notification.default.alert(strings[0],strings[1])}const modal=await this.createBackupItemToSharingCartModal(sectionName,(settings=>{_ajax.default.call([{methodname:"block_sharing_cart_backup_section_into_sharing_cart",args:{section_id:sectionId,settings:settings},done:async data=>{await this.renderItem(data)},fail:data=>{_notification.default.exception(data)}}])}));await modal.show()}async addCourseModuleBackupToSharingCart(courseModuleId){const courseModuleName=_classPrivateFieldGet(this,_course).getCourseModuleName(courseModuleId),modal=await this.createBackupItemToSharingCartModal(courseModuleName,(settings=>{_ajax.default.call([{methodname:"block_sharing_cart_backup_course_module_into_sharing_cart",args:{course_module_id:courseModuleId,settings:settings},done:async data=>{await this.renderItem(data)},fail:data=>{_notification.default.exception(data)}}])}));await modal.show()}async renderItem(item){var _classPrivateFieldGet5,_item$task_id;const existingItemIndex=_classPrivateFieldGet(this,_items).findIndex((i=>i.getItemId()===item.id)),existingItem=null!==(_classPrivateFieldGet5=_classPrivateFieldGet(this,_items)[existingItemIndex])&&void 0!==_classPrivateFieldGet5&&_classPrivateFieldGet5,getOldElement=()=>_classPrivateFieldGet(this,_element).querySelector('.sharing_cart_items .sharing_cart_item[data-itemid="'+item.id+'"]'),oldElement=getOldElement();if(existingItem&&oldElement){const element=await _classPrivateFieldGet(this,_baseFactory).moodle().template().createElementFromFragment("block_sharing_cart","item",1,{item_id:item.id});if(getOldElement()!==oldElement)return;_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items").replaceChild(element,oldElement),_classPrivateFieldGet(this,_items)[existingItemIndex]=_classPrivateFieldGet(this,_baseFactory).block().item().element(this,element),await this.setupItem(element);for(const subItem of element.querySelectorAll(".sharing_cart_item"))await this.setupItem(subItem);return}const element=await _classPrivateFieldGet(this,_baseFactory).moodle().template().createElementFromTemplate("block_sharing_cart/block/item",{id:item.id,name:item.name,type:item.type,status:0,old_instance_id:item.old_instance_id,status_awaiting:!0,has_run_now:!0,task_id:null!==(_item$task_id=item.task_id)&&void 0!==_item$task_id?_item$task_id:null,status_finished:!1,status_failed:!1,is_module:"section"!==item.type,is_section:"section"===item.type,is_root:!0});_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items").prepend(element),await this.setupItem(element)}importItem(item,sectionId,modal){_classPrivateFieldGet(this,_course).clearClipboard();const courseModuleIds=[];if(modal.querySelectorAll('input[type="checkbox"][data-type="coursemodule"]:checked').forEach((checkbox=>{courseModuleIds.push(checkbox.dataset.id)})),item.isSection()&&0===courseModuleIds.length)return modal.querySelectorAll(".form-check-input").forEach((async item=>{item.setCustomValidity(await(0,_str.get_string)("atleast_one_course_module_must_be_included","block_sharing_cart")),item.reportValidity()})),!1;item.isModule()&&courseModuleIds.push(item.getItemOldInstanceId()),_ajax.default.call([{methodname:"block_sharing_cart_restore_item_from_sharing_cart_into_section",args:{item_id:item.getItemId(),section_id:sectionId,course_modules_to_include:courseModuleIds},done:async success=>{success&&await _classPrivateFieldGet(this,_queue).loadQueue(!0)},fail:data=>{_notification.default.exception(data)}}])}async confirmImportBackupFromSharingCart(item,sectionId,e){e.preventDefault(),e.stopPropagation();const strings=await(0,_str.get_strings)([{key:"copy_item",component:"block_sharing_cart"},{key:"into_section",component:"block_sharing_cart"},{key:"import",component:"core"},{key:"cancel",component:"core"}]),sectionName=_classPrivateFieldGet(this,_course).getSectionName(sectionId),{html:html,js:js}=await _classPrivateFieldGet(this,_baseFactory).moodle().template().renderFragment("block_sharing_cart","item_restore_form",1,{item_id:item.getItemId()}),modal=await _modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:strings[0]+': "'+item.getItemName().slice(0,50).trim()+'" '+strings[1]+': "'+sectionName.slice(0,50).trim()+'"',body:html,buttons:{save:strings[2],cancel:strings[3]},removeOnClose:!0});modal.getRoot().on(_modal_events.default.shown,(()=>_classPrivateFieldGet(this,_baseFactory).moodle().template().runTemplateJS(js))),modal.getRoot().on(_modal_events.default.save,this.importItem.bind(this,item,sectionId,modal.getRoot()[0])),await modal.show()}async confirmDeleteItems(itemIds){const strings=await(0,_str.get_strings)([{key:"delete_items",component:"block_sharing_cart"},{key:"confirm_delete_items",component:"block_sharing_cart"},{key:"delete",component:"core"},{key:"cancel",component:"core"}]),modal=await _modal_factory.default.create({type:_modal_factory.default.types.DELETE_CANCEL,title:strings[0],body:strings[1],buttons:{delete:strings[2],cancel:strings[3]},removeOnClose:!0});modal.getRoot().on(_modal_events.default.delete,this.deleteItems.bind(this,itemIds)),await modal.show()}},_exports.default})); //# sourceMappingURL=element.min.js.map \ No newline at end of file diff --git a/amd/build/app/block/element.min.js.map b/amd/build/app/block/element.min.js.map index 9e1bb5e..3cc3d55 100644 --- a/amd/build/app/block/element.min.js.map +++ b/amd/build/app/block/element.min.js.map @@ -1 +1 @@ -{"version":3,"file":"element.min.js","sources":["../../../src/app/block/element.js"],"sourcesContent":["import Sortable from '../../lib/sortablejs';\nimport ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport {get_string, get_strings} from \"core/str\";\nimport Ajax from \"core/ajax\";\nimport Notification from \"core/notification\";\n\nexport default class BlockElement {\n /**\n * @type {BaseFactory}\n */\n #baseFactory;\n\n /**\n * @type {HTMLElement}\n */\n #element;\n\n /**\n * @type {CourseElement}\n */\n #course;\n\n /**\n * @type {QueueElement}\n */\n #queue;\n\n /**\n * @type {ItemElement[]}\n */\n #items = [];\n\n /**\n * @type {Sortable|NULL}\n */\n #sortable = null;\n\n /**\n * @type {ItemElement|NULL}\n */\n #clipboardItem = null;\n\n /**\n * @type {Boolean}\n */\n #canBackupUserdata = false;\n\n /**\n * @type {Boolean}\n */\n #canAnonymizeUserdata = false;\n\n /**\n * @type {Boolean}\n */\n #showSharingCartBasket = false;\n\n /**\n * @type {Number|null}\n */\n #draggedCourseModuleId = null;\n\n /**\n * @type {Number|null}\n */\n #draggedSectionId = null;\n\n /**\n * @param {BaseFactory} baseFactory\n * @param {HTMLElement} element\n * @param {Boolean} canBackupUserdata\n * @param {Boolean} canAnonymizeUserdata\n * @param {Boolean} showSharingCartBasket\n */\n constructor(baseFactory, element, canBackupUserdata, canAnonymizeUserdata, showSharingCartBasket) {\n this.#baseFactory = baseFactory;\n this.#element = element;\n this.#canBackupUserdata = canBackupUserdata;\n this.#canAnonymizeUserdata = canAnonymizeUserdata;\n this.#showSharingCartBasket = showSharingCartBasket;\n }\n\n /**\n * @return {{course: CourseElement, block: BlockElement, queue: QueueElement}}\n */\n addEventListeners() {\n this.setupCourse();\n this.setupQueue();\n this.setupItems();\n this.setupDragAndDrop();\n this.setupBulkDelete();\n\n return {course: this.#course, queue: this.#queue, block: this};\n }\n\n setupCourse() {\n const course = document.querySelector('.course-content');\n\n this.#course = this.#baseFactory.block().course().element(this, course);\n }\n\n setupQueue() {\n const queue = document.querySelector('.sharing_cart_queue');\n\n this.#queue = this.#baseFactory.block().queue().element(this, queue);\n }\n\n setupItems() {\n const items = this.#element.querySelectorAll('.sharing_cart_item');\n\n items.forEach((element) => {\n this.setupItem(element);\n });\n\n this.#sortable = new Sortable(this.#element.querySelector('.sharing_cart_items'), {\n dataIdAttr: 'data-itemid',\n onUpdate: () => {\n Ajax.call([{\n methodname: 'block_sharing_cart_reorder_sharing_cart_items',\n args: {\n item_ids: this.#sortable.toArray(),\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n });\n }\n\n setupDragAndDrop() {\n const dropZone = this.#element;\n\n dropZone.addEventListener('dragover', (e) => {\n if (!this.#draggedSectionId && !this.#draggedCourseModuleId) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n });\n dropZone.addEventListener('dragleave', (e) => {\n if (!this.#draggedSectionId && !this.#draggedCourseModuleId) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n });\n dropZone.addEventListener('drop', async (e) => {\n if (!this.#draggedSectionId && !this.#draggedCourseModuleId) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n\n if (this.#draggedSectionId) {\n await this.addSectionBackupToSharingCart(this.#draggedSectionId);\n } else if (this.#draggedCourseModuleId) {\n await this.addCourseModuleBackupToSharingCart(this.#draggedCourseModuleId);\n }\n });\n }\n\n setupBulkDelete() {\n const enableBulkDeleteButton = this.#element.querySelector('#block_sharing_cart_bulk_delete');\n const disableBulkDeleteButton = this.#element.querySelector('#block_sharing_cart_cancel_bulk_delete');\n const bulkDeleteButton = this.#element.querySelector('#block_sharing_cart_bulk_delete_confirm');\n\n const checkboxSelector = '.sharing_cart_item input[data-action=\"bulk_select\"][type=\"checkbox\"]';\n\n enableBulkDeleteButton.addEventListener('click', () => {\n enableBulkDeleteButton.classList.add('d-none');\n disableBulkDeleteButton.classList.remove('d-none');\n bulkDeleteButton.classList.remove('d-none');\n\n this.#element.querySelectorAll(checkboxSelector).forEach((checkbox) => {\n checkbox.classList.remove('d-none');\n checkbox.checked = false;\n });\n });\n\n disableBulkDeleteButton.addEventListener('click', () => {\n disableBulkDeleteButton.classList.add('d-none');\n bulkDeleteButton.classList.add('d-none');\n bulkDeleteButton.disabled = true;\n enableBulkDeleteButton.classList.remove('d-none');\n\n this.#element.querySelectorAll(checkboxSelector).forEach((checkbox) => {\n checkbox.classList.add('d-none');\n checkbox.checked = false;\n });\n });\n\n bulkDeleteButton.addEventListener('click', async () => {\n if (bulkDeleteButton.disabled) {\n return;\n }\n\n const itemIds = [];\n this.#element.querySelectorAll(checkboxSelector + ':checked').forEach((checkbox) => {\n itemIds.push(checkbox.value);\n });\n\n await this.confirmDeleteItems(itemIds);\n });\n }\n\n /**\n * @param {HTMLElement} element\n */\n setupItem(element) {\n const itemElement = this.#baseFactory.block().item().element(this, element);\n\n this.#element.querySelector('.no-items')?.remove();\n\n this.#items.push(\n itemElement\n );\n }\n\n /**\n * @param {ItemElement} item\n */\n async setClipboard(item) {\n this.#clipboardItem = item;\n\n await this.#course.setClipboard(item);\n }\n\n clearClipboard() {\n this.#clipboardItem = null;\n }\n\n /**\n * @param {Number|null} id\n */\n setDraggedSectionId(id) {\n this.#draggedSectionId = id;\n }\n\n /**\n * @param {Number|null} id\n */\n setDraggedCourseModuleId(id) {\n this.#draggedCourseModuleId = id;\n }\n\n /**\n * @param {ItemElement} item\n */\n async removeItemElement(item) {\n const childItems = item.getItemChildrenRecursively();\n childItems.forEach((childItem) => {\n const index = this.#items.findIndex((i) => i.getItemId() === Number.parseInt(childItem.dataset.itemid));\n if (index === -1) {\n return;\n }\n\n if (this.#items[index].getItemId() === this.#clipboardItem?.getItemId()) {\n this.#course.clearClipboard();\n }\n\n this.#items.splice(index, 1);\n childItem.remove();\n });\n\n const index = this.#items.findIndex((i) => i.getItemId() === item.getItemId());\n if (this.#items[index].getItemId() === this.#clipboardItem?.getItemId()) {\n this.#course.clearClipboard();\n }\n\n this.#items.splice(index, 1);\n item.remove();\n\n if (this.#items.length === 0) {\n this.#element.querySelector('.sharing_cart_items')\n .innerHTML = await get_string('no_items', 'block_sharing_cart');\n }\n }\n\n /**\n * @param {ItemElement} item\n */\n deleteItem(item) {\n Ajax.call([{\n methodname: 'block_sharing_cart_delete_item_from_sharing_cart',\n args: {\n item_id: item.getItemId(),\n },\n done: async (deleted) => {\n if (deleted) {\n await this.removeItemElement(item);\n } else {\n await Notification.alert('Failed to delete item');\n }\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n /**\n * @param {Array} itemIds\n */\n deleteItems(itemIds) {\n itemIds = itemIds.map((id) => Number.parseInt(id));\n\n Ajax.call([{\n methodname: 'block_sharing_cart_delete_items_from_sharing_cart',\n args: {\n item_ids: itemIds,\n },\n done: async (deletedItemIds) => {\n const items = this.#items.filter((i) => itemIds.includes(i.getItemId()));\n for (const item of items) {\n const deleted = deletedItemIds.includes(item.getItemId());\n if (!deleted) {\n Notification.alert('Failed to delete item: \"' + item.getItemName() + '\"');\n continue;\n }\n\n await this.removeItemElement(item);\n }\n\n document.getElementById('block_sharing_cart_bulk_delete_confirm').disabled = true;\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n getElement() {\n return this.#element;\n }\n\n /**\n * @param {String} itemName\n * @param {CallableFunction} onSave\n * @return {Promise}\n */\n async createBackupItemToSharingCartModal(itemName, onSave) {\n const strings = await get_strings([\n {\n key: 'backup_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'into_sharing_cart',\n component: 'block_sharing_cart',\n },\n {\n key: 'backup',\n component: 'block_sharing_cart',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const {html, js} = await this.#baseFactory.moodle().template().renderTemplate(\n 'block_sharing_cart/modal/backup_to_sharing_cart_modal_body',\n {\n show_user_data_backup: this.#canBackupUserdata,\n show_anonymize_user_data: this.#canBackupUserdata && this.#canAnonymizeUserdata,\n }\n );\n\n /**\n * @type {Modal}\n */\n const modal = await ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: strings[0] + ': \"' + itemName.slice(0, 50).trim() + '\" ' + strings[1],\n body: html,\n buttons: {\n save: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n modal.getRoot().on(ModalEvents.shown, () => this.#baseFactory.moodle().template().runTemplateJS(js));\n modal.getRoot().on(ModalEvents.save, () => {\n const modalUserdataCheckbox = document.getElementById('modal-userdata-checkbox');\n const modalAnonymizeCheckbox = document.getElementById('modal-anonymize-checkbox');\n\n onSave({\n users: modalUserdataCheckbox?.checked ?? false,\n anonymize: modalAnonymizeCheckbox?.checked ?? false\n });\n });\n\n return modal;\n }\n\n /**\n * @param {Number} sectionId\n */\n async addSectionBackupToSharingCart(sectionId) {\n const sectionName = this.#course.getSectionName(sectionId);\n\n const cms = this.#course.getSectionCourseModules(sectionId);\n\n if (cms.length === 0) {\n const strings = await get_strings([\n {\n key: 'no_course_modules_in_section',\n component: 'block_sharing_cart',\n },\n {\n key: 'no_course_modules_in_section_description',\n component: 'block_sharing_cart',\n },\n ]);\n\n await Notification.alert(strings[0], strings[1]);\n\n return;\n }\n\n const modal = await this.createBackupItemToSharingCartModal(sectionName, (settings) => {\n Ajax.call([{\n methodname: 'block_sharing_cart_backup_section_into_sharing_cart',\n args: {\n section_id: sectionId,\n settings: settings\n },\n done: async (data) => {\n await this.renderItem(data);\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n });\n\n await modal.show();\n }\n\n /**\n * @param {Number} courseModuleId\n */\n async addCourseModuleBackupToSharingCart(courseModuleId) {\n const courseModuleName = this.#course.getCourseModuleName(courseModuleId);\n\n const modal = await this.createBackupItemToSharingCartModal(courseModuleName, (settings) => {\n Ajax.call([{\n methodname: 'block_sharing_cart_backup_course_module_into_sharing_cart',\n args: {\n course_module_id: courseModuleId,\n settings: settings\n },\n done: async (data) => {\n await this.renderItem(data);\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n });\n await modal.show();\n }\n\n /**\n * @param {Object} item\n */\n async renderItem(item) {\n const existingItemIndex = this.#items.findIndex((i) => i.getItemId() === item.id);\n const existingItem = this.#items[existingItemIndex] ?? false;\n const oldElement = this.#element.querySelector('.sharing_cart_items .sharing_cart_item[data-itemid=\"' + item.id + '\"]');\n if (existingItem && oldElement) {\n const element = await this.#baseFactory.moodle().template().createElementFromFragment(\n 'block_sharing_cart',\n 'item',\n 1,\n {\n item_id: item.id,\n }\n );\n\n this.#element.querySelector('.sharing_cart_items').replaceChild(element, oldElement);\n this.#items[existingItemIndex] = this.#baseFactory.block().item().element(this, element);\n\n element.querySelectorAll('.sharing_cart_item').forEach((subItem) => {\n this.setupItem(subItem);\n });\n\n return;\n }\n\n const element = await this.#baseFactory.moodle().template().createElementFromTemplate(\n 'block_sharing_cart/block/item',\n {\n id: item.id,\n name: item.name,\n type: item.type,\n status: 0,\n old_instance_id: item.old_instance_id,\n status_awaiting: true,\n has_run_now: true,\n task_id: item.task_id ?? null,\n status_finished: false,\n status_failed: false,\n is_module: item.type !== 'section',\n is_section: item.type === 'section',\n is_root: true,\n }\n );\n this.#element.querySelector('.sharing_cart_items').prepend(element);\n\n this.setupItem(element);\n }\n\n /**\n * @param {ItemElement} item\n * @param {Number} sectionId\n * @param {HTMLElement} modal\n */\n importItem(item, sectionId, modal) {\n this.#course.clearClipboard();\n\n const courseModuleIds = [];\n modal.querySelectorAll('input[type=\"checkbox\"][data-type=\"coursemodule\"]:checked').forEach((checkbox) => {\n courseModuleIds.push(checkbox.dataset.id);\n });\n\n if (item.isSection() && courseModuleIds.length === 0) {\n modal.querySelectorAll('.form-check-input').forEach(async (item) => {\n item.setCustomValidity(\n await get_string('atleast_one_course_module_must_be_included', 'block_sharing_cart')\n );\n item.reportValidity();\n });\n return false;\n }\n\n if (item.isModule()) {\n courseModuleIds.push(item.getItemOldInstanceId());\n }\n\n Ajax.call([{\n methodname: 'block_sharing_cart_restore_item_from_sharing_cart_into_section',\n args: {\n item_id: item.getItemId(),\n section_id: sectionId,\n course_modules_to_include: courseModuleIds,\n },\n done: async (success) => {\n if (success) {\n await this.#queue.loadQueue(true);\n }\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n /**\n * @param {ItemElement} item\n * @param {Number} sectionId\n * @param {Event} e\n */\n async confirmImportBackupFromSharingCart(item, sectionId, e) {\n e.preventDefault();\n e.stopPropagation();\n\n const strings = await get_strings([\n {\n key: 'copy_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'into_section',\n component: 'block_sharing_cart',\n },\n {\n key: 'import',\n component: 'core',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const sectionName = this.#course.getSectionName(sectionId);\n\n const {html, js} = await this.#baseFactory.moodle().template().renderFragment(\n 'block_sharing_cart',\n 'item_restore_form',\n 1,\n {\n item_id: item.getItemId()\n }\n );\n\n const modal = await ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: strings[0] + ': ' +\n '\"' + item.getItemName().slice(0, 50).trim() + '\"' +\n ' ' + strings[1] + ': ' +\n '\"' + sectionName.slice(0, 50).trim() + '\"',\n body: html,\n buttons: {\n save: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n modal.getRoot().on(ModalEvents.shown, () => this.#baseFactory.moodle().template().runTemplateJS(js));\n modal.getRoot().on(ModalEvents.save, this.importItem.bind(this, item, sectionId, modal.getRoot()[0]));\n await modal.show();\n }\n\n /**\n * @param {Array} itemIds\n */\n async confirmDeleteItems(itemIds) {\n const strings = await get_strings([\n {\n key: 'delete_items',\n component: 'block_sharing_cart',\n },\n {\n key: 'confirm_delete_items',\n component: 'block_sharing_cart',\n },\n {\n key: 'delete',\n component: 'core',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const modal = await ModalFactory.create({\n type: ModalFactory.types.DELETE_CANCEL,\n title: strings[0],\n body: strings[1],\n buttons: {\n delete: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n\n modal.getRoot().on(ModalEvents.delete, this.deleteItems.bind(this, itemIds));\n await modal.show();\n }\n}\n"],"names":["constructor","baseFactory","element","canBackupUserdata","canAnonymizeUserdata","showSharingCartBasket","addEventListeners","setupCourse","setupQueue","setupItems","setupDragAndDrop","setupBulkDelete","course","this","queue","block","document","querySelector","_classPrivateFieldGet","querySelectorAll","forEach","setupItem","Sortable","dataIdAttr","onUpdate","call","methodname","args","item_ids","toArray","fail","data","exception","dropZone","addEventListener","e","preventDefault","stopPropagation","async","addSectionBackupToSharingCart","addCourseModuleBackupToSharingCart","enableBulkDeleteButton","disableBulkDeleteButton","bulkDeleteButton","checkboxSelector","classList","add","remove","checkbox","checked","disabled","itemIds","push","value","confirmDeleteItems","itemElement","item","setClipboard","clearClipboard","setDraggedSectionId","id","setDraggedCourseModuleId","getItemChildrenRecursively","childItem","index","findIndex","i","getItemId","Number","parseInt","dataset","itemid","_classPrivateFieldGet3","splice","_classPrivateFieldGet4","length","innerHTML","deleteItem","item_id","done","deleted","removeItemElement","Notification","alert","deleteItems","map","items","filter","includes","deletedItemIds","getItemName","getElementById","getElement","itemName","onSave","strings","key","component","html","js","moodle","template","renderTemplate","show_user_data_backup","show_anonymize_user_data","modal","ModalFactory","create","type","types","SAVE_CANCEL","title","slice","trim","body","buttons","save","cancel","removeOnClose","getRoot","on","ModalEvents","shown","runTemplateJS","modalUserdataCheckbox","modalAnonymizeCheckbox","users","anonymize","sectionId","sectionName","getSectionName","getSectionCourseModules","createBackupItemToSharingCartModal","settings","section_id","renderItem","show","courseModuleId","courseModuleName","getCourseModuleName","course_module_id","existingItemIndex","existingItem","oldElement","createElementFromFragment","replaceChild","subItem","createElementFromTemplate","name","status","old_instance_id","status_awaiting","has_run_now","task_id","status_finished","status_failed","is_module","is_section","is_root","prepend","importItem","courseModuleIds","isSection","setCustomValidity","reportValidity","isModule","getItemOldInstanceId","course_modules_to_include","success","loadQueue","renderFragment","bind","DELETE_CANCEL","delete"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"element.min.js","sources":["../../../src/app/block/element.js"],"sourcesContent":["import Sortable from '../../lib/sortablejs';\nimport ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport {get_string, get_strings} from \"core/str\";\nimport Ajax from \"core/ajax\";\nimport Notification from \"core/notification\";\n\nexport default class BlockElement {\n /**\n * @type {BaseFactory}\n */\n #baseFactory;\n\n /**\n * @type {HTMLElement}\n */\n #element;\n\n /**\n * @type {CourseElement}\n */\n #course;\n\n /**\n * @type {QueueElement}\n */\n #queue;\n\n /**\n * @type {ItemElement[]}\n */\n #items = [];\n\n /**\n * @type {Sortable|NULL}\n */\n #sortable = null;\n\n /**\n * @type {ItemElement|NULL}\n */\n #clipboardItem = null;\n\n /**\n * @type {Boolean}\n */\n #canBackupUserdata = false;\n\n /**\n * @type {Boolean}\n */\n #canAnonymizeUserdata = false;\n\n /**\n * @type {Boolean}\n */\n #showSharingCartBasket = false;\n\n /**\n * @type {Number|null}\n */\n #draggedCourseModuleId = null;\n\n /**\n * @type {Number|null}\n */\n #draggedSectionId = null;\n\n /**\n * @type {boolean}\n */\n #bulkDeleteEnabled = false;\n\n /**\n * @param {BaseFactory} baseFactory\n * @param {HTMLElement} element\n * @param {Boolean} canBackupUserdata\n * @param {Boolean} canAnonymizeUserdata\n * @param {Boolean} showSharingCartBasket\n */\n constructor(baseFactory, element, canBackupUserdata, canAnonymizeUserdata, showSharingCartBasket) {\n this.#baseFactory = baseFactory;\n this.#element = element;\n this.#canBackupUserdata = canBackupUserdata;\n this.#canAnonymizeUserdata = canAnonymizeUserdata;\n this.#showSharingCartBasket = showSharingCartBasket;\n }\n\n /**\n * @return {{course: CourseElement, block: BlockElement, queue: QueueElement}}\n */\n addEventListeners() {\n this.setupCourse();\n this.setupQueue();\n this.setupItems();\n this.setupDragAndDrop();\n this.setupBulkDelete();\n\n return {course: this.#course, queue: this.#queue, block: this};\n }\n\n setupCourse() {\n const course = document.querySelector('.course-content');\n\n this.#course = this.#baseFactory.block().course().element(this, course);\n }\n\n setupQueue() {\n const queue = document.querySelector('.sharing_cart_queue');\n\n this.#queue = this.#baseFactory.block().queue().element(this, queue);\n }\n\n async setupItems() {\n const items = this.#element.querySelectorAll('.sharing_cart_item');\n\n for (const element of items) {\n await this.setupItem(element);\n }\n\n this.#sortable = new Sortable(this.#element.querySelector('.sharing_cart_items'), {\n dataIdAttr: 'data-itemid',\n onUpdate: () => {\n Ajax.call([{\n methodname: 'block_sharing_cart_reorder_sharing_cart_items',\n args: {\n item_ids: this.#sortable.toArray(),\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n });\n }\n\n setupDragAndDrop() {\n const dropZone = this.#element;\n\n dropZone.addEventListener('dragover', (e) => {\n if (!this.#draggedSectionId && !this.#draggedCourseModuleId) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n });\n dropZone.addEventListener('dragleave', (e) => {\n if (!this.#draggedSectionId && !this.#draggedCourseModuleId) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n });\n dropZone.addEventListener('drop', async (e) => {\n if (!this.#draggedSectionId && !this.#draggedCourseModuleId) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n\n if (this.#draggedSectionId) {\n await this.addSectionBackupToSharingCart(this.#draggedSectionId);\n } else if (this.#draggedCourseModuleId) {\n await this.addCourseModuleBackupToSharingCart(this.#draggedCourseModuleId);\n }\n });\n }\n\n setupBulkDelete() {\n const enableBulkDeleteButton = this.#element.querySelector('#block_sharing_cart_bulk_delete');\n const disableBulkDeleteButton = this.#element.querySelector('#block_sharing_cart_cancel_bulk_delete');\n const bulkDeleteButton = this.#element.querySelector('#block_sharing_cart_bulk_delete_confirm');\n\n const selectAllContainer = this.#element.querySelector('#select_all_container');\n const selectAllCheckbox = this.#element.querySelector('#select_all_box');\n\n selectAllCheckbox.addEventListener('click', async () => {\n const itemCheckboxes = this.getItemCheckboxes();\n const allSelected = Array.from(itemCheckboxes).every(checkbox => checkbox.checked);\n itemCheckboxes.forEach(checkbox => {\n checkbox.checked = !allSelected;\n });\n itemCheckboxes.forEach(checkbox => checkbox.addEventListener('change', async () => {\n this.updateSelectAllState();\n }));\n\n this.updateSelectAllState();\n this.updateBulkDeleteButtonState();\n });\n\n enableBulkDeleteButton.addEventListener('click', () => {\n if (this.#items.length === 0) {\n return;\n }\n\n this.#bulkDeleteEnabled = true;\n\n enableBulkDeleteButton.classList.add('d-none');\n disableBulkDeleteButton.classList.remove('d-none');\n\n selectAllContainer.classList.remove('d-none');\n bulkDeleteButton.classList.remove('d-none');\n\n this.getItemCheckboxes().forEach((checkbox) => {\n checkbox.classList.remove('d-none');\n checkbox.checked = false;\n });\n });\n\n disableBulkDeleteButton.addEventListener('click', () => {\n disableBulkDeleteButton.classList.add('d-none');\n bulkDeleteButton.classList.add('d-none');\n bulkDeleteButton.disabled = true;\n enableBulkDeleteButton.classList.remove('d-none');\n selectAllContainer.classList.add('d-none');\n\n this.getItemCheckboxes().forEach((checkbox) => {\n checkbox.classList.add('d-none');\n checkbox.checked = false;\n });\n });\n\n bulkDeleteButton.addEventListener('click', async () => {\n if (bulkDeleteButton.disabled) {\n return;\n }\n\n const itemIds = [];\n this.getItemCheckboxes().forEach((checkbox) => {\n if (!checkbox.checked) {\n return;\n }\n\n itemIds.push(checkbox.value);\n });\n\n await this.confirmDeleteItems(itemIds);\n });\n }\n\n /**\n * @param {HTMLElement} element\n */\n async setupItem(element) {\n const itemElement = this.#baseFactory.block().item().element(this, element);\n\n if (itemElement.getStatus() !== '0' && this.isBulkDeleteEnabled()) {\n const checkbox = element.querySelector('input[data-action=\"bulk_select\"][type=\"checkbox\"]');\n checkbox?.classList?.remove('d-none');\n }\n\n this.#element.querySelector('.no-items')?.remove();\n\n this.#items.push(itemElement);\n\n this.updateBulkDeleteButtonState();\n this.updateSelectAllState();\n }\n\n getItemCheckboxes() {\n const checkboxSelector = '.sharing_cart_item:not([data-status=\"0\"]) input[data-action=\"bulk_select\"][type=\"checkbox\"]';\n return this.#element.querySelectorAll(checkboxSelector);\n }\n\n updateBulkDeleteButtonState() {\n const bulkDeleteButton = this.#element.querySelector('#block_sharing_cart_bulk_delete_confirm');\n bulkDeleteButton.disabled = !Array.from(this.getItemCheckboxes()).some(checkbox => checkbox.checked);\n }\n\n updateSelectAllState() {\n const selectAllCheckbox = this.#element.querySelector('#select_all_box');\n const selectAllLabel = this.#element.querySelector('#select_all_label');\n\n const itemCheckboxes = this.getItemCheckboxes();\n const allSelected = Array.from(itemCheckboxes).every(checkbox => checkbox.checked);\n const someSelected = Array.from(itemCheckboxes).some(checkbox => checkbox.checked);\n\n const strPromise = allSelected ?\n get_string('deselect_all', 'block_sharing_cart') :\n get_string('select_all', 'block_sharing_cart');\n strPromise.then((str) => {\n selectAllLabel.textContent = str;\n });\n\n selectAllCheckbox.checked = allSelected;\n selectAllCheckbox.indeterminate = !allSelected && someSelected;\n }\n\n isBulkDeleteEnabled() {\n return this.#bulkDeleteEnabled;\n }\n\n /**\n * @param {ItemElement} item\n */\n async setClipboard(item) {\n this.#clipboardItem = item;\n\n await this.#course.setClipboard(item);\n }\n\n clearClipboard() {\n this.#clipboardItem = null;\n }\n\n /**\n * @param {Number|null} id\n */\n setDraggedSectionId(id) {\n this.#draggedSectionId = id;\n }\n\n /**\n * @param {Number|null} id\n */\n setDraggedCourseModuleId(id) {\n this.#draggedCourseModuleId = id;\n }\n\n /**\n * @param {ItemElement} item\n */\n async removeItemElement(item) {\n const childItems = item.getItemChildrenRecursively();\n childItems.forEach((childItem) => {\n const index = this.#items.findIndex((i) => i.getItemId() === Number.parseInt(childItem.dataset.itemid));\n if (index === -1) {\n return;\n }\n\n if (this.#items[index].getItemId() === this.#clipboardItem?.getItemId()) {\n this.#course.clearClipboard();\n }\n\n this.#items.splice(index, 1);\n childItem.remove();\n });\n\n const index = this.#items.findIndex((i) => i.getItemId() === item.getItemId());\n if (this.#items[index].getItemId() === this.#clipboardItem?.getItemId()) {\n this.#course.clearClipboard();\n }\n\n this.#items.splice(index, 1);\n item.remove();\n\n if (this.#items.length === 0) {\n this.#element.querySelector('.sharing_cart_items')\n .innerHTML = await get_string('no_items', 'block_sharing_cart');\n }\n }\n\n /**\n * @param {ItemElement} item\n */\n deleteItem(item) {\n Ajax.call([{\n methodname: 'block_sharing_cart_delete_item_from_sharing_cart',\n args: {\n item_id: item.getItemId(),\n },\n done: async (deleted) => {\n if (deleted) {\n await this.removeItemElement(item);\n } else {\n await Notification.alert('Failed to delete item');\n }\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n /**\n * @param {Array} itemIds\n */\n deleteItems(itemIds) {\n itemIds = itemIds.map((id) => Number.parseInt(id));\n\n Ajax.call([{\n methodname: 'block_sharing_cart_delete_items_from_sharing_cart',\n args: {\n item_ids: itemIds,\n },\n done: async (deletedItemIds) => {\n const items = this.#items.filter((i) => itemIds.includes(i.getItemId()));\n for (const item of items) {\n const deleted = deletedItemIds.includes(item.getItemId());\n if (!deleted) {\n Notification.alert('Failed to delete item: \"' + item.getItemName() + '\"');\n continue;\n }\n\n await this.removeItemElement(item);\n }\n this.updateSelectAllState();\n\n document.getElementById('block_sharing_cart_bulk_delete_confirm').disabled = true;\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n getElement() {\n return this.#element;\n }\n\n /**\n * @param {String} itemName\n * @param {CallableFunction} onSave\n * @return {Promise}\n */\n async createBackupItemToSharingCartModal(itemName, onSave) {\n const strings = await get_strings([\n {\n key: 'backup_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'into_sharing_cart',\n component: 'block_sharing_cart',\n },\n {\n key: 'backup',\n component: 'block_sharing_cart',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const {html, js} = await this.#baseFactory.moodle().template().renderTemplate(\n 'block_sharing_cart/modal/backup_to_sharing_cart_modal_body',\n {\n show_user_data_backup: this.#canBackupUserdata,\n show_anonymize_user_data: this.#canBackupUserdata && this.#canAnonymizeUserdata,\n }\n );\n\n /**\n * @type {Modal}\n */\n const modal = await ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: strings[0] + ': \"' + itemName.slice(0, 50).trim() + '\" ' + strings[1],\n body: html,\n buttons: {\n save: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n modal.getRoot().on(ModalEvents.shown, () => this.#baseFactory.moodle().template().runTemplateJS(js));\n modal.getRoot().on(ModalEvents.save, () => {\n const modalUserdataCheckbox = document.getElementById('modal-userdata-checkbox');\n const modalAnonymizeCheckbox = document.getElementById('modal-anonymize-checkbox');\n\n onSave({\n users: modalUserdataCheckbox?.checked ?? false,\n anonymize: modalAnonymizeCheckbox?.checked ?? false\n });\n });\n\n return modal;\n }\n\n /**\n * @param {Number} sectionId\n */\n async addSectionBackupToSharingCart(sectionId) {\n const sectionName = this.#course.getSectionName(sectionId);\n\n const cms = this.#course.getSectionCourseModules(sectionId);\n\n if (cms.length === 0) {\n const strings = await get_strings([\n {\n key: 'no_course_modules_in_section',\n component: 'block_sharing_cart',\n },\n {\n key: 'no_course_modules_in_section_description',\n component: 'block_sharing_cart',\n },\n ]);\n\n await Notification.alert(strings[0], strings[1]);\n\n return;\n }\n\n const modal = await this.createBackupItemToSharingCartModal(sectionName, (settings) => {\n Ajax.call([{\n methodname: 'block_sharing_cart_backup_section_into_sharing_cart',\n args: {\n section_id: sectionId,\n settings: settings\n },\n done: async (data) => {\n await this.renderItem(data);\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n });\n\n await modal.show();\n }\n\n /**\n * @param {Number} courseModuleId\n */\n async addCourseModuleBackupToSharingCart(courseModuleId) {\n const courseModuleName = this.#course.getCourseModuleName(courseModuleId);\n\n const modal = await this.createBackupItemToSharingCartModal(courseModuleName, (settings) => {\n Ajax.call([{\n methodname: 'block_sharing_cart_backup_course_module_into_sharing_cart',\n args: {\n course_module_id: courseModuleId,\n settings: settings\n },\n done: async (data) => {\n await this.renderItem(data);\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n });\n await modal.show();\n }\n\n /**\n * @param {Object} item\n */\n async renderItem(item) {\n const existingItemIndex = this.#items.findIndex((i) => i.getItemId() === item.id);\n const existingItem = this.#items[existingItemIndex] ?? false;\n const getOldElement = () => {\n return this.#element.querySelector('.sharing_cart_items .sharing_cart_item[data-itemid=\"' + item.id + '\"]');\n };\n const oldElement = getOldElement();\n if (existingItem && oldElement) {\n const element = await this.#baseFactory.moodle().template().createElementFromFragment(\n 'block_sharing_cart',\n 'item',\n 1,\n {\n item_id: item.id,\n }\n );\n\n // Early exit if the element has been removed from the DOM in between rendering and checking earlier.\n if (getOldElement() !== oldElement) {\n return;\n }\n\n this.#element.querySelector('.sharing_cart_items').replaceChild(element, oldElement);\n this.#items[existingItemIndex] = this.#baseFactory.block().item().element(this, element);\n\n await this.setupItem(element); // test\n for (const subItem of element.querySelectorAll('.sharing_cart_item')) {\n await this.setupItem(subItem);\n }\n\n return;\n }\n\n const element = await this.#baseFactory.moodle().template().createElementFromTemplate(\n 'block_sharing_cart/block/item',\n {\n id: item.id,\n name: item.name,\n type: item.type,\n status: 0,\n old_instance_id: item.old_instance_id,\n status_awaiting: true,\n has_run_now: true,\n task_id: item.task_id ?? null,\n status_finished: false,\n status_failed: false,\n is_module: item.type !== 'section',\n is_section: item.type === 'section',\n is_root: true,\n }\n );\n this.#element.querySelector('.sharing_cart_items').prepend(element);\n\n await this.setupItem(element);\n }\n\n /**\n * @param {ItemElement} item\n * @param {Number} sectionId\n * @param {HTMLElement} modal\n */\n importItem(item, sectionId, modal) {\n this.#course.clearClipboard();\n\n const courseModuleIds = [];\n modal.querySelectorAll('input[type=\"checkbox\"][data-type=\"coursemodule\"]:checked').forEach((checkbox) => {\n courseModuleIds.push(checkbox.dataset.id);\n });\n\n if (item.isSection() && courseModuleIds.length === 0) {\n modal.querySelectorAll('.form-check-input').forEach(async (item) => {\n item.setCustomValidity(\n await get_string('atleast_one_course_module_must_be_included', 'block_sharing_cart')\n );\n item.reportValidity();\n });\n return false;\n }\n\n if (item.isModule()) {\n courseModuleIds.push(item.getItemOldInstanceId());\n }\n\n Ajax.call([{\n methodname: 'block_sharing_cart_restore_item_from_sharing_cart_into_section',\n args: {\n item_id: item.getItemId(),\n section_id: sectionId,\n course_modules_to_include: courseModuleIds,\n },\n done: async (success) => {\n if (success) {\n await this.#queue.loadQueue(true);\n }\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n /**\n * @param {ItemElement} item\n * @param {Number} sectionId\n * @param {Event} e\n */\n async confirmImportBackupFromSharingCart(item, sectionId, e) {\n e.preventDefault();\n e.stopPropagation();\n\n const strings = await get_strings([\n {\n key: 'copy_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'into_section',\n component: 'block_sharing_cart',\n },\n {\n key: 'import',\n component: 'core',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const sectionName = this.#course.getSectionName(sectionId);\n\n const {html, js} = await this.#baseFactory.moodle().template().renderFragment(\n 'block_sharing_cart',\n 'item_restore_form',\n 1,\n {\n item_id: item.getItemId()\n }\n );\n\n const modal = await ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: strings[0] + ': ' +\n '\"' + item.getItemName().slice(0, 50).trim() + '\"' +\n ' ' + strings[1] + ': ' +\n '\"' + sectionName.slice(0, 50).trim() + '\"',\n body: html,\n buttons: {\n save: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n modal.getRoot().on(ModalEvents.shown, () => this.#baseFactory.moodle().template().runTemplateJS(js));\n modal.getRoot().on(ModalEvents.save, this.importItem.bind(this, item, sectionId, modal.getRoot()[0]));\n await modal.show();\n }\n\n /**\n * @param {Array} itemIds\n */\n async confirmDeleteItems(itemIds) {\n const strings = await get_strings([\n {\n key: 'delete_items',\n component: 'block_sharing_cart',\n },\n {\n key: 'confirm_delete_items',\n component: 'block_sharing_cart',\n },\n {\n key: 'delete',\n component: 'core',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const modal = await ModalFactory.create({\n type: ModalFactory.types.DELETE_CANCEL,\n title: strings[0],\n body: strings[1],\n buttons: {\n delete: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n\n modal.getRoot().on(ModalEvents.delete, this.deleteItems.bind(this, itemIds));\n await modal.show();\n }\n}\n"],"names":["constructor","baseFactory","element","canBackupUserdata","canAnonymizeUserdata","showSharingCartBasket","addEventListeners","setupCourse","setupQueue","setupItems","setupDragAndDrop","setupBulkDelete","course","this","queue","block","document","querySelector","_classPrivateFieldGet","items","querySelectorAll","setupItem","Sortable","dataIdAttr","onUpdate","call","methodname","args","item_ids","toArray","fail","data","exception","dropZone","addEventListener","e","preventDefault","stopPropagation","async","addSectionBackupToSharingCart","addCourseModuleBackupToSharingCart","enableBulkDeleteButton","disableBulkDeleteButton","bulkDeleteButton","selectAllContainer","itemCheckboxes","getItemCheckboxes","allSelected","Array","from","every","checkbox","checked","forEach","updateSelectAllState","updateBulkDeleteButtonState","length","classList","add","remove","disabled","itemIds","push","value","confirmDeleteItems","itemElement","item","getStatus","isBulkDeleteEnabled","some","selectAllCheckbox","selectAllLabel","someSelected","then","str","textContent","indeterminate","setClipboard","clearClipboard","setDraggedSectionId","id","setDraggedCourseModuleId","getItemChildrenRecursively","childItem","index","findIndex","i","getItemId","Number","parseInt","dataset","itemid","_classPrivateFieldGet3","splice","_classPrivateFieldGet4","innerHTML","deleteItem","item_id","done","deleted","removeItemElement","Notification","alert","deleteItems","map","filter","includes","deletedItemIds","getItemName","getElementById","getElement","itemName","onSave","strings","key","component","html","js","moodle","template","renderTemplate","show_user_data_backup","show_anonymize_user_data","modal","ModalFactory","create","type","types","SAVE_CANCEL","title","slice","trim","body","buttons","save","cancel","removeOnClose","getRoot","on","ModalEvents","shown","runTemplateJS","modalUserdataCheckbox","modalAnonymizeCheckbox","users","anonymize","sectionId","sectionName","getSectionName","getSectionCourseModules","createBackupItemToSharingCartModal","settings","section_id","renderItem","show","courseModuleId","courseModuleName","getCourseModuleName","course_module_id","existingItemIndex","existingItem","getOldElement","oldElement","createElementFromFragment","replaceChild","subItem","createElementFromTemplate","name","status","old_instance_id","status_awaiting","has_run_now","task_id","status_finished","status_failed","is_module","is_section","is_root","prepend","importItem","courseModuleIds","isSection","setCustomValidity","reportValidity","isModule","getItemOldInstanceId","course_modules_to_include","success","loadQueue","renderFragment","bind","DELETE_CANCEL","delete"],"mappings":"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"} \ No newline at end of file diff --git a/amd/build/app/block/item/element.min.js b/amd/build/app/block/item/element.min.js index f87b202..e047217 100644 --- a/amd/build/app/block/item/element.min.js +++ b/amd/build/app/block/item/element.min.js @@ -1,3 +1,3 @@ -define("block_sharing_cart/app/block/item/element",["exports","core/modal_factory","core/modal_events","core/notification","core/str","core/ajax"],(function(_exports,_modal_factory,_modal_events,_notification,_str,_ajax){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classPrivateMethodInitSpec(obj,privateSet){_checkPrivateRedeclaration(obj,privateSet),privateSet.add(obj)}function _classPrivateFieldInitSpec(obj,privateMap,value){_checkPrivateRedeclaration(obj,privateMap),privateMap.set(obj,value)}function _checkPrivateRedeclaration(obj,privateCollection){if(privateCollection.has(obj))throw new TypeError("Cannot initialize the same private elements twice on an object")}function _classPrivateMethodGet(receiver,privateSet,fn){if(!privateSet.has(receiver))throw new TypeError("attempted to get private field on non-instance");return fn}function _classPrivateFieldGet(receiver,privateMap){return function(receiver,descriptor){if(descriptor.get)return descriptor.get.call(receiver);return descriptor.value}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"get"))}function _classPrivateFieldSet(receiver,privateMap,value){return function(receiver,descriptor,value){if(descriptor.set)descriptor.set.call(receiver,value);else{if(!descriptor.writable)throw new TypeError("attempted to set read only private field");descriptor.value=value}}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"set"),value),value}function _classExtractFieldDescriptor(receiver,privateMap,action){if(!privateMap.has(receiver))throw new TypeError("attempted to "+action+" private field on non-instance");return privateMap.get(receiver)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_notification=_interopRequireDefault(_notification),_ajax=_interopRequireDefault(_ajax);var _baseFactory=new WeakMap,_blockElement=new WeakMap,_element=new WeakMap,_pollItem=new WeakSet,_addEventListeners=new WeakSet;function _pollItem2(){let currentTry=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,retries=arguments.length>1&&void 0!==arguments[1]?arguments[1]:10;currentTry+=1,currentTry>=retries||_ajax.default.call([{methodname:"block_sharing_cart_get_item_from_sharing_cart",args:{item_id:this.getItemId()},done:async item=>{0!==item.status?await _classPrivateFieldGet(this,_blockElement).renderItem(item):new Promise((resolve=>{setTimeout(resolve,1e3*currentTry)})).then((()=>{_classPrivateMethodGet(this,_pollItem,_pollItem2).call(this,currentTry,retries)}))},fail:data=>{_notification.default.exception(data)}}])}function _addEventListeners2(){var _actionsContainer$que,_actionsContainer$que2,_actionsContainer$que3;_classPrivateFieldGet(this,_element).querySelector(".info").addEventListener("click",this.toggleCollapseRecursively.bind(this));const checkbox=_classPrivateFieldGet(this,_element).querySelector('input[data-action="bulk_select"][type="checkbox"]');null==checkbox||checkbox.addEventListener("click",(()=>{document.getElementById("block_sharing_cart_bulk_delete_confirm").disabled=document.querySelectorAll('.block.block_sharing_cart .sharing_cart_item input[data-action="bulk_select"][type="checkbox"]:checked').length<=0}));const actionsContainer=_classPrivateFieldGet(this,_element).querySelector(":scope > .item-body .sharing_cart_item_actions");null==actionsContainer||null===(_actionsContainer$que=actionsContainer.querySelector('[data-action="delete"]'))||void 0===_actionsContainer$que||_actionsContainer$que.addEventListener("click",this.confirmDeleteItem.bind(this)),null==actionsContainer||null===(_actionsContainer$que2=actionsContainer.querySelector('[data-action="copy_to_course"]'))||void 0===_actionsContainer$que2||_actionsContainer$que2.addEventListener("click",this.copyItemToCourse.bind(this)),null==actionsContainer||null===(_actionsContainer$que3=actionsContainer.querySelector('[data-action="run_now"]'))||void 0===_actionsContainer$que3||_actionsContainer$que3.addEventListener("click",this.runNow.bind(this))}return _exports.default=class{constructor(baseFactory,blockElement,element){_classPrivateMethodInitSpec(this,_addEventListeners),_classPrivateMethodInitSpec(this,_pollItem),_classPrivateFieldInitSpec(this,_baseFactory,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_blockElement,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_element,{writable:!0,value:void 0}),_classPrivateFieldSet(this,_baseFactory,baseFactory),_classPrivateFieldSet(this,_blockElement,blockElement),_classPrivateFieldSet(this,_element,element),"0"===_classPrivateFieldGet(this,_element).dataset.status&&_classPrivateMethodGet(this,_pollItem,_pollItem2).call(this),_classPrivateMethodGet(this,_addEventListeners,_addEventListeners2).call(this)}async copyItemToCourse(e){e.preventDefault(),e.stopPropagation(),await _classPrivateFieldGet(this,_blockElement).setClipboard(this)}async runNow(e){var _currentTarget$datase,_currentTarget$datase2;e.preventDefault(),e.stopPropagation();const currentTarget=e.currentTarget;currentTarget.disabled=!0,_ajax.default.call([{methodname:"block_sharing_cart_run_task_now",args:{task_id:null!==(_currentTarget$datase=null==currentTarget||null===(_currentTarget$datase2=currentTarget.dataset)||void 0===_currentTarget$datase2?void 0:_currentTarget$datase2.taskId)&&void 0!==_currentTarget$datase?_currentTarget$datase:null},done:async()=>{currentTarget.remove(),_classPrivateMethodGet(this,_pollItem,_pollItem2).call(this)},fail:data=>{_notification.default.exception(data),currentTarget.disabled=!1}}])}async confirmDeleteItem(e){e.preventDefault(),e.stopPropagation();const strings=await(0,_str.get_strings)([{key:"delete_item",component:"block_sharing_cart"},{key:"confirm_delete_item",component:"block_sharing_cart"},{key:"delete",component:"core"},{key:"cancel",component:"core"}]),modal=await _modal_factory.default.create({type:_modal_factory.default.types.DELETE_CANCEL,title:strings[0]+': "'+this.getItemName().slice(0,50).trim()+'"',body:strings[1],buttons:{delete:strings[2],cancel:strings[3]},removeOnClose:!0});modal.getRoot().on(_modal_events.default.delete,_classPrivateFieldGet(this,_blockElement).deleteItem.bind(_classPrivateFieldGet(this,_blockElement),this)),await modal.show()}getItemChildrenRecursively(){return _classPrivateFieldGet(this,_element).querySelectorAll(".sharing_cart_item")}getItemElement(){return _classPrivateFieldGet(this,_element)}getItemName(){return _classPrivateFieldGet(this,_element).querySelector(".name").innerText}getItemId(){return Number.parseInt(_classPrivateFieldGet(this,_element).dataset.itemid)}getItemOldInstanceId(){return Number.parseInt(_classPrivateFieldGet(this,_element).dataset.oldinstanceid)}getItemInfo(){return _classPrivateFieldGet(this,_element).querySelector(".info")}toggleCollapse(item){let collapse=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if("section"!==item.dataset.type&&"0"!==item.dataset.status&&"2"!==item.dataset.status)return;item.dataset.collapsed=null!==collapse?collapse?"true":"false":"true"===item.dataset.collapsed?"false":"true";const iconElement=item.querySelector(".info > i");iconElement.classList.contains("fa-exclamation-triangle")||(iconElement.classList.remove("fa-folder-o","fa-folder-open-o"),iconElement.classList.add("true"===item.dataset.collapsed?"fa-folder-o":"fa-folder-open-o"))}isModule(){return!this.isSection()}isSection(){return"section"===_classPrivateFieldGet(this,_element).dataset.type}toggleCollapseRecursively(e){e.preventDefault(),e.stopPropagation(),this.isModule()||"1"!==_classPrivateFieldGet(this,_element).dataset.status||(this.toggleCollapse(_classPrivateFieldGet(this,_element)),this.getItemChildrenRecursively().forEach((item=>{this.toggleCollapse(item,"true"===_classPrivateFieldGet(this,_element).dataset.collapsed)})))}remove(){_classPrivateFieldGet(this,_element).remove()}},_exports.default})); +define("block_sharing_cart/app/block/item/element",["exports","core/modal_factory","core/modal_events","core/notification","core/str","core/ajax"],(function(_exports,_modal_factory,_modal_events,_notification,_str,_ajax){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classPrivateMethodInitSpec(obj,privateSet){_checkPrivateRedeclaration(obj,privateSet),privateSet.add(obj)}function _classPrivateFieldInitSpec(obj,privateMap,value){_checkPrivateRedeclaration(obj,privateMap),privateMap.set(obj,value)}function _checkPrivateRedeclaration(obj,privateCollection){if(privateCollection.has(obj))throw new TypeError("Cannot initialize the same private elements twice on an object")}function _classPrivateMethodGet(receiver,privateSet,fn){if(!privateSet.has(receiver))throw new TypeError("attempted to get private field on non-instance");return fn}function _classPrivateFieldGet(receiver,privateMap){return function(receiver,descriptor){if(descriptor.get)return descriptor.get.call(receiver);return descriptor.value}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"get"))}function _classPrivateFieldSet(receiver,privateMap,value){return function(receiver,descriptor,value){if(descriptor.set)descriptor.set.call(receiver,value);else{if(!descriptor.writable)throw new TypeError("attempted to set read only private field");descriptor.value=value}}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"set"),value),value}function _classExtractFieldDescriptor(receiver,privateMap,action){if(!privateMap.has(receiver))throw new TypeError("attempted to "+action+" private field on non-instance");return privateMap.get(receiver)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_notification=_interopRequireDefault(_notification),_ajax=_interopRequireDefault(_ajax);var _baseFactory=new WeakMap,_blockElement=new WeakMap,_element=new WeakMap,_pollItem=new WeakSet,_addEventListeners=new WeakSet;function _pollItem2(){let currentTry=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,retries=arguments.length>1&&void 0!==arguments[1]?arguments[1]:10;currentTry+=1,currentTry>=retries||_ajax.default.call([{methodname:"block_sharing_cart_get_item_from_sharing_cart",args:{item_id:this.getItemId()},done:async item=>{0!==item.status?await _classPrivateFieldGet(this,_blockElement).renderItem(item):new Promise((resolve=>{setTimeout(resolve,1e3*currentTry)})).then((()=>{_classPrivateMethodGet(this,_pollItem,_pollItem2).call(this,currentTry,retries)}))},fail:data=>{_notification.default.exception(data)}}])}function _addEventListeners2(){var _actionsContainer$que,_actionsContainer$que2,_actionsContainer$que3;_classPrivateFieldGet(this,_element).querySelector(".info").addEventListener("click",this.toggleCollapseRecursively.bind(this));const checkbox=_classPrivateFieldGet(this,_element).querySelector('input[data-action="bulk_select"][type="checkbox"]');null==checkbox||checkbox.addEventListener("click",(()=>{_classPrivateFieldGet(this,_blockElement).updateSelectAllState(),_classPrivateFieldGet(this,_blockElement).updateBulkDeleteButtonState()}));const actionsContainer=_classPrivateFieldGet(this,_element).querySelector(":scope > .item-body .sharing_cart_item_actions");null==actionsContainer||null===(_actionsContainer$que=actionsContainer.querySelector('[data-action="delete"]'))||void 0===_actionsContainer$que||_actionsContainer$que.addEventListener("click",this.confirmDeleteItem.bind(this)),null==actionsContainer||null===(_actionsContainer$que2=actionsContainer.querySelector('[data-action="copy_to_course"]'))||void 0===_actionsContainer$que2||_actionsContainer$que2.addEventListener("click",this.copyItemToCourse.bind(this)),null==actionsContainer||null===(_actionsContainer$que3=actionsContainer.querySelector('[data-action="run_now"]'))||void 0===_actionsContainer$que3||_actionsContainer$que3.addEventListener("click",this.runNow.bind(this))}return _exports.default=class{constructor(baseFactory,blockElement,element){_classPrivateMethodInitSpec(this,_addEventListeners),_classPrivateMethodInitSpec(this,_pollItem),_classPrivateFieldInitSpec(this,_baseFactory,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_blockElement,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_element,{writable:!0,value:void 0}),_classPrivateFieldSet(this,_baseFactory,baseFactory),_classPrivateFieldSet(this,_blockElement,blockElement),_classPrivateFieldSet(this,_element,element),"0"===_classPrivateFieldGet(this,_element).dataset.status&&_classPrivateMethodGet(this,_pollItem,_pollItem2).call(this),_classPrivateMethodGet(this,_addEventListeners,_addEventListeners2).call(this)}async copyItemToCourse(e){e.preventDefault(),e.stopPropagation(),await _classPrivateFieldGet(this,_blockElement).setClipboard(this)}async runNow(e){var _currentTarget$datase,_currentTarget$datase2;e.preventDefault(),e.stopPropagation();const currentTarget=e.currentTarget;currentTarget.disabled=!0,_ajax.default.call([{methodname:"block_sharing_cart_run_task_now",args:{task_id:null!==(_currentTarget$datase=null==currentTarget||null===(_currentTarget$datase2=currentTarget.dataset)||void 0===_currentTarget$datase2?void 0:_currentTarget$datase2.taskId)&&void 0!==_currentTarget$datase?_currentTarget$datase:null},done:async()=>{currentTarget.remove(),_classPrivateMethodGet(this,_pollItem,_pollItem2).call(this)},fail:data=>{_notification.default.exception(data),currentTarget.disabled=!1}}])}async confirmDeleteItem(e){e.preventDefault(),e.stopPropagation();const strings=await(0,_str.get_strings)([{key:"delete_item",component:"block_sharing_cart"},{key:"confirm_delete_item",component:"block_sharing_cart"},{key:"delete",component:"core"},{key:"cancel",component:"core"}]),modal=await _modal_factory.default.create({type:_modal_factory.default.types.DELETE_CANCEL,title:strings[0]+': "'+this.getItemName().slice(0,50).trim()+'"',body:strings[1],buttons:{delete:strings[2],cancel:strings[3]},removeOnClose:!0});modal.getRoot().on(_modal_events.default.delete,_classPrivateFieldGet(this,_blockElement).deleteItem.bind(_classPrivateFieldGet(this,_blockElement),this)),await modal.show()}getItemChildrenRecursively(){return _classPrivateFieldGet(this,_element).querySelectorAll(".sharing_cart_item")}getItemElement(){return _classPrivateFieldGet(this,_element)}getStatus(){return _classPrivateFieldGet(this,_element).dataset.status}getItemName(){return _classPrivateFieldGet(this,_element).querySelector(".name").innerText}getItemId(){return Number.parseInt(_classPrivateFieldGet(this,_element).dataset.itemid)}getItemOldInstanceId(){return Number.parseInt(_classPrivateFieldGet(this,_element).dataset.oldinstanceid)}getItemInfo(){return _classPrivateFieldGet(this,_element).querySelector(".info")}toggleCollapse(item){let collapse=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if("section"!==item.dataset.type&&"0"!==item.dataset.status&&"2"!==item.dataset.status)return;item.dataset.collapsed=null!==collapse?collapse?"true":"false":"true"===item.dataset.collapsed?"false":"true";const iconElement=item.querySelector(".info > i");iconElement.classList.contains("fa-exclamation-triangle")||(iconElement.classList.remove("fa-folder-o","fa-folder-open-o"),iconElement.classList.add("true"===item.dataset.collapsed?"fa-folder-o":"fa-folder-open-o"))}isModule(){return!this.isSection()}isSection(){return"section"===_classPrivateFieldGet(this,_element).dataset.type}toggleCollapseRecursively(e){e.preventDefault(),e.stopPropagation(),this.isModule()||"1"!==_classPrivateFieldGet(this,_element).dataset.status||(this.toggleCollapse(_classPrivateFieldGet(this,_element)),this.getItemChildrenRecursively().forEach((item=>{this.toggleCollapse(item,"true"===_classPrivateFieldGet(this,_element).dataset.collapsed)})))}remove(){_classPrivateFieldGet(this,_element).remove()}},_exports.default})); //# sourceMappingURL=element.min.js.map \ No newline at end of file diff --git a/amd/build/app/block/item/element.min.js.map b/amd/build/app/block/item/element.min.js.map index 7a87051..aa81eaa 100644 --- a/amd/build/app/block/item/element.min.js.map +++ b/amd/build/app/block/item/element.min.js.map @@ -1 +1 @@ -{"version":3,"file":"element.min.js","sources":["../../../../src/app/block/item/element.js"],"sourcesContent":["import ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport Notification from \"core/notification\";\nimport {get_strings} from \"core/str\";\nimport Ajax from \"core/ajax\";\n\nexport default class ItemElement {\n /**\n * @type {BaseFactory}\n */\n #baseFactory;\n\n /**\n * @type {BlockElement}\n */\n #blockElement;\n\n /**\n * @type {HTMLElement}\n */\n #element;\n\n /**\n * @param {BaseFactory} baseFactory\n * @param {BlockElement} blockElement\n * @param {HTMLElement} element\n */\n constructor(baseFactory, blockElement, element) {\n this.#baseFactory = baseFactory;\n this.#blockElement = blockElement;\n this.#element = element;\n\n if (this.#element.dataset.status === '0') {\n this.#pollItem();\n }\n\n this.#addEventListeners();\n }\n\n #pollItem(currentTry = 0, retries = 10) {\n currentTry += 1;\n\n if (currentTry >= retries) {\n return;\n }\n\n Ajax.call([{\n methodname: 'block_sharing_cart_get_item_from_sharing_cart',\n args: {\n item_id: this.getItemId(),\n },\n done: async (item) => {\n if (item.status === 0) {\n new Promise(\n (resolve) => {\n setTimeout(resolve, currentTry * 1000);\n }\n ).then(\n () => {\n this.#pollItem(currentTry, retries);\n }\n );\n\n return;\n }\n\n await this.#blockElement.renderItem(item);\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n #addEventListeners() {\n this.#element.querySelector('.info').addEventListener('click', this.toggleCollapseRecursively.bind(this));\n\n const checkbox = this.#element.querySelector('input[data-action=\"bulk_select\"][type=\"checkbox\"]');\n checkbox?.addEventListener('click', () => {\n const bulkDeleteButton = document.getElementById('block_sharing_cart_bulk_delete_confirm');\n\n const blockSelector = '.block.block_sharing_cart';\n const checkboxSelector = blockSelector + ' .sharing_cart_item input[data-action=\"bulk_select\"][type=\"checkbox\"]';\n bulkDeleteButton.disabled = document.querySelectorAll(checkboxSelector + ':checked').length <= 0;\n });\n\n const actionsContainer = this.#element.querySelector(':scope > .item-body .sharing_cart_item_actions');\n\n actionsContainer?.querySelector('[data-action=\"delete\"]')?.addEventListener(\n 'click',\n this.confirmDeleteItem.bind(this)\n );\n actionsContainer?.querySelector('[data-action=\"copy_to_course\"]')?.addEventListener(\n 'click',\n this.copyItemToCourse.bind(this)\n );\n actionsContainer?.querySelector('[data-action=\"run_now\"]')?.addEventListener(\n 'click',\n this.runNow.bind(this)\n );\n }\n\n async copyItemToCourse(e) {\n e.preventDefault();\n e.stopPropagation();\n\n await this.#blockElement.setClipboard(this);\n }\n\n async runNow(e) {\n e.preventDefault();\n e.stopPropagation();\n\n const currentTarget = e.currentTarget;\n currentTarget.disabled = true;\n\n Ajax.call([{\n methodname: 'block_sharing_cart_run_task_now',\n args: {\n task_id: currentTarget?.dataset?.taskId ?? null,\n },\n done: async () => {\n currentTarget.remove();\n this.#pollItem();\n },\n fail: (data) => {\n Notification.exception(data);\n currentTarget.disabled = false;\n }\n }]);\n }\n\n async confirmDeleteItem(e) {\n e.preventDefault();\n e.stopPropagation();\n\n const strings = await get_strings([\n {\n key: 'delete_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'confirm_delete_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'delete',\n component: 'core',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const modal = await ModalFactory.create({\n type: ModalFactory.types.DELETE_CANCEL,\n title: strings[0] + ': \"' + this.getItemName().slice(0, 50).trim() + '\"',\n body: strings[1],\n buttons: {\n delete: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n modal.getRoot().on(ModalEvents.delete, this.#blockElement.deleteItem.bind(this.#blockElement, this));\n await modal.show();\n }\n\n /**\n * @return {NodeListOf}\n */\n getItemChildrenRecursively() {\n return this.#element.querySelectorAll('.sharing_cart_item');\n }\n\n /**\n * @return {HTMLElement}\n */\n getItemElement() {\n return this.#element;\n }\n\n /**\n * @return {String}\n */\n getItemName() {\n return this.#element.querySelector('.name').innerText;\n }\n\n /**\n * @return {Number}\n */\n getItemId() {\n return Number.parseInt(this.#element.dataset.itemid);\n }\n\n /**\n * @return {Number}\n */\n getItemOldInstanceId() {\n return Number.parseInt(this.#element.dataset.oldinstanceid);\n }\n\n /**\n * @return {HTMLElement}\n */\n getItemInfo() {\n return this.#element.querySelector('.info');\n }\n\n /**\n * @param {HTMLElement} item\n * @param {Boolean|NULL} collapse\n */\n toggleCollapse(item, collapse = null) {\n if (item.dataset.type !== 'section' &&\n item.dataset.status !== '0' &&\n item.dataset.status !== '2') {\n return;\n }\n\n if (collapse !== null) {\n item.dataset.collapsed = collapse ? 'true' : 'false';\n } else {\n item.dataset.collapsed = item.dataset.collapsed === 'true' ? 'false' : 'true';\n }\n\n const iconElement = item.querySelector('.info > i');\n if (!iconElement.classList.contains('fa-exclamation-triangle')) {\n iconElement.classList.remove('fa-folder-o', 'fa-folder-open-o');\n iconElement.classList.add(item.dataset.collapsed === 'true' ? 'fa-folder-o' : 'fa-folder-open-o');\n }\n }\n\n isModule() {\n return !this.isSection();\n }\n\n isSection() {\n return this.#element.dataset.type === 'section';\n }\n\n /**\n * @param {Event} e\n */\n toggleCollapseRecursively(e) {\n e.preventDefault();\n e.stopPropagation();\n\n if (this.isModule() || this.#element.dataset.status !== '1') {\n return;\n }\n\n this.toggleCollapse(this.#element);\n this.getItemChildrenRecursively().forEach((item) => {\n this.toggleCollapse(item, this.#element.dataset.collapsed === 'true');\n });\n }\n\n remove() {\n this.#element.remove();\n }\n}\n"],"names":["currentTry","retries","call","methodname","args","item_id","this","getItemId","done","async","item","status","_classPrivateFieldGet","renderItem","Promise","resolve","setTimeout","then","fail","data","exception","querySelector","addEventListener","toggleCollapseRecursively","bind","checkbox","document","getElementById","disabled","querySelectorAll","checkboxSelector","length","actionsContainer","confirmDeleteItem","copyItemToCourse","runNow","constructor","baseFactory","blockElement","element","dataset","e","preventDefault","stopPropagation","setClipboard","currentTarget","task_id","_currentTarget$datase2","taskId","remove","strings","key","component","modal","ModalFactory","create","type","types","DELETE_CANCEL","title","getItemName","slice","trim","body","buttons","delete","cancel","removeOnClose","getRoot","on","ModalEvents","deleteItem","show","getItemChildrenRecursively","getItemElement","innerText","Number","parseInt","itemid","getItemOldInstanceId","oldinstanceid","getItemInfo","toggleCollapse","collapse","collapsed","iconElement","classList","contains","add","isModule","isSection","forEach"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"element.min.js","sources":["../../../../src/app/block/item/element.js"],"sourcesContent":["import ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport Notification from \"core/notification\";\nimport {get_strings} from \"core/str\";\nimport Ajax from \"core/ajax\";\n\nexport default class ItemElement {\n /**\n * @type {BaseFactory}\n */\n #baseFactory;\n\n /**\n * @type {BlockElement}\n */\n #blockElement;\n\n /**\n * @type {HTMLElement}\n */\n #element;\n\n /**\n * @param {BaseFactory} baseFactory\n * @param {BlockElement} blockElement\n * @param {HTMLElement} element\n */\n constructor(baseFactory, blockElement, element) {\n this.#baseFactory = baseFactory;\n this.#blockElement = blockElement;\n this.#element = element;\n\n if (this.#element.dataset.status === '0') {\n this.#pollItem();\n }\n\n this.#addEventListeners();\n }\n\n #pollItem(currentTry = 0, retries = 10) {\n currentTry += 1;\n\n if (currentTry >= retries) {\n return;\n }\n\n Ajax.call([{\n methodname: 'block_sharing_cart_get_item_from_sharing_cart',\n args: {\n item_id: this.getItemId(),\n },\n done: async (item) => {\n if (item.status === 0) {\n new Promise(\n (resolve) => {\n setTimeout(resolve, currentTry * 1000);\n }\n ).then(\n () => {\n this.#pollItem(currentTry, retries);\n }\n );\n\n return;\n }\n\n await this.#blockElement.renderItem(item);\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n #addEventListeners() {\n this.#element.querySelector('.info').addEventListener('click', this.toggleCollapseRecursively.bind(this));\n\n const checkbox = this.#element.querySelector('input[data-action=\"bulk_select\"][type=\"checkbox\"]');\n checkbox?.addEventListener('click', () => {\n this.#blockElement.updateSelectAllState();\n this.#blockElement.updateBulkDeleteButtonState();\n });\n\n const actionsContainer = this.#element.querySelector(':scope > .item-body .sharing_cart_item_actions');\n\n actionsContainer?.querySelector('[data-action=\"delete\"]')?.addEventListener(\n 'click',\n this.confirmDeleteItem.bind(this)\n );\n actionsContainer?.querySelector('[data-action=\"copy_to_course\"]')?.addEventListener(\n 'click',\n this.copyItemToCourse.bind(this)\n );\n actionsContainer?.querySelector('[data-action=\"run_now\"]')?.addEventListener(\n 'click',\n this.runNow.bind(this)\n );\n }\n\n async copyItemToCourse(e) {\n e.preventDefault();\n e.stopPropagation();\n\n await this.#blockElement.setClipboard(this);\n }\n\n async runNow(e) {\n e.preventDefault();\n e.stopPropagation();\n\n const currentTarget = e.currentTarget;\n currentTarget.disabled = true;\n\n Ajax.call([{\n methodname: 'block_sharing_cart_run_task_now',\n args: {\n task_id: currentTarget?.dataset?.taskId ?? null,\n },\n done: async () => {\n currentTarget.remove();\n this.#pollItem();\n },\n fail: (data) => {\n Notification.exception(data);\n currentTarget.disabled = false;\n }\n }]);\n }\n\n async confirmDeleteItem(e) {\n e.preventDefault();\n e.stopPropagation();\n\n const strings = await get_strings([\n {\n key: 'delete_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'confirm_delete_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'delete',\n component: 'core',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const modal = await ModalFactory.create({\n type: ModalFactory.types.DELETE_CANCEL,\n title: strings[0] + ': \"' + this.getItemName().slice(0, 50).trim() + '\"',\n body: strings[1],\n buttons: {\n delete: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n modal.getRoot().on(ModalEvents.delete, this.#blockElement.deleteItem.bind(this.#blockElement, this));\n await modal.show();\n }\n\n /**\n * @return {NodeListOf}\n */\n getItemChildrenRecursively() {\n return this.#element.querySelectorAll('.sharing_cart_item');\n }\n\n /**\n * @return {HTMLElement}\n */\n getItemElement() {\n return this.#element;\n }\n\n getStatus() {\n return this.#element.dataset.status;\n }\n\n /**\n * @return {String}\n */\n getItemName() {\n return this.#element.querySelector('.name').innerText;\n }\n\n /**\n * @return {Number}\n */\n getItemId() {\n return Number.parseInt(this.#element.dataset.itemid);\n }\n\n /**\n * @return {Number}\n */\n getItemOldInstanceId() {\n return Number.parseInt(this.#element.dataset.oldinstanceid);\n }\n\n /**\n * @return {HTMLElement}\n */\n getItemInfo() {\n return this.#element.querySelector('.info');\n }\n\n /**\n * @param {HTMLElement} item\n * @param {Boolean|NULL} collapse\n */\n toggleCollapse(item, collapse = null) {\n if (item.dataset.type !== 'section' &&\n item.dataset.status !== '0' &&\n item.dataset.status !== '2') {\n return;\n }\n\n if (collapse !== null) {\n item.dataset.collapsed = collapse ? 'true' : 'false';\n } else {\n item.dataset.collapsed = item.dataset.collapsed === 'true' ? 'false' : 'true';\n }\n\n const iconElement = item.querySelector('.info > i');\n if (!iconElement.classList.contains('fa-exclamation-triangle')) {\n iconElement.classList.remove('fa-folder-o', 'fa-folder-open-o');\n iconElement.classList.add(item.dataset.collapsed === 'true' ? 'fa-folder-o' : 'fa-folder-open-o');\n }\n }\n\n isModule() {\n return !this.isSection();\n }\n\n isSection() {\n return this.#element.dataset.type === 'section';\n }\n\n /**\n * @param {Event} e\n */\n toggleCollapseRecursively(e) {\n e.preventDefault();\n e.stopPropagation();\n\n if (this.isModule() || this.#element.dataset.status !== '1') {\n return;\n }\n\n this.toggleCollapse(this.#element);\n this.getItemChildrenRecursively().forEach((item) => {\n this.toggleCollapse(item, this.#element.dataset.collapsed === 'true');\n });\n }\n\n remove() {\n this.#element.remove();\n }\n}\n"],"names":["currentTry","retries","call","methodname","args","item_id","this","getItemId","done","async","item","status","_classPrivateFieldGet","renderItem","Promise","resolve","setTimeout","then","fail","data","exception","querySelector","addEventListener","toggleCollapseRecursively","bind","checkbox","updateSelectAllState","updateBulkDeleteButtonState","actionsContainer","confirmDeleteItem","copyItemToCourse","runNow","constructor","baseFactory","blockElement","element","dataset","e","preventDefault","stopPropagation","setClipboard","currentTarget","disabled","task_id","_currentTarget$datase2","taskId","remove","strings","key","component","modal","ModalFactory","create","type","types","DELETE_CANCEL","title","getItemName","slice","trim","body","buttons","delete","cancel","removeOnClose","getRoot","on","ModalEvents","deleteItem","show","getItemChildrenRecursively","querySelectorAll","getItemElement","getStatus","innerText","Number","parseInt","itemid","getItemOldInstanceId","oldinstanceid","getItemInfo","toggleCollapse","collapse","collapsed","iconElement","classList","contains","add","isModule","isSection","forEach"],"mappings":"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"} \ No newline at end of file diff --git a/amd/build/app/block/queue/element.min.js.map b/amd/build/app/block/queue/element.min.js.map index 1f5d717..2286599 100644 --- a/amd/build/app/block/queue/element.min.js.map +++ b/amd/build/app/block/queue/element.min.js.map @@ -1 +1 @@ -{"version":3,"file":"element.min.js","sources":["../../../../src/app/block/queue/element.js"],"sourcesContent":["import {getCurrentCourseEditor} from \"core_courseformat/courseeditor\";\nimport Ajax from \"core/ajax\";\nimport * as Toast from 'core/toast';\nimport {get_string as getString} from \"core/str\";\n\nexport default class QueueElement {\n /**\n * @type {BaseFactory}\n */\n #baseFactory;\n\n /**\n * @type {BlockElement}\n */\n #blockElement;\n\n /**\n * @type {HTMLElement}\n */\n #element;\n\n /**\n * @type {CourseEditor}\n */\n #reactive;\n\n /**\n * @type {Promise|null}\n */\n #loadQueuePromise = null;\n\n /**\n * @type {Object|null}\n */\n #loadQueueToken = null;\n\n /**\n * @type {boolean}\n */\n #preventReload = false;\n\n /**\n *\n * @param {BaseFactory} baseFactory\n * @param {BlockElement} blockElement\n * @param {HTMLElement} element\n */\n constructor(baseFactory, blockElement, element) {\n this.#baseFactory = baseFactory;\n this.#blockElement = blockElement;\n this.#element = element;\n this.#reactive = getCurrentCourseEditor();\n\n this.tryReloadQueue(true);\n\n setInterval(() => {\n this.tryReloadQueue();\n }, 4000);\n }\n\n /**\n * @return {NodeListOf}\n */\n getQueueItems() {\n return this.#element.querySelectorAll('.queue-item');\n }\n\n /**\n * @param {boolean} ignoreQueueItemsCount\n */\n tryReloadQueue(ignoreQueueItemsCount = false) {\n if (ignoreQueueItemsCount === false && this.getQueueItems().length === 0) {\n return;\n }\n\n if (this.#loadQueuePromise !== null) {\n this.#loadQueuePromise.then(() => {\n this.tryReloadQueue();\n }).catch(() => {\n this.tryReloadQueue();\n });\n return;\n }\n\n this.#loadQueueToken = {};\n this.#loadQueuePromise = this.loadQueue(false, this.#loadQueueToken);\n this.#loadQueuePromise.then(() => {\n this.#loadQueuePromise = null;\n this.#loadQueueToken = null;\n }).catch(() => {\n this.#loadQueueToken = null;\n this.#loadQueuePromise = null;\n });\n }\n\n /**\n * @param {Boolean} showSpinner\n * @param {Object} token\n * @return {Promise}\n */\n async loadQueue(showSpinner = false, token = {}) {\n return new Promise(async (resolve, reject) => {\n token.abort = () => {\n reject();\n };\n\n const oldChildren = this.#element.children;\n const oldQueueItemsCount = this.getQueueItems().length;\n\n if (showSpinner) {\n this.#element.innerHTML = '';\n }\n\n const elements = await this.#baseFactory.moodle().template().createElementsFromFragment(\n 'block_sharing_cart',\n 'item_queue',\n M.cfg.contextid,\n {}\n );\n\n const queueItems = elements.filter((element) => {\n if (!(element instanceof Element)) {\n return false;\n }\n\n return element.classList.contains('queue-item');\n });\n\n if (oldQueueItemsCount > queueItems.length) {\n const removedElements = Array.from(oldChildren).filter((element) => {\n const correspondingElement = queueItems.find((el) => el.dataset.id === element.dataset.id);\n\n return correspondingElement === undefined;\n });\n\n const sectionIds = [];\n removedElements.forEach((element) => {\n const sectionId = element.dataset.toSectionId;\n\n if (!sectionId) {\n return;\n }\n\n if (sectionIds.indexOf(sectionId) !== -1) {\n return;\n }\n\n sectionIds.push(sectionId);\n });\n\n if (sectionIds.length > 0) {\n this.#reactive.dispatch('sectionState', sectionIds).then(() => {\n Toast.add(getString('you_may_need_to_reload_the_course_warning', 'block_sharing_cart'), {\n closeButton: true,\n autohide: false,\n type: 'warning'\n });\n });\n }\n }\n\n this.#element.innerHTML = '';\n\n queueItems.forEach((element) => {\n const runNowButton = element.querySelector('button.btn');\n\n if (!runNowButton) {\n return;\n }\n\n runNowButton.addEventListener('click', () => {\n const taskId = element.dataset.id;\n\n runNowButton.disabled = true;\n\n this.#preventReload = true;\n if (this.#loadQueueToken !== null) {\n this.#loadQueueToken.abort();\n }\n\n Ajax.call([{\n methodname: 'block_sharing_cart_run_task_now',\n args: {\n task_id: taskId\n }\n }]);\n\n setTimeout(() => {\n this.#preventReload = false;\n this.tryReloadQueue(true);\n }, 2000);\n }, {once: true});\n });\n\n elements.forEach((element) => {\n this.#element.appendChild(element);\n });\n\n resolve();\n });\n }\n}\n"],"names":["constructor","baseFactory","blockElement","element","tryReloadQueue","setInterval","getQueueItems","_classPrivateFieldGet","querySelectorAll","this","length","loadQueue","then","catch","showSpinner","token","Promise","async","resolve","reject","abort","oldChildren","children","oldQueueItemsCount","innerHTML","elements","moodle","template","createElementsFromFragment","M","cfg","contextid","queueItems","filter","Element","classList","contains","removedElements","Array","from","undefined","find","el","dataset","id","sectionIds","forEach","sectionId","toSectionId","indexOf","push","dispatch","Toast","add","closeButton","autohide","type","runNowButton","querySelector","addEventListener","taskId","disabled","call","methodname","args","task_id","setTimeout","once","appendChild"],"mappings":"s9EA+CIA,YAAYC,YAAaC,aAAcC,4WAlBnB,0EAKF,0EAKD,4CASOF,sDACCC,kDACLC,+CACC,gDAEZC,gBAAe,GAEpBC,aAAY,UACHD,mBACN,KAMPE,uBACWC,qCAAcC,iBAAiB,eAM1CJ,kBACkC,+DAAyC,IAAhCK,KAAKH,gBAAgBI,SAI7B,OAA3BH,0FASmB,iDACEE,KAAKE,WAAU,wBAAOF,sEACxBG,MAAK,kDACC,iDACF,SACxBC,OAAM,gDACkB,mDACE,wDAfFD,MAAK,UACnBR,oBACNS,OAAM,UACAT,2CAqBDU,oEAAqBC,6DAAQ,UAClC,IAAIC,SAAQC,MAAOC,QAASC,UAC/BJ,MAAMK,MAAQ,KACVD,gBAGEE,YAAcd,qCAAce,SAC5BC,mBAAqBd,KAAKH,gBAAgBI,OAE5CI,mDACcU,UAAY,uCAGxBC,eAAiBlB,yCAAkBmB,SAASC,WAAWC,2BACzD,qBACA,aACAC,EAAEC,IAAIC,UACN,IAGEC,WAAaP,SAASQ,QAAQ9B,SAC1BA,mBAAmB+B,SAIlB/B,QAAQgC,UAAUC,SAAS,mBAGlCb,mBAAqBS,WAAWtB,OAAQ,OAClC2B,gBAAkBC,MAAMC,KAAKlB,aAAaY,QAAQ9B,cAGpBqC,IAFHR,WAAWS,MAAMC,IAAOA,GAAGC,QAAQC,KAAOzC,QAAQwC,QAAQC,OAKrFC,WAAa,GACnBR,gBAAgBS,SAAS3C,gBACf4C,UAAY5C,QAAQwC,QAAQK,YAE7BD,YAIkC,IAAnCF,WAAWI,QAAQF,YAIvBF,WAAWK,KAAKH,cAGhBF,WAAWnC,OAAS,yCACLyC,SAAS,eAAgBN,YAAYjC,MAAK,KACrDwC,MAAMC,KAAI,mBAAU,4CAA6C,sBAAuB,CACpFC,aAAa,EACbC,UAAU,EACVC,KAAM,oDAMRhC,UAAY,GAE1BQ,WAAWc,SAAS3C,gBACVsD,aAAetD,QAAQuD,cAAc,cAEtCD,cAILA,aAAaE,iBAAiB,SAAS,WAC7BC,OAASzD,QAAQwC,QAAQC,GAE/Ba,aAAaI,UAAW,6CAEF,GACO,OAAzBtD,yFACqBa,sBAGpB0C,KAAK,CAAC,CACPC,WAAY,kCACZC,KAAM,CACFC,QAASL,WAIjBM,YAAW,gDACe,QACjB9D,gBAAe,KACrB,OACJ,CAAC+D,MAAM,OAGd1C,SAASqB,SAAS3C,+CACAiE,YAAYjE,YAG9Be"} \ No newline at end of file +{"version":3,"file":"element.min.js","sources":["../../../../src/app/block/queue/element.js"],"sourcesContent":["import {getCurrentCourseEditor} from \"core_courseformat/courseeditor\";\nimport Ajax from \"core/ajax\";\nimport * as Toast from 'core/toast';\nimport {get_string as getString} from \"core/str\";\n\nexport default class QueueElement {\n /**\n * @type {BaseFactory}\n */\n #baseFactory;\n\n /**\n * @type {BlockElement}\n */\n #blockElement;\n\n /**\n * @type {HTMLElement}\n */\n #element;\n\n /**\n * @type {CourseEditor}\n */\n #reactive;\n\n /**\n * @type {Promise|null}\n */\n #loadQueuePromise = null;\n\n /**\n * @type {Object|null}\n */\n #loadQueueToken = null;\n\n /**\n * @type {boolean}\n */\n #preventReload = false;\n\n /**\n *\n * @param {BaseFactory} baseFactory\n * @param {BlockElement} blockElement\n * @param {HTMLElement} element\n */\n constructor(baseFactory, blockElement, element) {\n this.#baseFactory = baseFactory;\n this.#blockElement = blockElement;\n this.#element = element;\n this.#reactive = getCurrentCourseEditor();\n\n this.tryReloadQueue(true);\n\n setInterval(() => {\n this.tryReloadQueue();\n }, 4000);\n }\n\n /**\n * @return {NodeListOf}\n */\n getQueueItems() {\n return this.#element.querySelectorAll('.queue-item');\n }\n\n /**\n * @param {boolean} ignoreQueueItemsCount\n */\n tryReloadQueue(ignoreQueueItemsCount = false) {\n if (ignoreQueueItemsCount === false && this.getQueueItems().length === 0) {\n return;\n }\n\n if (this.#loadQueuePromise !== null) {\n this.#loadQueuePromise.then(() => {\n this.tryReloadQueue();\n }).catch(() => {\n this.tryReloadQueue();\n });\n return;\n }\n\n this.#loadQueueToken = {};\n this.#loadQueuePromise = this.loadQueue(false, this.#loadQueueToken);\n this.#loadQueuePromise.then(() => {\n this.#loadQueuePromise = null;\n this.#loadQueueToken = null;\n }).catch(() => {\n this.#loadQueueToken = null;\n this.#loadQueuePromise = null;\n });\n }\n\n /**\n * @param {Boolean} showSpinner\n * @param {Object} token\n * @return {Promise}\n */\n async loadQueue(showSpinner = false, token = {}) {\n // eslint-disable-next-line no-async-promise-executor\n return new Promise(async (resolve, reject) => {\n token.abort = () => {\n reject();\n };\n\n const oldChildren = this.#element.children;\n const oldQueueItemsCount = this.getQueueItems().length;\n\n if (showSpinner) {\n this.#element.innerHTML = '';\n }\n\n const elements = await this.#baseFactory.moodle().template().createElementsFromFragment(\n 'block_sharing_cart',\n 'item_queue',\n M.cfg.contextid,\n {}\n );\n\n const queueItems = elements.filter((element) => {\n if (!(element instanceof Element)) {\n return false;\n }\n\n return element.classList.contains('queue-item');\n });\n\n if (oldQueueItemsCount > queueItems.length) {\n const removedElements = Array.from(oldChildren).filter((element) => {\n const correspondingElement = queueItems.find((el) => el.dataset.id === element.dataset.id);\n\n return correspondingElement === undefined;\n });\n\n const sectionIds = [];\n removedElements.forEach((element) => {\n const sectionId = element.dataset.toSectionId;\n\n if (!sectionId) {\n return;\n }\n\n if (sectionIds.indexOf(sectionId) !== -1) {\n return;\n }\n\n sectionIds.push(sectionId);\n });\n\n if (sectionIds.length > 0) {\n this.#reactive.dispatch('sectionState', sectionIds).then(() => {\n Toast.add(getString('you_may_need_to_reload_the_course_warning', 'block_sharing_cart'), {\n closeButton: true,\n autohide: false,\n type: 'warning'\n });\n });\n }\n }\n\n this.#element.innerHTML = '';\n\n queueItems.forEach((element) => {\n const runNowButton = element.querySelector('button.btn');\n\n if (!runNowButton) {\n return;\n }\n\n runNowButton.addEventListener('click', () => {\n const taskId = element.dataset.id;\n\n runNowButton.disabled = true;\n\n this.#preventReload = true;\n if (this.#loadQueueToken !== null) {\n this.#loadQueueToken.abort();\n }\n\n Ajax.call([{\n methodname: 'block_sharing_cart_run_task_now',\n args: {\n task_id: taskId\n }\n }]);\n\n setTimeout(() => {\n this.#preventReload = false;\n this.tryReloadQueue(true);\n }, 2000);\n }, {once: true});\n });\n\n elements.forEach((element) => {\n this.#element.appendChild(element);\n });\n\n resolve();\n });\n }\n}\n"],"names":["constructor","baseFactory","blockElement","element","tryReloadQueue","setInterval","getQueueItems","_classPrivateFieldGet","querySelectorAll","this","length","loadQueue","then","catch","showSpinner","token","Promise","async","resolve","reject","abort","oldChildren","children","oldQueueItemsCount","innerHTML","elements","moodle","template","createElementsFromFragment","M","cfg","contextid","queueItems","filter","Element","classList","contains","removedElements","Array","from","undefined","find","el","dataset","id","sectionIds","forEach","sectionId","toSectionId","indexOf","push","dispatch","Toast","add","closeButton","autohide","type","runNowButton","querySelector","addEventListener","taskId","disabled","call","methodname","args","task_id","setTimeout","once","appendChild"],"mappings":"s9EA+CIA,YAAYC,YAAaC,aAAcC,4WAlBnB,0EAKF,0EAKD,4CASOF,sDACCC,kDACLC,+CACC,gDAEZC,gBAAe,GAEpBC,aAAY,UACHD,mBACN,KAMPE,uBACWC,qCAAcC,iBAAiB,eAM1CJ,kBACkC,+DAAyC,IAAhCK,KAAKH,gBAAgBI,SAI7B,OAA3BH,0FASmB,iDACEE,KAAKE,WAAU,wBAAOF,sEACxBG,MAAK,kDACC,iDACF,SACxBC,OAAM,gDACkB,mDACE,wDAfFD,MAAK,UACnBR,oBACNS,OAAM,UACAT,2CAqBDU,oEAAqBC,6DAAQ,UAElC,IAAIC,SAAQC,MAAOC,QAASC,UAC/BJ,MAAMK,MAAQ,KACVD,gBAGEE,YAAcd,qCAAce,SAC5BC,mBAAqBd,KAAKH,gBAAgBI,OAE5CI,mDACcU,UAAY,uCAGxBC,eAAiBlB,yCAAkBmB,SAASC,WAAWC,2BACzD,qBACA,aACAC,EAAEC,IAAIC,UACN,IAGEC,WAAaP,SAASQ,QAAQ9B,SAC1BA,mBAAmB+B,SAIlB/B,QAAQgC,UAAUC,SAAS,mBAGlCb,mBAAqBS,WAAWtB,OAAQ,OAClC2B,gBAAkBC,MAAMC,KAAKlB,aAAaY,QAAQ9B,cAGpBqC,IAFHR,WAAWS,MAAMC,IAAOA,GAAGC,QAAQC,KAAOzC,QAAQwC,QAAQC,OAKrFC,WAAa,GACnBR,gBAAgBS,SAAS3C,gBACf4C,UAAY5C,QAAQwC,QAAQK,YAE7BD,YAIkC,IAAnCF,WAAWI,QAAQF,YAIvBF,WAAWK,KAAKH,cAGhBF,WAAWnC,OAAS,yCACLyC,SAAS,eAAgBN,YAAYjC,MAAK,KACrDwC,MAAMC,KAAI,mBAAU,4CAA6C,sBAAuB,CACpFC,aAAa,EACbC,UAAU,EACVC,KAAM,oDAMRhC,UAAY,GAE1BQ,WAAWc,SAAS3C,gBACVsD,aAAetD,QAAQuD,cAAc,cAEtCD,cAILA,aAAaE,iBAAiB,SAAS,WAC7BC,OAASzD,QAAQwC,QAAQC,GAE/Ba,aAAaI,UAAW,6CAEF,GACO,OAAzBtD,yFACqBa,sBAGpB0C,KAAK,CAAC,CACPC,WAAY,kCACZC,KAAM,CACFC,QAASL,WAIjBM,YAAW,gDACe,QACjB9D,gBAAe,KACrB,OACJ,CAAC+D,MAAM,OAGd1C,SAASqB,SAAS3C,+CACAiE,YAAYjE,YAG9Be"} \ No newline at end of file diff --git a/amd/src/app/block/element.js b/amd/src/app/block/element.js index 3025f4f..adb30c9 100644 --- a/amd/src/app/block/element.js +++ b/amd/src/app/block/element.js @@ -66,6 +66,11 @@ export default class BlockElement { */ #draggedSectionId = null; + /** + * @type {boolean} + */ + #bulkDeleteEnabled = false; + /** * @param {BaseFactory} baseFactory * @param {HTMLElement} element @@ -106,12 +111,12 @@ export default class BlockElement { this.#queue = this.#baseFactory.block().queue().element(this, queue); } - setupItems() { + async setupItems() { const items = this.#element.querySelectorAll('.sharing_cart_item'); - items.forEach((element) => { - this.setupItem(element); - }); + for (const element of items) { + await this.setupItem(element); + } this.#sortable = new Sortable(this.#element.querySelector('.sharing_cart_items'), { dataIdAttr: 'data-itemid', @@ -169,14 +174,37 @@ export default class BlockElement { const disableBulkDeleteButton = this.#element.querySelector('#block_sharing_cart_cancel_bulk_delete'); const bulkDeleteButton = this.#element.querySelector('#block_sharing_cart_bulk_delete_confirm'); - const checkboxSelector = '.sharing_cart_item input[data-action="bulk_select"][type="checkbox"]'; + const selectAllContainer = this.#element.querySelector('#select_all_container'); + const selectAllCheckbox = this.#element.querySelector('#select_all_box'); + + selectAllCheckbox.addEventListener('click', async () => { + const itemCheckboxes = this.getItemCheckboxes(); + const allSelected = Array.from(itemCheckboxes).every(checkbox => checkbox.checked); + itemCheckboxes.forEach(checkbox => { + checkbox.checked = !allSelected; + }); + itemCheckboxes.forEach(checkbox => checkbox.addEventListener('change', async () => { + this.updateSelectAllState(); + })); + + this.updateSelectAllState(); + this.updateBulkDeleteButtonState(); + }); enableBulkDeleteButton.addEventListener('click', () => { + if (this.#items.length === 0) { + return; + } + + this.#bulkDeleteEnabled = true; + enableBulkDeleteButton.classList.add('d-none'); disableBulkDeleteButton.classList.remove('d-none'); + + selectAllContainer.classList.remove('d-none'); bulkDeleteButton.classList.remove('d-none'); - this.#element.querySelectorAll(checkboxSelector).forEach((checkbox) => { + this.getItemCheckboxes().forEach((checkbox) => { checkbox.classList.remove('d-none'); checkbox.checked = false; }); @@ -187,8 +215,9 @@ export default class BlockElement { bulkDeleteButton.classList.add('d-none'); bulkDeleteButton.disabled = true; enableBulkDeleteButton.classList.remove('d-none'); + selectAllContainer.classList.add('d-none'); - this.#element.querySelectorAll(checkboxSelector).forEach((checkbox) => { + this.getItemCheckboxes().forEach((checkbox) => { checkbox.classList.add('d-none'); checkbox.checked = false; }); @@ -200,7 +229,11 @@ export default class BlockElement { } const itemIds = []; - this.#element.querySelectorAll(checkboxSelector + ':checked').forEach((checkbox) => { + this.getItemCheckboxes().forEach((checkbox) => { + if (!checkbox.checked) { + return; + } + itemIds.push(checkbox.value); }); @@ -211,14 +244,53 @@ export default class BlockElement { /** * @param {HTMLElement} element */ - setupItem(element) { + async setupItem(element) { const itemElement = this.#baseFactory.block().item().element(this, element); + if (itemElement.getStatus() !== '0' && this.isBulkDeleteEnabled()) { + const checkbox = element.querySelector('input[data-action="bulk_select"][type="checkbox"]'); + checkbox?.classList?.remove('d-none'); + } + this.#element.querySelector('.no-items')?.remove(); - this.#items.push( - itemElement - ); + this.#items.push(itemElement); + + this.updateBulkDeleteButtonState(); + this.updateSelectAllState(); + } + + getItemCheckboxes() { + const checkboxSelector = '.sharing_cart_item:not([data-status="0"]) input[data-action="bulk_select"][type="checkbox"]'; + return this.#element.querySelectorAll(checkboxSelector); + } + + updateBulkDeleteButtonState() { + const bulkDeleteButton = this.#element.querySelector('#block_sharing_cart_bulk_delete_confirm'); + bulkDeleteButton.disabled = !Array.from(this.getItemCheckboxes()).some(checkbox => checkbox.checked); + } + + updateSelectAllState() { + const selectAllCheckbox = this.#element.querySelector('#select_all_box'); + const selectAllLabel = this.#element.querySelector('#select_all_label'); + + const itemCheckboxes = this.getItemCheckboxes(); + const allSelected = Array.from(itemCheckboxes).every(checkbox => checkbox.checked); + const someSelected = Array.from(itemCheckboxes).some(checkbox => checkbox.checked); + + const strPromise = allSelected ? + get_string('deselect_all', 'block_sharing_cart') : + get_string('select_all', 'block_sharing_cart'); + strPromise.then((str) => { + selectAllLabel.textContent = str; + }); + + selectAllCheckbox.checked = allSelected; + selectAllCheckbox.indeterminate = !allSelected && someSelected; + } + + isBulkDeleteEnabled() { + return this.#bulkDeleteEnabled; } /** @@ -325,6 +397,7 @@ export default class BlockElement { await this.removeItemElement(item); } + this.updateSelectAllState(); document.getElementById('block_sharing_cart_bulk_delete_confirm').disabled = true; }, @@ -472,7 +545,10 @@ export default class BlockElement { async renderItem(item) { const existingItemIndex = this.#items.findIndex((i) => i.getItemId() === item.id); const existingItem = this.#items[existingItemIndex] ?? false; - const oldElement = this.#element.querySelector('.sharing_cart_items .sharing_cart_item[data-itemid="' + item.id + '"]'); + const getOldElement = () => { + return this.#element.querySelector('.sharing_cart_items .sharing_cart_item[data-itemid="' + item.id + '"]'); + }; + const oldElement = getOldElement(); if (existingItem && oldElement) { const element = await this.#baseFactory.moodle().template().createElementFromFragment( 'block_sharing_cart', @@ -483,12 +559,18 @@ export default class BlockElement { } ); + // Early exit if the element has been removed from the DOM in between rendering and checking earlier. + if (getOldElement() !== oldElement) { + return; + } + this.#element.querySelector('.sharing_cart_items').replaceChild(element, oldElement); this.#items[existingItemIndex] = this.#baseFactory.block().item().element(this, element); - element.querySelectorAll('.sharing_cart_item').forEach((subItem) => { - this.setupItem(subItem); - }); + await this.setupItem(element); // test + for (const subItem of element.querySelectorAll('.sharing_cart_item')) { + await this.setupItem(subItem); + } return; } @@ -513,7 +595,7 @@ export default class BlockElement { ); this.#element.querySelector('.sharing_cart_items').prepend(element); - this.setupItem(element); + await this.setupItem(element); } /** diff --git a/amd/src/app/block/item/element.js b/amd/src/app/block/item/element.js index c251e2d..50ffc9e 100644 --- a/amd/src/app/block/item/element.js +++ b/amd/src/app/block/item/element.js @@ -77,11 +77,8 @@ export default class ItemElement { const checkbox = this.#element.querySelector('input[data-action="bulk_select"][type="checkbox"]'); checkbox?.addEventListener('click', () => { - const bulkDeleteButton = document.getElementById('block_sharing_cart_bulk_delete_confirm'); - - const blockSelector = '.block.block_sharing_cart'; - const checkboxSelector = blockSelector + ' .sharing_cart_item input[data-action="bulk_select"][type="checkbox"]'; - bulkDeleteButton.disabled = document.querySelectorAll(checkboxSelector + ':checked').length <= 0; + this.#blockElement.updateSelectAllState(); + this.#blockElement.updateBulkDeleteButtonState(); }); const actionsContainer = this.#element.querySelector(':scope > .item-body .sharing_cart_item_actions'); @@ -181,6 +178,10 @@ export default class ItemElement { return this.#element; } + getStatus() { + return this.#element.dataset.status; + } + /** * @return {String} */ diff --git a/amd/src/app/block/queue/element.js b/amd/src/app/block/queue/element.js index 4718209..a9fa1b6 100644 --- a/amd/src/app/block/queue/element.js +++ b/amd/src/app/block/queue/element.js @@ -99,6 +99,7 @@ export default class QueueElement { * @return {Promise} */ async loadQueue(showSpinner = false, token = {}) { + // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { token.abort = () => { reject(); diff --git a/block_sharing_cart.php b/block_sharing_cart.php index 04f0ef0..f87e2a0 100644 --- a/block_sharing_cart.php +++ b/block_sharing_cart.php @@ -53,7 +53,9 @@ public function get_content(): object|string 'run_now', 'atleast_one_course_module_must_be_included', 'no_course_modules_in_section', - 'no_course_modules_in_section_description' + 'no_course_modules_in_section_description', + 'select_all', + 'deselect_all', ], 'block_sharing_cart'); $this->page->requires->strings_for_js([ 'import', diff --git a/lang/da/block_sharing_cart.php b/lang/da/block_sharing_cart.php index 46548f1..fd963af 100644 --- a/lang/da/block_sharing_cart.php +++ b/lang/da/block_sharing_cart.php @@ -40,12 +40,16 @@ $string['legacy_section_info'] = 'Dette er en gammel sektion. Delingskurven kan ikke kopiere denne sektion, men de enkelte aktiviteter er stadig tilgængelige.'; $string['maybe_the_queue_is_stuck'] = 'Hvis du vil køre kopieringen nu, skal du klikke på knappen ovenfor.'; $string['drop_here'] = 'Slip her...'; +$string['original_course'] = 'Originalt kursus:'; $string['copy_this_course'] = 'Kopier dette kursus'; $string['bulk_delete'] = 'Slet flere'; $string['cancel_bulk_delete'] = 'Annuller'; $string['delete_marked_items'] = 'Slet valgte elementer'; +$string['select_all'] = 'Vælg alle'; +$string['deselect_all'] = 'Fravælg alle'; + $string['no_course_modules_in_section'] = 'Ingen kursusmoduler i denne sektion'; $string['no_course_modules_in_section_description'] = 'Denne sektion indeholder ikke nogen kursusmoduler, og du kan derfor ikke kopiere den.'; diff --git a/lang/en/block_sharing_cart.php b/lang/en/block_sharing_cart.php index 1e3c12e..8b2cdcd 100644 --- a/lang/en/block_sharing_cart.php +++ b/lang/en/block_sharing_cart.php @@ -40,12 +40,16 @@ $string['legacy_section_info'] = 'This is a legacy section. The sharing cart is unable to copy this section, but the individual activities are still available.'; $string['maybe_the_queue_is_stuck'] = 'If you would like to run the restore now, click the button above.'; $string['drop_here'] = 'Drop here...'; +$string['original_course'] = 'Original course:'; $string['copy_this_course'] = 'Copy this course'; $string['bulk_delete'] = 'Bulk delete'; $string['cancel_bulk_delete'] = 'Cancel'; $string['delete_marked_items'] = 'Delete marked items'; +$string['select_all'] = 'Select all'; +$string['deselect_all'] = 'Deselect all'; + $string['no_course_modules_in_section'] = 'No course modules in this section'; $string['no_course_modules_in_section_description'] = 'This section does not contain any course modules and you are therefore not able to copy it.'; @@ -62,16 +66,6 @@ $string['settings:show_copy_section_in_block'] = 'Show the "Copy section" in block'; $string['settings:show_copy_section_in_block_desc'] = 'Show the "Copy section" in the sharing cart block, underneath all modules/activities'; -// TODO: Implement the following?? -/* -$string['settings:workaround_qtypes'] = 'Workaround for question types'; -$string['settings:workaround_qtypes_desc'] = 'The workaround for question restore issue will be performed if its question type is checked. -When the questions to be restored already exist, however, those data look like inconsistent, -this workaround will try to make another duplicates instead of reusing existing data. -It may be useful for avoiding some restore errors, such as error_question_match_sub_missing_in_db.'; -$string['settings:show_copy_activity_in_block'] = 'Show the "Copy activity" in block'; -$string['settings:show_copy_activity_in_block_desc'] = 'Show the "Copy activity" in the sharing cart block, underneath all modules/activities - This is only available if the user has the capability to backup activities, but not the capability to manage/move activities'; -*/ // Privacy $string['privacy:metadata:sharing_cart_items:user_id'] = 'The user ID which the item belongs to'; diff --git a/templates/block/content.mustache b/templates/block/content.mustache index d326165..ab62e7d 100644 --- a/templates/block/content.mustache +++ b/templates/block/content.mustache @@ -17,21 +17,29 @@ {{#str}}items, block_sharing_cart{{/str}} - + {{#str}}cancel_bulk_delete, block_sharing_cart{{/str}} - + {{#str}}bulk_delete, block_sharing_cart{{/str}}
- {{#js}} - require(['block_sharing_cart/local/block'], function (component) { + require(['block_sharing_cart/local/block'], (component) => { component.init('block_sharing_cart', {{canBackupUserdata}}, {{canAnonymizeUserdata}}, {{showSharingCartBasket}}, {{courseContextId}}); }); {{/js}} diff --git a/version.php b/version.php index 58e49d2..c185f44 100644 --- a/version.php +++ b/version.php @@ -6,7 +6,7 @@ /** @var object $plugin */ $plugin->component = 'block_sharing_cart'; -$plugin->version = 2024081901; +$plugin->version = 2024101000; $plugin->requires = 2023042400; // Moodle 4.2.0 $plugin->release = '5.0, release 1'; $plugin->maturity = MATURITY_STABLE; From bede3b18a86c078cf4ac09e989fb3847ecf971da Mon Sep 17 00:00:00 2001 From: Halfdan Karlsen Monie Date: Wed, 9 Oct 2024 11:00:57 +0200 Subject: [PATCH 4/9] praxisdigital/moodle-opgaver#444 - Show original course fullname on hover --- classes/app/backup/handler.php | 34 +++++++++++++++++------- classes/app/item/entity.php | 12 +++++++++ classes/app/item/repository.php | 5 +++- classes/external/task/run_now.php | 18 +++++++++++++ db/install.xml | 1 + db/upgrade.php | 44 +++++++++++++++++++++++++++++++ templates/block/item.mustache | 4 ++- version.php | 2 +- 8 files changed, 108 insertions(+), 12 deletions(-) diff --git a/classes/app/backup/handler.php b/classes/app/backup/handler.php index 0fa687e..e159584 100644 --- a/classes/app/backup/handler.php +++ b/classes/app/backup/handler.php @@ -24,6 +24,20 @@ public function __construct(base_factory $base_factory) $this->base_factory = $base_factory; } + private function get_backup_info(\stored_file $file): object + { + /** + * @var \file_storage $fs + */ + $fs = get_file_storage(); + $file_path = $fs->get_file_system()->get_local_path_from_storedfile($file); + + /** @var object $info */ + $info = \backup_general_helper::get_backup_information_from_mbz($file_path); + + return $info; + } + public function backup_course_module( int $course_module_id, entity $root_item, @@ -53,18 +67,20 @@ public function backup_section(int $section_id, entity $root_item, array $settin return $this->queue_async_backup($backup_controller, $root_item, $settings); } + public function get_backup_course_info(\stored_file $file): array + { + $info = $this->get_backup_info($file); + + return [ + 'id' => $info->original_course_id, + 'fullname' => $info->original_course_fullname + ]; + } public function get_backup_item_tree(\stored_file $file): array { $tree = []; - /** - * @var \file_storage $fs - */ - $fs = get_file_storage(); - $file_path = $fs->get_file_system()->get_local_path_from_storedfile($file); - - /** @var object $info */ - $info = \backup_general_helper::get_backup_information_from_mbz($file_path); + $info = $this->get_backup_info($file); foreach ($info->sections as $section) { $tree[$section->sectionid] = (object)[ @@ -104,4 +120,4 @@ private function queue_async_backup( return $asynctask; } -} \ No newline at end of file +} diff --git a/classes/app/item/entity.php b/classes/app/item/entity.php index fa127f7..38da112 100644 --- a/classes/app/item/entity.php +++ b/classes/app/item/entity.php @@ -135,6 +135,17 @@ public function is_module(): bool return !$this->is_section(); } + public function get_original_course_fullname(): ?string + { + return $this->record['original_course_fullname'] ?? null; + } + + public function set_original_course_fullname(?string $value): self + { + $this->record['original_course_fullname'] = $value; + return $this; + } + public function to_array(): array { return [ @@ -147,6 +158,7 @@ public function to_array(): array 'name' => format_string($this->get_name()), 'status' => $this->get_status(), 'sortorder' => $this->get_sortorder(), + 'original_course_fullname' => $this->get_original_course_fullname(), 'timecreated' => $this->get_timecreated(), 'timemodified' => $this->get_timemodified(), ]; diff --git a/classes/app/item/repository.php b/classes/app/item/repository.php index cb5e3d1..144f19d 100644 --- a/classes/app/item/repository.php +++ b/classes/app/item/repository.php @@ -157,6 +157,9 @@ public function update_sharing_cart_item_with_backup_file(entity $root_item, \st $root_item->set_file_id($file->get_id()); $root_item->set_timemodified(time()); + $course_info = $this->base_factory->backup()->handler()->get_backup_course_info($file); + $root_item->set_original_course_fullname($course_info['fullname'] ?? null); + $this->update($root_item); if ($root_item->get_type() !== entity::TYPE_SECTION) { @@ -237,4 +240,4 @@ public function get_stored_file_by_item(entity $item): ?\stored_file ) )[0] ?? null; } -} \ No newline at end of file +} diff --git a/classes/external/task/run_now.php b/classes/external/task/run_now.php index aac7c4c..804a416 100644 --- a/classes/external/task/run_now.php +++ b/classes/external/task/run_now.php @@ -34,6 +34,24 @@ public static function execute( \context_user::instance($USER->id) ); + if (CLI_MAINTENANCE) { + throw new \Exception( + get_string('sitemaintenance', 'admin') + ); + } + + if (moodle_needs_upgrading()) { + throw new \Exception( + get_string('cliupgradepending', 'admin') + ); + } + + if (!get_config('core', 'cron_enabled')) { + throw new \Exception( + get_string('crondisabled', 'tool_task') + ); + } + $task = $DB->get_record( 'task_adhoc', [ diff --git a/db/install.xml b/db/install.xml index dd2cdd5..0090416 100644 --- a/db/install.xml +++ b/db/install.xml @@ -15,6 +15,7 @@ + diff --git a/db/upgrade.php b/db/upgrade.php index 2e78e2c..24e5116 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -10,6 +10,8 @@ function xmldb_block_sharing_cart_upgrade($oldversion = 0): bool $dbman = $DB->get_manager(); + $base_factory = \block_sharing_cart\app\factory::make(); + if ($oldversion < 2011111100) { $table = new xmldb_table('sharing_cart'); @@ -480,5 +482,47 @@ function xmldb_block_sharing_cart_upgrade($oldversion = 0): bool upgrade_block_savepoint(true, 2024072900, 'sharing_cart'); } + if ($oldversion < 2024101800) { + $xmldb_table = new xmldb_table('block_sharing_cart_items'); + + if (!$dbman->field_exists($xmldb_table, 'original_course_fullname')) { + $dbman->add_field( + $xmldb_table, + new xmldb_field( + 'original_course_fullname', XMLDB_TYPE_CHAR, 255, notnull: false + ) + ); + } + + $item_record_set = $DB->get_recordset('block_sharing_cart_items', [ + 'status' => \block_sharing_cart\app\item\entity::STATUS_BACKEDUP, + 'parent_item_id' => null + ]); + foreach ($item_record_set as $item) { + try { + /** + * @var \file_storage $fs + */ + $fs = get_file_storage(); + $file = $fs->get_file_by_id($item->file_id); + if (!$file) { + continue; + } + + $course_info = $base_factory->backup()->handler()->get_backup_course_info($file); + $item->original_course_fullname = $course_info['fullname'] ?? null; + + $DB->update_record( + 'block_sharing_cart_items', + $item + ); + } catch (\Exception) { + } + } + $item_record_set->close(); + + upgrade_block_savepoint(true, 2024101800, 'sharing_cart'); + } + return true; } diff --git a/templates/block/item.mustache b/templates/block/item.mustache index 841d887..2a1e6a8 100644 --- a/templates/block/item.mustache +++ b/templates/block/item.mustache @@ -2,7 +2,9 @@ {{#module_is_disabled_on_site}}title="{{#str}}module_is_disabled_on_site, block_sharing_cart{{/str}}"{{/module_is_disabled_on_site}} data-module_is_disabled_on_site="{{#module_is_disabled_on_site}}1{{/module_is_disabled_on_site}}{{^module_is_disabled_on_site}}0{{/module_is_disabled_on_site}}" data-status="{{status}}" - {{^is_module}}data-collapsed="true"{{/is_module}}> + {{^is_module}}data-collapsed="true"{{/is_module}} + {{#original_course_fullname}}title="{{#str}}original_course, block_sharing_cart{{/str}} {{.}}"{{/original_course_fullname}} +>
{{#is_root}} diff --git a/version.php b/version.php index c185f44..e7668d4 100644 --- a/version.php +++ b/version.php @@ -6,7 +6,7 @@ /** @var object $plugin */ $plugin->component = 'block_sharing_cart'; -$plugin->version = 2024101000; +$plugin->version = 2024101800; $plugin->requires = 2023042400; // Moodle 4.2.0 $plugin->release = '5.0, release 1'; $plugin->maturity = MATURITY_STABLE; From 14bd6f2bb5564db338cd96a4715cd537d3f8b4e8 Mon Sep 17 00:00:00 2001 From: Frederik Milling Pytlick Date: Fri, 18 Oct 2024 10:10:15 +0200 Subject: [PATCH 5/9] praxisdigital/moodle-opgaver#473 - Fixed issue with MSSQL --- README.md | 38 ++++++++++++++++----------------- classes/app/restore/handler.php | 4 ++-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 38edad7..6f15717 100644 --- a/README.md +++ b/README.md @@ -37,25 +37,25 @@ Change Log ---------- * 5.0, release 1 2024.08.05 - * Total refactor of the whole plugin: - * Improvements - * Simplified the database structure. - * Code is now much more readable and maintainable. - * All HTML have been moved to mustache templates. - * We now use the Moodle core backup and restore system for sections as well. This means that we can now - restore sections and keep related access restrictions. - * All ajax calls are now done using the Moodle core external functions. - * As everything is now done asynchronously, you should have a much better experience when using the - sharing cart. - Not having to reload the whole page all the time... - * Supports the filter_multilang as well now. - * Changes - * It is no longer possible to move single activities between sections in the sharing cart. - * All backups/restores are now done asynchronously. If you have a lot of adhoc tasks running on your site, - it's also possible to manually run them. - * Old sharing cart items - * Will be converted to the new format when you upgrade the plugin. - * You won't be able to restore these items all at once like before, but you can restore them one by one. - * Old sections will be marked as legacy with a yellow warning icon. + * Total refactor of the whole plugin: + * Improvements + * Simplified the database structure. + * Code is now much more readable and maintainable. + * All HTML have been moved to mustache templates. + * We now use the Moodle core backup and restore system for sections as well. This means that we can now + restore sections and keep related access restrictions. + * All ajax calls are now done using the Moodle core external functions. + * As everything is now done asynchronously, you should have a much better experience when using the + sharing cart. - Not having to reload the whole page all the time... + * Supports the filter_multilang as well now. + * Changes + * It is no longer possible to move single activities between sections in the sharing cart. + * All backups/restores are now done asynchronously. If you have a lot of adhoc tasks running on your site, + it's also possible to manually run them. + * Old sharing cart items + * Will be converted to the new format when you upgrade the plugin. + * You won't be able to restore these items all at once like before, but you can restore them one by one. + * Old sections will be marked as legacy with a yellow warning icon. * 4.4, release 4 2024.02.06 * Added an anonymize userdata checkbox to the confirm modal. * 4.4, release 3 2024.02.05 diff --git a/classes/app/restore/handler.php b/classes/app/restore/handler.php index 14ca76f..1d79887 100644 --- a/classes/app/restore/handler.php +++ b/classes/app/restore/handler.php @@ -50,7 +50,7 @@ private function queue_async_restore( entity $item, array $settings = [] ): asynchronous_restore_task { - $restore_controller->execute_precheck(); + $restore_controller->execute_precheck(true); $asynctask = new asynchronous_restore_task(); $asynctask->set_blocking(false); @@ -65,4 +65,4 @@ private function queue_async_restore( return $asynctask; } -} \ No newline at end of file +} From 8aad62a138ed0986920b107dda480db7a04d22a4 Mon Sep 17 00:00:00 2001 From: Frederik Milling Pytlick Date: Fri, 18 Oct 2024 14:16:57 +0200 Subject: [PATCH 6/9] praxisdigital/moodle-opgaver#444 - Made changes according to feedback --- amd/src/app/block/element.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amd/src/app/block/element.js b/amd/src/app/block/element.js index adb30c9..79c405d 100644 --- a/amd/src/app/block/element.js +++ b/amd/src/app/block/element.js @@ -567,7 +567,7 @@ export default class BlockElement { this.#element.querySelector('.sharing_cart_items').replaceChild(element, oldElement); this.#items[existingItemIndex] = this.#baseFactory.block().item().element(this, element); - await this.setupItem(element); // test + await this.setupItem(element); for (const subItem of element.querySelectorAll('.sharing_cart_item')) { await this.setupItem(subItem); } From 0a835cee46c6222ad9f69eae0c1144448588ea16 Mon Sep 17 00:00:00 2001 From: Frederik Milling Pytlick Date: Thu, 31 Oct 2024 13:40:07 +0100 Subject: [PATCH 7/9] praxisdigital/moodle-opgaver#503 - Made backup/restore tasks only have 1 attempt Refactored javascript & improved the reflection of the task status inside the block --- amd/build/app/block/element.min.js | 2 +- amd/build/app/block/element.min.js.map | 2 +- amd/build/app/block/item/element.min.js | 2 +- amd/build/app/block/item/element.min.js.map | 2 +- amd/src/app/block/element.js | 13 ++++-- amd/src/app/block/item/element.js | 45 +++++++++++++++------ classes/output/block/item.php | 2 +- classes/task/asynchronous_backup_task.php | 5 +++ classes/task/asynchronous_restore_task.php | 5 +++ lang/da/block_sharing_cart.php | 6 ++- lang/en/block_sharing_cart.php | 6 ++- templates/block/content.mustache | 5 ++- templates/block/item/icon.mustache | 5 ++- templates/block/queue/items.mustache | 12 +++++- 14 files changed, 81 insertions(+), 31 deletions(-) diff --git a/amd/build/app/block/element.min.js b/amd/build/app/block/element.min.js index ad20e44..c6b5163 100644 --- a/amd/build/app/block/element.min.js +++ b/amd/build/app/block/element.min.js @@ -1,3 +1,3 @@ -define("block_sharing_cart/app/block/element",["exports","../../lib/sortablejs","core/modal_factory","core/modal_events","core/str","core/ajax","core/notification"],(function(_exports,_sortablejs,_modal_factory,_modal_events,_str,_ajax,_notification){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classPrivateFieldInitSpec(obj,privateMap,value){!function(obj,privateCollection){if(privateCollection.has(obj))throw new TypeError("Cannot initialize the same private elements twice on an object")}(obj,privateMap),privateMap.set(obj,value)}function _classPrivateFieldGet(receiver,privateMap){return function(receiver,descriptor){if(descriptor.get)return descriptor.get.call(receiver);return descriptor.value}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"get"))}function _classPrivateFieldSet(receiver,privateMap,value){return function(receiver,descriptor,value){if(descriptor.set)descriptor.set.call(receiver,value);else{if(!descriptor.writable)throw new TypeError("attempted to set read only private field");descriptor.value=value}}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"set"),value),value}function _classExtractFieldDescriptor(receiver,privateMap,action){if(!privateMap.has(receiver))throw new TypeError("attempted to "+action+" private field on non-instance");return privateMap.get(receiver)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_sortablejs=_interopRequireDefault(_sortablejs),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_ajax=_interopRequireDefault(_ajax),_notification=_interopRequireDefault(_notification);var _baseFactory=new WeakMap,_element=new WeakMap,_course=new WeakMap,_queue=new WeakMap,_items=new WeakMap,_sortable=new WeakMap,_clipboardItem=new WeakMap,_canBackupUserdata=new WeakMap,_canAnonymizeUserdata=new WeakMap,_showSharingCartBasket=new WeakMap,_draggedCourseModuleId=new WeakMap,_draggedSectionId=new WeakMap,_bulkDeleteEnabled=new WeakMap;return _exports.default=class{constructor(baseFactory,element,canBackupUserdata,canAnonymizeUserdata,showSharingCartBasket){_classPrivateFieldInitSpec(this,_baseFactory,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_element,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_course,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_queue,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_items,{writable:!0,value:[]}),_classPrivateFieldInitSpec(this,_sortable,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_clipboardItem,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_canBackupUserdata,{writable:!0,value:!1}),_classPrivateFieldInitSpec(this,_canAnonymizeUserdata,{writable:!0,value:!1}),_classPrivateFieldInitSpec(this,_showSharingCartBasket,{writable:!0,value:!1}),_classPrivateFieldInitSpec(this,_draggedCourseModuleId,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_draggedSectionId,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_bulkDeleteEnabled,{writable:!0,value:!1}),_classPrivateFieldSet(this,_baseFactory,baseFactory),_classPrivateFieldSet(this,_element,element),_classPrivateFieldSet(this,_canBackupUserdata,canBackupUserdata),_classPrivateFieldSet(this,_canAnonymizeUserdata,canAnonymizeUserdata),_classPrivateFieldSet(this,_showSharingCartBasket,showSharingCartBasket)}addEventListeners(){return this.setupCourse(),this.setupQueue(),this.setupItems(),this.setupDragAndDrop(),this.setupBulkDelete(),{course:_classPrivateFieldGet(this,_course),queue:_classPrivateFieldGet(this,_queue),block:this}}setupCourse(){const course=document.querySelector(".course-content");_classPrivateFieldSet(this,_course,_classPrivateFieldGet(this,_baseFactory).block().course().element(this,course))}setupQueue(){const queue=document.querySelector(".sharing_cart_queue");_classPrivateFieldSet(this,_queue,_classPrivateFieldGet(this,_baseFactory).block().queue().element(this,queue))}async setupItems(){const items=_classPrivateFieldGet(this,_element).querySelectorAll(".sharing_cart_item");for(const element of items)await this.setupItem(element);_classPrivateFieldSet(this,_sortable,new _sortablejs.default(_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items"),{dataIdAttr:"data-itemid",onUpdate:()=>{_ajax.default.call([{methodname:"block_sharing_cart_reorder_sharing_cart_items",args:{item_ids:_classPrivateFieldGet(this,_sortable).toArray()},fail:data=>{_notification.default.exception(data)}}])}}))}setupDragAndDrop(){const dropZone=_classPrivateFieldGet(this,_element);dropZone.addEventListener("dragover",(e=>{(_classPrivateFieldGet(this,_draggedSectionId)||_classPrivateFieldGet(this,_draggedCourseModuleId))&&(e.preventDefault(),e.stopPropagation())})),dropZone.addEventListener("dragleave",(e=>{(_classPrivateFieldGet(this,_draggedSectionId)||_classPrivateFieldGet(this,_draggedCourseModuleId))&&(e.preventDefault(),e.stopPropagation())})),dropZone.addEventListener("drop",(async e=>{(_classPrivateFieldGet(this,_draggedSectionId)||_classPrivateFieldGet(this,_draggedCourseModuleId))&&(e.preventDefault(),e.stopPropagation(),_classPrivateFieldGet(this,_draggedSectionId)?await this.addSectionBackupToSharingCart(_classPrivateFieldGet(this,_draggedSectionId)):_classPrivateFieldGet(this,_draggedCourseModuleId)&&await this.addCourseModuleBackupToSharingCart(_classPrivateFieldGet(this,_draggedCourseModuleId)))}))}setupBulkDelete(){const enableBulkDeleteButton=_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_bulk_delete"),disableBulkDeleteButton=_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_cancel_bulk_delete"),bulkDeleteButton=_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_bulk_delete_confirm"),selectAllContainer=_classPrivateFieldGet(this,_element).querySelector("#select_all_container");_classPrivateFieldGet(this,_element).querySelector("#select_all_box").addEventListener("click",(async()=>{const itemCheckboxes=this.getItemCheckboxes(),allSelected=Array.from(itemCheckboxes).every((checkbox=>checkbox.checked));itemCheckboxes.forEach((checkbox=>{checkbox.checked=!allSelected})),itemCheckboxes.forEach((checkbox=>checkbox.addEventListener("change",(async()=>{this.updateSelectAllState()})))),this.updateSelectAllState(),this.updateBulkDeleteButtonState()})),enableBulkDeleteButton.addEventListener("click",(()=>{0!==_classPrivateFieldGet(this,_items).length&&(_classPrivateFieldSet(this,_bulkDeleteEnabled,!0),enableBulkDeleteButton.classList.add("d-none"),disableBulkDeleteButton.classList.remove("d-none"),selectAllContainer.classList.remove("d-none"),bulkDeleteButton.classList.remove("d-none"),this.getItemCheckboxes().forEach((checkbox=>{checkbox.classList.remove("d-none"),checkbox.checked=!1})))})),disableBulkDeleteButton.addEventListener("click",(()=>{disableBulkDeleteButton.classList.add("d-none"),bulkDeleteButton.classList.add("d-none"),bulkDeleteButton.disabled=!0,enableBulkDeleteButton.classList.remove("d-none"),selectAllContainer.classList.add("d-none"),this.getItemCheckboxes().forEach((checkbox=>{checkbox.classList.add("d-none"),checkbox.checked=!1}))})),bulkDeleteButton.addEventListener("click",(async()=>{if(bulkDeleteButton.disabled)return;const itemIds=[];this.getItemCheckboxes().forEach((checkbox=>{checkbox.checked&&itemIds.push(checkbox.value)})),await this.confirmDeleteItems(itemIds)}))}async setupItem(element){var _classPrivateFieldGet2;const itemElement=_classPrivateFieldGet(this,_baseFactory).block().item().element(this,element);if("0"!==itemElement.getStatus()&&this.isBulkDeleteEnabled()){var _checkbox$classList;const checkbox=element.querySelector('input[data-action="bulk_select"][type="checkbox"]');null==checkbox||null===(_checkbox$classList=checkbox.classList)||void 0===_checkbox$classList||_checkbox$classList.remove("d-none")}null===(_classPrivateFieldGet2=_classPrivateFieldGet(this,_element).querySelector(".no-items"))||void 0===_classPrivateFieldGet2||_classPrivateFieldGet2.remove(),_classPrivateFieldGet(this,_items).push(itemElement),this.updateBulkDeleteButtonState(),this.updateSelectAllState()}getItemCheckboxes(){return _classPrivateFieldGet(this,_element).querySelectorAll('.sharing_cart_item:not([data-status="0"]) input[data-action="bulk_select"][type="checkbox"]')}updateBulkDeleteButtonState(){_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_bulk_delete_confirm").disabled=!Array.from(this.getItemCheckboxes()).some((checkbox=>checkbox.checked))}updateSelectAllState(){const selectAllCheckbox=_classPrivateFieldGet(this,_element).querySelector("#select_all_box"),selectAllLabel=_classPrivateFieldGet(this,_element).querySelector("#select_all_label"),itemCheckboxes=this.getItemCheckboxes(),allSelected=Array.from(itemCheckboxes).every((checkbox=>checkbox.checked)),someSelected=Array.from(itemCheckboxes).some((checkbox=>checkbox.checked));(allSelected?(0,_str.get_string)("deselect_all","block_sharing_cart"):(0,_str.get_string)("select_all","block_sharing_cart")).then((str=>{selectAllLabel.textContent=str})),selectAllCheckbox.checked=allSelected,selectAllCheckbox.indeterminate=!allSelected&&someSelected}isBulkDeleteEnabled(){return _classPrivateFieldGet(this,_bulkDeleteEnabled)}async setClipboard(item){_classPrivateFieldSet(this,_clipboardItem,item),await _classPrivateFieldGet(this,_course).setClipboard(item)}clearClipboard(){_classPrivateFieldSet(this,_clipboardItem,null)}setDraggedSectionId(id){_classPrivateFieldSet(this,_draggedSectionId,id)}setDraggedCourseModuleId(id){_classPrivateFieldSet(this,_draggedCourseModuleId,id)}async removeItemElement(item){var _classPrivateFieldGet4;item.getItemChildrenRecursively().forEach((childItem=>{var _classPrivateFieldGet3;const index=_classPrivateFieldGet(this,_items).findIndex((i=>i.getItemId()===Number.parseInt(childItem.dataset.itemid)));-1!==index&&(_classPrivateFieldGet(this,_items)[index].getItemId()===(null===(_classPrivateFieldGet3=_classPrivateFieldGet(this,_clipboardItem))||void 0===_classPrivateFieldGet3?void 0:_classPrivateFieldGet3.getItemId())&&_classPrivateFieldGet(this,_course).clearClipboard(),_classPrivateFieldGet(this,_items).splice(index,1),childItem.remove())}));const index=_classPrivateFieldGet(this,_items).findIndex((i=>i.getItemId()===item.getItemId()));_classPrivateFieldGet(this,_items)[index].getItemId()===(null===(_classPrivateFieldGet4=_classPrivateFieldGet(this,_clipboardItem))||void 0===_classPrivateFieldGet4?void 0:_classPrivateFieldGet4.getItemId())&&_classPrivateFieldGet(this,_course).clearClipboard(),_classPrivateFieldGet(this,_items).splice(index,1),item.remove(),0===_classPrivateFieldGet(this,_items).length&&(_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items").innerHTML=await(0,_str.get_string)("no_items","block_sharing_cart"))}deleteItem(item){_ajax.default.call([{methodname:"block_sharing_cart_delete_item_from_sharing_cart",args:{item_id:item.getItemId()},done:async deleted=>{deleted?await this.removeItemElement(item):await _notification.default.alert("Failed to delete item")},fail:data=>{_notification.default.exception(data)}}])}deleteItems(itemIds){itemIds=itemIds.map((id=>Number.parseInt(id))),_ajax.default.call([{methodname:"block_sharing_cart_delete_items_from_sharing_cart",args:{item_ids:itemIds},done:async deletedItemIds=>{const items=_classPrivateFieldGet(this,_items).filter((i=>itemIds.includes(i.getItemId())));for(const item of items){deletedItemIds.includes(item.getItemId())?await this.removeItemElement(item):_notification.default.alert('Failed to delete item: "'+item.getItemName()+'"')}this.updateSelectAllState(),document.getElementById("block_sharing_cart_bulk_delete_confirm").disabled=!0},fail:data=>{_notification.default.exception(data)}}])}getElement(){return _classPrivateFieldGet(this,_element)}async createBackupItemToSharingCartModal(itemName,onSave){const strings=await(0,_str.get_strings)([{key:"backup_item",component:"block_sharing_cart"},{key:"into_sharing_cart",component:"block_sharing_cart"},{key:"backup",component:"block_sharing_cart"},{key:"cancel",component:"core"}]),{html:html,js:js}=await _classPrivateFieldGet(this,_baseFactory).moodle().template().renderTemplate("block_sharing_cart/modal/backup_to_sharing_cart_modal_body",{show_user_data_backup:_classPrivateFieldGet(this,_canBackupUserdata),show_anonymize_user_data:_classPrivateFieldGet(this,_canBackupUserdata)&&_classPrivateFieldGet(this,_canAnonymizeUserdata)}),modal=await _modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:strings[0]+': "'+itemName.slice(0,50).trim()+'" '+strings[1],body:html,buttons:{save:strings[2],cancel:strings[3]},removeOnClose:!0});return modal.getRoot().on(_modal_events.default.shown,(()=>_classPrivateFieldGet(this,_baseFactory).moodle().template().runTemplateJS(js))),modal.getRoot().on(_modal_events.default.save,(()=>{var _modalUserdataCheckbo,_modalAnonymizeCheckb;const modalUserdataCheckbox=document.getElementById("modal-userdata-checkbox"),modalAnonymizeCheckbox=document.getElementById("modal-anonymize-checkbox");onSave({users:null!==(_modalUserdataCheckbo=null==modalUserdataCheckbox?void 0:modalUserdataCheckbox.checked)&&void 0!==_modalUserdataCheckbo&&_modalUserdataCheckbo,anonymize:null!==(_modalAnonymizeCheckb=null==modalAnonymizeCheckbox?void 0:modalAnonymizeCheckbox.checked)&&void 0!==_modalAnonymizeCheckb&&_modalAnonymizeCheckb})})),modal}async addSectionBackupToSharingCart(sectionId){const sectionName=_classPrivateFieldGet(this,_course).getSectionName(sectionId);if(0===_classPrivateFieldGet(this,_course).getSectionCourseModules(sectionId).length){const strings=await(0,_str.get_strings)([{key:"no_course_modules_in_section",component:"block_sharing_cart"},{key:"no_course_modules_in_section_description",component:"block_sharing_cart"}]);return void await _notification.default.alert(strings[0],strings[1])}const modal=await this.createBackupItemToSharingCartModal(sectionName,(settings=>{_ajax.default.call([{methodname:"block_sharing_cart_backup_section_into_sharing_cart",args:{section_id:sectionId,settings:settings},done:async data=>{await this.renderItem(data)},fail:data=>{_notification.default.exception(data)}}])}));await modal.show()}async addCourseModuleBackupToSharingCart(courseModuleId){const courseModuleName=_classPrivateFieldGet(this,_course).getCourseModuleName(courseModuleId),modal=await this.createBackupItemToSharingCartModal(courseModuleName,(settings=>{_ajax.default.call([{methodname:"block_sharing_cart_backup_course_module_into_sharing_cart",args:{course_module_id:courseModuleId,settings:settings},done:async data=>{await this.renderItem(data)},fail:data=>{_notification.default.exception(data)}}])}));await modal.show()}async renderItem(item){var _classPrivateFieldGet5,_item$task_id;const existingItemIndex=_classPrivateFieldGet(this,_items).findIndex((i=>i.getItemId()===item.id)),existingItem=null!==(_classPrivateFieldGet5=_classPrivateFieldGet(this,_items)[existingItemIndex])&&void 0!==_classPrivateFieldGet5&&_classPrivateFieldGet5,getOldElement=()=>_classPrivateFieldGet(this,_element).querySelector('.sharing_cart_items .sharing_cart_item[data-itemid="'+item.id+'"]'),oldElement=getOldElement();if(existingItem&&oldElement){const element=await _classPrivateFieldGet(this,_baseFactory).moodle().template().createElementFromFragment("block_sharing_cart","item",1,{item_id:item.id});if(getOldElement()!==oldElement)return;_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items").replaceChild(element,oldElement),_classPrivateFieldGet(this,_items)[existingItemIndex]=_classPrivateFieldGet(this,_baseFactory).block().item().element(this,element),await this.setupItem(element);for(const subItem of element.querySelectorAll(".sharing_cart_item"))await this.setupItem(subItem);return}const element=await _classPrivateFieldGet(this,_baseFactory).moodle().template().createElementFromTemplate("block_sharing_cart/block/item",{id:item.id,name:item.name,type:item.type,status:0,old_instance_id:item.old_instance_id,status_awaiting:!0,has_run_now:!0,task_id:null!==(_item$task_id=item.task_id)&&void 0!==_item$task_id?_item$task_id:null,status_finished:!1,status_failed:!1,is_module:"section"!==item.type,is_section:"section"===item.type,is_root:!0});_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items").prepend(element),await this.setupItem(element)}importItem(item,sectionId,modal){_classPrivateFieldGet(this,_course).clearClipboard();const courseModuleIds=[];if(modal.querySelectorAll('input[type="checkbox"][data-type="coursemodule"]:checked').forEach((checkbox=>{courseModuleIds.push(checkbox.dataset.id)})),item.isSection()&&0===courseModuleIds.length)return modal.querySelectorAll(".form-check-input").forEach((async item=>{item.setCustomValidity(await(0,_str.get_string)("atleast_one_course_module_must_be_included","block_sharing_cart")),item.reportValidity()})),!1;item.isModule()&&courseModuleIds.push(item.getItemOldInstanceId()),_ajax.default.call([{methodname:"block_sharing_cart_restore_item_from_sharing_cart_into_section",args:{item_id:item.getItemId(),section_id:sectionId,course_modules_to_include:courseModuleIds},done:async success=>{success&&await _classPrivateFieldGet(this,_queue).loadQueue(!0)},fail:data=>{_notification.default.exception(data)}}])}async confirmImportBackupFromSharingCart(item,sectionId,e){e.preventDefault(),e.stopPropagation();const strings=await(0,_str.get_strings)([{key:"copy_item",component:"block_sharing_cart"},{key:"into_section",component:"block_sharing_cart"},{key:"import",component:"core"},{key:"cancel",component:"core"}]),sectionName=_classPrivateFieldGet(this,_course).getSectionName(sectionId),{html:html,js:js}=await _classPrivateFieldGet(this,_baseFactory).moodle().template().renderFragment("block_sharing_cart","item_restore_form",1,{item_id:item.getItemId()}),modal=await _modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:strings[0]+': "'+item.getItemName().slice(0,50).trim()+'" '+strings[1]+': "'+sectionName.slice(0,50).trim()+'"',body:html,buttons:{save:strings[2],cancel:strings[3]},removeOnClose:!0});modal.getRoot().on(_modal_events.default.shown,(()=>_classPrivateFieldGet(this,_baseFactory).moodle().template().runTemplateJS(js))),modal.getRoot().on(_modal_events.default.save,this.importItem.bind(this,item,sectionId,modal.getRoot()[0])),await modal.show()}async confirmDeleteItems(itemIds){const strings=await(0,_str.get_strings)([{key:"delete_items",component:"block_sharing_cart"},{key:"confirm_delete_items",component:"block_sharing_cart"},{key:"delete",component:"core"},{key:"cancel",component:"core"}]),modal=await _modal_factory.default.create({type:_modal_factory.default.types.DELETE_CANCEL,title:strings[0],body:strings[1],buttons:{delete:strings[2],cancel:strings[3]},removeOnClose:!0});modal.getRoot().on(_modal_events.default.delete,this.deleteItems.bind(this,itemIds)),await modal.show()}},_exports.default})); +define("block_sharing_cart/app/block/element",["exports","../../lib/sortablejs","core/modal_factory","core/modal_events","core/str","core/ajax","core/notification"],(function(_exports,_sortablejs,_modal_factory,_modal_events,_str,_ajax,_notification){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classPrivateFieldInitSpec(obj,privateMap,value){!function(obj,privateCollection){if(privateCollection.has(obj))throw new TypeError("Cannot initialize the same private elements twice on an object")}(obj,privateMap),privateMap.set(obj,value)}function _classPrivateFieldGet(receiver,privateMap){return function(receiver,descriptor){if(descriptor.get)return descriptor.get.call(receiver);return descriptor.value}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"get"))}function _classPrivateFieldSet(receiver,privateMap,value){return function(receiver,descriptor,value){if(descriptor.set)descriptor.set.call(receiver,value);else{if(!descriptor.writable)throw new TypeError("attempted to set read only private field");descriptor.value=value}}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"set"),value),value}function _classExtractFieldDescriptor(receiver,privateMap,action){if(!privateMap.has(receiver))throw new TypeError("attempted to "+action+" private field on non-instance");return privateMap.get(receiver)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_sortablejs=_interopRequireDefault(_sortablejs),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_ajax=_interopRequireDefault(_ajax),_notification=_interopRequireDefault(_notification);var _baseFactory=new WeakMap,_element=new WeakMap,_course=new WeakMap,_queue=new WeakMap,_items=new WeakMap,_sortable=new WeakMap,_clipboardItem=new WeakMap,_canBackupUserdata=new WeakMap,_canAnonymizeUserdata=new WeakMap,_showSharingCartBasket=new WeakMap,_draggedCourseModuleId=new WeakMap,_draggedSectionId=new WeakMap,_bulkDeleteEnabled=new WeakMap;return _exports.default=class{constructor(baseFactory,element,canBackupUserdata,canAnonymizeUserdata,showSharingCartBasket){_classPrivateFieldInitSpec(this,_baseFactory,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_element,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_course,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_queue,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_items,{writable:!0,value:[]}),_classPrivateFieldInitSpec(this,_sortable,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_clipboardItem,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_canBackupUserdata,{writable:!0,value:!1}),_classPrivateFieldInitSpec(this,_canAnonymizeUserdata,{writable:!0,value:!1}),_classPrivateFieldInitSpec(this,_showSharingCartBasket,{writable:!0,value:!1}),_classPrivateFieldInitSpec(this,_draggedCourseModuleId,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_draggedSectionId,{writable:!0,value:null}),_classPrivateFieldInitSpec(this,_bulkDeleteEnabled,{writable:!0,value:!1}),_classPrivateFieldSet(this,_baseFactory,baseFactory),_classPrivateFieldSet(this,_element,element),_classPrivateFieldSet(this,_canBackupUserdata,canBackupUserdata),_classPrivateFieldSet(this,_canAnonymizeUserdata,canAnonymizeUserdata),_classPrivateFieldSet(this,_showSharingCartBasket,showSharingCartBasket)}addEventListeners(){return this.setupCourse(),this.setupQueue(),this.setupItems(),this.setupDragAndDrop(),this.setupBulkDelete(),{course:_classPrivateFieldGet(this,_course),queue:_classPrivateFieldGet(this,_queue),block:this}}setupCourse(){const course=document.querySelector(".course-content");_classPrivateFieldSet(this,_course,_classPrivateFieldGet(this,_baseFactory).block().course().element(this,course))}setupQueue(){const queue=document.querySelector(".sharing_cart_queue");_classPrivateFieldSet(this,_queue,_classPrivateFieldGet(this,_baseFactory).block().queue().element(this,queue))}async setupItems(){const items=_classPrivateFieldGet(this,_element).querySelectorAll(".sharing_cart_item");for(const element of items)await this.setupItem(element);_classPrivateFieldSet(this,_sortable,new _sortablejs.default(_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items"),{dataIdAttr:"data-itemid",onUpdate:()=>{_ajax.default.call([{methodname:"block_sharing_cart_reorder_sharing_cart_items",args:{item_ids:_classPrivateFieldGet(this,_sortable).toArray()},fail:data=>{_notification.default.exception(data)}}])}}))}setupDragAndDrop(){const dropZone=_classPrivateFieldGet(this,_element);dropZone.addEventListener("dragover",(e=>{(_classPrivateFieldGet(this,_draggedSectionId)||_classPrivateFieldGet(this,_draggedCourseModuleId))&&(e.preventDefault(),e.stopPropagation())})),dropZone.addEventListener("dragleave",(e=>{(_classPrivateFieldGet(this,_draggedSectionId)||_classPrivateFieldGet(this,_draggedCourseModuleId))&&(e.preventDefault(),e.stopPropagation())})),dropZone.addEventListener("drop",(async e=>{(_classPrivateFieldGet(this,_draggedSectionId)||_classPrivateFieldGet(this,_draggedCourseModuleId))&&(e.preventDefault(),e.stopPropagation(),_classPrivateFieldGet(this,_draggedSectionId)?await this.addSectionBackupToSharingCart(_classPrivateFieldGet(this,_draggedSectionId)):_classPrivateFieldGet(this,_draggedCourseModuleId)&&await this.addCourseModuleBackupToSharingCart(_classPrivateFieldGet(this,_draggedCourseModuleId)))}))}setupBulkDelete(){const enableBulkDeleteButton=_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_bulk_delete"),disableBulkDeleteButton=_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_cancel_bulk_delete"),bulkDeleteButton=_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_bulk_delete_confirm"),selectAllContainer=_classPrivateFieldGet(this,_element).querySelector("#select_all_container");_classPrivateFieldGet(this,_element).querySelector("#select_all_box").addEventListener("click",(async()=>{const itemCheckboxes=this.getItemCheckboxes(),allSelected=Array.from(itemCheckboxes).every((checkbox=>checkbox.checked));itemCheckboxes.forEach((checkbox=>{checkbox.checked=!allSelected})),itemCheckboxes.forEach((checkbox=>checkbox.addEventListener("change",(async()=>{this.updateSelectAllState()})))),this.updateSelectAllState(),this.updateBulkDeleteButtonState()})),enableBulkDeleteButton.addEventListener("click",(()=>{0!==_classPrivateFieldGet(this,_items).length&&(_classPrivateFieldSet(this,_bulkDeleteEnabled,!0),enableBulkDeleteButton.classList.add("d-none"),disableBulkDeleteButton.classList.remove("d-none"),selectAllContainer.classList.remove("d-none"),bulkDeleteButton.classList.remove("d-none"),this.getItemCheckboxes().forEach((checkbox=>{checkbox.classList.remove("d-none"),checkbox.checked=!1})))})),disableBulkDeleteButton.addEventListener("click",(()=>{disableBulkDeleteButton.classList.add("d-none"),bulkDeleteButton.classList.add("d-none"),bulkDeleteButton.disabled=!0,enableBulkDeleteButton.classList.remove("d-none"),selectAllContainer.classList.add("d-none"),this.getItemCheckboxes().forEach((checkbox=>{checkbox.classList.add("d-none"),checkbox.checked=!1}))})),bulkDeleteButton.addEventListener("click",(async()=>{if(bulkDeleteButton.disabled)return;const itemIds=[];this.getItemCheckboxes().forEach((checkbox=>{checkbox.checked&&itemIds.push(checkbox.value)})),await this.confirmDeleteItems(itemIds)}))}async setupItem(element){const itemElement=_classPrivateFieldGet(this,_baseFactory).block().item().element(this,element);if("0"!==itemElement.getStatus()&&this.isBulkDeleteEnabled()){var _checkbox$classList;const checkbox=element.querySelector('input[data-action="bulk_select"][type="checkbox"]');null==checkbox||null===(_checkbox$classList=checkbox.classList)||void 0===_checkbox$classList||_checkbox$classList.remove("d-none")}_classPrivateFieldGet(this,_element).querySelector(".no-items").classList.add("d-none");const existingItemIndex=_classPrivateFieldGet(this,_items).findIndex((i=>i.getItemId()===itemElement.getItemId()));-1!==existingItemIndex?_classPrivateFieldGet(this,_items)[existingItemIndex]=itemElement:_classPrivateFieldGet(this,_items).push(itemElement),this.updateBulkDeleteButtonState(),this.updateSelectAllState()}getItemCheckboxes(){return _classPrivateFieldGet(this,_element).querySelectorAll('.sharing_cart_item:not([data-status="0"]) input[data-action="bulk_select"][type="checkbox"]')}updateBulkDeleteButtonState(){_classPrivateFieldGet(this,_element).querySelector("#block_sharing_cart_bulk_delete_confirm").disabled=!Array.from(this.getItemCheckboxes()).some((checkbox=>checkbox.checked))}updateSelectAllState(){const selectAllCheckbox=_classPrivateFieldGet(this,_element).querySelector("#select_all_box"),selectAllLabel=_classPrivateFieldGet(this,_element).querySelector("#select_all_label"),itemCheckboxes=this.getItemCheckboxes(),allSelected=Array.from(itemCheckboxes).every((checkbox=>checkbox.checked)),someSelected=Array.from(itemCheckboxes).some((checkbox=>checkbox.checked));(allSelected?(0,_str.get_string)("deselect_all","block_sharing_cart"):(0,_str.get_string)("select_all","block_sharing_cart")).then((str=>{selectAllLabel.textContent=str})),selectAllCheckbox.checked=allSelected,selectAllCheckbox.indeterminate=!allSelected&&someSelected}isBulkDeleteEnabled(){return _classPrivateFieldGet(this,_bulkDeleteEnabled)}async setClipboard(item){_classPrivateFieldSet(this,_clipboardItem,item),await _classPrivateFieldGet(this,_course).setClipboard(item)}clearClipboard(){_classPrivateFieldSet(this,_clipboardItem,null)}setDraggedSectionId(id){_classPrivateFieldSet(this,_draggedSectionId,id)}setDraggedCourseModuleId(id){_classPrivateFieldSet(this,_draggedCourseModuleId,id)}async removeItemElement(item){var _classPrivateFieldGet3;item.getItemChildrenRecursively().forEach((childItem=>{var _classPrivateFieldGet2;const index=_classPrivateFieldGet(this,_items).findIndex((i=>i.getItemId()===Number.parseInt(childItem.dataset.itemid)));-1!==index&&(_classPrivateFieldGet(this,_items)[index].getItemId()===(null===(_classPrivateFieldGet2=_classPrivateFieldGet(this,_clipboardItem))||void 0===_classPrivateFieldGet2?void 0:_classPrivateFieldGet2.getItemId())&&_classPrivateFieldGet(this,_course).clearClipboard(),_classPrivateFieldGet(this,_items).splice(index,1),childItem.remove())}));const index=_classPrivateFieldGet(this,_items).findIndex((i=>i.getItemId()===item.getItemId()));_classPrivateFieldGet(this,_items)[index].getItemId()===(null===(_classPrivateFieldGet3=_classPrivateFieldGet(this,_clipboardItem))||void 0===_classPrivateFieldGet3?void 0:_classPrivateFieldGet3.getItemId())&&_classPrivateFieldGet(this,_course).clearClipboard(),_classPrivateFieldGet(this,_items).splice(index,1),item.remove(),0===_classPrivateFieldGet(this,_items).length&&_classPrivateFieldGet(this,_element).querySelector(".no-items").classList.remove("d-none")}deleteItem(item){_ajax.default.call([{methodname:"block_sharing_cart_delete_item_from_sharing_cart",args:{item_id:item.getItemId()},done:async deleted=>{deleted?(await this.removeItemElement(item),this.updateSelectAllState()):await _notification.default.alert("Failed to delete item")},fail:data=>{_notification.default.exception(data)}}])}deleteItems(itemIds){itemIds=itemIds.map((id=>Number.parseInt(id))),_ajax.default.call([{methodname:"block_sharing_cart_delete_items_from_sharing_cart",args:{item_ids:itemIds},done:async deletedItemIds=>{const items=_classPrivateFieldGet(this,_items).filter((i=>itemIds.includes(i.getItemId())));for(const item of items){deletedItemIds.includes(item.getItemId())?await this.removeItemElement(item):_notification.default.alert('Failed to delete item: "'+item.getItemName()+'"')}this.updateSelectAllState(),document.getElementById("block_sharing_cart_bulk_delete_confirm").disabled=!0},fail:data=>{_notification.default.exception(data)}}])}getElement(){return _classPrivateFieldGet(this,_element)}async createBackupItemToSharingCartModal(itemName,onSave){const strings=await(0,_str.get_strings)([{key:"backup_item",component:"block_sharing_cart"},{key:"into_sharing_cart",component:"block_sharing_cart"},{key:"backup",component:"block_sharing_cart"},{key:"cancel",component:"core"}]),{html:html,js:js}=await _classPrivateFieldGet(this,_baseFactory).moodle().template().renderTemplate("block_sharing_cart/modal/backup_to_sharing_cart_modal_body",{show_user_data_backup:_classPrivateFieldGet(this,_canBackupUserdata),show_anonymize_user_data:_classPrivateFieldGet(this,_canBackupUserdata)&&_classPrivateFieldGet(this,_canAnonymizeUserdata)}),modal=await _modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:strings[0]+': "'+itemName.slice(0,50).trim()+'" '+strings[1],body:html,buttons:{save:strings[2],cancel:strings[3]},removeOnClose:!0});return modal.getRoot().on(_modal_events.default.shown,(()=>_classPrivateFieldGet(this,_baseFactory).moodle().template().runTemplateJS(js))),modal.getRoot().on(_modal_events.default.save,(()=>{var _modalUserdataCheckbo,_modalAnonymizeCheckb;const modalUserdataCheckbox=document.getElementById("modal-userdata-checkbox"),modalAnonymizeCheckbox=document.getElementById("modal-anonymize-checkbox");onSave({users:null!==(_modalUserdataCheckbo=null==modalUserdataCheckbox?void 0:modalUserdataCheckbox.checked)&&void 0!==_modalUserdataCheckbo&&_modalUserdataCheckbo,anonymize:null!==(_modalAnonymizeCheckb=null==modalAnonymizeCheckbox?void 0:modalAnonymizeCheckbox.checked)&&void 0!==_modalAnonymizeCheckb&&_modalAnonymizeCheckb})})),modal}async addSectionBackupToSharingCart(sectionId){const sectionName=_classPrivateFieldGet(this,_course).getSectionName(sectionId);if(0===_classPrivateFieldGet(this,_course).getSectionCourseModules(sectionId).length){const strings=await(0,_str.get_strings)([{key:"no_course_modules_in_section",component:"block_sharing_cart"},{key:"no_course_modules_in_section_description",component:"block_sharing_cart"}]);return void await _notification.default.alert(strings[0],strings[1])}const modal=await this.createBackupItemToSharingCartModal(sectionName,(settings=>{_ajax.default.call([{methodname:"block_sharing_cart_backup_section_into_sharing_cart",args:{section_id:sectionId,settings:settings},done:async data=>{await this.renderItem(data)},fail:data=>{_notification.default.exception(data)}}])}));await modal.show()}async addCourseModuleBackupToSharingCart(courseModuleId){const courseModuleName=_classPrivateFieldGet(this,_course).getCourseModuleName(courseModuleId),modal=await this.createBackupItemToSharingCartModal(courseModuleName,(settings=>{_ajax.default.call([{methodname:"block_sharing_cart_backup_course_module_into_sharing_cart",args:{course_module_id:courseModuleId,settings:settings},done:async data=>{await this.renderItem(data)},fail:data=>{_notification.default.exception(data)}}])}));await modal.show()}async renderItem(item){var _classPrivateFieldGet4,_item$task_id;const existingItemIndex=_classPrivateFieldGet(this,_items).findIndex((i=>i.getItemId()===item.id)),existingItem=null!==(_classPrivateFieldGet4=_classPrivateFieldGet(this,_items)[existingItemIndex])&&void 0!==_classPrivateFieldGet4&&_classPrivateFieldGet4,getOldElement=()=>_classPrivateFieldGet(this,_element).querySelector('.sharing_cart_items .sharing_cart_item[data-itemid="'+item.id+'"]'),oldElement=getOldElement();if(existingItem&&oldElement){const element=await _classPrivateFieldGet(this,_baseFactory).moodle().template().createElementFromFragment("block_sharing_cart","item",1,{item_id:item.id});if(getOldElement()!==oldElement)return;_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items").replaceChild(element,oldElement),_classPrivateFieldGet(this,_items)[existingItemIndex]=_classPrivateFieldGet(this,_baseFactory).block().item().element(this,element),await this.setupItem(element);for(const subItem of element.querySelectorAll(".sharing_cart_item"))await this.setupItem(subItem);return}const element=await _classPrivateFieldGet(this,_baseFactory).moodle().template().createElementFromTemplate("block_sharing_cart/block/item",{id:item.id,name:item.name,type:item.type,status:0,old_instance_id:item.old_instance_id,status_awaiting:!0,has_run_now:!0,task_id:null!==(_item$task_id=item.task_id)&&void 0!==_item$task_id?_item$task_id:null,status_finished:!1,status_failed:!1,is_module:"section"!==item.type,is_section:"section"===item.type,is_root:!0});_classPrivateFieldGet(this,_element).querySelector(".sharing_cart_items").prepend(element),await this.setupItem(element)}importItem(item,sectionId,modal){_classPrivateFieldGet(this,_course).clearClipboard();const courseModuleIds=[];if(modal.querySelectorAll('input[type="checkbox"][data-type="coursemodule"]:checked').forEach((checkbox=>{courseModuleIds.push(checkbox.dataset.id)})),item.isSection()&&0===courseModuleIds.length)return modal.querySelectorAll(".form-check-input").forEach((async item=>{item.setCustomValidity(await(0,_str.get_string)("atleast_one_course_module_must_be_included","block_sharing_cart")),item.reportValidity()})),!1;item.isModule()&&courseModuleIds.push(item.getItemOldInstanceId()),_ajax.default.call([{methodname:"block_sharing_cart_restore_item_from_sharing_cart_into_section",args:{item_id:item.getItemId(),section_id:sectionId,course_modules_to_include:courseModuleIds},done:async success=>{success&&await _classPrivateFieldGet(this,_queue).loadQueue(!0)},fail:data=>{_notification.default.exception(data)}}])}async confirmImportBackupFromSharingCart(item,sectionId,e){e.preventDefault(),e.stopPropagation();const strings=await(0,_str.get_strings)([{key:"copy_item",component:"block_sharing_cart"},{key:"into_section",component:"block_sharing_cart"},{key:"import",component:"core"},{key:"cancel",component:"core"}]),sectionName=_classPrivateFieldGet(this,_course).getSectionName(sectionId),{html:html,js:js}=await _classPrivateFieldGet(this,_baseFactory).moodle().template().renderFragment("block_sharing_cart","item_restore_form",1,{item_id:item.getItemId()}),modal=await _modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:strings[0]+': "'+item.getItemName().slice(0,50).trim()+'" '+strings[1]+': "'+sectionName.slice(0,50).trim()+'"',body:html,buttons:{save:strings[2],cancel:strings[3]},removeOnClose:!0});modal.getRoot().on(_modal_events.default.shown,(()=>_classPrivateFieldGet(this,_baseFactory).moodle().template().runTemplateJS(js))),modal.getRoot().on(_modal_events.default.save,this.importItem.bind(this,item,sectionId,modal.getRoot()[0])),await modal.show()}async confirmDeleteItems(itemIds){const strings=await(0,_str.get_strings)([{key:"delete_items",component:"block_sharing_cart"},{key:"confirm_delete_items",component:"block_sharing_cart"},{key:"delete",component:"core"},{key:"cancel",component:"core"}]),modal=await _modal_factory.default.create({type:_modal_factory.default.types.DELETE_CANCEL,title:strings[0],body:strings[1],buttons:{delete:strings[2],cancel:strings[3]},removeOnClose:!0});modal.getRoot().on(_modal_events.default.delete,this.deleteItems.bind(this,itemIds)),await modal.show()}},_exports.default})); //# sourceMappingURL=element.min.js.map \ No newline at end of file diff --git a/amd/build/app/block/element.min.js.map b/amd/build/app/block/element.min.js.map index 3cc3d55..163fa5a 100644 --- a/amd/build/app/block/element.min.js.map +++ b/amd/build/app/block/element.min.js.map @@ -1 +1 @@ -{"version":3,"file":"element.min.js","sources":["../../../src/app/block/element.js"],"sourcesContent":["import Sortable from '../../lib/sortablejs';\nimport ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport {get_string, get_strings} from \"core/str\";\nimport Ajax from \"core/ajax\";\nimport Notification from \"core/notification\";\n\nexport default class BlockElement {\n /**\n * @type {BaseFactory}\n */\n #baseFactory;\n\n /**\n * @type {HTMLElement}\n */\n #element;\n\n /**\n * @type {CourseElement}\n */\n #course;\n\n /**\n * @type {QueueElement}\n */\n #queue;\n\n /**\n * @type {ItemElement[]}\n */\n #items = [];\n\n /**\n * @type {Sortable|NULL}\n */\n #sortable = null;\n\n /**\n * @type {ItemElement|NULL}\n */\n #clipboardItem = null;\n\n /**\n * @type {Boolean}\n */\n #canBackupUserdata = false;\n\n /**\n * @type {Boolean}\n */\n #canAnonymizeUserdata = false;\n\n /**\n * @type {Boolean}\n */\n #showSharingCartBasket = false;\n\n /**\n * @type {Number|null}\n */\n #draggedCourseModuleId = null;\n\n /**\n * @type {Number|null}\n */\n #draggedSectionId = null;\n\n /**\n * @type {boolean}\n */\n #bulkDeleteEnabled = false;\n\n /**\n * @param {BaseFactory} baseFactory\n * @param {HTMLElement} element\n * @param {Boolean} canBackupUserdata\n * @param {Boolean} canAnonymizeUserdata\n * @param {Boolean} showSharingCartBasket\n */\n constructor(baseFactory, element, canBackupUserdata, canAnonymizeUserdata, showSharingCartBasket) {\n this.#baseFactory = baseFactory;\n this.#element = element;\n this.#canBackupUserdata = canBackupUserdata;\n this.#canAnonymizeUserdata = canAnonymizeUserdata;\n this.#showSharingCartBasket = showSharingCartBasket;\n }\n\n /**\n * @return {{course: CourseElement, block: BlockElement, queue: QueueElement}}\n */\n addEventListeners() {\n this.setupCourse();\n this.setupQueue();\n this.setupItems();\n this.setupDragAndDrop();\n this.setupBulkDelete();\n\n return {course: this.#course, queue: this.#queue, block: this};\n }\n\n setupCourse() {\n const course = document.querySelector('.course-content');\n\n this.#course = this.#baseFactory.block().course().element(this, course);\n }\n\n setupQueue() {\n const queue = document.querySelector('.sharing_cart_queue');\n\n this.#queue = this.#baseFactory.block().queue().element(this, queue);\n }\n\n async setupItems() {\n const items = this.#element.querySelectorAll('.sharing_cart_item');\n\n for (const element of items) {\n await this.setupItem(element);\n }\n\n this.#sortable = new Sortable(this.#element.querySelector('.sharing_cart_items'), {\n dataIdAttr: 'data-itemid',\n onUpdate: () => {\n Ajax.call([{\n methodname: 'block_sharing_cart_reorder_sharing_cart_items',\n args: {\n item_ids: this.#sortable.toArray(),\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n });\n }\n\n setupDragAndDrop() {\n const dropZone = this.#element;\n\n dropZone.addEventListener('dragover', (e) => {\n if (!this.#draggedSectionId && !this.#draggedCourseModuleId) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n });\n dropZone.addEventListener('dragleave', (e) => {\n if (!this.#draggedSectionId && !this.#draggedCourseModuleId) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n });\n dropZone.addEventListener('drop', async (e) => {\n if (!this.#draggedSectionId && !this.#draggedCourseModuleId) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n\n if (this.#draggedSectionId) {\n await this.addSectionBackupToSharingCart(this.#draggedSectionId);\n } else if (this.#draggedCourseModuleId) {\n await this.addCourseModuleBackupToSharingCart(this.#draggedCourseModuleId);\n }\n });\n }\n\n setupBulkDelete() {\n const enableBulkDeleteButton = this.#element.querySelector('#block_sharing_cart_bulk_delete');\n const disableBulkDeleteButton = this.#element.querySelector('#block_sharing_cart_cancel_bulk_delete');\n const bulkDeleteButton = this.#element.querySelector('#block_sharing_cart_bulk_delete_confirm');\n\n const selectAllContainer = this.#element.querySelector('#select_all_container');\n const selectAllCheckbox = this.#element.querySelector('#select_all_box');\n\n selectAllCheckbox.addEventListener('click', async () => {\n const itemCheckboxes = this.getItemCheckboxes();\n const allSelected = Array.from(itemCheckboxes).every(checkbox => checkbox.checked);\n itemCheckboxes.forEach(checkbox => {\n checkbox.checked = !allSelected;\n });\n itemCheckboxes.forEach(checkbox => checkbox.addEventListener('change', async () => {\n this.updateSelectAllState();\n }));\n\n this.updateSelectAllState();\n this.updateBulkDeleteButtonState();\n });\n\n enableBulkDeleteButton.addEventListener('click', () => {\n if (this.#items.length === 0) {\n return;\n }\n\n this.#bulkDeleteEnabled = true;\n\n enableBulkDeleteButton.classList.add('d-none');\n disableBulkDeleteButton.classList.remove('d-none');\n\n selectAllContainer.classList.remove('d-none');\n bulkDeleteButton.classList.remove('d-none');\n\n this.getItemCheckboxes().forEach((checkbox) => {\n checkbox.classList.remove('d-none');\n checkbox.checked = false;\n });\n });\n\n disableBulkDeleteButton.addEventListener('click', () => {\n disableBulkDeleteButton.classList.add('d-none');\n bulkDeleteButton.classList.add('d-none');\n bulkDeleteButton.disabled = true;\n enableBulkDeleteButton.classList.remove('d-none');\n selectAllContainer.classList.add('d-none');\n\n this.getItemCheckboxes().forEach((checkbox) => {\n checkbox.classList.add('d-none');\n checkbox.checked = false;\n });\n });\n\n bulkDeleteButton.addEventListener('click', async () => {\n if (bulkDeleteButton.disabled) {\n return;\n }\n\n const itemIds = [];\n this.getItemCheckboxes().forEach((checkbox) => {\n if (!checkbox.checked) {\n return;\n }\n\n itemIds.push(checkbox.value);\n });\n\n await this.confirmDeleteItems(itemIds);\n });\n }\n\n /**\n * @param {HTMLElement} element\n */\n async setupItem(element) {\n const itemElement = this.#baseFactory.block().item().element(this, element);\n\n if (itemElement.getStatus() !== '0' && this.isBulkDeleteEnabled()) {\n const checkbox = element.querySelector('input[data-action=\"bulk_select\"][type=\"checkbox\"]');\n checkbox?.classList?.remove('d-none');\n }\n\n this.#element.querySelector('.no-items')?.remove();\n\n this.#items.push(itemElement);\n\n this.updateBulkDeleteButtonState();\n this.updateSelectAllState();\n }\n\n getItemCheckboxes() {\n const checkboxSelector = '.sharing_cart_item:not([data-status=\"0\"]) input[data-action=\"bulk_select\"][type=\"checkbox\"]';\n return this.#element.querySelectorAll(checkboxSelector);\n }\n\n updateBulkDeleteButtonState() {\n const bulkDeleteButton = this.#element.querySelector('#block_sharing_cart_bulk_delete_confirm');\n bulkDeleteButton.disabled = !Array.from(this.getItemCheckboxes()).some(checkbox => checkbox.checked);\n }\n\n updateSelectAllState() {\n const selectAllCheckbox = this.#element.querySelector('#select_all_box');\n const selectAllLabel = this.#element.querySelector('#select_all_label');\n\n const itemCheckboxes = this.getItemCheckboxes();\n const allSelected = Array.from(itemCheckboxes).every(checkbox => checkbox.checked);\n const someSelected = Array.from(itemCheckboxes).some(checkbox => checkbox.checked);\n\n const strPromise = allSelected ?\n get_string('deselect_all', 'block_sharing_cart') :\n get_string('select_all', 'block_sharing_cart');\n strPromise.then((str) => {\n selectAllLabel.textContent = str;\n });\n\n selectAllCheckbox.checked = allSelected;\n selectAllCheckbox.indeterminate = !allSelected && someSelected;\n }\n\n isBulkDeleteEnabled() {\n return this.#bulkDeleteEnabled;\n }\n\n /**\n * @param {ItemElement} item\n */\n async setClipboard(item) {\n this.#clipboardItem = item;\n\n await this.#course.setClipboard(item);\n }\n\n clearClipboard() {\n this.#clipboardItem = null;\n }\n\n /**\n * @param {Number|null} id\n */\n setDraggedSectionId(id) {\n this.#draggedSectionId = id;\n }\n\n /**\n * @param {Number|null} id\n */\n setDraggedCourseModuleId(id) {\n this.#draggedCourseModuleId = id;\n }\n\n /**\n * @param {ItemElement} item\n */\n async removeItemElement(item) {\n const childItems = item.getItemChildrenRecursively();\n childItems.forEach((childItem) => {\n const index = this.#items.findIndex((i) => i.getItemId() === Number.parseInt(childItem.dataset.itemid));\n if (index === -1) {\n return;\n }\n\n if (this.#items[index].getItemId() === this.#clipboardItem?.getItemId()) {\n this.#course.clearClipboard();\n }\n\n this.#items.splice(index, 1);\n childItem.remove();\n });\n\n const index = this.#items.findIndex((i) => i.getItemId() === item.getItemId());\n if (this.#items[index].getItemId() === this.#clipboardItem?.getItemId()) {\n this.#course.clearClipboard();\n }\n\n this.#items.splice(index, 1);\n item.remove();\n\n if (this.#items.length === 0) {\n this.#element.querySelector('.sharing_cart_items')\n .innerHTML = await get_string('no_items', 'block_sharing_cart');\n }\n }\n\n /**\n * @param {ItemElement} item\n */\n deleteItem(item) {\n Ajax.call([{\n methodname: 'block_sharing_cart_delete_item_from_sharing_cart',\n args: {\n item_id: item.getItemId(),\n },\n done: async (deleted) => {\n if (deleted) {\n await this.removeItemElement(item);\n } else {\n await Notification.alert('Failed to delete item');\n }\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n /**\n * @param {Array} itemIds\n */\n deleteItems(itemIds) {\n itemIds = itemIds.map((id) => Number.parseInt(id));\n\n Ajax.call([{\n methodname: 'block_sharing_cart_delete_items_from_sharing_cart',\n args: {\n item_ids: itemIds,\n },\n done: async (deletedItemIds) => {\n const items = this.#items.filter((i) => itemIds.includes(i.getItemId()));\n for (const item of items) {\n const deleted = deletedItemIds.includes(item.getItemId());\n if (!deleted) {\n Notification.alert('Failed to delete item: \"' + item.getItemName() + '\"');\n continue;\n }\n\n await this.removeItemElement(item);\n }\n this.updateSelectAllState();\n\n document.getElementById('block_sharing_cart_bulk_delete_confirm').disabled = true;\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n getElement() {\n return this.#element;\n }\n\n /**\n * @param {String} itemName\n * @param {CallableFunction} onSave\n * @return {Promise}\n */\n async createBackupItemToSharingCartModal(itemName, onSave) {\n const strings = await get_strings([\n {\n key: 'backup_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'into_sharing_cart',\n component: 'block_sharing_cart',\n },\n {\n key: 'backup',\n component: 'block_sharing_cart',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const {html, js} = await this.#baseFactory.moodle().template().renderTemplate(\n 'block_sharing_cart/modal/backup_to_sharing_cart_modal_body',\n {\n show_user_data_backup: this.#canBackupUserdata,\n show_anonymize_user_data: this.#canBackupUserdata && this.#canAnonymizeUserdata,\n }\n );\n\n /**\n * @type {Modal}\n */\n const modal = await ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: strings[0] + ': \"' + itemName.slice(0, 50).trim() + '\" ' + strings[1],\n body: html,\n buttons: {\n save: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n modal.getRoot().on(ModalEvents.shown, () => this.#baseFactory.moodle().template().runTemplateJS(js));\n modal.getRoot().on(ModalEvents.save, () => {\n const modalUserdataCheckbox = document.getElementById('modal-userdata-checkbox');\n const modalAnonymizeCheckbox = document.getElementById('modal-anonymize-checkbox');\n\n onSave({\n users: modalUserdataCheckbox?.checked ?? false,\n anonymize: modalAnonymizeCheckbox?.checked ?? false\n });\n });\n\n return modal;\n }\n\n /**\n * @param {Number} sectionId\n */\n async addSectionBackupToSharingCart(sectionId) {\n const sectionName = this.#course.getSectionName(sectionId);\n\n const cms = this.#course.getSectionCourseModules(sectionId);\n\n if (cms.length === 0) {\n const strings = await get_strings([\n {\n key: 'no_course_modules_in_section',\n component: 'block_sharing_cart',\n },\n {\n key: 'no_course_modules_in_section_description',\n component: 'block_sharing_cart',\n },\n ]);\n\n await Notification.alert(strings[0], strings[1]);\n\n return;\n }\n\n const modal = await this.createBackupItemToSharingCartModal(sectionName, (settings) => {\n Ajax.call([{\n methodname: 'block_sharing_cart_backup_section_into_sharing_cart',\n args: {\n section_id: sectionId,\n settings: settings\n },\n done: async (data) => {\n await this.renderItem(data);\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n });\n\n await modal.show();\n }\n\n /**\n * @param {Number} courseModuleId\n */\n async addCourseModuleBackupToSharingCart(courseModuleId) {\n const courseModuleName = this.#course.getCourseModuleName(courseModuleId);\n\n const modal = await this.createBackupItemToSharingCartModal(courseModuleName, (settings) => {\n Ajax.call([{\n methodname: 'block_sharing_cart_backup_course_module_into_sharing_cart',\n args: {\n course_module_id: courseModuleId,\n settings: settings\n },\n done: async (data) => {\n await this.renderItem(data);\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n });\n await modal.show();\n }\n\n /**\n * @param {Object} item\n */\n async renderItem(item) {\n const existingItemIndex = this.#items.findIndex((i) => i.getItemId() === item.id);\n const existingItem = this.#items[existingItemIndex] ?? false;\n const getOldElement = () => {\n return this.#element.querySelector('.sharing_cart_items .sharing_cart_item[data-itemid=\"' + item.id + '\"]');\n };\n const oldElement = getOldElement();\n if (existingItem && oldElement) {\n const element = await this.#baseFactory.moodle().template().createElementFromFragment(\n 'block_sharing_cart',\n 'item',\n 1,\n {\n item_id: item.id,\n }\n );\n\n // Early exit if the element has been removed from the DOM in between rendering and checking earlier.\n if (getOldElement() !== oldElement) {\n return;\n }\n\n this.#element.querySelector('.sharing_cart_items').replaceChild(element, oldElement);\n this.#items[existingItemIndex] = this.#baseFactory.block().item().element(this, element);\n\n await this.setupItem(element); // test\n for (const subItem of element.querySelectorAll('.sharing_cart_item')) {\n await this.setupItem(subItem);\n }\n\n return;\n }\n\n const element = await this.#baseFactory.moodle().template().createElementFromTemplate(\n 'block_sharing_cart/block/item',\n {\n id: item.id,\n name: item.name,\n type: item.type,\n status: 0,\n old_instance_id: item.old_instance_id,\n status_awaiting: true,\n has_run_now: true,\n task_id: item.task_id ?? null,\n status_finished: false,\n status_failed: false,\n is_module: item.type !== 'section',\n is_section: item.type === 'section',\n is_root: true,\n }\n );\n this.#element.querySelector('.sharing_cart_items').prepend(element);\n\n await this.setupItem(element);\n }\n\n /**\n * @param {ItemElement} item\n * @param {Number} sectionId\n * @param {HTMLElement} modal\n */\n importItem(item, sectionId, modal) {\n this.#course.clearClipboard();\n\n const courseModuleIds = [];\n modal.querySelectorAll('input[type=\"checkbox\"][data-type=\"coursemodule\"]:checked').forEach((checkbox) => {\n courseModuleIds.push(checkbox.dataset.id);\n });\n\n if (item.isSection() && courseModuleIds.length === 0) {\n modal.querySelectorAll('.form-check-input').forEach(async (item) => {\n item.setCustomValidity(\n await get_string('atleast_one_course_module_must_be_included', 'block_sharing_cart')\n );\n item.reportValidity();\n });\n return false;\n }\n\n if (item.isModule()) {\n courseModuleIds.push(item.getItemOldInstanceId());\n }\n\n Ajax.call([{\n methodname: 'block_sharing_cart_restore_item_from_sharing_cart_into_section',\n args: {\n item_id: item.getItemId(),\n section_id: sectionId,\n course_modules_to_include: courseModuleIds,\n },\n done: async (success) => {\n if (success) {\n await this.#queue.loadQueue(true);\n }\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n /**\n * @param {ItemElement} item\n * @param {Number} sectionId\n * @param {Event} e\n */\n async confirmImportBackupFromSharingCart(item, sectionId, e) {\n e.preventDefault();\n e.stopPropagation();\n\n const strings = await get_strings([\n {\n key: 'copy_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'into_section',\n component: 'block_sharing_cart',\n },\n {\n key: 'import',\n component: 'core',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const sectionName = this.#course.getSectionName(sectionId);\n\n const {html, js} = await this.#baseFactory.moodle().template().renderFragment(\n 'block_sharing_cart',\n 'item_restore_form',\n 1,\n {\n item_id: item.getItemId()\n }\n );\n\n const modal = await ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: strings[0] + ': ' +\n '\"' + item.getItemName().slice(0, 50).trim() + '\"' +\n ' ' + strings[1] + ': ' +\n '\"' + sectionName.slice(0, 50).trim() + '\"',\n body: html,\n buttons: {\n save: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n modal.getRoot().on(ModalEvents.shown, () => this.#baseFactory.moodle().template().runTemplateJS(js));\n modal.getRoot().on(ModalEvents.save, this.importItem.bind(this, item, sectionId, modal.getRoot()[0]));\n await modal.show();\n }\n\n /**\n * @param {Array} itemIds\n */\n async confirmDeleteItems(itemIds) {\n const strings = await get_strings([\n {\n key: 'delete_items',\n component: 'block_sharing_cart',\n },\n {\n key: 'confirm_delete_items',\n component: 'block_sharing_cart',\n },\n {\n key: 'delete',\n component: 'core',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const modal = await ModalFactory.create({\n type: ModalFactory.types.DELETE_CANCEL,\n title: strings[0],\n body: strings[1],\n buttons: {\n delete: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n\n modal.getRoot().on(ModalEvents.delete, this.deleteItems.bind(this, itemIds));\n await modal.show();\n }\n}\n"],"names":["constructor","baseFactory","element","canBackupUserdata","canAnonymizeUserdata","showSharingCartBasket","addEventListeners","setupCourse","setupQueue","setupItems","setupDragAndDrop","setupBulkDelete","course","this","queue","block","document","querySelector","_classPrivateFieldGet","items","querySelectorAll","setupItem","Sortable","dataIdAttr","onUpdate","call","methodname","args","item_ids","toArray","fail","data","exception","dropZone","addEventListener","e","preventDefault","stopPropagation","async","addSectionBackupToSharingCart","addCourseModuleBackupToSharingCart","enableBulkDeleteButton","disableBulkDeleteButton","bulkDeleteButton","selectAllContainer","itemCheckboxes","getItemCheckboxes","allSelected","Array","from","every","checkbox","checked","forEach","updateSelectAllState","updateBulkDeleteButtonState","length","classList","add","remove","disabled","itemIds","push","value","confirmDeleteItems","itemElement","item","getStatus","isBulkDeleteEnabled","some","selectAllCheckbox","selectAllLabel","someSelected","then","str","textContent","indeterminate","setClipboard","clearClipboard","setDraggedSectionId","id","setDraggedCourseModuleId","getItemChildrenRecursively","childItem","index","findIndex","i","getItemId","Number","parseInt","dataset","itemid","_classPrivateFieldGet3","splice","_classPrivateFieldGet4","innerHTML","deleteItem","item_id","done","deleted","removeItemElement","Notification","alert","deleteItems","map","filter","includes","deletedItemIds","getItemName","getElementById","getElement","itemName","onSave","strings","key","component","html","js","moodle","template","renderTemplate","show_user_data_backup","show_anonymize_user_data","modal","ModalFactory","create","type","types","SAVE_CANCEL","title","slice","trim","body","buttons","save","cancel","removeOnClose","getRoot","on","ModalEvents","shown","runTemplateJS","modalUserdataCheckbox","modalAnonymizeCheckbox","users","anonymize","sectionId","sectionName","getSectionName","getSectionCourseModules","createBackupItemToSharingCartModal","settings","section_id","renderItem","show","courseModuleId","courseModuleName","getCourseModuleName","course_module_id","existingItemIndex","existingItem","getOldElement","oldElement","createElementFromFragment","replaceChild","subItem","createElementFromTemplate","name","status","old_instance_id","status_awaiting","has_run_now","task_id","status_finished","status_failed","is_module","is_section","is_root","prepend","importItem","courseModuleIds","isSection","setCustomValidity","reportValidity","isModule","getItemOldInstanceId","course_modules_to_include","success","loadQueue","renderFragment","bind","DELETE_CANCEL","delete"],"mappings":"8hEAgFIA,YAAYC,YAAaC,QAASC,kBAAmBC,qBAAsBC,sWAjDlE,kEAKG,yEAKK,8EAKI,8EAKG,+EAKC,8EAKA,4EAKL,8EAKC,4CAUGJ,iDACJC,uDACUC,oEACGC,wEACCC,uBAMlCC,gCACSC,mBACAC,kBACAC,kBACAC,wBACAC,kBAEE,CAACC,6BAAQC,cAAcC,4BAAOD,aAAaE,MAAOF,MAG7DN,oBACUK,OAASI,SAASC,cAAc,sDAEvBC,yCAAkBH,QAAQH,SAASV,QAAQW,KAAMD,SAGpEJ,mBACUM,MAAQE,SAASC,cAAc,yDAEvBC,yCAAkBH,QAAQD,QAAQZ,QAAQW,KAAMC,iCAIxDK,MAAQD,qCAAcE,iBAAiB,0BAExC,MAAMlB,WAAWiB,YACZN,KAAKQ,UAAUnB,8CAGR,IAAIoB,oBAASJ,qCAAcD,cAAc,uBAAwB,CAC9EM,WAAY,cACZC,SAAU,mBACDC,KAAK,CAAC,CACPC,WAAY,gDACZC,KAAM,CACFC,SAAUV,sCAAeW,WAE7BC,KAAOC,6BACUC,UAAUD,cAO3CrB,yBACUuB,+BAAWpB,eAEjBoB,SAASC,iBAAiB,YAAaC,2BAC9BtB,+CAA2BA,gCAIhCsB,EAAEC,iBACFD,EAAEE,sBAENJ,SAASC,iBAAiB,aAAcC,2BAC/BtB,+CAA2BA,gCAIhCsB,EAAEC,iBACFD,EAAEE,sBAENJ,SAASC,iBAAiB,QAAQI,MAAAA,2BACzBzB,+CAA2BA,gCAIhCsB,EAAEC,iBACFD,EAAEE,wCAEExB,8BACMA,KAAK0B,oDAA8B1B,+CAClCA,oCACDA,KAAK2B,yDAAmC3B,kCAK1DF,wBACU8B,uBAAyBvB,qCAAcD,cAAc,mCACrDyB,wBAA0BxB,qCAAcD,cAAc,0CACtD0B,iBAAmBzB,qCAAcD,cAAc,2CAE/C2B,mBAAqB1B,qCAAcD,cAAc,yBAC7BC,qCAAcD,cAAc,mBAEpCiB,iBAAiB,SAASI,gBAClCO,eAAiBhC,KAAKiC,oBACtBC,YAAcC,MAAMC,KAAKJ,gBAAgBK,OAAMC,UAAYA,SAASC,UAC1EP,eAAeQ,SAAQF,WACnBA,SAASC,SAAWL,eAExBF,eAAeQ,SAAQF,UAAYA,SAASjB,iBAAiB,UAAUI,eAC9DgB,iCAGJA,4BACAC,iCAGTd,uBAAuBP,iBAAiB,SAAS,KAClB,IAAvBhB,mCAAYsC,wDAIU,GAE1Bf,uBAAuBgB,UAAUC,IAAI,UACrChB,wBAAwBe,UAAUE,OAAO,UAEzCf,mBAAmBa,UAAUE,OAAO,UACpChB,iBAAiBc,UAAUE,OAAO,eAE7Bb,oBAAoBO,SAASF,WAC9BA,SAASM,UAAUE,OAAO,UAC1BR,SAASC,SAAU,SAI3BV,wBAAwBR,iBAAiB,SAAS,KAC9CQ,wBAAwBe,UAAUC,IAAI,UACtCf,iBAAiBc,UAAUC,IAAI,UAC/Bf,iBAAiBiB,UAAW,EAC5BnB,uBAAuBgB,UAAUE,OAAO,UACxCf,mBAAmBa,UAAUC,IAAI,eAE5BZ,oBAAoBO,SAASF,WAC9BA,SAASM,UAAUC,IAAI,UACvBP,SAASC,SAAU,QAI3BT,iBAAiBT,iBAAiB,SAASI,aACnCK,iBAAiBiB,sBAIfC,QAAU,QACXf,oBAAoBO,SAASF,WACzBA,SAASC,SAIdS,QAAQC,KAAKX,SAASY,gBAGpBlD,KAAKmD,mBAAmBH,4BAOtB3D,0CACN+D,YAAc/C,yCAAkBH,QAAQmD,OAAOhE,QAAQW,KAAMX,YAEnC,MAA5B+D,YAAYE,aAAuBtD,KAAKuD,sBAAuB,+BACzDjB,SAAWjD,QAAQe,cAAc,qDACvCkC,MAAAA,sCAAAA,SAAUM,8DAAWE,OAAO,8EAGlB1C,cAAc,uEAAc0C,4CAE9BG,KAAKG,kBAEZV,mCACAD,uBAGTR,2BAEW5B,qCAAcE,iBADI,+FAI7BmC,8BAC6BrC,qCAAcD,cAAc,2CACpC2C,UAAYZ,MAAMC,KAAKpC,KAAKiC,qBAAqBuB,MAAKlB,UAAYA,SAASC,UAGhGE,6BACUgB,kBAAoBpD,qCAAcD,cAAc,mBAChDsD,eAAiBrD,qCAAcD,cAAc,qBAE7C4B,eAAiBhC,KAAKiC,oBACtBC,YAAcC,MAAMC,KAAKJ,gBAAgBK,OAAMC,UAAYA,SAASC,UACpEoB,aAAexB,MAAMC,KAAKJ,gBAAgBwB,MAAKlB,UAAYA,SAASC,WAEvDL,aACf,mBAAW,eAAgB,uBAC3B,mBAAW,aAAc,uBAClB0B,MAAMC,MACbH,eAAeI,YAAcD,OAGjCJ,kBAAkBlB,QAAUL,YAC5BuB,kBAAkBM,eAAiB7B,aAAeyB,aAGtDJ,mDACWvD,4CAMQqD,gDACOA,YAEhBhD,oCAAa2D,aAAaX,MAGpCY,2DAC0B,MAM1BC,oBAAoBC,iDACSA,IAM7BC,yBAAyBD,sDACSA,4BAMVd,iCACDA,KAAKgB,6BACb7B,SAAS8B,6CACVC,MAAQlE,mCAAYmE,WAAWC,GAAMA,EAAEC,cAAgBC,OAAOC,SAASN,UAAUO,QAAQC,WAChF,IAAXP,QAIAlE,mCAAYkE,OAAOG,oEAAgB1E,8DAAA+E,uBAAqBL,kDAC3CT,oDAGLe,OAAOT,MAAO,GAC1BD,UAAUxB,mBAGRyB,MAAQlE,mCAAYmE,WAAWC,GAAMA,EAAEC,cAAgBrB,KAAKqB,cAC9DrE,mCAAYkE,OAAOG,oEAAgB1E,8DAAAiF,uBAAqBP,kDAC3CT,oDAGLe,OAAOT,MAAO,GAC1BlB,KAAKP,SAEsB,IAAvBzC,mCAAYsC,8CACEvC,cAAc,uBACvB8E,gBAAkB,mBAAW,WAAY,uBAOtDC,WAAW9B,oBACFzC,KAAK,CAAC,CACPC,WAAY,mDACZC,KAAM,CACFsE,QAAS/B,KAAKqB,aAElBW,KAAM5D,MAAAA,UACE6D,cACMtF,KAAKuF,kBAAkBlC,YAEvBmC,sBAAaC,MAAM,0BAGjCxE,KAAOC,6BACUC,UAAUD,UAQnCwE,YAAY1C,SACRA,QAAUA,QAAQ2C,KAAKxB,IAAOQ,OAAOC,SAAST,oBAEzCvD,KAAK,CAAC,CACPC,WAAY,oDACZC,KAAM,CACFC,SAAUiC,SAEdqC,KAAM5D,MAAAA,uBACInB,MAAQD,mCAAYuF,QAAQnB,GAAMzB,QAAQ6C,SAASpB,EAAEC,mBACtD,MAAMrB,QAAQ/C,MAAO,CACNwF,eAAeD,SAASxC,KAAKqB,mBAMvC1E,KAAKuF,kBAAkBlC,4BAJZoC,MAAM,2BAA6BpC,KAAK0C,cAAgB,UAMxEtD,uBAELtC,SAAS6F,eAAe,0CAA0CjD,UAAW,GAEjF9B,KAAOC,6BACUC,UAAUD,UAKnC+E,0CACWjG,wDAQ8BkG,SAAUC,cACzCC,cAAgB,oBAAY,CAC9B,CACIC,IAAK,cACLC,UAAW,sBAEf,CACID,IAAK,oBACLC,UAAW,sBAEf,CACID,IAAK,SACLC,UAAW,sBAEf,CACID,IAAK,SACLC,UAAW,WAIbC,KAACA,KAADC,GAAOA,UAAYnG,yCAAkBoG,SAASC,WAAWC,eAC3D,6DACA,CACIC,4CAAuB5G,yBACvB6G,yBAA0BxG,sEAA2BL,8BAOvD8G,YAAcC,uBAAaC,OAAO,CACpCC,KAAMF,uBAAaG,MAAMC,YACzBC,MAAOhB,QAAQ,GAAK,MAAQF,SAASmB,MAAM,EAAG,IAAIC,OAAS,KAAOlB,QAAQ,GAC1EmB,KAAMhB,KACNiB,QAAS,CACLC,KAAMrB,QAAQ,GACdsB,OAAQtB,QAAQ,IAEpBuB,eAAe,WAEnBb,MAAMc,UAAUC,GAAGC,sBAAYC,OAAO,IAAM1H,yCAAkBoG,SAASC,WAAWsB,cAAcxB,MAChGM,MAAMc,UAAUC,GAAGC,sBAAYL,MAAM,2DAC3BQ,sBAAwB9H,SAAS6F,eAAe,2BAChDkC,uBAAyB/H,SAAS6F,eAAe,4BAEvDG,OAAO,CACHgC,oCAAOF,MAAAA,6BAAAA,sBAAuB1F,gEAC9B6F,wCAAWF,MAAAA,8BAAAA,uBAAwB3F,qEAIpCuE,0CAMyBuB,iBAC1BC,YAAcjI,oCAAakI,eAAeF,cAI7B,IAFPhI,oCAAamI,wBAAwBH,WAEzC1F,OAAc,OACZyD,cAAgB,oBAAY,CAC9B,CACIC,IAAK,+BACLC,UAAW,sBAEf,CACID,IAAK,2CACLC,UAAW,0CAIbd,sBAAaC,MAAMW,QAAQ,GAAIA,QAAQ,UAK3CU,YAAc9G,KAAKyI,mCAAmCH,aAAcI,yBACjE9H,KAAK,CAAC,CACPC,WAAY,sDACZC,KAAM,CACF6H,WAAYN,UACZK,SAAUA,UAEdrD,KAAM5D,MAAAA,aACIzB,KAAK4I,WAAW1H,OAE1BD,KAAOC,6BACUC,UAAUD,mBAK7B4F,MAAM+B,gDAMyBC,sBAC/BC,iBAAmB1I,oCAAa2I,oBAAoBF,gBAEpDhC,YAAc9G,KAAKyI,mCAAmCM,kBAAmBL,yBACtE9H,KAAK,CAAC,CACPC,WAAY,4DACZC,KAAM,CACFmI,iBAAkBH,eAClBJ,SAAUA,UAEdrD,KAAM5D,MAAAA,aACIzB,KAAK4I,WAAW1H,OAE1BD,KAAOC,6BACUC,UAAUD,mBAI7B4F,MAAM+B,wBAMCxF,qDACP6F,kBAAoB7I,mCAAYmE,WAAWC,GAAMA,EAAEC,cAAgBrB,KAAKc,KACxEgF,4CAAe9I,mCAAY6I,6EAC3BE,cAAgB,IACX/I,qCAAcD,cAAc,uDAAyDiD,KAAKc,GAAK,MAEpGkF,WAAaD,mBACfD,cAAgBE,WAAY,OACtBhK,cAAgBgB,yCAAkBoG,SAASC,WAAW4C,0BACxD,qBACA,OACA,EACA,CACIlE,QAAS/B,KAAKc,QAKlBiF,kBAAoBC,uDAIVjJ,cAAc,uBAAuBmJ,aAAalK,QAASgK,+CAC7DH,mBAAqB7I,yCAAkBH,QAAQmD,OAAOhE,QAAQW,KAAMX,eAE1EW,KAAKQ,UAAUnB,aAChB,MAAMmK,WAAWnK,QAAQkB,iBAAiB,4BACrCP,KAAKQ,UAAUgJ,sBAMvBnK,cAAgBgB,yCAAkBoG,SAASC,WAAW+C,0BACxD,gCACA,CACItF,GAAId,KAAKc,GACTuF,KAAMrG,KAAKqG,KACXzC,KAAM5D,KAAK4D,KACX0C,OAAQ,EACRC,gBAAiBvG,KAAKuG,gBACtBC,iBAAiB,EACjBC,aAAa,EACbC,8BAAS1G,KAAK0G,+CAAW,KACzBC,iBAAiB,EACjBC,eAAe,EACfC,UAAyB,YAAd7G,KAAK4D,KAChBkD,WAA0B,YAAd9G,KAAK4D,KACjBmD,SAAS,yCAGHhK,cAAc,uBAAuBiK,QAAQhL,eAErDW,KAAKQ,UAAUnB,SAQzBiL,WAAWjH,KAAMgF,UAAWvB,2CACX7C,uBAEPsG,gBAAkB,MACxBzD,MAAMvG,iBAAiB,4DAA4DiC,SAASF,WACxFiI,gBAAgBtH,KAAKX,SAASuC,QAAQV,OAGtCd,KAAKmH,aAA0C,IAA3BD,gBAAgB5H,cACpCmE,MAAMvG,iBAAiB,qBAAqBiC,SAAQf,MAAAA,OAChD4B,KAAKoH,wBACK,mBAAW,6CAA8C,uBAEnEpH,KAAKqH,qBAEF,EAGPrH,KAAKsH,YACLJ,gBAAgBtH,KAAKI,KAAKuH,sCAGzBhK,KAAK,CAAC,CACPC,WAAY,iEACZC,KAAM,CACFsE,QAAS/B,KAAKqB,YACdiE,WAAYN,UACZwC,0BAA2BN,iBAE/BlF,KAAM5D,MAAAA,UACEqJ,eACMzK,mCAAY0K,WAAU,IAGpC9J,KAAOC,6BACUC,UAAUD,mDAUMmC,KAAMgF,UAAW/G,GACtDA,EAAEC,iBACFD,EAAEE,wBAEI4E,cAAgB,oBAAY,CAC9B,CACIC,IAAK,YACLC,UAAW,sBAEf,CACID,IAAK,eACLC,UAAW,sBAEf,CACID,IAAK,SACLC,UAAW,QAEf,CACID,IAAK,SACLC,UAAW,UAIbgC,YAAcjI,oCAAakI,eAAeF,YAE1C9B,KAACA,KAADC,GAAOA,UAAYnG,yCAAkBoG,SAASC,WAAWsE,eAC3D,qBACA,oBACA,EACA,CACI5F,QAAS/B,KAAKqB,cAIhBoC,YAAcC,uBAAaC,OAAO,CACpCC,KAAMF,uBAAaG,MAAMC,YACzBC,MAAOhB,QAAQ,GAARA,MACG/C,KAAK0C,cAAcsB,MAAM,EAAG,IAAIC,OADnClB,KAEGA,QAAQ,GAFXA,MAGGkC,YAAYjB,MAAM,EAAG,IAAIC,OAAS,IAC5CC,KAAMhB,KACNiB,QAAS,CACLC,KAAMrB,QAAQ,GACdsB,OAAQtB,QAAQ,IAEpBuB,eAAe,IAEnBb,MAAMc,UAAUC,GAAGC,sBAAYC,OAAO,IAAM1H,yCAAkBoG,SAASC,WAAWsB,cAAcxB,MAChGM,MAAMc,UAAUC,GAAGC,sBAAYL,KAAMzH,KAAKsK,WAAWW,KAAKjL,KAAMqD,KAAMgF,UAAWvB,MAAMc,UAAU,WAC3Fd,MAAM+B,gCAMS7F,eACfoD,cAAgB,oBAAY,CAC9B,CACIC,IAAK,eACLC,UAAW,sBAEf,CACID,IAAK,uBACLC,UAAW,sBAEf,CACID,IAAK,SACLC,UAAW,QAEf,CACID,IAAK,SACLC,UAAW,UAIbQ,YAAcC,uBAAaC,OAAO,CACpCC,KAAMF,uBAAaG,MAAMgE,cACzB9D,MAAOhB,QAAQ,GACfmB,KAAMnB,QAAQ,GACdoB,QAAS,CACL2D,OAAQ/E,QAAQ,GAChBsB,OAAQtB,QAAQ,IAEpBuB,eAAe,IAGnBb,MAAMc,UAAUC,GAAGC,sBAAYqD,OAAQnL,KAAK0F,YAAYuF,KAAKjL,KAAMgD,gBAC7D8D,MAAM+B"} \ No newline at end of file +{"version":3,"file":"element.min.js","sources":["../../../src/app/block/element.js"],"sourcesContent":["import Sortable from '../../lib/sortablejs';\nimport ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport {get_string, get_strings} from \"core/str\";\nimport Ajax from \"core/ajax\";\nimport Notification from \"core/notification\";\n\nexport default class BlockElement {\n /**\n * @type {BaseFactory}\n */\n #baseFactory;\n\n /**\n * @type {HTMLElement}\n */\n #element;\n\n /**\n * @type {CourseElement}\n */\n #course;\n\n /**\n * @type {QueueElement}\n */\n #queue;\n\n /**\n * @type {ItemElement[]}\n */\n #items = [];\n\n /**\n * @type {Sortable|NULL}\n */\n #sortable = null;\n\n /**\n * @type {ItemElement|NULL}\n */\n #clipboardItem = null;\n\n /**\n * @type {Boolean}\n */\n #canBackupUserdata = false;\n\n /**\n * @type {Boolean}\n */\n #canAnonymizeUserdata = false;\n\n /**\n * @type {Boolean}\n */\n #showSharingCartBasket = false;\n\n /**\n * @type {Number|null}\n */\n #draggedCourseModuleId = null;\n\n /**\n * @type {Number|null}\n */\n #draggedSectionId = null;\n\n /**\n * @type {boolean}\n */\n #bulkDeleteEnabled = false;\n\n /**\n * @param {BaseFactory} baseFactory\n * @param {HTMLElement} element\n * @param {Boolean} canBackupUserdata\n * @param {Boolean} canAnonymizeUserdata\n * @param {Boolean} showSharingCartBasket\n */\n constructor(baseFactory, element, canBackupUserdata, canAnonymizeUserdata, showSharingCartBasket) {\n this.#baseFactory = baseFactory;\n this.#element = element;\n this.#canBackupUserdata = canBackupUserdata;\n this.#canAnonymizeUserdata = canAnonymizeUserdata;\n this.#showSharingCartBasket = showSharingCartBasket;\n }\n\n /**\n * @return {{course: CourseElement, block: BlockElement, queue: QueueElement}}\n */\n addEventListeners() {\n this.setupCourse();\n this.setupQueue();\n this.setupItems();\n this.setupDragAndDrop();\n this.setupBulkDelete();\n\n return {course: this.#course, queue: this.#queue, block: this};\n }\n\n setupCourse() {\n const course = document.querySelector('.course-content');\n\n this.#course = this.#baseFactory.block().course().element(this, course);\n }\n\n setupQueue() {\n const queue = document.querySelector('.sharing_cart_queue');\n\n this.#queue = this.#baseFactory.block().queue().element(this, queue);\n }\n\n async setupItems() {\n const items = this.#element.querySelectorAll('.sharing_cart_item');\n\n for (const element of items) {\n await this.setupItem(element);\n }\n\n this.#sortable = new Sortable(this.#element.querySelector('.sharing_cart_items'), {\n dataIdAttr: 'data-itemid',\n onUpdate: () => {\n Ajax.call([{\n methodname: 'block_sharing_cart_reorder_sharing_cart_items',\n args: {\n item_ids: this.#sortable.toArray(),\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n });\n }\n\n setupDragAndDrop() {\n const dropZone = this.#element;\n\n dropZone.addEventListener('dragover', (e) => {\n if (!this.#draggedSectionId && !this.#draggedCourseModuleId) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n });\n dropZone.addEventListener('dragleave', (e) => {\n if (!this.#draggedSectionId && !this.#draggedCourseModuleId) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n });\n dropZone.addEventListener('drop', async (e) => {\n if (!this.#draggedSectionId && !this.#draggedCourseModuleId) {\n return;\n }\n\n e.preventDefault();\n e.stopPropagation();\n\n if (this.#draggedSectionId) {\n await this.addSectionBackupToSharingCart(this.#draggedSectionId);\n } else if (this.#draggedCourseModuleId) {\n await this.addCourseModuleBackupToSharingCart(this.#draggedCourseModuleId);\n }\n });\n }\n\n setupBulkDelete() {\n const enableBulkDeleteButton = this.#element.querySelector('#block_sharing_cart_bulk_delete');\n const disableBulkDeleteButton = this.#element.querySelector('#block_sharing_cart_cancel_bulk_delete');\n const bulkDeleteButton = this.#element.querySelector('#block_sharing_cart_bulk_delete_confirm');\n\n const selectAllContainer = this.#element.querySelector('#select_all_container');\n const selectAllCheckbox = this.#element.querySelector('#select_all_box');\n\n selectAllCheckbox.addEventListener('click', async () => {\n const itemCheckboxes = this.getItemCheckboxes();\n const allSelected = Array.from(itemCheckboxes).every(checkbox => checkbox.checked);\n itemCheckboxes.forEach(checkbox => {\n checkbox.checked = !allSelected;\n });\n itemCheckboxes.forEach(checkbox => checkbox.addEventListener('change', async () => {\n this.updateSelectAllState();\n }));\n\n this.updateSelectAllState();\n this.updateBulkDeleteButtonState();\n });\n\n enableBulkDeleteButton.addEventListener('click', () => {\n if (this.#items.length === 0) {\n return;\n }\n\n this.#bulkDeleteEnabled = true;\n\n enableBulkDeleteButton.classList.add('d-none');\n disableBulkDeleteButton.classList.remove('d-none');\n\n selectAllContainer.classList.remove('d-none');\n bulkDeleteButton.classList.remove('d-none');\n\n this.getItemCheckboxes().forEach((checkbox) => {\n checkbox.classList.remove('d-none');\n checkbox.checked = false;\n });\n });\n\n disableBulkDeleteButton.addEventListener('click', () => {\n disableBulkDeleteButton.classList.add('d-none');\n bulkDeleteButton.classList.add('d-none');\n bulkDeleteButton.disabled = true;\n enableBulkDeleteButton.classList.remove('d-none');\n selectAllContainer.classList.add('d-none');\n\n this.getItemCheckboxes().forEach((checkbox) => {\n checkbox.classList.add('d-none');\n checkbox.checked = false;\n });\n });\n\n bulkDeleteButton.addEventListener('click', async () => {\n if (bulkDeleteButton.disabled) {\n return;\n }\n\n const itemIds = [];\n this.getItemCheckboxes().forEach((checkbox) => {\n if (!checkbox.checked) {\n return;\n }\n\n itemIds.push(checkbox.value);\n });\n\n await this.confirmDeleteItems(itemIds);\n });\n }\n\n /**\n * @param {HTMLElement} element\n */\n async setupItem(element) {\n const itemElement = this.#baseFactory.block().item().element(this, element);\n\n if (itemElement.getStatus() !== '0' && this.isBulkDeleteEnabled()) {\n const checkbox = element.querySelector('input[data-action=\"bulk_select\"][type=\"checkbox\"]');\n checkbox?.classList?.remove('d-none');\n }\n\n this.#element.querySelector('.no-items').classList.add('d-none');\n\n const existingItemIndex = this.#items.findIndex((i) => i.getItemId() === itemElement.getItemId());\n if (existingItemIndex !== -1) {\n this.#items[existingItemIndex] = itemElement;\n } else {\n this.#items.push(itemElement);\n }\n\n this.updateBulkDeleteButtonState();\n this.updateSelectAllState();\n }\n\n getItemCheckboxes() {\n const checkboxSelector = '.sharing_cart_item:not([data-status=\"0\"]) input[data-action=\"bulk_select\"][type=\"checkbox\"]';\n return this.#element.querySelectorAll(checkboxSelector);\n }\n\n updateBulkDeleteButtonState() {\n const bulkDeleteButton = this.#element.querySelector('#block_sharing_cart_bulk_delete_confirm');\n bulkDeleteButton.disabled = !Array.from(this.getItemCheckboxes()).some(checkbox => checkbox.checked);\n }\n\n updateSelectAllState() {\n const selectAllCheckbox = this.#element.querySelector('#select_all_box');\n const selectAllLabel = this.#element.querySelector('#select_all_label');\n\n const itemCheckboxes = this.getItemCheckboxes();\n const allSelected = Array.from(itemCheckboxes).every(checkbox => checkbox.checked);\n const someSelected = Array.from(itemCheckboxes).some(checkbox => checkbox.checked);\n\n const strPromise = allSelected ?\n get_string('deselect_all', 'block_sharing_cart') :\n get_string('select_all', 'block_sharing_cart');\n strPromise.then((str) => {\n selectAllLabel.textContent = str;\n });\n\n selectAllCheckbox.checked = allSelected;\n selectAllCheckbox.indeterminate = !allSelected && someSelected;\n }\n\n isBulkDeleteEnabled() {\n return this.#bulkDeleteEnabled;\n }\n\n /**\n * @param {ItemElement} item\n */\n async setClipboard(item) {\n this.#clipboardItem = item;\n\n await this.#course.setClipboard(item);\n }\n\n clearClipboard() {\n this.#clipboardItem = null;\n }\n\n /**\n * @param {Number|null} id\n */\n setDraggedSectionId(id) {\n this.#draggedSectionId = id;\n }\n\n /**\n * @param {Number|null} id\n */\n setDraggedCourseModuleId(id) {\n this.#draggedCourseModuleId = id;\n }\n\n /**\n * @param {ItemElement} item\n */\n async removeItemElement(item) {\n const childItems = item.getItemChildrenRecursively();\n childItems.forEach((childItem) => {\n const index = this.#items.findIndex((i) => i.getItemId() === Number.parseInt(childItem.dataset.itemid));\n if (index === -1) {\n return;\n }\n\n if (this.#items[index].getItemId() === this.#clipboardItem?.getItemId()) {\n this.#course.clearClipboard();\n }\n\n this.#items.splice(index, 1);\n childItem.remove();\n });\n\n const index = this.#items.findIndex((i) => i.getItemId() === item.getItemId());\n if (this.#items[index].getItemId() === this.#clipboardItem?.getItemId()) {\n this.#course.clearClipboard();\n }\n\n this.#items.splice(index, 1);\n item.remove();\n\n if (this.#items.length === 0) {\n this.#element.querySelector('.no-items').classList.remove('d-none');\n }\n }\n\n /**\n * @param {ItemElement} item\n */\n deleteItem(item) {\n Ajax.call([{\n methodname: 'block_sharing_cart_delete_item_from_sharing_cart',\n args: {\n item_id: item.getItemId(),\n },\n done: async (deleted) => {\n if (deleted) {\n await this.removeItemElement(item);\n this.updateSelectAllState();\n } else {\n await Notification.alert('Failed to delete item');\n }\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n /**\n * @param {Array} itemIds\n */\n deleteItems(itemIds) {\n itemIds = itemIds.map((id) => Number.parseInt(id));\n\n Ajax.call([{\n methodname: 'block_sharing_cart_delete_items_from_sharing_cart',\n args: {\n item_ids: itemIds,\n },\n done: async (deletedItemIds) => {\n const items = this.#items.filter((i) => itemIds.includes(i.getItemId()));\n for (const item of items) {\n const deleted = deletedItemIds.includes(item.getItemId());\n if (!deleted) {\n Notification.alert('Failed to delete item: \"' + item.getItemName() + '\"');\n continue;\n }\n\n await this.removeItemElement(item);\n }\n this.updateSelectAllState();\n\n document.getElementById('block_sharing_cart_bulk_delete_confirm').disabled = true;\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n getElement() {\n return this.#element;\n }\n\n /**\n * @param {String} itemName\n * @param {CallableFunction} onSave\n * @return {Promise}\n */\n async createBackupItemToSharingCartModal(itemName, onSave) {\n const strings = await get_strings([\n {\n key: 'backup_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'into_sharing_cart',\n component: 'block_sharing_cart',\n },\n {\n key: 'backup',\n component: 'block_sharing_cart',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const {html, js} = await this.#baseFactory.moodle().template().renderTemplate(\n 'block_sharing_cart/modal/backup_to_sharing_cart_modal_body',\n {\n show_user_data_backup: this.#canBackupUserdata,\n show_anonymize_user_data: this.#canBackupUserdata && this.#canAnonymizeUserdata,\n }\n );\n\n /**\n * @type {Modal}\n */\n const modal = await ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: strings[0] + ': \"' + itemName.slice(0, 50).trim() + '\" ' + strings[1],\n body: html,\n buttons: {\n save: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n modal.getRoot().on(ModalEvents.shown, () => this.#baseFactory.moodle().template().runTemplateJS(js));\n modal.getRoot().on(ModalEvents.save, () => {\n const modalUserdataCheckbox = document.getElementById('modal-userdata-checkbox');\n const modalAnonymizeCheckbox = document.getElementById('modal-anonymize-checkbox');\n\n onSave({\n users: modalUserdataCheckbox?.checked ?? false,\n anonymize: modalAnonymizeCheckbox?.checked ?? false\n });\n });\n\n return modal;\n }\n\n /**\n * @param {Number} sectionId\n */\n async addSectionBackupToSharingCart(sectionId) {\n const sectionName = this.#course.getSectionName(sectionId);\n\n const cms = this.#course.getSectionCourseModules(sectionId);\n\n if (cms.length === 0) {\n const strings = await get_strings([\n {\n key: 'no_course_modules_in_section',\n component: 'block_sharing_cart',\n },\n {\n key: 'no_course_modules_in_section_description',\n component: 'block_sharing_cart',\n },\n ]);\n\n await Notification.alert(strings[0], strings[1]);\n\n return;\n }\n\n const modal = await this.createBackupItemToSharingCartModal(sectionName, (settings) => {\n Ajax.call([{\n methodname: 'block_sharing_cart_backup_section_into_sharing_cart',\n args: {\n section_id: sectionId,\n settings: settings\n },\n done: async (data) => {\n await this.renderItem(data);\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n });\n\n await modal.show();\n }\n\n /**\n * @param {Number} courseModuleId\n */\n async addCourseModuleBackupToSharingCart(courseModuleId) {\n const courseModuleName = this.#course.getCourseModuleName(courseModuleId);\n\n const modal = await this.createBackupItemToSharingCartModal(courseModuleName, (settings) => {\n Ajax.call([{\n methodname: 'block_sharing_cart_backup_course_module_into_sharing_cart',\n args: {\n course_module_id: courseModuleId,\n settings: settings\n },\n done: async (data) => {\n await this.renderItem(data);\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n });\n await modal.show();\n }\n\n /**\n * @param {Object} item\n */\n async renderItem(item) {\n const existingItemIndex = this.#items.findIndex((i) => i.getItemId() === item.id);\n const existingItem = this.#items[existingItemIndex] ?? false;\n const getOldElement = () => {\n return this.#element.querySelector('.sharing_cart_items .sharing_cart_item[data-itemid=\"' + item.id + '\"]');\n };\n const oldElement = getOldElement();\n if (existingItem && oldElement) {\n const element = await this.#baseFactory.moodle().template().createElementFromFragment(\n 'block_sharing_cart',\n 'item',\n 1,\n {\n item_id: item.id,\n }\n );\n\n // Early exit if the element has been removed from the DOM in between rendering and checking earlier.\n if (getOldElement() !== oldElement) {\n return;\n }\n\n this.#element.querySelector('.sharing_cart_items').replaceChild(element, oldElement);\n this.#items[existingItemIndex] = this.#baseFactory.block().item().element(this, element);\n\n await this.setupItem(element);\n for (const subItem of element.querySelectorAll('.sharing_cart_item')) {\n await this.setupItem(subItem);\n }\n\n return;\n }\n\n const element = await this.#baseFactory.moodle().template().createElementFromTemplate(\n 'block_sharing_cart/block/item',\n {\n id: item.id,\n name: item.name,\n type: item.type,\n status: 0,\n old_instance_id: item.old_instance_id,\n status_awaiting: true,\n has_run_now: true,\n task_id: item.task_id ?? null,\n status_finished: false,\n status_failed: false,\n is_module: item.type !== 'section',\n is_section: item.type === 'section',\n is_root: true,\n }\n );\n this.#element.querySelector('.sharing_cart_items').prepend(element);\n\n await this.setupItem(element);\n }\n\n /**\n * @param {ItemElement} item\n * @param {Number} sectionId\n * @param {HTMLElement} modal\n */\n importItem(item, sectionId, modal) {\n this.#course.clearClipboard();\n\n const courseModuleIds = [];\n modal.querySelectorAll('input[type=\"checkbox\"][data-type=\"coursemodule\"]:checked').forEach((checkbox) => {\n courseModuleIds.push(checkbox.dataset.id);\n });\n\n if (item.isSection() && courseModuleIds.length === 0) {\n modal.querySelectorAll('.form-check-input').forEach(async (item) => {\n item.setCustomValidity(\n await get_string('atleast_one_course_module_must_be_included', 'block_sharing_cart')\n );\n item.reportValidity();\n });\n return false;\n }\n\n if (item.isModule()) {\n courseModuleIds.push(item.getItemOldInstanceId());\n }\n\n Ajax.call([{\n methodname: 'block_sharing_cart_restore_item_from_sharing_cart_into_section',\n args: {\n item_id: item.getItemId(),\n section_id: sectionId,\n course_modules_to_include: courseModuleIds,\n },\n done: async (success) => {\n if (success) {\n await this.#queue.loadQueue(true);\n }\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n /**\n * @param {ItemElement} item\n * @param {Number} sectionId\n * @param {Event} e\n */\n async confirmImportBackupFromSharingCart(item, sectionId, e) {\n e.preventDefault();\n e.stopPropagation();\n\n const strings = await get_strings([\n {\n key: 'copy_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'into_section',\n component: 'block_sharing_cart',\n },\n {\n key: 'import',\n component: 'core',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const sectionName = this.#course.getSectionName(sectionId);\n\n const {html, js} = await this.#baseFactory.moodle().template().renderFragment(\n 'block_sharing_cart',\n 'item_restore_form',\n 1,\n {\n item_id: item.getItemId()\n }\n );\n\n const modal = await ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: strings[0] + ': ' +\n '\"' + item.getItemName().slice(0, 50).trim() + '\"' +\n ' ' + strings[1] + ': ' +\n '\"' + sectionName.slice(0, 50).trim() + '\"',\n body: html,\n buttons: {\n save: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n modal.getRoot().on(ModalEvents.shown, () => this.#baseFactory.moodle().template().runTemplateJS(js));\n modal.getRoot().on(ModalEvents.save, this.importItem.bind(this, item, sectionId, modal.getRoot()[0]));\n await modal.show();\n }\n\n /**\n * @param {Array} itemIds\n */\n async confirmDeleteItems(itemIds) {\n const strings = await get_strings([\n {\n key: 'delete_items',\n component: 'block_sharing_cart',\n },\n {\n key: 'confirm_delete_items',\n component: 'block_sharing_cart',\n },\n {\n key: 'delete',\n component: 'core',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const modal = await ModalFactory.create({\n type: ModalFactory.types.DELETE_CANCEL,\n title: strings[0],\n body: strings[1],\n buttons: {\n delete: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n\n modal.getRoot().on(ModalEvents.delete, this.deleteItems.bind(this, itemIds));\n await modal.show();\n }\n}\n"],"names":["constructor","baseFactory","element","canBackupUserdata","canAnonymizeUserdata","showSharingCartBasket","addEventListeners","setupCourse","setupQueue","setupItems","setupDragAndDrop","setupBulkDelete","course","this","queue","block","document","querySelector","_classPrivateFieldGet","items","querySelectorAll","setupItem","Sortable","dataIdAttr","onUpdate","call","methodname","args","item_ids","toArray","fail","data","exception","dropZone","addEventListener","e","preventDefault","stopPropagation","async","addSectionBackupToSharingCart","addCourseModuleBackupToSharingCart","enableBulkDeleteButton","disableBulkDeleteButton","bulkDeleteButton","selectAllContainer","itemCheckboxes","getItemCheckboxes","allSelected","Array","from","every","checkbox","checked","forEach","updateSelectAllState","updateBulkDeleteButtonState","length","classList","add","remove","disabled","itemIds","push","value","confirmDeleteItems","itemElement","item","getStatus","isBulkDeleteEnabled","existingItemIndex","findIndex","i","getItemId","some","selectAllCheckbox","selectAllLabel","someSelected","then","str","textContent","indeterminate","setClipboard","clearClipboard","setDraggedSectionId","id","setDraggedCourseModuleId","getItemChildrenRecursively","childItem","index","Number","parseInt","dataset","itemid","_classPrivateFieldGet2","splice","_classPrivateFieldGet3","deleteItem","item_id","done","deleted","removeItemElement","Notification","alert","deleteItems","map","filter","includes","deletedItemIds","getItemName","getElementById","getElement","itemName","onSave","strings","key","component","html","js","moodle","template","renderTemplate","show_user_data_backup","show_anonymize_user_data","modal","ModalFactory","create","type","types","SAVE_CANCEL","title","slice","trim","body","buttons","save","cancel","removeOnClose","getRoot","on","ModalEvents","shown","runTemplateJS","modalUserdataCheckbox","modalAnonymizeCheckbox","users","anonymize","sectionId","sectionName","getSectionName","getSectionCourseModules","createBackupItemToSharingCartModal","settings","section_id","renderItem","show","courseModuleId","courseModuleName","getCourseModuleName","course_module_id","existingItem","getOldElement","oldElement","createElementFromFragment","replaceChild","subItem","createElementFromTemplate","name","status","old_instance_id","status_awaiting","has_run_now","task_id","status_finished","status_failed","is_module","is_section","is_root","prepend","importItem","courseModuleIds","isSection","setCustomValidity","reportValidity","isModule","getItemOldInstanceId","course_modules_to_include","success","loadQueue","renderFragment","bind","DELETE_CANCEL","delete"],"mappings":"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"} \ No newline at end of file diff --git a/amd/build/app/block/item/element.min.js b/amd/build/app/block/item/element.min.js index e047217..385d4d0 100644 --- a/amd/build/app/block/item/element.min.js +++ b/amd/build/app/block/item/element.min.js @@ -1,3 +1,3 @@ -define("block_sharing_cart/app/block/item/element",["exports","core/modal_factory","core/modal_events","core/notification","core/str","core/ajax"],(function(_exports,_modal_factory,_modal_events,_notification,_str,_ajax){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classPrivateMethodInitSpec(obj,privateSet){_checkPrivateRedeclaration(obj,privateSet),privateSet.add(obj)}function _classPrivateFieldInitSpec(obj,privateMap,value){_checkPrivateRedeclaration(obj,privateMap),privateMap.set(obj,value)}function _checkPrivateRedeclaration(obj,privateCollection){if(privateCollection.has(obj))throw new TypeError("Cannot initialize the same private elements twice on an object")}function _classPrivateMethodGet(receiver,privateSet,fn){if(!privateSet.has(receiver))throw new TypeError("attempted to get private field on non-instance");return fn}function _classPrivateFieldGet(receiver,privateMap){return function(receiver,descriptor){if(descriptor.get)return descriptor.get.call(receiver);return descriptor.value}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"get"))}function _classPrivateFieldSet(receiver,privateMap,value){return function(receiver,descriptor,value){if(descriptor.set)descriptor.set.call(receiver,value);else{if(!descriptor.writable)throw new TypeError("attempted to set read only private field");descriptor.value=value}}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"set"),value),value}function _classExtractFieldDescriptor(receiver,privateMap,action){if(!privateMap.has(receiver))throw new TypeError("attempted to "+action+" private field on non-instance");return privateMap.get(receiver)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_notification=_interopRequireDefault(_notification),_ajax=_interopRequireDefault(_ajax);var _baseFactory=new WeakMap,_blockElement=new WeakMap,_element=new WeakMap,_pollItem=new WeakSet,_addEventListeners=new WeakSet;function _pollItem2(){let currentTry=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,retries=arguments.length>1&&void 0!==arguments[1]?arguments[1]:10;currentTry+=1,currentTry>=retries||_ajax.default.call([{methodname:"block_sharing_cart_get_item_from_sharing_cart",args:{item_id:this.getItemId()},done:async item=>{0!==item.status?await _classPrivateFieldGet(this,_blockElement).renderItem(item):new Promise((resolve=>{setTimeout(resolve,1e3*currentTry)})).then((()=>{_classPrivateMethodGet(this,_pollItem,_pollItem2).call(this,currentTry,retries)}))},fail:data=>{_notification.default.exception(data)}}])}function _addEventListeners2(){var _actionsContainer$que,_actionsContainer$que2,_actionsContainer$que3;_classPrivateFieldGet(this,_element).querySelector(".info").addEventListener("click",this.toggleCollapseRecursively.bind(this));const checkbox=_classPrivateFieldGet(this,_element).querySelector('input[data-action="bulk_select"][type="checkbox"]');null==checkbox||checkbox.addEventListener("click",(()=>{_classPrivateFieldGet(this,_blockElement).updateSelectAllState(),_classPrivateFieldGet(this,_blockElement).updateBulkDeleteButtonState()}));const actionsContainer=_classPrivateFieldGet(this,_element).querySelector(":scope > .item-body .sharing_cart_item_actions");null==actionsContainer||null===(_actionsContainer$que=actionsContainer.querySelector('[data-action="delete"]'))||void 0===_actionsContainer$que||_actionsContainer$que.addEventListener("click",this.confirmDeleteItem.bind(this)),null==actionsContainer||null===(_actionsContainer$que2=actionsContainer.querySelector('[data-action="copy_to_course"]'))||void 0===_actionsContainer$que2||_actionsContainer$que2.addEventListener("click",this.copyItemToCourse.bind(this)),null==actionsContainer||null===(_actionsContainer$que3=actionsContainer.querySelector('[data-action="run_now"]'))||void 0===_actionsContainer$que3||_actionsContainer$que3.addEventListener("click",this.runNow.bind(this))}return _exports.default=class{constructor(baseFactory,blockElement,element){_classPrivateMethodInitSpec(this,_addEventListeners),_classPrivateMethodInitSpec(this,_pollItem),_classPrivateFieldInitSpec(this,_baseFactory,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_blockElement,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_element,{writable:!0,value:void 0}),_classPrivateFieldSet(this,_baseFactory,baseFactory),_classPrivateFieldSet(this,_blockElement,blockElement),_classPrivateFieldSet(this,_element,element),"0"===_classPrivateFieldGet(this,_element).dataset.status&&_classPrivateMethodGet(this,_pollItem,_pollItem2).call(this),_classPrivateMethodGet(this,_addEventListeners,_addEventListeners2).call(this)}async copyItemToCourse(e){e.preventDefault(),e.stopPropagation(),await _classPrivateFieldGet(this,_blockElement).setClipboard(this)}async runNow(e){var _currentTarget$datase,_currentTarget$datase2;e.preventDefault(),e.stopPropagation();const currentTarget=e.currentTarget;currentTarget.disabled=!0,_ajax.default.call([{methodname:"block_sharing_cart_run_task_now",args:{task_id:null!==(_currentTarget$datase=null==currentTarget||null===(_currentTarget$datase2=currentTarget.dataset)||void 0===_currentTarget$datase2?void 0:_currentTarget$datase2.taskId)&&void 0!==_currentTarget$datase?_currentTarget$datase:null},done:async()=>{currentTarget.remove(),_classPrivateMethodGet(this,_pollItem,_pollItem2).call(this)},fail:data=>{_notification.default.exception(data),currentTarget.disabled=!1}}])}async confirmDeleteItem(e){e.preventDefault(),e.stopPropagation();const strings=await(0,_str.get_strings)([{key:"delete_item",component:"block_sharing_cart"},{key:"confirm_delete_item",component:"block_sharing_cart"},{key:"delete",component:"core"},{key:"cancel",component:"core"}]),modal=await _modal_factory.default.create({type:_modal_factory.default.types.DELETE_CANCEL,title:strings[0]+': "'+this.getItemName().slice(0,50).trim()+'"',body:strings[1],buttons:{delete:strings[2],cancel:strings[3]},removeOnClose:!0});modal.getRoot().on(_modal_events.default.delete,_classPrivateFieldGet(this,_blockElement).deleteItem.bind(_classPrivateFieldGet(this,_blockElement),this)),await modal.show()}getItemChildrenRecursively(){return _classPrivateFieldGet(this,_element).querySelectorAll(".sharing_cart_item")}getItemElement(){return _classPrivateFieldGet(this,_element)}getStatus(){return _classPrivateFieldGet(this,_element).dataset.status}getItemName(){return _classPrivateFieldGet(this,_element).querySelector(".name").innerText}getItemId(){return Number.parseInt(_classPrivateFieldGet(this,_element).dataset.itemid)}getItemOldInstanceId(){return Number.parseInt(_classPrivateFieldGet(this,_element).dataset.oldinstanceid)}getItemInfo(){return _classPrivateFieldGet(this,_element).querySelector(".info")}toggleCollapse(item){let collapse=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if("section"!==item.dataset.type&&"0"!==item.dataset.status&&"2"!==item.dataset.status)return;item.dataset.collapsed=null!==collapse?collapse?"true":"false":"true"===item.dataset.collapsed?"false":"true";const iconElement=item.querySelector(".info > i");iconElement.classList.contains("fa-exclamation-triangle")||(iconElement.classList.remove("fa-folder-o","fa-folder-open-o"),iconElement.classList.add("true"===item.dataset.collapsed?"fa-folder-o":"fa-folder-open-o"))}isModule(){return!this.isSection()}isSection(){return"section"===_classPrivateFieldGet(this,_element).dataset.type}toggleCollapseRecursively(e){e.preventDefault(),e.stopPropagation(),this.isModule()||"1"!==_classPrivateFieldGet(this,_element).dataset.status||(this.toggleCollapse(_classPrivateFieldGet(this,_element)),this.getItemChildrenRecursively().forEach((item=>{this.toggleCollapse(item,"true"===_classPrivateFieldGet(this,_element).dataset.collapsed)})))}remove(){_classPrivateFieldGet(this,_element).remove()}},_exports.default})); +define("block_sharing_cart/app/block/item/element",["exports","core/modal_factory","core/modal_events","core/notification","core/str","core/ajax"],(function(_exports,_modal_factory,_modal_events,_notification,_str,_ajax){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classPrivateMethodInitSpec(obj,privateSet){_checkPrivateRedeclaration(obj,privateSet),privateSet.add(obj)}function _classPrivateFieldInitSpec(obj,privateMap,value){_checkPrivateRedeclaration(obj,privateMap),privateMap.set(obj,value)}function _checkPrivateRedeclaration(obj,privateCollection){if(privateCollection.has(obj))throw new TypeError("Cannot initialize the same private elements twice on an object")}function _classPrivateMethodGet(receiver,privateSet,fn){if(!privateSet.has(receiver))throw new TypeError("attempted to get private field on non-instance");return fn}function _classPrivateFieldGet(receiver,privateMap){return function(receiver,descriptor){if(descriptor.get)return descriptor.get.call(receiver);return descriptor.value}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"get"))}function _classPrivateFieldSet(receiver,privateMap,value){return function(receiver,descriptor,value){if(descriptor.set)descriptor.set.call(receiver,value);else{if(!descriptor.writable)throw new TypeError("attempted to set read only private field");descriptor.value=value}}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"set"),value),value}function _classExtractFieldDescriptor(receiver,privateMap,action){if(!privateMap.has(receiver))throw new TypeError("attempted to "+action+" private field on non-instance");return privateMap.get(receiver)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_notification=_interopRequireDefault(_notification),_ajax=_interopRequireDefault(_ajax);const polls=[];var _baseFactory=new WeakMap,_blockElement=new WeakMap,_element=new WeakMap,_pollItem=new WeakSet,_addEventListeners=new WeakSet;function _pollItem2(){let currentTry=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,retries=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1,uuid=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;if(null===uuid){if(uuid=crypto.randomUUID(),polls[this.getItemId()])return;polls[this.getItemId()]=uuid}else if(polls[this.getItemId()]!==uuid)return;currentTry+=1,-1!==retries&¤tTry>=retries||_ajax.default.call([{methodname:"block_sharing_cart_get_item_from_sharing_cart",args:{item_id:this.getItemId()},done:async item=>{if(0!==item.status)polls.splice(this.getItemId(),1),await _classPrivateFieldGet(this,_blockElement).renderItem(item);else{setTimeout((()=>{_classPrivateMethodGet(this,_pollItem,_pollItem2).call(this,currentTry,retries,uuid)}),currentTry>10?1e4:1e3*currentTry)}},fail:data=>{_notification.default.exception(data)}}])}function _addEventListeners2(){var _actionsContainer$que,_actionsContainer$que2,_actionsContainer$que3;_classPrivateFieldGet(this,_element).querySelector(".info").addEventListener("click",this.toggleCollapseRecursively.bind(this));const checkbox=_classPrivateFieldGet(this,_element).querySelector('input[data-action="bulk_select"][type="checkbox"]');null==checkbox||checkbox.addEventListener("click",(e=>{e.stopImmediatePropagation(),_classPrivateFieldGet(this,_blockElement).updateSelectAllState(),_classPrivateFieldGet(this,_blockElement).updateBulkDeleteButtonState()}));const actionsContainer=_classPrivateFieldGet(this,_element).querySelector(":scope > .item-body .sharing_cart_item_actions");null==actionsContainer||null===(_actionsContainer$que=actionsContainer.querySelector('[data-action="delete"]'))||void 0===_actionsContainer$que||_actionsContainer$que.addEventListener("click",this.confirmDeleteItem.bind(this)),null==actionsContainer||null===(_actionsContainer$que2=actionsContainer.querySelector('[data-action="copy_to_course"]'))||void 0===_actionsContainer$que2||_actionsContainer$que2.addEventListener("click",this.copyItemToCourse.bind(this)),null==actionsContainer||null===(_actionsContainer$que3=actionsContainer.querySelector('[data-action="run_now"]'))||void 0===_actionsContainer$que3||_actionsContainer$que3.addEventListener("click",this.runNow.bind(this))}return _exports.default=class{constructor(baseFactory,blockElement,element){_classPrivateMethodInitSpec(this,_addEventListeners),_classPrivateMethodInitSpec(this,_pollItem),_classPrivateFieldInitSpec(this,_baseFactory,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_blockElement,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_element,{writable:!0,value:void 0}),_classPrivateFieldSet(this,_baseFactory,baseFactory),_classPrivateFieldSet(this,_blockElement,blockElement),_classPrivateFieldSet(this,_element,element),"0"===_classPrivateFieldGet(this,_element).dataset.status&&_classPrivateMethodGet(this,_pollItem,_pollItem2).call(this),_classPrivateMethodGet(this,_addEventListeners,_addEventListeners2).call(this)}async copyItemToCourse(e){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),await _classPrivateFieldGet(this,_blockElement).setClipboard(this)}async runNow(e){var _currentTarget$datase,_currentTarget$datase2;e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation();const currentTarget=e.currentTarget;currentTarget.disabled=!0,_ajax.default.call([{methodname:"block_sharing_cart_run_task_now",args:{task_id:null!==(_currentTarget$datase=null==currentTarget||null===(_currentTarget$datase2=currentTarget.dataset)||void 0===_currentTarget$datase2?void 0:_currentTarget$datase2.taskId)&&void 0!==_currentTarget$datase?_currentTarget$datase:null},done:async()=>{currentTarget.remove(),_classPrivateMethodGet(this,_pollItem,_pollItem2).call(this)},fail:data=>{_notification.default.exception(data),currentTarget.disabled=!1}}])}async confirmDeleteItem(e){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation();const strings=await(0,_str.get_strings)([{key:"delete_item",component:"block_sharing_cart"},{key:"confirm_delete_item",component:"block_sharing_cart"},{key:"delete",component:"core"},{key:"cancel",component:"core"}]),modal=await _modal_factory.default.create({type:_modal_factory.default.types.DELETE_CANCEL,title:strings[0]+': "'+this.getItemName().slice(0,50).trim()+'"',body:strings[1],buttons:{delete:strings[2],cancel:strings[3]},removeOnClose:!0});modal.getRoot().on(_modal_events.default.delete,_classPrivateFieldGet(this,_blockElement).deleteItem.bind(_classPrivateFieldGet(this,_blockElement),this)),await modal.show()}getItemChildrenRecursively(){return _classPrivateFieldGet(this,_element).querySelectorAll(".sharing_cart_item")}getItemElement(){return _classPrivateFieldGet(this,_element)}getStatus(){return _classPrivateFieldGet(this,_element).dataset.status}getItemName(){return _classPrivateFieldGet(this,_element).querySelector(".name").innerText}getItemId(){return Number.parseInt(_classPrivateFieldGet(this,_element).dataset.itemid)}getItemOldInstanceId(){return Number.parseInt(_classPrivateFieldGet(this,_element).dataset.oldinstanceid)}getItemInfo(){return _classPrivateFieldGet(this,_element).querySelector(".info")}toggleCollapse(item){let collapse=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if("section"!==item.dataset.type&&"0"!==item.dataset.status&&"2"!==item.dataset.status)return;item.dataset.collapsed=null!==collapse?collapse?"true":"false":"true"===item.dataset.collapsed?"false":"true";const iconElement=item.querySelector(".info > i");iconElement.classList.contains("fa-exclamation-triangle")||(iconElement.classList.remove("fa-folder-o","fa-folder-open-o"),iconElement.classList.add("true"===item.dataset.collapsed?"fa-folder-o":"fa-folder-open-o"))}isModule(){return!this.isSection()}isSection(){return"section"===_classPrivateFieldGet(this,_element).dataset.type}toggleCollapseRecursively(e){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.isModule()||"1"!==_classPrivateFieldGet(this,_element).dataset.status||(this.toggleCollapse(_classPrivateFieldGet(this,_element)),this.getItemChildrenRecursively().forEach((item=>{this.toggleCollapse(item,"true"===_classPrivateFieldGet(this,_element).dataset.collapsed)})))}remove(){_classPrivateFieldGet(this,_element).remove()}},_exports.default})); //# sourceMappingURL=element.min.js.map \ No newline at end of file diff --git a/amd/build/app/block/item/element.min.js.map b/amd/build/app/block/item/element.min.js.map index aa81eaa..a30e589 100644 --- a/amd/build/app/block/item/element.min.js.map +++ b/amd/build/app/block/item/element.min.js.map @@ -1 +1 @@ -{"version":3,"file":"element.min.js","sources":["../../../../src/app/block/item/element.js"],"sourcesContent":["import ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport Notification from \"core/notification\";\nimport {get_strings} from \"core/str\";\nimport Ajax from \"core/ajax\";\n\nexport default class ItemElement {\n /**\n * @type {BaseFactory}\n */\n #baseFactory;\n\n /**\n * @type {BlockElement}\n */\n #blockElement;\n\n /**\n * @type {HTMLElement}\n */\n #element;\n\n /**\n * @param {BaseFactory} baseFactory\n * @param {BlockElement} blockElement\n * @param {HTMLElement} element\n */\n constructor(baseFactory, blockElement, element) {\n this.#baseFactory = baseFactory;\n this.#blockElement = blockElement;\n this.#element = element;\n\n if (this.#element.dataset.status === '0') {\n this.#pollItem();\n }\n\n this.#addEventListeners();\n }\n\n #pollItem(currentTry = 0, retries = 10) {\n currentTry += 1;\n\n if (currentTry >= retries) {\n return;\n }\n\n Ajax.call([{\n methodname: 'block_sharing_cart_get_item_from_sharing_cart',\n args: {\n item_id: this.getItemId(),\n },\n done: async (item) => {\n if (item.status === 0) {\n new Promise(\n (resolve) => {\n setTimeout(resolve, currentTry * 1000);\n }\n ).then(\n () => {\n this.#pollItem(currentTry, retries);\n }\n );\n\n return;\n }\n\n await this.#blockElement.renderItem(item);\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n #addEventListeners() {\n this.#element.querySelector('.info').addEventListener('click', this.toggleCollapseRecursively.bind(this));\n\n const checkbox = this.#element.querySelector('input[data-action=\"bulk_select\"][type=\"checkbox\"]');\n checkbox?.addEventListener('click', () => {\n this.#blockElement.updateSelectAllState();\n this.#blockElement.updateBulkDeleteButtonState();\n });\n\n const actionsContainer = this.#element.querySelector(':scope > .item-body .sharing_cart_item_actions');\n\n actionsContainer?.querySelector('[data-action=\"delete\"]')?.addEventListener(\n 'click',\n this.confirmDeleteItem.bind(this)\n );\n actionsContainer?.querySelector('[data-action=\"copy_to_course\"]')?.addEventListener(\n 'click',\n this.copyItemToCourse.bind(this)\n );\n actionsContainer?.querySelector('[data-action=\"run_now\"]')?.addEventListener(\n 'click',\n this.runNow.bind(this)\n );\n }\n\n async copyItemToCourse(e) {\n e.preventDefault();\n e.stopPropagation();\n\n await this.#blockElement.setClipboard(this);\n }\n\n async runNow(e) {\n e.preventDefault();\n e.stopPropagation();\n\n const currentTarget = e.currentTarget;\n currentTarget.disabled = true;\n\n Ajax.call([{\n methodname: 'block_sharing_cart_run_task_now',\n args: {\n task_id: currentTarget?.dataset?.taskId ?? null,\n },\n done: async () => {\n currentTarget.remove();\n this.#pollItem();\n },\n fail: (data) => {\n Notification.exception(data);\n currentTarget.disabled = false;\n }\n }]);\n }\n\n async confirmDeleteItem(e) {\n e.preventDefault();\n e.stopPropagation();\n\n const strings = await get_strings([\n {\n key: 'delete_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'confirm_delete_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'delete',\n component: 'core',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const modal = await ModalFactory.create({\n type: ModalFactory.types.DELETE_CANCEL,\n title: strings[0] + ': \"' + this.getItemName().slice(0, 50).trim() + '\"',\n body: strings[1],\n buttons: {\n delete: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n modal.getRoot().on(ModalEvents.delete, this.#blockElement.deleteItem.bind(this.#blockElement, this));\n await modal.show();\n }\n\n /**\n * @return {NodeListOf}\n */\n getItemChildrenRecursively() {\n return this.#element.querySelectorAll('.sharing_cart_item');\n }\n\n /**\n * @return {HTMLElement}\n */\n getItemElement() {\n return this.#element;\n }\n\n getStatus() {\n return this.#element.dataset.status;\n }\n\n /**\n * @return {String}\n */\n getItemName() {\n return this.#element.querySelector('.name').innerText;\n }\n\n /**\n * @return {Number}\n */\n getItemId() {\n return Number.parseInt(this.#element.dataset.itemid);\n }\n\n /**\n * @return {Number}\n */\n getItemOldInstanceId() {\n return Number.parseInt(this.#element.dataset.oldinstanceid);\n }\n\n /**\n * @return {HTMLElement}\n */\n getItemInfo() {\n return this.#element.querySelector('.info');\n }\n\n /**\n * @param {HTMLElement} item\n * @param {Boolean|NULL} collapse\n */\n toggleCollapse(item, collapse = null) {\n if (item.dataset.type !== 'section' &&\n item.dataset.status !== '0' &&\n item.dataset.status !== '2') {\n return;\n }\n\n if (collapse !== null) {\n item.dataset.collapsed = collapse ? 'true' : 'false';\n } else {\n item.dataset.collapsed = item.dataset.collapsed === 'true' ? 'false' : 'true';\n }\n\n const iconElement = item.querySelector('.info > i');\n if (!iconElement.classList.contains('fa-exclamation-triangle')) {\n iconElement.classList.remove('fa-folder-o', 'fa-folder-open-o');\n iconElement.classList.add(item.dataset.collapsed === 'true' ? 'fa-folder-o' : 'fa-folder-open-o');\n }\n }\n\n isModule() {\n return !this.isSection();\n }\n\n isSection() {\n return this.#element.dataset.type === 'section';\n }\n\n /**\n * @param {Event} e\n */\n toggleCollapseRecursively(e) {\n e.preventDefault();\n e.stopPropagation();\n\n if (this.isModule() || this.#element.dataset.status !== '1') {\n return;\n }\n\n this.toggleCollapse(this.#element);\n this.getItemChildrenRecursively().forEach((item) => {\n this.toggleCollapse(item, this.#element.dataset.collapsed === 'true');\n });\n }\n\n remove() {\n this.#element.remove();\n }\n}\n"],"names":["currentTry","retries","call","methodname","args","item_id","this","getItemId","done","async","item","status","_classPrivateFieldGet","renderItem","Promise","resolve","setTimeout","then","fail","data","exception","querySelector","addEventListener","toggleCollapseRecursively","bind","checkbox","updateSelectAllState","updateBulkDeleteButtonState","actionsContainer","confirmDeleteItem","copyItemToCourse","runNow","constructor","baseFactory","blockElement","element","dataset","e","preventDefault","stopPropagation","setClipboard","currentTarget","disabled","task_id","_currentTarget$datase2","taskId","remove","strings","key","component","modal","ModalFactory","create","type","types","DELETE_CANCEL","title","getItemName","slice","trim","body","buttons","delete","cancel","removeOnClose","getRoot","on","ModalEvents","deleteItem","show","getItemChildrenRecursively","querySelectorAll","getItemElement","getStatus","innerText","Number","parseInt","itemid","getItemOldInstanceId","oldinstanceid","getItemInfo","toggleCollapse","collapse","collapsed","iconElement","classList","contains","add","isModule","isSection","forEach"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"element.min.js","sources":["../../../../src/app/block/item/element.js"],"sourcesContent":["import ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport Notification from \"core/notification\";\nimport {get_strings} from \"core/str\";\nimport Ajax from \"core/ajax\";\n\nconst polls = [];\n\nexport default class ItemElement {\n /**\n * @type {BaseFactory}\n */\n #baseFactory;\n\n /**\n * @type {BlockElement}\n */\n #blockElement;\n\n /**\n * @type {HTMLElement}\n */\n #element;\n\n /**\n * @param {BaseFactory} baseFactory\n * @param {BlockElement} blockElement\n * @param {HTMLElement} element\n */\n constructor(baseFactory, blockElement, element) {\n this.#baseFactory = baseFactory;\n this.#blockElement = blockElement;\n this.#element = element;\n\n if (this.#element.dataset.status === '0') {\n this.#pollItem();\n }\n\n this.#addEventListeners();\n }\n\n #pollItem(currentTry = 0, retries = -1, uuid = null) {\n if (uuid === null) {\n uuid = crypto.randomUUID();\n\n if (polls[this.getItemId()]) {\n return;\n }\n\n polls[this.getItemId()] = uuid;\n } else if (polls[this.getItemId()] !== uuid) {\n return;\n }\n\n currentTry += 1;\n\n if (retries !== -1 && currentTry >= retries) {\n return;\n }\n\n Ajax.call([{\n methodname: 'block_sharing_cart_get_item_from_sharing_cart',\n args: {\n item_id: this.getItemId(),\n },\n done: async(item) => {\n if (item.status === 0) {\n // Cap the timeout at 10 seconds\n const timeOut = currentTry > 10 ? 10000 : currentTry * 1000;\n\n setTimeout(() => {\n this.#pollItem(currentTry, retries, uuid);\n }, timeOut);\n return;\n }\n\n // Remove the item from the polls array\n polls.splice(this.getItemId(), 1);\n\n await this.#blockElement.renderItem(item);\n },\n fail: (data) => {\n Notification.exception(data);\n }\n }]);\n }\n\n #addEventListeners() {\n this.#element.querySelector('.info').addEventListener('click', this.toggleCollapseRecursively.bind(this));\n\n const checkbox = this.#element.querySelector('input[data-action=\"bulk_select\"][type=\"checkbox\"]');\n checkbox?.addEventListener('click', (e) => {\n e.stopImmediatePropagation();\n\n this.#blockElement.updateSelectAllState();\n this.#blockElement.updateBulkDeleteButtonState();\n });\n\n const actionsContainer = this.#element.querySelector(':scope > .item-body .sharing_cart_item_actions');\n\n actionsContainer?.querySelector('[data-action=\"delete\"]')?.addEventListener(\n 'click',\n this.confirmDeleteItem.bind(this)\n );\n actionsContainer?.querySelector('[data-action=\"copy_to_course\"]')?.addEventListener(\n 'click',\n this.copyItemToCourse.bind(this)\n );\n actionsContainer?.querySelector('[data-action=\"run_now\"]')?.addEventListener(\n 'click',\n this.runNow.bind(this)\n );\n }\n\n async copyItemToCourse(e) {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n\n await this.#blockElement.setClipboard(this);\n }\n\n async runNow(e) {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n\n const currentTarget = e.currentTarget;\n currentTarget.disabled = true;\n\n Ajax.call([{\n methodname: 'block_sharing_cart_run_task_now',\n args: {\n task_id: currentTarget?.dataset?.taskId ?? null,\n },\n done: async () => {\n currentTarget.remove();\n this.#pollItem();\n },\n fail: (data) => {\n Notification.exception(data);\n currentTarget.disabled = false;\n }\n }]);\n }\n\n async confirmDeleteItem(e) {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n\n const strings = await get_strings([\n {\n key: 'delete_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'confirm_delete_item',\n component: 'block_sharing_cart',\n },\n {\n key: 'delete',\n component: 'core',\n },\n {\n key: 'cancel',\n component: 'core',\n }\n ]);\n\n const modal = await ModalFactory.create({\n type: ModalFactory.types.DELETE_CANCEL,\n title: strings[0] + ': \"' + this.getItemName().slice(0, 50).trim() + '\"',\n body: strings[1],\n buttons: {\n delete: strings[2],\n cancel: strings[3],\n },\n removeOnClose: true,\n });\n modal.getRoot().on(ModalEvents.delete, this.#blockElement.deleteItem.bind(this.#blockElement, this));\n await modal.show();\n }\n\n /**\n * @return {NodeListOf}\n */\n getItemChildrenRecursively() {\n return this.#element.querySelectorAll('.sharing_cart_item');\n }\n\n /**\n * @return {HTMLElement}\n */\n getItemElement() {\n return this.#element;\n }\n\n getStatus() {\n return this.#element.dataset.status;\n }\n\n /**\n * @return {String}\n */\n getItemName() {\n return this.#element.querySelector('.name').innerText;\n }\n\n /**\n * @return {Number}\n */\n getItemId() {\n return Number.parseInt(this.#element.dataset.itemid);\n }\n\n /**\n * @return {Number}\n */\n getItemOldInstanceId() {\n return Number.parseInt(this.#element.dataset.oldinstanceid);\n }\n\n /**\n * @return {HTMLElement}\n */\n getItemInfo() {\n return this.#element.querySelector('.info');\n }\n\n /**\n * @param {HTMLElement} item\n * @param {Boolean|NULL} collapse\n */\n toggleCollapse(item, collapse = null) {\n if (item.dataset.type !== 'section' &&\n item.dataset.status !== '0' &&\n item.dataset.status !== '2') {\n return;\n }\n\n if (collapse !== null) {\n item.dataset.collapsed = collapse ? 'true' : 'false';\n } else {\n item.dataset.collapsed = item.dataset.collapsed === 'true' ? 'false' : 'true';\n }\n\n const iconElement = item.querySelector('.info > i');\n if (!iconElement.classList.contains('fa-exclamation-triangle')) {\n iconElement.classList.remove('fa-folder-o', 'fa-folder-open-o');\n iconElement.classList.add(item.dataset.collapsed === 'true' ? 'fa-folder-o' : 'fa-folder-open-o');\n }\n }\n\n isModule() {\n return !this.isSection();\n }\n\n isSection() {\n return this.#element.dataset.type === 'section';\n }\n\n /**\n * @param {Event} e\n */\n toggleCollapseRecursively(e) {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n\n if (this.isModule() || this.#element.dataset.status !== '1') {\n return;\n }\n\n this.toggleCollapse(this.#element);\n this.getItemChildrenRecursively().forEach((item) => {\n this.toggleCollapse(item, this.#element.dataset.collapsed === 'true');\n });\n }\n\n remove() {\n this.#element.remove();\n }\n}\n"],"names":["polls","currentTry","retries","uuid","crypto","randomUUID","this","getItemId","call","methodname","args","item_id","done","async","item","status","splice","_classPrivateFieldGet","renderItem","setTimeout","fail","data","exception","querySelector","addEventListener","toggleCollapseRecursively","bind","checkbox","e","stopImmediatePropagation","updateSelectAllState","updateBulkDeleteButtonState","actionsContainer","confirmDeleteItem","copyItemToCourse","runNow","constructor","baseFactory","blockElement","element","dataset","preventDefault","stopPropagation","setClipboard","currentTarget","disabled","task_id","_currentTarget$datase2","taskId","remove","strings","key","component","modal","ModalFactory","create","type","types","DELETE_CANCEL","title","getItemName","slice","trim","body","buttons","delete","cancel","removeOnClose","getRoot","on","ModalEvents","deleteItem","show","getItemChildrenRecursively","querySelectorAll","getItemElement","getStatus","innerText","Number","parseInt","itemid","getItemOldInstanceId","oldinstanceid","getItemInfo","toggleCollapse","collapse","collapsed","iconElement","classList","contains","add","isModule","isSection","forEach"],"mappings":"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"} \ No newline at end of file diff --git a/amd/src/app/block/element.js b/amd/src/app/block/element.js index 79c405d..6623c85 100644 --- a/amd/src/app/block/element.js +++ b/amd/src/app/block/element.js @@ -252,9 +252,14 @@ export default class BlockElement { checkbox?.classList?.remove('d-none'); } - this.#element.querySelector('.no-items')?.remove(); + this.#element.querySelector('.no-items').classList.add('d-none'); - this.#items.push(itemElement); + const existingItemIndex = this.#items.findIndex((i) => i.getItemId() === itemElement.getItemId()); + if (existingItemIndex !== -1) { + this.#items[existingItemIndex] = itemElement; + } else { + this.#items.push(itemElement); + } this.updateBulkDeleteButtonState(); this.updateSelectAllState(); @@ -348,8 +353,7 @@ export default class BlockElement { item.remove(); if (this.#items.length === 0) { - this.#element.querySelector('.sharing_cart_items') - .innerHTML = await get_string('no_items', 'block_sharing_cart'); + this.#element.querySelector('.no-items').classList.remove('d-none'); } } @@ -365,6 +369,7 @@ export default class BlockElement { done: async (deleted) => { if (deleted) { await this.removeItemElement(item); + this.updateSelectAllState(); } else { await Notification.alert('Failed to delete item'); } diff --git a/amd/src/app/block/item/element.js b/amd/src/app/block/item/element.js index 50ffc9e..15a138b 100644 --- a/amd/src/app/block/item/element.js +++ b/amd/src/app/block/item/element.js @@ -4,6 +4,8 @@ import Notification from "core/notification"; import {get_strings} from "core/str"; import Ajax from "core/ajax"; +const polls = []; + export default class ItemElement { /** * @type {BaseFactory} @@ -37,10 +39,22 @@ export default class ItemElement { this.#addEventListeners(); } - #pollItem(currentTry = 0, retries = 10) { + #pollItem(currentTry = 0, retries = -1, uuid = null) { + if (uuid === null) { + uuid = crypto.randomUUID(); + + if (polls[this.getItemId()]) { + return; + } + + polls[this.getItemId()] = uuid; + } else if (polls[this.getItemId()] !== uuid) { + return; + } + currentTry += 1; - if (currentTry >= retries) { + if (retries !== -1 && currentTry >= retries) { return; } @@ -49,21 +63,20 @@ export default class ItemElement { args: { item_id: this.getItemId(), }, - done: async (item) => { + done: async(item) => { if (item.status === 0) { - new Promise( - (resolve) => { - setTimeout(resolve, currentTry * 1000); - } - ).then( - () => { - this.#pollItem(currentTry, retries); - } - ); + // Cap the timeout at 10 seconds + const timeOut = currentTry > 10 ? 10000 : currentTry * 1000; + setTimeout(() => { + this.#pollItem(currentTry, retries, uuid); + }, timeOut); return; } + // Remove the item from the polls array + polls.splice(this.getItemId(), 1); + await this.#blockElement.renderItem(item); }, fail: (data) => { @@ -76,7 +89,9 @@ export default class ItemElement { this.#element.querySelector('.info').addEventListener('click', this.toggleCollapseRecursively.bind(this)); const checkbox = this.#element.querySelector('input[data-action="bulk_select"][type="checkbox"]'); - checkbox?.addEventListener('click', () => { + checkbox?.addEventListener('click', (e) => { + e.stopImmediatePropagation(); + this.#blockElement.updateSelectAllState(); this.#blockElement.updateBulkDeleteButtonState(); }); @@ -100,6 +115,7 @@ export default class ItemElement { async copyItemToCourse(e) { e.preventDefault(); e.stopPropagation(); + e.stopImmediatePropagation(); await this.#blockElement.setClipboard(this); } @@ -107,6 +123,7 @@ export default class ItemElement { async runNow(e) { e.preventDefault(); e.stopPropagation(); + e.stopImmediatePropagation(); const currentTarget = e.currentTarget; currentTarget.disabled = true; @@ -130,6 +147,7 @@ export default class ItemElement { async confirmDeleteItem(e) { e.preventDefault(); e.stopPropagation(); + e.stopImmediatePropagation(); const strings = await get_strings([ { @@ -248,6 +266,7 @@ export default class ItemElement { toggleCollapseRecursively(e) { e.preventDefault(); e.stopPropagation(); + e.stopImmediatePropagation(); if (this.isModule() || this.#element.dataset.status !== '1') { return; diff --git a/classes/output/block/item.php b/classes/output/block/item.php index 07dc27b..f08ca9a 100644 --- a/classes/output/block/item.php +++ b/classes/output/block/item.php @@ -119,4 +119,4 @@ function (entity $item) use ($not_running_backup_tasks) { return (array)$root_item_context; } -} \ No newline at end of file +} diff --git a/classes/task/asynchronous_backup_task.php b/classes/task/asynchronous_backup_task.php index 32c174e..ac2c69d 100644 --- a/classes/task/asynchronous_backup_task.php +++ b/classes/task/asynchronous_backup_task.php @@ -95,6 +95,11 @@ public function execute(): void } } + public function retry_until_success(): bool + { + return false; + } + private function before_backup_started_hook(\backup_controller $backup_controller): void { try { diff --git a/classes/task/asynchronous_restore_task.php b/classes/task/asynchronous_restore_task.php index b9c94f9..5cd9fb3 100644 --- a/classes/task/asynchronous_restore_task.php +++ b/classes/task/asynchronous_restore_task.php @@ -99,6 +99,11 @@ public function execute(): void } } + public function retry_until_success(): bool + { + return false; + } + private function after_restore_finished_hook(\restore_controller $restore_controller): void { try { diff --git a/lang/da/block_sharing_cart.php b/lang/da/block_sharing_cart.php index fd963af..d7e9337 100644 --- a/lang/da/block_sharing_cart.php +++ b/lang/da/block_sharing_cart.php @@ -6,9 +6,9 @@ // Block $string['items'] = 'Backups'; $string['restores'] = 'Kopieringer'; -$string['no_items'] = '
Ingen backups.
+$string['no_items'] = 'Ingen backups.

-Træk og slip aktiviteter eller sektioner ind i delingskurven eller klik på ikonet, for at tilføje elementer til Delingskurven.
'; +Træk og slip aktiviteter eller sektioner ind i delingskurven eller klik på ikonet, for at tilføje elementer til Delingskurven.'; $string['no_restores'] = '
Ingen kopieringer i gang.

Klik på ikonet for at tilføje elementer fra Delingskurven til kurset.
'; @@ -38,6 +38,8 @@ $string['anonymize_user_data'] = 'Vil du anonymisere brugerdata?'; $string['atleast_one_course_module_must_be_included'] = 'Mindst et kursusmodul skal inkluderes, vælg venligst mindst et kursusmodul at inkludere.'; $string['legacy_section_info'] = 'Dette er en gammel sektion. Delingskurven kan ikke kopiere denne sektion, men de enkelte aktiviteter er stadig tilgængelige.'; +$string['restore_failed'] = 'Gendannelsen mislykkedes (task id: {$a}). Denne besked vil forsvinde efter et stykke tid.'; +$string['backup_failed'] = 'Backuppen mislykkedes. Du kan slette elementet fra Delingskurven og prøve igen.'; $string['maybe_the_queue_is_stuck'] = 'Hvis du vil køre kopieringen nu, skal du klikke på knappen ovenfor.'; $string['drop_here'] = 'Slip her...'; $string['original_course'] = 'Originalt kursus:'; diff --git a/lang/en/block_sharing_cart.php b/lang/en/block_sharing_cart.php index 8b2cdcd..83a49a0 100644 --- a/lang/en/block_sharing_cart.php +++ b/lang/en/block_sharing_cart.php @@ -6,9 +6,9 @@ // Block $string['items'] = 'Items'; $string['restores'] = 'Restores'; -$string['no_items'] = '
No items.
+$string['no_items'] = 'No items.

-Drag & drop activities or sections into the sharing cart or click the icon, to add items to the Sharing Cart.
'; +Drag & drop activities or sections into the sharing cart or click the icon, to add items to the Sharing Cart.'; $string['no_restores'] = '
No restores in progress.

Click the icon to add items from the Sharing Cart to the course.
'; @@ -38,6 +38,8 @@ $string['anonymize_user_data'] = 'Do you want to anonymize the user data?'; $string['atleast_one_course_module_must_be_included'] = 'Atleast one course module must be included, please select at least one course module to include.'; $string['legacy_section_info'] = 'This is a legacy section. The sharing cart is unable to copy this section, but the individual activities are still available.'; +$string['restore_failed'] = 'The restore failed (task id: {$a}). This message will disappear after a while.'; +$string['backup_failed'] = 'The backup failed. You can delete the item from the Sharing Cart and try again.'; $string['maybe_the_queue_is_stuck'] = 'If you would like to run the restore now, click the button above.'; $string['drop_here'] = 'Drop here...'; $string['original_course'] = 'Original course:'; diff --git a/templates/block/content.mustache b/templates/block/content.mustache index ab62e7d..e988c56 100644 --- a/templates/block/content.mustache +++ b/templates/block/content.mustache @@ -36,9 +36,10 @@ {{#items}} {{> block_sharing_cart/block/item}} {{/items}} - {{^items}} + +
{{#str}}no_items, block_sharing_cart{{/str}} - {{/items}} +