From a415dab32099fdc70e30fa0abed541365493b622 Mon Sep 17 00:00:00 2001 From: nate Date: Wed, 8 Apr 2026 14:03:52 +0400 Subject: [PATCH] improve query presentation --- apps/web/src/dashboard/query-builder.js | 42 +++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/apps/web/src/dashboard/query-builder.js b/apps/web/src/dashboard/query-builder.js index 44354d0..9161475 100644 --- a/apps/web/src/dashboard/query-builder.js +++ b/apps/web/src/dashboard/query-builder.js @@ -205,7 +205,7 @@ class QueryBuilder { Query JSON -
${query ? escapeHtml(JSON.stringify(query, null, 2)) : 'No conditions set'}
+
${query ? escapeHtml(formatQueryJson(query)) : 'No conditions set'}
`; @@ -230,7 +230,7 @@ class QueryBuilder { this.container.querySelector('#qb-copy').addEventListener('click', () => { const q = this.getQuery(); - navigator.clipboard.writeText(q ? JSON.stringify(q, null, 2) : '{}'); + navigator.clipboard.writeText(q ? formatQueryJson(q) : '{}'); const btn = this.container.querySelector('#qb-copy'); btn.textContent = 'Copied!'; setTimeout(() => { btn.textContent = 'Copy'; }, 1500); @@ -326,7 +326,43 @@ class QueryBuilder { const q = this.getQuery(); const preview = this.container.querySelector('#qb-preview'); if (preview) { - preview.textContent = q ? JSON.stringify(q, null, 2) : 'No conditions set'; + preview.textContent = q ? formatQueryJson(q) : 'No conditions set'; } } } + +// Compact-but-readable JSON formatter. Inlines any subtree that fits on a single +// line within MAX_INLINE chars; otherwise breaks across lines with 2-space indent. +const MAX_INLINE = 60; + +function formatQueryJson(value, indent = 0) { + const inline = inlineForm(value); + if (inline.length + indent <= MAX_INLINE) return inline; + if (Array.isArray(value)) { + if (value.length === 0) return '[]'; + const pad = ' '.repeat(indent + 2); + const close = ' '.repeat(indent); + const items = value.map(v => pad + formatQueryJson(v, indent + 2)); + return '[\n' + items.join(',\n') + '\n' + close + ']'; + } + if (value && typeof value === 'object') { + const entries = Object.entries(value); + if (entries.length === 0) return '{}'; + const pad = ' '.repeat(indent + 2); + const close = ' '.repeat(indent); + const items = entries.map(([k, v]) => pad + JSON.stringify(k) + ': ' + formatQueryJson(v, indent + 2 + JSON.stringify(k).length + 2)); + return '{\n' + items.join(',\n') + '\n' + close + '}'; + } + return JSON.stringify(value); +} + +function inlineForm(value) { + if (value === null || typeof value !== 'object') return JSON.stringify(value); + if (Array.isArray(value)) { + if (value.length === 0) return '[]'; + return '[ ' + value.map(inlineForm).join(', ') + ' ]'; + } + const entries = Object.entries(value); + if (entries.length === 0) return '{}'; + return '{ ' + entries.map(([k, v]) => JSON.stringify(k) + ': ' + inlineForm(v)).join(', ') + ' }'; +}