diff --git a/apps/monitor/src/query.rs b/apps/monitor/src/query.rs index be00d4a..93f005d 100644 --- a/apps/monitor/src/query.rs +++ b/apps/monitor/src/query.rs @@ -14,17 +14,10 @@ pub struct Response { pub fn evaluate(query: &Value, response: &Response) -> Result { match query { + Value::Array(clauses) => { + return Ok(clauses.iter().all(|c| evaluate(c, response).unwrap_or(false))); + } Value::Object(map) => { - if let Some(consider) = map.get("$consider") { - let is_down = consider.as_str() == Some("down"); - let rest: serde_json::Map = map.iter() - .filter(|(k, _)| k.as_str() != "$consider") - .map(|(k, v)| (k.clone(), v.clone())) - .collect(); - let matches = evaluate(&Value::Object(rest), response).unwrap_or(false); - return Ok(if is_down { !matches } else { matches }); - } - if let Some(and) = map.get("$and") { let Value::Array(clauses) = and else { bail!("$and expects array") }; return Ok(clauses.iter().all(|c| evaluate(c, response).unwrap_or(false))); diff --git a/apps/web/src/dashboard/query-builder.js b/apps/web/src/dashboard/query-builder.js index b85228f..8e43dde 100644 --- a/apps/web/src/dashboard/query-builder.js +++ b/apps/web/src/dashboard/query-builder.js @@ -20,7 +20,7 @@ class QueryBuilder { this.container = container; this.onChange = onChange; this.logic = '$and'; - this.consider = 'up'; // 'up' | 'down' + this.invert = false; // true = wrap in $not (match = down) this.rules = this._defaultRules(); this.render(); // Notify the form that the default query is already populated, so submitting @@ -48,7 +48,7 @@ class QueryBuilder { .filter(Boolean); if (conditions.length === 0) return null; const base = conditions.length === 1 ? conditions[0] : { [this.logic]: conditions }; - if (this.consider === 'down') return { $consider: 'down', ...base }; + if (this.invert) return { $not: base }; return base; } @@ -92,13 +92,19 @@ class QueryBuilder { if (!query || typeof query !== 'object') { this.rules = this._defaultRules(); this.logic = '$and'; - this.consider = 'up'; + this.invert = false; this.render(); return; } - this.consider = query.$consider === 'down' ? 'down' : 'up'; - const q = Object.fromEntries(Object.entries(query).filter(([k]) => k !== '$consider')); + // Detect $not wrapper (inverted query = match means down) + let q = query; + if ('$not' in query && Object.keys(query).length === 1) { + this.invert = true; + q = query.$not; + } else { + this.invert = false; + } if ('$and' in q || '$or' in q) { this.logic = '$and' in q ? '$and' : '$or'; @@ -175,10 +181,10 @@ class QueryBuilder { this.container.innerHTML = `
- Consider - + + when