You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2015/08/11 12:46:05 UTC

incubator-ignite git commit: IGNITE-843 Ensure active panel on new item creation.

Repository: incubator-ignite
Updated Branches:
  refs/heads/ignite-843 da1909cc3 -> 8f4607fe0


IGNITE-843 Ensure active panel on new item creation.


Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/8f4607fe
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/8f4607fe
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/8f4607fe

Branch: refs/heads/ignite-843
Commit: 8f4607fe09e5a7b2f2e33ae1dfbf0898bb070507
Parents: da1909c
Author: AKuznetsov <ak...@gridgain.com>
Authored: Tue Aug 11 17:46:14 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Tue Aug 11 17:46:14 2015 +0700

----------------------------------------------------------------------
 .../main/js/controllers/caches-controller.js    | 529 ++++++------
 .../main/js/controllers/clusters-controller.js  |   3 +
 .../src/main/js/controllers/common-module.js    | 818 ++++++++++---------
 .../main/js/controllers/metadata-controller.js  |  14 +-
 .../src/main/js/views/configuration/caches.jade |  13 +-
 .../main/js/views/configuration/clusters.jade   |  11 +-
 .../main/js/views/configuration/metadata.jade   |   4 +-
 7 files changed, 700 insertions(+), 692 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8f4607fe/modules/control-center-web/src/main/js/controllers/caches-controller.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/controllers/caches-controller.js b/modules/control-center-web/src/main/js/controllers/caches-controller.js
index 667e283..6b9f1bf 100644
--- a/modules/control-center-web/src/main/js/controllers/caches-controller.js
+++ b/modules/control-center-web/src/main/js/controllers/caches-controller.js
@@ -15,336 +15,345 @@
  * limitations under the License.
  */
 
-controlCenterModule.controller('cachesController', ['$scope', '$http', '$common', '$focus', '$confirm', '$copy', '$table',
+controlCenterModule.controller('cachesController', [
+        '$scope', '$http', '$common', '$focus', '$confirm', '$copy', '$table',
         function ($scope, $http, $common, $focus, $confirm, $copy, $table) {
-        $scope.joinTip = $common.joinTip;
-        $scope.getModel = $common.getModel;
-        $scope.javaBuildInClasses = $common.javaBuildInClasses;
-
-        $scope.tableReset = $table.tableReset;
-        $scope.tableNewItem = $table.tableNewItem;
-        $scope.tableNewItemActive = $table.tableNewItemActive;
-        $scope.tableEditing = $table.tableEditing;
-        $scope.tableStartEdit = $table.tableStartEdit;
-        $scope.tableRemove = $table.tableRemove;
-
-        $scope.tableSimpleSave = $table.tableSimpleSave;
-        $scope.tableSimpleSaveVisible = $table.tableSimpleSaveVisible;
-        $scope.tableSimpleUp = $table.tableSimpleUp;
-        $scope.tableSimpleDown = $table.tableSimpleDown;
-        $scope.tableSimpleDownVisible = $table.tableSimpleDownVisible;
-
-        $scope.tablePairSave = $table.tablePairSave;
-        $scope.tablePairSaveVisible = $table.tablePairSaveVisible;
-
-        $scope.availableWidth = $common.availableWidth;
-        $scope.compactJavaName = $common.compactJavaName;
-
-        $scope.atomicities = $common.mkOptions(['ATOMIC', 'TRANSACTIONAL']);
-
-        $scope.modes = $common.mkOptions(['PARTITIONED', 'REPLICATED', 'LOCAL']);
-
-        $scope.atomicWriteOrderModes = $common.mkOptions(['CLOCK', 'PRIMARY']);
-
-        $scope.memoryModes = $common.mkOptions(['ONHEAP_TIERED', 'OFFHEAP_TIERED', 'OFFHEAP_VALUES']);
-
-        $scope.evictionPolicies = [
-            {value: 'LRU', label: 'LRU'},
-            {value: 'RND', label: 'Random'},
-            {value: 'FIFO', label: 'FIFO'},
-            {value: 'SORTED', label: 'Sorted'},
-            {value: undefined, label: 'Not set'}
-        ];
-
-        $scope.rebalanceModes = $common.mkOptions(['SYNC', 'ASYNC', 'NONE']);
-
-        $scope.cacheStoreFactories = [
-            {value: 'CacheJdbcPojoStoreFactory', label: 'JDBC POJO store factory'},
-            {value: 'CacheJdbcBlobStoreFactory', label: 'JDBC BLOB store factory'},
-            {value: 'CacheHibernateBlobStoreFactory', label: 'Hibernate BLOB store factory'},
-            {value: undefined, label: 'Not set'}
-        ];
-
-        $scope.cacheStoreJdbcDialects = [
-            {value: 'Oracle', label: 'Oracle'},
-            {value: 'DB2', label: 'IBM DB2'},
-            {value: 'SQLServer', label: 'Microsoft SQL Server'},
-            {value: 'MySQL', label: 'My SQL'},
-            {value: 'PostgreSQL', label: 'Postgre SQL'},
-            {value: 'H2', label: 'H2 database'}
-        ];
-
-        $scope.ui = {expanded: false};
-
-        $scope.toggleExpanded = function () {
-            $scope.ui.expanded = !$scope.ui.expanded;
-        };
-
-        $scope.general = [];
-        $scope.advanced = [];
-
-        $http.get('/models/caches.json')
-            .success(function (data) {
-                $scope.screenTip = data.screenTip;
-                $scope.general = data.general;
-                $scope.advanced = data.advanced;
-            })
-            .error(function (errMsg) {
-                $common.showError(errMsg);
-            });
+            $scope.joinTip = $common.joinTip;
+            $scope.getModel = $common.getModel;
+            $scope.javaBuildInClasses = $common.javaBuildInClasses;
+
+            $scope.tableReset = $table.tableReset;
+            $scope.tableNewItem = $table.tableNewItem;
+            $scope.tableNewItemActive = $table.tableNewItemActive;
+            $scope.tableEditing = $table.tableEditing;
+            $scope.tableStartEdit = $table.tableStartEdit;
+            $scope.tableRemove = $table.tableRemove;
+
+            $scope.tableSimpleSave = $table.tableSimpleSave;
+            $scope.tableSimpleSaveVisible = $table.tableSimpleSaveVisible;
+            $scope.tableSimpleUp = $table.tableSimpleUp;
+            $scope.tableSimpleDown = $table.tableSimpleDown;
+            $scope.tableSimpleDownVisible = $table.tableSimpleDownVisible;
+
+            $scope.tablePairSave = $table.tablePairSave;
+            $scope.tablePairSaveVisible = $table.tablePairSaveVisible;
+
+            $scope.availableWidth = $common.availableWidth;
+            $scope.compactJavaName = $common.compactJavaName;
+
+            $scope.atomicities = $common.mkOptions(['ATOMIC', 'TRANSACTIONAL']);
+
+            $scope.modes = $common.mkOptions(['PARTITIONED', 'REPLICATED', 'LOCAL']);
+
+            $scope.atomicWriteOrderModes = $common.mkOptions(['CLOCK', 'PRIMARY']);
+
+            $scope.memoryModes = $common.mkOptions(['ONHEAP_TIERED', 'OFFHEAP_TIERED', 'OFFHEAP_VALUES']);
+
+            $scope.evictionPolicies = [
+                {value: 'LRU', label: 'LRU'},
+                {value: 'RND', label: 'Random'},
+                {value: 'FIFO', label: 'FIFO'},
+                {value: 'SORTED', label: 'Sorted'},
+                {value: undefined, label: 'Not set'}
+            ];
+
+            $scope.rebalanceModes = $common.mkOptions(['SYNC', 'ASYNC', 'NONE']);
+
+            $scope.cacheStoreFactories = [
+                {value: 'CacheJdbcPojoStoreFactory', label: 'JDBC POJO store factory'},
+                {value: 'CacheJdbcBlobStoreFactory', label: 'JDBC BLOB store factory'},
+                {value: 'CacheHibernateBlobStoreFactory', label: 'Hibernate BLOB store factory'},
+                {value: undefined, label: 'Not set'}
+            ];
+
+            $scope.cacheStoreJdbcDialects = [
+                {value: 'Oracle', label: 'Oracle'},
+                {value: 'DB2', label: 'IBM DB2'},
+                {value: 'SQLServer', label: 'Microsoft SQL Server'},
+                {value: 'MySQL', label: 'My SQL'},
+                {value: 'PostgreSQL', label: 'Postgre SQL'},
+                {value: 'H2', label: 'H2 database'}
+            ];
+
+            $scope.ui = {expanded: false};
+
+            $scope.toggleExpanded = function () {
+                $scope.ui.expanded = !$scope.ui.expanded;
+            };
+
+            $scope.panels = {activePanels: [0]};
+
+            $scope.general = [];
+            $scope.advanced = [];
+
+            $http.get('/models/caches.json')
+                .success(function (data) {
+                    $scope.screenTip = data.screenTip;
+                    $scope.general = data.general;
+                    $scope.advanced = data.advanced;
+                })
+                .error(function (errMsg) {
+                    $common.showError(errMsg);
+                });
 
-        $scope.caches = [];
-        $scope.queryMetadata = [];
-        $scope.storeMetadata = [];
+            $scope.caches = [];
+            $scope.queryMetadata = [];
+            $scope.storeMetadata = [];
 
-        $scope.required = function (field) {
-            var model = $common.isDefined(field.path) ? field.path + '.' + field.model : field.model;
+            $scope.required = function (field) {
+                var model = $common.isDefined(field.path) ? field.path + '.' + field.model : field.model;
 
-            var backupItem = $scope.backupItem;
+                var backupItem = $scope.backupItem;
 
-            var memoryMode = backupItem.memoryMode;
+                var memoryMode = backupItem.memoryMode;
 
-            var onHeapTired = memoryMode == 'ONHEAP_TIERED';
-            var offHeapTired = memoryMode == 'OFFHEAP_TIERED';
+                var onHeapTired = memoryMode == 'ONHEAP_TIERED';
+                var offHeapTired = memoryMode == 'OFFHEAP_TIERED';
 
-            var offHeapMaxMemory = backupItem.offHeapMaxMemory;
+                var offHeapMaxMemory = backupItem.offHeapMaxMemory;
 
-            if (model == 'offHeapMaxMemory' && offHeapTired)
-                return true;
+                if (model == 'offHeapMaxMemory' && offHeapTired)
+                    return true;
 
-            if (model == 'evictionPolicy.kind' && onHeapTired)
-                return backupItem.swapEnabled || ($common.isDefined(offHeapMaxMemory) && offHeapMaxMemory >= 0);
+                if (model == 'evictionPolicy.kind' && onHeapTired)
+                    return backupItem.swapEnabled || ($common.isDefined(offHeapMaxMemory) && offHeapMaxMemory >= 0);
 
-            return false;
-        };
+                return false;
+            };
 
-        function focusInvalidField(index, id) {
-            $focus(index < 0 ? 'new' + id : 'cur' + id);
+            function focusInvalidField(index, id) {
+                $focus(index < 0 ? 'new' + id : 'cur' + id);
 
-            return false;
-        }
+                return false;
+            }
 
-        $scope.tableSimpleValid = function (item, field, fx, index) {
-            if (!$common.isValidJavaClass('SQL function', fx, false))
-                return focusInvalidField(index, 'SqlFx');
+            $scope.tableSimpleValid = function (item, field, fx, index) {
+                if (!$common.isValidJavaClass('SQL function', fx, false))
+                    return focusInvalidField(index, 'SqlFx');
 
-            var model = item[field.model];
+                var model = item[field.model];
 
-            if ($common.isDefined(model)) {
-                var idx = _.indexOf(model, fx);
+                if ($common.isDefined(model)) {
+                    var idx = _.indexOf(model, fx);
 
-                // Found duplicate.
-                if (idx >= 0 && idx != index) {
-                    $common.showError('SQL function with such class name already exists!');
+                    // Found duplicate.
+                    if (idx >= 0 && idx != index) {
+                        $common.showError('SQL function with such class name already exists!');
 
-                    return focusInvalidField(index, 'SqlFx');
+                        return focusInvalidField(index, 'SqlFx');
+                    }
                 }
-            }
 
-            return true;
-        };
+                return true;
+            };
 
-        $scope.tablePairValid = function (item, field, keyCls, valCls, index) {
-            if (!$common.isValidJavaClass('Indexed type key', keyCls, true))
-                return focusInvalidField(index, 'KeyIndexedType');
+            $scope.tablePairValid = function (item, field, keyCls, valCls, index) {
+                if (!$common.isValidJavaClass('Indexed type key', keyCls, true))
+                    return focusInvalidField(index, 'KeyIndexedType');
 
-            if (!$common.isValidJavaClass('Indexed type value', valCls, true))
-                return focusInvalidField(index, 'ValueIndexedType');
+                if (!$common.isValidJavaClass('Indexed type value', valCls, true))
+                    return focusInvalidField(index, 'ValueIndexedType');
 
-            var model = item[field.model];
+                var model = item[field.model];
 
-            if ($common.isDefined(model)) {
-                var idx = _.findIndex(model, function (pair) {
-                    return pair.keyClass == keyCls
-                });
+                if ($common.isDefined(model)) {
+                    var idx = _.findIndex(model, function (pair) {
+                        return pair.keyClass == keyCls
+                    });
 
-                // Found duplicate.
-                if (idx >= 0 && idx != index) {
-                    $common.showError('Indexed type with such key class already exists!');
+                    // Found duplicate.
+                    if (idx >= 0 && idx != index) {
+                        $common.showError('Indexed type with such key class already exists!');
 
-                    return focusInvalidField(index, 'KeyIndexedType');
+                        return focusInvalidField(index, 'KeyIndexedType');
+                    }
                 }
-            }
 
-            return true;
-        };
+                return true;
+            };
 
-        // When landing on the page, get caches and show them.
-        $http.post('caches/list')
-            .success(function (data) {
-                $scope.spaces = data.spaces;
-                $scope.caches = data.caches;
+            // When landing on the page, get caches and show them.
+            $http.post('caches/list')
+                .success(function (data) {
+                    $scope.spaces = data.spaces;
+                    $scope.caches = data.caches;
 
-                _.forEach(data.metadatas, function (meta) {
-                    var kind = meta.kind;
+                    _.forEach(data.metadatas, function (meta) {
+                        var kind = meta.kind;
 
-                    if (kind == 'query' || kind == 'both')
-                        $scope.queryMetadata.push(meta);
+                        if (kind == 'query' || kind == 'both')
+                            $scope.queryMetadata.push(meta);
 
-                    if (kind == 'store' || kind == 'both')
-                        $scope.storeMetadata.push(meta);
-                });
+                        if (kind == 'store' || kind == 'both')
+                            $scope.storeMetadata.push(meta);
+                    });
 
-                var restoredItem = angular.fromJson(sessionStorage.cacheBackupItem);
+                    var restoredItem = angular.fromJson(sessionStorage.cacheBackupItem);
 
-                if (restoredItem) {
-                    if (restoredItem._id) {
-                        var idx = _.findIndex($scope.caches, function (cache) {
-                            return cache._id == restoredItem._id;
-                        });
+                    if (restoredItem) {
+                        if (restoredItem._id) {
+                            var idx = _.findIndex($scope.caches, function (cache) {
+                                return cache._id == restoredItem._id;
+                            });
 
-                        if (idx >= 0) {
-                            $scope.selectedItem = $scope.caches[idx];
-                            $scope.backupItem = restoredItem;
+                            if (idx >= 0) {
+                                $scope.selectedItem = $scope.caches[idx];
+                                $scope.backupItem = restoredItem;
+                            }
+                            else
+                                sessionStorage.removeItem('cacheBackupItem');
                         }
                         else
-                            sessionStorage.removeItem('cacheBackupItem');
+                            $scope.backupItem = restoredItem;
                     }
-                    else
-                        $scope.backupItem = restoredItem;
-                }
-                else if ($scope.caches.length > 0)
-                    $scope.selectItem($scope.caches[0]);
+                    else if ($scope.caches.length > 0)
+                        $scope.selectItem($scope.caches[0]);
 
-                $scope.$watch('backupItem', function (val) {
-                    if (val)
-                        sessionStorage.cacheBackupItem = angular.toJson(val);
-                }, true);
-            })
-            .error(function (errMsg) {
-                $common.showError(errMsg);
-            });
+                    $scope.$watch('backupItem', function (val) {
+                        if (val)
+                            sessionStorage.cacheBackupItem = angular.toJson(val);
+                    }, true);
+                })
+                .error(function (errMsg) {
+                    $common.showError(errMsg);
+                });
 
-        $scope.selectItem = function (item) {
-            $table.tableReset();
+            $scope.selectItem = function (item) {
+                $table.tableReset();
 
-            $scope.selectedItem = item;
-            $scope.backupItem = angular.copy(item);
-        };
+                $scope.selectedItem = item;
+                $scope.backupItem = angular.copy(item);
+            };
 
-        // Add new cache.
-        $scope.createItem = function () {
-            $table.tableReset();
+            // Add new cache.
+            $scope.createItem = function () {
+                $table.tableReset();
+                $common.ensureActivePanel($scope.panels, 0);
 
-            $scope.selectedItem = undefined;
+                $scope.selectedItem = undefined;
 
-            $scope.backupItem = {mode: 'PARTITIONED', atomicityMode: 'ATOMIC', readFromBackup: true, copyOnRead: true};
-            $scope.backupItem.queryMetadata = [];
-            $scope.backupItem.spaceMetadata = [];
-            $scope.backupItem.space = $scope.spaces[0]._id;
-        };
+                $scope.backupItem = {
+                    mode: 'PARTITIONED',
+                    atomicityMode: 'ATOMIC',
+                    readFromBackup: true,
+                    copyOnRead: true
+                };
+                $scope.backupItem.queryMetadata = [];
+                $scope.backupItem.spaceMetadata = [];
+                $scope.backupItem.space = $scope.spaces[0]._id;
+            };
 
-        // Check cache logical consistency.
-        function validate(item) {
-            var cacheStoreFactorySelected = item.cacheStoreFactory && item.cacheStoreFactory.kind;
+            // Check cache logical consistency.
+            function validate(item) {
+                var cacheStoreFactorySelected = item.cacheStoreFactory && item.cacheStoreFactory.kind;
 
-            if (cacheStoreFactorySelected && !(item.readThrough || item.writeThrough)) {
-                $common.showError('Store is configured but read/write through are not enabled!');
+                if (cacheStoreFactorySelected && !(item.readThrough || item.writeThrough)) {
+                    $common.showError('Store is configured but read/write through are not enabled!');
 
-                return false;
-            }
+                    return false;
+                }
 
-            if ((item.readThrough || item.writeThrough) && !cacheStoreFactorySelected) {
-                $common.showError('Read / write through are enabled but store is not configured!');
+                if ((item.readThrough || item.writeThrough) && !cacheStoreFactorySelected) {
+                    $common.showError('Read / write through are enabled but store is not configured!');
 
-                return false;
-            }
+                    return false;
+                }
 
-            if (item.writeBehindEnabled && !cacheStoreFactorySelected) {
-                $common.showError('Write behind enabled but store is not configured!');
+                if (item.writeBehindEnabled && !cacheStoreFactorySelected) {
+                    $common.showError('Write behind enabled but store is not configured!');
 
-                return false;
-            }
+                    return false;
+                }
 
-            return true;
-        }
+                return true;
+            }
 
-        // Save cache into database.
-        function save(item) {
-            $http.post('caches/save', item)
-                .success(function (_id) {
-                    var idx = _.findIndex($scope.caches, function (cache) {
-                        return cache._id == _id;
-                    });
+            // Save cache into database.
+            function save(item) {
+                $http.post('caches/save', item)
+                    .success(function (_id) {
+                        var idx = _.findIndex($scope.caches, function (cache) {
+                            return cache._id == _id;
+                        });
 
-                    if (idx >= 0)
-                        angular.extend($scope.caches[idx], item);
-                    else {
-                        item._id = _id;
+                        if (idx >= 0)
+                            angular.extend($scope.caches[idx], item);
+                        else {
+                            item._id = _id;
 
-                        $scope.caches.push(item);
-                    }
+                            $scope.caches.push(item);
+                        }
 
-                    $scope.selectItem(item);
+                        $scope.selectItem(item);
 
-                    $common.showInfo('Cache "' + item.name + '" saved.');
-                })
-                .error(function (errMsg) {
-                    $common.showError(errMsg);
-                });
-        }
+                        $common.showInfo('Cache "' + item.name + '" saved.');
+                    })
+                    .error(function (errMsg) {
+                        $common.showError(errMsg);
+                    });
+            }
 
-        // Save cache.
-        $scope.saveItem = function () {
-            $table.tableReset();
+            // Save cache.
+            $scope.saveItem = function () {
+                $table.tableReset();
 
-            var item = $scope.backupItem;
+                var item = $scope.backupItem;
 
-            if (validate(item))
-                save(item);
-        };
+                if (validate(item))
+                    save(item);
+            };
 
-        // Save cache with new name.
-        $scope.saveItemAs = function () {
-            $table.tableReset();
+            // Save cache with new name.
+            $scope.saveItemAs = function () {
+                $table.tableReset();
 
-            if (validate($scope.backupItem))
-                $copy.show($scope.backupItem.name).then(function (newName) {
-                    var item = angular.copy($scope.backupItem);
+                if (validate($scope.backupItem))
+                    $copy.show($scope.backupItem.name).then(function (newName) {
+                        var item = angular.copy($scope.backupItem);
 
-                    item._id = undefined;
-                    item.name = newName;
+                        item._id = undefined;
+                        item.name = newName;
 
-                    save(item);
-                });
-        };
+                        save(item);
+                    });
+            };
 
-        // Remove cache from db.
-        $scope.removeItem = function () {
-            $table.tableReset();
+            // Remove cache from db.
+            $scope.removeItem = function () {
+                $table.tableReset();
 
-            var selectedItem = $scope.selectedItem;
+                var selectedItem = $scope.selectedItem;
 
-            $confirm.show('Are you sure you want to remove cache: "' + selectedItem.name + '"?').then(
-                function () {
-                    var _id = selectedItem._id;
+                $confirm.show('Are you sure you want to remove cache: "' + selectedItem.name + '"?').then(
+                    function () {
+                        var _id = selectedItem._id;
 
-                    $http.post('caches/remove', {_id: _id})
-                        .success(function () {
-                            $common.showInfo('Cache has been removed: ' + selectedItem.name);
+                        $http.post('caches/remove', {_id: _id})
+                            .success(function () {
+                                $common.showInfo('Cache has been removed: ' + selectedItem.name);
 
-                            var caches = $scope.caches;
+                                var caches = $scope.caches;
 
-                            var idx = _.findIndex(caches, function (cache) {
-                                return cache._id == _id;
-                            });
+                                var idx = _.findIndex(caches, function (cache) {
+                                    return cache._id == _id;
+                                });
 
-                            if (idx >= 0) {
-                                caches.splice(idx, 1);
+                                if (idx >= 0) {
+                                    caches.splice(idx, 1);
 
-                                if (caches.length > 0)
-                                    $scope.selectItem(caches[0]);
-                                else {
-                                    $scope.selectedItem = undefined;
-                                    $scope.backupItem = undefined;
+                                    if (caches.length > 0)
+                                        $scope.selectItem(caches[0]);
+                                    else {
+                                        $scope.selectedItem = undefined;
+                                        $scope.backupItem = undefined;
+                                    }
                                 }
-                            }
-                        })
-                        .error(function (errMsg) {
-                            $common.showError(errMsg);
-                        });
-                }
-            );
-        };
-    }]
+                            })
+                            .error(function (errMsg) {
+                                $common.showError(errMsg);
+                            });
+                    }
+                );
+            };
+        }]
 );

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8f4607fe/modules/control-center-web/src/main/js/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/controllers/clusters-controller.js b/modules/control-center-web/src/main/js/controllers/clusters-controller.js
index d962f52..0ea68a1 100644
--- a/modules/control-center-web/src/main/js/controllers/clusters-controller.js
+++ b/modules/control-center-web/src/main/js/controllers/clusters-controller.js
@@ -103,6 +103,8 @@ controlCenterModule.controller('clustersController', ['$scope', '$http', '$commo
             $scope.ui.expanded = !$scope.ui.expanded;
         };
 
+        $scope.panels = {activePanels: [0]};
+
         var simpleTables = {
             addresses: {msg: 'Such IP address already exists!', id: 'IpAddress'},
             regions: {msg: 'Such region already exists!', id: 'Region'},
@@ -204,6 +206,7 @@ controlCenterModule.controller('clustersController', ['$scope', '$http', '$commo
         // Add new cluster.
         $scope.createItem = function () {
             $table.tableReset();
+            $common.ensureActivePanel($scope.panels, 0);
 
             $scope.selectedItem = undefined;
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8f4607fe/modules/control-center-web/src/main/js/controllers/common-module.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/controllers/common-module.js b/modules/control-center-web/src/main/js/controllers/common-module.js
index 4ee69ce..4563e96 100644
--- a/modules/control-center-web/src/main/js/controllers/common-module.js
+++ b/modules/control-center-web/src/main/js/controllers/common-module.js
@@ -57,360 +57,380 @@ controlCenterModule.config(function ($alertProvider) {
 });
 
 // Common functions to be used in controllers.
-controlCenterModule.service('$common', ['$alert', function ($alert) {
-    function isDefined(v) {
-        return !(v === undefined || v === null);
-    }
+controlCenterModule.service('$common', [
+    '$alert', function ($alert) {
+        function isDefined(v) {
+            return !(v === undefined || v === null);
+        }
 
-    function isEmptyArray(arr) {
-        if (isDefined(arr))
-            return arr.length == 0;
+        function isEmptyArray(arr) {
+            if (isDefined(arr))
+                return arr.length == 0;
 
-        return true;
-    }
+            return true;
+        }
 
-    function isEmptyString(s) {
-        if (isDefined(s))
-            return s.trim().length == 0;
+        function isEmptyString(s) {
+            if (isDefined(s))
+                return s.trim().length == 0;
 
-        return true;
-    }
+            return true;
+        }
 
-    var msgModal = undefined;
+        var msgModal = undefined;
 
-    function errorMessage(errMsg) {
-        return errMsg ? errMsg : 'Internal server error.';
-    }
+        function errorMessage(errMsg) {
+            return errMsg ? errMsg : 'Internal server error.';
+        }
 
-    function showError(msg, placement, container) {
-        if (msgModal)
-            msgModal.hide();
+        function showError(msg, placement, container) {
+            if (msgModal)
+                msgModal.hide();
 
-        msgModal = $alert({title: errorMessage(msg), placement: placement ? placement : 'top-right', container: container ? container : 'body'});
+            msgModal = $alert({
+                title: errorMessage(msg),
+                placement: placement ? placement : 'top-right',
+                container: container ? container : 'body'
+            });
 
-        return false;
-    }
+            return false;
+        }
 
-    var javaBuildInClasses = [
-        'BigDecimal', 'Boolean', 'Byte', 'Date', 'Double', 'Float', 'Integer', 'Long', 'Short', 'String', 'Time', 'Timestamp', 'UUID'
-    ];
+        var javaBuildInClasses = [
+            'BigDecimal', 'Boolean', 'Byte', 'Date', 'Double', 'Float', 'Integer', 'Long', 'Short', 'String', 'Time', 'Timestamp', 'UUID'
+        ];
 
-    var javaBuildInFullNameClasses = [
-        'java.math.BigDecimal', 'java.lang.Boolean', 'java.lang.Byte', 'java.sql.Date', 'java.lang.Double',
-        'java.lang.Float', 'java.lang.Integer', 'java.lang.Long', 'java.lang.Short', 'java.lang.String',
-        'java.sql.Time', 'java.sql.Timestamp', 'java.util.UUID'
-    ];
+        var javaBuildInFullNameClasses = [
+            'java.math.BigDecimal', 'java.lang.Boolean', 'java.lang.Byte', 'java.sql.Date', 'java.lang.Double',
+            'java.lang.Float', 'java.lang.Integer', 'java.lang.Long', 'java.lang.Short', 'java.lang.String',
+            'java.sql.Time', 'java.sql.Timestamp', 'java.util.UUID'
+        ];
 
-    function isJavaBuildInClass(cls) {
-        if (isEmptyString(cls))
-            return false;
+        function isJavaBuildInClass(cls) {
+            if (isEmptyString(cls))
+                return false;
 
-        return _.contains(javaBuildInClasses, cls) || _.contains(javaBuildInFullNameClasses, cls);
-    }
+            return _.contains(javaBuildInClasses, cls) || _.contains(javaBuildInFullNameClasses, cls);
+        }
 
-    var JDBC_TYPES = [
-        'BIT', 'BOOLEAN', 'TINYINT', 'SMALLINT', 'INTEGER', 'BIGINT', 'REAL', 'FLOAT', 'DOUBLE',
-        'NUMERIC', 'DECIMAL', 'CHAR', 'VARCHAR', 'LONGVARCHAR', 'NCHAR', 'NVARCHAR', 'LONGNVARCHAR',
-        'DATE', 'TIME', 'TIMESTAMP'
-    ];
-
-    var JAVA_KEYWORDS = [
-        'abstract',     'assert',        'boolean',      'break',           'byte',
-        'case',         'catch',         'char',         'class',           'const',
-        'continue',     'default',       'do',           'double',          'else',
-        'enum',         'extends',       'false',        'final',           'finally',
-        'float',        'for',           'goto',         'if',              'implements',
-        'import',       'instanceof',    'int',          'interface',       'long',
-        'native',       'new',           'null',         'package',         'private',
-        'protected',    'public',        'return',       'short',           'static',
-        'strictfp',     'super',         'switch',       'synchronized',    'this',
-        'throw',        'throws',        'transient',    'true',            'try',
-        'void',         'volatile',      'while'
-    ];
-
-    var VALID_JAVA_IDENTIFIER = new RegExp('^[a-zA-Z_$][a-zA-Z\d_$]*');
-
-    function isValidJavaIdentifier(msg, ident) {
-        if (isEmptyString(ident))
-            return showError(msg + ' could not be empty!');
-
-        if (_.contains(JAVA_KEYWORDS, ident))
-            return showError(msg + ' could not contains reserved java keyword: "' + ident + '"!');
-
-        if (!VALID_JAVA_IDENTIFIER.test(ident))
-            return showError(msg + ' contains invalid identifier: "' + ident + '"!');
-
-        return true;
-    }
+        var JDBC_TYPES = [
+            'BIT', 'BOOLEAN', 'TINYINT', 'SMALLINT', 'INTEGER', 'BIGINT', 'REAL', 'FLOAT', 'DOUBLE',
+            'NUMERIC', 'DECIMAL', 'CHAR', 'VARCHAR', 'LONGVARCHAR', 'NCHAR', 'NVARCHAR', 'LONGNVARCHAR',
+            'DATE', 'TIME', 'TIMESTAMP'
+        ];
+
+        var JAVA_KEYWORDS = [
+            'abstract',     'assert',        'boolean',      'break',           'byte',
+            'case',         'catch',         'char',         'class',           'const',
+            'continue',     'default',       'do',           'double',          'else',
+            'enum',         'extends',       'false',        'final',           'finally',
+            'float',        'for',           'goto',         'if',              'implements',
+            'import',       'instanceof',    'int',          'interface',       'long',
+            'native',       'new',           'null',         'package',         'private',
+            'protected',    'public',        'return',       'short',           'static',
+            'strictfp',     'super',         'switch',       'synchronized',    'this',
+            'throw',        'throws',        'transient',    'true',            'try',
+            'void',         'volatile',      'while'
+        ];
+
+        var VALID_JAVA_IDENTIFIER = new RegExp('^[a-zA-Z_$][a-zA-Z\d_$]*');
+
+        function isValidJavaIdentifier(msg, ident) {
+            if (isEmptyString(ident))
+                return showError(msg + ' could not be empty!');
 
-    var context = null;
+            if (_.contains(JAVA_KEYWORDS, ident))
+                return showError(msg + ' could not contains reserved java keyword: "' + ident + '"!');
 
-    /**
-     * Calculate width of specified text in body's font.
-     *
-     * @param text Text to calculate width.
-     * @returns {Number} Width of text in pixels.
-     */
-    function measureText(text) {
-        if (!context) {
-            var canvas = document.createElement('canvas');
+            if (!VALID_JAVA_IDENTIFIER.test(ident))
+                return showError(msg + ' contains invalid identifier: "' + ident + '"!');
 
-            context = canvas.getContext('2d');
+            return true;
+        }
 
-            var style = window.getComputedStyle(document.getElementsByTagName('body')[0]);
+        var context = null;
 
-            context.font = style.fontSize + ' ' + style.fontFamily;
-        }
+        /**
+         * Calculate width of specified text in body's font.
+         *
+         * @param text Text to calculate width.
+         * @returns {Number} Width of text in pixels.
+         */
+        function measureText(text) {
+            if (!context) {
+                var canvas = document.createElement('canvas');
 
-        return context.measureText(text).width;
-    }
+                context = canvas.getContext('2d');
 
-    /**
-     * Compact java full class name by max number of characters.
-     *
-     * @param s Class name to cut.
-     * @param maxLength Max available width in characters.
-     * @returns {*} Compacted class name.
-     */
-    function compactByMaxCharts(s, maxLength) {
-        if (s.length <= maxLength)
-            return s;
+                var style = window.getComputedStyle(document.getElementsByTagName('body')[0]);
 
-        var totalLength = s.length;
+                context.font = style.fontSize + ' ' + style.fontFamily;
+            }
 
-        var packages = s.split('.');
+            return context.measureText(text).width;
+        }
 
-        var packageCnt = packages.length - 1;
+        /**
+         * Compact java full class name by max number of characters.
+         *
+         * @param s Class name to cut.
+         * @param maxLength Max available width in characters.
+         * @returns {*} Compacted class name.
+         */
+        function compactByMaxCharts(s, maxLength) {
+            if (s.length <= maxLength)
+                return s;
+
+            var totalLength = s.length;
 
-        for (var i = 0; i < packageCnt && totalLength > maxLength; i ++) {
-            if (packages[i].length > 0) {
-                totalLength -= packages[i].length - 1;
+            var packages = s.split('.');
 
-                packages[i] = packages[i][0];
+            var packageCnt = packages.length - 1;
+
+            for (var i = 0; i < packageCnt && totalLength > maxLength; i++) {
+                if (packages[i].length > 0) {
+                    totalLength -= packages[i].length - 1;
+
+                    packages[i] = packages[i][0];
+                }
             }
-        }
 
-        if (totalLength > maxLength) {
-            var className = packages[packageCnt];
+            if (totalLength > maxLength) {
+                var className = packages[packageCnt];
 
-            var classNameLen = className.length;
+                var classNameLen = className.length;
 
-            var remains = Math.min(maxLength - totalLength + classNameLen, classNameLen);
+                var remains = Math.min(maxLength - totalLength + classNameLen, classNameLen);
 
-            if (remains < 3)
-                remains = Math.min(3, classNameLen);
+                if (remains < 3)
+                    remains = Math.min(3, classNameLen);
 
-            packages[packageCnt] = className.substring(0, remains) + '...';
-        }
+                packages[packageCnt] = className.substring(0, remains) + '...';
+            }
 
-        var result = packages[0];
+            var result = packages[0];
 
-        for (i = 1; i < packages.length; i ++)
-            result += '.' + packages[i];
+            for (i = 1; i < packages.length; i++)
+                result += '.' + packages[i];
 
-        return result
-    }
+            return result
+        }
 
-    /**
-     * Compact java full class name by max number of pixels.
-     *
-     * @param s Class name to cut.
-     * @param maxWidth Maximum available width in pixels.
-     * @returns {*} Compacted class name.
-     */
-    function compactByMaxPixels(s, maxWidth) {
-        var totalLength = measureText(s);
+        /**
+         * Compact java full class name by max number of pixels.
+         *
+         * @param s Class name to cut.
+         * @param maxWidth Maximum available width in pixels.
+         * @returns {*} Compacted class name.
+         */
+        function compactByMaxPixels(s, maxWidth) {
+            var totalLength = measureText(s);
 
-        if (totalLength <= maxWidth)
-            return s;
+            if (totalLength <= maxWidth)
+                return s;
 
-        var packages = s.split('.');
+            var packages = s.split('.');
 
-        var packageCnt = packages.length - 1;
+            var packageCnt = packages.length - 1;
 
-        for (var i = 0; i < packageCnt && totalLength > maxWidth; i++) {
-            if (packages[i].length > 1) {
-                totalLength -= measureText(packages[i].substring(2, packages[i].length));
+            for (var i = 0; i < packageCnt && totalLength > maxWidth; i++) {
+                if (packages[i].length > 1) {
+                    totalLength -= measureText(packages[i].substring(2, packages[i].length));
 
-                packages[i] = packages[i][0];
+                    packages[i] = packages[i][0];
+                }
             }
-        }
 
-        var shortPackage = '';
+            var shortPackage = '';
+
+            for (i = 0; i < packageCnt; i++)
+                shortPackage += packages[i] + '.';
 
-        for (i = 0; i < packageCnt; i++)
-            shortPackage += packages[i] + '.';
+            var className = packages[packageCnt];
 
-        var className = packages[packageCnt];
+            var classLen = className.length;
 
-        var classLen = className.length;
+            var minLen = Math.min(classLen, 3);
 
-        var minLen = Math.min(classLen, 3);
+            totalLength = measureText(shortPackage + className);
 
-        totalLength = measureText(shortPackage + className);
+            // Compact class name if shorten package path is very long.
+            if (totalLength > maxWidth) {
+                var maxLen = classLen;
 
-        // Compact class name if shorten package path is very long.
-        if (totalLength > maxWidth) {
-            var maxLen = classLen;
+                var middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
 
-            var middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
+                var minLenPx = measureText(shortPackage + className.substr(0, minLen) + '...');
+                var maxLenPx = totalLength;
 
-            var minLenPx = measureText(shortPackage + className.substr(0, minLen) + '...');
-            var maxLenPx = totalLength;
+                while (middleLen != minLen && middleLen != maxLen) {
+                    var middleLenPx = measureText(shortPackage + className.substr(0, middleLen) + '...');
 
-            while (middleLen != minLen && middleLen != maxLen) {
-                var middleLenPx = measureText(shortPackage + className.substr(0, middleLen) + '...');
+                    if (middleLenPx > maxWidth) {
+                        maxLen = middleLen;
+                        maxLenPx = middleLenPx;
+                    }
+                    else {
+                        minLen = middleLen;
+                        minLenPx = middleLenPx;
+                    }
 
-                if (middleLenPx > maxWidth) {
-                    maxLen = middleLen;
-                    maxLenPx = middleLenPx;
-                }
-                else {
-                    minLen = middleLen;
-                    minLenPx = middleLenPx;
+                    middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
                 }
 
-                middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
+                return shortPackage + className.substring(0, middleLen) + '...';
             }
 
-            return shortPackage + className.substring(0, middleLen) + '...';
+            return shortPackage + className;
         }
 
-        return shortPackage + className;
-    }
-
-    return {
-        getModel: function (obj, field) {
-            var path = field.path;
-
-            if (!isDefined(path))
-                return obj;
+        return {
+            getModel: function (obj, field) {
+                var path = field.path;
 
-            path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
-            path = path.replace(/^\./, '');           // strip a leading dot
+                if (!isDefined(path))
+                    return obj;
 
-            var segs = path.split('.');
-            var root = obj;
+                path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
+                path = path.replace(/^\./, '');           // strip a leading dot
 
-            while (segs.length > 0) {
-                var pathStep = segs.shift();
+                var segs = path.split('.');
+                var root = obj;
 
-                if (typeof root[pathStep] === 'undefined')
-                    root[pathStep] = {};
+                while (segs.length > 0) {
+                    var pathStep = segs.shift();
 
-                root = root[pathStep];
-            }
-
-            return root;
-        },
-        joinTip: function (arr) {
-            if (!arr) {
-                return arr;
-            }
+                    if (typeof root[pathStep] === 'undefined')
+                        root[pathStep] = {};
 
-            var lines = arr.map(function (line) {
-                var rtrimmed = line.replace(/\s+$/g, '');
+                    root = root[pathStep];
+                }
 
-                if (rtrimmed.indexOf('>', this.length - 1) == -1) {
-                    rtrimmed = rtrimmed + '<br/>';
+                return root;
+            },
+            joinTip: function (arr) {
+                if (!arr) {
+                    return arr;
                 }
 
-                return rtrimmed;
-            });
+                var lines = arr.map(function (line) {
+                    var rtrimmed = line.replace(/\s+$/g, '');
 
-            return lines.join('');
-        },
-        mkOptions: function (options) {
-            return _.map(options, function (option) {
-                return {value: option, label: option};
-            });
-        },
-        isDefined: isDefined,
-        isEmptyArray: isEmptyArray,
-        isEmptyString: isEmptyString,
-        errorMessage: errorMessage,
-        showError: showError,
-        showInfo: function (msg) {
-            if (msgModal)
-                msgModal.hide();
+                    if (rtrimmed.indexOf('>', this.length - 1) == -1) {
+                        rtrimmed = rtrimmed + '<br/>';
+                    }
 
-            msgModal = $alert({
-                type: 'success',
-                title: msg,
-                duration: 2
-            });
-        },
-        javaBuildInClasses: javaBuildInClasses,
-        isJavaBuildInClass: isJavaBuildInClass,
-        isValidJavaIdentifier: isValidJavaIdentifier,
-        isValidJavaClass: function (msg, ident, allowBuildInClass) {
-            if (isEmptyString(ident))
-                return showError(msg + ' could not be empty!');
+                    return rtrimmed;
+                });
 
-            var parts = ident.split('.');
+                return lines.join('');
+            },
+            mkOptions: function (options) {
+                return _.map(options, function (option) {
+                    return {value: option, label: option};
+                });
+            },
+            isDefined: isDefined,
+            isEmptyArray: isEmptyArray,
+            isEmptyString: isEmptyString,
+            errorMessage: errorMessage,
+            showError: showError,
+            showInfo: function (msg) {
+                if (msgModal)
+                    msgModal.hide();
+
+                msgModal = $alert({
+                    type: 'success',
+                    title: msg,
+                    duration: 2
+                });
+            },
+            JDBC_TYPES: JDBC_TYPES,
+            javaBuildInClasses: javaBuildInClasses,
+            isJavaBuildInClass: isJavaBuildInClass,
+            isValidJavaIdentifier: isValidJavaIdentifier,
+            isValidJavaClass: function (msg, ident, allowBuildInClass) {
+                if (isEmptyString(ident))
+                    return showError(msg + ' could not be empty!');
 
-            var len = parts.length;
+                var parts = ident.split('.');
 
-            if (!allowBuildInClass && isJavaBuildInClass(ident))
-                return showError(msg + ' should not be the Java build-in class!');
+                var len = parts.length;
 
-            if (len < 2 && !isJavaBuildInClass(ident))
-                return showError(msg + ' does not have package specified!');
+                if (!allowBuildInClass && isJavaBuildInClass(ident))
+                    return showError(msg + ' should not be the Java build-in class!');
 
-            for (var i = 0; i < parts.length; i++) {
-                var part = parts[i];
+                if (len < 2 && !isJavaBuildInClass(ident))
+                    return showError(msg + ' does not have package specified!');
 
-                if (!isValidJavaIdentifier(msg, part))
-                    return false;
-            }
+                for (var i = 0; i < parts.length; i++) {
+                    var part = parts[i];
 
-            return true;
-        },
-        JDBC_TYPES: JDBC_TYPES,
-        /**
-         * Calculate available width for text in link to edit element.
-         *
-         * @param id Id of contains link table.
-         * @returns {*[]} First element is length of class for single value, second element is length for pair vlaue.
-         */
-        availableWidth: function (id) {
-            var div = $('#' + id).find('div')[0];
-            var width = div.clientWidth;
+                    if (!isValidJavaIdentifier(msg, part))
+                        return false;
+                }
 
-            if (width > 0) {
-                var children = div.childNodes;
+                return true;
+            },
+            /**
+             * Calculate available width for text in link to edit element.
+             *
+             * @param id Id of contains link table.
+             * @returns {*[]} First element is length of class for single value, second element is length for pair vlaue.
+             */
+            availableWidth: function (id) {
+                var div = $('#' + id).find('div')[0];
+                var width = div.clientWidth;
+
+                if (width > 0) {
+                    var children = div.childNodes;
+
+                    for (var i = 1; i < children.length; i++) {
+                        var child = children[i];
+
+                        if ('offsetWidth' in child)
+                            width -= children[i].offsetWidth;
+                    }
 
-                for (var i = 1; i < children.length; i++) {
-                    var child = children[i];
+                    width -= measureText('99) ');
+                }
 
-                    if ('offsetWidth' in child)
-                        width -= children[i].offsetWidth;
+                return [width | 0, (width > 0 ? (width - measureText(' / ')) / 2 | 0 : width) | 0];
+            },
+            /**
+             * Cut class name by width in pixel or width in symbol count.
+             *
+             * @param s Class name to cut.
+             * @param maxLength Maximum length in symbols.
+             * @param maxWidth Maximum length in pixels.
+             * @returns Cutted class name.
+             */
+            compactJavaName: function (s, maxLength, maxWidth) {
+                try {
+                    // HTML5 calculation of showed message width.
+                    return compactByMaxPixels(s, maxWidth)
+                }
+                catch (err) {
+                    return compactByMaxCharts(s, maxLength)
                 }
+            },
+            ensureActivePanel: function (panels, pnlIdx) {
+                if (panels) {
+                    var activePanels = panels.activePanels;
 
-                width -= measureText('99) ');
-            }
+                    if (!activePanels || activePanels.length < 1)
+                        panels.activePanels = [pnlIdx];
+                    else if (!_.contains(activePanels, pnlIdx)) {
+                        var newActivePanels = activePanels.slice();
 
-            return [ width | 0, (width > 0 ? (width - measureText(' / ')) / 2 | 0 : width) | 0 ];
-        },
-        /**
-         * Cut class name by width in pixel or width in symbol count.
-         *
-         * @param s Class name to cut.
-         * @param maxLength Maximum length in symbols.
-         * @param maxWidth Maximum length in pixels.
-         * @returns Cutted class name.
-         */
-        compactJavaName: function (s, maxLength, maxWidth) {
-            try {
-                // HTML5 calculation of showed message width.
-                return compactByMaxPixels(s, maxWidth)
-            }
-            catch (err) {
-                return compactByMaxCharts(s, maxLength)
+                        newActivePanels.push(pnlIdx);
+
+                        panels.activePanels = newActivePanels;
+                    }
+                }
             }
         }
-    }
-}]);
+    }]);
 
 // Confirm popup service.
 controlCenterModule.service('$confirm', function ($modal, $rootScope, $q) {
@@ -471,115 +491,115 @@ controlCenterModule.service('$copy', function ($modal, $rootScope, $q) {
 });
 
 // Tables support service.
-controlCenterModule.service('$table', ['$common', function ($common) {
-    function _swapSimpleItems(a, ix1, ix2) {
-        var tmp = a[ix1];
+controlCenterModule.service('$table', [
+    '$common', function ($common) {
+        function _swapSimpleItems(a, ix1, ix2) {
+            var tmp = a[ix1];
 
-        a[ix1] = a[ix2];
-        a[ix2] = tmp;
-    }
+            a[ix1] = a[ix2];
+            a[ix2] = tmp;
+        }
 
-    function _model(item, field) {
-        return $common.getModel(item, field);
-    }
+        function _model(item, field) {
+            return $common.getModel(item, field);
+        }
 
-    var table = {name: 'none', editIndex: -1};
+        var table = {name: 'none', editIndex: -1};
 
-    function _tableReset() {
-        table.name = 'none';
-        table.editIndex = -1;
-    }
+        function _tableReset() {
+            table.name = 'none';
+            table.editIndex = -1;
+        }
 
-    function _tableState(name, editIndex) {
-        table.name = name;
-        table.editIndex = editIndex;
-    }
+        function _tableState(name, editIndex) {
+            table.name = name;
+            table.editIndex = editIndex;
+        }
 
-    return {
-        tableState: function (name, editIndex) {
-            _tableState(name, editIndex);
-        },
-        tableReset: function () {
-            _tableReset();
-        },
-        tableNewItem: function (field) {
-            _tableState(field.model, -1);
-        },
-        tableNewItemActive: function (field) {
-            return table.name == field.model && table.editIndex < 0;
-        },
-        tableEditing: function (field, index) {
-            return table.name == field.model && table.editIndex == index;
-        },
-        tableStartEdit: function (item, field, index) {
-            _tableState(field.model, index);
-
-            return _model(item, field)[field.model][index];
-        },
-        tableRemove: function (item, field, index) {
-            _tableReset();
-
-            _model(item, field)[field.model].splice(index, 1);
-        },
-        tableSimpleSave: function (valueValid, item, field, newValue, index) {
-            if (valueValid(item, field, newValue, index)) {
+        return {
+            tableState: function (name, editIndex) {
+                _tableState(name, editIndex);
+            },
+            tableReset: function () {
+                _tableReset();
+            },
+            tableNewItem: function (field) {
+                _tableState(field.model, -1);
+            },
+            tableNewItemActive: function (field) {
+                return table.name == field.model && table.editIndex < 0;
+            },
+            tableEditing: function (field, index) {
+                return table.name == field.model && table.editIndex == index;
+            },
+            tableStartEdit: function (item, field, index) {
+                _tableState(field.model, index);
+
+                return _model(item, field)[field.model][index];
+            },
+            tableRemove: function (item, field, index) {
                 _tableReset();
 
-                if (index < 0) {
-                    if (_model(item, field)[field.model])
-                        _model(item, field)[field.model].push(newValue);
+                _model(item, field)[field.model].splice(index, 1);
+            },
+            tableSimpleSave: function (valueValid, item, field, newValue, index) {
+                if (valueValid(item, field, newValue, index)) {
+                    _tableReset();
+
+                    if (index < 0) {
+                        if (_model(item, field)[field.model])
+                            _model(item, field)[field.model].push(newValue);
+                        else
+                            _model(item, field)[field.model] = [newValue];
+                    }
                     else
-                        _model(item, field)[field.model] = [newValue];
+                        _model(item, field)[field.model][index] = newValue;
                 }
-                else
-                    _model(item, field)[field.model][index] = newValue;
-            }
-        },
-        tableSimpleSaveVisible: function (newValue) {
-            return !$common.isEmptyString(newValue);
-        },
-        tableSimpleUp: function (item, field, index) {
-            _tableReset();
-
-            _swapSimpleItems(_model(item, field)[field.model], index, index - 1);
-        },
-        tableSimpleDown: function (item, field, index) {
-            _tableReset();
-
-            _swapSimpleItems(_model(item, field)[field.model], index, index + 1);
-        },
-        tableSimpleDownVisible: function (item, field, index) {
-            return index < _model(item, field)[field.model].length - 1;
-        },
-        tablePairSave: function (pairValid, item, field, newKey, newValue, index) {
-            if (pairValid(item, field, newKey, newValue, index)) {
+            },
+            tableSimpleSaveVisible: function (newValue) {
+                return !$common.isEmptyString(newValue);
+            },
+            tableSimpleUp: function (item, field, index) {
                 _tableReset();
 
-                var pair = {};
-
-                if (index < 0) {
-                    pair[field.keyName] = newKey;
-                    pair[field.valueName] = newValue;
+                _swapSimpleItems(_model(item, field)[field.model], index, index - 1);
+            },
+            tableSimpleDown: function (item, field, index) {
+                _tableReset();
 
-                    if (item[field.model])
-                        item[field.model].push(pair);
-                    else
-                        item[field.model] = [pair];
-                }
-                else {
-                    pair = item[field.model][index];
+                _swapSimpleItems(_model(item, field)[field.model], index, index + 1);
+            },
+            tableSimpleDownVisible: function (item, field, index) {
+                return index < _model(item, field)[field.model].length - 1;
+            },
+            tablePairSave: function (pairValid, item, field, newKey, newValue, index) {
+                if (pairValid(item, field, newKey, newValue, index)) {
+                    _tableReset();
+
+                    var pair = {};
+
+                    if (index < 0) {
+                        pair[field.keyName] = newKey;
+                        pair[field.valueName] = newValue;
+
+                        if (item[field.model])
+                            item[field.model].push(pair);
+                        else
+                            item[field.model] = [pair];
+                    }
+                    else {
+                        pair = item[field.model][index];
 
-                    pair[field.keyName] = newKey;
-                    pair[field.valueName] = newValue;
+                        pair[field.keyName] = newKey;
+                        pair[field.valueName] = newValue;
+                    }
                 }
+            },
+            tablePairSaveVisible: function (newKey, newValue) {
+                return !$common.isEmptyString(newKey) && !$common.isEmptyString(newValue);
             }
-        },
-        tablePairSaveVisible: function (newKey, newValue) {
-            return !$common.isEmptyString(newKey) && !$common.isEmptyString(newValue);
         }
-    }
-}]);
-
+    }]);
 
 // Filter to decode name using map(value, label).
 controlCenterModule.filter('displayValue', function () {
@@ -600,24 +620,6 @@ controlCenterModule.filter('displayValue', function () {
     }
 });
 
-/**
- * Filter for replacing all occurrences of {@code org.apache.ignite.} with {@code o.a.i.},
- * {@code org.apache.ignite.internal.} with {@code o.a.i.i.},
- * {@code org.apache.ignite.internal.visor.} with {@code o.a.i.i.v.} and
- * {@code org.apache.ignite.scalar.} with {@code o.a.i.s.}.
- *
- * @param s String to replace in.
- * @return Replaces string.
- */
-controlCenterModule.filter('compact', function () {
-    return function (s) {
-        return s.replace('org.apache.ignite.internal.visor.', 'o.a.i.i.v.').
-            replace('org.apache.ignite.internal.', 'o.a.i.i.').
-            replace('org.apache.ignite.scalar.', 'o.a.i.s.').
-            replace('org.apache.ignite.', 'o.a.i.');
-    }
-});
-
 // Directive to enable validation for IP addresses.
 controlCenterModule.directive('ipaddress', function () {
     const ip = '(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])';
@@ -703,7 +705,7 @@ controlCenterModule.directive('retainSelection', function ($timeout) {
             var input = this;
             var start = input.selectionStart;
 
-            $timeout(function() {
+            $timeout(function () {
                 var setCursor = false;
 
                 // Handle Backspace[8].
@@ -716,7 +718,7 @@ controlCenterModule.directive('retainSelection', function ($timeout) {
                 else if (key == 46)
                     setCursor = true;
                 // Handle: Caps Lock[20], Tab[9], Shift[16], Ctrl[17], Alt[18], Esc[27], Enter[13], Arrows[37..40], Home[36], End[35], Ins[45], PgUp[33], PgDown[34], F1..F12[111..124], Num Lock[], Scroll Lock[145].
-                else  if (!(key == 9 || key == 13 || (key > 15 && key < 20) || key == 27 ||
+                else if (!(key == 9 || key == 13 || (key > 15 && key < 20) || key == 27 ||
                     (key > 32 && key < 41) || key == 45 || (key > 111 && key < 124) || key == 144 || key == 145)) {
                     // Handle: Ctrl + [A[65], C[67], V[86]].
                     if (!(ctrlDown && (key = 65 || key == 67 || key == 86))) {
@@ -789,7 +791,8 @@ controlCenterModule.controller('activeLink', [
     }]);
 
 // Login popup controller.
-controlCenterModule.controller('auth', ['$scope', '$modal', '$http', '$window', '$common', '$focus',
+controlCenterModule.controller('auth', [
+    '$scope', '$modal', '$http', '$window', '$common', '$focus',
     function ($scope, $modal, $http, $window, $common, $focus) {
         $scope.action = 'login';
 
@@ -855,26 +858,31 @@ controlCenterModule.controller('auth', ['$scope', '$modal', '$http', '$window',
     }]);
 
 // Navigation bar controller.
-controlCenterModule.controller('notebooks', ['$scope', '$http', '$common', function ($scope, $http, $common) {
-    $scope.notebooks = [];
-
-    // When landing on the page, get clusters and show them.
-    $http.post('/notebooks/list')
-        .success(function (data) {
-            $scope.notebooks = data;
-
-            if ($scope.notebooks.length > 0) {
-                $scope.notebookDropdown = [
-                    {text: 'Create new notebook', href: '/notebooks/new', target: '_self'},
-                    {divider: true}
-                ];
-
-                _.forEach($scope.notebooks, function (notebook) {
-                    $scope.notebookDropdown.push({text: notebook.name, href: '/sql/' + notebook._id, target: '_self'});
-                });
-            }
-        })
-        .error(function (errMsg) {
-            $common.showError(errMsg);
-        });
-}]);
+controlCenterModule.controller('notebooks', [
+    '$scope', '$http', '$common', function ($scope, $http, $common) {
+        $scope.notebooks = [];
+
+        // When landing on the page, get clusters and show them.
+        $http.post('/notebooks/list')
+            .success(function (data) {
+                $scope.notebooks = data;
+
+                if ($scope.notebooks.length > 0) {
+                    $scope.notebookDropdown = [
+                        {text: 'Create new notebook', href: '/notebooks/new', target: '_self'},
+                        {divider: true}
+                    ];
+
+                    _.forEach($scope.notebooks, function (notebook) {
+                        $scope.notebookDropdown.push({
+                            text: notebook.name,
+                            href: '/sql/' + notebook._id,
+                            target: '_self'
+                        });
+                    });
+                }
+            })
+            .error(function (errMsg) {
+                $common.showError(errMsg);
+            });
+    }]);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8f4607fe/modules/control-center-web/src/main/js/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/controllers/metadata-controller.js b/modules/control-center-web/src/main/js/controllers/metadata-controller.js
index e484c7f..1d96484 100644
--- a/modules/control-center-web/src/main/js/controllers/metadata-controller.js
+++ b/modules/control-center-web/src/main/js/controllers/metadata-controller.js
@@ -246,18 +246,7 @@ controlCenterModule.controller('metadataController', [
                     ]
                 }];
 
-            $scope.activePanels = [0, 1];
-
-            $scope.ensureActivePanel = function (pnlIdx) {
-                if (!$scope.activePanels || $scope.activePanels.length < 1)
-                    $scope.activePanels = [pnlIdx];
-                else if (!_.contains($scope.activePanels, pnlIdx)) {
-                    var newActivePanels = $scope.activePanels.slice();
-                    newActivePanels.push(pnlIdx);
-
-                    $scope.activePanels = newActivePanels;
-                }
-            };
+            $scope.panels = {activePanels: [0, 1]};
 
             $scope.metadatas = [];
 
@@ -386,6 +375,7 @@ controlCenterModule.controller('metadataController', [
             // Add new metadata.
             $scope.createItem = function () {
                 $table.tableReset();
+                $common.ensureActivePanel($scope.panels, 0);
 
                 $scope.selectedItem = undefined;
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8f4607fe/modules/control-center-web/src/main/js/views/configuration/caches.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/configuration/caches.jade b/modules/control-center-web/src/main/js/views/configuration/caches.jade
index fe3f987..5301d5a 100644
--- a/modules/control-center-web/src/main/js/views/configuration/caches.jade
+++ b/modules/control-center-web/src/main/js/views/configuration/caches.jade
@@ -39,7 +39,7 @@ block content
             button.btn.btn-primary(event-focus='defaultFocusId' ng-click='createItem()') Add cache
         hr
         form.form-horizontal(name='inputForm' ng-if='backupItem' novalidate)
-            div(bs-collapse data-start-collapsed='false')
+            .panel-group(bs-collapse ng-model='panels.activePanels' data-allow-multiple='true' ng-click='triggerDigest = true')
                 .panel.panel-default
                     .panel-heading
                         h3
@@ -48,12 +48,11 @@ block content
                         .panel-body
                             .settings-row(ng-repeat='field in general')
                                 +form-row('backupItem')
-            div(ng-show='ui.expanded')
-                .advanced-options
-                    i.fa.fa-chevron-circle-up(ng-click='toggleExpanded()')
-                    a(ng-click='toggleExpanded()') {{ui.expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
-                .panel-group(bs-collapse data-allow-multiple='true' data-start-collapsed='true' ng-click='triggerDigest = true')
-                    .panel.panel-default(ng-repeat='group in advanced')
+                div(ng-show='ui.expanded')
+                    .advanced-options
+                        i.fa.fa-chevron-circle-up(ng-click='toggleExpanded()')
+                        a(ng-click='toggleExpanded()') {{ui.expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
+                    .panel.panel-default(ng-repeat='group in advanced' ng-click='triggerDigest = true')
                         .panel-heading
                             h3
                                 a(bs-collapse-toggle) {{::group.label}}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8f4607fe/modules/control-center-web/src/main/js/views/configuration/clusters.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/configuration/clusters.jade b/modules/control-center-web/src/main/js/views/configuration/clusters.jade
index b3737cf..3d210ed 100644
--- a/modules/control-center-web/src/main/js/views/configuration/clusters.jade
+++ b/modules/control-center-web/src/main/js/views/configuration/clusters.jade
@@ -42,7 +42,7 @@ block content
             i.tipLabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')
         hr
         form.form-horizontal(name='inputForm' ng-if='backupItem' novalidate)
-            div(bs-collapse data-start-collapsed='false')
+            .panel-group(bs-collapse ng-model='panels.activePanels' data-allow-multiple='true' ng-click='triggerDigest = true')
                 .panel.panel-default
                     .panel-heading
                         h3
@@ -51,11 +51,10 @@ block content
                         .panel-body
                             .settings-row(ng-repeat='field in general')
                                 +form-row('backupItem')
-            div(ng-show='ui.expanded')
-                .advanced-options
-                    i.fa.fa-chevron-circle-up(ng-click='toggleExpanded()')
-                    a(ng-click='toggleExpanded()') {{ui.expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
-                .panel-group(bs-collapse data-allow-multiple='true' data-start-collapsed='true')
+                div(ng-show='ui.expanded')
+                    .advanced-options
+                        i.fa.fa-chevron-circle-up(ng-click='toggleExpanded()')
+                        a(ng-click='toggleExpanded()') {{ui.expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
                     .panel.panel-default(ng-repeat='group in advanced')
                         .panel-heading
                             h3

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8f4607fe/modules/control-center-web/src/main/js/views/configuration/metadata.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/configuration/metadata.jade b/modules/control-center-web/src/main/js/views/configuration/metadata.jade
index 9d96515..738083f 100644
--- a/modules/control-center-web/src/main/js/views/configuration/metadata.jade
+++ b/modules/control-center-web/src/main/js/views/configuration/metadata.jade
@@ -36,11 +36,11 @@ block content
                             td(ng-class='{active: row._id == selectedItem._id}')
                                 a(event-focus='defaultFocusId' ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
         .padding-top-dflt
-            button.btn.btn-primary(ng-click='ensureActivePanel(0); createItem();' event-focus='defaultFocusId') Add metadata
+            button.btn.btn-primary(ng-click='createItem()' event-focus='defaultFocusId') Add metadata
             button.btn.btn-primary(ng-click='loadFromDb()') Load from database
         hr
         form.form-horizontal(name='inputForm' ng-if='backupItem' novalidate)
-            .panel-group(bs-collapse ng-model='activePanels' data-allow-multiple='true' ng-click='triggerDigest = true')
+            .panel-group(bs-collapse ng-model='panels.activePanels' data-allow-multiple='true' ng-click='triggerDigest = true')
                 .panel.panel-default(ng-repeat='group in metadata')
                     .panel-heading
                         h3