first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
define("core_reportbuilder/editor",["exports","jquery","core/inplace_editable","core/loadingicon","core/notification","core/pending","core/templates","core/str","core/toast","core_reportbuilder/local/selectors","core_reportbuilder/local/editor/columns","core_reportbuilder/local/editor/conditions","core_reportbuilder/local/editor/filters","core_reportbuilder/local/editor/sorting","core_reportbuilder/local/editor/card_view","core_reportbuilder/local/repository/reports","core_reportbuilder/local/repository/modals"],(function(_exports,_jquery,_inplace_editable,_loadingicon,_notification,_pending,_templates,_str,_toast,reportSelectors,_columns,_conditions,_filters,_sorting,_card_view,_reports,_modals){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending),_templates=_interopRequireDefault(_templates),reportSelectors=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(reportSelectors);let initialized=!1;_exports.init=()=>{(0,_columns.init)(initialized),(0,_conditions.init)(initialized),(0,_filters.init)(initialized),(0,_sorting.init)(initialized),(0,_card_view.init)(initialized),initialized||(document.addEventListener("click",(event=>{const toggleEditViewMode=event.target.closest(reportSelectors.actions.toggleEditPreview);if(toggleEditViewMode){event.preventDefault();const reportElement=event.target.closest(reportSelectors.regions.report),pendingPromise=new _pending.default("core_reportbuilder/reports:get"),toggledEditMode="1"!==toggleEditViewMode.dataset.editMode;(0,_loadingicon.addIconToContainer)(toggleEditViewMode).then((()=>(0,_reports.getReport)(reportElement.dataset.reportId,toggledEditMode))).then((response=>Promise.all([_jquery.default.parseHTML(response.javascript,null,!0).map((node=>node.innerHTML)).join("\n"),_templates.default.renderForPromise("core_reportbuilder/local/dynamictabs/editor",response)]))).then((_ref=>{let[responseJs,{html:html,js:js}]=_ref;return _templates.default.replaceNode(reportElement,html,js+responseJs)})).then((()=>pendingPromise.resolve())).catch(_notification.default.exception)}const reportEdit=event.target.closest(reportSelectors.actions.reportEdit);if(reportEdit){event.preventDefault();const reportModal=(0,_modals.createReportModal)(event.target,(0,_str.getString)("editreportdetails","core_reportbuilder"),reportEdit.dataset.reportId);reportModal.addEventListener(reportModal.events.FORM_SUBMITTED,(()=>{(0,_str.getString)("reportupdated","core_reportbuilder").then(_toast.add).then((()=>window.location.reload())).catch(_notification.default.exception)})),reportModal.show()}})),initialized=!0)}}));
//# sourceMappingURL=editor.min.js.map
File diff suppressed because one or more lines are too long
+10
View File
@@ -0,0 +1,10 @@
define("core_reportbuilder/filters",["exports","core/event_dispatcher","core/fragment","core/notification","core/pending","core/str","core/templates","core/toast","core_form/dynamicform","core_reportbuilder/local/events","core_reportbuilder/local/selectors","core_reportbuilder/local/repository/filters"],(function(_exports,_event_dispatcher,_fragment,_notification,_pending,_str,_templates,_toast,_dynamicform,reportEvents,reportSelectors,_filters){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
/**
* Report builder filter management
*
* @module core_reportbuilder/filters
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending),_templates=_interopRequireDefault(_templates),_dynamicform=_interopRequireDefault(_dynamicform),reportEvents=_interopRequireWildcard(reportEvents),reportSelectors=_interopRequireWildcard(reportSelectors);const setFilterButtonCount=async(reportElement,filterCount)=>{const filterButtonLabel=reportElement.querySelector(reportSelectors.regions.filterButtonLabel);filterButtonLabel.textContent=filterCount>0?await(0,_str.getString)("filtersappliedx","core_reportbuilder",filterCount):await(0,_str.getString)("filters","moodle")};_exports.init=(reportId,contextId)=>{const reportElement=document.querySelector(reportSelectors.forReport(reportId)),filterFormContainer=reportElement.querySelector(reportSelectors.regions.filtersForm);if(filterFormContainer.dataset.initialized)return;filterFormContainer.dataset.initialized=!0;const filterForm=new _dynamicform.default(filterFormContainer,"\\core_reportbuilder\\form\\filter");filterForm.addEventListener(filterForm.events.FORM_SUBMITTED,(event=>{event.preventDefault(),(0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{},reportElement),setFilterButtonCount(reportElement,event.detail),(0,_str.getString)("filtersapplied","core_reportbuilder").then(_toast.add).catch(_notification.default.exception)})),filterForm.addEventListener(filterForm.events.NOSUBMIT_BUTTON_PRESSED,(event=>{event.preventDefault();const pendingPromise=new _pending.default("core_reportbuilder/filters:reset"),reportParameters=reportElement.dataset.parameter;(0,_filters.resetFilters)(reportId,reportParameters).then((()=>(0,_str.getString)("filtersreset","core_reportbuilder"))).then(_toast.add).then((()=>(0,_fragment.loadFragment)("core_reportbuilder","filters_form",contextId,{reportid:reportId,parameters:reportParameters}))).then(((html,js)=>(_templates.default.replaceNodeContents(filterFormContainer,html,js),(0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{},reportElement),setFilterButtonCount(reportElement,0),pendingPromise.resolve()))).catch(_notification.default.exception)})),document.querySelector("#region-main").style.overflowX="visible"}}));
//# sourceMappingURL=filters.min.js.map
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
define("core_reportbuilder/local/editor/card_view",["exports","core_form/dynamicform","core/toast","core/str","core/pubsub","core/notification","core_reportbuilder/local/events","core_reportbuilder/local/selectors"],(function(_exports,_dynamicform,_toast,_str,_pubsub,_notification,reportEvents,reportSelectors){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_dynamicform=_interopRequireDefault(_dynamicform),_notification=_interopRequireDefault(_notification),reportEvents=_interopRequireWildcard(reportEvents),reportSelectors=_interopRequireWildcard(reportSelectors);let cardViewForm=null;_exports.init=initialized=>{(()=>{const cardViewFormContainer=document.querySelector(reportSelectors.regions.settingsCardView);cardViewFormContainer&&(cardViewForm=new _dynamicform.default(cardViewFormContainer,"\\core_reportbuilder\\form\\card_view"),cardViewForm.addEventListener(cardViewForm.events.FORM_SUBMITTED,(event=>{event.preventDefault(),(0,_str.getString)("cardviewsettingssaved","core_reportbuilder").then(_toast.add).catch(_notification.default.exception)})))})(),initialized||(0,_pubsub.subscribe)(reportEvents.publish.reportColumnsUpdated,(()=>{const reportElement=document.querySelector(reportSelectors.regions.report);cardViewForm.load({reportid:reportElement.dataset.reportId})}))}}));
//# sourceMappingURL=card_view.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"card_view.min.js","sources":["../../../src/local/editor/card_view.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Report builder card view editor\n *\n * @module core_reportbuilder/local/editor/card_view\n * @copyright 2021 Mikel Martín <mikel@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n\"use strict\";\n\nimport DynamicForm from 'core_form/dynamicform';\nimport {add as addToast} from 'core/toast';\nimport {getString} from \"core/str\";\nimport {subscribe as subscribe} from 'core/pubsub';\nimport Notification from 'core/notification';\nimport * as reportEvents from 'core_reportbuilder/local/events';\nimport * as reportSelectors from 'core_reportbuilder/local/selectors';\n\nlet cardViewForm = null;\n\n/**\n * Initialise card view form, must be called on each init because the form container is re-created when switching editor modes\n */\nconst initCardViewForm = () => {\n const cardViewFormContainer = document.querySelector(reportSelectors.regions.settingsCardView);\n if (!cardViewFormContainer) {\n return;\n }\n cardViewForm = new DynamicForm(cardViewFormContainer, '\\\\core_reportbuilder\\\\form\\\\card_view');\n\n cardViewForm.addEventListener(cardViewForm.events.FORM_SUBMITTED, (event) => {\n event.preventDefault();\n\n getString('cardviewsettingssaved', 'core_reportbuilder')\n .then(addToast)\n .catch(Notification.exception);\n });\n};\n\n/**\n * Initialise module\n *\n * @param {Boolean} initialized Ensure we only add our listeners once\n */\nexport const init = (initialized) => {\n initCardViewForm();\n if (initialized) {\n return;\n }\n\n // Update form each time a column is added or removed to the custom report.\n subscribe(reportEvents.publish.reportColumnsUpdated, () => {\n const reportElement = document.querySelector(reportSelectors.regions.report);\n cardViewForm.load({reportid: reportElement.dataset.reportId});\n });\n};\n"],"names":["cardViewForm","initialized","cardViewFormContainer","document","querySelector","reportSelectors","regions","settingsCardView","DynamicForm","addEventListener","events","FORM_SUBMITTED","event","preventDefault","then","addToast","catch","Notification","exception","initCardViewForm","reportEvents","publish","reportColumnsUpdated","reportElement","report","load","reportid","dataset","reportId"],"mappings":"omDAiCIA,aAAe,mBA0BEC,cArBI,YACfC,sBAAwBC,SAASC,cAAcC,gBAAgBC,QAAQC,kBACxEL,wBAGLF,aAAe,IAAIQ,qBAAYN,sBAAuB,yCAEtDF,aAAaS,iBAAiBT,aAAaU,OAAOC,gBAAiBC,QAC/DA,MAAMC,oCAEI,wBAAyB,sBAC9BC,KAAKC,YACLC,MAAMC,sBAAaC,gBAU5BC,GACIlB,mCAKMmB,aAAaC,QAAQC,sBAAsB,WAC3CC,cAAgBpB,SAASC,cAAcC,gBAAgBC,QAAQkB,QACrExB,aAAayB,KAAK,CAACC,SAAUH,cAAcI,QAAQC"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
define("core_reportbuilder/local/events",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;return _exports.default={tableReload:"core_reportbuilder_table_reload",publish:{reportColumnsUpdated:"core_reportbuilder_report_columns_updated"}},_exports.default}));
//# sourceMappingURL=events.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"events.min.js","sources":["../../src/local/events.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Report builder events\n *\n * @module core_reportbuilder/local/events\n * @copyright 2021 Paul Holden <paulh@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Events for the Report builder subsystem\n *\n * @constant\n * @property {String} tableReload See {@link event:tableReload}\n */\nexport default {\n /**\n * Trigger table reloading\n *\n * @event tableReload\n * @type {CustomEvent}\n * @property {object} detail\n * @property {Boolean} detail.preservePagination Whether current pagination should be preserved (default false)\n * @property {String} detail.preserveTriggerElement Element selector that should be focused after table reload (default null)\n *\n * @example <caption>Triggering table reload</caption>\n * import {dispatchEvent} from 'core/event_dispatcher';\n * import * as reportEvents from 'core_reportbuilder/local/events';\n *\n * dispatchEvent(reportEvents.tableReload, {}, document.querySelector(...));\n */\n tableReload: 'core_reportbuilder_table_reload',\n publish: {\n reportColumnsUpdated: 'core_reportbuilder_report_columns_updated',\n },\n};\n"],"names":["tableReload","publish","reportColumnsUpdated"],"mappings":"iLA6Be,CAgBXA,YAAa,kCACbC,QAAS,CACLC,qBAAsB"}
@@ -0,0 +1,10 @@
define("core_reportbuilder/local/repository/audiences",["exports","core/ajax"],(function(_exports,_ajax){var obj;
/**
* Module to handle audiences AJAX requests
*
* @module core_reportbuilder/local/repository/audiences
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.deleteAudience=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.deleteAudience=(reportId,instanceId)=>{const request={methodname:"core_reportbuilder_audiences_delete",args:{reportid:reportId,instanceid:instanceId}};return _ajax.default.call([request])[0]}}));
//# sourceMappingURL=audiences.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"audiences.min.js","sources":["../../../src/local/repository/audiences.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle audiences AJAX requests\n *\n * @module core_reportbuilder/local/repository/audiences\n * @copyright 2021 David Matamoros <davidmc@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Remove audience from given report\n *\n * @param {Number} reportId\n * @param {Number} instanceId\n * @return {Promise}\n */\nexport const deleteAudience = (reportId, instanceId) => {\n const request = {\n methodname: 'core_reportbuilder_audiences_delete',\n args: {reportid: reportId, instanceid: instanceId}\n };\n\n return Ajax.call([request])[0];\n};\n"],"names":["reportId","instanceId","request","methodname","args","reportid","instanceid","Ajax","call"],"mappings":";;;;;;;wKAgC8B,CAACA,SAAUC,oBAC/BC,QAAU,CACZC,WAAY,sCACZC,KAAM,CAACC,SAAUL,SAAUM,WAAYL,oBAGpCM,cAAKC,KAAK,CAACN,UAAU"}
+10
View File
@@ -0,0 +1,10 @@
define("core_reportbuilder/local/repository/columns",["exports","core/ajax"],(function(_exports,_ajax){var obj;
/**
* Module to handle column AJAX requests
*
* @module core_reportbuilder/local/repository/columns
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.reorderColumn=_exports.deleteColumn=_exports.addColumn=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.addColumn=(reportId,uniqueIdentifier)=>{const request={methodname:"core_reportbuilder_columns_add",args:{reportid:reportId,uniqueidentifier:uniqueIdentifier}};return _ajax.default.call([request])[0]};_exports.deleteColumn=(reportId,columnId)=>{const request={methodname:"core_reportbuilder_columns_delete",args:{reportid:reportId,columnid:columnId}};return _ajax.default.call([request])[0]};_exports.reorderColumn=(reportId,columnId,position)=>{const request={methodname:"core_reportbuilder_columns_reorder",args:{reportid:reportId,columnid:columnId,position:position}};return _ajax.default.call([request])[0]}}));
//# sourceMappingURL=columns.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"columns.min.js","sources":["../../../src/local/repository/columns.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle column AJAX requests\n *\n * @module core_reportbuilder/local/repository/columns\n * @copyright 2021 Paul Holden <paulh@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Add column to given report\n *\n * @param {Number} reportId\n * @param {String} uniqueIdentifier\n * @return {Promise}\n */\nexport const addColumn = (reportId, uniqueIdentifier) => {\n const request = {\n methodname: 'core_reportbuilder_columns_add',\n args: {reportid: reportId, uniqueidentifier: uniqueIdentifier}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Remove column from given report\n *\n * @param {Number} reportId\n * @param {Number} columnId\n * @return {Promise}\n */\nexport const deleteColumn = (reportId, columnId) => {\n const request = {\n methodname: 'core_reportbuilder_columns_delete',\n args: {reportid: reportId, columnid: columnId}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Re-order column within a report\n *\n * @param {Number} reportId\n * @param {Number} columnId\n * @param {Number} position\n * @return {Promise}\n */\nexport const reorderColumn = (reportId, columnId, position) => {\n const request = {\n methodname: 'core_reportbuilder_columns_reorder',\n args: {reportid: reportId, columnid: columnId, position: position}\n };\n\n return Ajax.call([request])[0];\n};\n"],"names":["reportId","uniqueIdentifier","request","methodname","args","reportid","uniqueidentifier","Ajax","call","columnId","columnid","position"],"mappings":";;;;;;;2MAgCyB,CAACA,SAAUC,0BAC1BC,QAAU,CACZC,WAAY,iCACZC,KAAM,CAACC,SAAUL,SAAUM,iBAAkBL,0BAG1CM,cAAKC,KAAK,CAACN,UAAU,0BAUJ,CAACF,SAAUS,kBAC7BP,QAAU,CACZC,WAAY,oCACZC,KAAM,CAACC,SAAUL,SAAUU,SAAUD,kBAGlCF,cAAKC,KAAK,CAACN,UAAU,2BAWH,CAACF,SAAUS,SAAUE,kBACxCT,QAAU,CACZC,WAAY,qCACZC,KAAM,CAACC,SAAUL,SAAUU,SAAUD,SAAUE,SAAUA,kBAGtDJ,cAAKC,KAAK,CAACN,UAAU"}
@@ -0,0 +1,10 @@
define("core_reportbuilder/local/repository/conditions",["exports","core/ajax"],(function(_exports,_ajax){var obj;
/**
* Module to handle condition AJAX requests
*
* @module core_reportbuilder/local/repository/conditions
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.resetConditions=_exports.reorderCondition=_exports.deleteCondition=_exports.addCondition=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.resetConditions=reportId=>{const request={methodname:"core_reportbuilder_conditions_reset",args:{reportid:reportId}};return _ajax.default.call([request])[0]};_exports.addCondition=(reportId,uniqueIdentifier)=>{const request={methodname:"core_reportbuilder_conditions_add",args:{reportid:reportId,uniqueidentifier:uniqueIdentifier}};return _ajax.default.call([request])[0]};_exports.deleteCondition=(reportId,conditionId)=>{const request={methodname:"core_reportbuilder_conditions_delete",args:{reportid:reportId,conditionid:conditionId}};return _ajax.default.call([request])[0]};_exports.reorderCondition=(reportId,conditionId,position)=>{const request={methodname:"core_reportbuilder_conditions_reorder",args:{reportid:reportId,conditionid:conditionId,position:position}};return _ajax.default.call([request])[0]}}));
//# sourceMappingURL=conditions.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"conditions.min.js","sources":["../../../src/local/repository/conditions.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle condition AJAX requests\n *\n * @module core_reportbuilder/local/repository/conditions\n * @copyright 2021 Paul Holden <paulh@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Reset all conditions for given report\n *\n * @param {Number} reportId\n * @return {Promise}\n */\nexport const resetConditions = reportId => {\n const request = {\n methodname: 'core_reportbuilder_conditions_reset',\n args: {reportid: reportId}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Add condition to given report\n *\n * @param {Number} reportId\n * @param {String} uniqueIdentifier\n * @return {Promise}\n */\nexport const addCondition = (reportId, uniqueIdentifier) => {\n const request = {\n methodname: 'core_reportbuilder_conditions_add',\n args: {reportid: reportId, uniqueidentifier: uniqueIdentifier}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Remove condition from given report\n *\n * @param {Number} reportId\n * @param {Number} conditionId\n * @return {Promise}\n */\nexport const deleteCondition = (reportId, conditionId) => {\n const request = {\n methodname: 'core_reportbuilder_conditions_delete',\n args: {reportid: reportId, conditionid: conditionId}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Reorder a condition in a given report\n *\n * @param {Number} reportId\n * @param {Number} conditionId\n * @param {Number} position\n * @return {Promise}\n */\nexport const reorderCondition = (reportId, conditionId, position) => {\n const request = {\n methodname: 'core_reportbuilder_conditions_reorder',\n args: {reportid: reportId, conditionid: conditionId, position: position}\n };\n\n return Ajax.call([request])[0];\n};\n"],"names":["reportId","request","methodname","args","reportid","Ajax","call","uniqueIdentifier","uniqueidentifier","conditionId","conditionid","position"],"mappings":";;;;;;;mPA+B+BA,iBACrBC,QAAU,CACZC,WAAY,sCACZC,KAAM,CAACC,SAAUJ,kBAGdK,cAAKC,KAAK,CAACL,UAAU,0BAUJ,CAACD,SAAUO,0BAC7BN,QAAU,CACZC,WAAY,oCACZC,KAAM,CAACC,SAAUJ,SAAUQ,iBAAkBD,0BAG1CF,cAAKC,KAAK,CAACL,UAAU,6BAUD,CAACD,SAAUS,qBAChCR,QAAU,CACZC,WAAY,uCACZC,KAAM,CAACC,SAAUJ,SAAUU,YAAaD,qBAGrCJ,cAAKC,KAAK,CAACL,UAAU,8BAWA,CAACD,SAAUS,YAAaE,kBAC9CV,QAAU,CACZC,WAAY,wCACZC,KAAM,CAACC,SAAUJ,SAAUU,YAAaD,YAAaE,SAAUA,kBAG5DN,cAAKC,KAAK,CAACL,UAAU"}
+10
View File
@@ -0,0 +1,10 @@
define("core_reportbuilder/local/repository/filters",["exports","core/ajax"],(function(_exports,_ajax){var obj;
/**
* Module to handle filter AJAX requests
*
* @module core_reportbuilder/local/repository/filters
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.setFilters=_exports.resetFilters=_exports.reorderFilter=_exports.deleteFilter=_exports.addFilter=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.resetFilters=(reportId,reportParameters)=>{const request={methodname:"core_reportbuilder_filters_reset",args:{reportid:reportId,parameters:reportParameters}};return _ajax.default.call([request])[0]};_exports.setFilters=(reportId,reportParameters,filterValues)=>{const request={methodname:"core_reportbuilder_set_filters",args:{reportid:reportId,parameters:reportParameters,values:filterValues}};return _ajax.default.call([request])[0]};_exports.addFilter=(reportId,uniqueIdentifier)=>{const request={methodname:"core_reportbuilder_filters_add",args:{reportid:reportId,uniqueidentifier:uniqueIdentifier}};return _ajax.default.call([request])[0]};_exports.deleteFilter=(reportId,filterId)=>{const request={methodname:"core_reportbuilder_filters_delete",args:{reportid:reportId,filterid:filterId}};return _ajax.default.call([request])[0]};_exports.reorderFilter=(reportId,filterId,position)=>{const request={methodname:"core_reportbuilder_filters_reorder",args:{reportid:reportId,filterid:filterId,position:position}};return _ajax.default.call([request])[0]}}));
//# sourceMappingURL=filters.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"filters.min.js","sources":["../../../src/local/repository/filters.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle filter AJAX requests\n *\n * @module core_reportbuilder/local/repository/filters\n * @copyright 2021 Paul Holden <paulh@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Reset all filters for given report\n *\n * @method\n * @param {Number} reportId\n * @param {String} reportParameters\n * @return {Promise}\n */\nexport const resetFilters = (reportId, reportParameters) => {\n const request = {\n methodname: 'core_reportbuilder_filters_reset',\n args: {reportid: reportId, parameters: reportParameters}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Set filter values for given report\n *\n * @method\n * @param {Number} reportId\n * @param {String} reportParameters\n * @param {String} filterValues\n * @return {Promise}\n */\nexport const setFilters = (reportId, reportParameters, filterValues) => {\n const request = {\n methodname: 'core_reportbuilder_set_filters',\n args: {reportid: reportId, parameters: reportParameters, values: filterValues}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Add a filter to the given report\n *\n * @param {Number} reportId\n * @param {String} uniqueIdentifier\n * @return {Promise}\n */\nexport const addFilter = (reportId, uniqueIdentifier) => {\n const request = {\n methodname: 'core_reportbuilder_filters_add',\n args: {reportid: reportId, uniqueidentifier: uniqueIdentifier}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Remove filter from given report\n *\n * @param {Number} reportId\n * @param {Number} filterId\n * @return {Promise}\n */\nexport const deleteFilter = (reportId, filterId) => {\n const request = {\n methodname: 'core_reportbuilder_filters_delete',\n args: {reportid: reportId, filterid: filterId}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Reorder a filter in a given report\n *\n * @param {Number} reportId\n * @param {Number} filterId\n * @param {Number} position\n * @return {Promise}\n */\nexport const reorderFilter = (reportId, filterId, position) => {\n const request = {\n methodname: 'core_reportbuilder_filters_reorder',\n args: {reportid: reportId, filterid: filterId, position: position}\n };\n\n return Ajax.call([request])[0];\n};\n"],"names":["reportId","reportParameters","request","methodname","args","reportid","parameters","Ajax","call","filterValues","values","uniqueIdentifier","uniqueidentifier","filterId","filterid","position"],"mappings":";;;;;;;wPAiC4B,CAACA,SAAUC,0BAC7BC,QAAU,CACZC,WAAY,mCACZC,KAAM,CAACC,SAAUL,SAAUM,WAAYL,0BAGpCM,cAAKC,KAAK,CAACN,UAAU,wBAYN,CAACF,SAAUC,iBAAkBQ,sBAC7CP,QAAU,CACZC,WAAY,iCACZC,KAAM,CAACC,SAAUL,SAAUM,WAAYL,iBAAkBS,OAAQD,sBAG9DF,cAAKC,KAAK,CAACN,UAAU,uBAUP,CAACF,SAAUW,0BAC1BT,QAAU,CACZC,WAAY,iCACZC,KAAM,CAACC,SAAUL,SAAUY,iBAAkBD,0BAG1CJ,cAAKC,KAAK,CAACN,UAAU,0BAUJ,CAACF,SAAUa,kBAC7BX,QAAU,CACZC,WAAY,oCACZC,KAAM,CAACC,SAAUL,SAAUc,SAAUD,kBAGlCN,cAAKC,KAAK,CAACN,UAAU,2BAWH,CAACF,SAAUa,SAAUE,kBACxCb,QAAU,CACZC,WAAY,qCACZC,KAAM,CAACC,SAAUL,SAAUc,SAAUD,SAAUE,SAAUA,kBAGtDR,cAAKC,KAAK,CAACN,UAAU"}
+10
View File
@@ -0,0 +1,10 @@
define("core_reportbuilder/local/repository/modals",["exports","core_form/modalform","core/str"],(function(_exports,_modalform,_str){var obj;
/**
* Module to handle modal form requests
*
* @module core_reportbuilder/local/repository/modals
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.createScheduleModal=_exports.createReportModal=void 0,_modalform=(obj=_modalform)&&obj.__esModule?obj:{default:obj};const createModalForm=(triggerElement,modalTitle,formClass,formArgs)=>new _modalform.default({modalConfig:{title:modalTitle},formClass:formClass,args:formArgs,saveButtonText:(0,_str.getString)("save","moodle"),returnFocus:triggerElement});_exports.createReportModal=function(triggerElement,modalTitle){let reportId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return createModalForm(triggerElement,modalTitle,"core_reportbuilder\\form\\report",{id:reportId})};_exports.createScheduleModal=function(triggerElement,modalTitle,reportId){let scheduleId=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;return createModalForm(triggerElement,modalTitle,"core_reportbuilder\\form\\schedule",{reportid:reportId,id:scheduleId})}}));
//# sourceMappingURL=modals.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"modals.min.js","sources":["../../../src/local/repository/modals.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle modal form requests\n *\n * @module core_reportbuilder/local/repository/modals\n * @copyright 2021 David Matamoros <davidmc@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport {getString} from 'core/str';\n\n/**\n * Return modal instance\n *\n * @param {EventTarget} triggerElement\n * @param {Promise} modalTitle\n * @param {String} formClass\n * @param {Object} formArgs\n * @return {ModalForm}\n */\nconst createModalForm = (triggerElement, modalTitle, formClass, formArgs) => {\n return new ModalForm({\n modalConfig: {\n title: modalTitle,\n },\n formClass: formClass,\n args: formArgs,\n saveButtonText: getString('save', 'moodle'),\n returnFocus: triggerElement,\n });\n};\n\n/**\n * Return report modal instance\n *\n * @param {EventTarget} triggerElement\n * @param {Promise} modalTitle\n * @param {Number} reportId\n * @return {ModalForm}\n */\nexport const createReportModal = (triggerElement, modalTitle, reportId = 0) => {\n return createModalForm(triggerElement, modalTitle, 'core_reportbuilder\\\\form\\\\report', {\n id: reportId,\n });\n};\n\n/**\n * Return schedule modal instance\n *\n * @param {EventTarget} triggerElement\n * @param {Promise} modalTitle\n * @param {Number} reportId\n * @param {Number} scheduleId\n * @return {ModalForm}\n */\nexport const createScheduleModal = (triggerElement, modalTitle, reportId, scheduleId = 0) => {\n return createModalForm(triggerElement, modalTitle, 'core_reportbuilder\\\\form\\\\schedule', {\n reportid: reportId,\n id: scheduleId,\n });\n};\n"],"names":["createModalForm","triggerElement","modalTitle","formClass","formArgs","ModalForm","modalConfig","title","args","saveButtonText","returnFocus","reportId","id","scheduleId","reportid"],"mappings":";;;;;;;gMAmCMA,gBAAkB,CAACC,eAAgBC,WAAYC,UAAWC,WACrD,IAAIC,mBAAU,CACjBC,YAAa,CACTC,MAAOL,YAEXC,UAAWA,UACXK,KAAMJ,SACNK,gBAAgB,kBAAU,OAAQ,UAClCC,YAAaT,4CAYY,SAACA,eAAgBC,gBAAYS,gEAAW,SAC9DX,gBAAgBC,eAAgBC,WAAY,mCAAoC,CACnFU,GAAID,yCAauB,SAACV,eAAgBC,WAAYS,cAAUE,kEAAa,SAC5Eb,gBAAgBC,eAAgBC,WAAY,qCAAsC,CACrFY,SAAUH,SACVC,GAAIC"}
+10
View File
@@ -0,0 +1,10 @@
define("core_reportbuilder/local/repository/reports",["exports","core/ajax"],(function(_exports,_ajax){var obj;
/**
* Module to handle report AJAX requests
*
* @module core_reportbuilder/local/repository/reports
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.getReport=_exports.deleteReport=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.deleteReport=reportId=>{const request={methodname:"core_reportbuilder_reports_delete",args:{reportid:reportId}};return _ajax.default.call([request])[0]};_exports.getReport=function(reportId,editMode){let pageSize=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;const request={methodname:"core_reportbuilder_reports_get",args:{reportid:reportId,editmode:editMode,pagesize:pageSize}};return _ajax.default.call([request])[0]}}));
//# sourceMappingURL=reports.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"reports.min.js","sources":["../../../src/local/repository/reports.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle report AJAX requests\n *\n * @module core_reportbuilder/local/repository/reports\n * @copyright 2021 Paul Holden <paulh@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Delete given report\n *\n * @param {Number} reportId\n * @return {Promise}\n */\nexport const deleteReport = reportId => {\n const request = {\n methodname: 'core_reportbuilder_reports_delete',\n args: {reportid: reportId}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Get report content\n *\n * @param {Number} reportId\n * @param {Boolean} editMode\n * @param {Number} [pageSize=0]\n * @return {Promise}\n */\nexport const getReport = (reportId, editMode, pageSize = 0) => {\n const request = {\n methodname: 'core_reportbuilder_reports_get',\n args: {reportid: reportId, editmode: editMode, pagesize: pageSize}\n };\n\n return Ajax.call([request])[0];\n};\n"],"names":["reportId","request","methodname","args","reportid","Ajax","call","editMode","pageSize","editmode","pagesize"],"mappings":";;;;;;;uLA+B4BA,iBAClBC,QAAU,CACZC,WAAY,oCACZC,KAAM,CAACC,SAAUJ,kBAGdK,cAAKC,KAAK,CAACL,UAAU,uBAWP,SAACD,SAAUO,cAAUC,gEAAW,QAC/CP,QAAU,CACZC,WAAY,iCACZC,KAAM,CAACC,SAAUJ,SAAUS,SAAUF,SAAUG,SAAUF,kBAGtDH,cAAKC,KAAK,CAACL,UAAU"}
@@ -0,0 +1,10 @@
define("core_reportbuilder/local/repository/schedules",["exports","core/ajax"],(function(_exports,_ajax){var obj;
/**
* Module to handle schedule AJAX requests
*
* @module core_reportbuilder/local/repository/schedules
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.toggleSchedule=_exports.sendSchedule=_exports.deleteSchedule=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.deleteSchedule=(reportId,scheduleId)=>{const request={methodname:"core_reportbuilder_schedules_delete",args:{reportid:reportId,scheduleid:scheduleId}};return _ajax.default.call([request])[0]};_exports.sendSchedule=(reportId,scheduleId)=>{const request={methodname:"core_reportbuilder_schedules_send",args:{reportid:reportId,scheduleid:scheduleId}};return _ajax.default.call([request])[0]};_exports.toggleSchedule=(reportId,scheduleId,scheduleEnabled)=>{const request={methodname:"core_reportbuilder_schedules_toggle",args:{reportid:reportId,scheduleid:scheduleId,enabled:scheduleEnabled}};return _ajax.default.call([request])[0]}}));
//# sourceMappingURL=schedules.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"schedules.min.js","sources":["../../../src/local/repository/schedules.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle schedule AJAX requests\n *\n * @module core_reportbuilder/local/repository/schedules\n * @copyright 2021 Paul Holden <paulh@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Delete schedule\n *\n * @method\n * @param {Number} reportId\n * @param {Number} scheduleId\n * @return {Promise}\n */\nexport const deleteSchedule = (reportId, scheduleId) => {\n const request = {\n methodname: 'core_reportbuilder_schedules_delete',\n args: {reportid: reportId, scheduleid: scheduleId}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Send schedule\n *\n * @method\n * @param {Number} reportId\n * @param {Number} scheduleId\n * @return {Promise}\n */\nexport const sendSchedule = (reportId, scheduleId) => {\n const request = {\n methodname: 'core_reportbuilder_schedules_send',\n args: {reportid: reportId, scheduleid: scheduleId}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Toggle schedule enabled\n *\n * @method\n * @param {Number} reportId\n * @param {Number} scheduleId\n * @param {Boolean} scheduleEnabled\n * @return {Promise}\n */\nexport const toggleSchedule = (reportId, scheduleId, scheduleEnabled) => {\n const request = {\n methodname: 'core_reportbuilder_schedules_toggle',\n args: {reportid: reportId, scheduleid: scheduleId, enabled: scheduleEnabled}\n };\n\n return Ajax.call([request])[0];\n};\n"],"names":["reportId","scheduleId","request","methodname","args","reportid","scheduleid","Ajax","call","scheduleEnabled","enabled"],"mappings":";;;;;;;sNAiC8B,CAACA,SAAUC,oBAC/BC,QAAU,CACZC,WAAY,sCACZC,KAAM,CAACC,SAAUL,SAAUM,WAAYL,oBAGpCM,cAAKC,KAAK,CAACN,UAAU,0BAWJ,CAACF,SAAUC,oBAC7BC,QAAU,CACZC,WAAY,oCACZC,KAAM,CAACC,SAAUL,SAAUM,WAAYL,oBAGpCM,cAAKC,KAAK,CAACN,UAAU,4BAYF,CAACF,SAAUC,WAAYQ,yBAC3CP,QAAU,CACZC,WAAY,sCACZC,KAAM,CAACC,SAAUL,SAAUM,WAAYL,WAAYS,QAASD,yBAGzDF,cAAKC,KAAK,CAACN,UAAU"}
+10
View File
@@ -0,0 +1,10 @@
define("core_reportbuilder/local/repository/sorting",["exports","core/ajax"],(function(_exports,_ajax){var obj;
/**
* Module to handle column sorting AJAX requests
*
* @module core_reportbuilder/local/repository/sorting
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.toggleColumnSorting=_exports.reorderColumnSorting=_exports.getColumnSorting=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.getColumnSorting=reportId=>{const request={methodname:"core_reportbuilder_columns_sort_get",args:{reportid:reportId}};return _ajax.default.call([request])[0]};_exports.reorderColumnSorting=(reportId,columnId,position)=>{const request={methodname:"core_reportbuilder_columns_sort_reorder",args:{reportid:reportId,columnid:columnId,position:position}};return _ajax.default.call([request])[0]};_exports.toggleColumnSorting=(reportId,columnId,enabled,direction)=>{const request={methodname:"core_reportbuilder_columns_sort_toggle",args:{reportid:reportId,columnid:columnId,enabled:enabled,direction:direction}};return _ajax.default.call([request])[0]}}));
//# sourceMappingURL=sorting.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"sorting.min.js","sources":["../../../src/local/repository/sorting.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle column sorting AJAX requests\n *\n * @module core_reportbuilder/local/repository/sorting\n * @copyright 2021 David Matamoros <davidmc@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Retrieve column sorting\n *\n * @param {Number} reportId\n * @return {Promise}\n */\nexport const getColumnSorting = reportId => {\n const request = {\n methodname: 'core_reportbuilder_columns_sort_get',\n args: {reportid: reportId}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Re-order sort column position\n *\n * @param {Number} reportId\n * @param {Number} columnId\n * @param {Number} position\n * @return {Promise}\n */\nexport const reorderColumnSorting = (reportId, columnId, position) => {\n const request = {\n methodname: 'core_reportbuilder_columns_sort_reorder',\n args: {reportid: reportId, columnid: columnId, position: position}\n };\n\n return Ajax.call([request])[0];\n};\n\n/**\n * Enables/disabled sorting on column\n *\n * @param {Number} reportId\n * @param {Number} columnId\n * @param {Boolean} enabled\n * @param {Number} direction\n * @return {Promise}\n */\nexport const toggleColumnSorting = (reportId, columnId, enabled, direction) => {\n const request = {\n methodname: 'core_reportbuilder_columns_sort_toggle',\n args: {reportid: reportId, columnid: columnId, enabled: enabled, direction: direction}\n };\n\n return Ajax.call([request])[0];\n};\n"],"names":["reportId","request","methodname","args","reportid","Ajax","call","columnId","position","columnid","enabled","direction"],"mappings":";;;;;;;uOA+BgCA,iBACtBC,QAAU,CACZC,WAAY,sCACZC,KAAM,CAACC,SAAUJ,kBAGdK,cAAKC,KAAK,CAACL,UAAU,kCAWI,CAACD,SAAUO,SAAUC,kBAC/CP,QAAU,CACZC,WAAY,0CACZC,KAAM,CAACC,SAAUJ,SAAUS,SAAUF,SAAUC,SAAUA,kBAGtDH,cAAKC,KAAK,CAACL,UAAU,iCAYG,CAACD,SAAUO,SAAUG,QAASC,mBACvDV,QAAU,CACZC,WAAY,yCACZC,KAAM,CAACC,SAAUJ,SAAUS,SAAUF,SAAUG,QAASA,QAASC,UAAWA,mBAGzEN,cAAKC,KAAK,CAACL,UAAU"}
+11
View File
@@ -0,0 +1,11 @@
define("core_reportbuilder/local/selectors",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;
/**
* Report builder selectors
*
* @module core_reportbuilder/local/selectors
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
const SELECTORS={regions:{report:'[data-region="core_reportbuilder/report"]',reportTable:'[data-region="reportbuilder-table"]',columnHeader:'[data-region="column-header"]',filterButtonLabel:'[data-region="filter-button-label"]',filtersForm:'[data-region="filters-form"]',sidebarMenu:'[data-region="sidebar-menu"]',sidebarCard:'[data-region="sidebar-card"]',sidebarItem:'[data-region="sidebar-item"]',settingsConditions:'[data-region="settings-conditions"]',activeConditions:'[data-region="active-conditions"]',activeCondition:'[data-region="active-condition"]',settingsFilters:'[data-region="settings-filters"]',activeFilters:'[data-region="active-filters"]',activeFilter:'[data-region="active-filter"]',settingsSorting:'[data-region="settings-sorting"]',audiencesContainer:'[data-region="audiences"]',audienceFormContainer:'[data-region="audience-form-container"]',audienceCard:'[data-region="audience-card"]',audienceHeading:'[data-region="audience-heading"]',audienceForm:'[data-region="audience-form"]',audienceEmptyMessage:"[data-region=no-instances-message]",audienceDescription:"[data-region=audience-description]",audienceNotSavedLabel:"[data-region=audience-not-saved]",settingsCardView:'[data-region="settings-cardview"]'},actions:{reportActionPopup:'[data-action="report-action-popup"]',reportCreate:'[data-action="report-create"]',reportEdit:'[data-action="report-edit"]',reportDelete:'[data-action="report-delete"]',reportAddColumn:'[data-action="report-add-column"]',reportRemoveColumn:'[data-action="report-remove-column"]',reportAddCondition:'[data-action="report-add-condition"]',reportRemoveCondition:'[data-action="report-remove-condition"]',reportAddFilter:'[data-action="report-add-filter"]',reportRemoveFilter:'[data-action="report-remove-filter"]',reportToggleColumnSort:'[data-action="report-toggle-column-sorting"]',reportToggleColumnSortDirection:'[data-action="report-toggle-sort-direction"]',sidebarSearch:'[data-action="sidebar-search"]',toggleEditPreview:'[data-action="toggle-edit-preview"]',audienceAdd:'[data-action="add-audience"]',audienceEdit:'[data-action="edit-audience"]',audienceDelete:'[data-action="delete-audience"]',toggleCardView:'[data-action="toggle-card"]',scheduleCreate:'[data-action="schedule-create"]',scheduleToggle:'[data-action="schedule-toggle"]',scheduleEdit:'[data-action="schedule-edit"]',scheduleSend:'[data-action="schedule-send"]',scheduleDelete:'[data-action="schedule-delete"]'},forReport:reportId=>"".concat(SELECTORS.regions.report,'[data-report-id="').concat(reportId,'"]')};var _default=SELECTORS;return _exports.default=_default,_exports.default}));
//# sourceMappingURL=selectors.min.js.map
File diff suppressed because one or more lines are too long
+10
View File
@@ -0,0 +1,10 @@
define("core_reportbuilder/report",["exports","core/notification","core_reportbuilder/local/events","core_reportbuilder/local/selectors","core_table/dynamic","core_table/local/dynamic/selectors"],(function(_exports,_notification,reportEvents,reportSelectors,_dynamic,tableSelectors){var obj;
/**
* Report builder report management
*
* @module core_reportbuilder/report
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_notification=(obj=_notification)&&obj.__esModule?obj:{default:obj},reportEvents=_interopRequireWildcard(reportEvents),reportSelectors=_interopRequireWildcard(reportSelectors),tableSelectors=_interopRequireWildcard(tableSelectors);const CLASSES_COLLAPSED="collapsed",CLASSES_EXPANDED="show",CLASSES_ICONUP="fa-angle-up",CLASSES_ICONDOWN="fa-angle-down";let initialized=!1;_exports.init=()=>{initialized||(document.addEventListener(reportEvents.tableReload,(async event=>{var _event$detail;const reportElement=event.target.closest(reportSelectors.regions.report);if(null===reportElement)return;const tableRoot=reportElement.querySelector(tableSelectors.main.region),pageNumber=null!==(_event$detail=event.detail)&&void 0!==_event$detail&&_event$detail.preservePagination?null:1;await(0,_dynamic.setPageNumber)(tableRoot,pageNumber,!1).then(_dynamic.refreshTableContent).then((()=>{var _event$detail2;const preserveTriggerElement=null===(_event$detail2=event.detail)||void 0===_event$detail2?void 0:_event$detail2.preserveTriggerElement;var _reportElement$queryS;preserveTriggerElement&&(null===(_reportElement$queryS=reportElement.querySelector(preserveTriggerElement))||void 0===_reportElement$queryS||_reportElement$queryS.focus())})).catch(_notification.default.exception)})),document.addEventListener("click",(event=>{const reportActionPopup=event.target.closest(reportSelectors.actions.reportActionPopup);if(null===reportActionPopup)return;event.preventDefault();const popupAction=JSON.parse(reportActionPopup.dataset.popupAction);window.openpopup(event,popupAction.jsfunctionargs)})),document.addEventListener("click",(event=>{const toggleCard=event.target.closest(reportSelectors.actions.toggleCardView);if(toggleCard){const tableCard=toggleCard.closest("tr"),toggleIcon=toggleCard.querySelector("i");event.preventDefault(),toggleCard.classList.contains(CLASSES_COLLAPSED)?(tableCard.classList.add(CLASSES_EXPANDED),toggleIcon.classList.replace(CLASSES_ICONDOWN,CLASSES_ICONUP),toggleCard.classList.remove(CLASSES_COLLAPSED),toggleCard.setAttribute("aria-expanded","true")):(tableCard.classList.remove(CLASSES_EXPANDED),toggleIcon.classList.replace(CLASSES_ICONUP,CLASSES_ICONDOWN),toggleCard.classList.add(CLASSES_COLLAPSED),toggleCard.removeAttribute("aria-expanded"))}})),initialized=!0)}}));
//# sourceMappingURL=report.min.js.map
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
define("core_reportbuilder/reports_list",["exports","core/event_dispatcher","core/notification","core/pending","core/prefetch","core/str","core/toast","core_reportbuilder/local/events","core_reportbuilder/local/selectors","core_reportbuilder/local/repository/reports","core_reportbuilder/local/repository/modals"],(function(_exports,_event_dispatcher,_notification,_pending,_prefetch,_str,_toast,reportEvents,reportSelectors,_reports,_modals){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending),reportEvents=_interopRequireWildcard(reportEvents),reportSelectors=_interopRequireWildcard(reportSelectors);_exports.init=()=>{(0,_prefetch.prefetchStrings)("core_reportbuilder",["deletereport","deletereportconfirm","editreportdetails","newreport","reportdeleted","reportupdated"]),(0,_prefetch.prefetchStrings)("core",["delete"]),document.addEventListener("click",(event=>{if(event.target.closest(reportSelectors.actions.reportCreate)){event.preventDefault();const reportModal=(0,_modals.createReportModal)(event.target,(0,_str.getString)("newreport","core_reportbuilder"));reportModal.addEventListener(reportModal.events.FORM_SUBMITTED,(event=>{window.location.href=event.detail})),reportModal.show()}const reportEdit=event.target.closest(reportSelectors.actions.reportEdit);if(reportEdit){event.preventDefault();const triggerElement=reportEdit.closest(".dropdown").querySelector(".dropdown-toggle"),reportModal=(0,_modals.createReportModal)(triggerElement,(0,_str.getString)("editreportdetails","core_reportbuilder"),reportEdit.dataset.reportId);reportModal.addEventListener(reportModal.events.FORM_SUBMITTED,(()=>{const reportElement=event.target.closest(reportSelectors.regions.report);(0,_str.getString)("reportupdated","core_reportbuilder").then(_toast.add).then((()=>{(0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{preservePagination:!0},reportElement)})).catch(_notification.default.exception)})),reportModal.show()}const reportDelete=event.target.closest(reportSelectors.actions.reportDelete);if(reportDelete){event.preventDefault();const triggerElement=reportDelete.closest(".dropdown").querySelector(".dropdown-toggle");_notification.default.saveCancelPromise((0,_str.getString)("deletereport","core_reportbuilder"),(0,_str.getString)("deletereportconfirm","core_reportbuilder",reportDelete.dataset.reportName),(0,_str.getString)("delete","core"),{triggerElement:triggerElement}).then((()=>{const pendingPromise=new _pending.default("core_reportbuilder/reports:delete"),reportElement=event.target.closest(reportSelectors.regions.report);return(0,_reports.deleteReport)(reportDelete.dataset.reportId).then((()=>(0,_toast.add)((0,_str.getString)("reportdeleted","core_reportbuilder")))).then((()=>((0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{preservePagination:!0},reportElement),pendingPromise.resolve()))).catch(_notification.default.exception)})).catch((()=>{}))}}))}}));
//# sourceMappingURL=reports_list.min.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+10
View File
@@ -0,0 +1,10 @@
define("core_reportbuilder/sidebar",["exports","core/pending","core/utils","core_reportbuilder/local/selectors"],(function(_exports,_pending,_utils,reportSelectors){var obj;
/**
* Report builder sidebar component
*
* @module core_reportbuilder/sidebar
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_pending=(obj=_pending)&&obj.__esModule?obj:{default:obj},reportSelectors=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(reportSelectors);const CLASSES_EXPANDED="show",CLASSES_COLLAPSED="collapsed",CLASSES_HIDE="d-none",sidebarCardFilter=(event,sidebarMenu)=>{const pendingPromise=new _pending.default("core_reportbuilder/sidebar:cardFilter"),sidebarCards=sidebarMenu.querySelectorAll(reportSelectors.regions.sidebarCard),sidebarItems=sidebarMenu.querySelectorAll(reportSelectors.regions.sidebarItem),searchTerm=event.target.value.toLowerCase();sidebarItems.forEach((item=>{const itemContent=item.textContent.toLowerCase();item.classList.toggle(CLASSES_HIDE,!itemContent.includes(searchTerm))})),sidebarCards.forEach((card=>{const visibleItems=card.querySelectorAll("".concat(reportSelectors.regions.sidebarItem,":not(.").concat(CLASSES_HIDE,")"));card.classList.toggle(CLASSES_HIDE,!visibleItems.length),expandCard(card)})),pendingPromise.resolve()},expandCard=card=>{let cardButton=card.querySelector('[data-toggle="collapse"]');if(cardButton.classList.contains(CLASSES_COLLAPSED)){cardButton.classList.remove(CLASSES_COLLAPSED),cardButton.setAttribute("aria-expanded","true"),card.querySelector(cardButton.dataset.target).classList.add(CLASSES_EXPANDED)}};_exports.init=selectorId=>{const sidebarMenu=document.querySelector(selectorId+reportSelectors.regions.sidebarMenu),sidebarSearch=sidebarMenu.querySelector(reportSelectors.actions.sidebarSearch),sidebarSearchDebounce=(0,_utils.debounce)(sidebarCardFilter,250);sidebarSearch.addEventListener("keyup",(event=>{const pendingPromise=new _pending.default("core_reportbuilder/sidebar:keyup");sidebarSearchDebounce(event,sidebarMenu),setTimeout((()=>{pendingPromise.resolve()}),250)}))}}));
//# sourceMappingURL=sidebar.min.js.map
File diff suppressed because one or more lines are too long
+268
View File
@@ -0,0 +1,268 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder audiences
*
* @module core_reportbuilder/audience
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
import 'core/inplace_editable';
import Templates from 'core/templates';
import Notification from 'core/notification';
import Pending from 'core/pending';
import {prefetchStrings} from 'core/prefetch';
import {getString} from 'core/str';
import DynamicForm from 'core_form/dynamicform';
import {add as addToast} from 'core/toast';
import {deleteAudience} from 'core_reportbuilder/local/repository/audiences';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
import {loadFragment} from 'core/fragment';
import {markFormAsDirty} from 'core_form/changechecker';
let reportId = 0;
let contextId = 0;
/**
* Add audience card
*
* @param {String} className
* @param {String} title
*/
const addAudienceCard = (className, title) => {
const pendingPromise = new Pending('core_reportbuilder/audience:add');
const audiencesContainer = document.querySelector(reportSelectors.regions.audiencesContainer);
const audienceCardLength = audiencesContainer.querySelectorAll(reportSelectors.regions.audienceCard).length;
const params = {
classname: className,
reportid: reportId,
showormessage: (audienceCardLength > 0),
title: title,
};
// Load audience card fragment, render and then initialise the form within.
loadFragment('core_reportbuilder', 'audience_form', contextId, params)
.then((html, js) => {
const audienceCard = Templates.appendNodeContents(audiencesContainer, html, js)[0];
const audienceEmptyMessage = audiencesContainer.querySelector(reportSelectors.regions.audienceEmptyMessage);
const audienceForm = initAudienceCardForm(audienceCard);
// Mark as dirty new audience form created to prevent users leaving the page without saving it.
markFormAsDirty(audienceForm.getFormNode());
audienceEmptyMessage.classList.add('hidden');
return getString('audienceadded', 'core_reportbuilder', title);
})
.then(addToast)
.then(() => pendingPromise.resolve())
.catch(Notification.exception);
};
/**
* Edit audience card
*
* @param {Element} audienceCard
*/
const editAudienceCard = audienceCard => {
const pendingPromise = new Pending('core_reportbuilder/audience:edit');
// Load audience form with data for editing, then toggle visible controls in the card.
const audienceForm = initAudienceCardForm(audienceCard);
audienceForm.load({id: audienceCard.dataset.audienceId})
.then(() => {
const audienceFormContainer = audienceCard.querySelector(reportSelectors.regions.audienceFormContainer);
const audienceDescription = audienceCard.querySelector(reportSelectors.regions.audienceDescription);
const audienceEdit = audienceCard.querySelector(reportSelectors.actions.audienceEdit);
audienceFormContainer.classList.remove('hidden');
audienceDescription.classList.add('hidden');
audienceEdit.disabled = true;
return pendingPromise.resolve();
})
.catch(Notification.exception);
};
/**
* Initialise dynamic form within given audience card
*
* @param {Element} audienceCard
* @return {DynamicForm}
*/
const initAudienceCardForm = audienceCard => {
const audienceFormContainer = audienceCard.querySelector(reportSelectors.regions.audienceFormContainer);
const audienceForm = new DynamicForm(audienceFormContainer, '\\core_reportbuilder\\form\\audience');
// After submitting the form, update the card instance and description properties.
audienceForm.addEventListener(audienceForm.events.FORM_SUBMITTED, data => {
const audienceHeading = audienceCard.querySelector(reportSelectors.regions.audienceHeading);
const audienceDescription = audienceCard.querySelector(reportSelectors.regions.audienceDescription);
audienceCard.dataset.audienceId = data.detail.instanceid;
audienceHeading.innerHTML = data.detail.heading;
audienceDescription.innerHTML = data.detail.description;
closeAudienceCardForm(audienceCard);
return getString('audiencesaved', 'core_reportbuilder')
.then(addToast);
});
// If cancelling the form, close the card or remove it if it was never created.
audienceForm.addEventListener(audienceForm.events.FORM_CANCELLED, () => {
if (audienceCard.dataset.audienceId > 0) {
closeAudienceCardForm(audienceCard);
} else {
removeAudienceCard(audienceCard);
}
});
return audienceForm;
};
/**
* Delete audience card
*
* @param {Element} audienceDelete
*/
const deleteAudienceCard = audienceDelete => {
const audienceCard = audienceDelete.closest(reportSelectors.regions.audienceCard);
const {audienceId, audienceTitle, audienceEditWarning = false} = audienceCard.dataset;
// The edit warning indicates the audience is in use in a report schedule.
const audienceDeleteConfirmation = audienceEditWarning ? 'audienceusedbyschedule' : 'deleteaudienceconfirm';
Notification.saveCancelPromise(
getString('deleteaudience', 'core_reportbuilder', audienceTitle),
getString(audienceDeleteConfirmation, 'core_reportbuilder', audienceTitle),
getString('delete', 'core'),
{triggerElement: audienceDelete}
).then(() => {
const pendingPromise = new Pending('core_reportbuilder/audience:delete');
return deleteAudience(reportId, audienceId)
.then(() => addToast(getString('audiencedeleted', 'core_reportbuilder', audienceTitle)))
.then(() => {
removeAudienceCard(audienceCard);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}).catch(() => {
return;
});
};
/**
* Close audience card form
*
* @param {Element} audienceCard
*/
const closeAudienceCardForm = audienceCard => {
// Remove the [data-region="audience-form-container"] (with all the event listeners attached to it), and create it again.
const audienceFormContainer = audienceCard.querySelector(reportSelectors.regions.audienceFormContainer);
const NewAudienceFormContainer = audienceFormContainer.cloneNode(false);
audienceCard.querySelector(reportSelectors.regions.audienceForm).replaceChild(NewAudienceFormContainer, audienceFormContainer);
// Show the description container and enable the action buttons.
audienceCard.querySelector(reportSelectors.regions.audienceDescription).classList.remove('hidden');
audienceCard.querySelector(reportSelectors.actions.audienceEdit).disabled = false;
audienceCard.querySelector(reportSelectors.actions.audienceDelete).disabled = false;
};
/**
* Remove audience card
*
* @param {Element} audienceCard
*/
const removeAudienceCard = audienceCard => {
audienceCard.remove();
const audiencesContainer = document.querySelector(reportSelectors.regions.audiencesContainer);
const audienceCards = audiencesContainer.querySelectorAll(reportSelectors.regions.audienceCard);
// Show message if there are no cards remaining, ensure first card's separator is not present.
if (audienceCards.length === 0) {
const audienceEmptyMessage = document.querySelector(reportSelectors.regions.audienceEmptyMessage);
audienceEmptyMessage.classList.remove('hidden');
} else {
const audienceFirstCardSeparator = audienceCards[0].querySelector('.audience-separator');
audienceFirstCardSeparator?.remove();
}
};
let initialized = false;
/**
* Initialise audiences tab.
*
* @param {Number} id
* @param {Number} contextid
*/
export const init = (id, contextid) => {
prefetchStrings('core_reportbuilder', [
'audienceadded',
'audiencedeleted',
'audiencesaved',
'audienceusedbyschedule',
'deleteaudience',
'deleteaudienceconfirm',
]);
prefetchStrings('core', [
'delete',
]);
reportId = id;
contextId = contextid;
if (initialized) {
// We already added the event listeners (can be called multiple times by mustache template).
return;
}
document.addEventListener('click', event => {
// Add instance.
const audienceAdd = event.target.closest(reportSelectors.actions.audienceAdd);
if (audienceAdd) {
event.preventDefault();
addAudienceCard(audienceAdd.dataset.uniqueIdentifier, audienceAdd.dataset.name);
}
// Edit instance.
const audienceEdit = event.target.closest(reportSelectors.actions.audienceEdit);
if (audienceEdit) {
const audienceEditCard = audienceEdit.closest(reportSelectors.regions.audienceCard);
event.preventDefault();
editAudienceCard(audienceEditCard);
}
// Delete instance.
const audienceDelete = event.target.closest(reportSelectors.actions.audienceDelete);
if (audienceDelete) {
event.preventDefault();
deleteAudienceCard(audienceDelete);
}
});
initialized = true;
};
+103
View File
@@ -0,0 +1,103 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder editor
*
* @module core_reportbuilder/editor
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
import $ from 'jquery';
import 'core/inplace_editable';
import {addIconToContainer} from 'core/loadingicon';
import Notification from 'core/notification';
import Pending from 'core/pending';
import Templates from 'core/templates';
import {getString} from 'core/str';
import {add as addToast} from 'core/toast';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
import {init as columnsEditorInit} from 'core_reportbuilder/local/editor/columns';
import {init as conditionsEditorInit} from 'core_reportbuilder/local/editor/conditions';
import {init as filtersEditorInit} from 'core_reportbuilder/local/editor/filters';
import {init as sortingEditorInit} from 'core_reportbuilder/local/editor/sorting';
import {init as cardviewEditorInit} from 'core_reportbuilder/local/editor/card_view';
import {getReport} from 'core_reportbuilder/local/repository/reports';
import {createReportModal} from 'core_reportbuilder/local/repository/modals';
let initialized = false;
/**
* Initialise editor and all it's modules
*/
export const init = () => {
columnsEditorInit(initialized);
conditionsEditorInit(initialized);
filtersEditorInit(initialized);
sortingEditorInit(initialized);
cardviewEditorInit(initialized);
// Ensure we only add our listeners once (can be called multiple times by mustache template).
if (initialized) {
return;
}
// Add event handlers to generic report editor elements.
document.addEventListener('click', event => {
// Toggle between edit and preview mode.
const toggleEditViewMode = event.target.closest(reportSelectors.actions.toggleEditPreview);
if (toggleEditViewMode) {
event.preventDefault();
const reportElement = event.target.closest(reportSelectors.regions.report);
const pendingPromise = new Pending('core_reportbuilder/reports:get');
const toggledEditMode = toggleEditViewMode.dataset.editMode !== "1";
addIconToContainer(toggleEditViewMode)
.then(() => getReport(reportElement.dataset.reportId, toggledEditMode))
.then(response => Promise.all([
$.parseHTML(response.javascript, null, true).map(node => node.innerHTML).join("\n"),
Templates.renderForPromise('core_reportbuilder/local/dynamictabs/editor', response),
]))
.then(([responseJs, {html, js}]) => Templates.replaceNode(reportElement, html, js + responseJs))
.then(() => pendingPromise.resolve())
.catch(Notification.exception);
}
// Edit report details modal.
const reportEdit = event.target.closest(reportSelectors.actions.reportEdit);
if (reportEdit) {
event.preventDefault();
const reportModal = createReportModal(event.target, getString('editreportdetails', 'core_reportbuilder'),
reportEdit.dataset.reportId);
reportModal.addEventListener(reportModal.events.FORM_SUBMITTED, () => {
getString('reportupdated', 'core_reportbuilder')
.then(addToast)
.then(() => {
return window.location.reload();
})
.catch(Notification.exception);
});
reportModal.show();
}
});
initialized = true;
};
+111
View File
@@ -0,0 +1,111 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder filter management
*
* @module core_reportbuilder/filters
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import {dispatchEvent} from 'core/event_dispatcher';
import {loadFragment} from 'core/fragment';
import Notification from 'core/notification';
import Pending from 'core/pending';
import {getString} from 'core/str';
import Templates from 'core/templates';
import {add as addToast} from 'core/toast';
import DynamicForm from 'core_form/dynamicform';
import * as reportEvents from 'core_reportbuilder/local/events';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
import {resetFilters} from 'core_reportbuilder/local/repository/filters';
/**
* Update filter button text to indicate applied filter count
*
* @param {Element} reportElement
* @param {Number} filterCount
*/
const setFilterButtonCount = async(reportElement, filterCount) => {
const filterButtonLabel = reportElement.querySelector(reportSelectors.regions.filterButtonLabel);
if (filterCount > 0) {
filterButtonLabel.textContent = await getString('filtersappliedx', 'core_reportbuilder', filterCount);
} else {
filterButtonLabel.textContent = await getString('filters', 'moodle');
}
};
/**
* Initialise module for given report
*
* @method
* @param {Number} reportId
* @param {Number} contextId
*/
export const init = (reportId, contextId) => {
const reportElement = document.querySelector(reportSelectors.forReport(reportId));
const filterFormContainer = reportElement.querySelector(reportSelectors.regions.filtersForm);
// Ensure we only add our listeners once (can be called multiple times by mustache template).
if (filterFormContainer.dataset.initialized) {
return;
}
filterFormContainer.dataset.initialized = true;
const filterForm = new DynamicForm(filterFormContainer, '\\core_reportbuilder\\form\\filter');
// Submit report filters.
filterForm.addEventListener(filterForm.events.FORM_SUBMITTED, event => {
event.preventDefault();
// After the form has been submitted, we should trigger report table reload.
dispatchEvent(reportEvents.tableReload, {}, reportElement);
setFilterButtonCount(reportElement, event.detail);
getString('filtersapplied', 'core_reportbuilder')
.then(addToast)
.catch(Notification.exception);
});
// Reset report filters.
filterForm.addEventListener(filterForm.events.NOSUBMIT_BUTTON_PRESSED, event => {
event.preventDefault();
const pendingPromise = new Pending('core_reportbuilder/filters:reset');
const reportParameters = reportElement.dataset.parameter;
resetFilters(reportId, reportParameters)
.then(() => getString('filtersreset', 'core_reportbuilder'))
.then(addToast)
.then(() => loadFragment('core_reportbuilder', 'filters_form', contextId, {
reportid: reportId,
parameters: reportParameters,
}))
.then((html, js) => {
Templates.replaceNodeContents(filterFormContainer, html, js);
dispatchEvent(reportEvents.tableReload, {}, reportElement);
setFilterButtonCount(reportElement, 0);
return pendingPromise.resolve();
})
.catch(Notification.exception);
});
// Modify "region-main" overflow for big filter forms.
document.querySelector('#region-main').style.overflowX = "visible";
};
@@ -0,0 +1,71 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder card view editor
*
* @module core_reportbuilder/local/editor/card_view
* @copyright 2021 Mikel Martín <mikel@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
import DynamicForm from 'core_form/dynamicform';
import {add as addToast} from 'core/toast';
import {getString} from "core/str";
import {subscribe as subscribe} from 'core/pubsub';
import Notification from 'core/notification';
import * as reportEvents from 'core_reportbuilder/local/events';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
let cardViewForm = null;
/**
* Initialise card view form, must be called on each init because the form container is re-created when switching editor modes
*/
const initCardViewForm = () => {
const cardViewFormContainer = document.querySelector(reportSelectors.regions.settingsCardView);
if (!cardViewFormContainer) {
return;
}
cardViewForm = new DynamicForm(cardViewFormContainer, '\\core_reportbuilder\\form\\card_view');
cardViewForm.addEventListener(cardViewForm.events.FORM_SUBMITTED, (event) => {
event.preventDefault();
getString('cardviewsettingssaved', 'core_reportbuilder')
.then(addToast)
.catch(Notification.exception);
});
};
/**
* Initialise module
*
* @param {Boolean} initialized Ensure we only add our listeners once
*/
export const init = (initialized) => {
initCardViewForm();
if (initialized) {
return;
}
// Update form each time a column is added or removed to the custom report.
subscribe(reportEvents.publish.reportColumnsUpdated, () => {
const reportElement = document.querySelector(reportSelectors.regions.report);
cardViewForm.load({reportid: reportElement.dataset.reportId});
});
};
@@ -0,0 +1,189 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder columns editor
*
* @module core_reportbuilder/local/editor/columns
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
import $ from 'jquery';
import {dispatchEvent} from 'core/event_dispatcher';
import 'core/inplace_editable';
import {eventTypes as inplaceEditableEvents} from 'core/local/inplace_editable/events';
import Notification from 'core/notification';
import Pending from 'core/pending';
import {prefetchStrings} from 'core/prefetch';
import {publish} from 'core/pubsub';
import SortableList from 'core/sortable_list';
import {getString} from 'core/str';
import {add as addToast} from 'core/toast';
import * as reportEvents from 'core_reportbuilder/local/events';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
import {addColumn, deleteColumn, reorderColumn} from 'core_reportbuilder/local/repository/columns';
import {getColumnSorting} from 'core_reportbuilder/local/repository/sorting';
/**
* Initialise module, prefetch all required strings
*
* @param {Boolean} initialized Ensure we only add our listeners once
*/
export const init = initialized => {
prefetchStrings('core_reportbuilder', [
'columnadded',
'columnaggregated',
'columndeleted',
'columnmoved',
'deletecolumn',
'deletecolumnconfirm',
]);
prefetchStrings('core', [
'delete',
]);
if (initialized) {
return;
}
document.addEventListener('click', event => {
// Add column to report.
const reportAddColumn = event.target.closest(reportSelectors.actions.reportAddColumn);
if (reportAddColumn) {
event.preventDefault();
const pendingPromise = new Pending('core_reportbuilder/columns:add');
const reportElement = reportAddColumn.closest(reportSelectors.regions.report);
addColumn(reportElement.dataset.reportId, reportAddColumn.dataset.uniqueIdentifier)
.then(data => publish(reportEvents.publish.reportColumnsUpdated, data))
.then(() => getString('columnadded', 'core_reportbuilder', reportAddColumn.dataset.name))
.then(addToast)
.then(() => {
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}
// Remove column from report.
const reportRemoveColumn = event.target.closest(reportSelectors.actions.reportRemoveColumn);
if (reportRemoveColumn) {
event.preventDefault();
const reportElement = reportRemoveColumn.closest(reportSelectors.regions.report);
const columnHeader = reportRemoveColumn.closest(reportSelectors.regions.columnHeader);
const columnName = columnHeader.dataset.columnName;
Notification.saveCancelPromise(
getString('deletecolumn', 'core_reportbuilder', columnName),
getString('deletecolumnconfirm', 'core_reportbuilder', columnName),
getString('delete', 'core'),
{triggerElement: reportRemoveColumn}
).then(() => {
const pendingPromise = new Pending('core_reportbuilder/columns:remove');
return deleteColumn(reportElement.dataset.reportId, columnHeader.dataset.columnId)
.then(data => publish(reportEvents.publish.reportColumnsUpdated, data))
.then(() => addToast(getString('columndeleted', 'core_reportbuilder', columnName)))
.then(() => {
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}).catch(() => {
return;
});
}
});
// Initialize sortable list to handle column moving (note JQuery dependency, see MDL-72293 for resolution).
var columnSortableList = new SortableList(`${reportSelectors.regions.reportTable} thead tr`, {isHorizontal: true});
columnSortableList.getElementName = element => Promise.resolve(element.data('columnName'));
$(document).on(SortableList.EVENTS.DRAG, `${reportSelectors.regions.report} th[data-column-id]`, (event, info) => {
const reportElement = event.target.closest(reportSelectors.regions.report);
const columnPosition = info.element.data('columnPosition');
const targetColumnPosition = info.targetNextElement.data('columnPosition');
$(reportElement).find('tbody tr').each(function() {
const cell = $(this).children(`td.c${columnPosition - 1}`)[0];
if (targetColumnPosition) {
var beforeCell = $(this).children(`td.c${targetColumnPosition - 1}`)[0];
this.insertBefore(cell, beforeCell);
} else {
this.appendChild(cell);
}
});
});
$(document).on(SortableList.EVENTS.DROP, `${reportSelectors.regions.report} th[data-column-id]`, (event, info) => {
if (info.positionChanged) {
const pendingPromise = new Pending('core_reportbuilder/columns:reorder');
const reportElement = event.target.closest(reportSelectors.regions.report);
const columnId = info.element.data('columnId');
const columnName = info.element.data('columnName');
const columnPosition = info.element.data('columnPosition');
// Select target position, if moving to the end then count number of element siblings.
let targetColumnPosition = info.targetNextElement.data('columnPosition') || info.element.siblings().length + 2;
if (targetColumnPosition > columnPosition) {
targetColumnPosition--;
}
// Re-order column, giving drop event transition time to finish.
const reorderPromise = reorderColumn(reportElement.dataset.reportId, columnId, targetColumnPosition);
Promise.all([reorderPromise, new Promise(resolve => setTimeout(resolve, 1000))])
.then(() => getString('columnmoved', 'core_reportbuilder', columnName))
.then(addToast)
.then(() => {
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}
});
// Initialize inplace editable listeners for column aggregation.
document.addEventListener(inplaceEditableEvents.elementUpdated, event => {
const columnAggregation = event.target.closest('[data-itemtype="columnaggregation"]');
if (columnAggregation) {
const pendingPromise = new Pending('core_reportbuilder/columns:aggregate');
const reportElement = columnAggregation.closest(reportSelectors.regions.report);
const columnHeader = columnAggregation.closest(reportSelectors.regions.columnHeader);
getString('columnaggregated', 'core_reportbuilder', columnHeader.dataset.columnName)
.then(addToast)
.then(() => {
// Pass preserveTriggerElement parameter so columnAggregationLink will be focused after the report reload.
const columnAggregationLink = `[data-itemtype="columnaggregation"][data-itemid="`
+ `${columnAggregation.dataset.itemid}"] > a`;
// Now reload the table, and notify listeners that columns have been updated.
dispatchEvent(reportEvents.tableReload, {preserveTriggerElement: columnAggregationLink}, reportElement);
return getColumnSorting(reportElement.dataset.reportId);
})
.then(data => publish(reportEvents.publish.reportColumnsUpdated, data))
.then(() => pendingPromise.resolve())
.catch(Notification.exception);
}
});
};
@@ -0,0 +1,244 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder conditions editor
*
* @module core_reportbuilder/local/editor/conditions
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
import $ from 'jquery';
import {dispatchEvent} from 'core/event_dispatcher';
import AutoComplete from 'core/form-autocomplete';
import 'core/inplace_editable';
import Notification from 'core/notification';
import Pending from 'core/pending';
import {prefetchStrings} from 'core/prefetch';
import SortableList from 'core/sortable_list';
import {getString} from 'core/str';
import Templates from 'core/templates';
import {add as addToast} from 'core/toast';
import DynamicForm from 'core_form/dynamicform';
import * as reportEvents from 'core_reportbuilder/local/events';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
import {addCondition, deleteCondition, reorderCondition, resetConditions} from 'core_reportbuilder/local/repository/conditions';
/**
* Reload conditions settings region
*
* @param {Element} reportElement
* @param {Object} templateContext
* @return {Promise}
*/
const reloadSettingsConditionsRegion = (reportElement, templateContext) => {
const pendingPromise = new Pending('core_reportbuilder/conditions:reload');
const settingsConditionsRegion = reportElement.querySelector(reportSelectors.regions.settingsConditions);
return Templates.renderForPromise('core_reportbuilder/local/settings/conditions', {conditions: templateContext})
.then(({html, js}) => {
const conditionsjs = $.parseHTML(templateContext.javascript, null, true).map(node => node.innerHTML).join("\n");
Templates.replaceNode(settingsConditionsRegion, html, js + conditionsjs);
initConditionsForm();
// Re-focus the add condition element after reloading the region.
const reportAddCondition = reportElement.querySelector(reportSelectors.actions.reportAddCondition);
reportAddCondition?.focus();
return pendingPromise.resolve();
});
};
/**
* Initialise conditions form, must be called on each init because the form container is re-created when switching editor modes
*/
const initConditionsForm = () => {
const reportElement = document.querySelector(reportSelectors.regions.report);
// Enhance condition selector.
const reportAddCondition = reportElement.querySelector(reportSelectors.actions.reportAddCondition);
AutoComplete.enhanceField(reportAddCondition, false, '', getString('selectacondition', 'core_reportbuilder'))
.catch(Notification.exception);
// Handle dynamic conditions form.
const conditionFormContainer = reportElement.querySelector(reportSelectors.regions.settingsConditions);
if (!conditionFormContainer) {
return;
}
const conditionForm = new DynamicForm(conditionFormContainer, '\\core_reportbuilder\\form\\condition');
// Submit report conditions.
conditionForm.addEventListener(conditionForm.events.FORM_SUBMITTED, event => {
event.preventDefault();
getString('conditionsapplied', 'core_reportbuilder')
.then(addToast)
.catch(Notification.exception);
// After the form has been submitted, we should trigger report table reload.
dispatchEvent(reportEvents.tableReload, {}, reportElement);
});
// Reset report conditions.
conditionForm.addEventListener(conditionForm.events.NOSUBMIT_BUTTON_PRESSED, event => {
event.preventDefault();
Notification.saveCancelPromise(
getString('resetconditions', 'core_reportbuilder'),
getString('resetconditionsconfirm', 'core_reportbuilder'),
getString('resetall', 'core_reportbuilder'),
{triggerElement: event.detail}
).then(() => {
const pendingPromise = new Pending('core_reportbuilder/conditions:reset');
return resetConditions(reportElement.dataset.reportId)
.then(data => reloadSettingsConditionsRegion(reportElement, data))
.then(() => addToast(getString('conditionsreset', 'core_reportbuilder')))
.then(() => {
dispatchEvent(reportEvents.tableReload, {}, reportElement);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}).catch(() => {
return;
});
});
};
/**
* Initialise module, prefetch all required strings
*
* @param {Boolean} initialized Ensure we only add our listeners once
*/
export const init = initialized => {
prefetchStrings('core_reportbuilder', [
'conditionadded',
'conditiondeleted',
'conditionmoved',
'conditionsapplied',
'conditionsreset',
'deletecondition',
'deleteconditionconfirm',
'resetall',
'resetconditions',
'resetconditionsconfirm',
'selectacondition',
]);
prefetchStrings('core', [
'delete',
]);
initConditionsForm();
if (initialized) {
return;
}
// Add condition to report.
document.addEventListener('change', event => {
const reportAddCondition = event.target.closest(reportSelectors.actions.reportAddCondition);
if (reportAddCondition) {
event.preventDefault();
// Check if dropdown is closed with no condition selected.
if (reportAddCondition.value === "" || reportAddCondition.value === "0") {
return;
}
const reportElement = reportAddCondition.closest(reportSelectors.regions.report);
const pendingPromise = new Pending('core_reportbuilder/conditions:add');
addCondition(reportElement.dataset.reportId, reportAddCondition.value)
.then(data => reloadSettingsConditionsRegion(reportElement, data))
.then(() => getString('conditionadded', 'core_reportbuilder',
reportAddCondition.options[reportAddCondition.selectedIndex].text))
.then(addToast)
.then(() => {
dispatchEvent(reportEvents.tableReload, {}, reportElement);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}
});
document.addEventListener('click', event => {
// Remove condition from report.
const reportRemoveCondition = event.target.closest(reportSelectors.actions.reportRemoveCondition);
if (reportRemoveCondition) {
event.preventDefault();
const reportElement = reportRemoveCondition.closest(reportSelectors.regions.report);
const conditionContainer = reportRemoveCondition.closest(reportSelectors.regions.activeCondition);
const conditionName = conditionContainer.dataset.conditionName;
Notification.saveCancelPromise(
getString('deletecondition', 'core_reportbuilder', conditionName),
getString('deleteconditionconfirm', 'core_reportbuilder', conditionName),
getString('delete', 'core'),
{triggerElement: reportRemoveCondition}
).then(() => {
const pendingPromise = new Pending('core_reportbuilder/conditions:remove');
return deleteCondition(reportElement.dataset.reportId, conditionContainer.dataset.conditionId)
.then(data => reloadSettingsConditionsRegion(reportElement, data))
.then(() => addToast(getString('conditiondeleted', 'core_reportbuilder', conditionName)))
.then(() => {
dispatchEvent(reportEvents.tableReload, {}, reportElement);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}).catch(() => {
return;
});
}
});
// Initialize sortable list to handle active conditions moving (note JQuery dependency, see MDL-72293 for resolution).
var activeConditionsSortableList = new SortableList(`${reportSelectors.regions.activeConditions}`,
{isHorizontal: false});
activeConditionsSortableList.getElementName = element => Promise.resolve(element.data('conditionName'));
$(document).on(SortableList.EVENTS.DROP, reportSelectors.regions.activeCondition, (event, info) => {
if (info.positionChanged) {
const pendingPromise = new Pending('core_reportbuilder/conditions:reorder');
const reportElement = event.target.closest(reportSelectors.regions.report);
const conditionId = info.element.data('conditionId');
const conditionPosition = info.element.data('conditionPosition');
// Select target position, if moving to the end then count number of element siblings.
let targetConditionPosition = info.targetNextElement.data('conditionPosition') || info.element.siblings().length + 2;
if (targetConditionPosition > conditionPosition) {
targetConditionPosition--;
}
// Re-order condition, giving drop event transition time to finish.
const reorderPromise = reorderCondition(reportElement.dataset.reportId, conditionId, targetConditionPosition);
Promise.all([reorderPromise, new Promise(resolve => setTimeout(resolve, 1000))])
.then(([data]) => reloadSettingsConditionsRegion(reportElement, data))
.then(() => getString('conditionmoved', 'core_reportbuilder', info.element.data('conditionName')))
.then(addToast)
.then(() => {
dispatchEvent(reportEvents.tableReload, {}, reportElement);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}
});
};
@@ -0,0 +1,181 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder filters editor
*
* @module core_reportbuilder/local/editor/filters
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
import $ from 'jquery';
import AutoComplete from 'core/form-autocomplete';
import 'core/inplace_editable';
import Notification from 'core/notification';
import Pending from 'core/pending';
import {prefetchStrings} from 'core/prefetch';
import SortableList from 'core/sortable_list';
import {getString} from 'core/str';
import Templates from 'core/templates';
import {add as addToast} from 'core/toast';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
import {addFilter, deleteFilter, reorderFilter} from 'core_reportbuilder/local/repository/filters';
/**
* Reload filters settings region
*
* @param {Element} reportElement
* @param {Object} templateContext
* @return {Promise}
*/
const reloadSettingsFiltersRegion = (reportElement, templateContext) => {
const pendingPromise = new Pending('core_reportbuilder/filters:reload');
const settingsFiltersRegion = reportElement.querySelector(reportSelectors.regions.settingsFilters);
return Templates.renderForPromise('core_reportbuilder/local/settings/filters', {filters: templateContext})
.then(({html, js}) => {
Templates.replaceNode(settingsFiltersRegion, html, js);
initFiltersForm();
// Re-focus the add filter element after reloading the region.
const reportAddFilter = reportElement.querySelector(reportSelectors.actions.reportAddFilter);
reportAddFilter?.focus();
return pendingPromise.resolve();
});
};
/**
* Initialise filters form, must be called on each init because the form container is re-created when switching editor modes
*/
const initFiltersForm = () => {
const reportElement = document.querySelector(reportSelectors.regions.report);
// Enhance filter selector.
const reportAddFilter = reportElement.querySelector(reportSelectors.actions.reportAddFilter);
AutoComplete.enhanceField(reportAddFilter, false, '', getString('selectafilter', 'core_reportbuilder'))
.catch(Notification.exception);
};
/**
* Initialise module, prefetch all required strings
*
* @param {Boolean} initialized Ensure we only add our listeners once
*/
export const init = initialized => {
prefetchStrings('core_reportbuilder', [
'deletefilter',
'deletefilterconfirm',
'filteradded',
'filterdeleted',
'filtermoved',
'selectafilter',
]);
prefetchStrings('core', [
'delete',
]);
initFiltersForm();
if (initialized) {
return;
}
// Add filter to report.
document.addEventListener('change', event => {
const reportAddFilter = event.target.closest(reportSelectors.actions.reportAddFilter);
if (reportAddFilter) {
event.preventDefault();
// Check if dropdown is closed with no filter selected.
if (reportAddFilter.value === "" || reportAddFilter.value === "0") {
return;
}
const reportElement = reportAddFilter.closest(reportSelectors.regions.report);
const pendingPromise = new Pending('core_reportbuilder/filters:add');
addFilter(reportElement.dataset.reportId, reportAddFilter.value)
.then(data => reloadSettingsFiltersRegion(reportElement, data))
.then(() => getString('filteradded', 'core_reportbuilder',
reportAddFilter.options[reportAddFilter.selectedIndex].text))
.then(addToast)
.then(() => pendingPromise.resolve())
.catch(Notification.exception);
}
});
document.addEventListener('click', event => {
// Remove filter from report.
const reportRemoveFilter = event.target.closest(reportSelectors.actions.reportRemoveFilter);
if (reportRemoveFilter) {
event.preventDefault();
const reportElement = reportRemoveFilter.closest(reportSelectors.regions.report);
const filterContainer = reportRemoveFilter.closest(reportSelectors.regions.activeFilter);
const filterName = filterContainer.dataset.filterName;
Notification.saveCancelPromise(
getString('deletefilter', 'core_reportbuilder', filterName),
getString('deletefilterconfirm', 'core_reportbuilder', filterName),
getString('delete', 'core'),
{triggerElement: reportRemoveFilter}
).then(() => {
const pendingPromise = new Pending('core_reportbuilder/filters:remove');
return deleteFilter(reportElement.dataset.reportId, filterContainer.dataset.filterId)
.then(data => reloadSettingsFiltersRegion(reportElement, data))
.then(() => addToast(getString('filterdeleted', 'core_reportbuilder', filterName)))
.then(() => pendingPromise.resolve())
.catch(Notification.exception);
}).catch(() => {
return;
});
}
});
// Initialize sortable list to handle active filters moving (note JQuery dependency, see MDL-72293 for resolution).
var activeFiltersSortableList = new SortableList(`${reportSelectors.regions.activeFilters} ul`, {isHorizontal: false});
activeFiltersSortableList.getElementName = element => Promise.resolve(element.data('filterName'));
$(document).on(SortableList.EVENTS.DROP, `${reportSelectors.regions.report} li[data-filter-id]`, (event, info) => {
if (info.positionChanged) {
const pendingPromise = new Pending('core_reportbuilder/filters:reorder');
const reportElement = event.target.closest(reportSelectors.regions.report);
const filterId = info.element.data('filterId');
const filterPosition = info.element.data('filterPosition');
// Select target position, if moving to the end then count number of element siblings.
let targetFilterPosition = info.targetNextElement.data('filterPosition') || info.element.siblings().length + 2;
if (targetFilterPosition > filterPosition) {
targetFilterPosition--;
}
// Re-order filter, giving drop event transition time to finish.
const reorderPromise = reorderFilter(reportElement.dataset.reportId, filterId, targetFilterPosition);
Promise.all([reorderPromise, new Promise(resolve => setTimeout(resolve, 1000))])
.then(([data]) => reloadSettingsFiltersRegion(reportElement, data))
.then(() => getString('filtermoved', 'core_reportbuilder', info.element.data('filterName')))
.then(addToast)
.then(() => pendingPromise.resolve())
.catch(Notification.exception);
}
});
};
@@ -0,0 +1,182 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder columns sorting editor
*
* @module core_reportbuilder/local/editor/sorting
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
import $ from 'jquery';
import 'core/inplace_editable';
import Notification from 'core/notification';
import Pending from 'core/pending';
import {subscribe} from 'core/pubsub';
import SortableList from 'core/sortable_list';
import {getString} from 'core/str';
import {add as addToast} from 'core/toast';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
import {reorderColumnSorting, toggleColumnSorting} from 'core_reportbuilder/local/repository/sorting';
import Templates from 'core/templates';
import {dispatchEvent} from 'core/event_dispatcher';
import * as reportEvents from 'core_reportbuilder/local/events';
// These constants match PHP consts SORT_ASC, SORT_DESC.
const SORTORDER = {
ASCENDING: 4,
DESCENDING: 3,
};
/**
* Reload sorting settings region
*
* @param {Object} context
* @return {Promise}
*/
const reloadSettingsSortingRegion = context => {
const pendingPromise = new Pending('core_reportbuilder/sorting:reload');
const settingsSortingRegion = document.querySelector(reportSelectors.regions.settingsSorting);
return Templates.renderForPromise('core_reportbuilder/local/settings/sorting', {sorting: context})
.then(({html, js}) => {
Templates.replaceNode(settingsSortingRegion, html, js);
return pendingPromise.resolve();
});
};
/**
* Updates column sorting
*
* @param {Element} reportElement
* @param {Element} element
* @param {Number} sortenabled
* @param {Number} sortdirection
* @return {Promise}
*/
const updateSorting = (reportElement, element, sortenabled, sortdirection) => {
const reportId = reportElement.dataset.reportId;
const listElement = element.closest('li');
const columnId = listElement.dataset.columnSortId;
const columnName = listElement.dataset.columnSortName;
return toggleColumnSorting(reportId, columnId, sortenabled, sortdirection)
.then(reloadSettingsSortingRegion)
.then(() => getString('columnsortupdated', 'core_reportbuilder', columnName))
.then(addToast)
.then(() => {
dispatchEvent(reportEvents.tableReload, {}, reportElement);
return null;
});
};
/**
* Initialise module
*
* @param {Boolean} initialized Ensure we only add our listeners once
*/
export const init = (initialized) => {
if (initialized) {
return;
}
// Update sorting region each time report columns are updated (added or removed).
subscribe(reportEvents.publish.reportColumnsUpdated, data => reloadSettingsSortingRegion(data)
.catch(Notification.exception)
);
document.addEventListener('click', event => {
// Enable/disable sorting on columns.
const toggleSorting = event.target.closest(reportSelectors.actions.reportToggleColumnSort);
if (toggleSorting) {
event.preventDefault();
const pendingPromise = new Pending('core_reportbuilder/sorting:toggle');
const reportElement = toggleSorting.closest(reportSelectors.regions.report);
const sortdirection = parseInt(toggleSorting.closest('li').dataset.columnSortDirection);
updateSorting(reportElement, toggleSorting, toggleSorting.checked, sortdirection)
.then(() => {
// Re-focus the toggle sorting element after reloading the region.
const toggleSortingElement = document.getElementById(toggleSorting.id);
toggleSortingElement?.focus();
return pendingPromise.resolve();
})
.catch(Notification.exception);
}
// Change column sort direction.
const toggleSortDirection = event.target.closest(reportSelectors.actions.reportToggleColumnSortDirection);
if (toggleSortDirection) {
event.preventDefault();
const pendingPromise = new Pending('core_reportbuilder/sorting:direction');
const reportElement = toggleSortDirection.closest(reportSelectors.regions.report);
const listElement = toggleSortDirection.closest('li');
const toggleSorting = listElement.querySelector(reportSelectors.actions.reportToggleColumnSort);
let sortdirection = parseInt(listElement.dataset.columnSortDirection);
if (sortdirection === SORTORDER.ASCENDING) {
sortdirection = SORTORDER.DESCENDING;
} else if (sortdirection === SORTORDER.DESCENDING) {
sortdirection = SORTORDER.ASCENDING;
}
updateSorting(reportElement, toggleSortDirection, toggleSorting.checked, sortdirection)
.then(() => {
// Re-focus the toggle sort direction element after reloading the region.
const toggleSortDirectionElement = document.getElementById(toggleSortDirection.id);
toggleSortDirectionElement?.focus();
return pendingPromise.resolve();
})
.catch(Notification.exception);
}
});
// Initialize sortable list to handle column sorting moving (note JQuery dependency, see MDL-72293 for resolution).
var columnsSortingSortableList = new SortableList(`${reportSelectors.regions.settingsSorting} ul`, {isHorizontal: false});
columnsSortingSortableList.getElementName = element => Promise.resolve(element.data('columnSortName'));
$(document).on(SortableList.EVENTS.DROP, `${reportSelectors.regions.report} li[data-column-sort-id]`, (event, info) => {
if (info.positionChanged) {
const pendingPromise = new Pending('core_reportbuilder/sorting:reorder');
const reportElement = event.target.closest(reportSelectors.regions.report);
const columnId = info.element.data('columnSortId');
const columnPosition = info.element.data('columnSortPosition');
// Select target position, if moving to the end then count number of element siblings.
let targetColumnSortPosition = info.targetNextElement.data('columnSortPosition') || info.element.siblings().length + 2;
if (targetColumnSortPosition > columnPosition) {
targetColumnSortPosition--;
}
// Re-order column sorting, giving drop event transition time to finish.
const reorderPromise = reorderColumnSorting(reportElement.dataset.reportId, columnId, targetColumnSortPosition);
Promise.all([reorderPromise, new Promise(resolve => setTimeout(resolve, 1000))])
.then(([data]) => reloadSettingsSortingRegion(data))
.then(() => getString('columnsortupdated', 'core_reportbuilder', info.element.data('columnSortName')))
.then(addToast)
.then(() => {
dispatchEvent(reportEvents.tableReload, {}, reportElement);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}
});
};
+50
View File
@@ -0,0 +1,50 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder events
*
* @module core_reportbuilder/local/events
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Events for the Report builder subsystem
*
* @constant
* @property {String} tableReload See {@link event:tableReload}
*/
export default {
/**
* Trigger table reloading
*
* @event tableReload
* @type {CustomEvent}
* @property {object} detail
* @property {Boolean} detail.preservePagination Whether current pagination should be preserved (default false)
* @property {String} detail.preserveTriggerElement Element selector that should be focused after table reload (default null)
*
* @example <caption>Triggering table reload</caption>
* import {dispatchEvent} from 'core/event_dispatcher';
* import * as reportEvents from 'core_reportbuilder/local/events';
*
* dispatchEvent(reportEvents.tableReload, {}, document.querySelector(...));
*/
tableReload: 'core_reportbuilder_table_reload',
publish: {
reportColumnsUpdated: 'core_reportbuilder_report_columns_updated',
},
};
@@ -0,0 +1,40 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Module to handle audiences AJAX requests
*
* @module core_reportbuilder/local/repository/audiences
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Ajax from 'core/ajax';
/**
* Remove audience from given report
*
* @param {Number} reportId
* @param {Number} instanceId
* @return {Promise}
*/
export const deleteAudience = (reportId, instanceId) => {
const request = {
methodname: 'core_reportbuilder_audiences_delete',
args: {reportid: reportId, instanceid: instanceId}
};
return Ajax.call([request])[0];
};
@@ -0,0 +1,73 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Module to handle column AJAX requests
*
* @module core_reportbuilder/local/repository/columns
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Ajax from 'core/ajax';
/**
* Add column to given report
*
* @param {Number} reportId
* @param {String} uniqueIdentifier
* @return {Promise}
*/
export const addColumn = (reportId, uniqueIdentifier) => {
const request = {
methodname: 'core_reportbuilder_columns_add',
args: {reportid: reportId, uniqueidentifier: uniqueIdentifier}
};
return Ajax.call([request])[0];
};
/**
* Remove column from given report
*
* @param {Number} reportId
* @param {Number} columnId
* @return {Promise}
*/
export const deleteColumn = (reportId, columnId) => {
const request = {
methodname: 'core_reportbuilder_columns_delete',
args: {reportid: reportId, columnid: columnId}
};
return Ajax.call([request])[0];
};
/**
* Re-order column within a report
*
* @param {Number} reportId
* @param {Number} columnId
* @param {Number} position
* @return {Promise}
*/
export const reorderColumn = (reportId, columnId, position) => {
const request = {
methodname: 'core_reportbuilder_columns_reorder',
args: {reportid: reportId, columnid: columnId, position: position}
};
return Ajax.call([request])[0];
};
@@ -0,0 +1,88 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Module to handle condition AJAX requests
*
* @module core_reportbuilder/local/repository/conditions
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Ajax from 'core/ajax';
/**
* Reset all conditions for given report
*
* @param {Number} reportId
* @return {Promise}
*/
export const resetConditions = reportId => {
const request = {
methodname: 'core_reportbuilder_conditions_reset',
args: {reportid: reportId}
};
return Ajax.call([request])[0];
};
/**
* Add condition to given report
*
* @param {Number} reportId
* @param {String} uniqueIdentifier
* @return {Promise}
*/
export const addCondition = (reportId, uniqueIdentifier) => {
const request = {
methodname: 'core_reportbuilder_conditions_add',
args: {reportid: reportId, uniqueidentifier: uniqueIdentifier}
};
return Ajax.call([request])[0];
};
/**
* Remove condition from given report
*
* @param {Number} reportId
* @param {Number} conditionId
* @return {Promise}
*/
export const deleteCondition = (reportId, conditionId) => {
const request = {
methodname: 'core_reportbuilder_conditions_delete',
args: {reportid: reportId, conditionid: conditionId}
};
return Ajax.call([request])[0];
};
/**
* Reorder a condition in a given report
*
* @param {Number} reportId
* @param {Number} conditionId
* @param {Number} position
* @return {Promise}
*/
export const reorderCondition = (reportId, conditionId, position) => {
const request = {
methodname: 'core_reportbuilder_conditions_reorder',
args: {reportid: reportId, conditionid: conditionId, position: position}
};
return Ajax.call([request])[0];
};
@@ -0,0 +1,108 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Module to handle filter AJAX requests
*
* @module core_reportbuilder/local/repository/filters
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Ajax from 'core/ajax';
/**
* Reset all filters for given report
*
* @method
* @param {Number} reportId
* @param {String} reportParameters
* @return {Promise}
*/
export const resetFilters = (reportId, reportParameters) => {
const request = {
methodname: 'core_reportbuilder_filters_reset',
args: {reportid: reportId, parameters: reportParameters}
};
return Ajax.call([request])[0];
};
/**
* Set filter values for given report
*
* @method
* @param {Number} reportId
* @param {String} reportParameters
* @param {String} filterValues
* @return {Promise}
*/
export const setFilters = (reportId, reportParameters, filterValues) => {
const request = {
methodname: 'core_reportbuilder_set_filters',
args: {reportid: reportId, parameters: reportParameters, values: filterValues}
};
return Ajax.call([request])[0];
};
/**
* Add a filter to the given report
*
* @param {Number} reportId
* @param {String} uniqueIdentifier
* @return {Promise}
*/
export const addFilter = (reportId, uniqueIdentifier) => {
const request = {
methodname: 'core_reportbuilder_filters_add',
args: {reportid: reportId, uniqueidentifier: uniqueIdentifier}
};
return Ajax.call([request])[0];
};
/**
* Remove filter from given report
*
* @param {Number} reportId
* @param {Number} filterId
* @return {Promise}
*/
export const deleteFilter = (reportId, filterId) => {
const request = {
methodname: 'core_reportbuilder_filters_delete',
args: {reportid: reportId, filterid: filterId}
};
return Ajax.call([request])[0];
};
/**
* Reorder a filter in a given report
*
* @param {Number} reportId
* @param {Number} filterId
* @param {Number} position
* @return {Promise}
*/
export const reorderFilter = (reportId, filterId, position) => {
const request = {
methodname: 'core_reportbuilder_filters_reorder',
args: {reportid: reportId, filterid: filterId, position: position}
};
return Ajax.call([request])[0];
};
@@ -0,0 +1,76 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Module to handle modal form requests
*
* @module core_reportbuilder/local/repository/modals
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import ModalForm from 'core_form/modalform';
import {getString} from 'core/str';
/**
* Return modal instance
*
* @param {EventTarget} triggerElement
* @param {Promise} modalTitle
* @param {String} formClass
* @param {Object} formArgs
* @return {ModalForm}
*/
const createModalForm = (triggerElement, modalTitle, formClass, formArgs) => {
return new ModalForm({
modalConfig: {
title: modalTitle,
},
formClass: formClass,
args: formArgs,
saveButtonText: getString('save', 'moodle'),
returnFocus: triggerElement,
});
};
/**
* Return report modal instance
*
* @param {EventTarget} triggerElement
* @param {Promise} modalTitle
* @param {Number} reportId
* @return {ModalForm}
*/
export const createReportModal = (triggerElement, modalTitle, reportId = 0) => {
return createModalForm(triggerElement, modalTitle, 'core_reportbuilder\\form\\report', {
id: reportId,
});
};
/**
* Return schedule modal instance
*
* @param {EventTarget} triggerElement
* @param {Promise} modalTitle
* @param {Number} reportId
* @param {Number} scheduleId
* @return {ModalForm}
*/
export const createScheduleModal = (triggerElement, modalTitle, reportId, scheduleId = 0) => {
return createModalForm(triggerElement, modalTitle, 'core_reportbuilder\\form\\schedule', {
reportid: reportId,
id: scheduleId,
});
};
@@ -0,0 +1,56 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Module to handle report AJAX requests
*
* @module core_reportbuilder/local/repository/reports
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Ajax from 'core/ajax';
/**
* Delete given report
*
* @param {Number} reportId
* @return {Promise}
*/
export const deleteReport = reportId => {
const request = {
methodname: 'core_reportbuilder_reports_delete',
args: {reportid: reportId}
};
return Ajax.call([request])[0];
};
/**
* Get report content
*
* @param {Number} reportId
* @param {Boolean} editMode
* @param {Number} [pageSize=0]
* @return {Promise}
*/
export const getReport = (reportId, editMode, pageSize = 0) => {
const request = {
methodname: 'core_reportbuilder_reports_get',
args: {reportid: reportId, editmode: editMode, pagesize: pageSize}
};
return Ajax.call([request])[0];
};
@@ -0,0 +1,76 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Module to handle schedule AJAX requests
*
* @module core_reportbuilder/local/repository/schedules
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Ajax from 'core/ajax';
/**
* Delete schedule
*
* @method
* @param {Number} reportId
* @param {Number} scheduleId
* @return {Promise}
*/
export const deleteSchedule = (reportId, scheduleId) => {
const request = {
methodname: 'core_reportbuilder_schedules_delete',
args: {reportid: reportId, scheduleid: scheduleId}
};
return Ajax.call([request])[0];
};
/**
* Send schedule
*
* @method
* @param {Number} reportId
* @param {Number} scheduleId
* @return {Promise}
*/
export const sendSchedule = (reportId, scheduleId) => {
const request = {
methodname: 'core_reportbuilder_schedules_send',
args: {reportid: reportId, scheduleid: scheduleId}
};
return Ajax.call([request])[0];
};
/**
* Toggle schedule enabled
*
* @method
* @param {Number} reportId
* @param {Number} scheduleId
* @param {Boolean} scheduleEnabled
* @return {Promise}
*/
export const toggleSchedule = (reportId, scheduleId, scheduleEnabled) => {
const request = {
methodname: 'core_reportbuilder_schedules_toggle',
args: {reportid: reportId, scheduleid: scheduleId, enabled: scheduleEnabled}
};
return Ajax.call([request])[0];
};
@@ -0,0 +1,74 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Module to handle column sorting AJAX requests
*
* @module core_reportbuilder/local/repository/sorting
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Ajax from 'core/ajax';
/**
* Retrieve column sorting
*
* @param {Number} reportId
* @return {Promise}
*/
export const getColumnSorting = reportId => {
const request = {
methodname: 'core_reportbuilder_columns_sort_get',
args: {reportid: reportId}
};
return Ajax.call([request])[0];
};
/**
* Re-order sort column position
*
* @param {Number} reportId
* @param {Number} columnId
* @param {Number} position
* @return {Promise}
*/
export const reorderColumnSorting = (reportId, columnId, position) => {
const request = {
methodname: 'core_reportbuilder_columns_sort_reorder',
args: {reportid: reportId, columnid: columnId, position: position}
};
return Ajax.call([request])[0];
};
/**
* Enables/disabled sorting on column
*
* @param {Number} reportId
* @param {Number} columnId
* @param {Boolean} enabled
* @param {Number} direction
* @return {Promise}
*/
export const toggleColumnSorting = (reportId, columnId, enabled, direction) => {
const request = {
methodname: 'core_reportbuilder_columns_sort_toggle',
args: {reportid: reportId, columnid: columnId, enabled: enabled, direction: direction}
};
return Ajax.call([request])[0];
};
+95
View File
@@ -0,0 +1,95 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder selectors
*
* @module core_reportbuilder/local/selectors
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Selectors for the Report builder subsystem
*
* @property {Object} regions
* @property {String} regions.systemReport System report page region
* @property {String} regions.filterButtonLabel Filters form toggle region
* @property {String} regions.filtersForm Filters form page region
*/
const SELECTORS = {
regions: {
report: '[data-region="core_reportbuilder/report"]',
reportTable: '[data-region="reportbuilder-table"]',
columnHeader: '[data-region="column-header"]',
filterButtonLabel: '[data-region="filter-button-label"]',
filtersForm: '[data-region="filters-form"]',
sidebarMenu: '[data-region="sidebar-menu"]',
sidebarCard: '[data-region="sidebar-card"]',
sidebarItem: '[data-region="sidebar-item"]',
settingsConditions: '[data-region="settings-conditions"]',
activeConditions: '[data-region="active-conditions"]',
activeCondition: '[data-region="active-condition"]',
settingsFilters: '[data-region="settings-filters"]',
activeFilters: '[data-region="active-filters"]',
activeFilter: '[data-region="active-filter"]',
settingsSorting: '[data-region="settings-sorting"]',
audiencesContainer: '[data-region="audiences"]',
audienceFormContainer: '[data-region="audience-form-container"]',
audienceCard: '[data-region="audience-card"]',
audienceHeading: '[data-region="audience-heading"]',
audienceForm: '[data-region="audience-form"]',
audienceEmptyMessage: '[data-region=no-instances-message]',
audienceDescription: '[data-region=audience-description]',
audienceNotSavedLabel: '[data-region=audience-not-saved]',
settingsCardView: '[data-region="settings-cardview"]',
},
actions: {
reportActionPopup: '[data-action="report-action-popup"]',
reportCreate: '[data-action="report-create"]',
reportEdit: '[data-action="report-edit"]',
reportDelete: '[data-action="report-delete"]',
reportAddColumn: '[data-action="report-add-column"]',
reportRemoveColumn: '[data-action="report-remove-column"]',
reportAddCondition: '[data-action="report-add-condition"]',
reportRemoveCondition: '[data-action="report-remove-condition"]',
reportAddFilter: '[data-action="report-add-filter"]',
reportRemoveFilter: '[data-action="report-remove-filter"]',
reportToggleColumnSort: '[data-action="report-toggle-column-sorting"]',
reportToggleColumnSortDirection: '[data-action="report-toggle-sort-direction"]',
sidebarSearch: '[data-action="sidebar-search"]',
toggleEditPreview: '[data-action="toggle-edit-preview"]',
audienceAdd: '[data-action="add-audience"]',
audienceEdit: '[data-action="edit-audience"]',
audienceDelete: '[data-action="delete-audience"]',
toggleCardView: '[data-action="toggle-card"]',
scheduleCreate: '[data-action="schedule-create"]',
scheduleToggle: '[data-action="schedule-toggle"]',
scheduleEdit: '[data-action="schedule-edit"]',
scheduleSend: '[data-action="schedule-send"]',
scheduleDelete: '[data-action="schedule-delete"]',
},
};
/**
* Selector for given report
*
* @method forReport
* @param {Number} reportId
* @return {String}
*/
SELECTORS.forReport = reportId => `${SELECTORS.regions.report}[data-report-id="${reportId}"]`;
export default SELECTORS;
+107
View File
@@ -0,0 +1,107 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder report management
*
* @module core_reportbuilder/report
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Notification from 'core/notification';
import * as reportEvents from 'core_reportbuilder/local/events';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
import {setPageNumber, refreshTableContent} from 'core_table/dynamic';
import * as tableSelectors from 'core_table/local/dynamic/selectors';
const CLASSES = {
COLLAPSED: 'collapsed',
EXPANDED: 'show',
ICONUP: 'fa-angle-up',
ICONDOWN: 'fa-angle-down'
};
let initialized = false;
/**
* Initialise module for given report
*
* @method
*/
export const init = () => {
if (initialized) {
// We already added the event listeners (can be called multiple times by mustache template).
return;
}
// Listen for the table reload event.
document.addEventListener(reportEvents.tableReload, async(event) => {
const reportElement = event.target.closest(reportSelectors.regions.report);
if (reportElement === null) {
return;
}
const tableRoot = reportElement.querySelector(tableSelectors.main.region);
const pageNumber = event.detail?.preservePagination ? null : 1;
await setPageNumber(tableRoot, pageNumber, false)
.then(refreshTableContent)
.then(() => {
// TODO: Refactor this after MDL-73130 lands.
const preserveTriggerElement = event.detail?.preserveTriggerElement;
if (preserveTriggerElement) {
reportElement.querySelector(preserveTriggerElement)?.focus();
}
return;
})
.catch(Notification.exception);
});
// Listen for trigger popup events.
document.addEventListener('click', event => {
const reportActionPopup = event.target.closest(reportSelectors.actions.reportActionPopup);
if (reportActionPopup === null) {
return;
}
event.preventDefault();
const popupAction = JSON.parse(reportActionPopup.dataset.popupAction);
window.openpopup(event, popupAction.jsfunctionargs);
});
// Listen for card view toggle events.
document.addEventListener('click', (event) => {
const toggleCard = event.target.closest(reportSelectors.actions.toggleCardView);
if (toggleCard) {
const tableCard = toggleCard.closest('tr');
const toggleIcon = toggleCard.querySelector('i');
event.preventDefault();
if (toggleCard.classList.contains(CLASSES.COLLAPSED)) {
tableCard.classList.add(CLASSES.EXPANDED);
toggleIcon.classList.replace(CLASSES.ICONDOWN, CLASSES.ICONUP);
toggleCard.classList.remove(CLASSES.COLLAPSED);
toggleCard.setAttribute('aria-expanded', "true");
} else {
tableCard.classList.remove(CLASSES.EXPANDED);
toggleIcon.classList.replace(CLASSES.ICONUP, CLASSES.ICONDOWN);
toggleCard.classList.add(CLASSES.COLLAPSED);
toggleCard.removeAttribute('aria-expanded');
}
}
});
initialized = true;
};
+119
View File
@@ -0,0 +1,119 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder reports list management
*
* @module core_reportbuilder/reports_list
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
import {dispatchEvent} from 'core/event_dispatcher';
import Notification from 'core/notification';
import Pending from 'core/pending';
import {prefetchStrings} from 'core/prefetch';
import {getString} from 'core/str';
import {add as addToast} from 'core/toast';
import * as reportEvents from 'core_reportbuilder/local/events';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
import {deleteReport} from 'core_reportbuilder/local/repository/reports';
import {createReportModal} from 'core_reportbuilder/local/repository/modals';
/**
* Initialise module
*/
export const init = () => {
prefetchStrings('core_reportbuilder', [
'deletereport',
'deletereportconfirm',
'editreportdetails',
'newreport',
'reportdeleted',
'reportupdated',
]);
prefetchStrings('core', [
'delete',
]);
document.addEventListener('click', event => {
const reportCreate = event.target.closest(reportSelectors.actions.reportCreate);
if (reportCreate) {
event.preventDefault();
// Redirect user to editing interface for the report after submission.
const reportModal = createReportModal(event.target, getString('newreport', 'core_reportbuilder'));
reportModal.addEventListener(reportModal.events.FORM_SUBMITTED, event => {
window.location.href = event.detail;
});
reportModal.show();
}
const reportEdit = event.target.closest(reportSelectors.actions.reportEdit);
if (reportEdit) {
event.preventDefault();
// Reload current report page after submission.
// Use triggerElement to return focus to the action menu toggle.
const triggerElement = reportEdit.closest('.dropdown').querySelector('.dropdown-toggle');
const reportModal = createReportModal(triggerElement, getString('editreportdetails', 'core_reportbuilder'),
reportEdit.dataset.reportId);
reportModal.addEventListener(reportModal.events.FORM_SUBMITTED, () => {
const reportElement = event.target.closest(reportSelectors.regions.report);
getString('reportupdated', 'core_reportbuilder')
.then(addToast)
.then(() => {
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
return;
})
.catch(Notification.exception);
});
reportModal.show();
}
const reportDelete = event.target.closest(reportSelectors.actions.reportDelete);
if (reportDelete) {
event.preventDefault();
// Use triggerElement to return focus to the action menu toggle.
const triggerElement = reportDelete.closest('.dropdown').querySelector('.dropdown-toggle');
Notification.saveCancelPromise(
getString('deletereport', 'core_reportbuilder'),
getString('deletereportconfirm', 'core_reportbuilder', reportDelete.dataset.reportName),
getString('delete', 'core'),
{triggerElement}
).then(() => {
const pendingPromise = new Pending('core_reportbuilder/reports:delete');
const reportElement = event.target.closest(reportSelectors.regions.report);
return deleteReport(reportDelete.dataset.reportId)
.then(() => addToast(getString('reportdeleted', 'core_reportbuilder')))
.then(() => {
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}).catch(() => {
return;
});
}
});
};
+194
View File
@@ -0,0 +1,194 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder audiences
*
* @module core_reportbuilder/schedules
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
import {dispatchEvent} from 'core/event_dispatcher';
import 'core/inplace_editable';
import Notification from 'core/notification';
import Pending from 'core/pending';
import {prefetchStrings} from 'core/prefetch';
import {getString} from 'core/str';
import {add as addToast} from 'core/toast';
import * as reportEvents from 'core_reportbuilder/local/events';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
import {createScheduleModal} from 'core_reportbuilder/local/repository/modals';
import {deleteSchedule, sendSchedule, toggleSchedule} from 'core_reportbuilder/local/repository/schedules';
let initialized = false;
/**
* Initialise schedules tab
*
* @param {Number} reportId
*/
export const init = reportId => {
prefetchStrings('core_reportbuilder', [
'deleteschedule',
'deletescheduleconfirm',
'disableschedule',
'editscheduledetails',
'enableschedule',
'newschedule',
'schedulecreated',
'scheduledeleted',
'schedulesent',
'scheduleupdated',
'sendschedule',
'sendscheduleconfirm',
]);
prefetchStrings('core', [
'confirm',
'delete',
]);
if (initialized) {
// We already added the event listeners (can be called multiple times by mustache template).
return;
}
document.addEventListener('click', event => {
// Create schedule.
const scheduleCreate = event.target.closest(reportSelectors.actions.scheduleCreate);
if (scheduleCreate) {
event.preventDefault();
const scheduleModal = createScheduleModal(event.target, getString('newschedule', 'core_reportbuilder'), reportId);
scheduleModal.addEventListener(scheduleModal.events.FORM_SUBMITTED, () => {
getString('schedulecreated', 'core_reportbuilder')
.then(addToast)
.then(() => {
const reportElement = document.querySelector(reportSelectors.regions.report);
dispatchEvent(reportEvents.tableReload, {}, reportElement);
return;
})
.catch(Notification.exception);
});
scheduleModal.show();
}
// Toggle schedule.
const scheduleToggle = event.target.closest(reportSelectors.actions.scheduleToggle);
if (scheduleToggle) {
const pendingPromise = new Pending('core_reportbuilder/schedules:toggle');
const scheduleStateToggle = +!Number(scheduleToggle.dataset.state);
toggleSchedule(reportId, scheduleToggle.dataset.id, scheduleStateToggle)
.then(() => {
const tableRow = scheduleToggle.closest('tr');
tableRow.classList.toggle('text-muted');
scheduleToggle.dataset.state = scheduleStateToggle;
const stringKey = scheduleStateToggle ? 'disableschedule' : 'enableschedule';
return getString(stringKey, 'core_reportbuilder');
})
.then(toggleLabel => {
const labelContainer = scheduleToggle.parentElement.querySelector(`label[for="${scheduleToggle.id}"] > span`);
labelContainer.innerHTML = toggleLabel;
return pendingPromise.resolve();
})
.catch(Notification.exception);
}
// Edit schedule.
const scheduleEdit = event.target.closest(reportSelectors.actions.scheduleEdit);
if (scheduleEdit) {
event.preventDefault();
// Use triggerElement to return focus to the action menu toggle.
const triggerElement = scheduleEdit.closest('.dropdown').querySelector('.dropdown-toggle');
const scheduleModal = createScheduleModal(triggerElement, getString('editscheduledetails', 'core_reportbuilder'),
reportId, scheduleEdit.dataset.scheduleId);
scheduleModal.addEventListener(scheduleModal.events.FORM_SUBMITTED, () => {
getString('scheduleupdated', 'core_reportbuilder')
.then(addToast)
.then(() => {
const reportElement = scheduleEdit.closest(reportSelectors.regions.report);
dispatchEvent(reportEvents.tableReload, {}, reportElement);
return;
})
.catch(Notification.exception);
});
scheduleModal.show();
}
// Send schedule.
const scheduleSend = event.target.closest(reportSelectors.actions.scheduleSend);
if (scheduleSend) {
event.preventDefault();
// Use triggerElement to return focus to the action menu toggle.
const triggerElement = scheduleSend.closest('.dropdown').querySelector('.dropdown-toggle');
Notification.saveCancelPromise(
getString('sendschedule', 'core_reportbuilder'),
getString('sendscheduleconfirm', 'core_reportbuilder', scheduleSend.dataset.scheduleName),
getString('confirm', 'core'),
{triggerElement}
).then(() => {
const pendingPromise = new Pending('core_reportbuilder/schedules:send');
return sendSchedule(reportId, scheduleSend.dataset.scheduleId)
.then(addToast(getString('schedulesent', 'core_reportbuilder')))
.then(() => pendingPromise.resolve())
.catch(Notification.exception);
}).catch(() => {
return;
});
}
// Delete schedule.
const scheduleDelete = event.target.closest(reportSelectors.actions.scheduleDelete);
if (scheduleDelete) {
event.preventDefault();
// Use triggerElement to return focus to the action menu toggle.
const triggerElement = scheduleDelete.closest('.dropdown').querySelector('.dropdown-toggle');
Notification.saveCancelPromise(
getString('deleteschedule', 'core_reportbuilder'),
getString('deletescheduleconfirm', 'core_reportbuilder', scheduleDelete.dataset.scheduleName),
getString('delete', 'core'),
{triggerElement}
).then(() => {
const pendingPromise = new Pending('core_reportbuilder/schedules:delete');
return deleteSchedule(reportId, scheduleDelete.dataset.scheduleId)
.then(addToast(getString('scheduledeleted', 'core_reportbuilder')))
.then(() => {
const reportElement = scheduleDelete.closest(reportSelectors.regions.report);
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}).catch(() => {
return;
});
}
});
initialized = true;
};
+101
View File
@@ -0,0 +1,101 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Report builder sidebar component
*
* @module core_reportbuilder/sidebar
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Pending from 'core/pending';
import {debounce} from 'core/utils';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
const DEBOUNCE_TIMER = 250;
const CLASSES = {
EXPANDED: 'show',
COLLAPSED: 'collapsed',
HIDE: 'd-none',
};
/**
* Initialise module
*
* @param {Event} event
* @param {Element} sidebarMenu
*/
const sidebarCardFilter = (event, sidebarMenu) => {
const pendingPromise = new Pending('core_reportbuilder/sidebar:cardFilter');
const sidebarCards = sidebarMenu.querySelectorAll(reportSelectors.regions.sidebarCard);
const sidebarItems = sidebarMenu.querySelectorAll(reportSelectors.regions.sidebarItem);
const searchTerm = event.target.value.toLowerCase();
// Toggle items according to match against search term.
sidebarItems.forEach(item => {
const itemContent = item.textContent.toLowerCase();
item.classList.toggle(CLASSES.HIDE, !itemContent.includes(searchTerm));
});
// Toggle cards according to whether they have any visible items.
sidebarCards.forEach(card => {
const visibleItems = card.querySelectorAll(`${reportSelectors.regions.sidebarItem}:not(.${CLASSES.HIDE})`);
card.classList.toggle(CLASSES.HIDE, !visibleItems.length);
expandCard(card);
});
pendingPromise.resolve();
};
/**
* Show a collapsed card.
* This function simulates the behaviour of JQuery show method on a collapsible element.
*
* @param {Element} card
*/
const expandCard = (card) => {
let cardButton = card.querySelector('[data-toggle="collapse"]');
if (cardButton.classList.contains(CLASSES.COLLAPSED)) {
cardButton.classList.remove(CLASSES.COLLAPSED);
cardButton.setAttribute('aria-expanded', "true");
let cardContent = card.querySelector(cardButton.dataset.target);
cardContent.classList.add(CLASSES.EXPANDED);
}
};
/**
* Initialise module
*
* @param {string} selectorId
*/
export const init = (selectorId) => {
const sidebarMenu = document.querySelector(selectorId + reportSelectors.regions.sidebarMenu);
const sidebarSearch = sidebarMenu.querySelector(reportSelectors.actions.sidebarSearch);
// Debounce the event listener to allow the user to finish typing.
const sidebarSearchDebounce = debounce(sidebarCardFilter, DEBOUNCE_TIMER);
sidebarSearch.addEventListener('keyup', event => {
const pendingPromise = new Pending('core_reportbuilder/sidebar:keyup');
sidebarSearchDebounce(event, sidebarMenu);
setTimeout(() => {
pendingPromise.resolve();
}, DEBOUNCE_TIMER);
});
};