MDL-85001 reportbuilder: ensure report uniqueness in filters loader.

Where the same report exists multiple times on the page, ensure we
are still able to uniquely identify each via ID. Update the filters
module to ensure the filters form for each report is initialised.
This commit is contained in:
Paul Holden 2025-03-25 11:12:30 +00:00
parent b3931cdb95
commit 821336a9fc
No known key found for this signature in database
GPG Key ID: A81A96D6045F6164
6 changed files with 11 additions and 10 deletions

View File

@ -5,6 +5,6 @@ define("core_reportbuilder/filters",["exports","core/event_dispatcher","core/fra
* @module core_reportbuilder/filters
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending),_templates=_interopRequireDefault(_templates),_dynamicform=_interopRequireDefault(_dynamicform),reportEvents=_interopRequireWildcard(reportEvents),reportSelectors=_interopRequireWildcard(reportSelectors);const setFilterButtonCount=async(reportElement,filterCount)=>{const filterButtonLabel=reportElement.querySelector(reportSelectors.regions.filterButtonLabel);filterButtonLabel.textContent=filterCount>0?await(0,_str.getString)("filtersappliedx","core_reportbuilder",filterCount):await(0,_str.getString)("filters","moodle")};_exports.init=(reportId,contextId)=>{const reportElement=document.querySelector(reportSelectors.forReport(reportId)),filterFormContainer=reportElement.querySelector(reportSelectors.regions.filtersForm);if(filterFormContainer.dataset.initialized)return;filterFormContainer.dataset.initialized=!0;const filterForm=new _dynamicform.default(filterFormContainer,"\\core_reportbuilder\\form\\filter");filterForm.addEventListener(filterForm.events.FORM_SUBMITTED,(event=>{event.preventDefault(),(0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{},reportElement),setFilterButtonCount(reportElement,event.detail),(0,_str.getString)("filtersapplied","core_reportbuilder").then(_toast.add).catch(_notification.default.exception)})),filterForm.addEventListener(filterForm.events.NOSUBMIT_BUTTON_PRESSED,(event=>{event.preventDefault();const pendingPromise=new _pending.default("core_reportbuilder/filters:reset"),reportParameters=reportElement.dataset.parameter;(0,_filters.resetFilters)(reportId,reportParameters).then((()=>(0,_str.getString)("filtersreset","core_reportbuilder"))).then(_toast.add).then((()=>(0,_fragment.loadFragment)("core_reportbuilder","filters_form",contextId,{reportid:reportId,parameters:reportParameters}))).then(((html,js)=>(_templates.default.replaceNodeContents(filterFormContainer,html,js),(0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{},reportElement),setFilterButtonCount(reportElement,0),pendingPromise.resolve()))).catch(_notification.default.exception)})),document.querySelector("#region-main").style.overflowX="visible"}}));
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending),_templates=_interopRequireDefault(_templates),_dynamicform=_interopRequireDefault(_dynamicform),reportEvents=_interopRequireWildcard(reportEvents),reportSelectors=_interopRequireWildcard(reportSelectors);const setFilterButtonCount=async(reportElement,filterCount)=>{const filterButtonLabel=reportElement.querySelector(reportSelectors.regions.filterButtonLabel);filterButtonLabel.textContent=filterCount>0?await(0,_str.getString)("filtersappliedx","core_reportbuilder",filterCount):await(0,_str.getString)("filters","moodle")};_exports.init=(reportElementId,contextId)=>{const reportElement=document.getElementById(reportElementId),filterFormContainer=reportElement.querySelector(reportSelectors.regions.filtersForm);if(filterFormContainer.dataset.initialized)return;filterFormContainer.dataset.initialized=!0;const filterForm=new _dynamicform.default(filterFormContainer,"\\core_reportbuilder\\form\\filter");filterForm.addEventListener(filterForm.events.FORM_SUBMITTED,(event=>{event.preventDefault(),(0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{},reportElement),setFilterButtonCount(reportElement,event.detail),(0,_str.getString)("filtersapplied","core_reportbuilder").then(_toast.add).catch(_notification.default.exception)})),filterForm.addEventListener(filterForm.events.NOSUBMIT_BUTTON_PRESSED,(event=>{event.preventDefault();const pendingPromise=new _pending.default("core_reportbuilder/filters:reset"),{reportId:reportId,reportParameters:reportParameters}=reportElement.dataset;(0,_filters.resetFilters)(reportId,reportParameters).then((()=>(0,_str.getString)("filtersreset","core_reportbuilder"))).then(_toast.add).then((()=>(0,_fragment.loadFragment)("core_reportbuilder","filters_form",contextId,{reportid:reportId,parameters:reportParameters}))).then(((html,js)=>(_templates.default.replaceNodeContents(filterFormContainer,html,js),(0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{},reportElement),setFilterButtonCount(reportElement,0),pendingPromise.resolve()))).catch(_notification.default.exception)})),document.querySelector("#region-main").style.overflowX="visible"}}));
//# sourceMappingURL=filters.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -53,11 +53,11 @@ const setFilterButtonCount = async(reportElement, filterCount) => {
* Initialise module for given report
*
* @method
* @param {Number} reportId
* @param {String} reportElementId
* @param {Number} contextId
*/
export const init = (reportId, contextId) => {
const reportElement = document.querySelector(reportSelectors.forReport(reportId));
export const init = (reportElementId, contextId) => {
const reportElement = document.getElementById(reportElementId);
const filterFormContainer = reportElement.querySelector(reportSelectors.regions.filtersForm);
// Ensure we only add our listeners once (can be called multiple times by mustache template).
@ -86,8 +86,8 @@ export const init = (reportId, contextId) => {
event.preventDefault();
const pendingPromise = new Pending('core_reportbuilder/filters:reset');
const reportParameters = reportElement.dataset.parameter;
const {reportId, reportParameters} = reportElement.dataset;
resetFilters(reportId, reportParameters)
.then(() => getString('filtersreset', 'core_reportbuilder'))
.then(addToast)

View File

@ -95,10 +95,11 @@
}}
<h2 class="sr-only">{{#str}} editor, core_reportbuilder {{/str}}</h2>
<div class="reportbuilder-report"
id="reportbuilder-report-{{uniqid}}"
data-region="core_reportbuilder/report"
data-report-id="{{id}}"
data-report-type="{{type}}"
data-parameter="[]"
data-report-parameters=""
{{#editmode}}data-editing{{/editmode}}
{{#attributes}}{{name}}="{{value}}" {{/attributes}}>
<div class="reportbuilder-wrapper d-flex flex-column flex-lg-row">

View File

@ -21,7 +21,6 @@
Example context (json):
{
"id": 3,
"contextid": 1,
"filtersapplied": 3,
"filtersform": "form"
@ -51,6 +50,6 @@
{{#js}}
require(['core_reportbuilder/filters'], function(filters) {
filters.init({{id}}, {{contextid}});
filters.init('reportbuilder-report-{{uniqid}}', {{contextid}});
});
{{/js}}

View File

@ -35,10 +35,11 @@
}
}}
<div class="reportbuilder-report {{classes}}"
id="reportbuilder-report-{{uniqid}}"
data-region="core_reportbuilder/report"
data-report-id="{{id}}"
data-report-type="{{type}}"
data-parameter="{{parameters}}"
data-report-parameters="{{parameters}}"
{{#attributes}}{{name}}="{{value}}" {{/attributes}}>
<div class="reportbuilder-wrapper">
{{#filterspresent}}