#!/usr/bin/env python3
"""V136 - Make V135 KPI banner clickable: opens inline modal with broken URLs detail
Modal: positioned fixed, shows top 10 broken with code/url/ms, dismissible by click outside or Escape.
"""
import sys
src, dst = sys.argv[1], sys.argv[2]
with open(src, "r", encoding="utf-8") as f:
c = f.read()
if "V136-HEALTH-MODAL" in c:
print("ALREADY", file=sys.stderr)
sys.exit(0)
# Change the span to add cursor:pointer and id + click handler. It's already id=v135-kpi-live
# Wrap in a click-capable element
# Find the span line
old_span = 'All-IA Hub · consolidation 84 dashboards'
new_span = 'All-IA Hub · consolidation 84 dashboards'
if old_span not in c:
print("span anchor missing", file=sys.stderr)
sys.exit(1)
c = c.replace(old_span, new_span, 1)
# Add modal HTML + JS logic. Insert modal markup at the END of the xnav div
anchor_xnav_close = '
🏥 Platform Health · Detail
Loading…
Loading…
Source: /api/screens-health.json · maintenu par cron ecosystem
''' + tabs_marker
if tabs_marker in c:
c = c.replace(tabs_marker, modal_html, 1)
# Add JS functions before the V135-KPI-BANNER IIFE
js_marker = "/* V135-KPI-BANNER: load screens-health summary"
js_add = '''/* V136-HEALTH-MODAL: show/hide drill-down modal with broken URL list */
function __v136ShowHealthModal(){
const modal = document.getElementById('v136-health-modal');
const content = document.getElementById('v136-modal-content');
const summary = document.getElementById('v136-modal-summary');
if (!modal || !content) return;
modal.style.display = 'flex';
content.textContent = 'Fetching /api/screens-health.json ...';
fetch('/api/screens-health.json', {cache: 'no-store'}).then(r => r.ok ? r.json() : null).then(d => {
if (!d || !d.counts) { content.textContent = 'Pas de data health disponible.'; return; }
const c = d.counts;
const total = d.total || 0;
summary.textContent = 'Scan ' + (d.generated_at || '') + ' · Total ' + total + ' URLs · UP ' + (c.UP||0) + ' · SLOW ' + (c.SLOW||0) + ' · BROKEN ' + (c.BROKEN||0) + ' · DOWN ' + (c.DOWN||0) + ' · PHANTOM ' + (c.PHANTOM||0);
const byUrl = d.by_url || {};
const broken = [];
const slow = [];
for (const url in byUrl) {
const info = byUrl[url];
if (info.status === 'BROKEN' || info.status === 'DOWN') broken.push({url, ...info});
else if (info.status === 'SLOW') slow.push({url, ...info});
}
broken.sort((a,b) => (b.code||0) - (a.code||0));
slow.sort((a,b) => (b.ms||0) - (a.ms||0));
let html = '';
if (broken.length) {
html += '