Integrate TDS v1.2 lt.* APIs throughout app
Lint / Python (flake8) (push) Failing after 58s
Lint / JS (eslint) (push) Successful in 7s
Security / Python Security (bandit) (push) Failing after 44s
Test / Python Tests (pytest) (push) Successful in 1m24s
Lint / Notify on failure (push) Successful in 2s
Lint / Deploy (push) Has been skipped

- app.js: replace raw fetch/escHtml/fmtRelTime with lt.api, lt.escHtml, lt.time.ago; modal open/close via lt.modal; add _toIso() for timestamp normalisation
- index.html: data-action="refresh", data-duration pills, lt.autoRefresh.start, remove local fmtRelTime
- suppressions.html: lt.api.post/delete, data-dur pill delegation
- base.html: user avatar with initials, admin badge, lt.keys.on('r') replaces manual keydown handler
- base.css: add dot-*, chip, row-state aliases so apps can use unprefixed class names

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-18 23:46:44 -04:00
parent bb6393e35b
commit 293edd674e
5 changed files with 123 additions and 161 deletions
+20 -19
View File
@@ -51,11 +51,11 @@
<div class="lt-form-group">
<label class="lt-label">Duration</label>
<div class="duration-pills">
<button type="button" class="pill" onclick="setDur(30, this)">30 min</button>
<button type="button" class="pill" onclick="setDur(60, this)">1 hr</button>
<button type="button" class="pill" onclick="setDur(240, this)">4 hr</button>
<button type="button" class="pill" onclick="setDur(480, this)">8 hr</button>
<button type="button" class="pill pill-manual active" onclick="setDur(null, this)">Manual ∞</button>
<button type="button" class="pill" data-dur="30">30 min</button>
<button type="button" class="pill" data-dur="60">1 hr</button>
<button type="button" class="pill" data-dur="240">4 hr</button>
<button type="button" class="pill" data-dur="480">8 hr</button>
<button type="button" class="pill pill-manual active" data-dur="">Manual ∞</button>
</div>
<input type="hidden" id="s-expires" name="expires_minutes" value="">
<div class="lt-field-hint" id="s-dur-hint">Persists until manually removed.</div>
@@ -207,30 +207,31 @@
reason: form.reason.value,
expires_minutes: form.expires_minutes.value ? parseInt(form.expires_minutes.value) : null,
};
const resp = await fetch('/api/suppressions', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(payload),
});
const data = await resp.json();
if (data.success) {
try {
await lt.api.post('/api/suppressions', payload);
showToast('Suppression applied', 'success');
setTimeout(() => location.reload(), 800);
} else {
showToast(data.error || 'Error', 'error');
} catch (err) {
showToast(err.message || 'Error', 'error');
}
}
async function removeSuppression(id) {
if (!confirm('Remove this suppression?')) return;
const resp = await fetch(`/api/suppressions/${id}`, {method:'DELETE'});
const data = await resp.json();
if (data.success) {
try {
await lt.api.delete(`/api/suppressions/${id}`);
document.getElementById(`sup-row-${id}`)?.remove();
showToast('Suppression removed', 'success');
} else {
showToast(data.error || 'Failed to remove suppression', 'error');
} catch (err) {
showToast(err.message || 'Failed to remove suppression', 'error');
}
}
document.addEventListener('click', e => {
const pill = e.target.closest('.pill[data-dur]');
if (!pill) return;
const val = pill.dataset.dur;
setDur(val ? parseInt(val) : null, pill);
});
</script>
{% endblock %}