On 02/20/2014 03:21 AM, Aline Manera wrote:

The "Update All" link is still disabled even when there are packages to be updated.

Also I'd suggest to remove the horizontal scroll bar as it is not needed.

More comments below
Agree. Though seems it's a bug in grid widget. The initial width of the grid content is always a little larger than the grid width so horizontal scroll bar appears. Let's track it in another issue with a lower priority.

On 02/18/2014 12:06 AM, Hongliang Wang wrote:
Added UI support for software updating. The Host Tab will initially
list available updates to user if there are any; or we will disable
"Update All" Button if no updates available.

V1 -> V2:
   2a) Fixed "Update All" Button always being disabled issue
       (Thanks to Paulo Ricardo Paz Vital's comment)

Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com>
---
  ui/css/theme-default/host.css | 22 +++++++++++++++
  ui/js/src/kimchi.api.js       | 52 ++++++++++++++++++++++++++++++++++
  ui/js/src/kimchi.host.js      | 65 +++++++++++++++++++++++++++++++++++++++++++
  ui/pages/i18n.html.tmpl       |  9 ++++++
  ui/pages/tabs/host.html.tmpl  | 13 +++++++++
  5 files changed, 161 insertions(+)

diff --git a/ui/css/theme-default/host.css b/ui/css/theme-default/host.css
index 67daeaf..1342ade 100644
--- a/ui/css/theme-default/host.css
+++ b/ui/css/theme-default/host.css
@@ -227,3 +227,25 @@
      width: 300px;
  }
  /* End of Debug Report */
+
+/* Software Updates */
+.host-panel #software-updates-grid {
+    border-color: #ddd;
+    height: 300px;
+    width: 850px;
+}
+
+.software-update-id {
+    width: 30px;
+}
+
+.software-update-name,
+.software-update-repos {
+    width: 220px;
+}
+
+.software-update-version,
+.software-update-arch {
+    width: 190px;
+}
+/* End of Software Updates */
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index 6433fe0..c3a9516 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -731,5 +731,57 @@ var kimchi = {
              success : suc,
              error : err
          });
+    },
+
+    listSoftwareUpdates : function(suc, err) {
+        kimchi.requestJSON({
+            url : kimchi.url + 'host/packagesupdate',
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            resend: true,
+            success : suc,
+            error : err
+        });
+    },
+
+    updateSoftwares : function(suc, err) {
+        var taskID = -1;
+        var onResponse = function(data) {
+            taskID = data['id'];
+            trackTask();
+        };
+
+        var trackTask = function() {
+            kimchi.getTask(taskID, onTaskResponse, err);
+        };
+
+        var onTaskResponse = function(result) {
+            var taskStatus = result['status'];
+            switch(taskStatus) {
+            case 'running':
+                setTimeout(function() {
+                    trackTask();
+                }, 200);
+                break;
+            case 'finished':
+                suc(result);
+                break;
+            case 'failed':
+                err(result);
+                break;
+            default:
+                break;
+            }
+        };

In the 'message' parameter from task, there will be the update output process.
I think would be good to show it to user - but I don't know where in the window

example:

Add a tab to the update grid with "Update output" where we can show the user the update progress
Good point!

For a complete coverage, we need consider following cases:

1. No Updates Available
    Disable "Update All" Button and list nothing in the grid.

2. There are Updates Found

    User Logged in Kimchi First Time and He Found Available Updates
    Because it's the first time the user found available updates and no action was taken before, so enable "Update All" Button here.
    User operations and system processes:
    #1 Clicks "Update All" Button
    #2 UI disable the button and send request to update software
    #3 Back-end stores the status of the update process (/task can be used by UI to track it)
    #4 User intentionally close the browser or the browser crashes so the user reopens browser to log in Kimchi
    #5 Because updating is time-consuming, so the task is still running. Here the UI should disable the "Update All" Button and set the content of the button with "Updating..." to tell the user the progress. So you can find that we need provide a "progress" here such as 10%, 20%, etc. to let user know the progress at any time.
    #6 After updating completed, list available updates again and if there is any, enable "Update All" Button at the same time.

Potential Effort
    The recommended enhancement for above includes:

    1) Add a property to host status like:
    GET /host

    {
        // ...
        "swupdate": {
            "status": "processing or running",
            "taskid": "1"
        },
        "status": "running"
    }

    2) Enhance task to allow showing progress like:
    GET /task/1

    {
        "id": 1,
        "status": "running",
        "progress": 0.5
    }

    3) For UI, we need a new visual widget: progress widget and integrate it with grid widget.

Conclusion

As discussed above, extra effort is needed for the task, so I suggest add a new item in enhancement and defer it to next release.

+
+        kimchi.requestJSON({
+            url : kimchi.url + 'host/packagesupdate/update',

Need to adjust it according to the latest patches

/host/swupdate
ACK.

+            type : "POST",
+            contentType : "application/json",
+            dataType : "json",
+            success : onResponse,
+            error : err
+        });
      }
  };
diff --git a/ui/js/src/kimchi.host.js b/ui/js/src/kimchi.host.js
index a5c341b..b6a5878 100644
--- a/ui/js/src/kimchi.host.js
+++ b/ui/js/src/kimchi.host.js
@@ -131,6 +131,69 @@ kimchi.host_main = function() {
          });
      };

+    var softwareUpdatesGridID = 'software-updates-grid';
+    var softwareUpdatesGrid = null;
+    var initSoftwareUpdatesGrid = function(softwareUpdates) {
+        softwareUpdatesGrid = new kimchi.widget.Grid({
+            container: 'software-updates-grid-container',
+            id: softwareUpdatesGridID,
+            title: i18n['KCHUPD6001M'],
+            toolbarButtons: [{
+                id: softwareUpdatesGridID + '-update-button',
+                label: i18n['KCHUPD6006M'],
+                disabled: true,
+                onClick: function(event) {
+                    var updateButton = $(this);
+                    $(updateButton).text(i18n['KCHUPD6007M']).prop('disabled', true);
+                    kimchi.updateSoftwares(function(result) {
+                        $(updateButton).text(i18n['KCHUPD6006M']).prop('disabled', false);
+                    });
+                }
+            }],
+            frozenFields: [{
+                name: 'id',
+                label: ' ',
+                'class': 'software-update-id'
+            }],
+            fields: [{
+                name: 'package_name',
+                label: i18n['KCHUPD6002M'],
+                'class': 'software-update-name'
+            }, {
+                name: 'version',
+                label: i18n['KCHUPD6003M'],
+                'class': 'software-update-version'
+            }, {
+                name: 'arch',
+                label: i18n['KCHUPD6004M'],
+                'class': 'software-update-arch'
+            }, {
+                name: 'repository',
+                label: i18n['KCHUPD6005M'],
+                'class': 'software-update-repos'
+            }],
+            data: softwareUpdates
+        });
+    };
+
+    var listSoftwareUpdates = function() {
+        kimchi.listSoftwareUpdates(function(softwareUpdates) {
+            $.each(softwareUpdates, function(i, item) {
+                softwareUpdates[i]['id'] = i + 1;
+            });
+
+            if(softwareUpdatesGrid) {
+                softwareUpdatesGrid.setData(softwareUpdates);
+            }
+            else {
+                initSoftwareUpdatesGrid(softwareUpdates);
+            }
+
+            $(softwareUpdatesGridID + '-update-button')
+                .prop('disabled', softwareUpdates.length === 0);
+        });
+    };
+
      var shutdownButtonID = '#host-button-shutdown';
      var restartButtonID = '#host-button-restart';
      var shutdownHost = function(params) {
@@ -189,6 +252,8 @@ kimchi.host_main = function() {
              kimchi.keepMonitoringHost = this['checked'];
          });

+        listSoftwareUpdates();
+
          kimchi.getCapabilities(function(capabilities) {
              if(!capabilities['system_report_tool']) {
                  return;
diff --git a/ui/pages/i18n.html.tmpl b/ui/pages/i18n.html.tmpl
index 098a0a9..a9d86b3 100644
--- a/ui/pages/i18n.html.tmpl
+++ b/ui/pages/i18n.html.tmpl
@@ -94,6 +94,15 @@ var i18n = {
      'KCHDR6010M': "$_("Download")",


+    'KCHUPD6001M': "$_("Software Updates")",
+    'KCHUPD6002M': "$_("Package Name")",
+    'KCHUPD6003M': "$_("Version")",
+    'KCHUPD6004M': "$_("Architecture")",
+    'KCHUPD6005M': "$_("Repository")",
+    'KCHUPD6006M': "$_("Update All")",
+    'KCHUPD6007M': "$_("Updating...")",
+
+
      'KCHVM6001M': "$_("This will delete the virtual machine and its virtual disks. This operation cannot be undone. Would you like to continue?")",

      'KCHNET6001E': "$_("The VLAN id must be between 1 and 4094.")",
diff --git a/ui/pages/tabs/host.html.tmpl b/ui/pages/tabs/host.html.tmpl
index d32773a..1de4fcd 100644
--- a/ui/pages/tabs/host.html.tmpl
+++ b/ui/pages/tabs/host.html.tmpl
@@ -123,6 +123,19 @@
                      </div>
                  </div>
              </div>
+            <div id="software-update-section" class="host-section">
+                <h3 class="section-header"
+                    aria-controls="content-software-update">
+                    $_("Software Updates")
+                </h3>
+                <div id="content-software-update" class="section-content">
+                    <div class="section-row">
+                        <div class="section-value">
+                            <div id="software-updates-grid-container"></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
              <div id="debug-report-section" class="host-section hidden">
                  <h3 class="section-header"
                      aria-controls="content-sys-reports">