[Kimchi-devel] [PATCH 12/17] Ginger Base : base plugin ui/js files

chandra at linux.vnet.ibm.com chandra at linux.vnet.ibm.com
Tue Sep 1 18:01:30 UTC 2015


From: chandrureddy <chandra at linux.vnet.ibm.com>

---
 plugins/gingerbase/ui/js/Makefile.am               |  27 +
 plugins/gingerbase/ui/js/src/gingerbase.api.js     | 371 +++++++++
 plugins/gingerbase/ui/js/src/gingerbase.form.js    |  48 ++
 plugins/gingerbase/ui/js/src/gingerbase.grid.js    | 528 +++++++++++++
 plugins/gingerbase/ui/js/src/gingerbase.host.js    | 859 +++++++++++++++++++++
 .../gingerbase/ui/js/src/gingerbase.line-chart.js  | 202 +++++
 plugins/gingerbase/ui/js/src/gingerbase.main.js    |  26 +
 .../ui/js/src/gingerbase.report_add_main.js        |  72 ++
 .../ui/js/src/gingerbase.report_rename_main.js     |  66 ++
 .../ui/js/src/gingerbase.repository_add_main.js    |  96 +++
 .../ui/js/src/gingerbase.repository_edit_main.js   |  74 ++
 plugins/gingerbase/ui/js/src/gingerbase.select.js  |  50 ++
 plugins/gingerbase/ui/js/widgets/circleGauge.js    | 100 +++
 plugins/kimchi/ui/js/src/kimchi.host.js            | 858 --------------------
 plugins/kimchi/ui/js/src/kimchi.report_add_main.js |  72 --
 .../kimchi/ui/js/src/kimchi.report_rename_main.js  |  66 --
 .../kimchi/ui/js/src/kimchi.repository_add_main.js |  96 ---
 .../ui/js/src/kimchi.repository_edit_main.js       |  74 --
 18 files changed, 2519 insertions(+), 1166 deletions(-)
 create mode 100644 plugins/gingerbase/ui/js/Makefile.am
 create mode 100644 plugins/gingerbase/ui/js/src/gingerbase.api.js
 create mode 100644 plugins/gingerbase/ui/js/src/gingerbase.form.js
 create mode 100644 plugins/gingerbase/ui/js/src/gingerbase.grid.js
 create mode 100644 plugins/gingerbase/ui/js/src/gingerbase.host.js
 create mode 100644 plugins/gingerbase/ui/js/src/gingerbase.line-chart.js
 create mode 100644 plugins/gingerbase/ui/js/src/gingerbase.main.js
 create mode 100644 plugins/gingerbase/ui/js/src/gingerbase.report_add_main.js
 create mode 100644 plugins/gingerbase/ui/js/src/gingerbase.report_rename_main.js
 create mode 100644 plugins/gingerbase/ui/js/src/gingerbase.repository_add_main.js
 create mode 100644 plugins/gingerbase/ui/js/src/gingerbase.repository_edit_main.js
 create mode 100644 plugins/gingerbase/ui/js/src/gingerbase.select.js
 create mode 100644 plugins/gingerbase/ui/js/widgets/circleGauge.js
 delete mode 100644 plugins/kimchi/ui/js/src/kimchi.host.js
 delete mode 100644 plugins/kimchi/ui/js/src/kimchi.report_add_main.js
 delete mode 100644 plugins/kimchi/ui/js/src/kimchi.report_rename_main.js
 delete mode 100644 plugins/kimchi/ui/js/src/kimchi.repository_add_main.js
 delete mode 100644 plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js

diff --git a/plugins/gingerbase/ui/js/Makefile.am b/plugins/gingerbase/ui/js/Makefile.am
new file mode 100644
index 0000000..142ccdb
--- /dev/null
+++ b/plugins/gingerbase/ui/js/Makefile.am
@@ -0,0 +1,27 @@
+#
+# Kimchi
+#
+# Copyright IBM, Corp. 2013
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+EXTRA_DIST = src widgets
+
+jsdir = $(datadir)/wok/plugins/gingerbase/ui/js
+
+dist_js_DATA = gingerbase.min.js $(filter-out gingerbase.min.js, $(wildcard *.js))
+
+gingerbase.min.js: widgets/*.js src/*.js
+	cat $(sort $^) > $@
+
+CLEANFILES = gingerbase.min.js
diff --git a/plugins/gingerbase/ui/js/src/gingerbase.api.js b/plugins/gingerbase/ui/js/src/gingerbase.api.js
new file mode 100644
index 0000000..480f6fb
--- /dev/null
+++ b/plugins/gingerbase/ui/js/src/gingerbase.api.js
@@ -0,0 +1,371 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2013-2015
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+var kimchi = {
+
+    widget: {},
+
+    trackingTasks: [],
+
+    /**
+     *
+     * Get host capabilities
+     * suc: callback if succeed err: callback if failed
+     */
+    getCapabilities : function(suc, err, done) {
+        done = typeof done !== 'undefined' ? done: function(){};
+        wok.requestJSON({
+            url : "plugins/gingerbase/host/capabilities",
+            type : "GET",
+            contentType : "application/json",
+            dataType : "json",
+            success: suc,
+            error: err,
+            complete: done
+        });
+    },
+
+    /**
+     * Get the i18 strings.
+     */
+    getI18n: function(suc, err, url, sync) {
+        wok.requestJSON({
+            url : url ? url : 'plugins/gingerbase/i18n.json',
+            type : 'GET',
+            resend: true,
+            dataType : 'json',
+            async : !sync,
+            success : suc,
+            error: err
+        });
+    },
+
+    /**
+     * Get the host static information.
+     */
+    getHost: function(suc, err) {
+        wok.requestJSON({
+            url : 'plugins/gingerbase/host',
+            type : 'GET',
+            resend: true,
+            contentType : 'application/json',
+            dataType : 'json',
+            success : suc,
+            error: err
+        });
+    },
+
+    /**
+     * Get the dynamic host stats (usually used for monitoring).
+     */
+    getHostStats : function(suc, err) {
+        wok.requestJSON({
+            url : 'plugins/gingerbase/host/stats',
+            type : 'GET',
+            contentType : 'application/json',
+            headers: {'Wok-Robot': 'wok-robot'},
+            dataType : 'json',
+            success : suc,
+            error: err
+        });
+    },
+
+    /**
+     * Get the historic host stats.
+     */
+    getHostStatsHistory : function(suc, err) {
+        wok.requestJSON({
+            url : 'plugins/gingerbase/host/stats/history',
+            type : 'GET',
+            resend: true,
+            contentType : 'application/json',
+            headers: {'Wok-Robot': 'wok-robot'},
+            dataType : 'json',
+            success : suc,
+            error: err
+        });
+    },
+
+    getTask : function(taskId, suc, err) {
+        wok.requestJSON({
+            url : 'plugins/gingerbase/tasks/' + encodeURIComponent(taskId),
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            success : suc,
+            error : err
+        });
+    },
+
+    getTasksByFilter : function(filter, suc, err, sync) {
+        wok.requestJSON({
+            url : 'plugins/gingerbase/tasks?' + filter,
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            async : !sync,
+            success : suc,
+            error : err
+        });
+    },
+
+    listReports : function(suc, err) {
+        wok.requestJSON({
+            url : 'plugins/gingerbase/debugreports',
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            resend: true,
+            success : suc,
+            error : err
+        });
+    },
+
+    trackTask : function(taskID, suc, err, progress) {
+        var onTaskResponse = function(result) {
+            var taskStatus = result['status'];
+            switch(taskStatus) {
+            case 'running':
+                progress && progress(result);
+                setTimeout(function() {
+                    kimchi.trackTask(taskID, suc, err, progress);
+                }, 2000);
+                break;
+            case 'finished':
+                suc && suc(result);
+                break;
+            case 'failed':
+                err && err(result);
+                break;
+            default:
+                break;
+            }
+        };
+
+        kimchi.getTask(taskID, onTaskResponse, err);
+        if(kimchi.trackingTasks.indexOf(taskID) < 0)
+            kimchi.trackingTasks.push(taskID);
+    },
+
+    createReport: function(settings, suc, err, progress) {
+        var onResponse = function(data) {
+            taskID = data['id'];
+            kimchi.trackTask(taskID, suc, err, progress);
+        };
+
+        wok.requestJSON({
+            url : 'plugins/gingerbase/debugreports',
+            type : "POST",
+            contentType : "application/json",
+            data : JSON.stringify(settings),
+            dataType : "json",
+            success : onResponse,
+            error : err
+        });
+    },
+
+    renameReport : function(name, settings, suc, err) {
+        $.ajax({
+            url : "plugins/gingerbase/debugreports/" + encodeURIComponent(name),
+            type : 'PUT',
+            contentType : 'application/json',
+            data : JSON.stringify(settings),
+            dataType : 'json',
+            success: suc,
+            error: err
+        });
+    },
+
+    deleteReport: function(settings, suc, err) {
+        var reportName = encodeURIComponent(settings['name']);
+        wok.requestJSON({
+            url : 'plugins/gingerbase/debugreports/' + reportName,
+            type : 'DELETE',
+            contentType : 'application/json',
+            dataType : 'json',
+            success : suc,
+            error : err
+        });
+    },
+
+    downloadReport: function(settings, suc, err) {
+        window.open(settings['file']);
+    },
+
+    shutdown: function(settings, suc, err) {
+        var reboot = settings && settings['reboot'] === true;
+        var url = 'plugins/gingerbase/host/' + (reboot ? 'reboot' : 'shutdown');
+        wok.requestJSON({
+            url : url,
+            type : 'POST',
+            contentType : 'application/json',
+            dataType : 'json',
+            success : suc,
+            error : err
+        });
+    },
+
+    listHostPartitions : function(suc, err) {
+        wok.requestJSON({
+            url : 'plugins/gingerbase/host/partitions',
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            success : suc,
+            error : err
+        });
+    },
+
+    listSoftwareUpdates : function(suc, err) {
+        wok.requestJSON({
+            url : 'plugins/gingerbase/host/packagesupdate',
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            resend: true,
+            success : suc,
+            error : err
+        });
+    },
+
+    updateSoftware : function(suc, err, progress) {
+        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':
+                progress && progress(result);
+                setTimeout(function() {
+                    trackTask();
+                }, 200);
+                break;
+            case 'finished':
+            case 'failed':
+                suc(result);
+                break;
+            default:
+                break;
+            }
+        };
+
+        wok.requestJSON({
+            url : 'plugins/gingerbase/host/swupdate',
+            type : "POST",
+            contentType : "application/json",
+            dataType : "json",
+            success : onResponse,
+            error : err
+        });
+    },
+
+    createRepository : function(settings, suc, err) {
+        wok.requestJSON({
+            url : "plugins/gingerbase/host/repositories",
+            type : "POST",
+            contentType : "application/json",
+            data : JSON.stringify(settings),
+            dataType : "json",
+            success: suc,
+            error: err
+        });
+    },
+
+    retrieveRepository : function(repository, suc, err) {
+        var reposID = encodeURIComponent(repository);
+        wok.requestJSON({
+            url : "plugins/gingerbase/host/repositories/" + reposID,
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            success : suc,
+            error : err
+        });
+    },
+
+    updateRepository : function(name, settings, suc, err) {
+        var reposID = encodeURIComponent(name);
+        $.ajax({
+            url : "plugins/gingerbase/host/repositories/" + reposID,
+            type : 'PUT',
+            contentType : 'application/json',
+            data : JSON.stringify(settings),
+            dataType : 'json',
+            success : suc,
+            error : err
+        });
+    },
+
+    enableRepository : function(name, enable, suc, err) {
+        var reposID = encodeURIComponent(name);
+        $.ajax({
+            url : "plugins/gingerbase/host/repositories/" + reposID +
+                  '/' + (enable === true ? 'enable' : 'disable'),
+            type : 'POST',
+            contentType : 'application/json',
+            dataType : 'json',
+            success : suc,
+            error : err
+        });
+    },
+
+    deleteRepository : function(repository, suc, err) {
+        var reposID = encodeURIComponent(repository);
+        wok.requestJSON({
+            url : 'plugins/gingerbase/host/repositories/' + reposID,
+            type : 'DELETE',
+            contentType : 'application/json',
+            dataType : 'json',
+            success : suc,
+            error : err
+        });
+    },
+
+    listRepositories : function(suc, err) {
+        wok.requestJSON({
+            url : 'plugins/gingerbase/host/repositories',
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            resend: true,
+            success : suc,
+            error : err
+        });
+    },
+
+    getCPUInfo : function(suc, err) {
+        wok.requestJSON({
+            url : 'plugins/gingerbase/host/cpuinfo',
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            resend : true,
+            success : suc,
+            error : err ? err : function(data) {
+                wok.message.error(data.responseJSON.reason);
+            }
+        });
+    }
+};
diff --git a/plugins/gingerbase/ui/js/src/gingerbase.form.js b/plugins/gingerbase/ui/js/src/gingerbase.form.js
new file mode 100644
index 0000000..0bb7c4b
--- /dev/null
+++ b/plugins/gingerbase/ui/js/src/gingerbase.form.js
@@ -0,0 +1,48 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2013-2014
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function($) {
+    $.fn.serializeObject = function() {
+        var formDataArray = $(this).serializeArray();
+        var formData = new Object();
+        $.each(formDataArray, function(index, data) {
+            formData.setDeepValue(data.name, data.value);
+        });
+        return formData;
+    };
+}(jQuery));
+
+(function($) {
+    $.fn.fillWithObject = function(obj) {
+        $(this).find("input").each(function(){
+            switch($(this).attr('type')) {
+                case 'text':
+                    $(this).val(obj.getDeepValue($(this).attr("name")));
+                    break;
+                case 'radio':
+                case 'checkbox':
+                    var a=String($(this).val());
+                    var b=String(obj.getDeepValue($(this).attr("name")));
+                    $(this).prop("checked",(a==b));
+                    break;
+                default:
+                    break;
+                }
+            });
+     };
+}(jQuery));
diff --git a/plugins/gingerbase/ui/js/src/gingerbase.grid.js b/plugins/gingerbase/ui/js/src/gingerbase.grid.js
new file mode 100644
index 0000000..4553135
--- /dev/null
+++ b/plugins/gingerbase/ui/js/src/gingerbase.grid.js
@@ -0,0 +1,528 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2013-2015
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+kimchi.widget.Grid = function(opts) {
+    this.opts = $.extend({}, this.opts, opts);
+    this.createDOM();
+    this.reload();
+};
+
+kimchi.widget.Grid.prototype = (function() {
+    var htmlStr = [
+        '<div id="{id}" class="grid">',
+            '<div class="grid-content">',
+                '<div class="grid-header">',
+                    '<div class="grid-frozen-header-view">',
+                        '<table class="grid-frozen-header-container">',
+                        '</table>',
+                    '</div>',
+                    '<div class="grid-header-view">',
+                        '<div class="grid-header-wrapper">',
+                            '<table class="grid-header-container">',
+                            '</table>',
+                        '</div>',
+                    '</div>',
+                '</div>',
+                '<div class="grid-body">',
+                    '<div class="grid-frozen-body-view">',
+                        '<div class="grid-frozen-body-wrapper">',
+                            '<table class="grid-frozen-body-container">',
+                            '</table>',
+                        '</div>',
+                    '</div>',
+                    '<div class="grid-body-view">',
+                        '<div class="grid-body-wrapper">',
+                            '<table class="grid-body-container">',
+                            '</table>',
+                        '</div>',
+                    '</div>',
+                '</div>',
+                '<div class="grid-resizer-leftmost hidden"></div>',
+                '<div class="grid-resizer hidden"></div>',
+            '</div>',
+            '<div class="grid-footer"></div>',
+            '<div class="grid-mask hidden">',
+                '<div class="grid-loading">',
+                    '<div class="grid-loading-icon"></div>',
+                    '<div class="grid-loading-text">',
+                        '{loading}',
+                    '</div>',
+                '</div>',
+            '</div>',
+            '<div class="grid-message hidden">',
+                '<div class="grid-message-text">',
+                    '{message}',
+                    '<button class="retry-button btn-small">',
+                        '{buttonLabel}',
+                    '</button>',
+                '</div>',
+                '<div class="detailed-title">',
+                    '{detailedLabel}',
+                '</div>',
+                '<div class="detailed-text"></div>',
+            '</div>',
+        '</div>'
+    ].join('');
+
+    var CONTAINER_NORMAL = 0, CONTAINER_FROZEN = 1;
+
+    var setupHeaders = function(header, body, fields) {
+        var colGroup = $('<colgroup></colgroup>').appendTo(header);
+        var headerHeader = $('<thead></thead>');
+        var headerRow = $('<tr></tr>').appendTo(headerHeader);
+        $.each(fields || [], function(i, field) {
+            $('<col class="' +
+                field['class'] +
+            '"/>')
+                .appendTo(colGroup);
+            $('<th><div class="cell-text-wrapper">' +
+                field['label'] +
+            '</div></th>').appendTo(headerRow);
+        });
+        headerHeader.appendTo(header);
+
+        var totalWidth = 0;
+        $('col', colGroup).each(function(index, col) {
+            var width = $(col).width();
+            totalWidth += width;
+            $(col).css('width', width + 'px');
+        });
+        $(body).append(colGroup.clone());
+        return totalWidth;
+    };
+
+    var getValue = function(name, obj) {
+        var result=undefined;
+        if(!Array.isArray(name)) {
+            name=name.parseKey();
+        }
+        if(name.length!=0) {
+            var tmpName=name.shift();
+            if(obj[tmpName]!=undefined) {
+                    result=obj[tmpName];
+            }
+            if(name.length!=0) {
+                    result=getValue(name,obj[tmpName]);
+            }
+        }
+        return(result);
+    };
+
+    var fillBody = function(container, fields) {
+        var data = this.data;
+        var tbody = ($('tbody', container).length && $('tbody', container))
+            || $('<tbody></tbody>').appendTo(container);
+        tbody.empty();
+        $.each(data, function(i, row) {
+            var rowNode = $('<tr></tr>').appendTo(tbody);
+            $.each(fields, function(fi, field) {
+                var value = getValue(field['name'], row);
+                $('<td><div class="cell-text-wrapper"' +
+                    (field['makeTitle'] === true
+                        ? ' title="' + value + '"'
+                        : ''
+                    ) + '>' + value.toString() + '</div></td>'
+                ).appendTo(rowNode);
+            });
+        });
+    };
+
+    var fixTableLayout = function(style) {
+        $.each([
+            this.frozenHeaderContainer,
+            this.headerContainer,
+            this.frozenBodyContainer,
+            this.bodyContainer
+        ], function(i, tableNode) {
+            $(tableNode).css('table-layout', style || 'fixed');
+        });
+    };
+
+    var initResizing = function(event) {
+        var resizer = event.data.resizer;
+        var pageX = event.pageX;
+        var tailPos = $(this).width() + $(this).offset()['left'];
+        var atResizer = Math.abs(pageX - tailPos) <= 2;
+        var isResizing = !$(resizer).hasClass('hidden');
+        $('body')[(atResizer || isResizing)
+            ? 'addClass'
+            : 'removeClass'
+        ]('resizing');
+    };
+
+    var clearResizing = function(event) {
+        $(event.data.resizer).hasClass('hidden') &&
+            $('body').removeClass('resizing');
+    };
+
+    var stylingRow = function(row, className, add) {
+        var index = $(row).index() + 1;
+        $('tr', this.frozenBodyContainer)
+            .removeClass(className);
+        $('tr', this.bodyContainer)
+            .removeClass(className);
+
+        if(add === false) {
+            return;
+        }
+
+        $('tr:nth-child(' + index + ')', this.frozenBodyContainer)
+            .addClass(className);
+        $('tr:nth-child(' + index + ')', this.bodyContainer)
+            .addClass(className);
+    };
+
+    var setBodyListeners = function() {
+        if(this['opts']['rowSelection'] != 'disabled') {
+            $('tr', this.gridBody).on('mouseover', {
+                grid: this
+            }, function(event) {
+                if (! $(this).hasClass('no-hover'))
+                    stylingRow.call(event.data.grid, this, 'hover');
+            });
+
+            $('tr', this.gridBody).on('mouseout', {
+                grid: this
+            }, function(event) {
+                stylingRow.call(event.data.grid, this, 'hover', false);
+            });
+
+            $('tr', this.gridBody).on('click', {
+                grid: this
+            }, function(event) {
+                var grid = event.data.grid;
+                grid.selectedIndex = $(this).index();
+                stylingRow.call(grid, this, 'selected');
+                grid['opts']['onRowSelected'] && grid['opts']['onRowSelected']();
+            });
+        }
+
+        $('.grid-body-view', this.domNode).on('scroll', {
+            grid: this
+        }, function(event) {
+            var grid = event.data.grid;
+            $('.grid-header .grid-header-view', grid.domNode)
+                .prop('scrollLeft', this.scrollLeft);
+            $('.grid-body .grid-frozen-body-view', grid.domNode)
+                .prop('scrollTop', this.scrollTop);
+        });
+    };
+
+    var setData = function(data) {
+        this.data = data;
+        fillBody.call(this, this.frozenBodyContainer, this['opts']['frozenFields']);
+        fillBody.call(this, this.bodyContainer, this['opts']['fields']);
+        setBodyListeners.call(this);
+    };
+
+    var getSelected = function() {
+        return this.selectedIndex >= 0
+            ? this.data[this.selectedIndex]
+            : null;
+    };
+
+    var startResizing = function(container, event) {
+        var grid = event.data.grid;
+        kimchi.widget.Grid.beingResized = grid;
+        if(!($('body').hasClass('resizing')
+                && $(grid.resizer).hasClass('hidden'))) {
+            return;
+        }
+
+        grid.columnBeingResized = container;
+        var pageX = event.pageX;
+        var gridOffsetX = grid.domNode.offset()['left'];
+        var leftmostOffsetX = $(container).offset()['left'] - gridOffsetX;
+        var left = pageX - gridOffsetX;
+        var contentHeight = $('.grid-content', grid.domNode).height();
+        $(grid.resizerLeftmost).css({
+            left: leftmostOffsetX + 'px',
+            height: contentHeight + 'px'
+        });
+        $(grid.resizer).css({
+            left: left + 'px',
+            height: contentHeight + 'px'
+        });
+        $(grid.resizerLeftmost).removeClass('hidden');
+        $(grid.resizer).removeClass('hidden');
+        event.preventDefault();
+    };
+
+    var endResizing = function(event) {
+        var grid = kimchi.widget.Grid.beingResized;
+        if(!$('body').hasClass('resizing')) {
+            return;
+        }
+        $(grid.resizerLeftmost).addClass('hidden');
+        $(grid.resizer).addClass('hidden');
+        $('body').removeClass('resizing');
+        var leftmostOffset = $(grid.columnBeingResized).offset()['left'];
+        var left = event.pageX;
+        if(leftmostOffset > left) {
+            return;
+        }
+        resizeColumnWidth.call(
+            grid,
+            $(grid.columnBeingResized).index(),
+            left - leftmostOffset
+        );
+        fixTableLayout.call(grid);
+        grid.columnBeingResized = null;
+        kimchi.widget.Grid.beingResized = null;
+    };
+
+    var resizeColumnWidth = function(index, width) {
+        var width = Math.ceil(width);
+        var widthArray = [];
+        var totalWidth = 0;
+        var header = this.headerContainer;
+        var body = this.bodyContainer;
+        if(this.containerBeingResized === CONTAINER_FROZEN) {
+            header = this.frozenHeaderContainer;
+            body = this.frozenBodyContainer;
+        }
+        $('col', header).each(function(i, colNode) {
+            var w = index === i ? width : $(colNode).width();
+            widthArray.push(w);
+            totalWidth += w;
+        });
+        $.each([header, body], function(i, container) {
+            container.css({
+                'table-layout': 'fixed',
+                width: totalWidth + 'px'
+            });
+            $('col:nth-child(' + (index + 1) + ')', container).css({
+                width: width + 'px'
+            });
+        });
+
+        if(this.containerBeingResized === CONTAINER_FROZEN) {
+            var headerView = $('.grid-header-view', this.domNode);
+            var bodyView = $('.grid-body-view', this.domNode);
+            $.each([headerView, bodyView], function(i, view) {
+                view.css({
+                    left: totalWidth + 'px'
+                });
+            });
+        }
+    };
+
+    var positionResizer = function(event) {
+        var grid = event.data.grid;
+        if($(grid.resizer).hasClass('hidden')) {
+            return;
+        }
+
+        var pageX = event.pageX;
+        var gridOffsetX = $(grid.domNode).offset()['left'];
+        var leftMost = $(grid.resizerLeftmost).position()['left'];
+        var offsetX = pageX - gridOffsetX;
+        offsetX = offsetX >= leftMost ? offsetX : leftMost;
+        $(grid.resizer).css('left', offsetX + 'px');
+    };
+
+    var showMessage = function(msg) {
+        $('.detailed-text', this.messageNode).text(msg);
+        $(this.messageNode).removeClass('hidden');
+    };
+
+    var hideMessage = function() {
+        $(this.messageNode).addClass('hidden');
+    };
+
+    var reload = function() {
+        var data = this['opts']['data'];
+        if(!data) {
+            return;
+        }
+
+        $(this.messageNode).addClass('hidden');
+
+        if($.isArray(data)) {
+            return this.setData(data);
+        }
+
+        if($.isFunction(data)) {
+            var loadData = data;
+            $(this.maskNode).removeClass('hidden');
+            loadData($.proxy(function(data) {
+                this.setData(data);
+                $(this.maskNode).addClass('hidden');
+            }, this));
+        }
+    };
+
+    var destroy = function() {
+        $('body').off('mousemove.grid#' + this['opts']['id'], positionResizer);
+        $('body').off('mouseup.grid#' + this['opts']['id'], endResizing);
+    };
+
+    var createDOM = function() {
+        var containerID = this['opts']['container'];
+        var container = $('#' + containerID);
+        var gridID = this['opts']['id'];
+        var rowSelection = this['opts']['rowSelection'] || 'single';
+        var domNode = $(wok.substitute(htmlStr, {
+            id: gridID,
+            loading: i18n['GGBGRD6001M'],
+            message: i18n['GGBGRD6002M'],
+            buttonLabel: i18n['GGBGRD6003M'],
+            detailedLabel: i18n['GGBGRD6004M']
+        })).appendTo(container);
+        this.domNode = domNode;
+
+        var height = domNode.height();
+        var width = domNode.width();
+
+        var title = this['opts']['title'];
+        var titleNode = null;
+        if(title) {
+            titleNode = $('<div class="grid-caption">' + title + '</div>')
+                .prependTo(domNode);
+        }
+
+        var toolbarButtons = this['opts']['toolbarButtons'];
+        var toolbarNode = null;
+        if(toolbarButtons) {
+            toolbarNode = $('<div class="grid-toolbar"></div>');
+            if(titleNode) {
+                titleNode.after(toolbarNode);
+            }
+            else {
+                toolbarNode.prependTo(domNode);
+            }
+
+            $.each(toolbarButtons, function(i, button) {
+                var btnHTML = [
+                    '<button',
+                        button['id'] ? (' id="' + button['id'] + '"') : '',
+                        ' class="grid-toolbar-button',
+                            button['class'] ? (' ' + button['class']) : '',
+                            '"',
+                            button['disabled'] === true ? ' disabled' : '',
+                            '>',
+                            button['label'],
+                    '</button>'
+                ].join('');
+                var btnNode = $(btnHTML).appendTo(toolbarNode);
+                button['onClick'] &&
+                    btnNode.on('click', button['onClick']);
+            });
+        }
+
+        var frozenHeaderContainer = $('.grid-frozen-header-container', domNode);
+        var frozenBodyContainer = $('.grid-frozen-body-container', domNode);
+        var frozenWidth = setupHeaders(
+                frozenHeaderContainer,
+                frozenBodyContainer,
+                this['opts']['frozenFields']
+        );
+        this.frozenHeaderContainer = frozenHeaderContainer;
+        this.frozenBodyContainer = frozenBodyContainer;
+
+        var headerContainer = $('.grid-header-container', domNode);
+        var bodyContainer = $('.grid-body-container', domNode);
+        setupHeaders(headerContainer, bodyContainer, this['opts']['fields']);
+        this.headerContainer = headerContainer;
+        this.bodyContainer = bodyContainer;
+
+        fixTableLayout.call(this, 'auto');
+
+        var gridContentNode = $('.grid-content', domNode);
+        var captionHeight = titleNode && $(titleNode).height() || 0;
+        var toolbarHeight = toolbarNode && $(toolbarNode).height() || 0;
+        gridContentNode.css('top', (captionHeight + toolbarHeight) + 'px');
+
+        var maskNode = $('.grid-mask', domNode);
+        maskNode.css('top', captionHeight + 'px');
+        this.maskNode = maskNode;
+
+        var messageNode = $('.grid-message', domNode);
+        messageNode.css('top', captionHeight + 'px');
+        this.messageNode = messageNode;
+
+        var headerView = $('.grid-header-view', domNode);
+        var bodyView = $('.grid-body-view', domNode);
+        headerView.css('left', (frozenWidth) + 'px');
+        bodyView.css('left', (frozenWidth) + 'px');
+
+        var bodyWidth = width - frozenWidth;
+        headerContainer.css('width', bodyWidth + 'px');
+        bodyContainer.css('width', bodyWidth + 'px');
+
+        fixTableLayout.call(this);
+
+        var gridBody = $('.grid-body', domNode);
+        this.gridBody = gridBody;
+        this.resizerLeftmost = $('.grid-resizer-leftmost', domNode);
+        this.resizer = $('.grid-resizer', domNode);
+        var gridHeader = $('.grid-header', domNode);
+        $('th', gridHeader).on('mouseover mousemove', {
+            resizer: this.resizer
+        }, initResizing);
+
+        $('th', gridHeader).on('mouseout', {
+            resizer: this.resizer
+        }, clearResizing);
+
+        this.containerBeingResized = CONTAINER_NORMAL;
+        $('th', frozenHeaderContainer).on('mousedown', {
+            grid: this
+        }, function(event) {
+                event.data.grid.containerBeingResized = CONTAINER_FROZEN;
+                startResizing(this, event);
+        });
+        $('th', headerContainer).on('mousedown', {
+            grid: this
+        }, function(event) {
+                event.data.grid.containerBeingResized = CONTAINER_NORMAL;
+                startResizing(this, event);
+        });
+
+        $('body').on('mousemove.grid#' + this['opts']['id'], {
+            grid: this
+        }, positionResizer);
+        $('body').on('mouseup.grid#' + this['opts']['id'], endResizing);
+
+        var data = this['opts']['data'];
+
+        $('.retry-button', domNode).on('click', {
+            grid: this
+        }, function(event) {
+            event.data.grid.reload();
+        });
+    };
+
+    return {
+        opts: {
+            container: null,
+            id: null,
+            rowSelection: 'single',
+            onRowSelected: null,
+            title: null,
+            toolbarButtons: null,
+            frozenFields: null,
+            fields: null
+        },
+        createDOM: createDOM,
+        setData: setData,
+        getSelected: getSelected,
+        reload: reload,
+        destroy: destroy,
+        showMessage: showMessage
+    };
+})();
diff --git a/plugins/gingerbase/ui/js/src/gingerbase.host.js b/plugins/gingerbase/ui/js/src/gingerbase.host.js
new file mode 100644
index 0000000..989461c
--- /dev/null
+++ b/plugins/gingerbase/ui/js/src/gingerbase.host.js
@@ -0,0 +1,859 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2013-2014
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+kimchi.host={};
+
+kimchi.host_main = function() {
+    var expand = function(header, toExpand) {
+        var controlledNode = $(header).attr('aria-controls');
+        $('#' + controlledNode)[toExpand ? 'removeClass' : 'addClass']('hidden');
+        $(header).attr('aria-expanded', toExpand ? 'true' : 'false');
+    };
+
+    var repositoriesGrid = null;
+    var initRepositoriesGrid = function(repo_type) {
+        var gridFields=[];
+        if (repo_type == "yum") {
+                gridFields=[{
+                    name: 'repo_id',
+                    label: i18n['GGBREPO6004M'],
+                    'class': 'repository-id'
+                }, {
+                    name: 'config[repo_name]',
+                    label: i18n['GGBREPO6005M'],
+                    'class': 'repository-name'
+                }, {
+                    name: 'enabled',
+                    label: i18n['GGBREPO6009M'],
+                    'class': 'repository-enabled'
+                }];
+        }
+        else if (repo_type == "deb") {
+                gridFields=[{
+                    name: 'baseurl',
+                    label: i18n['GGBREPO6006M'],
+                    makeTitle: true,
+                    'class': 'repository-baseurl deb'
+                }, {
+                    name: 'enabled',
+                    label: i18n['GGBREPO6009M'],
+                    'class': 'repository-enabled deb'
+                }, {
+                    name: 'config[dist]',
+                    label: "dist",
+                    'class': 'repository-gpgcheck deb'
+                }, {
+                    name: 'config[comps]',
+                    label: "comps",
+                    'class': 'repository-gpgcheck deb'
+                }];
+        }
+        else {
+            gridFields=[{
+                name: 'repo_id',
+                label: i18n['GGBREPO6004M'],
+                'class': 'repository-id'
+                }, {
+                    name: 'enabled',
+                    label: i18n['GGBREPO6009M'],
+                    'class': 'repository-enabled'
+                }, {
+                    name: 'baseurl',
+                    label: i18n['GGBREPO6006M'],
+                    makeTitle: true,
+                    'class': 'repository-baseurl'
+                }];
+        }
+        repositoriesGrid = new kimchi.widget.Grid({
+            container: 'repositories-grid-container',
+            id: 'repositories-grid',
+            title: i18n['GGBREPO6003M'],
+            toolbarButtons: [{
+                id: 'repositories-grid-add-button',
+                label: i18n['GGBREPO6012M'],
+                onClick: function(event) {
+                    wok.window.open({url:'plugins/gingerbase/repository-add.html',
+                                    class: repo_type});
+                }
+            }, {
+                id: 'repositories-grid-enable-button',
+                label: i18n['GGBREPO6016M'],
+                disabled: true,
+                onClick: function(event) {
+                    var repository = repositoriesGrid.getSelected();
+                    if(!repository) {
+                        return;
+                    }
+                    var name = repository['repo_id'];
+                    var enable = !repository['enabled'];
+                    $(this).prop('disabled', true);
+                    kimchi.enableRepository(name, enable, function() {
+                        wok.topic('kimchi/repositoryUpdated').publish();
+                    });
+                }
+            }, {
+                id: 'repositories-grid-edit-button',
+                label: i18n['GGBREPO6013M'],
+                disabled: true,
+                onClick: function(event) {
+                    var repository = repositoriesGrid.getSelected();
+                    if(!repository) {
+                        return;
+                    }
+                    kimchi.selectedRepository = repository['repo_id'];
+                    wok.window.open({url:'plugins/gingerbase/repository-edit.html',
+                                    class: repo_type});
+                }
+            }, {
+                id: 'repositories-grid-remove-button',
+                label: i18n['GGBREPO6014M'],
+                disabled: true,
+                onClick: function(event) {
+                    var repository = repositoriesGrid.getSelected();
+                    if(!repository) {
+                        return;
+                    }
+
+                    var settings = {
+                        title : i18n['GGBREPO6001M'],
+                        content : i18n['GGBREPO6002M'],
+                        confirm : i18n['GGBAPI6004M'],
+                        cancel : i18n['GGBAPI6003M']
+                    };
+
+                    wok.confirm(settings, function() {
+                        kimchi.deleteRepository(
+                            repository['repo_id'],
+                            function(result) {
+                                wok.topic('kimchi/repositoryDeleted').publish(result);
+                            }, function(error) {
+                            }
+                        );
+                    });
+                }
+            }],
+            onRowSelected: function(row) {
+                var repository = repositoriesGrid.getSelected();
+                if(!repository) {
+                    return;
+                }
+                $('#repositories-grid-remove-button').prop('disabled', false);
+                $('#repositories-grid-edit-button').prop('disabled', false);
+                var enabled = repository['enabled'];
+                $('#repositories-grid-enable-button')
+                    .text(i18n[enabled ? 'GGBREPO6017M' : 'GGBREPO6016M'])
+                    .prop('disabled', false);
+            },
+            frozenFields: [],
+            fields: gridFields,
+            data: listRepositories
+        });
+    };
+
+    var listRepositories = function(gridCallback) {
+        kimchi.listRepositories(function(repositories) {
+            if($.isFunction(gridCallback)) {
+                gridCallback(repositories);
+            }
+            else {
+                if(repositoriesGrid) {
+                    repositoriesGrid.setData(repositories);
+                }
+                else {
+                    initRepositoriesGrid();
+                    repositoriesGrid.setData(repositories);
+                }
+            }
+        },
+        function(error) {
+            var message = error && error['responseJSON'] && error['responseJSON']['reason'];
+
+            if($.isFunction(gridCallback)) {
+                gridCallback([]);
+            }
+            repositoriesGrid &&
+                repositoriesGrid.showMessage(message || i18n['GGBUPD6008M']);
+        });
+
+        $('#repositories-grid-remove-button').prop('disabled', true);
+        $('#repositories-grid-edit-button').prop('disabled', true);
+        $('#repositories-grid-enable-button').prop('disabled', true);
+    };
+
+    var softwareUpdatesGridID = 'software-updates-grid';
+    var softwareUpdatesGrid = null;
+    var progressAreaID = 'software-updates-progress-textarea';
+    var reloadProgressArea = function(result) {
+        var progressArea = $('#' + progressAreaID)[0];
+        $(progressArea).text(result['message']);
+        var scrollTop = $(progressArea).prop('scrollHeight');
+        $(progressArea).prop('scrollTop', scrollTop);
+    };
+
+    var initSoftwareUpdatesGrid = function(softwareUpdates) {
+        softwareUpdatesGrid = new kimchi.widget.Grid({
+            container: 'software-updates-grid-container',
+            id: softwareUpdatesGridID,
+            title: i18n['GGBUPD6001M'],
+            rowSelection: 'disabled',
+            toolbarButtons: [{
+                id: softwareUpdatesGridID + '-update-button',
+                label: i18n['GGBUPD6006M'],
+                disabled: true,
+                onClick: function(event) {
+                    var updateButton = $(this);
+                    var progressArea = $('#' + progressAreaID)[0];
+                    $('#software-updates-progress-container').removeClass('hidden');
+                    $(progressArea).text('');
+                    !wok.isElementInViewport(progressArea) &&
+                        progressArea.scrollIntoView();
+                    $(updateButton).text(i18n['GGBUPD6007M']).prop('disabled', true);
+
+                    kimchi.updateSoftware(function(result) {
+                        reloadProgressArea(result);
+                        $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false);
+                        wok.topic('kimchi/softwareUpdated').publish({
+                            result: result
+                        });
+                    }, function(error) {
+                        var message = error && error['responseJSON'] && error['responseJSON']['reason'];
+                        wok.message.error(message || i18n['GGBUPD6009M']);
+                        $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false);
+                    }, reloadProgressArea);
+                }
+            }],
+            frozenFields: [],
+            fields: [{
+                name: 'package_name',
+                label: i18n['GGBUPD6002M'],
+                'class': 'software-update-name'
+            }, {
+                name: 'version',
+                label: i18n['GGBUPD6003M'],
+                'class': 'software-update-version'
+            }, {
+                name: 'arch',
+                label: i18n['GGBUPD6004M'],
+                'class': 'software-update-arch'
+            }, {
+                name: 'repository',
+                label: i18n['GGBUPD6005M'],
+                'class': 'software-update-repos'
+            }],
+            data: listSoftwareUpdates
+        });
+    };
+
+    var listSoftwareUpdates = function(gridCallback) {
+        kimchi.listSoftwareUpdates(function(softwareUpdates) {
+            if($.isFunction(gridCallback)) {
+                gridCallback(softwareUpdates);
+            }
+            else {
+                if(softwareUpdatesGrid) {
+                    softwareUpdatesGrid.setData(softwareUpdates);
+                }
+                else {
+                    initSoftwareUpdatesGrid(softwareUpdates);
+                }
+            }
+
+            var updateButton = $('#' + softwareUpdatesGridID + '-update-button');
+            $(updateButton).prop('disabled', softwareUpdates.length === 0);
+        }, function(error) {
+            var message = error && error['responseJSON'] && error['responseJSON']['reason'];
+            if($.isFunction(gridCallback)) {
+                gridCallback([]);
+            }
+            softwareUpdatesGrid &&
+                softwareUpdatesGrid.showMessage(message || i18n['GGBUPD6008M']);
+        });
+    };
+
+    var reportGridID = 'available-reports-grid';
+    var reportGrid = null;
+    var enableReportButtons = function(toEnable) {
+        var buttonID = '#{grid}-{btn}-button';
+        $.each(['rename', 'remove', 'download'], function(i, n) {
+            $(wok.substitute(buttonID, {
+                grid: reportGridID,
+                btn: n
+            })).prop('disabled', !toEnable);
+        });
+    };
+    var initReportGrid = function(reports) {
+        reportGrid = new kimchi.widget.Grid({
+            container: 'available-reports-grid-container',
+            id: reportGridID,
+            title: i18n['GGBDR6002M'],
+            toolbarButtons: [{
+                id: reportGridID + '-generate-button',
+                label: i18n['GGBDR6006M'],
+                onClick: function(event) {
+                    wok.window.open('plugins/gingerbase/report-add.html');
+                }
+            }, {
+                id: reportGridID + '-rename-button',
+                label: i18n['GGBDR6008M'],
+                disabled: true,
+                onClick: function(event) {
+                    var report = reportGrid.getSelected();
+                    if(!report) {
+                        return;
+                    }
+
+                    kimchi.selectedReport = report['name'];
+                    wok.window.open('plugins/gingerbase/report-rename.html');
+                }
+            }, {
+                id: reportGridID + '-remove-button',
+                label: i18n['GGBDR6009M'],
+                disabled: true,
+                onClick: function(event) {
+                    var report = reportGrid.getSelected();
+                    if(!report) {
+                        return;
+                    }
+
+                    var settings = {
+                        title : i18n['GGBAPI6004M'],
+                        content : i18n['GGBDR6001M'],
+                        confirm : i18n['GGBAPI6002M'],
+                        cancel : i18n['GGBAPI6003M']
+                    };
+
+                    wok.confirm(settings, function() {
+                        kimchi.deleteReport({
+                            name: report['name']
+                        }, function(result) {
+                            listDebugReports();
+                        }, function(error) {
+                           wok.message.error(error.responseJSON.reason);
+                        });
+                    });
+                }
+            }, {
+                id: reportGridID + '-download-button',
+                label: i18n['GGBDR6010M'],
+                disabled: true,
+                onClick: function(event) {
+                    var report = reportGrid.getSelected();
+                    if(!report) {
+                        return;
+                    }
+
+                    kimchi.downloadReport({
+                        file: report['uri']
+                    });
+                }
+            }],
+            onRowSelected: function(row) {
+                var report = reportGrid.getSelected();
+                // Only enable report buttons if the selected line is not a
+                // pending report
+                if (report['time'] == i18n['GGBDR6007M']) {
+                    var gridElement = $('#'+ reportGridID);
+                    var row = $('tr:contains(' + report['name'] + ')', gridElement);
+                    enableReportButtons(false);
+                    row.attr('class', '');
+                }
+                else {
+                    enableReportButtons(true);
+                }
+            },
+            frozenFields: [],
+            fields: [{
+                name: 'name',
+                label: i18n['GGBDR6003M'],
+                'class': 'debug-report-name'
+            }, {
+                name: 'time',
+                label: i18n['GGBDR6005M'],
+                'class': 'debug-report-time'
+            }],
+            data: reports
+        });
+    };
+
+    var getPendingReports = function() {
+        var reports = []
+        var filter = 'status=running&target_uri=' + encodeURIComponent('^/plugins/gingerbase/debugreports/*')
+
+        kimchi.getTasksByFilter(filter, function(tasks) {
+            for(var i = 0; i < tasks.length; i++) {
+                reportName = tasks[i].target_uri.replace(/^\/plugins\/gingerbase\/debugreports\//, '') || i18n['GGBDR6012M'];
+                reports.push({'name': reportName, 'time': i18n['GGBDR6007M']})
+
+                if(kimchi.trackingTasks.indexOf(tasks[i].id) >= 0) {
+                    continue;
+                }
+
+                kimchi.trackTask(tasks[i].id, function(result) {
+                    wok.topic('kimchi/debugReportAdded').publish();
+                }, function(result) {
+                    // Error message from Async Task status
+                    if (result['message']) {
+                        var errText = result['message'];
+                    }
+                    // Error message from standard kimchi exception
+                    else {
+                        var errText = result['responseJSON']['reason'];
+                    }
+                    result && wok.message.error(errText);
+                    wok.topic('kimchi/debugReportAdded').publish();
+                }, null);
+            }
+        }, null, true);
+
+        return reports;
+    };
+
+    var listDebugReports = function() {
+        kimchi.listReports(function(reports) {
+            pendingReports = getPendingReports();
+            allReports = pendingReports.concat(reports);
+            $('#debug-report-section').removeClass('hidden');
+
+            // Row selection will be cleared so disable buttons here
+            enableReportButtons(false);
+
+            if(reportGrid) {
+                reportGrid.setData(allReports);
+            }
+            else {
+                initReportGrid(allReports);
+            }
+
+            // Set id-debug-img to pending reports
+            // It will display a loading icon
+            var gridElement = $('#' + reportGridID);
+                $.each($('td:contains(' + i18n['GGBDR6007M']  + ')', gridElement), function(index, row) {
+                $(row).parent().addClass('no-hover');
+                $(row).attr('id', 'id-debug-img');
+            });
+        }, function(error) {
+            if(error['status'] == 403) {
+                $('#debug-report-section').addClass('hidden');
+                return;
+            }
+            $('#debug-report-section').removeClass('hidden');
+        });
+    };
+
+    var shutdownButtonID = '#host-button-shutdown';
+    var restartButtonID = '#host-button-restart';
+    var shutdownHost = function(params) {
+        var settings = {
+            title : i18n['GGBAPI6004M'],
+            content : i18n['GGBHOST6008M'],
+            confirm : i18n['GGBAPI6002M'],
+            cancel : i18n['GGBAPI6003M']
+        };
+
+        wok.confirm(settings, function() {
+            kimchi.shutdown(params);
+            $(shutdownButtonID).prop('disabled', true);
+            $(restartButtonID).prop('disabled', true);
+            // Check if there is any VM is running.
+            // FIXME : Find alternative way to figure out if any vms running
+            // kimchi.listVMs(function(vms) {
+            //     for(var i = 0; i < vms.length; i++) {
+            //         if(vms[i]['state'] === 'running') {
+            //             wok.message.error.code('GGBHOST6001E');
+            //             $(shutdownButtonID).prop('disabled', false);
+            //             $(restartButtonID).prop('disabled', false);
+            //             return;
+            //         }
+            //     }
+            //
+            // });
+        }, function() {
+        });
+    };
+
+    var initPage = function() {
+        $('#host-info-container .section-header').each(function(i, header) {
+            $('<span class="arrow"></span>').prependTo(header);
+            var toExpand = $(header).attr('aria-expanded') !== 'false';
+            expand(header, toExpand);
+        });
+
+        $('#host-info-container').on('click', '.section-header', function(event) {
+            var toExpand = $(this).attr('aria-expanded') === 'false';
+            expand(this, toExpand);
+        });
+
+        $('#host-button-shutdown').on('click', function(event) {
+            shutdownHost(null);
+        });
+
+        $('#host-button-restart').on('click', function(event) {
+            shutdownHost({
+                reboot: true
+            });
+        });
+
+        var setupUI = function() {
+            if (kimchi.capabilities == undefined) {
+                setTimeout(setupUI, 2000);
+                return;
+            }
+
+            if((kimchi.capabilities['repo_mngt_tool']) && (kimchi.capabilities['repo_mngt_tool']!="None")) {
+                initRepositoriesGrid(kimchi.capabilities['repo_mngt_tool']);
+                $('#repositories-section').switchClass('hidden', kimchi.capabilities['repo_mngt_tool']);
+                wok.topic('kimchi/repositoryAdded')
+                    .subscribe(listRepositories);
+                wok.topic('kimchi/repositoryUpdated')
+                    .subscribe(listRepositories);
+                wok.topic('kimchi/repositoryDeleted')
+                    .subscribe(listRepositories);
+            }
+
+            if(kimchi.capabilities['update_tool']) {
+                $('#software-update-section').removeClass('hidden');
+                initSoftwareUpdatesGrid();
+                wok.topic('kimchi/softwareUpdated')
+                    .subscribe(listSoftwareUpdates);
+                $('#software-updates-progress-container').accordion({
+                    collapsible: true
+                });
+            }
+
+            if(kimchi.capabilities['system_report_tool']) {
+                listDebugReports();
+                wok.topic('kimchi/debugReportAdded')
+                    .subscribe(listDebugReports);
+                wok.topic('kimchi/debugReportRenamed')
+                    .subscribe(listDebugReports);
+            }
+        };
+        setupUI();
+    };
+
+    kimchi.getHost(function(data) {
+        var htmlTmpl = $('#host-tmpl').html();
+        data['logo'] = data['logo'] || '';
+        data['memory'] = wok.formatMeasurement(data['memory'], {
+            fixed: 2
+        });
+        var templated = wok.substitute(htmlTmpl, data);
+        $('#host-content-container').html(templated);
+
+        initPage();
+        initTracker();
+    });
+
+    var StatsMgr = function() {
+        var statsArray = {
+            cpu: {
+                u: {
+                    type: 'percent',
+                    legend: i18n['GGBHOST6002M'],
+                    points: []
+                }
+            },
+            memory: {
+                u: {
+                    type: 'value',
+                    base: 2,
+                    fixed: 2,
+                    legend: i18n['GGBHOST6003M'],
+                    points: []
+                }
+            },
+            diskIO: {
+                r: {
+                    type: 'value',
+                    base: 2,
+                    fixed: 2,
+                    unit: 'B/s',
+                    legend: i18n['GGBHOST6004M'],
+                    points: []
+                },
+                w: {
+                    type: 'value',
+                    base: 2,
+                    fixed: 2,
+                    unit: 'B/s',
+                    legend: i18n['GGBHOST6005M'],
+                    'class': 'disk-write',
+                    points: []
+                }
+            },
+            networkIO: {
+                r: {
+                    type: 'value',
+                    base: 2,
+                    fixed: 2,
+                    unit: 'B/s',
+                    legend: i18n['GGBHOST6006M'],
+                    points: []
+                },
+                s: {
+                    type: 'value',
+                    base: 2,
+                    fixed: 2,
+                    unit: 'B/s',
+                    legend: i18n['GGBHOST6007M'],
+                    'class': 'network-sent',
+                    points: []
+                }
+            }
+        };
+        var SIZE = 20;
+        var cursor = SIZE;
+
+        var add = function(stats) {
+            for(var key in stats) {
+                var item = stats[key];
+                for(var metrics in item) {
+                    var value = item[metrics]['v'];
+                    var max = item[metrics]['max'];
+                    var unifiedMetrics = statsArray[key][metrics];
+                    var ps = unifiedMetrics['points'];
+                    if(!Array.isArray(value)){
+                        ps.push(value);
+                        if(ps.length > SIZE + 1) {
+                            ps.shift();
+                        }
+                    }
+                    else{
+                        ps=ps.concat(value);
+                        ps.splice(0, ps.length-SIZE-1);
+                        unifiedMetrics['points']=ps;
+                    }
+                    if(max !== undefined) {
+                        unifiedMetrics['max'] = max;
+                    }
+                    else {
+                        if(unifiedMetrics['type'] !== 'value') {
+                            continue;
+                        }
+                        max = -Infinity;
+                        $.each(ps, function(i, value) {
+                            if(value > max) {
+                                max = value;
+                            }
+                        });
+                        if(max === 0) {
+                            ++max;
+                        }
+                        max *= 1.1;
+                        unifiedMetrics['max'] = max;
+                    }
+                }
+            }
+            cursor++;
+        };
+
+        var get = function(which) {
+            var stats = statsArray[which];
+            var lines = [];
+            for(var k in stats) {
+                var obj = stats[k];
+                var line = {
+                    type: obj['type'],
+                    base: obj['base'],
+                    unit: obj['unit'],
+                    fixed: obj['fixed'],
+                    legend: obj['legend']
+                };
+                if(obj['max']) {
+                    line['max'] = obj['max'];
+                }
+                if(obj['class']) {
+                    line['class'] = obj['class'];
+                }
+                var ps = obj['points'];
+                var numStats = ps.length;
+                var unifiedPoints = [];
+                $.each(ps, function(i, value) {
+                    unifiedPoints.push({
+                        x: cursor - numStats + i,
+                        y: value
+                    });
+                });
+                line['points'] = unifiedPoints;
+                lines.push(line);
+            }
+            return lines;
+        };
+
+        return {
+            add: add,
+            get: get
+        };
+    };
+
+    var Tracker = function(charts) {
+      var charts = charts;
+      var timer = null;
+      var statsPool = new StatsMgr();
+      var setCharts = function(newCharts) {
+          charts = newCharts;
+          for(var key in charts) {
+              var chart = charts[key];
+              chart.updateUI(statsPool.get(key));
+          }
+      };
+
+      var self = this;
+
+      var UnifyStats = function(stats) {
+          var result= {
+              cpu: {
+                  u: {
+                      v: stats['cpu_utilization']
+                  }
+              },
+              memory: {
+                  u: {
+                  }
+              },
+              diskIO: {
+                  r: {
+                      v: stats['disk_read_rate']
+                  },
+                  w: {
+                      v: stats['disk_write_rate']
+                  }
+              },
+              networkIO: {
+                  r: {
+                      v: stats['net_recv_rate']
+                  },
+                  s: {
+                      v: stats['net_sent_rate']
+                  }
+              }
+          };
+          if(Array.isArray(stats['memory'])){
+              result.memory.u['v']=[];
+              result.memory.u['max']=-Infinity;
+              for(var i=0;i<stats['memory'].length;i++){
+                  result.memory.u['v'].push(stats['memory'][i]['avail']);
+                  result.memory.u['max']=Math.max(result.memory.u['max'],stats['memory'][i]['total']);
+              }
+          }
+          else {
+              result.memory.u['v']=stats['memory']['avail'],
+              result.memory.u['max']=stats['memory']['total']
+          }
+          return(result);
+      };
+
+
+      var statsCallback = function(stats) {
+              var unifiedStats = UnifyStats(stats);
+              statsPool.add(unifiedStats);
+              for(var key in charts) {
+                  var chart = charts[key];
+                  chart.updateUI(statsPool.get(key));
+              }
+              timer = setTimeout(function() {
+                  continueTrack();
+              }, 1000);
+          };
+
+      var track = function() {
+          kimchi.getHostStatsHistory(statsCallback,
+            function() {
+                continueTrack();
+            });
+      };
+
+      var continueTrack = function() {
+          kimchi.getHostStats(statsCallback,
+            function() {
+                continueTrack();
+            });
+      };
+
+      var destroy = function() {
+          timer && clearTimeout(timer);
+          timer = null;
+      };
+
+      return {
+        setCharts: setCharts,
+        start: track,
+        stop: destroy
+      };
+    };
+
+    var initTracker = function() {
+        // TODO: Extend tabs with onUnload event to unregister timers.
+        if(kimchi.hostTimer) {
+            kimchi.hostTimer.stop();
+            delete kimchi.hostTimer;
+        }
+
+        var trackedCharts = {
+            cpu: new kimchi.widget.LineChart({
+                id: 'chart-cpu',
+                node: 'container-chart-cpu',
+                type: 'percent'
+            }),
+            memory: new kimchi.widget.LineChart({
+                id: 'chart-memory',
+                node: 'container-chart-memory',
+                type: 'value'
+            }),
+            diskIO: new kimchi.widget.LineChart({
+                id: 'chart-disk-io',
+                node: 'container-chart-disk-io',
+                type: 'value'
+            }),
+            networkIO: new kimchi.widget.LineChart({
+                id: 'chart-network-io',
+                node: 'container-chart-network-io',
+                type: 'value'
+            })
+        };
+
+        if(kimchi.hostTimer) {
+            kimchi.hostTimer.setCharts(trackedCharts);
+        }
+        else {
+            kimchi.hostTimer = new Tracker(trackedCharts);
+            kimchi.hostTimer.start();
+        }
+    };
+
+    $('#host-root-container').on('remove', function() {
+        if(kimchi.hostTimer) {
+            kimchi.hostTimer.stop();
+            delete kimchi.hostTimer;
+            }
+
+        repositoriesGrid && repositoriesGrid.destroy();
+        wok.topic('kimchi/repositoryAdded')
+            .unsubscribe(listRepositories);
+        wok.topic('kimchi/repositoryUpdated')
+            .unsubscribe(listRepositories);
+        wok.topic('kimchi/repositoryDeleted')
+            .unsubscribe(listRepositories);
+
+        softwareUpdatesGrid && softwareUpdatesGrid.destroy();
+        wok.topic('kimchi/softwareUpdated').unsubscribe(listSoftwareUpdates);
+
+        reportGrid && reportGrid.destroy();
+        wok.topic('kimchi/debugReportAdded').unsubscribe(listDebugReports);
+        wok.topic('kimchi/debugReportRenamed').unsubscribe(listDebugReports);
+    });
+};
diff --git a/plugins/gingerbase/ui/js/src/gingerbase.line-chart.js b/plugins/gingerbase/ui/js/src/gingerbase.line-chart.js
new file mode 100644
index 0000000..13bbee1
--- /dev/null
+++ b/plugins/gingerbase/ui/js/src/gingerbase.line-chart.js
@@ -0,0 +1,202 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2013-2014
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * new kimchi.widget.LineChart({
+ *   node: 'line-chart-cpu',
+ *   id: 'line-chart',
+ *   type: 'value'
+ * });
+ */
+kimchi.widget.LineChart = function(params) {
+    var container = $('#' + params['node']);
+    container.addClass('chart-container');
+    var height = container.height();
+    var width = container.width();
+    var numHLines = 4;
+    var linesSpace = height / numHLines;
+    var period = params['period'] || 20;
+    var xFactor = width / period;
+    var yFactor = height / 100;
+    var xStart = params['xStart'] || 0;
+    var linesOffset = 0;
+    var canvasID = params['id'];
+    var maxValue = params['maxValue'] || -Infinity;
+    var type = params['type'];
+    var chartVAxis = null;
+    var chartTitle = null;
+    var chartLegend = null;
+    var seriesMap = {};
+    var formatSettings = {};
+
+    var setMaxValue = function(newValue) {
+        maxValue = newValue;
+    };
+
+    /**
+     *
+     * settings: {
+     *   'class': 'disk-read-rate'
+     * }
+     */
+    var updateUI = function(data) {
+        var container = $('#' + params['node']);
+        if(!container.length) {
+            return;
+        }
+
+        if(!$.isArray(data)) {
+            data = [data];
+        }
+        var seriesCount = 0;
+        var singleSeries = data.length === 1;
+        var firstSeries = data[0];
+
+        // TODO: Multiple axes support.
+        if(type === 'value') {
+            $.each(data, function(i, series) {
+                if(series['max'] > maxValue) {
+                    maxValue = series['max'];
+                    formatSettings = {
+                        base: series['base'],
+                        unit: series['unit'],
+                        fixed: series['fixed']
+                    };
+                }
+            });
+        }
+
+        var canvasNode = $('#' + canvasID);
+        canvasNode.length && canvasNode.remove();
+        var htmlStr = [
+          '<svg id="', canvasID, '" class="line-chart"',
+              ' height="', height, '" width="', width, '"',
+          '>',
+            '<rect height="', height, '" width="', width, '" class="background" />'
+        ];
+
+        for(var x = linesOffset; x < width; x += linesSpace) {
+            htmlStr.push(
+                '<line x1="', x, '" y1="', 0, '" x2="', x, '" y2="', height, '" />'
+            );
+        }
+
+        linesOffset -= xFactor;
+        while(linesOffset < 0) {
+            linesOffset = linesSpace + linesOffset;
+        }
+
+        for(var y = height - linesSpace; y > 0; y -= linesSpace) {
+            htmlStr.push(
+                '<line x1="', 0, '" y1="', y, '" x2="', width, '" y2="', y, '" />'
+            );
+        }
+
+        var maxValueLabel = i18n['GGBHOST6001M'] + ' ' +
+            (type === 'value'
+                ? wok.formatMeasurement(maxValue, formatSettings)
+                : '100%');
+        if(!chartVAxis) {
+            chartVAxis = $('<div class="chart-vaxis-container">' +
+                maxValueLabel +
+                '</div>'
+            );
+            container.before(chartVAxis);
+        }
+        else {
+            chartVAxis.text(maxValueLabel);
+        }
+
+        seriesNames = [];
+        $.each(data, function(i, series) {
+            var points = series['points'];
+            var className = series['class'];
+            var latestPoint = points.slice(-1).pop();
+            xStart = latestPoint['x'] - period;
+
+            htmlStr.push('<polyline',
+                ' class="series', className ? ' ' + className : '', '"',
+                ' points="'
+            );
+            var first = true;
+            $.each(points, function(i, point) {
+                if(first) {
+                    first = false;
+                }
+                else {
+                    htmlStr.push(' ');
+                }
+
+                var x = xFactor * (point['x'] - xStart);
+                var y = height - yFactor * (type === 'value' ?
+                    point['y'] * 100 / maxValue :
+                    point['y']
+                );
+                htmlStr.push(x, ',', y);
+            });
+            htmlStr.push('" />');
+        });
+
+        htmlStr.push('</svg>');
+
+        var canvasNode = $(htmlStr.join('')).appendTo(container);
+
+        if(!chartLegend) {
+            chartLegend = $('<div class="chart-legend-container"></div>');
+            container.after(chartLegend);
+        }
+        else {
+            chartLegend.empty();
+        }
+        $('polyline.series', canvasNode).each(function(i, polyline) {
+            var wrapper = $('<div class="legend-wrapper"></div>')
+                .appendTo(chartLegend);
+            $([
+                '<svg class="legend-icon" width="20" height="10">',
+                    '<line x1="0" y1="5" x2="20" y2="5"/>',
+                '</svg>'
+            ].join('')).appendTo(wrapper);
+            $('line', wrapper).css({
+                stroke: $(polyline).css('stroke'),
+                'stroke-width': $(polyline).css('stroke-width')
+            });
+            var label = data[i]['legend'];
+            var base = data[i]['base'];
+            $('<label class="legend-label">' + label + '</label>')
+                .appendTo(wrapper);
+            var latestPoint = data[i]['points'].slice(-1).pop();
+            var latestValue = latestPoint['y'];
+            if(type === 'value') {
+                latestValue = wok.formatMeasurement(
+                    latestValue,
+                    formatSettings
+                );
+            }
+            else {
+                latestValue += '%';
+            }
+            $('<div class="latest-value">' + latestValue + '</div>')
+                .appendTo(wrapper);
+        });
+    };
+
+    return {
+        setMaxValue: setMaxValue,
+        updateUI: updateUI
+    }
+};
diff --git a/plugins/gingerbase/ui/js/src/gingerbase.main.js b/plugins/gingerbase/ui/js/src/gingerbase.main.js
new file mode 100644
index 0000000..2fdeb85
--- /dev/null
+++ b/plugins/gingerbase/ui/js/src/gingerbase.main.js
@@ -0,0 +1,26 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2013-2014
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+kimchi.capabilities = undefined;
+kimchi.getCapabilities(function(result) {
+    kimchi.capabilities = result;
+
+    if(kimchi.capabilities.federation=="on")
+        $('#peers').removeClass('hide-content');
+}, function() {
+    kimchi.capabilities = {};
+});
diff --git a/plugins/gingerbase/ui/js/src/gingerbase.report_add_main.js b/plugins/gingerbase/ui/js/src/gingerbase.report_add_main.js
new file mode 100644
index 0000000..87010b1
--- /dev/null
+++ b/plugins/gingerbase/ui/js/src/gingerbase.report_add_main.js
@@ -0,0 +1,72 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2013-2014
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+kimchi.report_add_main = function() {
+    var reportGridID = 'available-reports-grid';
+    var addReportForm = $('#form-report-add');
+    var submitButton = $('#button-report-add');
+    var nameTextbox = $('input[name="name"]', addReportForm);
+    nameTextbox.select();
+
+    var submitForm = function(event) {
+        if(submitButton.prop('disabled')) {
+            return false;
+        }
+        var reportName = nameTextbox.val();
+        var validator = RegExp("^[_A-Za-z0-9-]*$");
+        if (!validator.test(reportName)) {
+            wok.message.error.code('GGBDR6011M');
+            return false;
+        }
+        var formData = addReportForm.serializeObject();
+        var taskAccepted = false;
+        var onTaskAccepted = function() {
+            if(taskAccepted) {
+                return;
+            }
+            taskAccepted = true;
+            wok.window.close();
+            wok.topic('kimchi/debugReportAdded').publish();
+        };
+
+        kimchi.createReport(formData, function(result) {
+            onTaskAccepted();
+            wok.topic('kimchi/debugReportAdded').publish();
+        }, function(result) {
+            // Error message from Async Task status
+            if (result['message']) {
+                var errText = result['message'];
+            }
+            // Error message from standard kimchi exception
+            else {
+                var errText = result['responseJSON']['reason'];
+            }
+            result && wok.message.error(errText);
+
+            taskAccepted &&
+                $('.grid-body-view table tr:first-child',
+                    '#' + reportGridID).remove();
+            submitButton.prop('disabled', false);
+            nameTextbox.select();
+        }, onTaskAccepted);
+
+        event.preventDefault();
+    };
+
+    addReportForm.on('submit', submitForm);
+    submitButton.on('click', submitForm);
+};
diff --git a/plugins/gingerbase/ui/js/src/gingerbase.report_rename_main.js b/plugins/gingerbase/ui/js/src/gingerbase.report_rename_main.js
new file mode 100644
index 0000000..6134b2e
--- /dev/null
+++ b/plugins/gingerbase/ui/js/src/gingerbase.report_rename_main.js
@@ -0,0 +1,66 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2014
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+kimchi.report_rename_main = function() {
+    var renameReportForm = $('#form-report-rename');
+    var submitButton = $('#button-report-rename');
+    var nameTextbox = $('input[name="name"]', renameReportForm);
+    var submitForm = function(event) {
+        if(submitButton.prop('disabled')) {
+            return false;
+        }
+        var reportName = nameTextbox.val();
+
+        // if the user hasn't changed the report's name,
+        // nothing should be done.
+        if (reportName == kimchi.selectedReport) {
+            wok.message.error.code('GGBDR6013M');
+            return false;
+        }
+
+        var validator = RegExp("^[A-Za-z0-9-]*$");
+        if (!validator.test(reportName)) {
+            wok.message.error.code('GGBDR6011M');
+            return false;
+        }
+        var formData = renameReportForm.serializeObject();
+        submitButton.prop('disabled', true);
+        nameTextbox.prop('disabled', true);
+        kimchi.renameReport(kimchi.selectedReport, formData, function(result) {
+            submitButton.prop('disabled', false);
+            nameTextbox.prop('disabled', false);
+            wok.window.close();
+            wok.topic('kimchi/debugReportRenamed').publish({
+                result: result
+            });
+        }, function(result) {
+            var errText = result &&
+                result['responseJSON'] &&
+                result['responseJSON']['reason'];
+            wok.message.error(errText);
+            submitButton.prop('disabled', false);
+            nameTextbox.prop('disabled', false).focus();
+        });
+
+        event.preventDefault();
+    };
+
+    renameReportForm.on('submit', submitForm);
+    submitButton.on('click', submitForm);
+
+    nameTextbox.val(kimchi.selectedReport).select();
+};
diff --git a/plugins/gingerbase/ui/js/src/gingerbase.repository_add_main.js b/plugins/gingerbase/ui/js/src/gingerbase.repository_add_main.js
new file mode 100644
index 0000000..656306b
--- /dev/null
+++ b/plugins/gingerbase/ui/js/src/gingerbase.repository_add_main.js
@@ -0,0 +1,96 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2014
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+kimchi.repository_add_main = function() {
+
+    var addForm = $('#form-repository-add');
+    var addButton = $('#button-repository-add');
+
+    var validateField = function(event) {
+        var valid=($(this).val()!=='');
+        $(addButton).prop('disabled', !valid);
+        return(valid);
+    };
+
+    var validateForm = function(event) {
+        var valid=false;
+        addForm.find('input.required').each( function() {
+            valid=($(this).val()!=='');
+            return(!valid);
+        });
+        return(valid);
+    }
+
+    addForm.find('input.required').on('input propertychange', validateField);
+
+    var weedObject = function(obj) {
+        for (var key in obj) {
+            if (obj.hasOwnProperty(key)) {
+                if((typeof(obj[key])==="object") && !Array.isArray(obj[key])) {
+                    weedObject(obj[key]);
+                }
+                else if(obj[key] == '') {
+                    delete obj[key];
+                }
+            }
+        }
+    }
+
+    var addRepository = function(event) {
+        var valid = validateForm();
+        if(!valid) {
+            return false;
+        }
+
+        var formData = $(addForm).serializeObject();
+
+        if (formData && formData.isMirror!=undefined) {
+            formData.isMirror=(String(formData.isMirror).toLowerCase() === 'true');
+        }
+        if(formData.isMirror) {
+            if(formData.config==undefined) {
+                formData.config=new Object();
+            }
+            formData.config.mirrorlist=formData.baseurl;
+            delete formData.baseurl;
+            delete formData.isMirror;
+        }
+        weedObject(formData);
+        if(formData.config && formData.config.comps) {
+            formData.config.comps=formData.config.comps.split(/[,\s]/);
+            for(var i=0; i>formData.config.comps.length; i++) {
+                formData.config.comps[i]=formData.config.comps[i].trim();
+            }
+            for (var j=formData.config.comps.indexOf(""); j!=-1; j=formData.config.comps.indexOf("")) {
+                formData.config.comps.splice(j, 1);
+            }
+        }
+
+        kimchi.createRepository(formData, function() {
+            wok.topic('kimchi/repositoryAdded').publish();
+            wok.window.close();
+        }, function(jqXHR, textStatus, errorThrown) {
+            var reason = jqXHR &&
+                jqXHR['responseJSON'] &&
+                jqXHR['responseJSON']['reason'];
+            wok.message.error(reason);
+        });
+        return false;
+    };
+
+    $(addForm).on('submit', addRepository);
+};
diff --git a/plugins/gingerbase/ui/js/src/gingerbase.repository_edit_main.js b/plugins/gingerbase/ui/js/src/gingerbase.repository_edit_main.js
new file mode 100644
index 0000000..5bfc51e
--- /dev/null
+++ b/plugins/gingerbase/ui/js/src/gingerbase.repository_edit_main.js
@@ -0,0 +1,74 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2014
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+kimchi.repository_edit_main = function() {
+
+    var editForm = $('#form-repository-edit');
+
+    var saveButton = $('#repository-edit-button-save');
+
+    if(kimchi.capabilities['repo_mngt_tool']=="yum") {
+        editForm.find('input.deb').prop('disabled', true);
+    }
+    else if(kimchi.capabilities['repo_mngt_tool']=="deb") {
+        editForm.find('input.yum').prop('disabled', true);
+    }
+
+    kimchi.retrieveRepository(kimchi.selectedRepository, function(repository) {
+        editForm.fillWithObject(repository);
+
+        $('input', editForm).on('input propertychange', function(event) {
+            if($(this).val() !== '') {
+                $(saveButton).prop('disabled', false);
+            }
+        });
+    });
+
+
+    var editRepository = function(event) {
+        var formData = $(editForm).serializeObject();
+
+        if (formData && formData.config) {
+            formData.config.gpgcheck=(String(formData.config.gpgcheck).toLowerCase() === 'true');
+        }
+
+        if(formData.config && formData.config.comps) {
+            formData.config.comps=formData.config.comps.split(/[,\s]/);
+            for(var i=0; i>formData.config.comps.length; i++) {
+                formData.config.comps[i]=formData.config.comps[i].trim();
+            }
+            for (var j=formData.config.comps.indexOf(""); j!=-1; j=formData.config.comps.indexOf("")) {
+                formData.config.comps.splice(j, 1);
+            }
+        }
+
+        kimchi.updateRepository(kimchi.selectedRepository, formData, function() {
+            wok.topic('kimchi/repositoryUpdated').publish();
+            wok.window.close();
+        }, function(jqXHR, textStatus, errorThrown) {
+            var reason = jqXHR &&
+                jqXHR['responseJSON'] &&
+                jqXHR['responseJSON']['reason'];
+            wok.message.error(reason);
+        });
+
+        return false;
+    };
+
+    $(editForm).on('submit', editRepository);
+    $(saveButton).on('click', editRepository);
+};
diff --git a/plugins/gingerbase/ui/js/src/gingerbase.select.js b/plugins/gingerbase/ui/js/src/gingerbase.select.js
new file mode 100644
index 0000000..751167f
--- /dev/null
+++ b/plugins/gingerbase/ui/js/src/gingerbase.select.js
@@ -0,0 +1,50 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2013-2014
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+kimchi.select = function(id, options) {
+    var listControl = $('#'+ id);
+    var targetId = listControl.data('target');
+    var labelId = listControl.data('label');
+    var value = $('#' + targetId).val();
+    var item;
+    var itemTag = 'li';
+    var selectedClass = 'active';
+    $.each(options, function(index, option) {
+        item = $('<' + itemTag + '></' + itemTag + '>');
+        item.text(option.label);
+        item.data('value', option.value);
+        if(option.value === value) {
+            item.addClass(selectedClass);
+            $('#' + labelId).text(option.label);
+        }
+        listControl.append(item);
+    });
+
+    listControl.on('click', itemTag, function() {
+        listControl.children().removeClass(selectedClass);
+        $(this).addClass(selectedClass);
+        $('#' + labelId).text($(this).text());
+        var target = $('#' + targetId);
+        var oldValue = target.val();
+        var newValue = $(this).data('value');
+        target.val(newValue);
+        if(oldValue !== newValue) {
+            target.change();
+        }
+    });
+};
diff --git a/plugins/gingerbase/ui/js/widgets/circleGauge.js b/plugins/gingerbase/ui/js/widgets/circleGauge.js
new file mode 100644
index 0000000..32973ac
--- /dev/null
+++ b/plugins/gingerbase/ui/js/widgets/circleGauge.js
@@ -0,0 +1,100 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2014
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ (function($) {
+    $.widget('kimchi.circleGauge', {
+
+        options : {
+            color : '#87C004',
+            fillColor : '#87C004',
+            lineWidth : 20,
+            shadowSize : '2px',
+            font : 'bold 13px Geneva, sans-serif',
+            textAlign : 'center',
+            radius : 35,
+            peakRate : 100,
+            display : 0,
+            circle : 0,
+            label : ''
+        },
+
+        _create : function() {
+            //valuesAttr="{" + this.element.data('value')+ "}";
+            //console.info(valuesAttr);
+            //values=eval("(" + valuesAttr + ")");
+            //$.extend(this.options, values);
+            this.options.display=this.element.data('display');
+            this.options.percentage=this.element.data('percentage');
+            this._fixupPeakRate();
+            this._draw();
+        },
+
+        setValues : function(values) {
+            $.extend(this.options, values);
+            this._fixupPeakRate();
+            this._draw();
+        },
+
+        _fixupPeakRate : function() {
+            if (this.options.circle>this.options.peakRate) {
+                this.options.peakRate=this.options.circle;
+            }
+        },
+
+        _draw : function() {
+            this.element.empty();
+            var canvas = document.createElement('canvas');
+            //this.element.append($(canvas));  //I don't quite understand this line so trying the one below...
+            this.element.append(canvas);
+
+            var ctx = canvas.getContext('2d');
+            var radius = this.options.radius;
+
+            var shadowSize = 2;
+            var width = height = radius * 2;
+            $(canvas).attr('height', height);
+            $(canvas).attr('width', width);
+
+            $(canvas).css({
+                'boxShadow' : shadowSize + 'px ' + shadowSize + 'px ' + shadowSize + 'px #fff, -' + shadowSize + 'px -' + shadowSize + 'px ' + shadowSize + 'px #eaeaea',
+                borderRadius : radius + 'px'
+            });
+
+            ctx.clearRect(0, 0, width, height);
+            ctx.fillStyle = this.options.fillColor;
+            ctx.font = this.options.font;
+            ctx.textAlign = 'center';
+            var originPos = radius;
+            ctx.textBaseline = 'middle';
+            ctx.fillText(this.options.display, originPos, originPos);
+            ctx.strokeStyle = this.options.color;
+            ctx.lineWidth = this.options.lineWidth;
+            ctx.beginPath();
+            ctx.arc(originPos, originPos, radius, -.5 * Math.PI, (this.options.percentage / 50 - .5) * Math.PI);
+            ctx.stroke();
+        },
+
+        destroy : function() {
+            this.element.empty();
+            $.Widget.prototype.destroy.call(this);
+        }
+    });
+}(jQuery));
+
+kimchi.circleGauge = function(selector) {
+    $(selector).circleGauge();
+};
diff --git a/plugins/kimchi/ui/js/src/kimchi.host.js b/plugins/kimchi/ui/js/src/kimchi.host.js
deleted file mode 100644
index ab02333..0000000
--- a/plugins/kimchi/ui/js/src/kimchi.host.js
+++ /dev/null
@@ -1,858 +0,0 @@
-/*
- * Project Kimchi
- *
- * Copyright IBM, Corp. 2013-2014
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-kimchi.host={};
-
-kimchi.host_main = function() {
-    var expand = function(header, toExpand) {
-        var controlledNode = $(header).attr('aria-controls');
-        $('#' + controlledNode)[toExpand ? 'removeClass' : 'addClass']('hidden');
-        $(header).attr('aria-expanded', toExpand ? 'true' : 'false');
-    };
-
-    var repositoriesGrid = null;
-    var initRepositoriesGrid = function(repo_type) {
-        var gridFields=[];
-        if (repo_type == "yum") {
-                gridFields=[{
-                    name: 'repo_id',
-                    label: i18n['KCHREPO6004M'],
-                    'class': 'repository-id'
-                }, {
-                    name: 'config[repo_name]',
-                    label: i18n['KCHREPO6005M'],
-                    'class': 'repository-name'
-                }, {
-                    name: 'enabled',
-                    label: i18n['KCHREPO6009M'],
-                    'class': 'repository-enabled'
-                }];
-        }
-        else if (repo_type == "deb") {
-                gridFields=[{
-                    name: 'baseurl',
-                    label: i18n['KCHREPO6006M'],
-                    makeTitle: true,
-                    'class': 'repository-baseurl deb'
-                }, {
-                    name: 'enabled',
-                    label: i18n['KCHREPO6009M'],
-                    'class': 'repository-enabled deb'
-                }, {
-                    name: 'config[dist]',
-                    label: "dist",
-                    'class': 'repository-gpgcheck deb'
-                }, {
-                    name: 'config[comps]',
-                    label: "comps",
-                    'class': 'repository-gpgcheck deb'
-                }];
-        }
-        else {
-            gridFields=[{
-                name: 'repo_id',
-                label: i18n['KCHREPO6004M'],
-                'class': 'repository-id'
-                }, {
-                    name: 'enabled',
-                    label: i18n['KCHREPO6009M'],
-                    'class': 'repository-enabled'
-                }, {
-                    name: 'baseurl',
-                    label: i18n['KCHREPO6006M'],
-                    makeTitle: true,
-                    'class': 'repository-baseurl'
-                }];
-        }
-        repositoriesGrid = new kimchi.widget.Grid({
-            container: 'repositories-grid-container',
-            id: 'repositories-grid',
-            title: i18n['KCHREPO6003M'],
-            toolbarButtons: [{
-                id: 'repositories-grid-add-button',
-                label: i18n['KCHREPO6012M'],
-                onClick: function(event) {
-                    wok.window.open({url:'plugins/kimchi/repository-add.html',
-                                    class: repo_type});
-                }
-            }, {
-                id: 'repositories-grid-enable-button',
-                label: i18n['KCHREPO6016M'],
-                disabled: true,
-                onClick: function(event) {
-                    var repository = repositoriesGrid.getSelected();
-                    if(!repository) {
-                        return;
-                    }
-                    var name = repository['repo_id'];
-                    var enable = !repository['enabled'];
-                    $(this).prop('disabled', true);
-                    kimchi.enableRepository(name, enable, function() {
-                        wok.topic('kimchi/repositoryUpdated').publish();
-                    });
-                }
-            }, {
-                id: 'repositories-grid-edit-button',
-                label: i18n['KCHREPO6013M'],
-                disabled: true,
-                onClick: function(event) {
-                    var repository = repositoriesGrid.getSelected();
-                    if(!repository) {
-                        return;
-                    }
-                    kimchi.selectedRepository = repository['repo_id'];
-                    wok.window.open({url:'plugins/kimchi/repository-edit.html',
-                                    class: repo_type});
-                }
-            }, {
-                id: 'repositories-grid-remove-button',
-                label: i18n['KCHREPO6014M'],
-                disabled: true,
-                onClick: function(event) {
-                    var repository = repositoriesGrid.getSelected();
-                    if(!repository) {
-                        return;
-                    }
-
-                    var settings = {
-                        title : i18n['KCHREPO6001M'],
-                        content : i18n['KCHREPO6002M'],
-                        confirm : i18n['KCHAPI6004M'],
-                        cancel : i18n['KCHAPI6003M']
-                    };
-
-                    wok.confirm(settings, function() {
-                        kimchi.deleteRepository(
-                            repository['repo_id'],
-                            function(result) {
-                                wok.topic('kimchi/repositoryDeleted').publish(result);
-                            }, function(error) {
-                            }
-                        );
-                    });
-                }
-            }],
-            onRowSelected: function(row) {
-                var repository = repositoriesGrid.getSelected();
-                if(!repository) {
-                    return;
-                }
-                $('#repositories-grid-remove-button').prop('disabled', false);
-                $('#repositories-grid-edit-button').prop('disabled', false);
-                var enabled = repository['enabled'];
-                $('#repositories-grid-enable-button')
-                    .text(i18n[enabled ? 'KCHREPO6017M' : 'KCHREPO6016M'])
-                    .prop('disabled', false);
-            },
-            frozenFields: [],
-            fields: gridFields,
-            data: listRepositories
-        });
-    };
-
-    var listRepositories = function(gridCallback) {
-        kimchi.listRepositories(function(repositories) {
-            if($.isFunction(gridCallback)) {
-                gridCallback(repositories);
-            }
-            else {
-                if(repositoriesGrid) {
-                    repositoriesGrid.setData(repositories);
-                }
-                else {
-                    initRepositoriesGrid();
-                    repositoriesGrid.setData(repositories);
-                }
-            }
-        },
-        function(error) {
-            var message = error && error['responseJSON'] && error['responseJSON']['reason'];
-
-            if($.isFunction(gridCallback)) {
-                gridCallback([]);
-            }
-            repositoriesGrid &&
-                repositoriesGrid.showMessage(message || i18n['KCHUPD6008M']);
-        });
-
-        $('#repositories-grid-remove-button').prop('disabled', true);
-        $('#repositories-grid-edit-button').prop('disabled', true);
-        $('#repositories-grid-enable-button').prop('disabled', true);
-    };
-
-    var softwareUpdatesGridID = 'software-updates-grid';
-    var softwareUpdatesGrid = null;
-    var progressAreaID = 'software-updates-progress-textarea';
-    var reloadProgressArea = function(result) {
-        var progressArea = $('#' + progressAreaID)[0];
-        $(progressArea).text(result['message']);
-        var scrollTop = $(progressArea).prop('scrollHeight');
-        $(progressArea).prop('scrollTop', scrollTop);
-    };
-
-    var initSoftwareUpdatesGrid = function(softwareUpdates) {
-        softwareUpdatesGrid = new kimchi.widget.Grid({
-            container: 'software-updates-grid-container',
-            id: softwareUpdatesGridID,
-            title: i18n['KCHUPD6001M'],
-            rowSelection: 'disabled',
-            toolbarButtons: [{
-                id: softwareUpdatesGridID + '-update-button',
-                label: i18n['KCHUPD6006M'],
-                disabled: true,
-                onClick: function(event) {
-                    var updateButton = $(this);
-                    var progressArea = $('#' + progressAreaID)[0];
-                    $('#software-updates-progress-container').removeClass('hidden');
-                    $(progressArea).text('');
-                    !wok.isElementInViewport(progressArea) &&
-                        progressArea.scrollIntoView();
-                    $(updateButton).text(i18n['KCHUPD6007M']).prop('disabled', true);
-
-                    kimchi.updateSoftware(function(result) {
-                        reloadProgressArea(result);
-                        $(updateButton).text(i18n['KCHUPD6006M']).prop('disabled', false);
-                        wok.topic('kimchi/softwareUpdated').publish({
-                            result: result
-                        });
-                    }, function(error) {
-                        var message = error && error['responseJSON'] && error['responseJSON']['reason'];
-                        wok.message.error(message || i18n['KCHUPD6009M']);
-                        $(updateButton).text(i18n['KCHUPD6006M']).prop('disabled', false);
-                    }, reloadProgressArea);
-                }
-            }],
-            frozenFields: [],
-            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: listSoftwareUpdates
-        });
-    };
-
-    var listSoftwareUpdates = function(gridCallback) {
-        kimchi.listSoftwareUpdates(function(softwareUpdates) {
-            if($.isFunction(gridCallback)) {
-                gridCallback(softwareUpdates);
-            }
-            else {
-                if(softwareUpdatesGrid) {
-                    softwareUpdatesGrid.setData(softwareUpdates);
-                }
-                else {
-                    initSoftwareUpdatesGrid(softwareUpdates);
-                }
-            }
-
-            var updateButton = $('#' + softwareUpdatesGridID + '-update-button');
-            $(updateButton).prop('disabled', softwareUpdates.length === 0);
-        }, function(error) {
-            var message = error && error['responseJSON'] && error['responseJSON']['reason'];
-            if($.isFunction(gridCallback)) {
-                gridCallback([]);
-            }
-            softwareUpdatesGrid &&
-                softwareUpdatesGrid.showMessage(message || i18n['KCHUPD6008M']);
-        });
-    };
-
-    var reportGridID = 'available-reports-grid';
-    var reportGrid = null;
-    var enableReportButtons = function(toEnable) {
-        var buttonID = '#{grid}-{btn}-button';
-        $.each(['rename', 'remove', 'download'], function(i, n) {
-            $(wok.substitute(buttonID, {
-                grid: reportGridID,
-                btn: n
-            })).prop('disabled', !toEnable);
-        });
-    };
-    var initReportGrid = function(reports) {
-        reportGrid = new kimchi.widget.Grid({
-            container: 'available-reports-grid-container',
-            id: reportGridID,
-            title: i18n['KCHDR6002M'],
-            toolbarButtons: [{
-                id: reportGridID + '-generate-button',
-                label: i18n['KCHDR6006M'],
-                onClick: function(event) {
-                    wok.window.open('plugins/kimchi/report-add.html');
-                }
-            }, {
-                id: reportGridID + '-rename-button',
-                label: i18n['KCHDR6008M'],
-                disabled: true,
-                onClick: function(event) {
-                    var report = reportGrid.getSelected();
-                    if(!report) {
-                        return;
-                    }
-
-                    kimchi.selectedReport = report['name'];
-                    wok.window.open('plugins/kimchi/report-rename.html');
-                }
-            }, {
-                id: reportGridID + '-remove-button',
-                label: i18n['KCHDR6009M'],
-                disabled: true,
-                onClick: function(event) {
-                    var report = reportGrid.getSelected();
-                    if(!report) {
-                        return;
-                    }
-
-                    var settings = {
-                        title : i18n['KCHAPI6004M'],
-                        content : i18n['KCHDR6001M'],
-                        confirm : i18n['KCHAPI6002M'],
-                        cancel : i18n['KCHAPI6003M']
-                    };
-
-                    wok.confirm(settings, function() {
-                        kimchi.deleteReport({
-                            name: report['name']
-                        }, function(result) {
-                            listDebugReports();
-                        }, function(error) {
-                           wok.message.error(error.responseJSON.reason);
-                        });
-                    });
-                }
-            }, {
-                id: reportGridID + '-download-button',
-                label: i18n['KCHDR6010M'],
-                disabled: true,
-                onClick: function(event) {
-                    var report = reportGrid.getSelected();
-                    if(!report) {
-                        return;
-                    }
-
-                    kimchi.downloadReport({
-                        file: report['uri']
-                    });
-                }
-            }],
-            onRowSelected: function(row) {
-                var report = reportGrid.getSelected();
-                // Only enable report buttons if the selected line is not a
-                // pending report
-                if (report['time'] == i18n['KCHDR6007M']) {
-                    var gridElement = $('#'+ reportGridID);
-                    var row = $('tr:contains(' + report['name'] + ')', gridElement);
-                    enableReportButtons(false);
-                    row.attr('class', '');
-                }
-                else {
-                    enableReportButtons(true);
-                }
-            },
-            frozenFields: [],
-            fields: [{
-                name: 'name',
-                label: i18n['KCHDR6003M'],
-                'class': 'debug-report-name'
-            }, {
-                name: 'time',
-                label: i18n['KCHDR6005M'],
-                'class': 'debug-report-time'
-            }],
-            data: reports
-        });
-    };
-
-    var getPendingReports = function() {
-        var reports = []
-        var filter = 'status=running&target_uri=' + encodeURIComponent('^/plugins/kimchi/debugreports/*')
-
-        kimchi.getTasksByFilter(filter, function(tasks) {
-            for(var i = 0; i < tasks.length; i++) {
-                reportName = tasks[i].target_uri.replace(/^\/plugins\/kimchi\/debugreports\//, '') || i18n['KCHDR6012M'];
-                reports.push({'name': reportName, 'time': i18n['KCHDR6007M']})
-
-                if(kimchi.trackingTasks.indexOf(tasks[i].id) >= 0) {
-                    continue;
-                }
-
-                kimchi.trackTask(tasks[i].id, function(result) {
-                    wok.topic('kimchi/debugReportAdded').publish();
-                }, function(result) {
-                    // Error message from Async Task status
-                    if (result['message']) {
-                        var errText = result['message'];
-                    }
-                    // Error message from standard kimchi exception
-                    else {
-                        var errText = result['responseJSON']['reason'];
-                    }
-                    result && wok.message.error(errText);
-                    wok.topic('kimchi/debugReportAdded').publish();
-                }, null);
-            }
-        }, null, true);
-
-        return reports;
-    };
-
-    var listDebugReports = function() {
-        kimchi.listReports(function(reports) {
-            pendingReports = getPendingReports();
-            allReports = pendingReports.concat(reports);
-            $('#debug-report-section').removeClass('hidden');
-
-            // Row selection will be cleared so disable buttons here
-            enableReportButtons(false);
-
-            if(reportGrid) {
-                reportGrid.setData(allReports);
-            }
-            else {
-                initReportGrid(allReports);
-            }
-
-            // Set id-debug-img to pending reports
-            // It will display a loading icon
-            var gridElement = $('#' + reportGridID);
-                $.each($('td:contains(' + i18n['KCHDR6007M']  + ')', gridElement), function(index, row) {
-                $(row).parent().addClass('no-hover');
-                $(row).attr('id', 'id-debug-img');
-            });
-        }, function(error) {
-            if(error['status'] == 403) {
-                $('#debug-report-section').addClass('hidden');
-                return;
-            }
-            $('#debug-report-section').removeClass('hidden');
-        });
-    };
-
-    var shutdownButtonID = '#host-button-shutdown';
-    var restartButtonID = '#host-button-restart';
-    var shutdownHost = function(params) {
-        var settings = {
-            title : i18n['KCHAPI6004M'],
-            content : i18n['KCHHOST6008M'],
-            confirm : i18n['KCHAPI6002M'],
-            cancel : i18n['KCHAPI6003M']
-        };
-
-        wok.confirm(settings, function() {
-            kimchi.shutdown(params);
-            $(shutdownButtonID).prop('disabled', true);
-            $(restartButtonID).prop('disabled', true);
-            // Check if there is any VM is running.
-            kimchi.listVMs(function(vms) {
-                for(var i = 0; i < vms.length; i++) {
-                    if(vms[i]['state'] === 'running') {
-                        wok.message.error.code('KCHHOST6001E');
-                        $(shutdownButtonID).prop('disabled', false);
-                        $(restartButtonID).prop('disabled', false);
-                        return;
-                    }
-                }
-
-            });
-        }, function() {
-        });
-    };
-
-    var initPage = function() {
-        $('#host-info-container .section-header').each(function(i, header) {
-            $('<span class="arrow"></span>').prependTo(header);
-            var toExpand = $(header).attr('aria-expanded') !== 'false';
-            expand(header, toExpand);
-        });
-
-        $('#host-info-container').on('click', '.section-header', function(event) {
-            var toExpand = $(this).attr('aria-expanded') === 'false';
-            expand(this, toExpand);
-        });
-
-        $('#host-button-shutdown').on('click', function(event) {
-            shutdownHost(null);
-        });
-
-        $('#host-button-restart').on('click', function(event) {
-            shutdownHost({
-                reboot: true
-            });
-        });
-
-        var setupUI = function() {
-            if (kimchi.capabilities == undefined) {
-                setTimeout(setupUI, 2000);
-                return;
-            }
-
-            if((kimchi.capabilities['repo_mngt_tool']) && (kimchi.capabilities['repo_mngt_tool']!="None")) {
-                initRepositoriesGrid(kimchi.capabilities['repo_mngt_tool']);
-                $('#repositories-section').switchClass('hidden', kimchi.capabilities['repo_mngt_tool']);
-                wok.topic('kimchi/repositoryAdded')
-                    .subscribe(listRepositories);
-                wok.topic('kimchi/repositoryUpdated')
-                    .subscribe(listRepositories);
-                wok.topic('kimchi/repositoryDeleted')
-                    .subscribe(listRepositories);
-            }
-
-            if(kimchi.capabilities['update_tool']) {
-                $('#software-update-section').removeClass('hidden');
-                initSoftwareUpdatesGrid();
-                wok.topic('kimchi/softwareUpdated')
-                    .subscribe(listSoftwareUpdates);
-                $('#software-updates-progress-container').accordion({
-                    collapsible: true
-                });
-            }
-
-            if(kimchi.capabilities['system_report_tool']) {
-                listDebugReports();
-                wok.topic('kimchi/debugReportAdded')
-                    .subscribe(listDebugReports);
-                wok.topic('kimchi/debugReportRenamed')
-                    .subscribe(listDebugReports);
-            }
-        };
-        setupUI();
-    };
-
-    kimchi.getHost(function(data) {
-        var htmlTmpl = $('#host-tmpl').html();
-        data['logo'] = data['logo'] || '';
-        data['memory'] = wok.formatMeasurement(data['memory'], {
-            fixed: 2
-        });
-        var templated = wok.substitute(htmlTmpl, data);
-        $('#host-content-container').html(templated);
-
-        initPage();
-        initTracker();
-    });
-
-    var StatsMgr = function() {
-        var statsArray = {
-            cpu: {
-                u: {
-                    type: 'percent',
-                    legend: i18n['KCHHOST6002M'],
-                    points: []
-                }
-            },
-            memory: {
-                u: {
-                    type: 'value',
-                    base: 2,
-                    fixed: 2,
-                    legend: i18n['KCHHOST6003M'],
-                    points: []
-                }
-            },
-            diskIO: {
-                r: {
-                    type: 'value',
-                    base: 2,
-                    fixed: 2,
-                    unit: 'B/s',
-                    legend: i18n['KCHHOST6004M'],
-                    points: []
-                },
-                w: {
-                    type: 'value',
-                    base: 2,
-                    fixed: 2,
-                    unit: 'B/s',
-                    legend: i18n['KCHHOST6005M'],
-                    'class': 'disk-write',
-                    points: []
-                }
-            },
-            networkIO: {
-                r: {
-                    type: 'value',
-                    base: 2,
-                    fixed: 2,
-                    unit: 'B/s',
-                    legend: i18n['KCHHOST6006M'],
-                    points: []
-                },
-                s: {
-                    type: 'value',
-                    base: 2,
-                    fixed: 2,
-                    unit: 'B/s',
-                    legend: i18n['KCHHOST6007M'],
-                    'class': 'network-sent',
-                    points: []
-                }
-            }
-        };
-        var SIZE = 20;
-        var cursor = SIZE;
-
-        var add = function(stats) {
-            for(var key in stats) {
-                var item = stats[key];
-                for(var metrics in item) {
-                    var value = item[metrics]['v'];
-                    var max = item[metrics]['max'];
-                    var unifiedMetrics = statsArray[key][metrics];
-                    var ps = unifiedMetrics['points'];
-                    if(!Array.isArray(value)){
-                        ps.push(value);
-                        if(ps.length > SIZE + 1) {
-                            ps.shift();
-                        }
-                    }
-                    else{
-                        ps=ps.concat(value);
-                        ps.splice(0, ps.length-SIZE-1);
-                        unifiedMetrics['points']=ps;
-                    }
-                    if(max !== undefined) {
-                        unifiedMetrics['max'] = max;
-                    }
-                    else {
-                        if(unifiedMetrics['type'] !== 'value') {
-                            continue;
-                        }
-                        max = -Infinity;
-                        $.each(ps, function(i, value) {
-                            if(value > max) {
-                                max = value;
-                            }
-                        });
-                        if(max === 0) {
-                            ++max;
-                        }
-                        max *= 1.1;
-                        unifiedMetrics['max'] = max;
-                    }
-                }
-            }
-            cursor++;
-        };
-
-        var get = function(which) {
-            var stats = statsArray[which];
-            var lines = [];
-            for(var k in stats) {
-                var obj = stats[k];
-                var line = {
-                    type: obj['type'],
-                    base: obj['base'],
-                    unit: obj['unit'],
-                    fixed: obj['fixed'],
-                    legend: obj['legend']
-                };
-                if(obj['max']) {
-                    line['max'] = obj['max'];
-                }
-                if(obj['class']) {
-                    line['class'] = obj['class'];
-                }
-                var ps = obj['points'];
-                var numStats = ps.length;
-                var unifiedPoints = [];
-                $.each(ps, function(i, value) {
-                    unifiedPoints.push({
-                        x: cursor - numStats + i,
-                        y: value
-                    });
-                });
-                line['points'] = unifiedPoints;
-                lines.push(line);
-            }
-            return lines;
-        };
-
-        return {
-            add: add,
-            get: get
-        };
-    };
-
-    var Tracker = function(charts) {
-      var charts = charts;
-      var timer = null;
-      var statsPool = new StatsMgr();
-      var setCharts = function(newCharts) {
-          charts = newCharts;
-          for(var key in charts) {
-              var chart = charts[key];
-              chart.updateUI(statsPool.get(key));
-          }
-      };
-
-      var self = this;
-
-      var UnifyStats = function(stats) {
-          var result= {
-              cpu: {
-                  u: {
-                      v: stats['cpu_utilization']
-                  }
-              },
-              memory: {
-                  u: {
-                  }
-              },
-              diskIO: {
-                  r: {
-                      v: stats['disk_read_rate']
-                  },
-                  w: {
-                      v: stats['disk_write_rate']
-                  }
-              },
-              networkIO: {
-                  r: {
-                      v: stats['net_recv_rate']
-                  },
-                  s: {
-                      v: stats['net_sent_rate']
-                  }
-              }
-          };
-          if(Array.isArray(stats['memory'])){
-              result.memory.u['v']=[];
-              result.memory.u['max']=-Infinity;
-              for(var i=0;i<stats['memory'].length;i++){
-                  result.memory.u['v'].push(stats['memory'][i]['avail']);
-                  result.memory.u['max']=Math.max(result.memory.u['max'],stats['memory'][i]['total']);
-              }
-          }
-          else {
-              result.memory.u['v']=stats['memory']['avail'],
-              result.memory.u['max']=stats['memory']['total']
-          }
-          return(result);
-      };
-
-
-      var statsCallback = function(stats) {
-              var unifiedStats = UnifyStats(stats);
-              statsPool.add(unifiedStats);
-              for(var key in charts) {
-                  var chart = charts[key];
-                  chart.updateUI(statsPool.get(key));
-              }
-              timer = setTimeout(function() {
-                  continueTrack();
-              }, 1000);
-          };
-
-      var track = function() {
-          kimchi.getHostStatsHistory(statsCallback,
-            function() {
-                continueTrack();
-            });
-      };
-
-      var continueTrack = function() {
-          kimchi.getHostStats(statsCallback,
-            function() {
-                continueTrack();
-            });
-      };
-
-      var destroy = function() {
-          timer && clearTimeout(timer);
-          timer = null;
-      };
-
-      return {
-        setCharts: setCharts,
-        start: track,
-        stop: destroy
-      };
-    };
-
-    var initTracker = function() {
-        // TODO: Extend tabs with onUnload event to unregister timers.
-        if(kimchi.hostTimer) {
-            kimchi.hostTimer.stop();
-            delete kimchi.hostTimer;
-        }
-
-        var trackedCharts = {
-            cpu: new kimchi.widget.LineChart({
-                id: 'chart-cpu',
-                node: 'container-chart-cpu',
-                type: 'percent'
-            }),
-            memory: new kimchi.widget.LineChart({
-                id: 'chart-memory',
-                node: 'container-chart-memory',
-                type: 'value'
-            }),
-            diskIO: new kimchi.widget.LineChart({
-                id: 'chart-disk-io',
-                node: 'container-chart-disk-io',
-                type: 'value'
-            }),
-            networkIO: new kimchi.widget.LineChart({
-                id: 'chart-network-io',
-                node: 'container-chart-network-io',
-                type: 'value'
-            })
-        };
-
-        if(kimchi.hostTimer) {
-            kimchi.hostTimer.setCharts(trackedCharts);
-        }
-        else {
-            kimchi.hostTimer = new Tracker(trackedCharts);
-            kimchi.hostTimer.start();
-        }
-    };
-
-    $('#host-root-container').on('remove', function() {
-        if(kimchi.hostTimer) {
-            kimchi.hostTimer.stop();
-            delete kimchi.hostTimer;
-            }
-
-        repositoriesGrid && repositoriesGrid.destroy();
-        wok.topic('kimchi/repositoryAdded')
-            .unsubscribe(listRepositories);
-        wok.topic('kimchi/repositoryUpdated')
-            .unsubscribe(listRepositories);
-        wok.topic('kimchi/repositoryDeleted')
-            .unsubscribe(listRepositories);
-
-        softwareUpdatesGrid && softwareUpdatesGrid.destroy();
-        wok.topic('kimchi/softwareUpdated').unsubscribe(listSoftwareUpdates);
-
-        reportGrid && reportGrid.destroy();
-        wok.topic('kimchi/debugReportAdded').unsubscribe(listDebugReports);
-        wok.topic('kimchi/debugReportRenamed').unsubscribe(listDebugReports);
-    });
-};
diff --git a/plugins/kimchi/ui/js/src/kimchi.report_add_main.js b/plugins/kimchi/ui/js/src/kimchi.report_add_main.js
deleted file mode 100644
index 5f098d3..0000000
--- a/plugins/kimchi/ui/js/src/kimchi.report_add_main.js
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Project Kimchi
- *
- * Copyright IBM, Corp. 2013-2014
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-kimchi.report_add_main = function() {
-    var reportGridID = 'available-reports-grid';
-    var addReportForm = $('#form-report-add');
-    var submitButton = $('#button-report-add');
-    var nameTextbox = $('input[name="name"]', addReportForm);
-    nameTextbox.select();
-
-    var submitForm = function(event) {
-        if(submitButton.prop('disabled')) {
-            return false;
-        }
-        var reportName = nameTextbox.val();
-        var validator = RegExp("^[_A-Za-z0-9-]*$");
-        if (!validator.test(reportName)) {
-            wok.message.error.code('KCHDR6011M');
-            return false;
-        }
-        var formData = addReportForm.serializeObject();
-        var taskAccepted = false;
-        var onTaskAccepted = function() {
-            if(taskAccepted) {
-                return;
-            }
-            taskAccepted = true;
-            wok.window.close();
-            wok.topic('kimchi/debugReportAdded').publish();
-        };
-
-        kimchi.createReport(formData, function(result) {
-            onTaskAccepted();
-            wok.topic('kimchi/debugReportAdded').publish();
-        }, function(result) {
-            // Error message from Async Task status
-            if (result['message']) {
-                var errText = result['message'];
-            }
-            // Error message from standard kimchi exception
-            else {
-                var errText = result['responseJSON']['reason'];
-            }
-            result && wok.message.error(errText);
-
-            taskAccepted &&
-                $('.grid-body-view table tr:first-child',
-                    '#' + reportGridID).remove();
-            submitButton.prop('disabled', false);
-            nameTextbox.select();
-        }, onTaskAccepted);
-
-        event.preventDefault();
-    };
-
-    addReportForm.on('submit', submitForm);
-    submitButton.on('click', submitForm);
-};
diff --git a/plugins/kimchi/ui/js/src/kimchi.report_rename_main.js b/plugins/kimchi/ui/js/src/kimchi.report_rename_main.js
deleted file mode 100644
index 1bdb8d9..0000000
--- a/plugins/kimchi/ui/js/src/kimchi.report_rename_main.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Project Kimchi
- *
- * Copyright IBM, Corp. 2014
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-kimchi.report_rename_main = function() {
-    var renameReportForm = $('#form-report-rename');
-    var submitButton = $('#button-report-rename');
-    var nameTextbox = $('input[name="name"]', renameReportForm);
-    var submitForm = function(event) {
-        if(submitButton.prop('disabled')) {
-            return false;
-        }
-        var reportName = nameTextbox.val();
-
-        // if the user hasn't changed the report's name,
-        // nothing should be done.
-        if (reportName == kimchi.selectedReport) {
-            wok.message.error.code('KCHDR6013M');
-            return false;
-        }
-
-        var validator = RegExp("^[A-Za-z0-9-]*$");
-        if (!validator.test(reportName)) {
-            wok.message.error.code('KCHDR6011M');
-            return false;
-        }
-        var formData = renameReportForm.serializeObject();
-        submitButton.prop('disabled', true);
-        nameTextbox.prop('disabled', true);
-        kimchi.renameReport(kimchi.selectedReport, formData, function(result) {
-            submitButton.prop('disabled', false);
-            nameTextbox.prop('disabled', false);
-            wok.window.close();
-            wok.topic('kimchi/debugReportRenamed').publish({
-                result: result
-            });
-        }, function(result) {
-            var errText = result &&
-                result['responseJSON'] &&
-                result['responseJSON']['reason'];
-            wok.message.error(errText);
-            submitButton.prop('disabled', false);
-            nameTextbox.prop('disabled', false).focus();
-        });
-
-        event.preventDefault();
-    };
-
-    renameReportForm.on('submit', submitForm);
-    submitButton.on('click', submitForm);
-
-    nameTextbox.val(kimchi.selectedReport).select();
-};
diff --git a/plugins/kimchi/ui/js/src/kimchi.repository_add_main.js b/plugins/kimchi/ui/js/src/kimchi.repository_add_main.js
deleted file mode 100644
index 656306b..0000000
--- a/plugins/kimchi/ui/js/src/kimchi.repository_add_main.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Project Kimchi
- *
- * Copyright IBM, Corp. 2014
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-kimchi.repository_add_main = function() {
-
-    var addForm = $('#form-repository-add');
-    var addButton = $('#button-repository-add');
-
-    var validateField = function(event) {
-        var valid=($(this).val()!=='');
-        $(addButton).prop('disabled', !valid);
-        return(valid);
-    };
-
-    var validateForm = function(event) {
-        var valid=false;
-        addForm.find('input.required').each( function() {
-            valid=($(this).val()!=='');
-            return(!valid);
-        });
-        return(valid);
-    }
-
-    addForm.find('input.required').on('input propertychange', validateField);
-
-    var weedObject = function(obj) {
-        for (var key in obj) {
-            if (obj.hasOwnProperty(key)) {
-                if((typeof(obj[key])==="object") && !Array.isArray(obj[key])) {
-                    weedObject(obj[key]);
-                }
-                else if(obj[key] == '') {
-                    delete obj[key];
-                }
-            }
-        }
-    }
-
-    var addRepository = function(event) {
-        var valid = validateForm();
-        if(!valid) {
-            return false;
-        }
-
-        var formData = $(addForm).serializeObject();
-
-        if (formData && formData.isMirror!=undefined) {
-            formData.isMirror=(String(formData.isMirror).toLowerCase() === 'true');
-        }
-        if(formData.isMirror) {
-            if(formData.config==undefined) {
-                formData.config=new Object();
-            }
-            formData.config.mirrorlist=formData.baseurl;
-            delete formData.baseurl;
-            delete formData.isMirror;
-        }
-        weedObject(formData);
-        if(formData.config && formData.config.comps) {
-            formData.config.comps=formData.config.comps.split(/[,\s]/);
-            for(var i=0; i>formData.config.comps.length; i++) {
-                formData.config.comps[i]=formData.config.comps[i].trim();
-            }
-            for (var j=formData.config.comps.indexOf(""); j!=-1; j=formData.config.comps.indexOf("")) {
-                formData.config.comps.splice(j, 1);
-            }
-        }
-
-        kimchi.createRepository(formData, function() {
-            wok.topic('kimchi/repositoryAdded').publish();
-            wok.window.close();
-        }, function(jqXHR, textStatus, errorThrown) {
-            var reason = jqXHR &&
-                jqXHR['responseJSON'] &&
-                jqXHR['responseJSON']['reason'];
-            wok.message.error(reason);
-        });
-        return false;
-    };
-
-    $(addForm).on('submit', addRepository);
-};
diff --git a/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js b/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js
deleted file mode 100644
index 5bfc51e..0000000
--- a/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Project Kimchi
- *
- * Copyright IBM, Corp. 2014
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-kimchi.repository_edit_main = function() {
-
-    var editForm = $('#form-repository-edit');
-
-    var saveButton = $('#repository-edit-button-save');
-
-    if(kimchi.capabilities['repo_mngt_tool']=="yum") {
-        editForm.find('input.deb').prop('disabled', true);
-    }
-    else if(kimchi.capabilities['repo_mngt_tool']=="deb") {
-        editForm.find('input.yum').prop('disabled', true);
-    }
-
-    kimchi.retrieveRepository(kimchi.selectedRepository, function(repository) {
-        editForm.fillWithObject(repository);
-
-        $('input', editForm).on('input propertychange', function(event) {
-            if($(this).val() !== '') {
-                $(saveButton).prop('disabled', false);
-            }
-        });
-    });
-
-
-    var editRepository = function(event) {
-        var formData = $(editForm).serializeObject();
-
-        if (formData && formData.config) {
-            formData.config.gpgcheck=(String(formData.config.gpgcheck).toLowerCase() === 'true');
-        }
-
-        if(formData.config && formData.config.comps) {
-            formData.config.comps=formData.config.comps.split(/[,\s]/);
-            for(var i=0; i>formData.config.comps.length; i++) {
-                formData.config.comps[i]=formData.config.comps[i].trim();
-            }
-            for (var j=formData.config.comps.indexOf(""); j!=-1; j=formData.config.comps.indexOf("")) {
-                formData.config.comps.splice(j, 1);
-            }
-        }
-
-        kimchi.updateRepository(kimchi.selectedRepository, formData, function() {
-            wok.topic('kimchi/repositoryUpdated').publish();
-            wok.window.close();
-        }, function(jqXHR, textStatus, errorThrown) {
-            var reason = jqXHR &&
-                jqXHR['responseJSON'] &&
-                jqXHR['responseJSON']['reason'];
-            wok.message.error(reason);
-        });
-
-        return false;
-    };
-
-    $(editForm).on('submit', editRepository);
-    $(saveButton).on('click', editRepository);
-};
-- 
2.1.0




More information about the Kimchi-devel mailing list