From df6f48334fb51b73fbb1abcbaf0d215bebc2dad7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 28 Aug 2026 12:52:04 -0400 Subject: [PATCH] fix: translate filter attrs for the API without rewriting the form a3b1ab558 translated DateTime to StartDateTime by assigning to attr.value, which edits the filter form itself, not just the query being built. The form is submitted whenever a filter changes, and montagereview.php decides whether the range terms are already there with if (!$filter->has_term('DateTime', '>=')) (montagereview.php:193) if (!$filter->has_term('DateTime', '<=')) (montagereview.php:196) so a form arriving with StartDateTime failed both checks and PHP appended a second pair. Selecting a monitor left the filter bar showing four date terms. Verified against a live install by submitting the same filter both ways: terms as StartDateTime -> 7 terms, 4 date terms terms as DateTime -> 5 terms, 2 date terms Compute the API attribute into a local and leave attr.value alone. The pre-existing Monitor to MonitorId rewrite moves too: it has the same shape and montagereview.php has its own 'Monitor' handling. The URL is unchanged, so the DateTime fix still holds; only the side effect on the submitted form is gone. --- web/skins/classic/views/js/montagereview.js | 24 +++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/web/skins/classic/views/js/montagereview.js b/web/skins/classic/views/js/montagereview.js index 92ffb9849..a02e11d69 100644 --- a/web/skins/classic/views/js/montagereview.js +++ b/web/skins/classic/views/js/montagereview.js @@ -1316,23 +1316,29 @@ function loadEventData(e) { const op_name = 'filter[Query][terms]['+found[1]+'][op]'; const op = this.form.elements[op_name]; if (attr) { - if (attr.value==='Monitor') attr.value='MonitorId'; - // DateTime is a filter-engine pseudo-attribute, not an Events - // column: Filter.php resolves 'DateTime' and 'StartDateTime' to the - // same E.StartDateTime. The API takes column names, and silently - // ignores a term it cannot resolve rather than erroring, so leaving - // it as DateTime returns every event ever instead of the window. - if (attr.value==='DateTime') attr.value='StartDateTime'; + // Translate to the column names the API expects, in a local rather + // than by writing back to attr.value. The form is submitted when a + // filter changes, and montagereview.php decides whether the range + // terms are already present by looking for 'DateTime'; a form left + // holding 'StartDateTime' came back with a second, duplicate pair. + // Filter.php resolves 'DateTime' and 'StartDateTime' to the same + // E.StartDateTime, so only the query needs the column name. The + // API silently ignores a term it cannot resolve rather than + // erroring, which is why an untranslated DateTime returned every + // event ever instead of the requested window. + let apiAttr = attr.value; + if (apiAttr === 'Monitor') apiAttr = 'MonitorId'; + if (apiAttr === 'DateTime') apiAttr = 'StartDateTime'; let urlVal = val; // Normalize date/time values to YYYY-MM-DD HH:mm:ss for the API URL. // Locale formats using / as separator break the URL path. - if (/Date|Time/.test(attr.value)) { + if (/Date|Time/.test(apiAttr)) { const m = moment(val); if (m.isValid()) { urlVal = m.format('YYYY-MM-DD HH:mm:ss'); } } - url += '/'+attr.value+' '+op.value+':'+encodeURIComponent(urlVal); + url += '/'+apiAttr+' '+op.value+':'+encodeURIComponent(urlVal); } else { console.warn('No attr for '+attr_name); }