luci2: append markup for uci change indicator when rendering main menu
[project/luci2/ui.git] / luci2 / htdocs / luci2 / luci2.js
index fe73a95..6f40b77 100644 (file)
@@ -3684,6 +3684,18 @@ function LuCI2()
                        }
                }),
 
+               _render_change_indicator: function()
+               {
+                       return $('<ul />')
+                               .addClass('nav navbar-nav navbar-right')
+                               .append($('<li />')
+                                       .append($('<a />')
+                                               .attr('id', 'changes')
+                                               .attr('href', '#')
+                                               .append($('<span />')
+                                                       .addClass('label label-info'))));
+               },
+
                renderMainMenu: _luci2.rpc.declare({
                        object: 'luci2.ui',
                        method: 'menu',
@@ -3694,7 +3706,8 @@ function LuCI2()
 
                                $('#mainmenu')
                                        .empty()
-                                       .append(_luci2.globals.mainMenu.render(0, 1));
+                                       .append(_luci2.globals.mainMenu.render(0, 1))
+                                       .append(_luci2.ui._render_change_indicator());
                        }
                }),
 
@@ -3707,9 +3720,11 @@ function LuCI2()
 
                renderView: function()
                {
-                       var node = arguments[0];
-                       var name = node.view.split(/\//).join('.');
-                       var args = [ ];
+                       var node  = arguments[0];
+                       var name  = node.view.split(/\//).join('.');
+                       var cname = _luci2.toClassName(name);
+                       var views = _luci2.views || (_luci2.views = { });
+                       var args  = [ ];
 
                        for (var i = 1; i < arguments.length; i++)
                                args.push(arguments[i]);
@@ -3718,16 +3733,12 @@ function LuCI2()
                                _luci2.globals.currentView.finish();
 
                        _luci2.ui.renderViewMenu();
-
-                       if (!_luci2._views)
-                               _luci2._views = { };
-
                        _luci2.setHash('view', node.view);
 
-                       if (_luci2._views[name] instanceof _luci2.ui.view)
+                       if (views[cname] instanceof _luci2.ui.view)
                        {
-                               _luci2.globals.currentView = _luci2._views[name];
-                               return _luci2._views[name].render.apply(_luci2._views[name], args);
+                               _luci2.globals.currentView = views[cname];
+                               return views[cname].render.apply(views[cname], args);
                        }
 
                        var url = _luci2.globals.resource + '/view/' + name + '.js';
@@ -3747,13 +3758,13 @@ function LuCI2()
 
                                        var viewConstructor = eval(viewConstructorSource);
 
-                                       _luci2._views[name] = new viewConstructor({
+                                       views[cname] = new viewConstructor({
                                                name: name,
                                                acls: node.write || { }
                                        });
 
-                                       _luci2.globals.currentView = _luci2._views[name];
-                                       return _luci2._views[name].render.apply(_luci2._views[name], args);
+                                       _luci2.globals.currentView = views[cname];
+                                       return views[cname].render.apply(views[cname], args);
                                }
                                catch(e) {
                                        alert('Unable to instantiate view "%s": %s'.format(url, e));
@@ -3763,6 +3774,23 @@ function LuCI2()
                        });
                },
 
+               changeView: function()
+               {
+                       var name = _luci2.getHash('view');
+                       var node = _luci2.globals.defaultNode;
+
+                       if (name && _luci2.globals.mainMenu)
+                               node = _luci2.globals.mainMenu.getNode(name);
+
+                       if (node)
+                       {
+                               _luci2.ui.loading(true);
+                               _luci2.ui.renderView(node).then(function() {
+                                       _luci2.ui.loading(false);
+                               });
+                       }
+               },
+
                updateHostname: function()
                {
                        return _luci2.system.getBoardInfo().then(function(info) {
@@ -3788,6 +3816,7 @@ function LuCI2()
                                                switch (c[0])
                                                {
                                                case 'order':
+                                                       log.push('uci reorder %s.<ins>%s=<strong>%s</strong></ins>'.format(config, c[1], c[2]));
                                                        break;
 
                                                case 'remove':
@@ -3853,13 +3882,19 @@ function LuCI2()
                        _luci2.ui.loading(true);
 
                        $.when(
+                               _luci2.session.updateACLs(),
                                _luci2.ui.updateHostname(),
                                _luci2.ui.updateChanges(),
-                               _luci2.ui.renderMainMenu()
+                               _luci2.ui.renderMainMenu(),
+                               _luci2.NetworkModel.init()
                        ).then(function() {
                                _luci2.ui.renderView(_luci2.globals.defaultNode).then(function() {
                                        _luci2.ui.loading(false);
-                               })
+                               });
+
+                               $(window).on('hashchange', function() {
+                                       _luci2.ui.changeView();
+                               });
                        });
                },
 
@@ -4073,10 +4108,7 @@ function LuCI2()
 
                _onclick: function(ev)
                {
-                       _luci2.ui.loading(true);
-                       _luci2.ui.renderView(ev.data).then(function() {
-                               _luci2.ui.loading(false);
-                       });
+                       _luci2.setHash('view', ev.data);
 
                        ev.preventDefault();
                        this.blur();
@@ -4129,7 +4161,7 @@ function LuCI2()
                                }
                                else
                                {
-                                       item.find('a').click(nodes[i], this._onclick);
+                                       item.find('a').click(nodes[i].view, this._onclick);
                                }
                        }
 
@@ -5915,52 +5947,32 @@ function LuCI2()
                }
        });
 
-       this.cbi.NetworkList = this.cbi.AbstractValue.extend({
-               load: function(sid)
+       this.cbi.ButtonValue = this.cbi.AbstractValue.extend({
+               widget: function(sid)
                {
-                       var self = this;
+                       this.options.optional = true;
 
-                       if (!self.interfaces)
-                       {
-                               self.interfaces = [ ];
-                               return _luci2.network.getNetworkStatus().then(function(ifaces) {
-                                       self.interfaces = ifaces;
-                                       self = null;
-                               });
-                       }
+                       var btn = $('<button />')
+                               .addClass('btn btn-default')
+                               .attr('id', this.id(sid))
+                               .attr('type', 'button')
+                               .text(this.label('text'));
 
-                       return undefined;
+                       return this.validator(sid, btn);
+               }
+       });
+
+       this.cbi.NetworkList = this.cbi.AbstractValue.extend({
+               load: function(sid)
+               {
+                       return _luci2.NetworkModel.init();
                },
 
                _device_icon: function(dev)
                {
-                       var type = 'ethernet';
-                       var desc = _luci2.tr('Ethernet device');
-
-                       if (dev.type == 'IP tunnel')
-                       {
-                               type = 'tunnel';
-                               desc = _luci2.tr('Tunnel interface');
-                       }
-                       else if (dev['bridge-members'])
-                       {
-                               type = 'bridge';
-                               desc = _luci2.tr('Bridge');
-                       }
-                       else if (dev.wireless)
-                       {
-                               type = 'wifi';
-                               desc = _luci2.tr('Wireless Network');
-                       }
-                       else if (dev.device.indexOf('.') > 0)
-                       {
-                               type = 'vlan';
-                               desc = _luci2.tr('VLAN interface');
-                       }
-
                        return $('<img />')
-                               .attr('src', _luci2.globals.resource + '/icons/' + type + (dev.up ? '' : '_disabled') + '.png')
-                               .attr('title', '%s (%s)'.format(desc, dev.device));
+                               .attr('src', dev.icon())
+                               .attr('title', '%s (%s)'.format(dev.description(), dev.name() || '?'));
                },
 
                widget: function(sid)
@@ -5980,34 +5992,36 @@ function LuCI2()
                                for (var i = 0; i < value.length; i++)
                                        check[value[i]] = true;
 
-                       if (this.interfaces)
+                       var interfaces = _luci2.NetworkModel.getInterfaces();
+
+                       for (var i = 0; i < interfaces.length; i++)
                        {
-                               for (var i = 0; i < this.interfaces.length; i++)
-                               {
-                                       var iface = this.interfaces[i];
-                                       var badge = $('<span />')
-                                               .addClass('badge')
-                                               .text('%s: '.format(iface['interface']));
-
-                                       if (iface.device && iface.device.subdevices)
-                                               for (var j = 0; j < iface.device.subdevices.length; j++)
-                                                       badge.append(this._device_icon(iface.device.subdevices[j]));
-                                       else if (iface.device)
-                                               badge.append(this._device_icon(iface.device));
-                                       else
-                                               badge.append($('<em />').text(_luci2.tr('(No devices attached)')));
+                               var iface = interfaces[i];
+                               var badge = $('<span />')
+                                       .addClass('badge')
+                                       .text('%s: '.format(iface.name()));
 
-                                       $('<li />')
-                                               .append($('<label />')
-                                                       .addClass(itype + ' inline')
-                                                       .append($('<input />')
-                                                               .attr('name', itype + id)
-                                                               .attr('type', itype)
-                                                               .attr('value', iface['interface'])
-                                                               .prop('checked', !!check[iface['interface']]))
-                                                       .append(badge))
-                                               .appendTo(ul);
-                               }
+                               var dev = iface.getDevice();
+                               var subdevs = iface.getSubdevices();
+
+                               if (subdevs.length)
+                                       for (var j = 0; j < subdevs.length; j++)
+                                               badge.append(this._device_icon(subdevs[j]));
+                               else if (dev)
+                                       badge.append(this._device_icon(dev));
+                               else
+                                       badge.append($('<em />').text(_luci2.tr('(No devices attached)')));
+
+                               $('<li />')
+                                       .append($('<label />')
+                                               .addClass(itype + ' inline')
+                                               .append($('<input />')
+                                                       .attr('name', itype + id)
+                                                       .attr('type', itype)
+                                                       .attr('value', iface.name())
+                                                       .prop('checked', !!check[iface.name()]))
+                                               .append(badge))
+                                       .appendTo(ul);
                        }
 
                        if (!this.options.multiple)
@@ -6019,7 +6033,7 @@ function LuCI2()
                                                        .attr('name', itype + id)
                                                        .attr('type', itype)
                                                        .attr('value', '')
-                                                       .prop('checked', !value))
+                                                       .prop('checked', $.isEmptyObject(check)))
                                                .append(_luci2.tr('unspecified')))
                                        .appendTo(ul);
                        }
@@ -6870,6 +6884,16 @@ function LuCI2()
                }
        });
 
+       this.cbi.SingleSection = this.cbi.NamedSection.extend({
+               render: function()
+               {
+                       this.instance = { };
+                       this.instance[this.uci_type] = { tabs: [ ] };
+
+                       return this._render_section_body(this.uci_type, 0);
+               }
+       });
+
        this.cbi.DummySection = this.cbi.TypedSection.extend({
                sections: function(cb)
                {