mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 12:32:08 +02:00
MDL-70795 reportbuilder: custom report filters editor.
Implement module for filters editing, allowing the report editor to define which filters are available when users are viewing the report. These filters allow those users viewing the report to further limit the data being displayed (after conditions have been applied), by selecting their own values for each filter. Co-authored-by: Paul Holden <paulh@moodle.com>
This commit is contained in:
parent
ab596ec11a
commit
09b69d04e3
@ -48,11 +48,14 @@ $string['columnmoved'] = 'Moved column \'{$a}\'';
|
||||
$string['customreports'] = 'Custom reports';
|
||||
$string['deletecolumn'] = 'Delete column \'{$a}\'';
|
||||
$string['deletecolumnconfirm'] = 'Are you sure you want to delete the column \'{$a}\'?';
|
||||
$string['deletefilter'] = 'Delete filter \'{$a}\'';
|
||||
$string['deletefilterconfirm'] = 'Are you sure you want to delete the filter \'{$a}\'?';
|
||||
$string['entitycourse'] = 'Course';
|
||||
$string['entityuser'] = 'User';
|
||||
$string['errorreportaccess'] = 'You can not view this report';
|
||||
$string['errorsourceinvalid'] = 'Could not find valid report source';
|
||||
$string['errorsourceunavailable'] = 'Report source is not available';
|
||||
$string['filteradded'] = 'Added filter \'{$a}\'';
|
||||
$string['filtercontains'] = 'Contains';
|
||||
$string['filterdatecurrent'] = 'Current';
|
||||
$string['filterdatedays'] = 'day(s)';
|
||||
@ -66,6 +69,7 @@ $string['filterdateseconds'] = 'second(s)';
|
||||
$string['filterdateto'] = 'Date to';
|
||||
$string['filterdateweeks'] = 'week(s)';
|
||||
$string['filterdateyears'] = 'year(s)';
|
||||
$string['filterdeleted'] = 'Deleted filter \'{$a}\'';
|
||||
$string['filterdoesnotcontain'] = 'Does not contain';
|
||||
$string['filterdurationunit'] = '{$a} unit';
|
||||
$string['filterendswith'] = 'Ends with';
|
||||
@ -81,17 +85,22 @@ $string['filterisequalto'] = 'Is equal to';
|
||||
$string['filterisnotempty'] = 'Is not empty';
|
||||
$string['filterisnotequalto'] = 'Is not equal to';
|
||||
$string['filterlessthan'] = 'Less than';
|
||||
$string['filtermoved'] = 'Moved filter \'{$a}\'';
|
||||
$string['filterrange'] = 'Range';
|
||||
$string['filtersapplied'] = 'Filters applied';
|
||||
$string['filtersappliedx'] = 'Filters ({$a})';
|
||||
$string['filters'] = 'Filters';
|
||||
$string['filters_help'] = 'Report filters allow users viewing the report to further limit the data being displayed, by selecting their own values for each filter. Filter values are stored on a per-user basis.';
|
||||
$string['filtersreset'] = 'Filters reset';
|
||||
$string['filterstartswith'] = 'Starts with';
|
||||
$string['includedefaultsetup'] = 'Include default setup';
|
||||
$string['includedefaultsetup_help'] = 'Populate report with default layout as defined by the selected source. These include pre-defined columns, filters and conditions.';
|
||||
$string['movecolumn'] = 'Move column \'{$a}\'';
|
||||
$string['movecondition'] = 'Move condition \'{$a}\'';
|
||||
$string['movefilter'] = 'Move filter \'{$a}\'';
|
||||
$string['newreport'] = 'New report';
|
||||
$string['noconditions'] = 'There are no conditions selected';
|
||||
$string['nofilters'] = 'There are no filters selected';
|
||||
$string['privacy:metadata:column'] = 'Report column definitions';
|
||||
$string['privacy:metadata:column:uniqueidentifier'] = 'Unique identifier of the column';
|
||||
$string['privacy:metadata:column:usercreated'] = 'The ID of the user who created the column';
|
||||
@ -106,6 +115,7 @@ $string['privacy:metadata:report:name'] = 'The name of the report';
|
||||
$string['privacy:metadata:report:usercreated'] = 'The ID of the user who created the report';
|
||||
$string['privacy:metadata:report:usermodified'] = 'The ID of the user who last modified the report';
|
||||
$string['renamecolumn'] = 'Rename column \'{$a}\'';
|
||||
$string['renamefilter'] = 'Rename filter \'{$a}\'';
|
||||
$string['reportbuilder'] = 'Report builder';
|
||||
$string['reportcreated'] = 'Report created';
|
||||
$string['reportdeleted'] = 'Report deleted';
|
||||
@ -115,6 +125,7 @@ $string['reportsource_help'] = 'The report source defines where the data for the
|
||||
$string['reportupdated'] = 'Report updated';
|
||||
$string['resetall'] = 'Reset all';
|
||||
$string['selectacondition'] = 'Select a condition';
|
||||
$string['selectafilter'] = 'Select a filter';
|
||||
$string['selectareportsource'] = 'Select a report source';
|
||||
$string['selectcourses'] = 'Select courses';
|
||||
$string['showhide'] = 'Show/hide \'{$a}\'';
|
||||
|
2
reportbuilder/amd/build/editor.min.js
vendored
2
reportbuilder/amd/build/editor.min.js
vendored
@ -1,2 +1,2 @@
|
||||
function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core_reportbuilder/editor",["exports","core/inplace_editable","core/notification","core/pending","core/templates","core_reportbuilder/local/selectors","core_reportbuilder/local/editor/columns","core_reportbuilder/local/editor/conditions","core_reportbuilder/local/repository/reports"],function(a,b,c,d,e,f,g,h,i){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;c=l(c);d=l(d);e=l(e);f=k(f);function j(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;j=function(){return a};return a}function k(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=j();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function l(a){return a&&a.__esModule?a:{default:a}}var m=!1,n=function(){var a=document.querySelector(f.regions.report);(0,g.init)(a,m);(0,h.init)(a,m);if(m){return}document.addEventListener("click",function(b){var g=b.target.closest(f.actions.toggleEditPreview);if(g){b.preventDefault();var h=new d.default("core_reportbuilder/reports:get"),j="1"!==g.dataset.editMode,k="";(0,i.getReport)(a.dataset.reportId,j).then(function(a){k=a.javascript;return e.default.render("core_reportbuilder/custom_report",a)}).then(function(b,c){return e.default.replaceNodeContents(a,b,c+k)}).then(function(){return h.resolve()}).catch(c.default.exception)}});m=!0};a.init=n});
|
||||
function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core_reportbuilder/editor",["exports","core/inplace_editable","core/notification","core/pending","core/templates","core_reportbuilder/local/selectors","core_reportbuilder/local/editor/columns","core_reportbuilder/local/editor/conditions","core_reportbuilder/local/editor/filters","core_reportbuilder/local/repository/reports"],function(a,b,c,d,e,f,g,h,i,j){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;c=m(c);d=m(d);e=m(e);f=l(f);function k(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;k=function(){return a};return a}function l(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=k();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function m(a){return a&&a.__esModule?a:{default:a}}var n=!1,o=function(){var a=document.querySelector(f.regions.report);(0,g.init)(a,n);(0,h.init)(a,n);(0,i.init)(a,n);if(n){return}document.addEventListener("click",function(b){var g=b.target.closest(f.actions.toggleEditPreview);if(g){b.preventDefault();var h=new d.default("core_reportbuilder/reports:get"),i="1"!==g.dataset.editMode,k="";(0,j.getReport)(a.dataset.reportId,i).then(function(a){k=a.javascript;return e.default.render("core_reportbuilder/custom_report",a)}).then(function(b,c){return e.default.replaceNodeContents(a,b,c+k)}).then(function(){return h.resolve()}).catch(c.default.exception)}});n=!0};a.init=o});
|
||||
//# sourceMappingURL=editor.min.js.map
|
||||
|
@ -1 +1 @@
|
||||
{"version":3,"sources":["../src/editor.js"],"names":["initialized","init","reportElement","document","querySelector","reportSelectors","regions","report","addEventListener","event","toggleEditViewMode","target","closest","actions","toggleEditPreview","preventDefault","pendingPromise","Pending","toggledEditMode","dataset","editMode","customjs","reportId","then","response","javascript","Templates","render","html","js","replaceNodeContents","resolve","catch","Notification","exception"],"mappings":"qmBAwBA,a,+DAGA,OACA,OACA,OACA,O,4lBAKIA,CAAAA,CAAW,G,CAKFC,CAAI,CAAG,UAAM,CACtB,GAAMC,CAAAA,CAAa,CAAGC,QAAQ,CAACC,aAAT,CAAuBC,CAAe,CAACC,OAAhB,CAAwBC,MAA/C,CAAtB,CAEA,WAAkBL,CAAlB,CAAiCF,CAAjC,EACA,WAAqBE,CAArB,CAAoCF,CAApC,EAGA,GAAIA,CAAJ,CAAiB,CACb,MACH,CAGDG,QAAQ,CAACK,gBAAT,CAA0B,OAA1B,CAAmC,SAAAC,CAAK,CAAI,CAGxC,GAAMC,CAAAA,CAAkB,CAAGD,CAAK,CAACE,MAAN,CAAaC,OAAb,CAAqBP,CAAe,CAACQ,OAAhB,CAAwBC,iBAA7C,CAA3B,CACA,GAAIJ,CAAJ,CAAwB,CACpBD,CAAK,CAACM,cAAN,GADoB,GAGdC,CAAAA,CAAc,CAAG,GAAIC,UAAJ,CAAY,gCAAZ,CAHH,CAIdC,CAAe,CAA2C,GAAxC,GAAAR,CAAkB,CAACS,OAAnB,CAA2BC,QAJ/B,CAMhBC,CAAQ,CAAG,EANK,CAQpB,gBAAUnB,CAAa,CAACiB,OAAd,CAAsBG,QAAhC,CAA0CJ,CAA1C,EACKK,IADL,CACU,SAAAC,CAAQ,CAAI,CACdH,CAAQ,CAAGG,CAAQ,CAACC,UAApB,CACA,MAAOC,WAAUC,MAAV,CAAiB,kCAAjB,CAAqDH,CAArD,CACV,CAJL,EAKKD,IALL,CAKU,SAACK,CAAD,CAAOC,CAAP,CAAc,CAChB,MAAOH,WAAUI,mBAAV,CAA8B5B,CAA9B,CAA6C0B,CAA7C,CAAmDC,CAAE,CAAGR,CAAxD,CACV,CAPL,EAQKE,IARL,CAQU,iBAAMP,CAAAA,CAAc,CAACe,OAAf,EAAN,CARV,EASKC,KATL,CASWC,UAAaC,SATxB,CAUH,CACJ,CAvBD,EAyBAlC,CAAW,GACd,C","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 editor\n *\n * @module core_reportbuilder/editor\n * @package core_reportbuilder\n * @copyright 2021 David Matamoros <davidmc@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n\"use strict\";\n\nimport 'core/inplace_editable';\nimport Notification from 'core/notification';\nimport Pending from 'core/pending';\nimport Templates from 'core/templates';\nimport * as reportSelectors from 'core_reportbuilder/local/selectors';\nimport {init as columnsEditorInit} from 'core_reportbuilder/local/editor/columns';\nimport {init as conditionsEditorInit} from 'core_reportbuilder/local/editor/conditions';\nimport {getReport} from 'core_reportbuilder/local/repository/reports';\n\nlet initialized = false;\n\n/**\n * Initialise editor and all it's modules\n */\nexport const init = () => {\n const reportElement = document.querySelector(reportSelectors.regions.report);\n\n columnsEditorInit(reportElement, initialized);\n conditionsEditorInit(reportElement, initialized);\n\n // Ensure we only add our listeners once (can be called multiple times by mustache template).\n if (initialized) {\n return;\n }\n\n // Add event handlers to generic report editor elements.\n document.addEventListener('click', event => {\n\n // Toggle between edit and preview mode.\n const toggleEditViewMode = event.target.closest(reportSelectors.actions.toggleEditPreview);\n if (toggleEditViewMode) {\n event.preventDefault();\n\n const pendingPromise = new Pending('core_reportbuilder/reports:get');\n const toggledEditMode = toggleEditViewMode.dataset.editMode !== \"1\";\n\n let customjs = '';\n\n getReport(reportElement.dataset.reportId, toggledEditMode)\n .then(response => {\n customjs = response.javascript;\n return Templates.render('core_reportbuilder/custom_report', response);\n })\n .then((html, js) => {\n return Templates.replaceNodeContents(reportElement, html, js + customjs);\n })\n .then(() => pendingPromise.resolve())\n .catch(Notification.exception);\n }\n });\n\n initialized = true;\n};\n"],"file":"editor.min.js"}
|
||||
{"version":3,"sources":["../src/editor.js"],"names":["initialized","init","reportElement","document","querySelector","reportSelectors","regions","report","addEventListener","event","toggleEditViewMode","target","closest","actions","toggleEditPreview","preventDefault","pendingPromise","Pending","toggledEditMode","dataset","editMode","customjs","reportId","then","response","javascript","Templates","render","html","js","replaceNodeContents","resolve","catch","Notification","exception"],"mappings":"ipBAwBA,a,+DAGA,OACA,OACA,OACA,O,4lBAMIA,CAAAA,CAAW,G,CAKFC,CAAI,CAAG,UAAM,CACtB,GAAMC,CAAAA,CAAa,CAAGC,QAAQ,CAACC,aAAT,CAAuBC,CAAe,CAACC,OAAhB,CAAwBC,MAA/C,CAAtB,CAEA,WAAkBL,CAAlB,CAAiCF,CAAjC,EACA,WAAqBE,CAArB,CAAoCF,CAApC,EACA,WAAkBE,CAAlB,CAAiCF,CAAjC,EAGA,GAAIA,CAAJ,CAAiB,CACb,MACH,CAGDG,QAAQ,CAACK,gBAAT,CAA0B,OAA1B,CAAmC,SAAAC,CAAK,CAAI,CAGxC,GAAMC,CAAAA,CAAkB,CAAGD,CAAK,CAACE,MAAN,CAAaC,OAAb,CAAqBP,CAAe,CAACQ,OAAhB,CAAwBC,iBAA7C,CAA3B,CACA,GAAIJ,CAAJ,CAAwB,CACpBD,CAAK,CAACM,cAAN,GADoB,GAGdC,CAAAA,CAAc,CAAG,GAAIC,UAAJ,CAAY,gCAAZ,CAHH,CAIdC,CAAe,CAA2C,GAAxC,GAAAR,CAAkB,CAACS,OAAnB,CAA2BC,QAJ/B,CAMhBC,CAAQ,CAAG,EANK,CAQpB,gBAAUnB,CAAa,CAACiB,OAAd,CAAsBG,QAAhC,CAA0CJ,CAA1C,EACKK,IADL,CACU,SAAAC,CAAQ,CAAI,CACdH,CAAQ,CAAGG,CAAQ,CAACC,UAApB,CACA,MAAOC,WAAUC,MAAV,CAAiB,kCAAjB,CAAqDH,CAArD,CACV,CAJL,EAKKD,IALL,CAKU,SAACK,CAAD,CAAOC,CAAP,CAAc,CAChB,MAAOH,WAAUI,mBAAV,CAA8B5B,CAA9B,CAA6C0B,CAA7C,CAAmDC,CAAE,CAAGR,CAAxD,CACV,CAPL,EAQKE,IARL,CAQU,iBAAMP,CAAAA,CAAc,CAACe,OAAf,EAAN,CARV,EASKC,KATL,CASWC,UAAaC,SATxB,CAUH,CACJ,CAvBD,EAyBAlC,CAAW,GACd,C","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 editor\n *\n * @module core_reportbuilder/editor\n * @package core_reportbuilder\n * @copyright 2021 David Matamoros <davidmc@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n\"use strict\";\n\nimport 'core/inplace_editable';\nimport Notification from 'core/notification';\nimport Pending from 'core/pending';\nimport Templates from 'core/templates';\nimport * as reportSelectors from 'core_reportbuilder/local/selectors';\nimport {init as columnsEditorInit} from 'core_reportbuilder/local/editor/columns';\nimport {init as conditionsEditorInit} from 'core_reportbuilder/local/editor/conditions';\nimport {init as filtersEditorInit} from 'core_reportbuilder/local/editor/filters';\nimport {getReport} from 'core_reportbuilder/local/repository/reports';\n\nlet initialized = false;\n\n/**\n * Initialise editor and all it's modules\n */\nexport const init = () => {\n const reportElement = document.querySelector(reportSelectors.regions.report);\n\n columnsEditorInit(reportElement, initialized);\n conditionsEditorInit(reportElement, initialized);\n filtersEditorInit(reportElement, initialized);\n\n // Ensure we only add our listeners once (can be called multiple times by mustache template).\n if (initialized) {\n return;\n }\n\n // Add event handlers to generic report editor elements.\n document.addEventListener('click', event => {\n\n // Toggle between edit and preview mode.\n const toggleEditViewMode = event.target.closest(reportSelectors.actions.toggleEditPreview);\n if (toggleEditViewMode) {\n event.preventDefault();\n\n const pendingPromise = new Pending('core_reportbuilder/reports:get');\n const toggledEditMode = toggleEditViewMode.dataset.editMode !== \"1\";\n\n let customjs = '';\n\n getReport(reportElement.dataset.reportId, toggledEditMode)\n .then(response => {\n customjs = response.javascript;\n return Templates.render('core_reportbuilder/custom_report', response);\n })\n .then((html, js) => {\n return Templates.replaceNodeContents(reportElement, html, js + customjs);\n })\n .then(() => pendingPromise.resolve())\n .catch(Notification.exception);\n }\n });\n\n initialized = true;\n};\n"],"file":"editor.min.js"}
|
2
reportbuilder/amd/build/local/editor/filters.min.js
vendored
Normal file
2
reportbuilder/amd/build/local/editor/filters.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core_reportbuilder/local/editor/filters",["exports","jquery","core/event_dispatcher","core/inplace_editable","core/notification","core/pending","core/sortable_list","core/str","core/templates","core/toast","core_reportbuilder/local/events","core_reportbuilder/local/selectors","core_reportbuilder/local/repository/filters"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=p(b);e=p(e);f=p(f);g=p(g);i=p(i);k=o(k);l=o(l);function n(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;n=function(){return a};return a}function o(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=n();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function p(a){return a&&a.__esModule?a:{default:a}}function q(a,b){return v(a)||u(a,b)||s(a,b)||r()}function r(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function s(a,b){if(!a)return;if("string"==typeof a)return t(a,b);var c=Object.prototype.toString.call(a).slice(8,-1);if("Object"===c&&a.constructor)c=a.constructor.name;if("Map"===c||"Set"===c)return Array.from(c);if("Arguments"===c||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(c))return t(a,b)}function t(a,b){if(null==b||b>a.length)b=a.length;for(var c=0,d=Array(b);c<b;c++){d[c]=a[c]}return d}function u(a,b){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(a)))return;var c=[],d=!0,e=!1,f=void 0;try{for(var g=a[Symbol.iterator](),h;!(d=(h=g.next()).done);d=!0){c.push(h.value);if(b&&c.length===b)break}}catch(a){e=!0;f=a}finally{try{if(!d&&null!=g["return"])g["return"]()}finally{if(e)throw f}}return c}function v(a){if(Array.isArray(a))return a}var w=function(a,b){var c=new f.default("core_reportbuilder/filters:reload"),d=a.querySelector(l.regions.settingsFilters);return i.default.renderForPromise("core_reportbuilder/local/settings/filters",{filters:b}).then(function(a){var b=a.html,e=a.js;i.default.replaceNode(d,b,e);return c.resolve()})},x=function(a,d){if(d){return}a.addEventListener("click",function(b){var d=b.target.closest(l.actions.reportAddFilter);if(d){b.preventDefault();if("0"===d.value){return}var o=new f.default("core_reportbuilder/filters:add");(0,m.addFilter)(a.dataset.reportId,d.value).then(function(b){return w(a,b)}).then(function(){return(0,h.get_string)("filteradded","core_reportbuilder",d.options[d.selectedIndex].text)}).then(j.add).then(function(){return o.resolve()}).catch(e.default.exception)}var g=b.target.closest(l.actions.reportRemoveFilter);if(g){b.preventDefault();var i=g.closest(l.regions.activeFilter),n=i.dataset.filterName;(0,h.get_strings)([{key:"deletefilter",component:"core_reportbuilder",param:n},{key:"deletefilterconfirm",component:"core_reportbuilder",param:n},{key:"delete",component:"moodle"}]).then(function(b){var d=q(b,3),g=d[0],l=d[1],o=d[2];e.default.confirm(g,l,o,null,function(){var b=new f.default("core_reportbuilder/filters:remove");(0,m.deleteFilter)(a.dataset.reportId,i.dataset.filterId).then(function(b){return w(a,b)}).then(function(){return(0,h.get_string)("filterdeleted","core_reportbuilder",n)}).then(j.add).then(function(){(0,c.dispatchEvent)(k.tableReload,{},a);return b.resolve()}).catch(e.default.exception)})}).catch(e.default.exception)}});var i=new g.default("".concat(l.regions.activeFilters," ul"),{isHorizontal:!1});i.getElementName=function(a){return Promise.resolve(a.data("filterName"))};(0,b.default)(a).on(g.default.EVENTS.DROP,"li[data-filter-id]",function(b,c){if(c.positionChanged){var d=new f.default("core_reportbuilder/filters:reorder"),g=c.element.data("filterId"),i=c.element.data("filterPosition"),k=c.targetNextElement.data("filterPosition")||c.element.siblings().length+2;if(k>i){k--}(0,m.reorderFilter)(a.dataset.reportId,g,k).then(function(b){return w(a,b)}).then(function(){return(0,h.get_string)("filtermoved","core_reportbuilder",c.element.data("filterName"))}).then(j.add).then(function(){return d.resolve()}).catch(e.default.exception)}})};a.init=x});
|
||||
//# sourceMappingURL=filters.min.js.map
|
1
reportbuilder/amd/build/local/editor/filters.min.js.map
Normal file
1
reportbuilder/amd/build/local/editor/filters.min.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -1,2 +1,2 @@
|
||||
define ("core_reportbuilder/local/repository/filters",["exports","core/ajax"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.resetFilters=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);var c=function(a){return b.default.call([{methodname:"core_reportbuilder_filters_reset",args:{reportid:a}}])[0]};a.resetFilters=c});
|
||||
define ("core_reportbuilder/local/repository/filters",["exports","core/ajax"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.reorderFilter=a.deleteFilter=a.addFilter=a.resetFilters=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);var c=function(a){return b.default.call([{methodname:"core_reportbuilder_filters_reset",args:{reportid:a}}])[0]};a.resetFilters=c;var d=function(a,c){return b.default.call([{methodname:"core_reportbuilder_filters_add",args:{reportid:a,uniqueidentifier:c}}])[0]};a.addFilter=d;var e=function(a,c){return b.default.call([{methodname:"core_reportbuilder_filters_delete",args:{reportid:a,filterid:c}}])[0]};a.deleteFilter=e;var f=function(a,c,d){return b.default.call([{methodname:"core_reportbuilder_filters_reorder",args:{reportid:a,filterid:c,position:d}}])[0]};a.reorderFilter=f});
|
||||
//# sourceMappingURL=filters.min.js.map
|
||||
|
@ -1 +1 @@
|
||||
{"version":3,"sources":["../../../src/local/repository/filters.js"],"names":["resetFilters","reportId","Ajax","call","methodname","args","reportid"],"mappings":"gLAuBA,uDASO,GAAMA,CAAAA,CAAY,CAAG,SAAAC,CAAQ,CAAI,CAMpC,MAAOC,WAAKC,IAAL,CAAU,CALD,CACZC,UAAU,CAAE,kCADA,CAEZC,IAAI,CAAE,CAACC,QAAQ,CAAEL,CAAX,CAFM,CAKC,CAAV,EAAqB,CAArB,CACV,CAPM,C","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 * @return {Promise}\n */\nexport const resetFilters = reportId => {\n const request = {\n methodname: 'core_reportbuilder_filters_reset',\n args: {reportid: reportId}\n };\n\n return Ajax.call([request])[0];\n};\n"],"file":"filters.min.js"}
|
||||
{"version":3,"sources":["../../../src/local/repository/filters.js"],"names":["resetFilters","reportId","Ajax","call","methodname","args","reportid","addFilter","uniqueIdentifier","uniqueidentifier","deleteFilter","filterId","filterid","reorderFilter","position"],"mappings":"2NAuBA,uDASO,GAAMA,CAAAA,CAAY,CAAG,SAAAC,CAAQ,CAAI,CAMpC,MAAOC,WAAKC,IAAL,CAAU,CALD,CACZC,UAAU,CAAE,kCADA,CAEZC,IAAI,CAAE,CAACC,QAAQ,CAAEL,CAAX,CAFM,CAKC,CAAV,EAAqB,CAArB,CACV,CAPM,C,iBAgBA,GAAMM,CAAAA,CAAS,CAAG,SAACN,CAAD,CAAWO,CAAX,CAAgC,CAMrD,MAAON,WAAKC,IAAL,CAAU,CALD,CACZC,UAAU,CAAE,gCADA,CAEZC,IAAI,CAAE,CAACC,QAAQ,CAAEL,CAAX,CAAqBQ,gBAAgB,CAAED,CAAvC,CAFM,CAKC,CAAV,EAAqB,CAArB,CACV,CAPM,C,cAgBA,GAAME,CAAAA,CAAY,CAAG,SAACT,CAAD,CAAWU,CAAX,CAAwB,CAMhD,MAAOT,WAAKC,IAAL,CAAU,CALD,CACZC,UAAU,CAAE,mCADA,CAEZC,IAAI,CAAE,CAACC,QAAQ,CAAEL,CAAX,CAAqBW,QAAQ,CAAED,CAA/B,CAFM,CAKC,CAAV,EAAqB,CAArB,CACV,CAPM,C,iBAiBA,GAAME,CAAAA,CAAa,CAAG,SAACZ,CAAD,CAAWU,CAAX,CAAqBG,CAArB,CAAkC,CAM3D,MAAOZ,WAAKC,IAAL,CAAU,CALD,CACZC,UAAU,CAAE,oCADA,CAEZC,IAAI,CAAE,CAACC,QAAQ,CAAEL,CAAX,CAAqBW,QAAQ,CAAED,CAA/B,CAAyCG,QAAQ,CAAEA,CAAnD,CAFM,CAKC,CAAV,EAAqB,CAArB,CACV,CAPM,C","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 * @return {Promise}\n */\nexport const resetFilters = reportId => {\n const request = {\n methodname: 'core_reportbuilder_filters_reset',\n args: {reportid: reportId}\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"],"file":"filters.min.js"}
|
@ -1,2 +1,2 @@
|
||||
define ("core_reportbuilder/local/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;var b={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\"]",settingsConditions:"[data-region=\"settings-conditions\"]",activeConditions:"[data-region=\"active-conditions\"]",activeCondition:"[data-region=\"active-condition\"]"},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\"]",sidebarSearch:"[data-action=\"sidebar-search\"]"}};b.forReport=function(a){return"".concat(b.regions.report,"[data-report-id=\"").concat(a,"\"]")};a.default=b;return a.default});
|
||||
define ("core_reportbuilder/local/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;var b={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\"]",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\"]"},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\"]",sidebarSearch:"[data-action=\"sidebar-search\"]"}};b.forReport=function(a){return"".concat(b.regions.report,"[data-report-id=\"").concat(a,"\"]")};a.default=b;return a.default});
|
||||
//# sourceMappingURL=selectors.min.js.map
|
||||
|
@ -1 +1 @@
|
||||
{"version":3,"sources":["../../src/local/selectors.js"],"names":["SELECTORS","regions","report","reportTable","columnHeader","filterButtonLabel","filtersForm","sidebarMenu","sidebarCard","settingsConditions","activeConditions","activeCondition","actions","reportActionPopup","reportCreate","reportEdit","reportDelete","reportAddColumn","reportRemoveColumn","reportAddCondition","reportRemoveCondition","sidebarSearch","forReport","reportId"],"mappings":"oJA+BA,GAAMA,CAAAA,CAAS,CAAG,CACdC,OAAO,CAAE,CACLC,MAAM,CAAE,6CADH,CAELC,WAAW,CAAE,uCAFR,CAGLC,YAAY,CAAE,iCAHT,CAILC,iBAAiB,CAAE,uCAJd,CAKLC,WAAW,CAAE,gCALR,CAMLC,WAAW,CAAE,gCANR,CAOLC,WAAW,CAAE,gCAPR,CAQLC,kBAAkB,CAAE,uCARf,CASLC,gBAAgB,CAAE,qCATb,CAULC,eAAe,CAAE,oCAVZ,CADK,CAadC,OAAO,CAAE,CACLC,iBAAiB,CAAE,uCADd,CAELC,YAAY,CAAE,iCAFT,CAGLC,UAAU,CAAE,+BAHP,CAILC,YAAY,CAAE,iCAJT,CAKLC,eAAe,CAAE,qCALZ,CAMLC,kBAAkB,CAAE,wCANf,CAOLC,kBAAkB,CAAE,wCAPf,CAQLC,qBAAqB,CAAE,2CARlB,CASLC,aAAa,CAAE,kCATV,CAbK,CAAlB,CAiCArB,CAAS,CAACsB,SAAV,CAAsB,SAAAC,CAAQ,kBAAOvB,CAAS,CAACC,OAAV,CAAkBC,MAAzB,8BAAmDqB,CAAnD,QAA9B,C,UAEevB,C","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 selectors\n *\n * @module core_reportbuilder/local/selectors\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 * Selectors for the Report builder subsystem\n *\n * @property {Object} regions\n * @property {String} regions.systemReport System report page region\n * @property {String} regions.filterButtonLabel Filters form toggle region\n * @property {String} regions.filtersForm Filters form page region\n */\nconst SELECTORS = {\n regions: {\n report: '[data-region=\"core_reportbuilder/report\"]',\n reportTable: '[data-region=\"reportbuilder-table\"]',\n columnHeader: '[data-region=\"column-header\"]',\n filterButtonLabel: '[data-region=\"filter-button-label\"]',\n filtersForm: '[data-region=\"filters-form\"]',\n sidebarMenu: '[data-region=\"sidebar-menu\"]',\n sidebarCard: '[data-region=\"sidebar-card\"]',\n settingsConditions: '[data-region=\"settings-conditions\"]',\n activeConditions: '[data-region=\"active-conditions\"]',\n activeCondition: '[data-region=\"active-condition\"]',\n },\n actions: {\n reportActionPopup: '[data-action=\"report-action-popup\"]',\n reportCreate: '[data-action=\"report-create\"]',\n reportEdit: '[data-action=\"report-edit\"]',\n reportDelete: '[data-action=\"report-delete\"]',\n reportAddColumn: '[data-action=\"report-add-column\"]',\n reportRemoveColumn: '[data-action=\"report-remove-column\"]',\n reportAddCondition: '[data-action=\"report-add-condition\"]',\n reportRemoveCondition: '[data-action=\"report-remove-condition\"]',\n sidebarSearch: '[data-action=\"sidebar-search\"]',\n },\n};\n\n/**\n * Selector for given report\n *\n * @method forReport\n * @param {Number} reportId\n * @return {String}\n */\nSELECTORS.forReport = reportId => `${SELECTORS.regions.report}[data-report-id=\"${reportId}\"]`;\n\nexport default SELECTORS;\n"],"file":"selectors.min.js"}
|
||||
{"version":3,"sources":["../../src/local/selectors.js"],"names":["SELECTORS","regions","report","reportTable","columnHeader","filterButtonLabel","filtersForm","sidebarMenu","sidebarCard","settingsConditions","activeConditions","activeCondition","settingsFilters","activeFilters","activeFilter","actions","reportActionPopup","reportCreate","reportEdit","reportDelete","reportAddColumn","reportRemoveColumn","reportAddCondition","reportRemoveCondition","reportAddFilter","reportRemoveFilter","sidebarSearch","forReport","reportId"],"mappings":"oJA+BA,GAAMA,CAAAA,CAAS,CAAG,CACdC,OAAO,CAAE,CACLC,MAAM,CAAE,6CADH,CAELC,WAAW,CAAE,uCAFR,CAGLC,YAAY,CAAE,iCAHT,CAILC,iBAAiB,CAAE,uCAJd,CAKLC,WAAW,CAAE,gCALR,CAMLC,WAAW,CAAE,gCANR,CAOLC,WAAW,CAAE,gCAPR,CAQLC,kBAAkB,CAAE,uCARf,CASLC,gBAAgB,CAAE,qCATb,CAULC,eAAe,CAAE,oCAVZ,CAWLC,eAAe,CAAE,oCAXZ,CAYLC,aAAa,CAAE,kCAZV,CAaLC,YAAY,CAAE,iCAbT,CADK,CAgBdC,OAAO,CAAE,CACLC,iBAAiB,CAAE,uCADd,CAELC,YAAY,CAAE,iCAFT,CAGLC,UAAU,CAAE,+BAHP,CAILC,YAAY,CAAE,iCAJT,CAKLC,eAAe,CAAE,qCALZ,CAMLC,kBAAkB,CAAE,wCANf,CAOLC,kBAAkB,CAAE,wCAPf,CAQLC,qBAAqB,CAAE,2CARlB,CASLC,eAAe,CAAE,qCATZ,CAULC,kBAAkB,CAAE,wCAVf,CAWLC,aAAa,CAAE,kCAXV,CAhBK,CAAlB,CAsCA1B,CAAS,CAAC2B,SAAV,CAAsB,SAAAC,CAAQ,kBAAO5B,CAAS,CAACC,OAAV,CAAkBC,MAAzB,8BAAmD0B,CAAnD,QAA9B,C,UAEe5B,C","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 selectors\n *\n * @module core_reportbuilder/local/selectors\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 * Selectors for the Report builder subsystem\n *\n * @property {Object} regions\n * @property {String} regions.systemReport System report page region\n * @property {String} regions.filterButtonLabel Filters form toggle region\n * @property {String} regions.filtersForm Filters form page region\n */\nconst SELECTORS = {\n regions: {\n report: '[data-region=\"core_reportbuilder/report\"]',\n reportTable: '[data-region=\"reportbuilder-table\"]',\n columnHeader: '[data-region=\"column-header\"]',\n filterButtonLabel: '[data-region=\"filter-button-label\"]',\n filtersForm: '[data-region=\"filters-form\"]',\n sidebarMenu: '[data-region=\"sidebar-menu\"]',\n sidebarCard: '[data-region=\"sidebar-card\"]',\n settingsConditions: '[data-region=\"settings-conditions\"]',\n activeConditions: '[data-region=\"active-conditions\"]',\n activeCondition: '[data-region=\"active-condition\"]',\n settingsFilters: '[data-region=\"settings-filters\"]',\n activeFilters: '[data-region=\"active-filters\"]',\n activeFilter: '[data-region=\"active-filter\"]',\n },\n actions: {\n reportActionPopup: '[data-action=\"report-action-popup\"]',\n reportCreate: '[data-action=\"report-create\"]',\n reportEdit: '[data-action=\"report-edit\"]',\n reportDelete: '[data-action=\"report-delete\"]',\n reportAddColumn: '[data-action=\"report-add-column\"]',\n reportRemoveColumn: '[data-action=\"report-remove-column\"]',\n reportAddCondition: '[data-action=\"report-add-condition\"]',\n reportRemoveCondition: '[data-action=\"report-remove-condition\"]',\n reportAddFilter: '[data-action=\"report-add-filter\"]',\n reportRemoveFilter: '[data-action=\"report-remove-filter\"]',\n sidebarSearch: '[data-action=\"sidebar-search\"]',\n },\n};\n\n/**\n * Selector for given report\n *\n * @method forReport\n * @param {Number} reportId\n * @return {String}\n */\nSELECTORS.forReport = reportId => `${SELECTORS.regions.report}[data-report-id=\"${reportId}\"]`;\n\nexport default SELECTORS;\n"],"file":"selectors.min.js"}
|
@ -31,6 +31,7 @@ import Templates from 'core/templates';
|
||||
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 {getReport} from 'core_reportbuilder/local/repository/reports';
|
||||
|
||||
let initialized = false;
|
||||
@ -43,6 +44,7 @@ export const init = () => {
|
||||
|
||||
columnsEditorInit(reportElement, initialized);
|
||||
conditionsEditorInit(reportElement, initialized);
|
||||
filtersEditorInit(reportElement, initialized);
|
||||
|
||||
// Ensure we only add our listeners once (can be called multiple times by mustache template).
|
||||
if (initialized) {
|
||||
|
147
reportbuilder/amd/src/local/editor/filters.js
Normal file
147
reportbuilder/amd/src/local/editor/filters.js
Normal file
@ -0,0 +1,147 @@
|
||||
// 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
|
||||
* @package core_reportbuilder
|
||||
* @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 {dispatchEvent} from 'core/event_dispatcher';
|
||||
import 'core/inplace_editable';
|
||||
import Notification from 'core/notification';
|
||||
import Pending from 'core/pending';
|
||||
import SortableList from 'core/sortable_list';
|
||||
import {get_string as getString, get_strings as getStrings} from 'core/str';
|
||||
import Templates from 'core/templates';
|
||||
import {add as addToast} from 'core/toast';
|
||||
import * as reportEvents from 'core_reportbuilder/local/events';
|
||||
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);
|
||||
return pendingPromise.resolve();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise module
|
||||
*
|
||||
* @param {Element} reportElement
|
||||
* @param {Boolean} initialized Ensure we only add our listeners once
|
||||
*/
|
||||
export const init = (reportElement, initialized) => {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
reportElement.addEventListener('click', event => {
|
||||
|
||||
// Add filter to report.
|
||||
const reportAddFilter = event.target.closest(reportSelectors.actions.reportAddFilter);
|
||||
if (reportAddFilter) {
|
||||
event.preventDefault();
|
||||
|
||||
// Check if dropdown is closed with no filter selected.
|
||||
if (reportAddFilter.value === '0') {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// Remove filter from report.
|
||||
const reportRemoveFilter = event.target.closest(reportSelectors.actions.reportRemoveFilter);
|
||||
if (reportRemoveFilter) {
|
||||
event.preventDefault();
|
||||
|
||||
const filterContainer = reportRemoveFilter.closest(reportSelectors.regions.activeFilter);
|
||||
const filterName = filterContainer.dataset.filterName;
|
||||
|
||||
getStrings([
|
||||
{key: 'deletefilter', component: 'core_reportbuilder', param: filterName},
|
||||
{key: 'deletefilterconfirm', component: 'core_reportbuilder', param: filterName},
|
||||
{key: 'delete', component: 'moodle'},
|
||||
]).then(([confirmTitle, confirmText, confirmButton]) => {
|
||||
Notification.confirm(confirmTitle, confirmText, confirmButton, null, () => {
|
||||
const pendingPromise = new Pending('core_reportbuilder/filters:remove');
|
||||
|
||||
deleteFilter(reportElement.dataset.reportId, filterContainer.dataset.filterId)
|
||||
.then(data => reloadSettingsFiltersRegion(reportElement, data))
|
||||
.then(() => getString('filterdeleted', 'core_reportbuilder', filterName))
|
||||
.then(addToast)
|
||||
.then(() => {
|
||||
dispatchEvent(reportEvents.tableReload, {}, reportElement);
|
||||
return pendingPromise.resolve();
|
||||
})
|
||||
.catch(Notification.exception);
|
||||
});
|
||||
return;
|
||||
}).catch(Notification.exception);
|
||||
}
|
||||
});
|
||||
|
||||
// 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'));
|
||||
|
||||
$(reportElement).on(SortableList.EVENTS.DROP, 'li[data-filter-id]', (event, info) => {
|
||||
if (info.positionChanged) {
|
||||
const pendingPromise = new Pending('core_reportbuilder/filters:reorder');
|
||||
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--;
|
||||
}
|
||||
|
||||
reorderFilter(reportElement.dataset.reportId, filterId, targetFilterPosition)
|
||||
.then(data => reloadSettingsFiltersRegion(reportElement, data))
|
||||
.then(() => getString('filtermoved', 'core_reportbuilder', info.element.data('filterName')))
|
||||
.then(addToast)
|
||||
.then(() => pendingPromise.resolve())
|
||||
.catch(Notification.exception);
|
||||
}
|
||||
});
|
||||
};
|
@ -38,3 +38,52 @@ export const resetFilters = reportId => {
|
||||
|
||||
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];
|
||||
};
|
||||
|
@ -41,6 +41,9 @@ const SELECTORS = {
|
||||
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"]',
|
||||
},
|
||||
actions: {
|
||||
reportActionPopup: '[data-action="report-action-popup"]',
|
||||
@ -51,6 +54,8 @@ const SELECTORS = {
|
||||
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"]',
|
||||
sidebarSearch: '[data-action="sidebar-search"]',
|
||||
},
|
||||
};
|
||||
|
@ -95,6 +95,80 @@ abstract class datasource extends base {
|
||||
*/
|
||||
abstract public function get_default_columns(): array;
|
||||
|
||||
/**
|
||||
* Add filters from the given entity name to be available to use in a custom report
|
||||
*
|
||||
* @param string $entityname
|
||||
* @param array $include Include only these filters, if omitted then include all
|
||||
* @param array $exclude Exclude these filters, if omitted then exclude none
|
||||
* @throws coding_exception If both $include and $exclude are non-empty
|
||||
*/
|
||||
final protected function add_filters_from_entity(string $entityname, array $include = [], array $exclude = []): void {
|
||||
if (!empty($include) && !empty($exclude)) {
|
||||
throw new coding_exception('Cannot specify filters to include and exclude simultaneously');
|
||||
}
|
||||
|
||||
$entity = $this->get_entity($entityname);
|
||||
|
||||
// Retrieve filtered filters from entity, respecting given $include/$exclude parameters.
|
||||
$filters = array_filter($entity->get_filters(), static function(filter $filter) use ($include, $exclude): bool {
|
||||
if (!empty($include)) {
|
||||
return in_array($filter->get_name(), $include);
|
||||
}
|
||||
|
||||
if (!empty($exclude)) {
|
||||
return !in_array($filter->get_name(), $exclude);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
foreach ($filters as $filter) {
|
||||
$this->add_filter($filter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add default datasource filters to the report
|
||||
*
|
||||
* This method is optional and can be called when the report is created to add the default filters defined in the
|
||||
* selected datasource.
|
||||
*/
|
||||
public function add_default_filters(): void {
|
||||
$reportid = $this->get_report_persistent()->get('id');
|
||||
$filteridentifiers = $this->get_default_filters();
|
||||
foreach ($filteridentifiers as $uniqueidentifier) {
|
||||
report::add_report_filter($reportid, $uniqueidentifier);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filters that will be added to the report once is created
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
abstract public function get_default_filters(): array;
|
||||
|
||||
/**
|
||||
* Return all configured report filters
|
||||
*
|
||||
* @return filter[]
|
||||
*/
|
||||
public function get_active_filters(): array {
|
||||
$filters = [];
|
||||
|
||||
$activefilters = filter_model::get_filter_records($this->get_report_persistent()->get('id'), 'filterorder');
|
||||
foreach ($activefilters as $filter) {
|
||||
$instance = $this->get_filter($filter->get('uniqueidentifier'));
|
||||
if ($instance !== null && $instance->get_is_available()) {
|
||||
$filters[$instance->get_unique_identifier()] = $instance
|
||||
->set_persistent($filter);
|
||||
}
|
||||
}
|
||||
|
||||
return $filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add conditions from the given entity name to be available to use in a custom report
|
||||
*
|
||||
|
@ -89,6 +89,8 @@ class custom_report_exporter extends persistent_exporter {
|
||||
'table' => ['type' => PARAM_RAW],
|
||||
'sidebarmenucards' => ['type' => custom_report_menu_cards_exporter::read_properties_definition()],
|
||||
'conditions' => ['type' => custom_report_conditions_exporter::read_properties_definition()],
|
||||
'filters' => ['type' => custom_report_filters_exporter::read_properties_definition()],
|
||||
'filtersapplied' => ['type' => PARAM_INT],
|
||||
'filtersform' => [
|
||||
'type' => PARAM_RAW,
|
||||
'optional' => true,
|
||||
@ -119,6 +121,7 @@ class custom_report_exporter extends persistent_exporter {
|
||||
$report = manager::get_report_from_persistent($this->persistent);
|
||||
|
||||
$conditionsexporter = new custom_report_conditions_exporter(null, ['report' => $report]);
|
||||
$filtersexporter = new custom_report_filters_exporter(null, ['report' => $report]);
|
||||
if ($this->editmode) {
|
||||
$menucardexporter = new custom_report_menu_cards_exporter(null, [
|
||||
'menucards' => report_helper::get_available_columns($report->get_report_persistent())
|
||||
@ -130,6 +133,8 @@ class custom_report_exporter extends persistent_exporter {
|
||||
'table' => $output->render($table),
|
||||
'sidebarmenucards' => $menucards,
|
||||
'conditions' => (array) $conditionsexporter->export($output),
|
||||
'filters' => (array) $filtersexporter->export($output),
|
||||
'filtersapplied' => $report->get_applied_filter_count(),
|
||||
'filtersform' => $filtersform,
|
||||
'editmode' => (int)$this->editmode,
|
||||
'showeditbutton' => $this->showeditbutton,
|
||||
|
162
reportbuilder/classes/external/custom_report_filters_exporter.php
vendored
Normal file
162
reportbuilder/classes/external/custom_report_filters_exporter.php
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
// 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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\external;
|
||||
|
||||
use renderer_base;
|
||||
use core\external\exporter;
|
||||
use core_reportbuilder\local\report\base;
|
||||
use core_reportbuilder\local\models\filter;
|
||||
use core_reportbuilder\output\filter_heading_editable;
|
||||
|
||||
/**
|
||||
* Custom report filters exporter class
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class custom_report_filters_exporter extends exporter {
|
||||
|
||||
/**
|
||||
* Return a list of objects that are related to the exporter
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_related(): array {
|
||||
return [
|
||||
'report' => base::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of additional properties for read structure and export
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
protected static function define_other_properties(): array {
|
||||
return [
|
||||
'hasavailablefilters' => [
|
||||
'type' => PARAM_BOOL,
|
||||
],
|
||||
'availablefilters' => [
|
||||
'type' => [
|
||||
'optiongroup' => [
|
||||
'type' => [
|
||||
'text' => ['type' => PARAM_TEXT],
|
||||
'values' => [
|
||||
'type' => [
|
||||
'value' => ['type' => PARAM_TEXT],
|
||||
'visiblename' => ['type' => PARAM_TEXT],
|
||||
],
|
||||
'multiple' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'multiple' => true,
|
||||
'optional' => true
|
||||
],
|
||||
'hasactivefilters' => [
|
||||
'type' => PARAM_BOOL,
|
||||
],
|
||||
'activefilters' => [
|
||||
'type' => [
|
||||
'id' => ['type' => PARAM_INT],
|
||||
'heading' => ['type' => PARAM_TEXT],
|
||||
'headingeditable' => ['type' => PARAM_RAW],
|
||||
'sortorder' => ['type' => PARAM_INT],
|
||||
'movetitle' => ['type' => PARAM_TEXT],
|
||||
'entityname' => ['type' => PARAM_TEXT],
|
||||
],
|
||||
'multiple' => true,
|
||||
'optional' => true
|
||||
],
|
||||
'helpicon' => [
|
||||
'type' => PARAM_RAW,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the additional values to inject while exporting
|
||||
*
|
||||
* @param renderer_base $output
|
||||
* @return array
|
||||
*/
|
||||
protected function get_other_values(renderer_base $output): array {
|
||||
/** @var base $report */
|
||||
$report = $this->related['report'];
|
||||
|
||||
// Current filter instances contained in the report.
|
||||
$filterinstances = filter::get_filter_records($report->get_report_persistent()->get('id'), 'filterorder');
|
||||
$filteridentifiers = array_map(static function(filter $filter): string {
|
||||
return $filter->get('uniqueidentifier');
|
||||
}, $filterinstances);
|
||||
|
||||
$availablefilters = $activefilters = [];
|
||||
|
||||
// Populate available filters.
|
||||
foreach ($report->get_filters() as $filter) {
|
||||
if (in_array($filter->get_unique_identifier(), $filteridentifiers)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$entityname = $filter->get_entity_name();
|
||||
if (!array_key_exists($entityname, $availablefilters)) {
|
||||
$availablefilters[$entityname] = [
|
||||
'optiongroup' => [
|
||||
'text' => $report->get_entity_title($entityname)->out(),
|
||||
'values' => [],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$availablefilters[$entityname]['optiongroup']['values'][] = [
|
||||
'value' => $filter->get_unique_identifier(),
|
||||
'visiblename' => $filter->get_header(),
|
||||
];
|
||||
}
|
||||
|
||||
// Populate active filters.
|
||||
foreach ($filterinstances as $filter) {
|
||||
$editable = new filter_heading_editable($filter->get('id'));
|
||||
|
||||
$filterinstance = $report->get_filter($filter->get('uniqueidentifier'));
|
||||
$entityname = $filterinstance->get_entity_name();
|
||||
$displayvalue = $filterinstance->get_header();
|
||||
|
||||
$activefilters[] = [
|
||||
'id' => $filter->get('id'),
|
||||
'entityname' => $report->get_entity_title($entityname)->out(),
|
||||
'heading' => $displayvalue,
|
||||
'headingeditable' => $editable->render($output),
|
||||
'sortorder' => $filter->get('filterorder'),
|
||||
'movetitle' => get_string('movefilter', 'core_reportbuilder', $displayvalue),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'hasavailablefilters' => !empty($availablefilters),
|
||||
'availablefilters' => array_values($availablefilters),
|
||||
'hasactivefilters' => !empty($activefilters),
|
||||
'activefilters' => $activefilters,
|
||||
'helpicon' => $output->help_icon('filters', 'core_reportbuilder'),
|
||||
];
|
||||
}
|
||||
}
|
96
reportbuilder/classes/external/filters/add.php
vendored
Normal file
96
reportbuilder/classes/external/filters/add.php
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
// 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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\external\filters;
|
||||
|
||||
use external_api;
|
||||
use external_function_parameters;
|
||||
use external_single_structure;
|
||||
use external_value;
|
||||
use core_reportbuilder\manager;
|
||||
use core_reportbuilder\permission;
|
||||
use core_reportbuilder\external\custom_report_filters_exporter;
|
||||
use core_reportbuilder\local\helpers\report;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once("{$CFG->libdir}/externallib.php");
|
||||
|
||||
/**
|
||||
* External method for adding report filters
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class add extends external_api {
|
||||
|
||||
/**
|
||||
* External method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function execute_parameters(): external_function_parameters {
|
||||
return new external_function_parameters([
|
||||
'reportid' => new external_value(PARAM_INT, 'Report ID'),
|
||||
'uniqueidentifier' => new external_value(PARAM_RAW, 'Unique identifier of the filter'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* External method execution
|
||||
*
|
||||
* @param int $reportid
|
||||
* @param string $uniqueidentifier
|
||||
* @return array
|
||||
*/
|
||||
public static function execute(int $reportid, string $uniqueidentifier): array {
|
||||
global $PAGE;
|
||||
|
||||
[
|
||||
'reportid' => $reportid,
|
||||
'uniqueidentifier' => $uniqueidentifier,
|
||||
] = self::validate_parameters(self::execute_parameters(), [
|
||||
'reportid' => $reportid,
|
||||
'uniqueidentifier' => $uniqueidentifier,
|
||||
]);
|
||||
|
||||
$report = manager::get_report_from_id($reportid);
|
||||
|
||||
self::validate_context($report->get_context());
|
||||
permission::require_can_edit_report($report->get_report_persistent());
|
||||
|
||||
report::add_report_filter($reportid, $uniqueidentifier);
|
||||
|
||||
$exporter = new custom_report_filters_exporter(null, [
|
||||
'report' => $report,
|
||||
]);
|
||||
|
||||
return (array) $exporter->export($PAGE->get_renderer('core'));
|
||||
}
|
||||
|
||||
/**
|
||||
* External method return value
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function execute_returns(): external_single_structure {
|
||||
return custom_report_filters_exporter::get_read_structure();
|
||||
}
|
||||
}
|
96
reportbuilder/classes/external/filters/delete.php
vendored
Normal file
96
reportbuilder/classes/external/filters/delete.php
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
// 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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\external\filters;
|
||||
|
||||
use external_api;
|
||||
use external_function_parameters;
|
||||
use external_single_structure;
|
||||
use external_value;
|
||||
use core_reportbuilder\manager;
|
||||
use core_reportbuilder\permission;
|
||||
use core_reportbuilder\external\custom_report_filters_exporter;
|
||||
use core_reportbuilder\local\helpers\report;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once("{$CFG->libdir}/externallib.php");
|
||||
|
||||
/**
|
||||
* External method for deleting report filters
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class delete extends external_api {
|
||||
|
||||
/**
|
||||
* External method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function execute_parameters(): external_function_parameters {
|
||||
return new external_function_parameters([
|
||||
'reportid' => new external_value(PARAM_INT, 'Report ID'),
|
||||
'filterid' => new external_value(PARAM_INT, 'Filter ID'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* External method execution
|
||||
*
|
||||
* @param int $reportid
|
||||
* @param int $filterid
|
||||
* @return array
|
||||
*/
|
||||
public static function execute(int $reportid, int $filterid): array {
|
||||
global $PAGE;
|
||||
|
||||
[
|
||||
'reportid' => $reportid,
|
||||
'filterid' => $filterid,
|
||||
] = self::validate_parameters(self::execute_parameters(), [
|
||||
'reportid' => $reportid,
|
||||
'filterid' => $filterid,
|
||||
]);
|
||||
|
||||
$report = manager::get_report_from_id($reportid);
|
||||
|
||||
self::validate_context($report->get_context());
|
||||
permission::require_can_edit_report($report->get_report_persistent());
|
||||
|
||||
report::delete_report_filter($reportid, $filterid);
|
||||
|
||||
$exporter = new custom_report_filters_exporter(null, [
|
||||
'report' => $report,
|
||||
]);
|
||||
|
||||
return (array) $exporter->export($PAGE->get_renderer('core'));
|
||||
}
|
||||
|
||||
/**
|
||||
* External method return value
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function execute_returns(): external_single_structure {
|
||||
return custom_report_filters_exporter::get_read_structure();
|
||||
}
|
||||
}
|
100
reportbuilder/classes/external/filters/reorder.php
vendored
Normal file
100
reportbuilder/classes/external/filters/reorder.php
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
// 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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\external\filters;
|
||||
|
||||
use external_api;
|
||||
use external_function_parameters;
|
||||
use external_single_structure;
|
||||
use external_value;
|
||||
use core_reportbuilder\manager;
|
||||
use core_reportbuilder\permission;
|
||||
use core_reportbuilder\external\custom_report_filters_exporter;
|
||||
use core_reportbuilder\local\helpers\report;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once("{$CFG->libdir}/externallib.php");
|
||||
|
||||
/**
|
||||
* External method for re-ordering report filters
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class reorder extends external_api {
|
||||
|
||||
/**
|
||||
* External method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function execute_parameters(): external_function_parameters {
|
||||
return new external_function_parameters([
|
||||
'reportid' => new external_value(PARAM_INT, 'Report ID'),
|
||||
'filterid' => new external_value(PARAM_INT, 'Filter ID'),
|
||||
'position' => new external_value(PARAM_INT, 'New filter position')
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* External method execution
|
||||
*
|
||||
* @param int $reportid
|
||||
* @param int $filterid
|
||||
* @param int $position
|
||||
* @return array
|
||||
*/
|
||||
public static function execute(int $reportid, int $filterid, int $position): array {
|
||||
global $PAGE;
|
||||
|
||||
[
|
||||
'reportid' => $reportid,
|
||||
'filterid' => $filterid,
|
||||
'position' => $position,
|
||||
] = self::validate_parameters(self::execute_parameters(), [
|
||||
'reportid' => $reportid,
|
||||
'filterid' => $filterid,
|
||||
'position' => $position,
|
||||
]);
|
||||
|
||||
$report = manager::get_report_from_id($reportid);
|
||||
|
||||
self::validate_context($report->get_context());
|
||||
permission::require_can_edit_report($report->get_report_persistent());
|
||||
|
||||
report::reorder_report_filter($reportid, $filterid, $position);
|
||||
|
||||
$exporter = new custom_report_filters_exporter(null, [
|
||||
'report' => $report,
|
||||
]);
|
||||
|
||||
return (array) $exporter->export($PAGE->get_renderer('core'));
|
||||
}
|
||||
|
||||
/**
|
||||
* External method return value
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function execute_returns(): external_single_structure {
|
||||
return custom_report_filters_exporter::get_read_structure();
|
||||
}
|
||||
}
|
@ -256,6 +256,86 @@ class report {
|
||||
return static::reorder_persistents_by_field($condition, $conditions, $position, 'filterorder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given filter to report
|
||||
*
|
||||
* @param int $reportid
|
||||
* @param string $uniqueidentifier
|
||||
* @return filter
|
||||
* @throws invalid_parameter_exception
|
||||
*/
|
||||
public static function add_report_filter(int $reportid, string $uniqueidentifier): filter {
|
||||
$report = manager::get_report_from_id($reportid);
|
||||
|
||||
$reportfilters = $report->get_filters();
|
||||
if (!array_key_exists($uniqueidentifier, $reportfilters)) {
|
||||
throw new invalid_parameter_exception('Invalid filter');
|
||||
}
|
||||
|
||||
$filter = new filter(0, (object) [
|
||||
'reportid' => $reportid,
|
||||
'uniqueidentifier' => $uniqueidentifier,
|
||||
'filterorder' => filter::get_max_filterorder($reportid) + 1,
|
||||
]);
|
||||
|
||||
return $filter->create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete given filter from report
|
||||
*
|
||||
* @param int $reportid
|
||||
* @param int $filterid
|
||||
* @return bool
|
||||
* @throws invalid_parameter_exception
|
||||
*/
|
||||
public static function delete_report_filter(int $reportid, int $filterid): bool {
|
||||
global $DB;
|
||||
|
||||
$filter = filter::get_filter_record($reportid, $filterid);
|
||||
if ($filter === false) {
|
||||
throw new invalid_parameter_exception('Invalid filter');
|
||||
}
|
||||
|
||||
// After deletion, re-index remaining report filters.
|
||||
if ($result = $filter->delete()) {
|
||||
$sqlupdateorder = '
|
||||
UPDATE {' . filter::TABLE . '}
|
||||
SET filterorder = filterorder - 1
|
||||
WHERE reportid = :reportid
|
||||
AND filterorder > :filterorder
|
||||
AND iscondition = 0';
|
||||
|
||||
$DB->execute($sqlupdateorder, ['reportid' => $reportid, 'filterorder' => $filter->get('filterorder')]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-order given filter within a report
|
||||
*
|
||||
* @param int $reportid
|
||||
* @param int $filterid
|
||||
* @param int $position
|
||||
* @return bool
|
||||
* @throws invalid_parameter_exception
|
||||
*/
|
||||
public static function reorder_report_filter(int $reportid, int $filterid, int $position): bool {
|
||||
$filter = filter::get_filter_record($reportid, $filterid);
|
||||
if ($filter === false) {
|
||||
throw new invalid_parameter_exception('Invalid filter');
|
||||
}
|
||||
|
||||
// Get the rest of the report filters, excluding the one we are moving.
|
||||
$filters = filter::get_records_select('reportid = :reportid AND iscondition = 0 AND id <> :id', [
|
||||
'reportid' => $reportid,
|
||||
'id' => $filterid,
|
||||
], 'filterorder');
|
||||
|
||||
return static::reorder_persistents_by_field($filter, $filters, $position, 'filterorder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available columns for a given report
|
||||
*
|
||||
|
@ -287,6 +287,7 @@ abstract class base {
|
||||
/**
|
||||
* Returns title of given report entity
|
||||
*
|
||||
* @param string $name
|
||||
* @return lang_string
|
||||
* @throws coding_exception
|
||||
*/
|
||||
@ -345,17 +346,10 @@ abstract class base {
|
||||
* Each entity must have already been added to the report before calling this method
|
||||
*
|
||||
* @param string[] $columns Unique identifier of each entity column
|
||||
* @throws coding_exception For unknown entities
|
||||
*/
|
||||
final protected function add_columns_from_entities(array $columns): void {
|
||||
foreach ($columns as $column) {
|
||||
[$entityname, $columnname] = explode(':', $column, 2);
|
||||
|
||||
if (!array_key_exists($entityname, $this->entities)) {
|
||||
throw new coding_exception('Invalid entity name', $entityname);
|
||||
}
|
||||
|
||||
$this->add_column($this->entities[$entityname]->get_column($columnname));
|
||||
$this->add_column_from_entity($column);
|
||||
}
|
||||
}
|
||||
|
||||
@ -502,7 +496,6 @@ abstract class base {
|
||||
return (array) json_decode($conditions);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a filter to the report
|
||||
*
|
||||
@ -530,23 +523,30 @@ abstract class base {
|
||||
return $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given filter to the report from an entity
|
||||
*
|
||||
* The entity must have already been added to the report before calling this method
|
||||
*
|
||||
* @param string $uniqueidentifier
|
||||
* @return filter
|
||||
*/
|
||||
final protected function add_filter_from_entity(string $uniqueidentifier): filter {
|
||||
[$entityname, $filtername] = explode(':', $uniqueidentifier, 2);
|
||||
|
||||
return $this->add_filter($this->get_entity($entityname)->get_filter($filtername));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given filters to the report from one or more entities
|
||||
*
|
||||
* Each entity must have already been added to the report before calling this method
|
||||
*
|
||||
* @param string[] $filters Unique identifier of each entity filter
|
||||
* @throws coding_exception For unknown entities
|
||||
*/
|
||||
final protected function add_filters_from_entities(array $filters): void {
|
||||
foreach ($filters as $filter) {
|
||||
[$entityname, $filtername] = explode(':', $filter, 2);
|
||||
|
||||
if (!array_key_exists($entityname, $this->entities)) {
|
||||
throw new coding_exception('Invalid entity name', $entityname);
|
||||
}
|
||||
|
||||
$this->add_filter($this->entities[$entityname]->get_filter($filtername));
|
||||
$this->add_filter_from_entity($filter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -581,7 +581,7 @@ abstract class base {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all report filter instances
|
||||
* Return all active report filter instances
|
||||
*
|
||||
* @return filter_base[]
|
||||
*/
|
||||
|
@ -21,6 +21,7 @@ namespace core_reportbuilder\local\report;
|
||||
use lang_string;
|
||||
use moodle_exception;
|
||||
use core_reportbuilder\local\filters\base;
|
||||
use core_reportbuilder\local\models\filter as filter_model;
|
||||
|
||||
/**
|
||||
* Class to represent a report filter
|
||||
@ -61,6 +62,9 @@ final class filter {
|
||||
/** @var array $limitoperators */
|
||||
protected $limitoperators = [];
|
||||
|
||||
/** @var filter_model $persistent */
|
||||
protected $persistent;
|
||||
|
||||
/**
|
||||
* Filter constructor
|
||||
*
|
||||
@ -307,4 +311,24 @@ final class filter {
|
||||
|
||||
return array_intersect_key($operators, array_flip($this->limitoperators));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set filter persistent
|
||||
*
|
||||
* @param filter_model $persistent
|
||||
* @return self
|
||||
*/
|
||||
public function set_persistent(filter_model $persistent): self {
|
||||
$this->persistent = $persistent;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return filter persistent
|
||||
*
|
||||
* @return filter_model|null
|
||||
*/
|
||||
public function get_persistent(): ?filter_model {
|
||||
return $this->persistent ?? null;
|
||||
}
|
||||
}
|
||||
|
81
reportbuilder/classes/output/filter_heading_editable.php
Normal file
81
reportbuilder/classes/output/filter_heading_editable.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
// 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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\output;
|
||||
|
||||
use core_external;
|
||||
use core_reportbuilder\local\models\filter;
|
||||
use core\output\inplace_editable;
|
||||
use core_reportbuilder\manager;
|
||||
use core_reportbuilder\permission;
|
||||
use core_reportbuilder\local\models\report;
|
||||
|
||||
/**
|
||||
* Filter heading editable component
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class filter_heading_editable extends inplace_editable {
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param int $filterid
|
||||
* @param filter|null $filter
|
||||
*/
|
||||
public function __construct(int $filterid, ?filter $filter = null) {
|
||||
if ($filter === null) {
|
||||
$filter = new filter($filterid);
|
||||
}
|
||||
|
||||
$report = $filter->get_report();
|
||||
$editable = permission::can_edit_report($report);
|
||||
|
||||
$filterinstance = manager::get_report_from_persistent($report)
|
||||
->get_filter($filter->get('uniqueidentifier'));
|
||||
|
||||
$displayvalue = $filter->get('heading') ?: $filterinstance->get_header();
|
||||
|
||||
parent::__construct('core_reportbuilder', 'filterheading', $filter->get('id'), $editable, $displayvalue,
|
||||
$displayvalue, get_string('renamefilter', 'core_reportbuilder', $filterinstance->get_header()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update filter persistent and return self, called from inplace_editable callback
|
||||
*
|
||||
* @param int $filterid
|
||||
* @param string $value
|
||||
* @return self
|
||||
*/
|
||||
public static function update(int $filterid, string $value): self {
|
||||
$filter = new filter($filterid);
|
||||
|
||||
$report = $filter->get_report();
|
||||
core_external::validate_context($report->get_context());
|
||||
permission::require_can_edit_report($report);
|
||||
|
||||
$value = clean_param($value, PARAM_TEXT);
|
||||
$filter
|
||||
->set('heading', $value)
|
||||
->update();
|
||||
|
||||
return new self(0, $filter);
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ use core_reportbuilder\local\filters\base;
|
||||
use core_reportbuilder\local\models\report;
|
||||
use core_reportbuilder\local\report\base as base_report;
|
||||
use core_reportbuilder\local\report\filter;
|
||||
use core\output\notification;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
@ -51,6 +52,9 @@ abstract class base_report_table extends table_sql implements dynamic, renderabl
|
||||
/** @var string $groupbysql */
|
||||
protected $groupbysql = '';
|
||||
|
||||
/** @var bool $applyfilters */
|
||||
protected $applyfilters = true;
|
||||
|
||||
/**
|
||||
* Initialises table SQL properties
|
||||
*
|
||||
@ -81,19 +85,23 @@ abstract class base_report_table extends table_sql implements dynamic, renderabl
|
||||
}
|
||||
|
||||
// For each filter, we also need to apply their values (will differ according to user viewing the report).
|
||||
$filtervalues = $this->report->get_filter_values();
|
||||
foreach ($this->report->get_active_filters() as $filter) {
|
||||
[$filtersql, $filterparams] = $this->get_filter_sql($filter, $filtervalues);
|
||||
if ($filtersql !== '') {
|
||||
$joins = array_merge($joins, $filter->get_joins());
|
||||
$wheres[] = "({$filtersql})";
|
||||
$params = array_merge($params, $filterparams);
|
||||
if ($this->applyfilters) {
|
||||
$filtervalues = $this->report->get_filter_values();
|
||||
foreach ($this->report->get_active_filters() as $filter) {
|
||||
[$filtersql, $filterparams] = $this->get_filter_sql($filter, $filtervalues);
|
||||
if ($filtersql !== '') {
|
||||
$joins = array_merge($joins, $filter->get_joins());
|
||||
$wheres[] = "({$filtersql})";
|
||||
$params = array_merge($params, $filterparams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$wheresql = '1=1';
|
||||
// Join all the filters into a SQL WHERE clause, falling back to all records.
|
||||
if (!empty($wheres)) {
|
||||
$wheresql = implode(' AND ', $wheres);
|
||||
} else {
|
||||
$wheresql = '1=1';
|
||||
}
|
||||
|
||||
if (!empty($groupby)) {
|
||||
@ -115,6 +123,16 @@ abstract class base_report_table extends table_sql implements dynamic, renderabl
|
||||
) {$counttablealias}", $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether active filters should be applied to the report, defaults to true except in the case where we are editing a report
|
||||
* and we do not want filters to be applied to it
|
||||
*
|
||||
* @param bool $applyfilters
|
||||
*/
|
||||
public function set_filters_applied(bool $applyfilters): void {
|
||||
$this->applyfilters = $applyfilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return SQL fragments from given filter instance suitable for inclusion in table SQL
|
||||
*
|
||||
@ -169,4 +187,18 @@ abstract class base_report_table extends table_sql implements dynamic, renderabl
|
||||
public function guess_base_url(): void {
|
||||
$this->baseurl = new moodle_url('/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Override print_nothing_to_display to modity the output styles.
|
||||
*/
|
||||
public function print_nothing_to_display() {
|
||||
global $OUTPUT;
|
||||
|
||||
echo $this->get_dynamic_table_html_start();
|
||||
echo $this->render_reset_button();
|
||||
|
||||
echo $OUTPUT->render(new notification(get_string('nothingtodisplay'), notification::NOTIFY_INFO));
|
||||
|
||||
echo $this->get_dynamic_table_html_end();
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\table;
|
||||
|
||||
use core\output\notification;
|
||||
use html_writer;
|
||||
use moodle_exception;
|
||||
use moodle_url;
|
||||
@ -41,6 +42,9 @@ class custom_report_table extends base_report_table {
|
||||
/** @var string Unique ID prefix for the table */
|
||||
private const UNIQUEID_PREFIX = 'custom-report-table-';
|
||||
|
||||
/** @var bool Whether filters should be applied in report (we don't want them when editing) */
|
||||
protected const REPORT_APPLY_FILTERS = false;
|
||||
|
||||
/**
|
||||
* Table constructor. Note that the passed unique ID value must match the pattern "custom-report-table-(\d+)" so that
|
||||
* dynamic updates continue to load the same report
|
||||
@ -101,6 +105,8 @@ class custom_report_table extends base_report_table {
|
||||
$this->pageable(true);
|
||||
|
||||
// Initialise table SQL properties.
|
||||
$this->set_filters_applied(static::REPORT_APPLY_FILTERS);
|
||||
|
||||
$fieldsql = implode(', ', $fields);
|
||||
$this->init_sql($fieldsql, "{{$maintable}} {$maintablealias}", $joins, $where, $params, $groupby);
|
||||
}
|
||||
@ -195,7 +201,6 @@ class custom_report_table extends base_report_table {
|
||||
|
||||
$columns = $this->get_active_columns();
|
||||
if (empty($columns)) {
|
||||
$this->print_nothing_to_display();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -250,13 +255,21 @@ class custom_report_table extends base_report_table {
|
||||
}
|
||||
|
||||
/**
|
||||
* Override end of HTML to ensure that column headers are always added
|
||||
* Override print_nothing_to_display to ensure that column headers are always added.
|
||||
*/
|
||||
public function finish_html() {
|
||||
if ($this->totalrows == 0 && !$this->started_output) {
|
||||
$this->start_output();
|
||||
}
|
||||
public function print_nothing_to_display() {
|
||||
global $OUTPUT;
|
||||
|
||||
parent::finish_html();
|
||||
$this->start_html();
|
||||
$this->print_headers();
|
||||
echo html_writer::end_tag('table');
|
||||
echo html_writer::end_tag('div');
|
||||
$this->wrap_html_finish();
|
||||
|
||||
$notification = (new notification(get_string('nothingtodisplay'), notification::NOTIFY_INFO))
|
||||
->set_extra_classes(['mt-3']);
|
||||
echo $OUTPUT->render($notification);
|
||||
|
||||
echo $this->get_dynamic_table_html_end();
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,9 @@ function core_reportbuilder_inplace_editable($itemtype, $itemid, $newvalue) {
|
||||
case 'columnheading':
|
||||
return \core_reportbuilder\output\column_heading_editable::update($itemid, $newvalue);
|
||||
|
||||
case 'filterheading':
|
||||
return \core_reportbuilder\output\filter_heading_editable::update($itemid, $newvalue);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -40,6 +40,16 @@
|
||||
{{/body}}
|
||||
{{/ core_reportbuilder/toggle_card }}
|
||||
|
||||
{{< core_reportbuilder/toggle_card }}
|
||||
{{$collapsed}}collapsed{{/collapsed}}
|
||||
{{$id}}settingsfilters{{/id}}
|
||||
{{$header}}{{#str}} filters, core_reportbuilder {{/str}}{{/header}}
|
||||
{{$helpicon}}{{{filters.helpicon}}}{{/helpicon}}
|
||||
{{$body}}
|
||||
{{> core_reportbuilder/local/settings/filters}}
|
||||
{{/body}}
|
||||
{{/ core_reportbuilder/toggle_card }}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
79
reportbuilder/templates/local/settings/filters.mustache
Normal file
79
reportbuilder/templates/local/settings/filters.mustache
Normal file
@ -0,0 +1,79 @@
|
||||
{{!
|
||||
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/>.
|
||||
}}
|
||||
{{!
|
||||
@template core_reportbuilder/local/settings/filters
|
||||
|
||||
Template for custom report filters settings area
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"id": 3,
|
||||
"filtersform": "form"
|
||||
}
|
||||
}}
|
||||
|
||||
<div class="p-2" data-region="settings-filters">
|
||||
{{#filters}}
|
||||
{{#hasavailablefilters}}
|
||||
<div>
|
||||
<label for="addfilterselect" class="sr-only">{{#str}}selectafilter, core_reportbuilder{{/str}}</label>
|
||||
<select id="addfilterselect" name="addfilterselect" data-action="report-add-filter" class="w-100 custom-select">
|
||||
<option value="0">{{#str}}selectafilter, core_reportbuilder{{/str}}…</option>
|
||||
{{#availablefilters}}
|
||||
{{#optiongroup}}
|
||||
<optgroup label="{{text}}">
|
||||
{{#values}}
|
||||
<option value="{{value}}">{{visiblename}}</option>
|
||||
{{/values}}
|
||||
</optgroup>
|
||||
{{/optiongroup}}
|
||||
{{/availablefilters}}
|
||||
</select>
|
||||
</div>
|
||||
{{/hasavailablefilters}}
|
||||
|
||||
<div data-region="active-filters" class="form-vertical">
|
||||
{{#hasactivefilters}}
|
||||
<ul class="list-group reportbuilder-sortable-list mt-2 ml-0">
|
||||
{{#activefilters}}
|
||||
<li class="list-group-item list-group-item-action d-flex align-items-start text-dark"
|
||||
data-region="active-filter" data-filter-id="{{id}}" data-filter-name="{{heading}}" data-filter-position="{{sortorder}}">
|
||||
{{>core/drag_handle}}
|
||||
<div>
|
||||
<div class="d-flex">
|
||||
<small class="text-muted text-nowrap text-uppercase">{{entityname}} • {{heading}}</small>
|
||||
</div>
|
||||
<div>
|
||||
{{{headingeditable}}}
|
||||
</div>
|
||||
</div>
|
||||
<a data-action="report-remove-filter" class="ml-auto" href="#">
|
||||
{{#pix}}e/cancel, core, {{#str}}deletefilter, core_reportbuilder, {{{heading}}}{{/str}}{{/pix}}
|
||||
</a>
|
||||
</li>
|
||||
{{/activefilters}}
|
||||
</ul>
|
||||
{{/hasactivefilters}}
|
||||
|
||||
{{^hasactivefilters}}
|
||||
{{< core_reportbuilder/local/settings/empty_message }}
|
||||
{{$nothingtoshow}} {{#str}} nofilters, core_reportbuilder {{/str}} {{/nothingtoshow}}
|
||||
{{/ core_reportbuilder/local/settings/empty_message }}
|
||||
{{/hasactivefilters}}
|
||||
</div>
|
||||
{{/filters}}
|
||||
</div>
|
152
reportbuilder/tests/behat/filtereditor.feature
Normal file
152
reportbuilder/tests/behat/filtereditor.feature
Normal file
@ -0,0 +1,152 @@
|
||||
@core_reportbuilder @javascript
|
||||
Feature: Manage custom report filters
|
||||
In order to manage the filters of custom reports
|
||||
As an admin
|
||||
I need to add, edit and delete filters in a report
|
||||
|
||||
Scenario: Add filter to report
|
||||
Given the following "core_reportbuilder > Reports" exist:
|
||||
| name | source | default |
|
||||
| My report | core_user\reportbuilder\datasource\users | 0 |
|
||||
And I am on the "My report" "reportbuilder > Editor" page logged in as "admin"
|
||||
When I click on "Show/hide settings sidebar" "button"
|
||||
And I click on "Show/hide 'Filters'" "button"
|
||||
Then I should see "There are no filters selected" in the "[data-region='active-filters']" "css_element"
|
||||
And I set the field "Select a filter" to "Email address"
|
||||
And I should see "Added filter 'Email address'"
|
||||
And I should not see "There are no filters selected" in the "[data-region='active-filters']" "css_element"
|
||||
And I should see "Email address" in the "[data-region='active-filters']" "css_element"
|
||||
|
||||
Scenario: Rename filter in report
|
||||
Given the following "core_reportbuilder > Reports" exist:
|
||||
| name | source | default |
|
||||
| My report | core_user\reportbuilder\datasource\users | 0 |
|
||||
And the following "core_reportbuilder > Filters" exist:
|
||||
| report | uniqueidentifier |
|
||||
| My report | user:email |
|
||||
And I am on the "My report" "reportbuilder > Editor" page logged in as "admin"
|
||||
When I click on "Show/hide settings sidebar" "button"
|
||||
And I click on "Show/hide 'Filters'" "button"
|
||||
And I set the field "Rename filter 'Email address'" to "My Email filter"
|
||||
And I reload the page
|
||||
And I click on "Show/hide settings sidebar" "button"
|
||||
And I click on "Show/hide 'Filters'" "button"
|
||||
Then I should see "My Email filter" in the "[data-region='active-filters']" "css_element"
|
||||
|
||||
Scenario: Move filter in report
|
||||
Given the following "core_reportbuilder > Reports" exist:
|
||||
| name | source | default |
|
||||
| My report | core_user\reportbuilder\datasource\users | 0 |
|
||||
And the following "core_reportbuilder > Filters" exist:
|
||||
| report | uniqueidentifier |
|
||||
| My report | user:fullname |
|
||||
| My report | user:email |
|
||||
| My report | user:country |
|
||||
And I am on the "My report" "reportbuilder > Editor" page logged in as "admin"
|
||||
When I click on "Show/hide settings sidebar" "button"
|
||||
And I click on "Show/hide 'Filters'" "button"
|
||||
And I click on "Move filter 'Country'" "button"
|
||||
And I click on "After \"Full name\"" "link" in the "Move filter 'Country'" "dialogue"
|
||||
Then I should see "Moved filter 'Country'"
|
||||
And "Country" "text" should appear before "Email address" "text"
|
||||
|
||||
Scenario: Delete filter from report
|
||||
Given the following "core_reportbuilder > Reports" exist:
|
||||
| name | source | default |
|
||||
| My report | core_user\reportbuilder\datasource\users | 0 |
|
||||
And the following "core_reportbuilder > Filters" exist:
|
||||
| report | uniqueidentifier |
|
||||
| My report | user:email |
|
||||
And I am on the "My report" "reportbuilder > Editor" page logged in as "admin"
|
||||
When I click on "Show/hide settings sidebar" "button"
|
||||
And I click on "Show/hide 'Filters'" "button"
|
||||
And I click on "Delete filter 'Email address'" "link"
|
||||
And I click on "Delete" "button" in the "Delete filter 'Email address'" "dialogue"
|
||||
Then I should see "Deleted filter 'Email address'"
|
||||
And I should see "There are no filters selected" in the "[data-region='active-filters']" "css_element"
|
||||
And I should not see "Email address" in the "[data-region='active-filters']" "css_element"
|
||||
|
||||
Scenario: Use report filters when previewing report
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| user1 | User | 1 |
|
||||
| user2 | User | 2 |
|
||||
| user3 | User | 3 |
|
||||
And the following "core_reportbuilder > Reports" exist:
|
||||
| name | source | default |
|
||||
| My report | core_user\reportbuilder\datasource\users | 0 |
|
||||
And the following "core_reportbuilder > Columns" exist:
|
||||
| report | uniqueidentifier |
|
||||
| My report | user:fullname |
|
||||
| My report | user:email |
|
||||
And the following "core_reportbuilder > Filters" exist:
|
||||
| report | uniqueidentifier |
|
||||
| My report | user:fullname |
|
||||
And I am on the "My report" "reportbuilder > Editor" page logged in as "admin"
|
||||
And I change window size to "large"
|
||||
And I should see "user1@example.com" in the ".reportbuilder-table" "css_element"
|
||||
And I should see "user2@example.com" in the ".reportbuilder-table" "css_element"
|
||||
And I should see "user3@example.com" in the ".reportbuilder-table" "css_element"
|
||||
When I click on "Switch to preview mode" "button"
|
||||
And I click on "Filters" "button"
|
||||
And I set the following fields in the "Full name" "core_reportbuilder > Filter" to these values:
|
||||
| Full name operator | Does not contain |
|
||||
| Full name value | User 2 |
|
||||
And I click on "Apply" "button" in the "[data-region='report-filters']" "css_element"
|
||||
Then I should see "Filters applied"
|
||||
And I should see "Filters (1)" in the "#dropdownFiltersButton" "css_element"
|
||||
And the following should exist in the "reportbuilder-table" table:
|
||||
| Full name | Email address |
|
||||
| User 1 | user1@example.com |
|
||||
| User 3 | user3@example.com |
|
||||
And the following should not exist in the "reportbuilder-table" table:
|
||||
| Full name | Email address |
|
||||
| User 2 | user2@example.com |
|
||||
|
||||
Scenario: Use report filters when previewing report that contains same condition
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| user1 | User | 1 |
|
||||
| user2 | User | 2 |
|
||||
| user3 | User | 3 |
|
||||
And the following "core_reportbuilder > Reports" exist:
|
||||
| name | source | default |
|
||||
| My report | core_user\reportbuilder\datasource\users | 0 |
|
||||
And the following "core_reportbuilder > Columns" exist:
|
||||
| report | uniqueidentifier |
|
||||
| My report | user:fullname |
|
||||
| My report | user:email |
|
||||
And the following "core_reportbuilder > Conditions" exist:
|
||||
| report | uniqueidentifier |
|
||||
| My report | user:email |
|
||||
And the following "core_reportbuilder > Filters" exist:
|
||||
| report | uniqueidentifier |
|
||||
| My report | user:email |
|
||||
And I am on the "My report" "reportbuilder > Editor" page logged in as "admin"
|
||||
And I change window size to "large"
|
||||
And I should see "user1@example.com" in the ".reportbuilder-table" "css_element"
|
||||
And I should see "user2@example.com" in the ".reportbuilder-table" "css_element"
|
||||
And I should see "user3@example.com" in the ".reportbuilder-table" "css_element"
|
||||
# Set a condition to the report.
|
||||
When I click on "Show/hide settings sidebar" "button"
|
||||
And I click on "Show/hide 'Conditions'" "button"
|
||||
And I set the following fields in the "Email address" "core_reportbuilder > Condition" to these values:
|
||||
| Email address operator | Is not equal to |
|
||||
| Email address value | user3@example.com |
|
||||
And I click on "Apply" "button" in the "#settingsconditions" "css_element"
|
||||
And I click on "Switch to preview mode" "button"
|
||||
And I click on "Filters" "button"
|
||||
And I set the following fields in the "Email address" "core_reportbuilder > Filter" to these values:
|
||||
| Email address operator | Is not equal to |
|
||||
| Email address value | user2@example.com |
|
||||
And I click on "Apply" "button" in the "[data-region='report-filters']" "css_element"
|
||||
Then I should see "Filters applied"
|
||||
And I should see "Filters (1)" in the "#dropdownFiltersButton" "css_element"
|
||||
# Assert we haven't overridden the condition and user3 is still not showing in the report.
|
||||
And the following should exist in the "reportbuilder-table" table:
|
||||
| Full name | Email address |
|
||||
| User 1 | user1@example.com |
|
||||
And the following should not exist in the "reportbuilder-table" table:
|
||||
| Full name | Email address |
|
||||
| User 2 | user2@example.com |
|
||||
| User 3 | user3@example.com |
|
93
reportbuilder/tests/external/filters/add_test.php
vendored
Normal file
93
reportbuilder/tests/external/filters/add_test.php
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
// 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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\external\filters;
|
||||
|
||||
use core_reportbuilder\manager;
|
||||
use core_reportbuilder_generator;
|
||||
use external_api;
|
||||
use externallib_advanced_testcase;
|
||||
use core_reportbuilder\report_access_exception;
|
||||
use core_reportbuilder\local\models\filter;
|
||||
use core_user\reportbuilder\datasource\users;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once("{$CFG->dirroot}/webservice/tests/helpers.php");
|
||||
|
||||
/**
|
||||
* Unit tests of external class for adding report filters
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @covers \core_reportbuilder\external\filters\add
|
||||
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class add_test extends externallib_advanced_testcase {
|
||||
|
||||
/**
|
||||
* Text execute method
|
||||
*/
|
||||
public function test_execute(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
|
||||
$report = $generator->create_report([
|
||||
'name' => 'My report',
|
||||
'source' => users::class,
|
||||
'default' => false,
|
||||
]);
|
||||
|
||||
// Add filter.
|
||||
$result = add::execute($report->get('id'), 'user:fullname');
|
||||
$result = external_api::clean_returnvalue(add::execute_returns(), $result);
|
||||
$this->assertTrue($result['hasavailablefilters']);
|
||||
$this->assertEquals('User', $result['availablefilters'][0]['optiongroup']['text']);
|
||||
$this->assertNotEmpty($result['availablefilters'][0]['optiongroup']['values']);
|
||||
$this->assertTrue($result['hasactivefilters']);
|
||||
$this->assertCount(1, $result['activefilters']);
|
||||
$this->assertEquals('Full name', $result['activefilters'][0]['heading']);
|
||||
|
||||
// Assert report filters.
|
||||
$filters = filter::get_filter_records($report->get('id'));
|
||||
$this->assertCount(1, $filters);
|
||||
$this->assertEquals('user:fullname', reset($filters)->get('uniqueidentifier'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test execute method for a user without permission to edit reports
|
||||
*/
|
||||
public function test_execute_access_exception(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
|
||||
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
|
||||
$this->expectException(report_access_exception::class);
|
||||
$this->expectExceptionMessage('You can not edit this report');
|
||||
add::execute($report->get('id'), 'user:fullname');
|
||||
}
|
||||
}
|
98
reportbuilder/tests/external/filters/delete_test.php
vendored
Normal file
98
reportbuilder/tests/external/filters/delete_test.php
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
// 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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\external\filters;
|
||||
|
||||
use core_reportbuilder_generator;
|
||||
use external_api;
|
||||
use externallib_advanced_testcase;
|
||||
use core_reportbuilder\report_access_exception;
|
||||
use core_reportbuilder\local\models\filter;
|
||||
use core_user\reportbuilder\datasource\users;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once("{$CFG->dirroot}/webservice/tests/helpers.php");
|
||||
|
||||
/**
|
||||
* Unit tests of external class for deleting report filters
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @covers \core_reportbuilder\external\filters\delete
|
||||
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class delete_test extends externallib_advanced_testcase {
|
||||
|
||||
/**
|
||||
* Text execute method
|
||||
*/
|
||||
public function test_execute(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
|
||||
$report = $generator->create_report([
|
||||
'name' => 'My report',
|
||||
'source' => users::class,
|
||||
'default' => false,
|
||||
]);
|
||||
|
||||
// Add two filters.
|
||||
$filterfullname = $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:fullname']);
|
||||
$generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:email']);
|
||||
|
||||
// Delete the first filter.
|
||||
$result = delete::execute($report->get('id'), $filterfullname->get('id'));
|
||||
$result = external_api::clean_returnvalue(delete::execute_returns(), $result);
|
||||
$this->assertTrue($result['hasavailablefilters']);
|
||||
$this->assertEquals('User', $result['availablefilters'][0]['optiongroup']['text']);
|
||||
$this->assertNotEmpty($result['availablefilters'][0]['optiongroup']['values']);
|
||||
$this->assertTrue($result['hasactivefilters']);
|
||||
$this->assertCount(1, $result['activefilters']);
|
||||
$this->assertEquals('Email address', $result['activefilters'][0]['heading']);
|
||||
|
||||
// Assert report filters.
|
||||
$filters = filter::get_filter_records($report->get('id'));
|
||||
$this->assertCount(1, $filters);
|
||||
$this->assertEquals('user:email', reset($filters)->get('uniqueidentifier'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test execute method for a user without permission to edit reports
|
||||
*/
|
||||
public function test_execute_access_exception(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
|
||||
$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
|
||||
$filter = $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:email']);
|
||||
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
|
||||
$this->expectException(report_access_exception::class);
|
||||
$this->expectExceptionMessage('You can not edit this report');
|
||||
delete::execute($report->get('id'), $filter->get('id'));
|
||||
}
|
||||
}
|
108
reportbuilder/tests/external/filters/reorder_test.php
vendored
Normal file
108
reportbuilder/tests/external/filters/reorder_test.php
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
// 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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_reportbuilder\external\filters;
|
||||
|
||||
use core_reportbuilder_generator;
|
||||
use external_api;
|
||||
use externallib_advanced_testcase;
|
||||
use core_reportbuilder\report_access_exception;
|
||||
use core_reportbuilder\local\models\filter;
|
||||
use core_user\reportbuilder\datasource\users;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once("{$CFG->dirroot}/webservice/tests/helpers.php");
|
||||
|
||||
/**
|
||||
* Unit tests of external class for re-ordering report filters
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @covers \core_reportbuilder\external\filters\reorder
|
||||
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class reorder_test extends externallib_advanced_testcase {
|
||||
|
||||
/**
|
||||
* Text execute method
|
||||
*/
|
||||
public function test_execute(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
|
||||
$report = $generator->create_report([
|
||||
'name' => 'My report',
|
||||
'source' => users::class,
|
||||
'default' => false,
|
||||
]);
|
||||
|
||||
// Add four filters.
|
||||
$generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:fullname']);
|
||||
$generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:email']);
|
||||
$generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:country']);
|
||||
$filtercity = $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:city']);
|
||||
|
||||
// Move the city filter to second position.
|
||||
$result = reorder::execute($report->get('id'), $filtercity->get('id'), 2);
|
||||
$result = external_api::clean_returnvalue(reorder::execute_returns(), $result);
|
||||
$this->assertTrue($result['hasavailablefilters']);
|
||||
$this->assertEquals('User', $result['availablefilters'][0]['optiongroup']['text']);
|
||||
$this->assertNotEmpty($result['availablefilters'][0]['optiongroup']['values']);
|
||||
$this->assertTrue($result['hasactivefilters']);
|
||||
$this->assertCount(4, $result['activefilters']);
|
||||
|
||||
// Assert report filters order.
|
||||
$filters = filter::get_filter_records($report->get('id'), 'filterorder');
|
||||
|
||||
$filteridentifiers = array_map(static function(filter $filter): string {
|
||||
return $filter->get('uniqueidentifier');
|
||||
}, $filters);
|
||||
|
||||
$this->assertEquals([
|
||||
'user:fullname',
|
||||
'user:city',
|
||||
'user:email',
|
||||
'user:country',
|
||||
], $filteridentifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test execute method for a user without permission to edit reports
|
||||
*/
|
||||
public function test_execute_access_exception(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
|
||||
$report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
|
||||
$filter = $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:email']);
|
||||
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
|
||||
$this->expectException(report_access_exception::class);
|
||||
$this->expectExceptionMessage('You can not edit this report');
|
||||
reorder::execute($report->get('id'), $filter->get('id'), 1);
|
||||
}
|
||||
}
|
@ -40,7 +40,7 @@ class testable_system_report_table extends system_report_table {
|
||||
$record = parent::format_row($row);
|
||||
$result = [];
|
||||
|
||||
$columns = $this->systemreport->get_columns();
|
||||
$columns = $this->report->get_columns();
|
||||
foreach ($columns as $column) {
|
||||
$result[$column->get_name()] = $record[$column->get_column_alias()];
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ class users extends datasource {
|
||||
|
||||
$userentityname = $userentity->get_entity_name();
|
||||
$this->add_columns_from_entity($userentityname);
|
||||
$this->add_filters_from_entity($userentityname);
|
||||
$this->add_conditions_from_entity($userentityname);
|
||||
}
|
||||
|
||||
@ -73,6 +74,15 @@ class users extends datasource {
|
||||
return ['user:fullname', 'user:username', 'user:email'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filters that will be added to the report once is created
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_default_filters(): array {
|
||||
return ['user:fullname', 'user:username', 'user:email'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the conditions that will be added to the report once is created
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user