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.
This commit is contained in:
Isaac Connor committed 2026-08-28 12:52:04 -04:00
1 parent cbd68bb323
commit df6f48334f
1 file changed
+15 -9
+15 -9
View File
@@ -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);
}