luci-app-babeld: rewrite javascript without CDN includes
authorJonathan Pagel <jonny_tischbein@systemli.org>
Tue, 9 Feb 2021 21:32:28 +0000 (22:32 +0100)
committerPaul Spooren <mail@aparcar.org>
Mon, 15 Feb 2021 17:44:02 +0000 (07:44 -1000)
Rewrite luci app in javascript without external sources

CC-Signed-off-by: Nick Hainke <vincent@systemli.org>
Signed-off-by: Jonathan Pagel <jonny_tischbein@systemli.org>
applications/luci-app-babeld/Makefile
applications/luci-app-babeld/luasrc/model/cbi/babeld.lua [deleted file]
applications/luci-app-babeld/luasrc/view/babeld.htm [new file with mode: 0644]
applications/luci-app-babeld/root/etc/uci-defaults/40_luci-babeld [new file with mode: 0644]
applications/luci-app-babeld/root/usr/share/luci/menu.d/luci-app-babeld.json
applications/luci-app-babeld/root/usr/share/rpcd/acl.d/luci-app-babeld.json
applications/luci-app-babeld/root/www/luci-static/resources/babeld.js [new file with mode: 0644]

index adfd08ccd8ea1825ec9826cf950ce6679a4a045a..6af9280261b657df4b6914f3a47b7878d84e0ef3 100644 (file)
@@ -7,4 +7,3 @@ LUCI_PKGARCH:=all
 include ../../luci.mk
 
 # call BuildPackage - OpenWrt buildroot signature
-
diff --git a/applications/luci-app-babeld/luasrc/model/cbi/babeld.lua b/applications/luci-app-babeld/luasrc/model/cbi/babeld.lua
deleted file mode 100644 (file)
index 2169de4..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-m = Map("babeld", translate("Babeld Overview"))
-m.pageaction = false
-
-s = m:section(NamedSection, "__babeldoverview__")
-
-function s.render(self, sid)
-       local tpl = require "luci.template"
-
-       tpl.render_string([[
-               <%
-               local utl = require "luci.util"
-               local v6_port = 33123
-               -- FIXME: check if call is correct
-               local dump = utl.exec("(echo dump | nc ::1 %d)" % v6_port)
-               local t = {}
-
-               for strline in string.gmatch(dump, "[^\n]+") do
-                       t[#t+1] = strline;
-               end
-
-               local babel_version = t[1]
-               local babeld_version = t[2]
-               local babeld_host = string.split(t[3], " ")[2]
-               local babeld_id = string.split(t[4], " ")[2]
-               local babeld_status = t[5]
-
-               %>
-               <div class="cbi-section-node">
-                       <h3>Babel-Info</h3>
-                       <div class="table" id=babel_status_main">
-                               <div class="tr table-titles">
-                                       <div class="th">Version</div>
-                                       <div class="th">Version-Daemon</div>
-                                       <div class="th">Host</div>
-                                       <div class="th">ID</div>
-                                       <div class="th">Status</div>
-                               </div>
-                               <div class="tr">
-                                       <div class="td"><%= babel_version %></div>
-                                       <div class="td"><%= babeld_version %></div>
-                                       <div class="td"><%= babeld_host %></div>
-                                       <div class="td"><%= babeld_id %></div>
-                                       <div class="td"><%= babeld_status %></div>
-                               </div>
-                       </div>
-               </div>
-               
-               <%
-               local xroutes = {}
-               for key,value in ipairs(t) do
-                       if string.match(value, "xroute") then
-                               xroutes[#xroutes+1] = value
-                       end
-               end
-               %>
-
-               <div class="cbi-section-node">
-                       <h3>X-Routes</h3>
-                       <div class="table" id=babel_overview_xroute">
-                               <div class="tr table-titles">
-                                       <div class="th">Route</div>
-                                       <div class="th">Prefix</div>
-                                       <div class="th">From</div>
-                                       <div class="th">Metric</div>
-                               </div>
-                               <%
-                               for key,route in ipairs(xroutes) do
-                                       local route_sep = string.split(route," ")
-                               %>
-                                       <div class="tr">
-                                               <div class="td"><%= route_sep[3] %></div>
-                                               <div class="td"><%= route_sep[5] %></div>
-                                               <div class="td"><%= route_sep[7] %></div>
-                                               <div class="td"><%= route_sep[9] %></div>
-                                       </div>
-                               <%
-                               end
-                               %>
-                       </div>
-               </div>
-               
-               <%
-               local routes = {}
-               for key,value in ipairs(t) do
-                       if string.match(value, "add route") then
-                                       routes[#routes+1] = value
-                       end
-               end
-               %>
-
-               <div class="cbi-section-node">
-                       <h3>Routes</h3>
-                       <div class="table" id=babel_overview_route">
-                               <div class="tr table-titles">
-                                       <div class="th">Prefix</div>
-                                       <div class="th">From</div>
-                                       <div class="th">Installed</div>
-                                       <div class="th">ID</div>
-                                       <div class="th">Metric</div>
-                                       <div class="th">Ref-Metric</div>
-                                       <div class="th">Via</div>
-                                       <div class="th">Interface</div>
-                               </div>
-                               <%
-                               for key,route in ipairs(routes) do
-                                       local route_sep = string.split(route," ")
-                               %>
-
-                                       <div class="tr">
-                                               <div class="td"><%= route_sep[5] %></div>
-                                               <div class="td"><%= route_sep[7] %></div>
-                                               <div class="td"><%= route_sep[9] %></div>
-                                               <div class="td"><%= route_sep[11] %></div>
-                                               <div class="td"><%= route_sep[13] %></div>
-                                               <div class="td"><%= route_sep[15] %></div>
-                                               <div class="td"><%= route_sep[17] %></div>
-                                               <div class="td"><%= route_sep[19] %></div>
-                                       </div>
-                               <%
-                               end
-                               %>
-                       </div>
-               </div>
-       ]])
-end
-
-return m
diff --git a/applications/luci-app-babeld/luasrc/view/babeld.htm b/applications/luci-app-babeld/luasrc/view/babeld.htm
new file mode 100644 (file)
index 0000000..d3436f0
--- /dev/null
@@ -0,0 +1,22 @@
+<%+header%>
+<script type="text/javascript" src="<%=resource%>/babeld.js"></script>
+
+<div id="babeld"></div>
+
+<script type="text/javascript">
+    data = {};
+    data["ubus_rpc_session"] = "<%=luci.dispatcher.context.authsession%>"
+    origin = document.location.href.replace(location.pathname, "")
+    ubus_url = origin + "/ubus/"
+
+    var info = ubus_call("babeld", "get_info", {});
+    var xroutes = ubus_call("babeld", "get_xroutes", {});
+    var routes = ubus_call("babeld", "get_routes", {});
+    var neighbours = ubus_call("babeld", "get_neighbours", {});
+
+    renderTableInfo(info, 'babeld');
+    renderTableXRoutes(xroutes, 'babeld');
+    renderTableRoutes(routes, 'babeld');
+    renderTableNeighbours(neighbours, 'babeld');
+</script>
+<%+footer%>
diff --git a/applications/luci-app-babeld/root/etc/uci-defaults/40_luci-babeld b/applications/luci-app-babeld/root/etc/uci-defaults/40_luci-babeld
new file mode 100644 (file)
index 0000000..c9b223e
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+uci set babeld.@general[0].ubus_bindings='true'
+
+return 0
index 8d0b010c2121971d6e05e974fd42335241ac5586..a5f7e9259e1069c36a64537089538a22055a4103 100644 (file)
@@ -2,9 +2,8 @@
        "admin/status/babeld": {
                "title": "Babeld",
                "action": {
-                       "type": "cbi",
-                       "path": "babeld",
-                       "post": { "cbi.submit": true }
+                       "type": "template",
+                       "path": "babeld"
                },
                "depends": {
                        "acl": [ "luci-app-babeld" ]
index 51687bad5cfe9b12bc7ddfa16c6ed4dfcdb00b07..71755b30d4653511c4699dd2ae89c42e36e681e7 100644 (file)
@@ -2,10 +2,16 @@
        "luci-app-babeld": {
                "description": "Grant UCI access for babeld",
                "read": {
-                       "uci": [ "babeld" ]
+                       "uci": [ "babeld" ],
+                       "ubus": {
+                               "babeld": [ "*" ]
+                       }
                },
                "write": {
-                       "uci": [ "babeld" ]
+                       "uci": [ "babeld" ],
+                       "ubus": {
+                               "babeld": [ "*" ]
+                       }
                }
        }
 }
diff --git a/applications/luci-app-babeld/root/www/luci-static/resources/babeld.js b/applications/luci-app-babeld/root/www/luci-static/resources/babeld.js
new file mode 100644 (file)
index 0000000..864010e
--- /dev/null
@@ -0,0 +1,189 @@
+function ubus_call(command, argument, params) {
+    var request_data = {};
+    request_data.jsonrpc = "2.0";
+    request_data.method = "call";
+    request_data.params = [data.ubus_rpc_session, command, argument, params]
+    var request_json = JSON.stringify(request_data);
+    var request = new XMLHttpRequest();
+    request.open("POST", ubus_url, false);
+    request.setRequestHeader("Content-type", "application/json");
+    request.send(request_json);
+    if (request.status === 200) {
+        var response = JSON.parse(request.responseText)
+        if (!("error" in response) && "result" in response) {
+            if (response.result.length === 2) {
+                return response.result[1];
+            }
+        } else {
+            console.err("Failed query ubus!");
+        }
+    }
+}
+
+function renderTableXRoutes(data, target_id) {
+    for (var protocol in data) {
+        var target = document.getElementById(target_id);
+
+        var title = document.createElement('h3');
+        title.appendChild(document.createTextNode('X-Routes ' + protocol));
+        target.appendChild(title);
+
+        var table = document.createElement('div');
+        table.setAttribute('class', 'table');
+        table.setAttribute('id', 'babel_overview_xroutes_' + protocol);
+
+        var headerRow = document.createElement('div');
+        headerRow.setAttribute('class', 'tr table-titles');
+        var headerContent = '<div class="th" style="font-weight: 700;">' + protocol + ' Prefix</div>\
+                             <div class="th" style="font-weight: 700;">Metric</div>\
+                             <div class="th" style="font-weight: 700;">Source-Prefix</div>';
+
+        headerRow.innerHTML = headerContent;
+        table.appendChild(headerRow);
+
+
+        for (var prefix in data[protocol]) {
+            var prefixRow = document.createElement('div');
+            prefixRow.setAttribute('class', 'tr');
+            var prefixContent = '<div class="td" data-title="xroutes_' + protocol + '_prefix">' + prefix + '</div>\
+                                 <div class="td" data-title="xroutes_' + protocol + '_metric">' + data[protocol][prefix]["metric"] + '</div>\
+                                 <div class="td" data-title="xroutes_' + protocol + '_src-prefix">' + data[protocol][prefix]["src-prefix"] + '</div>';
+
+            prefixRow.innerHTML = prefixContent;
+            table.appendChild(prefixRow);
+        }
+        target.appendChild(table);
+    }
+}
+
+function renderTableRoutes(data, target_id) {
+    for (var protocol in data) {
+        var target = document.getElementById(target_id);
+
+        var title = document.createElement('h3');
+        title.appendChild(document.createTextNode('Routes ' + protocol));
+        target.appendChild(title);
+
+        var table = document.createElement('div');
+        table.setAttribute('class', 'table');
+        table.setAttribute('id', 'babel_overview_routes_' + protocol);
+
+        var headerRow = document.createElement('div');
+        headerRow.setAttribute('class', 'tr table-titles');
+        var headerContent = '<div class="th" style="font-weight: 700;">' + protocol + ' Prefix</div>\
+                             <div class="th" style="font-weight: 700;">Source-Prefix</div>\
+                             <div class="th" style="font-weight: 700;">Route-Metric</div>\
+                             <div class="th" style="font-weight: 700;">Route Smoothed Metric</div>\
+                             <div class="th" style="font-weight: 700;">Refmetric</div>\
+                             <div class="th" style="font-weight: 700;">ID</div>\
+                             <div class="th" style="font-weight: 700;">Seq. No.</div>\
+                             <div class="th" style="font-weight: 700;">Channes</div>\
+                             <div class="th" style="font-weight: 700;">Age</div>\
+                             <div class="th" style="font-weight: 700;">Via</div>\
+                             <div class="th" style="font-weight: 700;">Nexthop</div>\
+                             <div class="th" style="font-weight: 700;">Installed</div>\
+                             <div class="th" style="font-weight: 700;">Feasible</div>';
+
+        headerRow.innerHTML = headerContent;
+        table.appendChild(headerRow);
+
+        for (var prefix in data[protocol]) {
+            var prefixRow = document.createElement('div');
+            prefixRow.setAttribute('class', 'tr');
+            var prefixContent = '<div class="td" data-title="routes_' + protocol + '_prefix">' + prefix + '</div>\
+                                 <div class="td" data-title="routes_' + protocol + '_src-prefix">' + data[protocol][prefix]["src-prefix"] + '</div>\
+                                 <div class="td" data-title="routes_' + protocol + '_metric">' + data[protocol][prefix]["route_metric"] + '</div>\
+                                 <div class="td" data-title="routes_' + protocol + '_rout-smoothed-metric">' + data[protocol][prefix]["route_smoothed_metric"] + '</div>\
+                                 <div class="td" data-title="routes_' + protocol + '_refmetric">' + data[protocol][prefix]["refmetric"] + '</div>\
+                                 <div class="td" data-title="routes_' + protocol + '_id">' + data[protocol][prefix]["id"] + '</div>\
+                                 <div class="td" data-title="routes_' + protocol + '_seqno">' + data[protocol][prefix]["seqno"] + '</div>\
+                                 <div class="td" data-title="routes_' + protocol + '_channels">' + data[protocol][prefix]["channels"] + '</div>\
+                                 <div class="td" data-title="routes_' + protocol + '_age">' + data[protocol][prefix]["age"] + '</div>\
+                                 <div class="td" data-title="routes_' + protocol + '_via">' + data[protocol][prefix]["via"] + '</div>\
+                                 <div class="td" data-title="routes_' + protocol + '_nexthop">' + data[protocol][prefix]["nexthop"] + '</div>\
+                                 <div class="td" data-title="routes_' + protocol + '_installed">' + data[protocol][prefix]["installed"] + '</div>\
+                                 <div class="td" data-title="routes_' + protocol + '_feasible">' + data[protocol][prefix]["feasible"] + '</div>';
+
+            prefixRow.innerHTML = prefixContent;
+            table.appendChild(prefixRow);
+        }
+        target.appendChild(table);
+    }
+}
+
+function renderTableNeighbours(data, target_id) {
+    for (var protocol in data) {
+        var target = document.getElementById(target_id);
+
+        var title = document.createElement('h3');
+        title.appendChild(document.createTextNode('Neighbours ' + protocol));
+        target.appendChild(title);
+
+        var table = document.createElement('div');
+        table.setAttribute('class', 'table');
+        table.setAttribute('id', 'babel_overview_neighbours_' + protocol);
+
+        var headerRow = document.createElement('div');
+        headerRow.setAttribute('class', 'tr table-titles');
+        var headerContent = '<div class="th" style="font-weight: 700;">' + protocol + ' Neighbour</div>\
+                             <div class="th" style="font-weight: 700;">Device</div>\
+                             <div class="th" style="font-weight: 700;">Hello-Reach</div>\
+                             <div class="th" style="font-weight: 700;">RX cost</div>\
+                             <div class="th" style="font-weight: 700;">TX cost</div>\
+                             <div class="th" style="font-weight: 700;">RTT</div>\
+                             <div class="th" style="font-weight: 700;">Channel</div>\
+                             <div class="th" style="font-weight: 700;">Interface up</div>';
+
+        headerRow.innerHTML = headerContent;
+        table.appendChild(headerRow);
+
+        for (var neighbour in data[protocol]) {
+            var neighbourRow = document.createElement('div');
+            neighbourRow.setAttribute('class', 'tr');
+            var neighbourContent = '<div class="td" data-title="' + protocol + '_neighbour">' + neighbour + '</div>\
+                                    <div class="td" data-title="neighbours_' + protocol + '_dev">' + data[protocol][neighbour]["dev"] + '</div>\
+                                    <div class="td" data-title="neighbours_' + protocol + '_hello-reach">' + data[protocol][neighbour]["hello-reach"] + '</div>\
+                                    <div class="td" data-title="neighbours_' + protocol + '_rxcost">' + data[protocol][neighbour]["rxcost"] + '</div>\
+                                    <div class="td" data-title="neighbours_' + protocol + '_txcost">' + data[protocol][neighbour]["txcost"] + '</div>\
+                                    <div class="td" data-title="neighbours_' + protocol + '_rtt">' + data[protocol][neighbour]["rtt"] + '</div>\
+                                    <div class="td" data-title="neighbours_' + protocol + '_channel">' + data[protocol][neighbour]["channel"] + '</div>\
+                                    <div class="td" data-title="neighbours_' + protocol + '_if_up">' + data[protocol][neighbour]["if_up"] + '</div>';
+
+            neighbourRow.innerHTML = neighbourContent;
+            table.appendChild(neighbourRow);
+        }
+        target.appendChild(table);
+    }
+}
+
+function renderTableInfo(data, target_id) {
+    var target = document.getElementById(target_id);
+
+    var title = document.createElement('h3');
+    title.appendChild(document.createTextNode('Info'));
+    target.appendChild(title);
+
+    var table = document.createElement('div');
+    table.setAttribute('class', 'table');
+    table.setAttribute('id', 'babel_overview_info');
+
+
+    var headerRow = document.createElement('div');
+    headerRow.setAttribute('class', 'tr table-titles');
+    var headerContent = '<div class="th" style="font-weight: 700;">Babeld Version</div>\
+                         <div class="th" style="font-weight: 700;">My-ID</div>\
+                         <div class="th" style="font-weight: 700;">Host</div>';
+
+    headerRow.innerHTML = headerContent;
+    table.appendChild(headerRow);
+
+    var neighbourRow = document.createElement('div');
+    neighbourRow.setAttribute('class', 'tr');
+    var neighbourContent = '<div class="td" data-title="info_babeld-version">' + data["babeld-version"] + '</div>\
+                            <div class="td" data-title="info_dev">' + data["my-id"] + '</div>\
+                            <div class="td" data-title="info_hello-reach">' + data["host"] + '</div>';
+
+    neighbourRow.innerHTML = neighbourContent;
+    table.appendChild(neighbourRow);
+    target.appendChild(table);
+}