diff --git a/luciexpress/htdocs/plugins/core/plugin.json b/luciexpress/htdocs/plugins/core/plugin.json
index 23e3506b6..4e948337b 100644
--- a/luciexpress/htdocs/plugins/core/plugin.json
+++ b/luciexpress/htdocs/plugins/core/plugin.json
@@ -14,13 +14,14 @@
"widgets/luci.navbar",
"widgets/luci.top_bar",
"widgets/luci.slider",
+ "widgets/luci.expandable",
"widgets/luci.errors",
"widgets/core.modal",
"widgets/luci.input.port",
"widgets/luci.input.port.range",
"widgets/luci.input.timespan",
"widgets/luci.input.radio",
- "widgets/luci.input.ipaddress"
+ "widgets/luci.input.ipaddress"
],
"pages": {
"overview": {
diff --git a/luciexpress/htdocs/plugins/core/widgets/luci.expandable.html b/luciexpress/htdocs/plugins/core/widgets/luci.expandable.html
new file mode 100644
index 000000000..199edeca6
--- /dev/null
+++ b/luciexpress/htdocs/plugins/core/widgets/luci.expandable.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+ {{title | translate}}
+
+
+
+
+
+
diff --git a/luciexpress/htdocs/plugins/core/widgets/luci.expandable.js b/luciexpress/htdocs/plugins/core/widgets/luci.expandable.js
new file mode 100644
index 000000000..cded030c7
--- /dev/null
+++ b/luciexpress/htdocs/plugins/core/widgets/luci.expandable.js
@@ -0,0 +1,16 @@
+JUCI.app
+.directive("luciExpandable", function(){
+ var plugin_root = $juci.module("core").plugin_root;
+ return {
+ templateUrl: plugin_root + "/widgets/luci.expandable.html",
+ replace: true,
+ scope: {
+ title: "@",
+ status: "="
+ },
+ transclude: true,
+ link: function (scope, element, attrs) {
+
+ }
+ };
+})
diff --git a/luciexpress/htdocs/plugins/status/pages/status.status.dsl.js b/luciexpress/htdocs/plugins/status/pages/status.status.dsl.js
index 3d92fd8f7..ad968c434 100644
--- a/luciexpress/htdocs/plugins/status/pages/status.status.dsl.js
+++ b/luciexpress/htdocs/plugins/status/pages/status.status.dsl.js
@@ -30,6 +30,28 @@ JUCI.app
$rpc.router.dslstats().done(function(dslstats){
dslstats = dslstats.dslstats;
+
+ // compute floating point values (because ubus blobs do not support floats yet)
+ function reconstruct_floats(obj) {
+ for (var property in obj) {
+ if (obj.hasOwnProperty(property)) {
+ if (typeof obj[property] == "object") {
+ reconstruct_floats(obj[property]);
+ } else {
+ var matches = property.match(/(.*)_x([\d]*)/);
+ if(matches && matches.length == 3){
+ try {
+ obj[matches[1]] = parseFloat(String(obj[property])) / parseFloat(matches[2]);
+ } catch(e) {
+ obj[matches[1]] = "Err";
+ }
+ }
+ }
+ }
+ }
+ }
+ reconstruct_floats(dslstats);
+
$scope.online = dslstats.status && dslstats.status.length > 0;
// todo fields
diff --git a/luciexpress/htdocs/plugins/status/pages/status.status.html b/luciexpress/htdocs/plugins/status/pages/status.status.html
index 77293af38..5a4a74265 100644
--- a/luciexpress/htdocs/plugins/status/pages/status.status.html
+++ b/luciexpress/htdocs/plugins/status/pages/status.status.html
@@ -4,43 +4,28 @@
{{ 'Status' | translate }}
{{ 'status.status.info' | translate }}
-
-
-
-
-
-
-
-
-
- {{sec.name | translate}}
-
-
-
-
-
-
- - {{err.subsystem}}: {{err.code}}
-
-
-
-
- {{sec.interface["ipv4-address"][0].address}}
-
-
- {{sec.interface["route"][0].nexthop}}
-
-
- {{sec.interface["dns-server"][0]}}
-
-
- {{sec.interface["dns-server"][1]}}
-
-
-
-
+
+
+
+ {{sec.interface["ipv4-address"][0].address}}
+
+
+ {{sec.interface["route"][0].nexthop}}
+
+
+ {{sec.interface["dns-server"][0]}}
+
+
+ {{sec.interface["dns-server"][1]}}
+
+
+
+
+
+
+ {{dslinfo.status}}
+
+
+
diff --git a/luciexpress/htdocs/plugins/status/pages/status.status.js b/luciexpress/htdocs/plugins/status/pages/status.status.js
index 43e4a0653..100bc510c 100644
--- a/luciexpress/htdocs/plugins/status/pages/status.status.js
+++ b/luciexpress/htdocs/plugins/status/pages/status.status.js
@@ -31,11 +31,27 @@ JUCI.app
});
});
sections = sections.sort(function(a, b) { return a.interface.up > b.interface.up; });
- for(var c = 0; c < $scope.sections.length; c++){
- Object.assign($scope.sections[c], sections[c]);
+ for(var c = 0; c < sections.length; c++){
+ var sec = sections[c];
+ if(sec.interface.up) sec.status = "ok";
+ else if(sec.interface.pending) sec.status = "progress";
+ else sec.status = "error";
+ Object.assign($scope.sections[c], sec);
}
$scope.$apply();
next();
+ },
+ function(next){
+ $rpc.router.dslstats().done(function(result){
+ switch(result.dslstats.status){
+ case 'Idle': $scope.dsl_status = 'error'; break;
+ case 'Showtime': $scope.dsl_status = 'ok'; break;
+ default: $scope.dsl_status = 'progress'; break;
+ }
+ $scope.dslinfo = result.dslstats;
+ $scope.$apply();
+ next();
+ });
}
], function(){
resume();
diff --git a/luciexpress/htdocs/plugins/status/tests/test-status.js b/luciexpress/htdocs/plugins/status/tests/test-status.js
index 32e61f83f..8cebaf8df 100644
--- a/luciexpress/htdocs/plugins/status/tests/test-status.js
+++ b/luciexpress/htdocs/plugins/status/tests/test-status.js
@@ -20,4 +20,11 @@ describe("Status", function(){
expect($rpc.router).to.be.ok();
expect($rpc.router.info).to.be.ok();
});
+ it("should have accessible router.igmptable call", function(){
+ expect($rpc.router).to.be.ok();
+ expect($rpc.router.igmptable).to.be.ok();
+ $rpc.router.igmptable()
+ .done(function(){ done(); })
+ .fail(function(){ throw new Error("Was unable to call router.igmptable"); });
+ });
});