luci2: implement uci changelog view, display pending changes in upper right corner
authorJo-Philipp Wich <jow@openwrt.org>
Thu, 3 Oct 2013 13:59:20 +0000 (13:59 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Thu, 3 Oct 2013 13:59:20 +0000 (13:59 +0000)
luci2/htdocs/luci2.html
luci2/htdocs/luci2/bootstrap/cascade.css
luci2/htdocs/luci2/luci2.js

index d6fe09a2de8aa984e908963b96706c024f8f2c86..98d64447388a566eba4cdab899af05d14ba18d32 100644 (file)
@@ -29,6 +29,8 @@
                 <div class="container">
                     <a id="hostname" class="brand" href="#">&nbsp;</a>
                     <div id="mainmenu"></div>
+
+                    <div class="pull-right" id="changes"></div>
     <!--
                     <div class="pull-right">
                         <span id="xhr_poll_status" style="display:none" onclick="XHR.running() ? XHR.halt() : XHR.run()">
index d79ec965260dc0a92efed50729476115dc5f69e9..24b0bf40336f59f1466be53dec10b4f605a8569c 100644 (file)
@@ -2232,69 +2232,16 @@ td.cbi-value-field var {
        color: #0069D6;
 }
 
-.uci-change-list {
-       font-family: monospace;
-}
-
-.uci-change-list ins,
-.uci-change-legend-label ins {
-       text-decoration: none;
-       border: 1px solid #00FF00;
-       background-color: #CCFFCC;
-       display: block;
-       padding: 2px;
+pre.uci-changes {
+       margin: 3px 0;
 }
 
-.uci-change-list del,
-.uci-change-legend-label del {
+pre.uci-changes ins {
        text-decoration: none;
-       border: 1px solid #FF0000;
-       background-color: #FFCCCC;
-       display: block;
-       font-style: normal;
-       padding: 2px;
+       color: #008000;
 }
 
-.uci-change-list var,
-.uci-change-legend-label var {
+pre.uci-changes del {
        text-decoration: none;
-       border: 1px solid #CCCCCC;
-       background-color: #EEEEEE;
-       display: block;
-       font-style: normal;
-       padding: 2px;
-}
-
-.uci-change-list var ins,
-.uci-change-list var del {
-       /*display: inline;*/
-       border: none;
-       white-space: pre;
-       font-style: normal;
-       padding: 0px;
-}
-
-.uci-change-legend {
-       padding: 5px;
-}
-
-.uci-change-legend-label {
-       width: 150px;
-       float: left;
-}
-
-.uci-change-legend-label>ins,
-.uci-change-legend-label>del,
-.uci-change-legend-label>var {
-       float: left;
-       margin-right: 4px;
-       width: 10px;
-       height: 10px;
-       display: block;
-}
-
-.uci-change-legend-label var ins,
-.uci-change-legend-label var del {
-       line-height: 6px;
-       border: none;
+       color: #800000;
 }
index 02b0015a4f432ac6c966aaf67a589ae8a1f294ae..52ea2e7a035600270e911853a59ed7edcf9839c5 100644 (file)
@@ -584,13 +584,44 @@ function LuCI2()
 
                },
 
-               changes: _luci2.rpc.declare({
+               configs: _luci2.rpc.declare({
+                       object: 'uci',
+                       method: 'configs',
+                       expect: { configs: [ ] }
+               }),
+
+               _changes: _luci2.rpc.declare({
                        object: 'uci',
                        method: 'changes',
                        params: [ 'config' ],
                        expect: { changes: [ ] }
                }),
 
+               changes: function(config)
+               {
+                       if (typeof(config) == 'string')
+                               return this._changes(config);
+
+                       var configlist;
+                       return this.configs().then(function(configs) {
+                               _luci2.rpc.batch();
+                               configlist = configs;
+
+                               for (var i = 0; i < configs.length; i++)
+                                       _luci2.uci._changes(configs[i]);
+
+                               return _luci2.rpc.flush();
+                       }).then(function(changes) {
+                               var rv = { };
+
+                               for (var i = 0; i < configlist.length; i++)
+                                       if (changes[i].length)
+                                               rv[configlist[i]] = changes[i];
+
+                               return rv;
+                       });
+               },
+
                commit: _luci2.rpc.declare({
                        object: 'uci',
                        method: 'commit',
@@ -2053,12 +2084,90 @@ function LuCI2()
                        });
                },
 
+               updateChanges: function()
+               {
+                       return _luci2.uci.changes().then(function(changes) {
+                               var n = 0;
+                               var html = '';
+
+                               for (var config in changes)
+                               {
+                                       var log = [ ];
+
+                                       for (var i = 0; i < changes[config].length; i++)
+                                       {
+                                               var c = changes[config][i];
+
+                                               switch (c[0])
+                                               {
+                                               case 'order':
+                                                       break;
+
+                                               case 'remove':
+                                                       if (c.length < 3)
+                                                               log.push('uci delete %s.<del>%s</del>'.format(config, c[1]));
+                                                       else
+                                                               log.push('uci delete %s.%s.<del>%s</del>'.format(config, c[1], c[2]));
+                                                       break;
+
+                                               case 'rename':
+                                                       if (c.length < 4)
+                                                               log.push('uci rename %s.<ins>%s=<strong>%s</strong></ins>'.format(config, c[1], c[2], c[3]));
+                                                       else
+                                                               log.push('uci rename %s.%s.<ins>%s=<strong>%s</strong></ins>'.format(config, c[1], c[2], c[3], c[4]));
+                                                       break;
+
+                                               case 'add':
+                                                       log.push('uci add %s (= <ins><strong>%s</strong></ins>)'.format(config, c[1]));
+                                                       break;
+
+                                               case 'list-add':
+                                                       log.push('uci add_list %s.%s.<ins>%s=<strong>%s</strong></ins>'.format(config, c[1], c[2], c[3], c[4]));
+                                                       break;
+
+                                               case 'list-del':
+                                                       log.push('uci del_list %s.%s.<del>%s=<strong>%s</strong></del>'.format(config, c[1], c[2], c[3], c[4]));
+                                                       break;
+
+                                               case 'set':
+                                                       if (c.length < 4)
+                                                               log.push('uci set %s.<ins>%s=<strong>%s</strong></ins>'.format(config, c[1], c[2]));
+                                                       else
+                                                               log.push('uci set %s.%s.<ins>%s=<strong>%s</strong></ins>'.format(config, c[1], c[2], c[3], c[4]));
+                                                       break;
+                                               }
+                                       }
+
+                                       html += '<code>/etc/config/%s</code><pre class="uci-changes">%s</pre>'.format(config, log.join('\n'));
+                                       n += changes[config].length;
+                               }
+
+                               if (n > 0)
+                                       $('#changes')
+                                               .empty()
+                                               .show()
+                                               .append($('<a />')
+                                                       .attr('href', '#')
+                                                       .addClass('label')
+                                                       .addClass('notice')
+                                                       .text(_luci2.trcp('Pending configuration changes', '1 change', '%d changes', n).format(n))
+                                                       .click(function(ev) {
+                                                               _luci2.ui.dialog(_luci2.tr('Staged configuration changes'), html, { style: 'close' });
+                                                               ev.preventDefault();
+                                                       }));
+                               else
+                                       $('#changes')
+                                               .hide();
+                       });
+               },
+
                init: function()
                {
                        _luci2.ui.loading(true);
 
                        $.when(
                                _luci2.ui.updateHostname(),
+                               _luci2.ui.updateChanges(),
                                _luci2.ui.renderMainMenu()
                        ).then(function() {
                                _luci2.ui.renderView(_luci2.globals.defaultNode).then(function() {
@@ -5396,7 +5505,9 @@ function LuCI2()
                                                        _luci2.uci['delete'](c, s, (o === true) ? undefined : o);
                                                }
 
-                               return _luci2.rpc.flush();
+                               return _luci2.rpc.flush().then(function() {
+                                       return _luci2.ui.updateChanges();
+                               });
                        }, this));
 
                        var self = this;