You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by an...@apache.org on 2015/07/06 13:23:32 UTC

incubator-ignite git commit: # ignite-843 Add validation for ip address

Repository: incubator-ignite
Updated Branches:
  refs/heads/ignite-843 b7e9946d1 -> 23835fa1a


# ignite-843 Add validation for ip address


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

Branch: refs/heads/ignite-843
Commit: 23835fa1af5c5da634876dfcb023abf7ce7aff5e
Parents: b7e9946
Author: Andrey <an...@gridgain.com>
Authored: Mon Jul 6 18:23:42 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Mon Jul 6 18:23:42 2015 +0700

----------------------------------------------------------------------
 .../nodejs/public/form-models/clusters.json     |  1 +
 .../public/javascripts/controllers/clusters.js  |  1 +
 .../public/javascripts/controllers/common.js    | 79 +++++++++++++-------
 .../nodejs/public/stylesheets/style.css         |  2 +-
 .../nodejs/public/stylesheets/style.less        | 44 ++++++++---
 .../nodejs/views/includes/controls.jade         | 32 ++++----
 6 files changed, 106 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/23835fa1/modules/web-control-center/nodejs/public/form-models/clusters.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/public/form-models/clusters.json b/modules/web-control-center/nodejs/public/form-models/clusters.json
index 3258cc8..14c1d82 100644
--- a/modules/web-control-center/nodejs/public/form-models/clusters.json
+++ b/modules/web-control-center/nodejs/public/form-models/clusters.json
@@ -52,6 +52,7 @@
               "model": "addresses",
               "editIdx": -1,
               "reordering": true,
+              "ipaddress": true,
               "placeholder": "IP address:port",
               "tip": [
                 "Addresses may be represented as follows:",

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/23835fa1/modules/web-control-center/nodejs/public/javascripts/controllers/clusters.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/public/javascripts/controllers/clusters.js b/modules/web-control-center/nodejs/public/javascripts/controllers/clusters.js
index a3a3de3..24a3a7c 100644
--- a/modules/web-control-center/nodejs/public/javascripts/controllers/clusters.js
+++ b/modules/web-control-center/nodejs/public/javascripts/controllers/clusters.js
@@ -20,6 +20,7 @@ configuratorModule.controller('clustersController', ['$scope', '$alert', '$http'
         $scope.joinTip = commonFunctions.joinTip;
         $scope.getModel = commonFunctions.getModel;
         $scope.errorMessage = commonFunctions.errorMessage;
+        $scope.console = console;
 
         $scope.templates = [
             {value: {}, label: 'none'},

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/23835fa1/modules/web-control-center/nodejs/public/javascripts/controllers/common.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/public/javascripts/controllers/common.js b/modules/web-control-center/nodejs/public/javascripts/controllers/common.js
index 154eafd..f0221c2 100644
--- a/modules/web-control-center/nodejs/public/javascripts/controllers/common.js
+++ b/modules/web-control-center/nodejs/public/javascripts/controllers/common.js
@@ -19,7 +19,7 @@ var configuratorModule = angular.module('ignite-web-configurator', ['smart-table
 
 configuratorModule.service('commonFunctions', function () {
     return {
-        getModel: function(obj, path) {
+        getModel: function (obj, path) {
             if (!path)
                 return obj;
 
@@ -46,7 +46,7 @@ configuratorModule.service('commonFunctions', function () {
             a[ix1] = a[ix2];
             a[ix2] = tmp;
         },
-        joinTip: function(arr) {
+        joinTip: function (arr) {
             if (!arr) {
                 return arr;
             }
@@ -63,7 +63,7 @@ configuratorModule.service('commonFunctions', function () {
 
             return lines.join("");
         },
-        errorMessage: function(errMsg) {
+        errorMessage: function (errMsg) {
             return errMsg ? errMsg : 'Internal server error.';
         }
     }
@@ -134,37 +134,58 @@ configuratorModule.filter('compact', function () {
     }
 });
 
-configuratorModule.controller('activeLink', ['$scope', function ($scope) {
-    $scope.isActive = function (path) {
-        return window.location.pathname.substr(0, path.length) == path;
-    };
-}]);
+configuratorModule.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])';
+    const port = '([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])';
+    const portRange = '(:' + port + '(..' + port + ')?)?';
+    const host = '(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])';
 
-configuratorModule.controller('auth', ['$scope', '$modal', '$alert', '$http', '$window', 'commonFunctions',
+    return {
+        require: 'ngModel',
+        link: function (scope, elem, attrs, ctrl) {
+            ctrl.$validators.ipaddress = function (modelValue, viewValue) {
+                if (ctrl.$isEmpty(modelValue) || !attrs['ipaddress'])
+                    return true;
+
+                return viewValue.match(new RegExp('(^' + ip + portRange + '$)|(^' + host + portRange + '$)')) != null;
+            }
+        }
+    }
+});
+
+configuratorModule.controller('activeLink', [
+    '$scope', function ($scope) {
+        $scope.isActive = function (path) {
+            return window.location.pathname.substr(0, path.length) == path;
+        };
+    }]);
+
+configuratorModule.controller('auth', [
+    '$scope', '$modal', '$alert', '$http', '$window', 'commonFunctions',
     function ($scope, $modal, $alert, $http, $window, commonFunctions) {
-    $scope.errorMessage = commonFunctions.errorMessage;
+        $scope.errorMessage = commonFunctions.errorMessage;
 
-    $scope.action = 'login';
+        $scope.action = 'login';
 
-    $scope.valid = false;
+        $scope.valid = false;
 
-    // Pre-fetch an external template populated with a custom scope
-    var authModal = $modal({scope: $scope, template: '/login', show: false});
+        // Pre-fetch an external template populated with a custom scope
+        var authModal = $modal({scope: $scope, template: '/login', show: false});
 
-    $scope.login = function () {
-        // Show when some event occurs (use $promise property to ensure the template has been loaded)
-        authModal.$promise.then(authModal.show);
-    };
+        $scope.login = function () {
+            // Show when some event occurs (use $promise property to ensure the template has been loaded)
+            authModal.$promise.then(authModal.show);
+        };
 
-    $scope.auth = function (action, user_info) {
-        $http.post('/rest/auth/' + action, user_info)
-            .success(function (data) {
-                authModal.hide();
+        $scope.auth = function (action, user_info) {
+            $http.post('/rest/auth/' + action, user_info)
+                .success(function (data) {
+                    authModal.hide();
 
-                $window.location = '/clusters';
-            })
-            .error(function (data) {
-                $alert({placement: 'top', container: '#errors-container', title: $scope.errorMessage(data)});
-            });
-    };
-}]);
\ No newline at end of file
+                    $window.location = '/clusters';
+                })
+                .error(function (data) {
+                    $alert({placement: 'top', container: '#errors-container', title: $scope.errorMessage(data)});
+                });
+        };
+    }]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/23835fa1/modules/web-control-center/nodejs/public/stylesheets/style.css
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/public/stylesheets/style.css b/modules/web-control-center/nodejs/public/stylesheets/style.css
index f965b87..b07c421 100644
--- a/modules/web-control-center/nodejs/public/stylesheets/style.css
+++ b/modules/web-control-center/nodejs/public/stylesheets/style.css
@@ -1 +1 @@
-.main-header .logo{height:auto}.main-sidebar{padding-top:60px}.navbar-default .navbar-brand,.navbar-default .navbar-brand:hover{position:absolute;width:100%;left:0;text-align:center}.modal-backdrop.am-fade{opacity:.5;transition:opacity .15s linear}.modal-backdrop.am-fade.ng-enter{opacity:0}.modal-backdrop.am-fade.ng-enter.ng-enter-active{opacity:.5}.modal-backdrop.am-fade.ng-leave{opacity:.5}.modal-backdrop.am-fade.ng-leave.ng-leave-active{opacity:0}.modal.center .modal-dialog{position:fixed;top:40%;left:50%;min-width:320px;max-width:630px;width:50%;transform:translateX(-50%) translateY(-50%)}.border-left{box-shadow:1px 0 0 0 #eee inset}.border-right{box-shadow:1px 0 0 0 #eee}.theme-line{background-color:#f9f9f9}.theme-line header{background-color:#fff}.theme-line header a.btn{border:0 none;padding:10px 25px;background-color:rgba(0,0,0,0.15)}.theme-line header a.btn:hover{background-color:rgba(0,0,0,0.25)}.theme-line header a.btn.btn-link{background:transparent;color:rgba(255,255,25
 5,0.8)}.theme-line header a.btn.btn-link:hover{color:#fff;text-decoration:none}.theme-line .navbar-nav a{background-color:transparent}.theme-line .navbar-nav a:hover,.theme-line .navbar-nav a:active,.theme-line .navbar-nav a:focus{background-color:transparent}.theme-line .main-links{padding-top:50px}.theme-line .main-links h3{margin-top:0;font-size:17px}.theme-line .main-links .links a{color:#888}.theme-line .main-links .links a:hover{text-decoration:none}.theme-line #category-columns,.theme-solid #category-columns{margin:50px 30px 0}.theme-line #category-columns h4{text-transform:uppercase;font-weight:300;color:#999;font-size:14px}.theme-line #category-columns ul{list-style:none;padding:0;margin-bottom:15px}.theme-line #category-columns ul li a{padding:4px 0;display:block;font-size:16px}.theme-line #category-columns ul .view-all{font-size:0.85em}.theme-line .docs-header{color:#999;overflow:hidden}.theme-line .docs-header h1{color:#444;margin-top:0;font-size:25px}.theme-line .btn-pr
 imary{border:0 none;background-color:#ec1c24}.theme-line .btn-primary:hover{background-color:#950d12}.theme-line .main-content .nav-horizontal a{box-shadow:0 0;border:0 none;background-color:#fff;border-radius:0;color:#aaa;padding:6px;margin:0 14px}.theme-line .main-content .nav-horizontal a:hover{color:#999;border-bottom:4px solid #ddd}.theme-line .main-content .nav-horizontal a.active{border-bottom:4px solid #888}.theme-line .sidebar-nav{color:#474a54;padding-bottom:30px}.theme-line .sidebar-nav ul{padding:0;list-style:none;font-size:13px;margin:3px 0 0}.theme-line .sidebar-nav ul li a{padding:3px 0;display:block;color:#666;position:relative;white-space:nowrap;overflow:hidden;-o-text-overflow:ellipsis;text-overflow:ellipsis}.theme-line .sidebar-nav ul li a:before{top:0;content:" ";display:block;width:6px;height:100%;position:absolute;left:-30px}.theme-line .sidebar-nav ul li a:hover{text-decoration:none}.theme-line .select li a,.theme-line .typeahead li a{color:#666;background-col
 or:transparent}.theme-line .select li a:hover,.theme-line .typeahead li a:hover{color:#ec1c24;background-color:transparent}.theme-line .select .active,.theme-line .typeahead .active{background-color:#eee}.theme-line .sidebar-nav ul li .subcategory{padding-left:15px}.theme-line .sidebar-nav h4{margin-top:2em;font-weight:normal;text-transform:uppercase;font-size:11px;margin-bottom:10px;color:#bbb}.theme-line .sidebar-nav h4:first-child{margin-top:0}.theme-line .sidebar-nav .ask{width:100%;text-align:center;padding:10px}.theme-line .border-left .sidebar-nav{padding-left:15px}.theme-line .suggest{padding:4px;display:inline-block;font-size:12px}.header{padding:15px}.header .has-github{padding-right:136px}.header h1.navbar-brand{height:40px;width:200px;padding:0;margin:5px 15px 0 0}.header h1.navbar-brand a{text-indent:-99999px;background:no-repeat center center;display:block;width:100%;height:100%;background-size:contain}.header .nav.navbar-nav.pull-right{position:relative;right:-30px}.h
 eader .nav.navbar-nav .not-link{padding:15px;display:inline-block}.header .nav.navbar-nav .stable,.header .nav.navbar-nav .beta,.header .nav.navbar-nav .private{font-size:9px;padding:3px 5px;display:inline-block;line-height:8px;border-radius:3px;margin-left:6px;color:#fff;top:-2px;position:relative;opacity:0.6;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";filter:alpha(opacity=60)}.header .nav.navbar-nav a:hover>.stable,.header .nav.navbar-nav a:hover>.beta,.header .nav.navbar-nav a:hover>.private{opacity:1;-ms-filter:none;filter:none}.header .nav.navbar-nav .beta{background-color:#59c3d1}.header .nav.navbar-nav .stable{background-color:#41b841}.header .nav.navbar-nav .private{background-color:#333}.theme-line header{border-bottom:8px solid}.theme-line header h2{color:#aaa}.theme-line header p{color:#666}.theme-line header{border-bottom-color:#ec1c24}.theme-line .navbar-nav{color:#888}.theme-line .navbar-nav a{color:#bbb}.theme-line header a.btn{background-color:#e
 c1c24}.theme-line header a.btn:hover{background-color:#950d12}.theme-line header .navbar-nav .tt-cursor{background-color:#ec1c24}.theme-line header .navbar-nav a:hover,.theme-line header .navbar-nav .open>a{color:#ec1c24}.theme-line .navbar-nav .active a{color:#ec1c24}.theme-line .navbar-nav .active a:hover{color:#950d12}.theme-line .main-links .links a:hover{color:#ec1c24}.theme-line .main-content a{color:#666}.theme-line .main-content a:hover{color:#950d12}.theme-line .sidebar-nav ul li a.active:before{background-color:#ec1c24}.theme-line .sidebar-nav ul li a.active{color:#ec1c24}.theme-line .sidebar-nav ul li a:hover,.theme-line .sidebar-nav ul li a.active:hover{color:#950d12}.theme-line .main-content .nav-horizontal a.active{border-color:#ec1c24;color:#ec1c24}.theme-line .main-content .nav-horizontal a:hover{color:#950d12}.theme-line .main-content .nav-horizontal a.active:hover{border-color:#950d12}.theme-line header .navbar-nav a.active,.theme-line #versions-list li a:hover str
 ong,.theme-line #versions-list li a.active .current,.theme-line #versions-list li a:active .current{color:#ec1c24}.theme-line.body-threes .section-right .threes-nav .btn-default:hover,.theme-line.page-docs.body-threes .section-right .threes-nav .pull-right a:hover{color:#ec1c24;border-color:#ec1c24}.theme-line .section-right{padding-left:30px}.body-overlap .main-content{margin-top:30px}.body-box .main-content,.body-overlap .main-content{padding:30px;box-shadow:0 0 0 1px rgba(0,0,0,0.1);background-color:#fff}body{font-weight:400;font-family:Roboto Slab, serif}h1,h2,h3,h4,h5,h6{font-weight:700;font-family:Roboto Slab, serif}.submit-vote.submit-vote-parent.voted a.submit-vote-button,.submit-vote.submit-vote-parent a.submit-vote-button:hover{background-color:#ec1c24}div.submit-vote.submit-vote-parent.voted a.submit-vote-button:hover{background-color:#950d12}a,.link .title{color:#ec1c24}a:hover,.link:hover .title{color:#950d12}.header h1.navbar-brand a{background-image:url("https://www.f
 ilepicker.io/api/file/QagunjDGRFul2JgNCAli")}.header h1.navbar-brand{width:96px}.block-edit-parameters{text-align:right;padding-bottom:5px}.ng-table-pager{display:none}.container-footer{margin-top:20px}.vcenter{display:inline-block;vertical-align:middle;float:none}.vcenter2{position:relative;top:50%;transform:translateY(-50%)}.modal{display:block;overflow:hidden}.modal .close{position:absolute;top:0.65em;right:0.65em;float:none}.modal-header .close{margin-right:-2px}.modal .modal-dialog{width:610px}.modal .modal-content{border-radius:0;background-color:#f7f7f7}.modal .modal-content .modal-header{background-color:#fff;text-align:center;color:#555;padding:24px;font-family:"myriad-pro",sans-serif}.modal .modal-content .modal-header h4{font-family:"myriad-pro",sans-serif;font-size:22px}.modal .modal-content .modal-header h4 .fa{display:block;font-size:41px;color:#ddd;margin-bottom:5px}.modal .modal-content .modal-header p{color:#aaa;font-size:1em;margin:3px 0 0}.modal .modal-content .mo
 dal-spacer{padding:10px 10px 0 10px}.modal .modal-content .modal-footer{margin-top:0}.modal-body{padding-top:15px}h1.ignite-logo{background-image:url("https://www.filepicker.io/api/file/QagunjDGRFul2JgNCAli")}.st-sort-ascent:after{font-family:FontAwesome, serif;content:'\f077'}.st-sort-descent:after{font-family:FontAwesome, serif;content:'\f078'}.block-display-image img{max-width:100%;max-height:450px;margin:auto;display:block}.greedy{min-height:200px;height:calc(100vh - 230px)}@media (min-width:768px){.navbar-nav>li>a{padding-top:20px;padding-bottom:10px}}.details-row{padding-left:1.3em}.details-table-row{padding:0}.details-row,.settings-row{display:block;margin:0.65em 0;line-height:28px}.details-row [class*="col-"],.settings-row [class*="col-"]{display:inline-block;vertical-align:middle;float:none;padding-left:0 !important;padding-right:0 !important}.details-row input[type="checkbox"],.settings-row input[type="checkbox"]{line-height:20px;margin-right:4px}.details-row .checkbox lab
 el,.settings-row .checkbox label{line-height:20px;vertical-align:middle}button{margin-right:4px}h1,h2,h3{user-select:none;font-weight:normal;line-height:1}h3{color:black;font-size:1.2em;margin-top:0;margin-bottom:1.5em}table tr:hover{cursor:pointer}.input-group{display:inline-block}.input-group .form-control{width:auto;margin-left:0;margin-right:0}.form-control{display:inline-block;text-align:left;padding:3px 3px;height:28px}.form-control button{text-align:left}.table-form-control{width:auto}button .caret{float:right;margin-left:0;margin-top:7px}.theme-line .panel-heading{padding:10px 10px;margin:0}.theme-line .panel-heading h3{margin-bottom:0}.theme-line .panel-heading h3>a{color:black;cursor:pointer}.theme-line .panel-title a{color:#ec1c24}.theme-line .panel-title h3{margin-bottom:1.3em}.theme-line .panel-body{padding:0.65em 1.3em}.theme-line .main-content a.customize{color:#ec1c24;cursor:pointer}.theme-line .panel-collapse{margin:0}.theme-line .links table,.theme-line table.links
 -edit,.theme-line table.links-edit-small-padding{display:table;table-layout:fixed;margin-bottom:10px}.theme-line .links table td,.theme-line table.links-edit td,.theme-line table.links-edit-small-padding td{padding-left:18px}.theme-line .links table .active a,.theme-line table.links-edit .active a,.theme-line table.links-edit-small-padding .active a{color:#ec1c24;font-weight:bold}.theme-line .links table a:hover,.theme-line table.links-edit a:hover,.theme-line table.links-edit-small-padding a:hover{color:#950d12}.theme-line .links table a,.theme-line table.links-edit a,.theme-line table.links-edit-small-padding a{color:#666}.theme-line table.links-edit label{line-height:28px;color:#666}.btn{padding:3px 6px}.panel-title a{font-size:14px}.panel-details{margin-top:1.3em;margin-bottom:0.65em;padding:0.65em;border-radius:4px;border:thin dotted lightgrey}.tooltip.right .tooltip-arrow{border-right-color:#ec1c24}.tooltip>.tooltip-inner{max-width:400px;text-align:left;background-color:#ec1c2
 4}label{font-weight:normal;line-height:14px;margin-bottom:0}.form-horizontal .checkbox{padding-top:0}.input-tip{display:block;overflow:hidden;padding-right:4px}.labelField{float:left;margin-right:4px}.tipField{float:right;line-height:28px;margin-right:5px}.tipLabel{font-size:14px;margin-left:4px}.fieldButton{float:right;margin-left:4px;margin-right:0}.table-nowrap{table-layout:fixed}.td-overflow{max-width:100px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fa-edit{cursor:pointer}.fa-remove{color:#ec1c24;margin-left:5px;margin-right:5px;cursor:pointer}label.required:after{color:#ec1c24;content:' *';display:inline}.blank{visibility:hidden}.alert{outline:0}.alert.bottom,.alert.bottom-left,.alert.bottom-right,.alert.top,.alert.top-left,.alert.top-right{position:fixed;z-index:1050;margin:20px}.alert.top,.alert.top-left,.alert.top-right{top:50px}.alert.top{right:0;left:0}.alert.top-right{right:0}.alert.top-right .close{padding-left:10px}.alert.top-left{left:0}.alert.top-left 
 .close{padding-right:10px}.alert.bottom,.alert.bottom-left,.alert.bottom-right{bottom:0}.alert.bottom{right:0;left:0}.alert.bottom-right{right:0}.alert.bottom-right .close{padding-left:10px}.alert.bottom-left{left:0}.alert.bottom-left .close{padding-right:10px}#cfgResult textarea{font-family:monospace;font-size:12px}input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type="number"]{-moz-appearance:textfield}input.ng-dirty.ng-invalid{border-color:#ec1c24}input.ng-dirty.ng-invalid :focus{border-color:#ec1c24}.form-control-feedback{display:inline-block;color:#ec1c24;right:18px;line-height:28px;pointer-events:initial}.syntaxhighlighter{padding:10px 5px;border-radius:6px}.theme-line table.links-edit-small-padding{margin-top:10px}.theme-line table.links-edit-small-padding label{line-height:28px;color:#666}.theme-line table.links-edit-small-padding a{line-height:28px}.theme-line table.links-edit-small-paddin
 g input[type="checkbox"]{line-height:20px;margin-right:4px}.theme-line table.links-edit-small-padding .checkbox label{line-height:20px;vertical-align:middle}.theme-line table.links-edit-small-padding th{text-align:center}.theme-line table.links-edit-small-padding td{padding-left:10px}.configBox .nav>li>a{padding:5px 5px}
\ No newline at end of file
+.main-header .logo{height:auto}.main-sidebar{padding-top:60px}.navbar-default .navbar-brand,.navbar-default .navbar-brand:hover{position:absolute;width:100%;left:0;text-align:center}.modal-backdrop.am-fade{opacity:.5;transition:opacity .15s linear}.modal-backdrop.am-fade.ng-enter{opacity:0}.modal-backdrop.am-fade.ng-enter.ng-enter-active{opacity:.5}.modal-backdrop.am-fade.ng-leave{opacity:.5}.modal-backdrop.am-fade.ng-leave.ng-leave-active{opacity:0}.modal.center .modal-dialog{position:fixed;top:40%;left:50%;min-width:320px;max-width:630px;width:50%;transform:translateX(-50%) translateY(-50%)}.border-left{box-shadow:1px 0 0 0 #eee inset}.border-right{box-shadow:1px 0 0 0 #eee}.theme-line{background-color:#f9f9f9}.theme-line header{background-color:#fff}.theme-line header a.btn{border:0 none;padding:10px 25px;background-color:rgba(0,0,0,0.15)}.theme-line header a.btn:hover{background-color:rgba(0,0,0,0.25)}.theme-line header a.btn.btn-link{background:transparent;color:rgba(255,255,25
 5,0.8)}.theme-line header a.btn.btn-link:hover{color:#fff;text-decoration:none}.theme-line .navbar-nav a{background-color:transparent}.theme-line .navbar-nav a:hover,.theme-line .navbar-nav a:active,.theme-line .navbar-nav a:focus{background-color:transparent}.theme-line .main-links{padding-top:50px}.theme-line .main-links h3{margin-top:0;font-size:17px}.theme-line .main-links .links a{color:#888}.theme-line .main-links .links a:hover{text-decoration:none}.theme-line #category-columns,.theme-solid #category-columns{margin:50px 30px 0}.theme-line #category-columns h4{text-transform:uppercase;font-weight:300;color:#999;font-size:14px}.theme-line #category-columns ul{list-style:none;padding:0;margin-bottom:15px}.theme-line #category-columns ul li a{padding:4px 0;display:block;font-size:16px}.theme-line #category-columns ul .view-all{font-size:0.85em}.theme-line .docs-header{color:#999;overflow:hidden}.theme-line .docs-header h1{color:#444;margin-top:0;font-size:25px}.theme-line .btn-pr
 imary{border:0 none;background-color:#ec1c24}.theme-line .btn-primary:hover{background-color:#950d12}.theme-line .main-content .nav-horizontal a{box-shadow:0 0;border:0 none;background-color:#fff;border-radius:0;color:#aaa;padding:6px;margin:0 14px}.theme-line .main-content .nav-horizontal a:hover{color:#999;border-bottom:4px solid #ddd}.theme-line .main-content .nav-horizontal a.active{border-bottom:4px solid #888}.theme-line .sidebar-nav{color:#474a54;padding-bottom:30px}.theme-line .sidebar-nav ul{padding:0;list-style:none;font-size:13px;margin:3px 0 0}.theme-line .sidebar-nav ul li a{padding:3px 0;display:block;color:#666;position:relative;white-space:nowrap;overflow:hidden;-o-text-overflow:ellipsis;text-overflow:ellipsis}.theme-line .sidebar-nav ul li a:before{top:0;content:" ";display:block;width:6px;height:100%;position:absolute;left:-30px}.theme-line .sidebar-nav ul li a:hover{text-decoration:none}.theme-line .select li a,.theme-line .typeahead li a{color:#666;background-col
 or:transparent}.theme-line .select li a:hover,.theme-line .typeahead li a:hover{color:#ec1c24;background-color:transparent}.theme-line .select .active,.theme-line .typeahead .active{background-color:#eee}.theme-line .sidebar-nav ul li .subcategory{padding-left:15px}.theme-line .sidebar-nav h4{margin-top:2em;font-weight:normal;text-transform:uppercase;font-size:11px;margin-bottom:10px;color:#bbb}.theme-line .sidebar-nav h4:first-child{margin-top:0}.theme-line .sidebar-nav .ask{width:100%;text-align:center;padding:10px}.theme-line .border-left .sidebar-nav{padding-left:15px}.theme-line .suggest{padding:4px;display:inline-block;font-size:12px}.header{padding:15px}.header .has-github{padding-right:136px}.header h1.navbar-brand{height:40px;width:200px;padding:0;margin:5px 15px 0 0}.header h1.navbar-brand a{text-indent:-99999px;background:no-repeat center center;display:block;width:100%;height:100%;background-size:contain}.header .nav.navbar-nav.pull-right{position:relative;right:-30px}.h
 eader .nav.navbar-nav .not-link{padding:15px;display:inline-block}.header .nav.navbar-nav .stable,.header .nav.navbar-nav .beta,.header .nav.navbar-nav .private{font-size:9px;padding:3px 5px;display:inline-block;line-height:8px;border-radius:3px;margin-left:6px;color:#fff;top:-2px;position:relative;opacity:0.6;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";filter:alpha(opacity=60)}.header .nav.navbar-nav a:hover>.stable,.header .nav.navbar-nav a:hover>.beta,.header .nav.navbar-nav a:hover>.private{opacity:1;-ms-filter:none;filter:none}.header .nav.navbar-nav .beta{background-color:#59c3d1}.header .nav.navbar-nav .stable{background-color:#41b841}.header .nav.navbar-nav .private{background-color:#333}.theme-line header{border-bottom:8px solid}.theme-line header h2{color:#aaa}.theme-line header p{color:#666}.theme-line header{border-bottom-color:#ec1c24}.theme-line .navbar-nav{color:#888}.theme-line .navbar-nav a{color:#bbb}.theme-line header a.btn{background-color:#e
 c1c24}.theme-line header a.btn:hover{background-color:#950d12}.theme-line header .navbar-nav .tt-cursor{background-color:#ec1c24}.theme-line header .navbar-nav a:hover,.theme-line header .navbar-nav .open>a{color:#ec1c24}.theme-line .navbar-nav .active a{color:#ec1c24}.theme-line .navbar-nav .active a:hover{color:#950d12}.theme-line .main-links .links a:hover{color:#ec1c24}.theme-line .main-content a{color:#666}.theme-line .main-content a:hover{color:#950d12}.theme-line .sidebar-nav ul li a.active:before{background-color:#ec1c24}.theme-line .sidebar-nav ul li a.active{color:#ec1c24}.theme-line .sidebar-nav ul li a:hover,.theme-line .sidebar-nav ul li a.active:hover{color:#950d12}.theme-line .main-content .nav-horizontal a.active{border-color:#ec1c24;color:#ec1c24}.theme-line .main-content .nav-horizontal a:hover{color:#950d12}.theme-line .main-content .nav-horizontal a.active:hover{border-color:#950d12}.theme-line header .navbar-nav a.active,.theme-line #versions-list li a:hover str
 ong,.theme-line #versions-list li a.active .current,.theme-line #versions-list li a:active .current{color:#ec1c24}.theme-line.body-threes .section-right .threes-nav .btn-default:hover,.theme-line.page-docs.body-threes .section-right .threes-nav .pull-right a:hover{color:#ec1c24;border-color:#ec1c24}.theme-line .section-right{padding-left:30px}.body-overlap .main-content{margin-top:30px}.body-box .main-content,.body-overlap .main-content{padding:30px;box-shadow:0 0 0 1px rgba(0,0,0,0.1);background-color:#fff}body{font-weight:400;font-family:Roboto Slab, serif}h1,h2,h3,h4,h5,h6{font-weight:700;font-family:Roboto Slab, serif}.submit-vote.submit-vote-parent.voted a.submit-vote-button,.submit-vote.submit-vote-parent a.submit-vote-button:hover{background-color:#ec1c24}div.submit-vote.submit-vote-parent.voted a.submit-vote-button:hover{background-color:#950d12}a,.link .title{color:#ec1c24}a:hover,.link:hover .title{color:#950d12}.header h1.navbar-brand a{background-image:url("https://www.f
 ilepicker.io/api/file/QagunjDGRFul2JgNCAli")}.header h1.navbar-brand{width:96px}.block-edit-parameters{text-align:right;padding-bottom:5px}.ng-table-pager{display:none}.container-footer{margin-top:20px}.vcenter{display:inline-block;vertical-align:middle;float:none}.vcenter2{position:relative;top:50%;transform:translateY(-50%)}.modal{display:block;overflow:hidden}.modal .close{position:absolute;top:0.65em;right:0.65em;float:none}.modal-header .close{margin-right:-2px}.modal .modal-dialog{width:610px}.modal .modal-content{border-radius:0;background-color:#f7f7f7}.modal .modal-content .modal-header{background-color:#fff;text-align:center;color:#555;padding:24px;font-family:"myriad-pro",sans-serif}.modal .modal-content .modal-header h4{font-family:"myriad-pro",sans-serif;font-size:22px}.modal .modal-content .modal-header h4 .fa{display:block;font-size:41px;color:#ddd;margin-bottom:5px}.modal .modal-content .modal-header p{color:#aaa;font-size:1em;margin:3px 0 0}.modal .modal-content .mo
 dal-spacer{padding:10px 10px 0 10px}.modal .modal-content .modal-footer{margin-top:0}.modal-body{padding-top:15px}h1.ignite-logo{background-image:url("https://www.filepicker.io/api/file/QagunjDGRFul2JgNCAli")}.st-sort-ascent:after{font-family:FontAwesome, serif;content:'\f077'}.st-sort-descent:after{font-family:FontAwesome, serif;content:'\f078'}.block-display-image img{max-width:100%;max-height:450px;margin:auto;display:block}.greedy{min-height:200px;height:calc(100vh - 230px)}@media (min-width:768px){.navbar-nav>li>a{padding-top:20px;padding-bottom:10px}}.details-row{padding:0 0.65em}.details-table-row{padding:0}.details-row,.settings-row{display:block;margin:0.65em 0;line-height:28px}.details-row [class*="col-"],.settings-row [class*="col-"]{display:inline-block;vertical-align:middle;float:none;padding-left:0 !important;padding-right:0 !important}.details-row input[type="checkbox"],.settings-row input[type="checkbox"]{line-height:20px;margin-right:4px}.details-row .checkbox label
 ,.settings-row .checkbox label{line-height:20px;vertical-align:middle}button{margin-right:4px}h1,h2,h3{user-select:none;font-weight:normal;line-height:1}h3{color:black;font-size:1.2em;margin-top:0;margin-bottom:1.5em}table tr:hover{cursor:pointer}.input-group{display:inline-block}.input-group .form-control{width:auto;margin-left:0;margin-right:0}.form-control{display:inline-block;text-align:left;padding:3px 3px;height:28px}.form-control button{text-align:left}.table-form-control{width:auto}button .caret{float:right;margin-left:0;margin-top:7px}.theme-line .panel-heading{padding:10px 10px;margin:0}.theme-line .panel-heading h3{margin-bottom:0}.theme-line .panel-heading h3>a{color:black;cursor:pointer}.theme-line .panel-title a{color:#ec1c24}.theme-line .panel-title h3{margin-bottom:1.3em}.theme-line .panel-body{padding:0.65em 1.3em}.theme-line .main-content a.customize{margin-left:5px;color:#ec1c24;cursor:pointer}.theme-line .panel-collapse{margin:0}.theme-line .links table,.theme-li
 ne table.links-edit,.theme-line table.links-edit-details,.theme-line table.links-edit-small-padding{display:table;table-layout:fixed;margin-bottom:10px}.theme-line .links table td,.theme-line table.links-edit td,.theme-line table.links-edit-details td,.theme-line table.links-edit-small-padding td{padding-left:18px}.theme-line .links table .active a,.theme-line table.links-edit .active a,.theme-line table.links-edit-details .active a,.theme-line table.links-edit-small-padding .active a{color:#ec1c24;font-weight:bold}.theme-line .links table a:hover,.theme-line table.links-edit a:hover,.theme-line table.links-edit-details a:hover,.theme-line table.links-edit-small-padding a:hover{color:#950d12}.theme-line .links table a,.theme-line table.links-edit a,.theme-line table.links-edit-details a,.theme-line table.links-edit-small-padding a{color:#666}.theme-line table.links-edit label{line-height:28px;color:#666}.theme-line table.links-edit-details label{line-height:28px;color:#666}.theme-li
 ne table.links-edit-details td{padding:0}.theme-line table.links-edit-details td .input-tip{padding:0}.btn{padding:3px 6px}.panel-title a{font-size:14px}.panel-details{margin-top:0.65em;padding:0;border-radius:4px;border:thin dotted lightgrey}.tooltip.right .tooltip-arrow{border-right-color:#ec1c24}.tooltip>.tooltip-inner{max-width:400px;text-align:left;background-color:#ec1c24}label{font-weight:normal;line-height:14px;margin-bottom:0}.form-horizontal .checkbox{padding-top:0}.input-tip{display:block;overflow:hidden}.labelField{float:left;margin-right:4px}.stackTipField{float:right;line-height:28px;margin-left:5px}.form-horizontal .form-group{margin:0}.form-horizontal .has-feedback .form-control-feedback{right:0}.tipField{float:right;line-height:28px;margin-left:5px}.tipLabel{font-size:14px;margin-left:4px}.fieldButton{float:right;margin-left:4px;margin-right:0}.table-nowrap{table-layout:fixed}.td-overflow{max-width:100px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fa-
 edit{cursor:pointer}.fa-remove{color:#ec1c24;cursor:pointer}label.required:after{color:#ec1c24;content:' *';display:inline}.blank{visibility:hidden}.alert{outline:0}.alert.bottom,.alert.bottom-left,.alert.bottom-right,.alert.top,.alert.top-left,.alert.top-right{position:fixed;z-index:1050;margin:20px}.alert.top,.alert.top-left,.alert.top-right{top:50px}.alert.top{right:0;left:0}.alert.top-right{right:0}.alert.top-right .close{padding-left:10px}.alert.top-left{left:0}.alert.top-left .close{padding-right:10px}.alert.bottom,.alert.bottom-left,.alert.bottom-right{bottom:0}.alert.bottom{right:0;left:0}.alert.bottom-right{right:0}.alert.bottom-right .close{padding-left:10px}.alert.bottom-left{left:0}.alert.bottom-left .close{padding-right:10px}#cfgResult textarea{font-family:monospace;font-size:12px}input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type="number"]{-moz-appearance:textfield}input.ng-dirty.n
 g-invalid{border-color:#ec1c24}input.ng-dirty.ng-invalid :focus{border-color:#ec1c24}.form-control-feedback{display:inline-block;color:#ec1c24;right:18px;line-height:28px;pointer-events:initial}.syntaxhighlighter{padding:10px 5px;border-radius:6px}.theme-line table.links-edit-small-padding{margin-top:10px}.theme-line table.links-edit-small-padding label{line-height:28px;color:#666}.theme-line table.links-edit-small-padding a{line-height:28px}.theme-line table.links-edit-small-padding input[type="checkbox"]{line-height:20px;margin-right:4px}.theme-line table.links-edit-small-padding .checkbox label{line-height:20px;vertical-align:middle}.theme-line table.links-edit-small-padding th{text-align:center}.theme-line table.links-edit-small-padding td{padding-left:10px}.configBox .nav>li>a{padding:5px 5px}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/23835fa1/modules/web-control-center/nodejs/public/stylesheets/style.less
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/public/stylesheets/style.less b/modules/web-control-center/nodejs/public/stylesheets/style.less
index 96fec00..1d5ebcd 100644
--- a/modules/web-control-center/nodejs/public/stylesheets/style.less
+++ b/modules/web-control-center/nodejs/public/stylesheets/style.less
@@ -620,7 +620,7 @@ h1.ignite-logo {
 }
 
 .details-row {
-  padding-left: 1.3em;
+  padding: 0 0.65em;
 }
 
 .details-table-row  {
@@ -735,7 +735,7 @@ button .caret {
 }
 
 .theme-line .main-content a.customize {
-  //margin-left: 10px;
+  margin-left: 5px;
   color: #ec1c24;
   cursor: pointer;
 }
@@ -774,6 +774,21 @@ button .caret {
   }
 }
 
+.theme-line table.links-edit-details:extend(.theme-line .links table all) {
+  label {
+    line-height: @input-height;
+    color: #666;
+  }
+
+  td {
+    padding: 0;
+
+    .input-tip {
+      padding: 0;
+    }
+  }
+}
+
 .btn {
   padding: 3px 6px;
 }
@@ -783,9 +798,9 @@ button .caret {
 }
 
 .panel-details {
-  margin-top: 1.3em;
-  margin-bottom: 0.65em;
-  padding: 0.65em;
+  margin-top: 0.65em;
+
+  padding: 0;
 
   border-radius: 4px;
   border: thin dotted lightgrey;
@@ -814,7 +829,6 @@ label {
 .input-tip {
   display: block;
   overflow: hidden;
-  padding-right:4px;
 }
 
 .labelField {
@@ -822,10 +836,24 @@ label {
   margin-right: 4px;
 }
 
+.stackTipField {
+  float: right;
+  line-height: @input-height;
+  margin-left: 5px;
+}
+
+.form-horizontal .form-group {
+  margin: 0;
+}
+
+.form-horizontal .has-feedback .form-control-feedback {
+  right: 0;
+}
+
 .tipField {
   float: right;
   line-height: @input-height;
-  margin-right: 5px;
+  margin-left: 5px;
 }
 
 .tipLabel {
@@ -856,8 +884,6 @@ label {
 
 .fa-remove {
   color: #ec1c24;
-  margin-left: 5px;
-  margin-right: 5px;
   cursor: pointer;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/23835fa1/modules/web-control-center/nodejs/views/includes/controls.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/includes/controls.jade b/modules/web-control-center/nodejs/views/includes/controls.jade
index 4a698d7..16d61cf 100644
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ b/modules/web-control-center/nodejs/views/includes/controls.jade
@@ -31,6 +31,8 @@ mixin details-row
     - var detailMdl = 'getModel(backupItem, detail.path)[detail.model]';
     - var detailCommon = {'ng-model': detailMdl};
 
+    - var customValidators = {'ng-attr-ipaddress': '{{detail.ipaddress}}'}
+
     div(ng-switch='detail.type')
         div.checkbox(ng-switch-when='check')
             label
@@ -63,26 +65,28 @@ mixin details-row
             .col-sm-8
                 button.form-control(bs-select data-multiple='1' data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in {{detail.items}}')&attributes(detailCommon)
             +tipField('detail.tip')
-        div(ng-switch-when='table-simple' style='margin-right: 5px; margin-top: -0.65em')&attributes(detailCommon)
-            table.col-sm-12.links-edit(st-table='#{detailMdl}' ng-show='#{detailMdl}.length > 0')
+        div(ng-switch-when='table-simple')&attributes(detailCommon)
+            table.col-sm-12.links-edit-details(st-table='#{detailMdl}' ng-show='#{detailMdl}.length > 0')
                 tbody
                     tr(ng-repeat='item in #{detailMdl} track by $index')
-                        td.col-sm-11
+                        td
                             div(ng-show='detail.editIdx != {{$index}}')
-                                a(ng-click='detail.editIdx = $index; curValue = #{detailMdl}[$index]') {{$index + 1}}) {{item}}
-                                i.tipField.fa.fa-remove(ng-click='detail.editIdx = -1; #{detailMdl}.splice($index, 1)')
+                                i.stackTipField.fa.fa-remove(ng-click='detail.editIdx = -1; #{detailMdl}.splice($index, 1)')
+                                i.stackTipField.fa.fa-arrow-down(ng-show='$index < #{detailMdl}.length - 1' ng-click='swapSimpleItems(#{detailMdl}, $index, $index + 1); detail.editIdx = -1;')
+                                i.stackTipField.fa.fa-arrow-up(ng-show='$index > 0' ng-click='swapSimpleItems(detailMdl, $index, $index - 1); detail.editIdx = -1;')
+                                .input-tip
+                                    a(ng-click='detail.editIdx = $index; curValue = #{detailMdl}[$index]') {{$index + 1}}) {{item}}
                             div(ng-show='detail.editIdx == {{$index}}')
                                 label.labelField {{$index + 1}})
-                                i.tipField.fa.fa-floppy-o(ng-click='detail.editIdx = -1; #{detailMdl}[$index]=curValue')
-                                .input-tip
-                                    input.form-control(type='text' ng-model='curValue' placeholder='{{detail.placeholder}}')
-                        td.col-sm-1(ng-if='detail.reordering')
-                            i.fa.fa-arrow-up(ng-show='$index > 0' ng-click='swapSimpleItems(detailMdl, $index, $index - 1); detail.editIdx = -1;')
-                            i.fa.fa-arrow-down(ng-show='$index < #{detailMdl}.length - 1' ng-click='swapSimpleItems(#{detailMdl}, $index, $index + 1); detail.editIdx = -1;')
-            button.btn.btn-primary.fieldButton(ng-disabled='!newValue || #{detailMdl}.indexOf(newValue) >= 0' ng-click='detail.editIdx = -1; #{detailMdl} ? #{detailMdl}.push(newValue) : #{detailMdl} = [newValue];') Add
+                                i.stackTipField.fa.fa-floppy-o(ng-click='#{detailMdl}[$index] = curValue ? curValue : #{detailMdl}[$index]; detail.editIdx = curValue ? -1 : detail.editIdx')
+                                .input-tip.form-group.has-feedback
+                                    input.form-control(name='{{detail.model}}.edit' type='text' ng-model='curValue' placeholder='{{detail.placeholder}}')&attributes(customValidators)
+                                    +exclamation('{{detail.model}}.edit', 'ipaddress', 'Invalid address, see help for format description.')
+            button.btn.btn-primary.fieldButton(style='margin-left: 0' ng-disabled='!newValue || #{detailMdl}.indexOf(newValue) >= 0' ng-click='detail.editIdx = -1; #{detailMdl} ? #{detailMdl}.push(newValue) : #{detailMdl} = [newValue];') Add
             +tipField('detail.tip')
-            .input-tip
-                input.form-control(type='text' ng-model='newValue' ng-focus='detail.editIdx = -1' placeholder='{{detail.placeholder}}')
+            .input-tip.form-group.has-feedback
+                input.form-control(name='{{detail.model}}' type='text' ng-model='newValue' ng-focus='detail.editIdx = -1' placeholder='{{detail.placeholder}}')&attributes(customValidators)
+                +exclamation('{{detail.model}}', 'ipaddress', 'Invalid address, see help for format description.')
 
 mixin form-row
     - var lblClasses = ['col-sm-2']