luci2: rework system administration view with fancier ssh pubkey handling
[project/luci2/ui.git] / luci2 / htdocs / luci2 / luci2.js
index 52ea2e7..84ebf84 100644 (file)
@@ -387,7 +387,7 @@ function LuCI2()
        };
 
        this.globals = {
-               timeout:  3000,
+               timeout:  15000,
                resource: '/luci2',
                sid:      '00000000000000000000000000000000'
        };
@@ -788,13 +788,13 @@ function LuCI2()
                                        var net = nets[i] = networks[i];
                                        var dev = net.l3_device || net.l2_device;
                                        if (dev)
-                                               net.device = devs[dev] = { };
+                                               net.device = devs[dev] || (devs[dev] = { });
                                }
 
                                _luci2.rpc.batch();
 
                                for (var dev in devs)
-                                       _luci2.network.listDeviceNamestatus(dev);
+                                       _luci2.network.getDeviceStatus(dev);
 
                                return _luci2.rpc.flush();
                        }).then(function(devices) {
@@ -817,7 +817,7 @@ function LuCI2()
                                                if (!devs[brm[j]])
                                                {
                                                        devs[brm[j]] = { };
-                                                       _luci2.network.listDeviceNamestatus(brm[j]);
+                                                       _luci2.network.getDeviceStatus(brm[j]);
                                                }
 
                                                devs[devices[i]['device']].subdevices[j] = devs[brm[j]];
@@ -867,6 +867,9 @@ function LuCI2()
 
                                for (var i = 0; i < interfaces.length; i++)
                                {
+                                       if (!interfaces[i].route)
+                                               continue;
+
                                        for (var j = 0; j < interfaces[i].route.length; j++)
                                        {
                                                var rt = interfaces[i].route[j];
@@ -928,7 +931,7 @@ function LuCI2()
                        }
                }),
 
-               listDeviceNamestatus: _luci2.rpc.declare({
+               getDeviceStatus: _luci2.rpc.declare({
                        object: 'network.device',
                        method: 'status',
                        params: [ 'name' ],
@@ -943,6 +946,73 @@ function LuCI2()
                        object: 'luci2.network',
                        method: 'conntrack_count',
                        expect: { '': { count: 0, limit: 0 } }
+               }),
+
+               listSwitchNames: _luci2.rpc.declare({
+                       object: 'luci2.network',
+                       method: 'switch_list',
+                       expect: { switches: [ ] }
+               }),
+
+               getSwitchInfo: _luci2.rpc.declare({
+                       object: 'luci2.network',
+                       method: 'switch_info',
+                       params: [ 'switch' ],
+                       expect: { info: { } },
+                       filter: function(data, params) {
+                               data['attrs']      = data['switch'];
+                               data['vlan_attrs'] = data['vlan'];
+                               data['port_attrs'] = data['port'];
+                               data['switch']     = params['switch'];
+
+                               delete data.vlan;
+                               delete data.port;
+
+                               return data;
+                       }
+               }),
+
+               getSwitchStatus: _luci2.rpc.declare({
+                       object: 'luci2.network',
+                       method: 'switch_status',
+                       params: [ 'switch' ],
+                       expect: { ports: [ ] }
+               }),
+
+
+               runPing: _luci2.rpc.declare({
+                       object: 'luci2.network',
+                       method: 'ping',
+                       params: [ 'data' ],
+                       expect: { '': { code: -1 } }
+               }),
+
+               runPing6: _luci2.rpc.declare({
+                       object: 'luci2.network',
+                       method: 'ping6',
+                       params: [ 'data' ],
+                       expect: { '': { code: -1 } }
+               }),
+
+               runTraceroute: _luci2.rpc.declare({
+                       object: 'luci2.network',
+                       method: 'traceroute',
+                       params: [ 'data' ],
+                       expect: { '': { code: -1 } }
+               }),
+
+               runTraceroute6: _luci2.rpc.declare({
+                       object: 'luci2.network',
+                       method: 'traceroute6',
+                       params: [ 'data' ],
+                       expect: { '': { code: -1 } }
+               }),
+
+               runNslookup: _luci2.rpc.declare({
+                       object: 'luci2.network',
+                       method: 'nslookup',
+                       params: [ 'data' ],
+                       expect: { '': { code: -1 } }
                })
        };
 
@@ -2034,6 +2104,9 @@ function LuCI2()
                {
                        var name = node.view.split(/\//).join('.');
 
+                       if (_luci2.globals.currentView)
+                               _luci2.globals.currentView.finish();
+
                        _luci2.ui.renderViewMenu();
 
                        if (!_luci2._views)
@@ -2042,7 +2115,10 @@ function LuCI2()
                        _luci2.setHash('view', node.view);
 
                        if (_luci2._views[name] instanceof _luci2.ui.view)
+                       {
+                               _luci2.globals.currentView = _luci2._views[name];
                                return _luci2._views[name].render();
+                       }
 
                        var url = _luci2.globals.resource + '/view/' + name + '.js';
 
@@ -2053,7 +2129,7 @@ function LuCI2()
                        }).then(function(data) {
                                try {
                                        var viewConstructorSource = (
-                                               '(function(L, $) {\n' +
+                                               '(function(L, $) { ' +
                                                        'return %s' +
                                                '})(_luci2, $);\n\n' +
                                                '//@ sourceURL=%s'
@@ -2066,6 +2142,7 @@ function LuCI2()
                                                acls: node.write || { }
                                        });
 
+                                       _luci2.globals.currentView = _luci2._views[name];
                                        return _luci2._views[name].render();
                                }
                                catch(e) {
@@ -2118,7 +2195,7 @@ function LuCI2()
                                                        break;
 
                                                case 'add':
-                                                       log.push('uci add %s (= <ins><strong>%s</strong></ins>)'.format(config, c[1]));
+                                                       log.push('uci add %s <ins>%s</ins> (= <ins><strong>%s</strong></ins>)'.format(config, c[2], c[1]));
                                                        break;
 
                                                case 'list-add':
@@ -2246,6 +2323,42 @@ function LuCI2()
                        return this._fetch_template().then(function() {
                                return _luci2.deferrable(self.execute());
                        });
+               },
+
+               repeat: function(func, interval)
+               {
+                       var self = this;
+
+                       if (!self._timeouts)
+                               self._timeouts = [ ];
+
+                       var index = self._timeouts.length;
+
+                       if (typeof(interval) != 'number')
+                               interval = 5000;
+
+                       var setTimer, runTimer;
+
+                       setTimer = function() {
+                               self._timeouts[index] = window.setTimeout(runTimer, interval);
+                       };
+
+                       runTimer = function() {
+                               _luci2.deferrable(func.call(self)).then(setTimer);
+                       };
+
+                       runTimer();
+               },
+
+               finish: function()
+               {
+                       if ($.isArray(this._timeouts))
+                       {
+                               for (var i = 0; i < this._timeouts.length; i++)
+                                       window.clearTimeout(this._timeouts[i]);
+
+                               delete this._timeouts;
+                       }
                }
        });
 
@@ -2299,7 +2412,10 @@ function LuCI2()
                                var child = this.firstChildView(nodes[i]);
                                if (child)
                                {
-                                       $.extend(node, child);
+                                       for (var key in child)
+                                               if (!node.hasOwnProperty(key) && child.hasOwnProperty(key))
+                                                       node[key] = child[key];
+
                                        return node;
                                }
                        }
@@ -2584,7 +2700,9 @@ function LuCI2()
        this.ui.devicebadge = AbstractWidget.extend({
                render: function()
                {
-                       var dev = this.options.l3_device || this.options.device || '?';
+                       var l2dev = this.options.l2_device || this.options.device;
+                       var l3dev = this.options.l3_device;
+                       var dev = l3dev || l2dev || '?';
 
                        var span = document.createElement('span');
                                span.className = 'ifacebadge';
@@ -2625,7 +2743,7 @@ function LuCI2()
                                var type = 'ethernet';
                                var desc = _luci2.tr('Ethernet device');
 
-                               if (this.options.l3_device != this.options.device)
+                               if (l3dev != l2dev)
                                {
                                        type = 'tunnel';
                                        desc = _luci2.tr('Tunnel interface');
@@ -2875,6 +2993,7 @@ function LuCI2()
                                }
                        }
 
+                       validation.i18n('Must be a valid IPv6 address');
                        return false;
                },
 
@@ -3578,12 +3697,10 @@ function LuCI2()
 
                        if (chg)
                        {
-                               val = val ? this.options.enabled : this.options.disabled;
-
                                if (this.options.optional && val == this.options.initial)
                                        this.map.set(uci.config, uci.section, uci.option, undefined);
                                else
-                                       this.map.set(uci.config, uci.section, uci.option, val);
+                                       this.map.set(uci.config, uci.section, uci.option, val ? this.options.enabled : this.options.disabled);
                        }
 
                        return chg;