Revert "feat: grouped query builder with $upIf/$downIf condition groups"
This reverts commit 99b59070a2.
This commit is contained in:
parent
99b59070a2
commit
5328471229
|
|
@ -50,17 +50,6 @@ pub struct Response {
|
|||
pub fn evaluate(query: &Value, response: &Response) -> Result<bool> {
|
||||
match query {
|
||||
Value::Object(map) => {
|
||||
// $upIf / $downIf — named groups, $downIf takes precedence
|
||||
if map.contains_key("$upIf") || map.contains_key("$downIf") {
|
||||
if let Some(down) = map.get("$downIf") {
|
||||
if evaluate(down, response).unwrap_or(false) { return Ok(false); }
|
||||
}
|
||||
if let Some(up) = map.get("$upIf") {
|
||||
return evaluate(up, response);
|
||||
}
|
||||
return Ok(true); // only $downIf set and didn't match → up
|
||||
}
|
||||
|
||||
// $and / $or / $not
|
||||
if let Some(and) = map.get("$and") {
|
||||
let Value::Array(clauses) = and else { bail!("$and expects array") };
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm text-gray-400 mb-1.5">Conditions <span class="text-gray-600">(optional)</span></label>
|
||||
<p class="text-xs text-gray-600 mb-3">Define up/down conditions. <span class="text-red-400/70">Down if</span> takes priority over <span class="text-green-400/70">Up if</span>. Leave empty to use default (status < 400).</p>
|
||||
<label class="block text-sm text-gray-400 mb-1.5">Query Conditions <span class="text-gray-600">(optional)</span></label>
|
||||
<p class="text-xs text-gray-600 mb-3">Define when this monitor should be considered "up". Defaults to status < 400.</p>
|
||||
<div id="query-builder"></div>
|
||||
</div>
|
||||
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
if (!requireAuth()) throw 'auth';
|
||||
|
||||
let currentQuery = null;
|
||||
const qb = new GroupedQueryBuilder(document.getElementById('query-builder'), (q) => {
|
||||
const qb = new QueryBuilder(document.getElementById('query-builder'), (q) => {
|
||||
currentQuery = q;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -304,150 +304,3 @@ class QueryBuilder {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Grouped Query Builder ─────────────────────────────────────────────────────
|
||||
// Two named condition groups: "Up if..." and "Down if..."
|
||||
// $downIf takes precedence over $upIf. Both optional.
|
||||
|
||||
class GroupedQueryBuilder {
|
||||
constructor(container, onChange) {
|
||||
this.container = container;
|
||||
this.onChange = onChange;
|
||||
this.groups = {
|
||||
upIf: new QueryBuilder(null, () => this._emit()),
|
||||
downIf: new QueryBuilder(null, () => this._emit()),
|
||||
};
|
||||
this.groups.upIf.rules = [];
|
||||
this.groups.downIf.rules = [];
|
||||
this._render();
|
||||
}
|
||||
|
||||
_emit() {
|
||||
this.onChange?.(this.getQuery());
|
||||
}
|
||||
|
||||
getQuery() {
|
||||
const up = this.groups.upIf.rules.length ? this.groups.upIf.getQuery() : null;
|
||||
const down = this.groups.downIf.rules.length ? this.groups.downIf.getQuery() : null;
|
||||
if (!up && !down) return null;
|
||||
const q = {};
|
||||
if (up) q.$upIf = up;
|
||||
if (down) q.$downIf = down;
|
||||
return q;
|
||||
}
|
||||
|
||||
setQuery(query) {
|
||||
if (!query || typeof query !== 'object') return;
|
||||
if (query.$upIf) { this.groups.upIf.setQuery(query.$upIf); }
|
||||
if (query.$downIf) { this.groups.downIf.setQuery(query.$downIf); }
|
||||
this._render();
|
||||
}
|
||||
|
||||
_render() {
|
||||
this.container.innerHTML = `
|
||||
<div class="space-y-4">
|
||||
<div id="gqb-upif"></div>
|
||||
<div id="gqb-downif"></div>
|
||||
<div class="mt-3 p-3 bg-gray-950 rounded border border-gray-800">
|
||||
<div class="flex items-center justify-between mb-1">
|
||||
<span class="text-xs text-gray-500 font-mono">Query JSON</span>
|
||||
<button id="gqb-copy" class="text-xs text-blue-400 hover:text-blue-300">Copy</button>
|
||||
</div>
|
||||
<pre id="gqb-preview" class="text-xs text-gray-300 font-mono whitespace-pre-wrap overflow-x-auto"></pre>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
this._renderGroup('upIf', this.container.querySelector('#gqb-upif'), '🟢 Up if', 'text-green-400', 'border-green-900/50');
|
||||
this._renderGroup('downIf', this.container.querySelector('#gqb-downif'), '🔴 Down if', 'text-red-400', 'border-red-900/50');
|
||||
this._updatePreview();
|
||||
|
||||
this.container.querySelector('#gqb-copy').addEventListener('click', () => {
|
||||
const q = this.getQuery();
|
||||
navigator.clipboard.writeText(JSON.stringify(q ?? {}, null, 2));
|
||||
const btn = this.container.querySelector('#gqb-copy');
|
||||
btn.textContent = 'Copied!';
|
||||
setTimeout(() => btn.textContent = 'Copy', 1500);
|
||||
});
|
||||
}
|
||||
|
||||
_renderGroup(key, el, label, labelClass, borderClass) {
|
||||
const group = this.groups[key];
|
||||
const hasRules = group.rules.length > 0;
|
||||
|
||||
el.innerHTML = `
|
||||
<div class="rounded border ${borderClass} bg-gray-900/50 p-3">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<span class="text-sm font-medium ${labelClass}">${label}</span>
|
||||
<div class="flex items-center gap-3">
|
||||
${hasRules ? `
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="text-xs text-gray-500">Match</span>
|
||||
<select id="gqb-logic-${key}" class="bg-gray-800 border border-gray-700 text-gray-200 text-xs rounded px-2 py-1 focus:border-blue-500 focus:outline-none">
|
||||
<option value="$and" ${group.logic === '$and' ? 'selected' : ''}>ALL</option>
|
||||
<option value="$or" ${group.logic === '$or' ? 'selected' : ''}>ANY</option>
|
||||
</select>
|
||||
</div>
|
||||
` : ''}
|
||||
<button id="gqb-add-${key}" class="text-xs text-blue-400 hover:text-blue-300">+ Add condition</button>
|
||||
${hasRules ? `<button id="gqb-clear-${key}" class="text-xs text-gray-600 hover:text-gray-400">Clear</button>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
${hasRules ? `
|
||||
<div id="gqb-rules-${key}" class="space-y-2">
|
||||
${group.rules.map((rule, i) => group._renderRule(rule, i)).join('')}
|
||||
</div>
|
||||
` : `<p class="text-xs text-gray-600 italic">No conditions — defaults to status < 400</p>`}
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Bind logic toggle
|
||||
const logicSel = el.querySelector(`#gqb-logic-${key}`);
|
||||
if (logicSel) {
|
||||
logicSel.addEventListener('change', (e) => {
|
||||
group.logic = e.target.value;
|
||||
this._renderGroup(key, el, label, labelClass, borderClass);
|
||||
this._updatePreview();
|
||||
this._emit();
|
||||
});
|
||||
}
|
||||
|
||||
// Bind add
|
||||
el.querySelector(`#gqb-add-${key}`).addEventListener('click', () => {
|
||||
group.rules.push(group._emptyRule());
|
||||
this._renderGroup(key, el, label, labelClass, borderClass);
|
||||
this._updatePreview();
|
||||
this._emit();
|
||||
});
|
||||
|
||||
// Bind clear
|
||||
const clearBtn = el.querySelector(`#gqb-clear-${key}`);
|
||||
if (clearBtn) {
|
||||
clearBtn.addEventListener('click', () => {
|
||||
group.rules = [];
|
||||
this._renderGroup(key, el, label, labelClass, borderClass);
|
||||
this._updatePreview();
|
||||
this._emit();
|
||||
});
|
||||
}
|
||||
|
||||
// Bind rule events — wrap onChange to re-render preview
|
||||
if (hasRules) {
|
||||
group.container = el.querySelector(`#gqb-rules-${key}`);
|
||||
group.onChange = () => { this._updatePreview(); this._emit(); };
|
||||
el.querySelectorAll('.qb-rule').forEach((ruleEl, i) => {
|
||||
group._bindRuleEvents(ruleEl, i);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_updatePreview() {
|
||||
const q = this.getQuery();
|
||||
const pre = this.container.querySelector('#gqb-preview');
|
||||
if (pre) {
|
||||
pre.innerHTML = q
|
||||
? escapeHtml(JSON.stringify(q, null, 2))
|
||||
: '<span class="text-gray-600">No conditions — defaults to status < 400</span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,13 +86,6 @@ export function evaluate(query: unknown, ctx: EvalContext): boolean {
|
|||
|
||||
const q = query as Record<string, unknown>;
|
||||
|
||||
// $upIf / $downIf — named condition groups, $downIf takes precedence
|
||||
if ("$upIf" in q || "$downIf" in q) {
|
||||
if ("$downIf" in q && evaluate(q.$downIf, ctx)) return false;
|
||||
if ("$upIf" in q) return evaluate(q.$upIf, ctx);
|
||||
return true; // only $downIf set and it didn't match → up
|
||||
}
|
||||
|
||||
// $and
|
||||
if ("$and" in q) {
|
||||
const clauses = q.$and;
|
||||
|
|
|
|||
Loading…
Reference in New Issue