@@ -349,7 +349,7 @@ function renderUnifiSwitches(unifiSwitches, dataUpdated) {
return `
return `
<div class="link-host-panel" id="panel- ${ CSS . escape ( swName ) } ">
<div class="link-host-panel" id="panel- ${ CSS . escape ( swName ) } ">
<div class="link-host-title" data-action="toggle-panel">
<div class="link-host-title" data-action="toggle-panel" role="button" tabindex="0" aria-expanded="true" >
<span class="link-host-name"> ${ escHtml ( swName ) } </span>
<span class="link-host-name"> ${ escHtml ( swName ) } </span>
<span class="link-host-ip"> ${ escHtml ( sw . ip || '' ) } </span>
<span class="link-host-ip"> ${ escHtml ( sw . ip || '' ) } </span>
<span class="link-host-upd"> ${ escHtml ( sw . model || '' ) } ${ updStr ? ' · ' + updStr : '' } ${ poeLoad } </span>
<span class="link-host-upd"> ${ escHtml ( sw . model || '' ) } ${ updStr ? ' · ' + updStr : '' } ${ poeLoad } </span>
@@ -366,8 +366,11 @@ function renderUnifiSwitches(unifiSwitches, dataUpdated) {
// ── Panel collapse / expand ───────────────────────────────────────
// ── Panel collapse / expand ───────────────────────────────────────
function togglePanel ( panel ) {
function togglePanel ( panel ) {
panel . classList . toggle ( 'collapsed' ) ;
panel . classList . toggle ( 'collapsed' ) ;
const btn = panel . querySelector ( '.panel-toggle ' ) ;
const isCollapsed = panel . classList . contains ( 'collapsed ' ) ;
if ( btn ) btn . textContent = panel . classList . contains ( 'collapsed' ) ? '[+]' : '[– ]' ;
const btn = panel . querySelector ( '.panel-toggle' ) ;
const title = panel . querySelector ( '.link-host-title' ) ;
if ( btn ) btn . textContent = isCollapsed ? '[+]' : '[– ]' ;
if ( title ) title . setAttribute ( 'aria-expanded' , isCollapsed ? 'false' : 'true' ) ;
const id = panel . id ;
const id = panel . id ;
if ( id ) {
if ( id ) {
const collapsed = JSON . parse ( sessionStorage . getItem ( 'linksCollapsed' ) || '{}' ) ;
const collapsed = JSON . parse ( sessionStorage . getItem ( 'linksCollapsed' ) || '{}' ) ;
@@ -383,8 +386,10 @@ function restoreCollapseState() {
if ( ! panel ) continue ;
if ( ! panel ) continue ;
if ( isCollapsed ) {
if ( isCollapsed ) {
panel . classList . add ( 'collapsed' ) ;
panel . classList . add ( 'collapsed' ) ;
const btn = panel . querySelector ( '.panel-toggle' ) ;
const btn = panel . querySelector ( '.panel-toggle' ) ;
if ( btn ) btn . textContent = '[+]' ;
const title = panel . querySelector ( '.link-host-title' ) ;
if ( btn ) btn . textContent = '[+]' ;
if ( title ) title . setAttribute ( 'aria-expanded' , 'false' ) ;
}
}
}
}
}
}
@@ -463,12 +468,12 @@ function renderLinks(data) {
const sample = Object . values ( ifaces ) [ 0 ] || { } ;
const sample = Object . values ( ifaces ) [ 0 ] || { } ;
const ip = sample . host _ip || '' ;
const ip = sample . host _ip || '' ;
const updStr = data . updated
const updStr = data . updated
? new Date ( data . updated . replace ( ' UTC' , 'Z' ) . replace ( ' ' , 'T' ) ) . toLocaleTimeString ( )
? new Date ( _toIso ( data . updated ) ) . toLocaleTimeString ( )
: '' ;
: '' ;
parts . push ( `
parts . push ( `
<div class="link-host-panel" id="panel- ${ CSS . escape ( hostname ) } ">
<div class="link-host-panel" id="panel- ${ CSS . escape ( hostname ) } ">
<div class="link-host-title" data-action="toggle-panel">
<div class="link-host-title" data-action="toggle-panel" role="button" tabindex="0" aria-expanded="true" >
<span class="link-host-name"> ${ escHtml ( hostname ) } </span>
<span class="link-host-name"> ${ escHtml ( hostname ) } </span>
<span class="link-host-ip"> ${ escHtml ( ip ) } </span>
<span class="link-host-ip"> ${ escHtml ( ip ) } </span>
<span class="link-host-upd"> ${ updStr } </span>
<span class="link-host-upd"> ${ updStr } </span>
@@ -498,8 +503,10 @@ function applyLinksSearch() {
function collapseAll ( ) {
function collapseAll ( ) {
document . querySelectorAll ( '.link-host-panel' ) . forEach ( p => {
document . querySelectorAll ( '.link-host-panel' ) . forEach ( p => {
p . classList . add ( 'collapsed' ) ;
p . classList . add ( 'collapsed' ) ;
const btn = p . querySelector ( '.panel-toggle' ) ;
const btn = p . querySelector ( '.panel-toggle' ) ;
if ( btn ) btn . textContent = '[+]' ;
const title = p . querySelector ( '.link-host-title' ) ;
if ( btn ) btn . textContent = '[+]' ;
if ( title ) title . setAttribute ( 'aria-expanded' , 'false' ) ;
} ) ;
} ) ;
sessionStorage . setItem ( 'linksCollapsed' , JSON . stringify (
sessionStorage . setItem ( 'linksCollapsed' , JSON . stringify (
Object . fromEntries ( [ ... document . querySelectorAll ( '.link-host-panel' ) ] . map ( p => [ p . id , true ] ) )
Object . fromEntries ( [ ... document . querySelectorAll ( '.link-host-panel' ) ] . map ( p => [ p . id , true ] ) )
@@ -509,8 +516,10 @@ function collapseAll() {
function expandAll ( ) {
function expandAll ( ) {
document . querySelectorAll ( '.link-host-panel' ) . forEach ( p => {
document . querySelectorAll ( '.link-host-panel' ) . forEach ( p => {
p . classList . remove ( 'collapsed' ) ;
p . classList . remove ( 'collapsed' ) ;
const btn = p . querySelector ( '.panel-toggle' ) ;
const btn = p . querySelector ( '.panel-toggle' ) ;
if ( btn ) btn . textContent = '[– ]' ;
const title = p . querySelector ( '.link-host-title' ) ;
if ( btn ) btn . textContent = '[– ]' ;
if ( title ) title . setAttribute ( 'aria-expanded' , 'true' ) ;
} ) ;
} ) ;
sessionStorage . setItem ( 'linksCollapsed' , '{}' ) ;
sessionStorage . setItem ( 'linksCollapsed' , '{}' ) ;
}
}
@@ -575,6 +584,12 @@ document.addEventListener('click', e => {
if ( e . target . closest ( '[data-action="expand-all"]' ) ) { expandAll ( ) ; return ; }
if ( e . target . closest ( '[data-action="expand-all"]' ) ) { expandAll ( ) ; return ; }
} ) ;
} ) ;
document . addEventListener ( 'keydown' , e => {
if ( e . key !== 'Enter' && e . key !== ' ' ) return ;
const toggleTitle = e . target . closest ( '[data-action="toggle-panel"]' ) ;
if ( toggleTitle ) { e . preventDefault ( ) ; togglePanel ( toggleTitle . closest ( '.link-host-panel' ) ) ; }
} ) ;
document . getElementById ( 'links-search' ) ? . addEventListener ( 'input' , applyLinksSearch ) ;
document . getElementById ( 'links-search' ) ? . addEventListener ( 'input' , applyLinksSearch ) ;
< / script >
< / script >
{% endblock %}
{% endblock %}