Add custom status badge formatting and row highlighting to site KPI table with color-coded visual indicators for different health states
Browse files
panel_app/kpi_health_check_panel.py
CHANGED
|
@@ -465,6 +465,73 @@ site_kpi_table = pn.widgets.Tabulator(
|
|
| 465 |
height=520, sizing_mode="stretch_width", layout="fit_data_table"
|
| 466 |
)
|
| 467 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 468 |
_set_tabulator_pagination(site_summary_table, page_size=50)
|
| 469 |
_set_tabulator_pagination(multirat_summary_table, page_size=50)
|
| 470 |
_set_tabulator_pagination(top_anomalies_table, page_size=50)
|
|
|
|
| 465 |
height=520, sizing_mode="stretch_width", layout="fit_data_table"
|
| 466 |
)
|
| 467 |
|
| 468 |
+
try:
|
| 469 |
+
site_kpi_table.text_align = {
|
| 470 |
+
"status": "center",
|
| 471 |
+
"bad_days_recent": "center",
|
| 472 |
+
"max_streak_recent": "center",
|
| 473 |
+
"baseline_median": "right",
|
| 474 |
+
"recent_median": "right",
|
| 475 |
+
}
|
| 476 |
+
site_kpi_table.widths = {
|
| 477 |
+
"status": 170,
|
| 478 |
+
"KPI": 260,
|
| 479 |
+
"bad_days_recent": 140,
|
| 480 |
+
"max_streak_recent": 160,
|
| 481 |
+
}
|
| 482 |
+
|
| 483 |
+
site_kpi_table.formatters = {
|
| 484 |
+
"status": pn.io.JSCode(
|
| 485 |
+
"""
|
| 486 |
+
function format(cell, formatterParams, onRendered){
|
| 487 |
+
var v = cell.getValue();
|
| 488 |
+
var s = (v === null || v === undefined) ? '' : String(v);
|
| 489 |
+
var bg = '#455a64';
|
| 490 |
+
if(s === 'PERSISTENT_DEGRADED') bg = '#b71c1c';
|
| 491 |
+
else if(s === 'DEGRADED') bg = '#e53935';
|
| 492 |
+
else if(s === 'RESOLVED') bg = '#2e7d32';
|
| 493 |
+
else if(s === 'NO_DATA') bg = '#616161';
|
| 494 |
+
else if(s === 'OK') bg = '#1565c0';
|
| 495 |
+
|
| 496 |
+
onRendered(function(){
|
| 497 |
+
try {
|
| 498 |
+
var rowEl = cell.getRow().getElement();
|
| 499 |
+
if(rowEl){
|
| 500 |
+
rowEl.style.borderLeft = '0px solid transparent';
|
| 501 |
+
rowEl.style.backgroundColor = '';
|
| 502 |
+
if(s === 'PERSISTENT_DEGRADED'){
|
| 503 |
+
rowEl.style.borderLeft = '6px solid #b71c1c';
|
| 504 |
+
rowEl.style.backgroundColor = '#ffebee';
|
| 505 |
+
} else if(s === 'DEGRADED'){
|
| 506 |
+
rowEl.style.borderLeft = '6px solid #e53935';
|
| 507 |
+
rowEl.style.backgroundColor = '#fff5f5';
|
| 508 |
+
} else if(s === 'RESOLVED'){
|
| 509 |
+
rowEl.style.borderLeft = '6px solid #2e7d32';
|
| 510 |
+
rowEl.style.backgroundColor = '#f1f8e9';
|
| 511 |
+
} else if(s === 'NO_DATA'){
|
| 512 |
+
rowEl.style.borderLeft = '6px solid #616161';
|
| 513 |
+
rowEl.style.backgroundColor = '#f5f5f5';
|
| 514 |
+
}
|
| 515 |
+
}
|
| 516 |
+
|
| 517 |
+
var cellEl = cell.getElement();
|
| 518 |
+
if(cellEl){
|
| 519 |
+
cellEl.style.padding = '0px';
|
| 520 |
+
cellEl.style.textAlign = 'center';
|
| 521 |
+
cellEl.innerHTML = "<span style='display:inline-block; padding:2px 10px; border-radius:999px; font-weight:700; font-size:12px; color:#fff; background-color:" + bg + ";'>" + s + "</span>";
|
| 522 |
+
}
|
| 523 |
+
} catch (e) {
|
| 524 |
+
}
|
| 525 |
+
});
|
| 526 |
+
|
| 527 |
+
return s;
|
| 528 |
+
}
|
| 529 |
+
"""
|
| 530 |
+
)
|
| 531 |
+
}
|
| 532 |
+
except Exception: # noqa: BLE001
|
| 533 |
+
pass
|
| 534 |
+
|
| 535 |
_set_tabulator_pagination(site_summary_table, page_size=50)
|
| 536 |
_set_tabulator_pagination(multirat_summary_table, page_size=50)
|
| 537 |
_set_tabulator_pagination(top_anomalies_table, page_size=50)
|