2 Copyright
2020 Jo-Philipp Wich
<jo@mein.io
>
3 Licensed to the public under the Apache License
2.0.
7 local sys = require
"luci.sys"
8 local util = require
"luci.util"
9 local http = require
"luci.http"
10 local disp = require
"luci.dispatcher"
11 local ver = require
"luci.version"
13 local boardinfo = util.ubus(
"system",
"board") or { }
15 local node = disp.context.dispatched
16 local path = table.concat(disp.context.path,
"-")
18 http.prepare_content(
"text/html; charset=UTF-8")
21 <html lang=
"<%=luci.i18n.context.lang%>">
23 <meta http-equiv=
"Content-Type" content=
"text/html; charset=utf-8" />
24 <meta http-equiv=
"Content-Script-Type" content=
"text/javascript" />
25 <meta name=
"viewport" content=
"width=device-width, initial-scale=1" />
26 <link rel=
"stylesheet" type=
"text/css" media=
"screen" href=
"<%=media%>/cascade.css" />
27 <link rel=
"icon" href=
"<%=media%>/favicon.png" type=
"image/svg+xml" />
28 <script type=
"text/javascript" src=
"<%=url('admin/translations', luci.i18n.context.lang)%><%# ?v=PKG_VERSION %>"></script>
29 <script type=
"text/javascript" src=
"<%=resource%>/cbi.js"></script>
30 <script type=
"text/javascript">//<![CDATA[
32 function get_children(node) {
35 for (var k in node.children) {
36 if (!node.children.hasOwnProperty(k))
39 if (!node.children[k].satisfied)
42 if (!node.children[k].hasOwnProperty('title'))
45 children.push(Object.assign(node.children[k], { name: k }));
48 return children.sort(function(a, b) {
49 return ((a.order ||
1000) - (b.order ||
1000));
53 function handle_mainmenu_expand(ev) {
54 var a = ev.target, ul1 = a.parentNode.parentNode, ul2 = a.nextElementSibling;
56 document.querySelectorAll('ul.mainmenu.l1
> li.active').forEach(function(li) {
57 if (li !== a.parentNode)
58 li.classList.remove('active');
64 if (ul2.parentNode.offsetLeft + ul2.offsetWidth <= ul1.offsetLeft + ul1.offsetWidth)
65 ul2.classList.add('align-left');
67 ul1.classList.add('active');
68 a.parentNode.classList.add('active');
75 function render_mainmenu(tree, url, level) {
76 var l = (level ||
0) +
1,
77 ul = E('ul', { 'class': 'mainmenu l%d'.format(l) }),
78 children = get_children(tree);
80 if (children.length ==
0 || l
> 2)
83 for (var i =
0; i < children.length; i++) {
84 var isActive = (L.env.dispatchpath[l] == children[i].name),
85 activeClass = 'mainmenu-item-%s%s'.format(children[i].name, isActive ? ' selected' : '');
87 ul.appendChild(E('li', { 'class': activeClass }, [
89 'href': L.url(url, children[i].name),
90 'click': (l ==
1) ? handle_mainmenu_expand : null,
91 }, [ _(children[i].title) ]),
92 render_mainmenu(children[i], url + '/' + children[i].name, l)
97 var container = document.querySelector('#mainmenu');
99 container.firstElementChild.appendChild(ul);
100 container.style.display = '';
106 function render_modemenu(tree) {
107 var menu = document.querySelector('#modemenu'),
108 children = get_children(tree);
110 for (var i =
0; i < children.length; i++) {
111 var isActive = (L.env.requestpath.length ? children[i].name == L.env.requestpath[
0] : i ==
0);
114 menu.appendChild(E([], ['\u00a0|\u00a0']));
116 menu.appendChild(E('div', { 'class': isActive ? 'active' : null }, [
117 E('a', { 'href': L.url(children[i].name) }, [ _(children[i].title) ])
121 render_mainmenu(children[i], children[i].name);
124 if (menu.children.length
> 1)
125 menu.style.display = '';
128 function render_tabmenu(tree, url, level) {
129 var container = document.querySelector('#tabmenu'),
130 l = (level ||
0) +
1,
131 ul = E('ul', { 'class': 'cbi-tabmenu' }),
132 children = get_children(tree),
135 if (children.length ==
0)
138 for (var i =
0; i < children.length; i++) {
139 var isActive = (L.env.dispatchpath[l +
2] == children[i].name),
140 activeClass = isActive ? ' cbi-tab' : '',
141 className = 'tabmenu-item-%s %s'.format(children[i].name, activeClass);
143 ul.appendChild(E('li', { 'class': className }, [
144 E('a', { 'href': L.url(url, children[i].name) }, [ _(children[i].title) ] )
148 activeNode = children[i];
151 container.appendChild(ul);
152 container.style.display = '';
155 container.appendChild(render_tabmenu(activeNode, url + '/' + activeNode.name, l));
160 function toggle_sidebar(ev) {
161 var btn = ev.currentTarget,
162 bar = document.querySelector('#mainmenu');
164 if (btn.classList.contains('active')) {
165 btn.classList.remove('active');
166 bar.classList.remove('active');
169 btn.classList.add('active');
170 bar.classList.add('active');
174 document.addEventListener('luci-loaded', function(ev) {
175 var tree = <%= luci.http.write_json(luci.dispatcher.menu_json() or {}) %
>,
179 render_modemenu(tree);
181 if (L.env.dispatchpath.length
>=
3) {
182 for (var i =
0; i <
3 && node; i++) {
183 node = node.children[L.env.dispatchpath[i]];
184 url = url + (url ? '/' : '') + L.env.dispatchpath[i];
188 render_tabmenu(node, url);
191 document.querySelector('#menubar
> .navigation').addEventListener('click', toggle_sidebar);
195 <title><%=striptags( (boardinfo.hostname or
"?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %
> - LuCI
</title>
197 <body class=
"lang_<%=luci.i18n.context.lang%>" data-page=
"<%= pcdata(path) %>">
200 <span id=
"skiplink1"><a href=
"#navigation"><%:Skip to navigation%
></a></span>
201 <span id=
"skiplink2"><a href=
"#content"><%:Skip to content%
></a></span>
205 <h2 class=
"navigation"><a id=
"navigation" name=
"navigation"><%:Navigation%
></a></h2>
207 <span class=
"hostname"><%=(boardinfo.hostname or
"?")%
></span>
208 <span class=
"distversion"><%=ver.distversion%
></span>
209 <span class=
"indicators">
210 <span id=
"xhr_poll_status" style=
"display:none" onclick=
"XHR.running() ? XHR.halt() : XHR.run()">
211 <span id=
"xhr_poll_status_on" style=
"display:none"><%:Refreshing%
></span>
212 <span id=
"xhr_poll_status_off" style=
"display:none"><%:Paused%
></span>
217 <div id=
"modemenu" style=
"display:none"></div>
219 <div id=
"maincontainer">
220 <div id=
"mainmenu" style=
"display:none">
224 <div id=
"maincontent">
225 <%- if luci.sys.process.info(
"uid") ==
0 and luci.sys.user.getuser(
"root") and not luci.sys.user.getpasswd(
"root") and category ~=
"failsafe" and path ~=
"admin-system-admin-password" then -%
>
226 <div class=
"alert-message warning">
227 <h4><%:No password set!%
></h4>
228 <p><%:There is no password set on this router. Please configure a root password to protect the web interface and enable SSH.%
></p>
229 <% if disp.lookup(
"admin/system/admin") then %
>
230 <div class=
"right"><a class=
"btn" href=
"<%=url("admin/system/admin
")%>"><%:Go to password configuration...%
></a></div>
235 <div id=
"tabmenu" style=
"display:none"></div>