diff --git a/lang/en/reportbuilder.php b/lang/en/reportbuilder.php index 2cd6e1b4e00..b9f661e702b 100644 --- a/lang/en/reportbuilder.php +++ b/lang/en/reportbuilder.php @@ -48,6 +48,11 @@ $string['audiencedeleted'] = 'Deleted audience \'{$a}\''; $string['audiencemultiselectpostfix'] = '{$a->elements} plus {$a->morecount} more'; $string['audiencenotsaved'] = 'Audience not saved'; $string['audiencesaved'] = 'Audience saved'; +$string['cardview'] = 'Card view'; +$string['cardview_help'] = 'Card view allows you to define the layout of your report when viewed on narrow devices. Columns will collapse beyond the limit set here, with a toggle to expand the card to view all report data.'; +$string['cardviewfirstcolumntitle'] = 'First column title'; +$string['cardviewsettingssaved'] = 'Card view settings saved'; +$string['cardviewvisiblecolumns'] = 'Columns visible'; $string['columnadded'] = 'Added column \'{$a}\''; $string['columnaggregated'] = 'Aggregated column \'{$a}\''; $string['columndeleted'] = 'Deleted column \'{$a}\''; diff --git a/lib/db/install.xml b/lib/db/install.xml index 5f0e91518ee..fe1bfa19341 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -1,5 +1,5 @@ - @@ -4387,6 +4387,7 @@ + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index d9abd50a0bf..c76b4d959f9 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -3130,5 +3130,20 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2021110800.02); } + if ($oldversion < 2021110800.03) { + + // Define field settingsdata to be added to reportbuilder_report. + $table = new xmldb_table('reportbuilder_report'); + $field = new xmldb_field('settingsdata', XMLDB_TYPE_TEXT, null, null, null, null, null, 'conditiondata'); + + // Conditionally launch add field settingsdata. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Main savepoint reached. + upgrade_main_savepoint(true, 2021110800.03); + } + return true; } diff --git a/reportbuilder/amd/build/editor.min.js b/reportbuilder/amd/build/editor.min.js index bebbbc2aef7..4dde824c2ec 100644 --- a/reportbuilder/amd/build/editor.min.js +++ b/reportbuilder/amd/build/editor.min.js @@ -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/editor/filters","core_reportbuilder/local/editor/sorting","core_reportbuilder/local/repository/reports"],function(a,b,c,d,e,f,g,h,i,j,k){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;c=n(c);d=n(d);e=n(e);f=m(f);function l(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;l=function(){return a};return a}function m(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=l();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 n(a){return a&&a.__esModule?a:{default:a}}var o=!1,p=function(){(0,g.init)(o);(0,h.init)(o);(0,i.init)(o);(0,j.init)(o);if(o){return}document.addEventListener("click",function(a){var b=a.target.closest(f.actions.toggleEditPreview);if(b){a.preventDefault();var g=a.target.closest(f.regions.report),h=new d.default("core_reportbuilder/reports:get"),i="1"!==b.dataset.editMode,j="";(0,k.getReport)(g.dataset.reportId,i).then(function(a){j=a.javascript;return e.default.render("core_reportbuilder/local/dynamictabs/editor",a)}).then(function(a,b){return e.default.replaceNode(g,a,b+j)}).then(function(){return h.resolve()}).catch(c.default.exception)}});o=!0};a.init=p}); +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/editor/sorting","core_reportbuilder/local/editor/card_view","core_reportbuilder/local/repository/reports"],function(a,b,c,d,e,f,g,h,i,j,k,l){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;c=o(c);d=o(d);e=o(e);f=n(f);function m(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;m=function(){return a};return a}function n(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=m();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 o(a){return a&&a.__esModule?a:{default:a}}var p=!1,q=function(){(0,g.init)(p);(0,h.init)(p);(0,i.init)(p);(0,j.init)(p);(0,k.init)(p);if(p){return}document.addEventListener("click",function(a){var b=a.target.closest(f.actions.toggleEditPreview);if(b){a.preventDefault();var g=a.target.closest(f.regions.report),h=new d.default("core_reportbuilder/reports:get"),i="1"!==b.dataset.editMode,j="";(0,l.getReport)(g.dataset.reportId,i).then(function(a){j=a.javascript;return e.default.render("core_reportbuilder/local/dynamictabs/editor",a)}).then(function(a,b){return e.default.replaceNode(g,a,b+j)}).then(function(){return h.resolve()}).catch(c.default.exception)}});p=!0};a.init=q}); //# sourceMappingURL=editor.min.js.map diff --git a/reportbuilder/amd/build/editor.min.js.map b/reportbuilder/amd/build/editor.min.js.map index 63bf578068e..0f0f1fd9a22 100644 --- a/reportbuilder/amd/build/editor.min.js.map +++ b/reportbuilder/amd/build/editor.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/editor.js"],"names":["initialized","init","document","addEventListener","event","toggleEditViewMode","target","closest","reportSelectors","actions","toggleEditPreview","preventDefault","reportElement","regions","report","pendingPromise","Pending","toggledEditMode","dataset","editMode","customjs","reportId","then","response","javascript","Templates","render","html","js","replaceNode","resolve","catch","Notification","exception"],"mappings":"6rBAuBA,a,+DAGA,OACA,OACA,OACA,O,4lBAOIA,CAAAA,CAAW,G,CAKFC,CAAI,CAAG,UAAM,CACtB,WAAkBD,CAAlB,EACA,WAAqBA,CAArB,EACA,WAAkBA,CAAlB,EACA,WAAkBA,CAAlB,EAGA,GAAIA,CAAJ,CAAiB,CACb,MACH,CAGDE,QAAQ,CAACC,gBAAT,CAA0B,OAA1B,CAAmC,SAAAC,CAAK,CAAI,CAGxC,GAAMC,CAAAA,CAAkB,CAAGD,CAAK,CAACE,MAAN,CAAaC,OAAb,CAAqBC,CAAe,CAACC,OAAhB,CAAwBC,iBAA7C,CAA3B,CACA,GAAIL,CAAJ,CAAwB,CACpBD,CAAK,CAACO,cAAN,GADoB,GAGdC,CAAAA,CAAa,CAAGR,CAAK,CAACE,MAAN,CAAaC,OAAb,CAAqBC,CAAe,CAACK,OAAhB,CAAwBC,MAA7C,CAHF,CAIdC,CAAc,CAAG,GAAIC,UAAJ,CAAY,gCAAZ,CAJH,CAKdC,CAAe,CAA2C,GAAxC,GAAAZ,CAAkB,CAACa,OAAnB,CAA2BC,QAL/B,CAOhBC,CAAQ,CAAG,EAPK,CASpB,gBAAUR,CAAa,CAACM,OAAd,CAAsBG,QAAhC,CAA0CJ,CAA1C,EACKK,IADL,CACU,SAAAC,CAAQ,CAAI,CACdH,CAAQ,CAAGG,CAAQ,CAACC,UAApB,CACA,MAAOC,WAAUC,MAAV,CAAiB,6CAAjB,CAAgEH,CAAhE,CACV,CAJL,EAKKD,IALL,CAKU,SAACK,CAAD,CAAOC,CAAP,CAAc,CAChB,MAAOH,WAAUI,WAAV,CAAsBjB,CAAtB,CAAqCe,CAArC,CAA2CC,CAAE,CAAGR,CAAhD,CACV,CAPL,EAQKE,IARL,CAQU,iBAAMP,CAAAA,CAAc,CAACe,OAAf,EAAN,CARV,EASKC,KATL,CASWC,UAAaC,SATxB,CAUH,CACJ,CAxBD,EA0BAjC,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 .\n\n/**\n * Report builder editor\n *\n * @module core_reportbuilder/editor\n * @copyright 2021 David Matamoros \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 {init as sortingEditorInit} from 'core_reportbuilder/local/editor/sorting';\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 columnsEditorInit(initialized);\n conditionsEditorInit(initialized);\n filtersEditorInit(initialized);\n sortingEditorInit(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 reportElement = event.target.closest(reportSelectors.regions.report);\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/local/dynamictabs/editor', response);\n })\n .then((html, js) => {\n return Templates.replaceNode(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"} \ No newline at end of file +{"version":3,"sources":["../src/editor.js"],"names":["initialized","init","document","addEventListener","event","toggleEditViewMode","target","closest","reportSelectors","actions","toggleEditPreview","preventDefault","reportElement","regions","report","pendingPromise","Pending","toggledEditMode","dataset","editMode","customjs","reportId","then","response","javascript","Templates","render","html","js","replaceNode","resolve","catch","Notification","exception"],"mappings":"2uBAuBA,a,+DAGA,OACA,OACA,OACA,O,4lBAQIA,CAAAA,CAAW,G,CAKFC,CAAI,CAAG,UAAM,CACtB,WAAkBD,CAAlB,EACA,WAAqBA,CAArB,EACA,WAAkBA,CAAlB,EACA,WAAkBA,CAAlB,EACA,WAAmBA,CAAnB,EAGA,GAAIA,CAAJ,CAAiB,CACb,MACH,CAGDE,QAAQ,CAACC,gBAAT,CAA0B,OAA1B,CAAmC,SAAAC,CAAK,CAAI,CAGxC,GAAMC,CAAAA,CAAkB,CAAGD,CAAK,CAACE,MAAN,CAAaC,OAAb,CAAqBC,CAAe,CAACC,OAAhB,CAAwBC,iBAA7C,CAA3B,CACA,GAAIL,CAAJ,CAAwB,CACpBD,CAAK,CAACO,cAAN,GADoB,GAGdC,CAAAA,CAAa,CAAGR,CAAK,CAACE,MAAN,CAAaC,OAAb,CAAqBC,CAAe,CAACK,OAAhB,CAAwBC,MAA7C,CAHF,CAIdC,CAAc,CAAG,GAAIC,UAAJ,CAAY,gCAAZ,CAJH,CAKdC,CAAe,CAA2C,GAAxC,GAAAZ,CAAkB,CAACa,OAAnB,CAA2BC,QAL/B,CAOhBC,CAAQ,CAAG,EAPK,CASpB,gBAAUR,CAAa,CAACM,OAAd,CAAsBG,QAAhC,CAA0CJ,CAA1C,EACKK,IADL,CACU,SAAAC,CAAQ,CAAI,CACdH,CAAQ,CAAGG,CAAQ,CAACC,UAApB,CACA,MAAOC,WAAUC,MAAV,CAAiB,6CAAjB,CAAgEH,CAAhE,CACV,CAJL,EAKKD,IALL,CAKU,SAACK,CAAD,CAAOC,CAAP,CAAc,CAChB,MAAOH,WAAUI,WAAV,CAAsBjB,CAAtB,CAAqCe,CAArC,CAA2CC,CAAE,CAAGR,CAAhD,CACV,CAPL,EAQKE,IARL,CAQU,iBAAMP,CAAAA,CAAc,CAACe,OAAf,EAAN,CARV,EASKC,KATL,CASWC,UAAaC,SATxB,CAUH,CACJ,CAxBD,EA0BAjC,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 .\n\n/**\n * Report builder editor\n *\n * @module core_reportbuilder/editor\n * @copyright 2021 David Matamoros \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 {init as sortingEditorInit} from 'core_reportbuilder/local/editor/sorting';\nimport {init as cardviewEditorInit} from 'core_reportbuilder/local/editor/card_view';\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 columnsEditorInit(initialized);\n conditionsEditorInit(initialized);\n filtersEditorInit(initialized);\n sortingEditorInit(initialized);\n cardviewEditorInit(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 reportElement = event.target.closest(reportSelectors.regions.report);\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/local/dynamictabs/editor', response);\n })\n .then((html, js) => {\n return Templates.replaceNode(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"} \ No newline at end of file diff --git a/reportbuilder/amd/build/local/editor/card_view.min.js b/reportbuilder/amd/build/local/editor/card_view.min.js new file mode 100644 index 00000000000..365f1a3a89d --- /dev/null +++ b/reportbuilder/amd/build/local/editor/card_view.min.js @@ -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/card_view",["exports","core_form/dynamicform","core/toast","core/str","core/pubsub","core/notification","core_reportbuilder/local/events","core_reportbuilder/local/selectors"],function(a,b,c,d,e,f,g,h){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=k(b);f=k(f);g=j(g);h=j(h);function i(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;i=function(){return a};return a}function j(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=i();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 k(a){return a&&a.__esModule?a:{default:a}}var l=null,m=function(){var a=document.querySelector(h.regions.settingsCardView);if(!a){return}l=new b.default(a,"\\core_reportbuilder\\form\\card_view");l.addEventListener(l.events.FORM_SUBMITTED,function(a){a.preventDefault();(0,d.get_string)("cardviewsettingssaved","core_reportbuilder").then(c.add).catch(f.default.exception)})},n=function(a){m();if(a){return}(0,e.subscribe)(g.publish.reportColumnsUpdated,function(){var a=document.querySelector(h.regions.report);l.load({reportid:a.dataset.reportId})})};a.init=n}); +//# sourceMappingURL=card_view.min.js.map diff --git a/reportbuilder/amd/build/local/editor/card_view.min.js.map b/reportbuilder/amd/build/local/editor/card_view.min.js.map new file mode 100644 index 00000000000..03f2e43face --- /dev/null +++ b/reportbuilder/amd/build/local/editor/card_view.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../../src/local/editor/card_view.js"],"names":["cardViewForm","initCardViewForm","cardViewFormContainer","document","querySelector","reportSelectors","regions","settingsCardView","DynamicForm","addEventListener","events","FORM_SUBMITTED","event","preventDefault","then","addToast","catch","Notification","exception","init","initialized","reportEvents","publish","reportColumnsUpdated","reportElement","report","load","reportid","dataset","reportId"],"mappings":"shBAuBA,a,+DAEA,OAIA,OACA,OACA,O,4lBAEIA,CAAAA,CAAY,CAAG,I,CAKbC,CAAgB,CAAG,UAAM,CAC3B,GAAMC,CAAAA,CAAqB,CAAGC,QAAQ,CAACC,aAAT,CAAuBC,CAAe,CAACC,OAAhB,CAAwBC,gBAA/C,CAA9B,CACA,GAAI,CAACL,CAAL,CAA4B,CACxB,MACH,CACDF,CAAY,CAAG,GAAIQ,UAAJ,CAAgBN,CAAhB,CAAuC,uCAAvC,CAAf,CAEAF,CAAY,CAACS,gBAAb,CAA8BT,CAAY,CAACU,MAAb,CAAoBC,cAAlD,CAAkE,SAACC,CAAD,CAAW,CACzEA,CAAK,CAACC,cAAN,GAEA,iBAAU,uBAAV,CAAmC,oBAAnC,EACKC,IADL,CACUC,KADV,EAEKC,KAFL,CAEWC,UAAaC,SAFxB,CAGH,CAND,CAOH,C,CAOYC,CAAI,CAAG,SAACC,CAAD,CAAiB,CACjCnB,CAAgB,GAChB,GAAImB,CAAJ,CAAiB,CACb,MACH,CAGD,gBAAUC,CAAY,CAACC,OAAb,CAAqBC,oBAA/B,CAAqD,UAAM,CACvD,GAAMC,CAAAA,CAAa,CAAGrB,QAAQ,CAACC,aAAT,CAAuBC,CAAe,CAACC,OAAhB,CAAwBmB,MAA/C,CAAtB,CACAzB,CAAY,CAAC0B,IAAb,CAAkB,CAACC,QAAQ,CAAEH,CAAa,CAACI,OAAd,CAAsBC,QAAjC,CAAlB,CACH,CAHD,CAIH,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 .\n\n/**\n * Report builder card view editor\n *\n * @module core_reportbuilder/local/editor/card_view\n * @copyright 2021 Mikel Martín \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n\"use strict\";\n\nimport DynamicForm from 'core_form/dynamicform';\nimport {add as addToast} from 'core/toast';\nimport {get_string as getString} from \"core/str\";\nimport {subscribe as subscribe} from 'core/pubsub';\nimport Notification from 'core/notification';\nimport * as reportEvents from 'core_reportbuilder/local/events';\nimport * as reportSelectors from 'core_reportbuilder/local/selectors';\n\nlet cardViewForm = null;\n\n/**\n * Initialise card view form, must be called on each init because the form container is re-created when switching editor modes\n */\nconst initCardViewForm = () => {\n const cardViewFormContainer = document.querySelector(reportSelectors.regions.settingsCardView);\n if (!cardViewFormContainer) {\n return;\n }\n cardViewForm = new DynamicForm(cardViewFormContainer, '\\\\core_reportbuilder\\\\form\\\\card_view');\n\n cardViewForm.addEventListener(cardViewForm.events.FORM_SUBMITTED, (event) => {\n event.preventDefault();\n\n getString('cardviewsettingssaved', 'core_reportbuilder')\n .then(addToast)\n .catch(Notification.exception);\n });\n};\n\n/**\n * Initialise module\n *\n * @param {Boolean} initialized Ensure we only add our listeners once\n */\nexport const init = (initialized) => {\n initCardViewForm();\n if (initialized) {\n return;\n }\n\n // Update form each time a column is added or removed to the custom report.\n subscribe(reportEvents.publish.reportColumnsUpdated, () => {\n const reportElement = document.querySelector(reportSelectors.regions.report);\n cardViewForm.load({reportid: reportElement.dataset.reportId});\n });\n};\n"],"file":"card_view.min.js"} \ No newline at end of file diff --git a/reportbuilder/amd/build/local/selectors.min.js b/reportbuilder/amd/build/local/selectors.min.js index 09fdd41210c..13e103d5ce4 100644 --- a/reportbuilder/amd/build/local/selectors.min.js +++ b/reportbuilder/amd/build/local/selectors.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\"]",settingsFilters:"[data-region=\"settings-filters\"]",activeFilters:"[data-region=\"active-filters\"]",activeFilter:"[data-region=\"active-filter\"]",settingsSorting:"[data-region=\"settings-sorting\"]",audiencesContainer:"[data-region=\"audiences\"]",audienceFormContainer:"[data-region=\"audience-form-container\"]",audienceCard:"[data-region=\"audience-card\"]",audienceForm:"[data-region=\"audience-form\"]",audienceEmptyMessage:"[data-region=no-instances-message]",audienceDescription:"[data-region=audience-description]",audienceNotSavedLabel:"[data-region=audience-not-saved]"},actions:{reportActionPopup:"[data-action=\"report-action-popup\"]",reportCreate:"[data-action=\"report-create\"]",reportEdit:"[data-action=\"report-edit\"]",reportDelete:"[data-action=\"report-delete\"]",reportAddColumn:"[data-action=\"report-add-column\"]",reportRemoveColumn:"[data-action=\"report-remove-column\"]",reportAddCondition:"[data-action=\"report-add-condition\"]",reportRemoveCondition:"[data-action=\"report-remove-condition\"]",reportAddFilter:"[data-action=\"report-add-filter\"]",reportRemoveFilter:"[data-action=\"report-remove-filter\"]",reportToggleColumnSort:"[data-action=\"report-toggle-column-sorting\"]",reportToggleColumnSortDirection:"[data-action=\"report-toggle-sort-direction\"]",sidebarSearch:"[data-action=\"sidebar-search\"]",toggleEditPreview:"[data-action=\"toggle-edit-preview\"]",audienceAdd:"[data-action=\"add-audience\"]",audienceEdit:"[data-action=\"edit-audience\"]",audienceDelete:"[data-action=\"delete-audience\"]"}};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\"]",settingsSorting:"[data-region=\"settings-sorting\"]",audiencesContainer:"[data-region=\"audiences\"]",audienceFormContainer:"[data-region=\"audience-form-container\"]",audienceCard:"[data-region=\"audience-card\"]",audienceForm:"[data-region=\"audience-form\"]",audienceEmptyMessage:"[data-region=no-instances-message]",audienceDescription:"[data-region=audience-description]",audienceNotSavedLabel:"[data-region=audience-not-saved]",settingsCardView:"[data-region=\"settings-cardview\"]"},actions:{reportActionPopup:"[data-action=\"report-action-popup\"]",reportCreate:"[data-action=\"report-create\"]",reportEdit:"[data-action=\"report-edit\"]",reportDelete:"[data-action=\"report-delete\"]",reportAddColumn:"[data-action=\"report-add-column\"]",reportRemoveColumn:"[data-action=\"report-remove-column\"]",reportAddCondition:"[data-action=\"report-add-condition\"]",reportRemoveCondition:"[data-action=\"report-remove-condition\"]",reportAddFilter:"[data-action=\"report-add-filter\"]",reportRemoveFilter:"[data-action=\"report-remove-filter\"]",reportToggleColumnSort:"[data-action=\"report-toggle-column-sorting\"]",reportToggleColumnSortDirection:"[data-action=\"report-toggle-sort-direction\"]",sidebarSearch:"[data-action=\"sidebar-search\"]",toggleEditPreview:"[data-action=\"toggle-edit-preview\"]",audienceAdd:"[data-action=\"add-audience\"]",audienceEdit:"[data-action=\"edit-audience\"]",audienceDelete:"[data-action=\"delete-audience\"]"}};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 diff --git a/reportbuilder/amd/build/local/selectors.min.js.map b/reportbuilder/amd/build/local/selectors.min.js.map index 0ec42fdbb3f..f6f1002e53e 100644 --- a/reportbuilder/amd/build/local/selectors.min.js.map +++ b/reportbuilder/amd/build/local/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","settingsFilters","activeFilters","activeFilter","settingsSorting","audiencesContainer","audienceFormContainer","audienceCard","audienceForm","audienceEmptyMessage","audienceDescription","audienceNotSavedLabel","actions","reportActionPopup","reportCreate","reportEdit","reportDelete","reportAddColumn","reportRemoveColumn","reportAddCondition","reportRemoveCondition","reportAddFilter","reportRemoveFilter","reportToggleColumnSort","reportToggleColumnSortDirection","sidebarSearch","toggleEditPreview","audienceAdd","audienceEdit","audienceDelete","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,CAcLC,eAAe,CAAE,oCAdZ,CAeLC,kBAAkB,CAAE,6BAff,CAgBLC,qBAAqB,CAAE,2CAhBlB,CAiBLC,YAAY,CAAE,iCAjBT,CAkBLC,YAAY,CAAE,iCAlBT,CAmBLC,oBAAoB,CAAE,oCAnBjB,CAoBLC,mBAAmB,CAAE,oCApBhB,CAqBLC,qBAAqB,CAAE,kCArBlB,CADK,CAwBdC,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,sBAAsB,CAAE,gDAXnB,CAYLC,+BAA+B,CAAE,gDAZ5B,CAaLC,aAAa,CAAE,kCAbV,CAcLC,iBAAiB,CAAE,uCAdd,CAeLC,WAAW,CAAE,gCAfR,CAgBLC,YAAY,CAAE,iCAhBT,CAiBLC,cAAc,CAAE,mCAjBX,CAxBK,CAAlB,CAoDAxC,CAAS,CAACyC,SAAV,CAAsB,SAAAC,CAAQ,kBAAO1C,CAAS,CAACC,OAAV,CAAkBC,MAAzB,8BAAmDwC,CAAnD,QAA9B,C,UAEe1C,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 .\n\n/**\n * Report builder selectors\n *\n * @module core_reportbuilder/local/selectors\n * @copyright 2021 Paul Holden \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 settingsSorting: '[data-region=\"settings-sorting\"]',\n audiencesContainer: '[data-region=\"audiences\"]',\n audienceFormContainer: '[data-region=\"audience-form-container\"]',\n audienceCard: '[data-region=\"audience-card\"]',\n audienceForm: '[data-region=\"audience-form\"]',\n audienceEmptyMessage: '[data-region=no-instances-message]',\n audienceDescription: '[data-region=audience-description]',\n audienceNotSavedLabel: '[data-region=audience-not-saved]',\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 reportToggleColumnSort: '[data-action=\"report-toggle-column-sorting\"]',\n reportToggleColumnSortDirection: '[data-action=\"report-toggle-sort-direction\"]',\n sidebarSearch: '[data-action=\"sidebar-search\"]',\n toggleEditPreview: '[data-action=\"toggle-edit-preview\"]',\n audienceAdd: '[data-action=\"add-audience\"]',\n audienceEdit: '[data-action=\"edit-audience\"]',\n audienceDelete: '[data-action=\"delete-audience\"]',\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"} \ No newline at end of file +{"version":3,"sources":["../../src/local/selectors.js"],"names":["SELECTORS","regions","report","reportTable","columnHeader","filterButtonLabel","filtersForm","sidebarMenu","sidebarCard","settingsConditions","activeConditions","activeCondition","settingsFilters","activeFilters","activeFilter","settingsSorting","audiencesContainer","audienceFormContainer","audienceCard","audienceForm","audienceEmptyMessage","audienceDescription","audienceNotSavedLabel","settingsCardView","actions","reportActionPopup","reportCreate","reportEdit","reportDelete","reportAddColumn","reportRemoveColumn","reportAddCondition","reportRemoveCondition","reportAddFilter","reportRemoveFilter","reportToggleColumnSort","reportToggleColumnSortDirection","sidebarSearch","toggleEditPreview","audienceAdd","audienceEdit","audienceDelete","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,CAcLC,eAAe,CAAE,oCAdZ,CAeLC,kBAAkB,CAAE,6BAff,CAgBLC,qBAAqB,CAAE,2CAhBlB,CAiBLC,YAAY,CAAE,iCAjBT,CAkBLC,YAAY,CAAE,iCAlBT,CAmBLC,oBAAoB,CAAE,oCAnBjB,CAoBLC,mBAAmB,CAAE,oCApBhB,CAqBLC,qBAAqB,CAAE,kCArBlB,CAsBLC,gBAAgB,CAAE,qCAtBb,CADK,CAyBdC,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,sBAAsB,CAAE,gDAXnB,CAYLC,+BAA+B,CAAE,gDAZ5B,CAaLC,aAAa,CAAE,kCAbV,CAcLC,iBAAiB,CAAE,uCAdd,CAeLC,WAAW,CAAE,gCAfR,CAgBLC,YAAY,CAAE,iCAhBT,CAiBLC,cAAc,CAAE,mCAjBX,CAzBK,CAAlB,CAqDAzC,CAAS,CAAC0C,SAAV,CAAsB,SAAAC,CAAQ,kBAAO3C,CAAS,CAACC,OAAV,CAAkBC,MAAzB,8BAAmDyC,CAAnD,QAA9B,C,UAEe3C,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 .\n\n/**\n * Report builder selectors\n *\n * @module core_reportbuilder/local/selectors\n * @copyright 2021 Paul Holden \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 settingsSorting: '[data-region=\"settings-sorting\"]',\n audiencesContainer: '[data-region=\"audiences\"]',\n audienceFormContainer: '[data-region=\"audience-form-container\"]',\n audienceCard: '[data-region=\"audience-card\"]',\n audienceForm: '[data-region=\"audience-form\"]',\n audienceEmptyMessage: '[data-region=no-instances-message]',\n audienceDescription: '[data-region=audience-description]',\n audienceNotSavedLabel: '[data-region=audience-not-saved]',\n settingsCardView: '[data-region=\"settings-cardview\"]',\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 reportToggleColumnSort: '[data-action=\"report-toggle-column-sorting\"]',\n reportToggleColumnSortDirection: '[data-action=\"report-toggle-sort-direction\"]',\n sidebarSearch: '[data-action=\"sidebar-search\"]',\n toggleEditPreview: '[data-action=\"toggle-edit-preview\"]',\n audienceAdd: '[data-action=\"add-audience\"]',\n audienceEdit: '[data-action=\"edit-audience\"]',\n audienceDelete: '[data-action=\"delete-audience\"]',\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"} \ No newline at end of file diff --git a/reportbuilder/amd/src/editor.js b/reportbuilder/amd/src/editor.js index 2d801ec4153..80262f8a4b8 100644 --- a/reportbuilder/amd/src/editor.js +++ b/reportbuilder/amd/src/editor.js @@ -32,6 +32,7 @@ import {init as columnsEditorInit} from 'core_reportbuilder/local/editor/columns import {init as conditionsEditorInit} from 'core_reportbuilder/local/editor/conditions'; import {init as filtersEditorInit} from 'core_reportbuilder/local/editor/filters'; import {init as sortingEditorInit} from 'core_reportbuilder/local/editor/sorting'; +import {init as cardviewEditorInit} from 'core_reportbuilder/local/editor/card_view'; import {getReport} from 'core_reportbuilder/local/repository/reports'; let initialized = false; @@ -44,6 +45,7 @@ export const init = () => { conditionsEditorInit(initialized); filtersEditorInit(initialized); sortingEditorInit(initialized); + cardviewEditorInit(initialized); // Ensure we only add our listeners once (can be called multiple times by mustache template). if (initialized) { diff --git a/reportbuilder/amd/src/local/editor/card_view.js b/reportbuilder/amd/src/local/editor/card_view.js new file mode 100644 index 00000000000..19ebf9c047f --- /dev/null +++ b/reportbuilder/amd/src/local/editor/card_view.js @@ -0,0 +1,71 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Report builder card view editor + * + * @module core_reportbuilder/local/editor/card_view + * @copyright 2021 Mikel Martín + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +"use strict"; + +import DynamicForm from 'core_form/dynamicform'; +import {add as addToast} from 'core/toast'; +import {get_string as getString} from "core/str"; +import {subscribe as subscribe} from 'core/pubsub'; +import Notification from 'core/notification'; +import * as reportEvents from 'core_reportbuilder/local/events'; +import * as reportSelectors from 'core_reportbuilder/local/selectors'; + +let cardViewForm = null; + +/** + * Initialise card view form, must be called on each init because the form container is re-created when switching editor modes + */ +const initCardViewForm = () => { + const cardViewFormContainer = document.querySelector(reportSelectors.regions.settingsCardView); + if (!cardViewFormContainer) { + return; + } + cardViewForm = new DynamicForm(cardViewFormContainer, '\\core_reportbuilder\\form\\card_view'); + + cardViewForm.addEventListener(cardViewForm.events.FORM_SUBMITTED, (event) => { + event.preventDefault(); + + getString('cardviewsettingssaved', 'core_reportbuilder') + .then(addToast) + .catch(Notification.exception); + }); +}; + +/** + * Initialise module + * + * @param {Boolean} initialized Ensure we only add our listeners once + */ +export const init = (initialized) => { + initCardViewForm(); + if (initialized) { + return; + } + + // Update form each time a column is added or removed to the custom report. + subscribe(reportEvents.publish.reportColumnsUpdated, () => { + const reportElement = document.querySelector(reportSelectors.regions.report); + cardViewForm.load({reportid: reportElement.dataset.reportId}); + }); +}; diff --git a/reportbuilder/amd/src/local/selectors.js b/reportbuilder/amd/src/local/selectors.js index 0baa51c87fd..227680553df 100644 --- a/reportbuilder/amd/src/local/selectors.js +++ b/reportbuilder/amd/src/local/selectors.js @@ -52,6 +52,7 @@ const SELECTORS = { audienceEmptyMessage: '[data-region=no-instances-message]', audienceDescription: '[data-region=audience-description]', audienceNotSavedLabel: '[data-region=audience-not-saved]', + settingsCardView: '[data-region="settings-cardview"]', }, actions: { reportActionPopup: '[data-action="report-action-popup"]', diff --git a/reportbuilder/classes/external/custom_report_card_view_exporter.php b/reportbuilder/classes/external/custom_report_card_view_exporter.php new file mode 100644 index 00000000000..cf1db527823 --- /dev/null +++ b/reportbuilder/classes/external/custom_report_card_view_exporter.php @@ -0,0 +1,90 @@ +. + +declare(strict_types=1); + +namespace core_reportbuilder\external; + +use core_reportbuilder\form\card_view; +use renderer_base; +use core\external\exporter; +use core_reportbuilder\local\report\base; + +/** + * Custom report card view exporter class + * + * @package core_reportbuilder + * @copyright 2021 Mikel Martín + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class custom_report_card_view_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 [ + 'form' => [ + 'type' => PARAM_RAW, + 'optional' => true, + ], + 'helpicon' => [ + 'type' => PARAM_RAW, + 'optional' => true, + ], + ]; + } + + /** + * 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']; + + $reportid = $report->get_report_persistent()->get('id'); + + $reportsettings = $report->get_settings_values(); + $cardviewsettings = [ + 'showfirsttitle' => $reportsettings['cardview_showfirsttitle'] ?? 0, + 'visiblecolumns' => $reportsettings['cardview_visiblecolumns'] ?? 1, + ]; + $cardviewform = new card_view(null, null, 'post', '', [], true, + array_merge(['reportid' => $reportid], $cardviewsettings)); + $cardviewform->set_data_for_dynamic_submission(); + + return [ + 'form' => $cardviewform->render(), + 'helpicon' => $output->help_icon('cardview', 'core_reportbuilder'), + ]; + } +} diff --git a/reportbuilder/classes/external/custom_report_exporter.php b/reportbuilder/classes/external/custom_report_exporter.php index 8eedcb07606..8fb9026f1a0 100644 --- a/reportbuilder/classes/external/custom_report_exporter.php +++ b/reportbuilder/classes/external/custom_report_exporter.php @@ -93,6 +93,7 @@ class custom_report_exporter extends persistent_exporter { 'conditions' => ['type' => custom_report_conditions_exporter::read_properties_definition()], 'filters' => ['type' => custom_report_filters_exporter::read_properties_definition()], 'sorting' => ['type' => custom_report_columns_sorting_exporter::read_properties_definition()], + 'cardview' => ['type' => custom_report_card_view_exporter::read_properties_definition()], 'filtersapplied' => ['type' => PARAM_INT], 'filterspresent' => ['type' => PARAM_BOOL], 'filtersform' => [ @@ -147,6 +148,8 @@ class custom_report_exporter extends persistent_exporter { $filters = (array) $filtersexporter->export($output); $sortingexporter = new custom_report_columns_sorting_exporter(null, ['report' => $report]); $sorting = (array) $sortingexporter->export($output); + $cardviewexporter = new custom_report_card_view_exporter(null, ['report' => $report]); + $cardview = (array) $cardviewexporter->export($output); } return [ @@ -155,6 +158,7 @@ class custom_report_exporter extends persistent_exporter { 'conditions' => $conditions ?? [], 'filters' => $filters ?? [], 'sorting' => $sorting ?? [], + 'cardview' => $cardview ?? [], 'filtersapplied' => $report->get_applied_filter_count(), 'filterspresent' => $filterspresent, 'filtersform' => $filtersform, diff --git a/reportbuilder/classes/form/card_view.php b/reportbuilder/classes/form/card_view.php new file mode 100644 index 00000000000..4c5183947cb --- /dev/null +++ b/reportbuilder/classes/form/card_view.php @@ -0,0 +1,135 @@ +. + +declare(strict_types=1); + +namespace core_reportbuilder\form; + +use context; +use moodle_url; +use core_form\dynamic_form; +use core_reportbuilder\manager; +use core_reportbuilder\permission; +use core_reportbuilder\local\report\base; +use core_reportbuilder\local\models\report; +use core_reportbuilder\local\models\column; + +/** + * Card view dynamic form + * + * @package core_reportbuilder + * @copyright 2021 Mikel Martín + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class card_view extends dynamic_form { + + /** + * Return instance of the report using the card view form + * + * @return base + */ + private function get_report(): base { + $report = new report($this->optional_param('reportid', 0, PARAM_INT)); + $parameters = (array) json_decode($this->optional_param('parameters', '', PARAM_RAW)); + + return manager::get_report_from_persistent($report, $parameters); + } + + /** + * Returns context where this form is used + * + * @return context + */ + protected function get_context_for_dynamic_submission(): context { + return $this->get_report()->get_context(); + } + + /** + * Check if current user has access to this form, otherwise throw exception + */ + public function check_access_for_dynamic_submission(): void { + permission::require_can_edit_report($this->get_report()->get_report_persistent()); + } + + /** + * Store the conditions values and operators + * + * @return bool + */ + public function process_dynamic_submission(): bool { + $values = $this->get_data(); + + $settings = [ + 'cardview_showfirsttitle' => (int)$values->showfirsttitle, + // Minimum value for 'cardview_visiblecolumns' should be 1. + 'cardview_visiblecolumns' => max((int)$values->visiblecolumns, 1) + ]; + return $this->get_report()->set_settings_values($settings); + } + + /** + * Load in existing data as form defaults + */ + public function set_data_for_dynamic_submission(): void { + $report = $this->get_report(); + $totalcolumns = column::count_records(['reportid' => $report->get_report_persistent()->get('id')]); + $settings = $report->get_settings_values(); + $defaults = [ + // Maximum value for 'cardview_visiblecolumns' should be the report total number of columns. + 'visiblecolumns' => min($settings['cardview_visiblecolumns'] ?? 1, $totalcolumns), + 'showfirsttitle' => $settings['cardview_showfirsttitle'] ?? 0, + ]; + $this->set_data(array_merge($defaults, $this->_ajaxformdata)); + } + + /** + * Returns url to set in $PAGE->set_url() when form is being rendered or submitted via AJAX + * + * @return moodle_url + */ + protected function get_page_url_for_dynamic_submission(): moodle_url { + return new moodle_url('/reportbuilder/edit.php'); + } + + /** + * Card view form definition + */ + public function definition(): void { + $mform = $this->_form; + + $reportid = $this->optional_param('reportid', 0, PARAM_INT); + $totalcolumns = column::count_records(['reportid' => $reportid]); + $visibilityarray = []; + // Generate select options from 1 to report total number of columns. + for ($i = 1; $i <= max($totalcolumns, 1); $i++) { + $visibilityarray[$i] = $i; + } + + $mform->addElement('hidden', 'reportid'); + $mform->setType('reportid', PARAM_INT); + + $mform->addElement('select', 'visiblecolumns', get_string('cardviewvisiblecolumns', 'core_reportbuilder'), + $visibilityarray); + $mform->setType('visiblecolumns', PARAM_INT); + + $mform->addElement('selectyesno', 'showfirsttitle', get_string('cardviewfirstcolumntitle', 'core_reportbuilder')); + $mform->setType('showfirsttitle', PARAM_BOOL); + + $mform->disable_form_change_checker(); + + $this->add_action_buttons(false); + } +} diff --git a/reportbuilder/classes/local/models/report.php b/reportbuilder/classes/local/models/report.php index 2499952b40f..facfd167118 100644 --- a/reportbuilder/classes/local/models/report.php +++ b/reportbuilder/classes/local/models/report.php @@ -65,6 +65,11 @@ class report extends persistent { 'null' => NULL_ALLOWED, 'default' => null, ], + 'settingsdata' => [ + 'type' => PARAM_RAW, + 'null' => NULL_ALLOWED, + 'default' => null, + ], 'contextid' => [ 'type' => PARAM_INT, 'default' => static function(): int { diff --git a/reportbuilder/classes/local/report/base.php b/reportbuilder/classes/local/report/base.php index 1bc150219c1..368f1c4fa42 100644 --- a/reportbuilder/classes/local/report/base.php +++ b/reportbuilder/classes/local/report/base.php @@ -496,6 +496,31 @@ abstract class base { return (array) json_decode($conditions); } + /** + * Set the settings values of the report + * + * @param array $values + * @return bool + */ + final public function set_settings_values(array $values): bool { + $currentsettings = $this->get_settings_values(); + $settings = array_merge($currentsettings, $values); + $this->report->set('settingsdata', json_encode($settings)) + ->save(); + return true; + } + + /** + * Get the settings values of the report + * + * @return array + */ + final public function get_settings_values(): array { + $settings = (string) $this->report->get('settingsdata'); + + return (array) json_decode($settings); + } + /** * Adds a filter to the report * diff --git a/reportbuilder/templates/local/settings/area.mustache b/reportbuilder/templates/local/settings/area.mustache index 92d755e4e40..28ff3609c5c 100644 --- a/reportbuilder/templates/local/settings/area.mustache +++ b/reportbuilder/templates/local/settings/area.mustache @@ -106,6 +106,16 @@ {{/body}} {{/ core_reportbuilder/toggle_card }} + {{< core_reportbuilder/toggle_card }} + {{$collapsed}}collapsed{{/collapsed}} + {{$id}}settingscardview{{/id}} + {{$header}}{{#str}} cardview, core_reportbuilder {{/str}}{{/header}} + {{$helpicon}}{{{cardview.helpicon}}}{{/helpicon}} + {{$body}} + {{> core_reportbuilder/local/settings/card_view}} + {{/body}} + {{/ core_reportbuilder/toggle_card }} + diff --git a/reportbuilder/templates/local/settings/card_view.mustache b/reportbuilder/templates/local/settings/card_view.mustache new file mode 100644 index 00000000000..144c8e5f607 --- /dev/null +++ b/reportbuilder/templates/local/settings/card_view.mustache @@ -0,0 +1,32 @@ +{{! + 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 . +}} +{{! + @template core_reportbuilder/local/settings/card_view + + Template for custom report card view settings area + + Example context (json): + { + "form": "form" + } +}} + +
+ {{#cardview}} + {{{form}}} + {{/cardview}} +
diff --git a/reportbuilder/tests/behat/audience.feature b/reportbuilder/tests/behat/audience.feature index a3662cd2605..fb8c7ea90e9 100644 --- a/reportbuilder/tests/behat/audience.feature +++ b/reportbuilder/tests/behat/audience.feature @@ -31,14 +31,14 @@ Feature: Configure access to reports based on intended audience Then I click on "Add audience 'Manually added users'" "link" And I should see "Added audience 'Manually added users'" And I set the field "Add users manually" to "User 1,User 3" - And I press "Save changes" + # It would be better to reference the report table directly, but we can't because of MDL-73011. + And I click on "Save changes" "button" in the "[role=tabpanel].active" "css_element" And I should see "Audience saved" And I should see "User 1" And I should not see "User 2" And I should see "User 3" And I should not see "Add an audience to this report" And I click on the "Access" dynamic tab - # It would be better to reference the report table directly, but we can't because of MDL-73011. And I should see "User 1" in the "[role=tabpanel].active" "css_element" And I should not see "User 2" in the "[role=tabpanel].active" "css_element" And I should see "User 3" in the "[role=tabpanel].active" "css_element" @@ -55,12 +55,12 @@ Feature: Configure access to reports based on intended audience When I click on "Add audience 'Assigned system role'" "link" And I should see "Added audience 'Assigned system role'" And I set the field "Select a role" to "Test role" - And I press "Save changes" + # It would be better to reference the report table directly, but we can't because of MDL-73011. + And I click on "Save changes" "button" in the "[role=tabpanel].active" "css_element" Then I should see "Audience saved" And I should see "Test role" And I should not see "Add an audience to this report" And I click on the "Access" dynamic tab - # It would be better to reference the report table directly, but we can't because of MDL-73011. And I should not see "User 1" in the "[role=tabpanel].active" "css_element" And I should see "User 2" in the "[role=tabpanel].active" "css_element" And I should not see "User 3" in the "[role=tabpanel].active" "css_element" @@ -77,12 +77,12 @@ Feature: Configure access to reports based on intended audience When I click on "Add audience 'Member of cohort'" "link" And I should see "Added audience 'Member of cohort'" And I set the field "Select members from cohort" to "Cohort1" - And I press "Save changes" + # It would be better to reference the report table directly, but we can't because of MDL-73011. + And I click on "Save changes" "button" in the "[role=tabpanel].active" "css_element" Then I should see "Audience saved" And I should see "Cohort1" And I should not see "Add an audience to this report" And I click on the "Access" dynamic tab - # It would be better to reference the report table directly, but we can't because of MDL-73011. And I should not see "User 1" in the "[role=tabpanel].active" "css_element" And I should not see "User 2" in the "[role=tabpanel].active" "css_element" And I should see "User 3" in the "[role=tabpanel].active" "css_element" @@ -98,7 +98,8 @@ Feature: Configure access to reports based on intended audience Given I am on the "My report" "reportbuilder > Editor" page logged in as "admin" And I click on the "Audience" dynamic tab And I click on "Add audience 'All users'" "link" - And I press "Save changes" + # It would be better to reference the report table directly, but we can't because of MDL-73011. + And I click on "Save changes" "button" in the "[role=tabpanel].active" "css_element" When I click on "Delete audience 'All users'" "button" And I click on "Delete" "button" in the "Delete audience 'All users'" "dialogue" Then I should see "Deleted audience 'All users'" @@ -112,12 +113,12 @@ Feature: Configure access to reports based on intended audience And I should see "Add an audience to this report" Then I click on "Add audience 'Manually added users'" "link" And I set the field "Add users manually" to "User 1,User 3" - And I press "Save changes" + # It would be better to reference the report table directly, but we can't because of MDL-73011. + And I click on "Save changes" "button" in the "[role=tabpanel].active" "css_element" And I press "Edit audience 'Manually added users'" And I set the field "Add users manually" to "User 2" - And I press "Save changes" + And I click on "Save changes" "button" in the "[role=tabpanel].active" "css_element" And I should see "Audience saved" - # It would be better to reference the report table directly, but we can't because of MDL-73011. And I should not see "User 1" in the "[role=tabpanel].active" "css_element" And I should see "User 2" in the "[role=tabpanel].active" "css_element" And I should not see "User 3" in the "[role=tabpanel].active" "css_element" @@ -155,7 +156,8 @@ Feature: Configure access to reports based on intended audience And I should see "Add an audience to this report" Then I click on "Add audience 'Manually added users'" "link" And I set the field "Add users manually" to "User 1" - And I press "Save changes" + # It would be better to reference the report table directly, but we can't because of MDL-73011. + And I click on "Save changes" "button" in the "[role=tabpanel].active" "css_element" And I log out And I log in as "user1" And I navigate to "Reports > Report builder > Custom reports" in site administration @@ -199,7 +201,8 @@ Feature: Configure access to reports based on intended audience And I should see "Add an audience to this report" Then I click on "Add audience 'Manually added users'" "link" And I set the field "Add users manually" to "User 1" - And I press "Save changes" + # It would be better to reference the report table directly, but we can't because of MDL-73011. + And I click on "Save changes" "button" in the "[role=tabpanel].active" "css_element" And I log out And I log in as "user1" And I navigate to "Reports > Report builder > Custom reports" in site administration diff --git a/theme/boost/scss/moodle/reportbuilder.scss b/theme/boost/scss/moodle/reportbuilder.scss index ebfd21192f9..d46d375b95a 100644 --- a/theme/boost/scss/moodle/reportbuilder.scss +++ b/theme/boost/scss/moodle/reportbuilder.scss @@ -156,6 +156,16 @@ div[data-region="settings-sorting"] .list-group-item span[data-drag-type="move"] .icon { vertical-align: middle; } + div[data-region="settings-cardview"] form { + .col-md-3, + .col-md-9 { + flex: 1 1; + max-width: initial; + } + div[data-fieldtype="submit"] { + flex-basis: auto; + } + } } /* Add button styles when a toggle button is active. */ diff --git a/theme/boost/style/moodle.css b/theme/boost/style/moodle.css index d6c90c550d9..65f650f0280 100644 --- a/theme/boost/style/moodle.css +++ b/theme/boost/style/moodle.css @@ -20746,6 +20746,14 @@ div.editor_atto_toolbar button .icon { .reportbuilder-sidebar-settings div[data-region="settings-sorting"] .list-group-item span[data-drag-type="move"] .icon { vertical-align: middle; } +.reportbuilder-sidebar-settings div[data-region="settings-cardview"] form .col-md-3, +.reportbuilder-sidebar-settings div[data-region="settings-cardview"] form .col-md-9 { + flex: 1 1; + max-width: initial; } + +.reportbuilder-sidebar-settings div[data-region="settings-cardview"] form div[data-fieldtype="submit"] { + flex-basis: auto; } + /* Add button styles when a toggle button is active. */ .reportbuilder-wrapper button.btn-outline-secondary[data-toggle="collapse"]:not(.collapsed), .reportbuilder-wrapper .dropdown.show button.btn-outline-secondary[data-toggle="dropdown"] { diff --git a/theme/classic/style/moodle.css b/theme/classic/style/moodle.css index f6016ae3a96..e0c9929e2e3 100644 --- a/theme/classic/style/moodle.css +++ b/theme/classic/style/moodle.css @@ -20692,6 +20692,14 @@ div.editor_atto_toolbar button .icon { .reportbuilder-sidebar-settings div[data-region="settings-sorting"] .list-group-item span[data-drag-type="move"] .icon { vertical-align: middle; } +.reportbuilder-sidebar-settings div[data-region="settings-cardview"] form .col-md-3, +.reportbuilder-sidebar-settings div[data-region="settings-cardview"] form .col-md-9 { + flex: 1 1; + max-width: initial; } + +.reportbuilder-sidebar-settings div[data-region="settings-cardview"] form div[data-fieldtype="submit"] { + flex-basis: auto; } + /* Add button styles when a toggle button is active. */ .reportbuilder-wrapper button.btn-outline-secondary[data-toggle="collapse"]:not(.collapsed), .reportbuilder-wrapper .dropdown.show button.btn-outline-secondary[data-toggle="dropdown"] { diff --git a/version.php b/version.php index fd8a130bf19..7d29c105aec 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2021110800.02; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2021110800.03; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes. $release = '4.0dev+ (Build: 20211106)'; // Human-friendly version name