modules/admin-core, modules/admin-full: implement display support for dnsmasq dhcpv6...
[project/luci.git] / modules / admin-full / luasrc / view / admin_status / index.htm
1 <%#
2 LuCI - Lua Configuration Interface
3 Copyright 2008 Steven Barth <steven@midlink.org>
4 Copyright 2008-2011 Jo-Philipp Wich <xm@subsignal.org>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10         http://www.apache.org/licenses/LICENSE-2.0
11
12 $Id$
13
14 -%>
15
16 <%
17         require "luci.fs"
18         require "luci.tools.status"
19
20         local has_ipv6 = luci.fs.access("/proc/net/ipv6_route")
21         local has_dhcp = luci.fs.access("/etc/config/dhcp")
22         local has_wifi = luci.fs.stat("/etc/config/wireless")
23               has_wifi = has_wifi and has_wifi.size > 0
24
25         if luci.http.formvalue("status") == "1" then
26                 local ntm = require "luci.model.network".init()
27                 local wan = ntm:get_wannet()
28                 local wan6 = ntm:get_wan6net()
29
30                 local _, _, memtotal, memcached, membuffers, memfree = luci.sys.sysinfo()
31
32                 local conn_count = tonumber((
33                         luci.sys.exec("wc -l /proc/net/nf_conntrack") or
34                         luci.sys.exec("wc -l /proc/net/ip_conntrack") or
35                         ""):match("%d+")) or 0
36
37                 local conn_max = tonumber((
38                         luci.sys.exec("sysctl net.nf_conntrack_max") or
39                         luci.sys.exec("sysctl net.ipv4.netfilter.ip_conntrack_max") or
40                         ""):match("%d+")) or 4096
41
42                 local rv = {
43                         uptime     = luci.sys.uptime(),
44                         localtime  = os.date(),
45                         loadavg    = { luci.sys.loadavg() },
46                         memtotal   = memtotal,
47                         memcached  = memcached,
48                         membuffers = membuffers,
49                         memfree    = memfree,
50                         connmax    = conn_max,
51                         conncount  = conn_count,
52                         leases     = luci.tools.status.dhcp_leases(),
53                         leases6    = luci.tools.status.dhcp6_leases(),
54                         wifinets   = luci.tools.status.wifi_networks()
55                 }
56
57                 if wan then
58                         rv.wan = {
59                                 ipaddr  = wan:ipaddr(),
60                                 gwaddr  = wan:gwaddr(),
61                                 netmask = wan:netmask(),
62                                 dns     = wan:dnsaddrs(),
63                                 expires = wan:expires(),
64                                 uptime  = wan:uptime(),
65                                 proto   = wan:proto(),
66                                 ifname  = wan:ifname(),
67                                 link    = wan:adminlink()
68                         }
69                 end
70
71                 if wan6 then
72                         rv.wan6 = {
73                                 ip6addr = wan6:ip6addr(),
74                                 gw6addr = wan6:gw6addr(),
75                                 dns     = wan6:dns6addrs(),
76                                 uptime  = wan6:uptime(),
77                                 ifname  = wan6:ifname(),
78                                 link    = wan6:adminlink()
79                         }
80                 end
81
82                 luci.http.prepare_content("application/json")
83                 luci.http.write_json(rv)
84
85                 return
86         end
87
88         local system, model = luci.sys.sysinfo()
89 -%>
90
91 <%+header%>
92
93 <script type="text/javascript" src="<%=resource%>/cbi.js"></script>
94 <script type="text/javascript">//<![CDATA[
95         function progressbar(v, m)
96         {
97                 var vn = parseInt(v) || 0;
98                 var mn = parseInt(m) || 100;
99                 var pc = Math.floor((100 / mn) * vn);
100
101                 return String.format(
102                         '<div style="width:200px; position:relative; border:1px solid #999999">' +
103                                 '<div style="background-color:#CCCCCC; width:%d%%; height:15px">' +
104                                         '<div style="position:absolute; left:0; top:0; text-align:center; width:100%%; color:#000000">' +
105                                                 '<small>%s / %s (%d%%)</small>' +
106                                         '</div>' +
107                                 '</div>' +
108                         '</div>', pc, v, m, pc
109                 );
110         }
111
112         var wifidevs = <%=luci.http.write_json(netdevs)%>;
113         var arptable = <%=luci.http.write_json(arpcache)%>;
114
115         XHR.poll(5, '<%=REQUEST_URI%>', { status: 1 },
116                 function(x, info)
117                 {
118                         var si = document.getElementById('wan4_i');
119                         var ss = document.getElementById('wan4_s');
120                         var ifc = info.wan;
121
122                         if (ifc && ifc.ifname && ifc.proto != 'none')
123                         {
124                                 var s = String.format(
125                                         '<strong><%:Type%>: </strong>%s<br />' +
126                                         '<strong><%:Address%>: </strong>%s<br />' +
127                                         '<strong><%:Netmask%>: </strong>%s<br />' +
128                                         '<strong><%:Gateway%>: </strong>%s<br />',
129                                                 ifc.proto,
130                                                 (ifc.ipaddr) ? ifc.ipaddr : '0.0.0.0',
131                                                 (ifc.netmask && ifc.netmask != ifc.ipaddr) ? ifc.netmask : '255.255.255.255',
132                                                 (ifc.gwaddr) ? ifc.gwaddr : '0.0.0.0'
133                                 );
134
135                                 for (var i = 0; i < ifc.dns.length; i++)
136                                 {
137                                         s += String.format(
138                                                 '<strong><%:DNS%> %d: </strong>%s<br />',
139                                                 i + 1, ifc.dns[i]
140                                         );
141                                 }
142
143                                 if (ifc.expires > -1)
144                                 {
145                                         s += String.format(
146                                                 '<strong><%:Expires%>: </strong>%t<br />',
147                                                 ifc.expires
148                                         );
149                                 }
150
151                                 if (ifc.uptime > 0)
152                                 {
153                                         s += String.format(
154                                                 '<strong><%:Connected%>: </strong>%t<br />',
155                                                 ifc.uptime
156                                         );
157                                 }
158
159                                 ss.innerHTML = String.format('<small>%s</small>', s);
160                                 si.innerHTML = String.format(
161                                         '<img src="<%=resource%>/icons/ethernet.png" />' +
162                                         '<br /><small><a href="%s">%s</a></small>',
163                                                 ifc.link, ifc.ifname
164                                 );
165                         }
166                         else
167                         {
168                                 si.innerHTML = '<img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small>';
169                                 ss.innerHTML = '<em><%:Not connected%></em>';
170                         }
171
172                         <% if has_ipv6 then %>
173                         var si6 = document.getElementById('wan6_i');
174                         var ss6 = document.getElementById('wan6_s');
175                         var ifc6 = info.wan6;
176
177                         if (ifc6 && ifc6.ifname && ifc6.proto != 'none')
178                         {
179                                 var s = String.format(
180                                         '<strong><%:Address%>: </strong>%s<br />' +
181                                         '<strong><%:Gateway%>: </strong>%s<br />',
182                                                 (ifc6.ip6addr) ? ifc6.ip6addr : '::',
183                                                 (ifc6.gw6addr) ? ifc6.gw6addr : '::'
184                                 );
185
186                                 for (var i = 0; i < ifc6.dns.length; i++)
187                                 {
188                                         s += String.format(
189                                                 '<strong><%:DNS%> %d: </strong>%s<br />',
190                                                 i + 1, ifc6.dns[i]
191                                         );
192                                 }
193
194                                 if (ifc6.uptime > 0)
195                                 {
196                                         s += String.format(
197                                                 '<strong><%:Connected%>: </strong>%t<br />',
198                                                 ifc6.uptime
199                                         );
200                                 }
201
202                                 ss6.innerHTML = String.format('<small>%s</small>', s);
203                                 si6.innerHTML = String.format(
204                                         '<img src="<%=resource%>/icons/ethernet.png" />' +
205                                         '<br /><small><a href="%s">%s</a></small>',
206                                                 ifc6.link, ifc6.ifname
207                                 );
208                         }
209                         else
210                         {
211                                 si6.innerHTML = '<img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small>';
212                                 ss6.innerHTML = '<em><%:Not connected%></em>';
213                         }
214                         <% end %>
215
216                         <% if has_dhcp then %>
217                         var ls = document.getElementById('lease_status_table');
218                         if (ls)
219                         {
220                                 /* clear all rows */
221                                 while( ls.rows.length > 1 )
222                                         ls.rows[0].parentNode.deleteRow(1);
223
224                                 for( var i = 0; i < info.leases.length; i++ )
225                                 {
226                                         var timestr;
227
228                                         if (info.leases[i].expires <= 0)
229                                                 timestr = '<em><%:expired%></em>';
230                                         else
231                                                 timestr = String.format('%t', info.leases[i].expires);
232
233                                         var tr = ls.rows[0].parentNode.insertRow(-1);
234                                                 tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
235
236                                         tr.insertCell(-1).innerHTML = info.leases[i].hostname ? info.leases[i].hostname : '?';
237                                         tr.insertCell(-1).innerHTML = info.leases[i].ipaddr;
238                                         tr.insertCell(-1).innerHTML = info.leases[i].macaddr;
239                                         tr.insertCell(-1).innerHTML = timestr;
240                                 }
241
242                                 if( ls.rows.length == 1 )
243                                 {
244                                         var tr = ls.rows[0].parentNode.insertRow(-1);
245                                                 tr.className = 'cbi-section-table-row';
246
247                                         var td = tr.insertCell(-1);
248                                                 td.colSpan = 4;
249                                                 td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
250                                 }
251                         }
252
253                         var ls6 = document.getElementById('lease6_status_table');
254                         if (ls6 && info.leases6)
255                         {
256                                 ls6.parentNode.style.display = 'block';
257
258                                 /* clear all rows */
259                                 while( ls6.rows.length > 1 )
260                                         ls6.rows[0].parentNode.deleteRow(1);
261
262                                 for( var i = 0; i < info.leases6.length; i++ )
263                                 {
264                                         var timestr;
265
266                                         if (info.leases6[i].expires <= 0)
267                                                 timestr = '<em><%:expired%></em>';
268                                         else
269                                                 timestr = String.format('%t', info.leases6[i].expires);
270
271                                         var tr = ls6.rows[0].parentNode.insertRow(-1);
272                                                 tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
273
274                                         tr.insertCell(-1).innerHTML = info.leases6[i].hostname ? info.leases6[i].hostname : '?';
275                                         tr.insertCell(-1).innerHTML = info.leases6[i].ip6addr;
276                                         tr.insertCell(-1).innerHTML = info.leases6[i].duid;
277                                         tr.insertCell(-1).innerHTML = timestr;
278                                 }
279
280                                 if( ls6.rows.length == 1 )
281                                 {
282                                         var tr = ls6.rows[0].parentNode.insertRow(-1);
283                                                 tr.className = 'cbi-section-table-row';
284
285                                         var td = tr.insertCell(-1);
286                                                 td.colSpan = 4;
287                                                 td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
288                                 }
289                         }
290                         <% end %>
291
292                         <% if has_wifi then %>
293                         var assoclist = [ ];
294
295                         var ws = document.getElementById('wifi_status_table');
296                         if (ws)
297                         {
298                                 var wsbody = ws.rows[0].parentNode;
299                                 while (ws.rows.length > 0)
300                                         wsbody.deleteRow(0);
301
302                                 for (var didx = 0; didx < info.wifinets.length; didx++)
303                                 {
304                                         var dev = info.wifinets[didx];
305
306                                         var tr = wsbody.insertRow(-1);
307                                         var td;
308
309                                         td = tr.insertCell(-1);
310                                         td.width     = "33%";
311                                         td.innerHTML = dev.name;
312                                         td.style.verticalAlign = "top";
313
314                                         td = tr.insertCell(-1);
315
316                                         var s = '';
317
318                                         for (var nidx = 0; nidx < dev.networks.length; nidx++)
319                                         {
320                                                 var net = dev.networks[nidx];
321                                                 var is_assoc = (net.bssid != '00:00:00:00:00:00' && net.channel);
322
323                                                 var icon;
324                                                 if (!is_assoc)
325                                                         icon = "<%=resource%>/icons/signal-none.png";
326                                                 else if (net.quality == 0)
327                                                         icon = "<%=resource%>/icons/signal-0.png";
328                                                 else if (net.quality < 25)
329                                                         icon = "<%=resource%>/icons/signal-0-25.png";
330                                                 else if (net.quality < 50)
331                                                         icon = "<%=resource%>/icons/signal-25-50.png";
332                                                 else if (net.quality < 75)
333                                                         icon = "<%=resource%>/icons/signal-50-75.png";
334                                                 else
335                                                         icon = "<%=resource%>/icons/signal-75-100.png";
336
337                                                 s += String.format(
338                                                         '<table><tr><td style="text-align:center; width:32px; padding:3px">' +
339                                                                 '<img src="%s" title="<%:Signal%>: %d dBm / <%:Noise%>: %d dBm" />' +
340                                                                 '<br /><small>%d%%</small>' +
341                                                         '</td><td style="text-align:left; padding:3px"><small>' +
342                                                                 '<strong><%:SSID%>:</strong> <a href="%s">%h</a><br />' +
343                                                                 '<strong><%:Mode%>:</strong> %s<br />' +
344                                                                 '<strong><%:Channel%>:</strong> %d (%.3f <%:GHz%>)<br />' +
345                                                                 '<strong><%:Bitrate%>:</strong> %s <%:Mbit/s%><br />',
346                                                                 icon, net.signal, net.noise,
347                                                                 net.quality,
348                                                                 net.link, net.ssid,
349                                                                 net.mode,
350                                                                 net.channel, net.frequency,
351                                                                 net.bitrate || '?'
352                                                 );
353
354                                                 if (is_assoc)
355                                                 {
356                                                         s += String.format(
357                                                                 '<strong><%:BSSID%>:</strong> %s<br />' +
358                                                                 '<strong><%:Encryption%>:</strong> %s',
359                                                                         net.bssid,
360                                                                         net.encryption
361                                                         );
362                                                 }
363                                                 else
364                                                 {
365                                                         s += '<em><%:Wireless is disabled or not associated%></em>';
366                                                 }
367
368                                                 s += '</small></td></tr></table>';
369
370                                                 for (var bssid in net.assoclist)
371                                                 {
372                                                         assoclist.push({
373                                                                 bssid:    bssid,
374                                                                 signal:   net.assoclist[bssid].signal,
375                                                                 noise:    net.assoclist[bssid].noise,
376                                                                 rx_rate:  net.assoclist[bssid].rx_rate,
377                                                                 rx_mcs:   net.assoclist[bssid].rx_mcs,
378                                                                 rx_40mhz: net.assoclist[bssid].rx_40mhz,
379                                                                 tx_rate:  net.assoclist[bssid].tx_rate,
380                                                                 tx_mcs:   net.assoclist[bssid].tx_mcs,
381                                                                 tx_40mhz: net.assoclist[bssid].tx_40mhz,
382                                                                 link:     net.link,
383                                                                 name:     net.name
384                                                         });
385                                                 }
386                                         }
387
388                                         if (!s)
389                                                 s = '<em><%:No information available%></em>';
390
391                                         td.innerHTML = s;
392                                 }
393                         }
394
395                         var ac = document.getElementById('wifi_assoc_table');
396                         if (ac)
397                         {
398                                 /* clear all rows */
399                                 while( ac.rows.length > 1 )
400                                         ac.rows[0].parentNode.deleteRow(1);
401
402                                 assoclist.sort(function(a, b) {
403                                         return (a.name == b.name)
404                                                 ? (a.bssid < b.bssid)
405                                                 : (a.name  > b.name )
406                                         ;
407                                 });
408
409                                 for( var i = 0; i < assoclist.length; i++ )
410                                 {
411                                         var tr = ac.rows[0].parentNode.insertRow(-1);
412                                                 tr.className = 'cbi-section-table-row cbi-rowstyle-' + (1 + (i % 2));
413
414                                         var icon;
415                                         var q = (-1 * (assoclist[i].noise - assoclist[i].signal)) / 5;
416                                         if (q < 1)
417                                                 icon = "<%=resource%>/icons/signal-0.png";
418                                         else if (q < 2)
419                                                 icon = "<%=resource%>/icons/signal-0-25.png";
420                                         else if (q < 3)
421                                                 icon = "<%=resource%>/icons/signal-25-50.png";
422                                         else if (q < 4)
423                                                 icon = "<%=resource%>/icons/signal-50-75.png";
424                                         else
425                                                 icon = "<%=resource%>/icons/signal-75-100.png";
426
427                                         tr.insertCell(-1).innerHTML = String.format(
428                                                 '<img src="%s" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%>" />',
429                                                 icon, assoclist[i].signal, assoclist[i].noise
430                                         );
431
432                                         tr.insertCell(-1).innerHTML = assoclist[i].bssid;
433
434                                         tr.insertCell(-1).innerHTML = String.format(
435                                                 '<a href="%s">%h</a>',
436                                                         assoclist[i].link,
437                                                         assoclist[i].name
438                                         );
439
440                                         tr.insertCell(-1).innerHTML = String.format('%d <%:dBm%>', assoclist[i].signal);
441                                         tr.insertCell(-1).innerHTML = String.format('%d <%:dBm%>', assoclist[i].noise);
442
443                                         tr.insertCell(-1).innerHTML = (assoclist[i].rx_mcs > -1)
444                                                 ? String.format('%.1f <%:Mbit/s%>, MCS %d, %d<%:MHz%>', assoclist[i].rx_rate / 1000, assoclist[i].rx_mcs, assoclist[i].rx_40mhz ? 40 : 20)
445                                                 : String.format('%.1f <%:Mbit/s%>', assoclist[i].rx_rate / 1000)
446                                         ;
447
448                                         tr.insertCell(-1).innerHTML = (assoclist[i].tx_mcs > -1)
449                                                 ? String.format('%.1f <%:Mbit/s%>, MCS %d, %d<%:MHz%>', assoclist[i].tx_rate / 1000, assoclist[i].tx_mcs, assoclist[i].tx_40mhz ? 40 : 20)
450                                                 : String.format('%.1f <%:Mbit/s%>', assoclist[i].tx_rate / 1000)
451                                         ;
452                                 }
453
454                                 if (ac.rows.length == 1)
455                                 {
456                                         var tr = ac.rows[0].parentNode.insertRow(-1);
457                                                 tr.className = 'cbi-section-table-row';
458
459                                         var td = tr.insertCell(-1);
460                                                 td.colSpan = 7;
461                                                 td.innerHTML = '<br /><em><%:No information available%></em>';
462                                 }
463                         }
464                         <% end %>
465
466                         var e;
467
468                         if (e = document.getElementById('localtime'))
469                                 e.innerHTML = info.localtime;
470
471                         if (e = document.getElementById('uptime'))
472                                 e.innerHTML = String.format('%t', info.uptime);
473
474                         if (e = document.getElementById('loadavg'))
475                                 e.innerHTML = String.format('%.02f, %.02f, %.02f',
476                                         info.loadavg[0], info.loadavg[1], info.loadavg[2]);
477
478                         if (e = document.getElementById('memtotal'))
479                                 e.innerHTML = progressbar(
480                                         (info.memfree + info.membuffers + info.memcached) + " <%:kB%>",
481                                         info.memtotal + " <%:kB%>"
482                                 );
483
484                         if (e = document.getElementById('memfree'))
485                                 e.innerHTML = progressbar(
486                                         info.memfree + " <%:kB%>", info.memtotal + " <%:kB%>"
487                                 );
488
489                         if (e = document.getElementById('memcache'))
490                                 e.innerHTML = progressbar(
491                                         info.memcached + " <%:kB%>", info.memtotal + " <%:kB%>"
492                                 );
493
494                         if (e = document.getElementById('membuff'))
495                                 e.innerHTML = progressbar(
496                                         info.membuffers + " <%:kB%>", info.memtotal + " <%:kB%>"
497                                 );
498
499                         if (e = document.getElementById('conns'))
500                                 e.innerHTML = progressbar(info.conncount, info.connmax);
501
502                 }
503         );
504 //]]></script>
505
506 <h2><a id="content" name="content"><%:Status%></a></h2>
507
508 <fieldset class="cbi-section">
509         <legend><%:System%></legend>
510
511         <table width="100%" cellspacing="10">
512                 <tr><td width="33%"><%:Router Name%></td><td><%=luci.sys.hostname() or "?"%></td></tr>
513                 <tr><td width="33%"><%:Router Model%></td><td><%=pcdata(model or "?")%></td></tr>
514                 <tr><td width="33%"><%:Firmware Version%></td><td>
515                         <%=pcdata(luci.version.distname)%> <%=pcdata(luci.version.distversion)%> /
516                         <%=pcdata(luci.version.luciname)%> (<%=pcdata(luci.version.luciversion)%>)
517                 </td></tr>
518                 <tr><td width="33%"><%:Kernel Version%></td><td><%=luci.sys.exec("uname -r")%></td></tr>
519                 <tr><td width="33%"><%:Local Time%></td><td id="localtime">-</td></tr>
520                 <tr><td width="33%"><%:Uptime%></td><td id="uptime">-</td></tr>
521                 <tr><td width="33%"><%:Load Average%></td><td id="loadavg">-</td></tr>
522         </table>
523 </fieldset>
524
525 <fieldset class="cbi-section">
526         <legend><%:Memory%></legend>
527
528         <table width="100%" cellspacing="10">
529                 <tr><td width="33%"><%:Total Available%></td><td id="memtotal">-</td></tr>
530                 <tr><td width="33%"><%:Free%></td><td id="memfree">-</td></tr>
531                 <tr><td width="33%"><%:Cached%></td><td id="memcache">-</td></tr>
532                 <tr><td width="33%"><%:Buffered%></td><td id="membuff">-</td></tr>
533         </table>
534 </fieldset>
535
536 <fieldset class="cbi-section">
537         <legend><%:Network%></legend>
538
539         <table width="100%" cellspacing="10">
540                 <tr><td width="33%" style="vertical-align:top"><%:IPv4 WAN Status%></td><td>
541                         <table><tr>
542                                 <td id="wan4_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
543                                 <td id="wan4_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
544                         </tr></table>
545                 </td></tr>
546                 <% if has_ipv6 then %>
547                 <tr><td width="33%" style="vertical-align:top"><%:IPv6 WAN Status%></td><td>
548                         <table><tr>
549                                 <td id="wan6_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
550                                 <td id="wan6_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
551                         </tr></table>
552                 </td></tr>
553                 <% end %>
554                 <tr><td width="33%"><%:Active Connections%></td><td id="conns">-</td></tr>
555         </table>
556 </fieldset>
557
558 <% if has_dhcp then %>
559 <fieldset class="cbi-section">
560         <legend><%:DHCP Leases%></legend>
561
562         <table class="cbi-section-table" id="lease_status_table">
563                 <tr class="cbi-section-table-titles">
564                         <th class="cbi-section-table-cell"><%:Hostname%></th>
565                         <th class="cbi-section-table-cell"><%:IPv4-Address%></th>
566                         <th class="cbi-section-table-cell"><%:MAC-Address%></th>
567                         <th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
568                 </tr>
569                 <tr class="cbi-section-table-row">
570                         <td colspan="4"><em><br /><%:Collecting data...%></em></td>
571                 </tr>
572         </table>
573 </fieldset>
574
575 <fieldset class="cbi-section" style="display:none">
576         <legend><%:DHCPv6 Leases%></legend>
577
578         <table class="cbi-section-table" id="lease6_status_table">
579                 <tr class="cbi-section-table-titles">
580                         <th class="cbi-section-table-cell"><%:Hostname%></th>
581                         <th class="cbi-section-table-cell"><%:IPv6-Address%></th>
582                         <th class="cbi-section-table-cell"><%:DUID%></th>
583                         <th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
584                 </tr>
585                 <tr class="cbi-section-table-row">
586                         <td colspan="4"><em><br /><%:Collecting data...%></em></td>
587                 </tr>
588         </table>
589 </fieldset>
590 <% end %>
591
592 <% if has_wifi then %>
593 <fieldset class="cbi-section">
594         <legend><%:Wireless%></legend>
595
596         <table id="wifi_status_table" width="100%" cellspacing="10">
597                 <tr><td><em><%:Collecting data...%></em></td></tr>
598         </table>
599 </fieldset>
600
601 <fieldset class="cbi-section">
602         <legend><%:Associated Stations%></legend>
603
604         <table class="cbi-section-table" id="wifi_assoc_table">
605                 <tr class="cbi-section-table-titles">
606                         <th class="cbi-section-table-cell">&#160;</th>
607                         <th class="cbi-section-table-cell"><%:MAC-Address%></th>
608                         <th class="cbi-section-table-cell"><%:Network%></th>
609                         <th class="cbi-section-table-cell"><%:Signal%></th>
610                         <th class="cbi-section-table-cell"><%:Noise%></th>
611                         <th class="cbi-section-table-cell"><%:RX Rate%></th>
612                         <th class="cbi-section-table-cell"><%:TX Rate%></th>
613                 </tr>
614                 <tr class="cbi-section-table-row">
615                         <td colspan="7"><em><br /><%:Collecting data...%></em></td>
616                 </tr>
617         </table>
618 </fieldset>
619 <% end %>
620
621 <%-
622         require "luci.util"
623         require "nixio.fs"
624
625         local plugins = nixio.fs.dir(luci.util.libpath() .. "/view/admin_status/index")
626         if plugins then
627                 local inc
628                 for inc in plugins do
629                         if inc:match("%.htm$") then
630                                 include("admin_status/index/" .. inc:gsub("%.htm$", ""))
631                         end
632                 end
633         end
634 -%>
635
636 <%+footer%>