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/23 10:40:32 UTC

[01/50] [abbrv] incubator-ignite git commit: IGNITE-843 Added tooltips.

Repository: incubator-ignite
Updated Branches:
  refs/heads/ignite-1121 679e3280a -> a45a700c6


IGNITE-843 Added tooltips.


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

Branch: refs/heads/ignite-1121
Commit: 36cfaad67739ced742c8a7a052a0bbc7b5388934
Parents: d298fd8
Author: AKuznetsov <ak...@gridgain.com>
Authored: Mon Jul 20 17:40:45 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Mon Jul 20 17:40:45 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/models/metadata.json     | 31 ++++++++++++--------
 1 file changed, 19 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/36cfaad6/modules/web-control-center/nodejs/controllers/models/metadata.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/metadata.json b/modules/web-control-center/nodejs/controllers/models/metadata.json
index a3c0c75..3315835 100644
--- a/modules/web-control-center/nodejs/controllers/models/metadata.json
+++ b/modules/web-control-center/nodejs/controllers/models/metadata.json
@@ -25,7 +25,14 @@
       "type": "dropdown",
       "model": "kind",
       "items": "kinds",
-      "tip": ["TODO."]
+      "tip": [
+        "Use following template for metadata:",
+        "<ul>",
+        "  <li>query - Create cache type metadata to use with queries only.</li>",
+        "  <li>store - Create cache type metadata to use with JDBC POJO store only.</li>",
+        "  <li>both - Create cache type metadata to use with query and store.</li>",
+        "</ul>"
+      ]
     },
     {
       "label": "Database schema",
@@ -33,7 +40,7 @@
       "model": "databaseSchema",
       "hide": "backupItem.kind == 'query'",
       "placeholder": "Input DB schema name",
-      "tip": ["TODO."]
+      "tip": ["Schema name in database."]
     },
     {
       "label": "Database table",
@@ -41,7 +48,7 @@
       "model": "databaseTable",
       "hide": "backupItem.kind == 'query'",
       "placeholder": "Input DB table name",
-      "tip": ["TODO."]
+      "tip": ["Table name in database."]
     },
     {
       "label": "Key type",
@@ -49,7 +56,7 @@
       "model": "keyType",
       "required": true,
       "placeholder": "Full class name for Key",
-      "tip": ["TODO."]
+      "tip": ["Key class used to store key in cache."]
     },
     {
       "label": "Value type",
@@ -57,7 +64,7 @@
       "model": "valueType",
       "required": true,
       "placeholder": "Full class name for Value",
-      "tip": ["TODO."]
+      "tip": ["Value class used to store value in cache."]
     },
     {
       "label": "Key fields",
@@ -66,7 +73,7 @@
       "keyName": "name",
       "valueName": "className",
       "hide": "backupItem.kind == 'query'",
-      "tip": ["Collection of key fields descriptions."]
+      "tip": ["Collection of key fields descriptions for CacheJdbcPojoStore."]
     },
     {
       "label": "Value fields",
@@ -75,7 +82,7 @@
       "keyName": "name",
       "valueName": "className",
       "hide": "backupItem.kind == 'query'",
-      "tip": ["Collection of value fields descriptions."]
+      "tip": ["Collection of value fields descriptions for CacheJdbcPojoStore.."]
     },
     {
       "label": "Query fields",
@@ -84,7 +91,7 @@
       "keyName": "name",
       "valueName": "className",
       "hide": "backupItem.kind != 'query'",
-      "tip": ["TODO."]
+      "tip": ["Collection of name-to-type mappings to be queried, in addition to indexed fields."]
     },
     {
       "label": "Ascending fields",
@@ -93,7 +100,7 @@
       "keyName": "name",
       "valueName": "className",
       "hide": "backupItem.kind != 'query'",
-      "tip": ["TODO."]
+      "tip": ["Collection of name-to-type mappings to index in ascending order."]
     },
     {
       "label": "Descending fields",
@@ -102,7 +109,7 @@
       "keyName": "name",
       "valueName": "className",
       "hide": "backupItem.kind != 'query'",
-      "tip": ["TODO."]
+      "tip": ["Collection of name-to-type mappings to index in descending order."]
     },
     {
       "label": "Text fields",
@@ -110,14 +117,14 @@
       "model": "textFields",
       "hide": "backupItem.kind != 'query'",
       "placeholder": "Field name",
-      "tip": ["TODO."]
+      "tip": ["Fields to index as text."]
     },
     {
       "label": "Groups",
       "type": "groupsMetadata",
       "model": "groups",
       "hide": "backupItem.kind != 'query'",
-      "tip": ["TODO."]
+      "tip": ["Collection of group indexes."]
     }
   ],
   "metadataDb": [


[09/50] [abbrv] incubator-ignite git commit: IGNITE-843: WIP: groups.

Posted by an...@apache.org.
IGNITE-843: WIP: groups.


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

Branch: refs/heads/ignite-1121
Commit: 18f554d8348a5e8f168d08708716b0490b183a00
Parents: 3ab9a91
Author: AKuznetsov <ak...@gridgain.com>
Authored: Tue Jul 21 00:49:29 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Tue Jul 21 00:49:29 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/metadata-controller.js             |  4 ++++
 .../nodejs/views/includes/controls.jade                   | 10 ++++++++--
 2 files changed, 12 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/18f554d8/modules/web-control-center/nodejs/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/metadata-controller.js b/modules/web-control-center/nodejs/controllers/metadata-controller.js
index 5f20fb2..9b100af 100644
--- a/modules/web-control-center/nodejs/controllers/metadata-controller.js
+++ b/modules/web-control-center/nodejs/controllers/metadata-controller.js
@@ -455,6 +455,10 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             $table.tableReset();
         };
 
+        $scope.tableGroupSaveVisible = function(group) {
+            return $common.isNonEmpty(group);
+        };
+
         $scope.tableRemoveGroupItem = function(group, index) {
             console.log("group: " + group.name);
             console.log("index: " + index);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/18f554d8/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 ce476d7..aaed1a1 100644
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ b/modules/web-control-center/nodejs/views/includes/controls.jade
@@ -276,8 +276,14 @@ mixin form-row-custom(lblClasses, fieldClasses)
                     tr.col-sm-12(ng-repeat='group in #{fieldMdl}')
                         td.col-sm-6
                             div
-                                a.labelFormField(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{group.name}}
-                                +btn-remove('tableRemove(backupItem, field, $index)')
+                                div(ng-show='!tableEditing(field, $index)')
+                                    a.labelFormField(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{group.name}}
+                                    +btn-remove('tableRemove(backupItem, field, $index)')
+                                div(ng-show='tableEditing(field, $index)')
+                                    label.labelField {{$index + 1}})
+                                    +btn-save('tableGroupSaveVisible(curName)', 'tableGroupSave(field, curDbName, curDbType, curJavaName, curJavaType, $index)')
+                                    .input-tip
+                                        input.form-control(type='text' ng-model='curName' placeholder='Index name')
                                 table.links-edit.col-sm-12(st-table='group.fields' ng-show='group.fields.length > 0')
                                     tr(ng-repeat='groupItem in group.fields')
                                         td


[25/50] [abbrv] incubator-ignite git commit: Merge branch 'ignite-843' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-1121

Posted by an...@apache.org.
Merge branch 'ignite-843' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-1121


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

Branch: refs/heads/ignite-1121
Commit: 6265e3ad89ac88e89b1ae95c3828bea5e8b2066d
Parents: 573dd09 66e7328
Author: Andrey <an...@gridgain.com>
Authored: Wed Jul 22 09:00:58 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Wed Jul 22 09:00:58 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/caches-controller.js     |  14 +-
 .../nodejs/controllers/clusters-controller.js   |  10 +
 .../nodejs/controllers/common-module.js         |   7 +-
 .../nodejs/controllers/metadata-controller.js   | 181 ++++++++++++++++---
 .../nodejs/controllers/models/clusters.json     |  29 ++-
 .../nodejs/controllers/models/metadata.json     |  47 +++--
 .../nodejs/controllers/profile-controller.js    |   2 +-
 .../nodejs/controllers/summary-controller.js    |  26 +--
 .../nodejs/public/stylesheets/style.less        |  50 ++++-
 .../nodejs/views/configuration/caches.jade      |   6 +-
 .../nodejs/views/configuration/clusters.jade    |   8 +-
 .../nodejs/views/configuration/metadata.jade    |  18 +-
 .../nodejs/views/configuration/summary.jade     |   8 +-
 .../nodejs/views/includes/controls.jade         | 106 +++++++----
 .../nodejs/views/settings/admin.jade            |  11 +-
 .../nodejs/views/settings/profile.jade          |   2 +-
 .../nodejs/views/sql/sql.jade                   |   2 +-
 .../nodejs/views/templates/select.jade          |   2 +-
 18 files changed, 398 insertions(+), 131 deletions(-)
----------------------------------------------------------------------



[21/50] [abbrv] incubator-ignite git commit: # ignite-843 Fixed select ui

Posted by an...@apache.org.
# ignite-843 Fixed select ui


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

Branch: refs/heads/ignite-1121
Commit: 677f5e46ef1fefa0262f7f42b1cb7927168e11d0
Parents: 692cee9
Author: Andrey <an...@gridgain.com>
Authored: Tue Jul 21 16:54:42 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Tue Jul 21 16:54:42 2015 +0700

----------------------------------------------------------------------
 .../web-control-center/nodejs/public/stylesheets/style.less    | 6 ++----
 modules/web-control-center/nodejs/views/templates/select.jade  | 2 +-
 2 files changed, 3 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/677f5e46/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 da6ffae..61b09d5 100644
--- a/modules/web-control-center/nodejs/public/stylesheets/style.less
+++ b/modules/web-control-center/nodejs/public/stylesheets/style.less
@@ -243,7 +243,7 @@
 
   li a:hover {
     color: @ignite-red;
-    background-color: transparent;
+    //background-color: transparent;
   }
 
   .active {
@@ -1063,10 +1063,8 @@ a {
 
 .block-callout {
   background-color: @ignite-block-callout-background;
-  border-left-width: 5px;
-  border-left-style: solid;
+  border-left: 5px solid;
   border-color: @ignite-block-callout-border;
-
   margin-bottom: 20px;
 
   p {

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/677f5e46/modules/web-control-center/nodejs/views/templates/select.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/templates/select.jade b/modules/web-control-center/nodejs/views/templates/select.jade
index 9bebac0..10c1946 100644
--- a/modules/web-control-center/nodejs/views/templates/select.jade
+++ b/modules/web-control-center/nodejs/views/templates/select.jade
@@ -18,7 +18,7 @@ ul.select.dropdown-menu(tabindex='-1', ng-show='$isVisible()', role='select')
     li(role='presentation', ng-repeat='match in $matches')
         hr(ng-if='match.value == undefined' style='margin: 5px 0')
         a(style='cursor: default; padding: 3px 6px;', role='menuitem', tabindex='-1', ng-class='{active: $isActive($index)}' ng-click='$select($index, $event)')
-            i(class='{{$iconCheckmark}}', ng-if='$isMultiple && $isActive($index)' ng-class='{active: $isActive($index)}' style='color: #ec1c24; margin-left: 15px; line-height: 20px; float: right;background-color: transparent;')
+            i(class='{{$iconCheckmark}}', ng-if='$isActive($index)' ng-class='{active: $isActive($index)}' style='color: #ec1c24; margin-left: 15px; line-height: 20px; float: right;background-color: transparent;')
             span(ng-bind='match.label')
     li(ng-if='$showAllNoneButtons || ($isMultiple && $matches.length > 5)')
         hr(style='margin: 5px 0')


[02/50] [abbrv] incubator-ignite git commit: # ignite-843 Remove debug

Posted by an...@apache.org.
# ignite-843 Remove debug


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

Branch: refs/heads/ignite-1121
Commit: 94b581f862bcb7ecb0747de2bc7dc33b5287f482
Parents: 827e559
Author: Andrey <an...@gridgain.com>
Authored: Mon Jul 20 17:55:52 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Mon Jul 20 17:55:52 2015 +0700

----------------------------------------------------------------------
 modules/web-control-center/nodejs/app.js | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/94b581f8/modules/web-control-center/nodejs/app.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/app.js b/modules/web-control-center/nodejs/app.js
index 713426b..8c347db 100644
--- a/modules/web-control-center/nodejs/app.js
+++ b/modules/web-control-center/nodejs/app.js
@@ -53,7 +53,6 @@ app.use(bodyParser.json());
 app.use(bodyParser.urlencoded({extended: false}));
 
 app.use(require('less-middleware')(path.join(__dirname, 'public'), {
-    debug: true,
     render: {
         compress: false
     }


[45/50] [abbrv] incubator-ignite git commit: IGNITE-843 Cleanup after project structure changed.

Posted by an...@apache.org.
IGNITE-843 Cleanup after project structure changed.


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

Branch: refs/heads/ignite-1121
Commit: 766a6c2f49c76008562e1292cc6216492cd38894
Parents: 58e0c64
Author: AKuznetsov <ak...@gridgain.com>
Authored: Wed Jul 22 21:51:34 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Wed Jul 22 21:51:34 2015 +0700

----------------------------------------------------------------------
 .../nodejs/views/sql/sql.jade                   | 57 --------------------
 1 file changed, 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/766a6c2f/modules/web-control-center/nodejs/views/sql/sql.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/sql/sql.jade b/modules/web-control-center/nodejs/views/sql/sql.jade
deleted file mode 100644
index 7c4ddaf..0000000
--- a/modules/web-control-center/nodejs/views/sql/sql.jade
+++ /dev/null
@@ -1,57 +0,0 @@
-
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-         http://www.apache.org/licenses/LICENSE-2.0
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-extends ../templates/layout
-
-append scripts
-    script(src='/cache-viewer-controller.js')
-    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js')
-
-append css
-    link(rel='stylesheet', href='/stylesheets/sql-console.css')
-
-block container
-    .docs-header
-        h1 Connect to Ignite and execute SQL queries
-        hr
-    div(ng-controller='cacheViewerController')
-        h4 Sql console
-
-        table#queryTable(cellpadding=0, cellspacing=0, ng-init='queryType = "sql"')
-            tr
-                td
-                    label(for='queryTypeSelect') Query&nbsp;type:
-                    select#queryTypeSelect(ng-model='queryType')
-                        option(value='sql') Sql query
-                        option(value='id') Get by ID
-                        option(value='scane') Scan cache
-
-                td.queryTd
-                    div(ng-show='queryType == "sql"')
-                        #querySql
-
-                td
-                    | Default&nbsp;cache:
-                    div#defCacheSelect
-                        div(ng-repeat='c in caches', ng-class='{def: defCache == c}', ng-click='defCache = c') {{c}}
-
-        #resultPanel
-            strong Results
-
-            #queryResult
-                div(ng-repeat='r in results')
-                    .resultRow
-                        | {{r.id}} -> {{r.s}}
-                        span.props  {{r.fields}}
-


[05/50] [abbrv] incubator-ignite git commit: IGNITE-843 WIP query groups.

Posted by an...@apache.org.
IGNITE-843 WIP query groups.


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

Branch: refs/heads/ignite-1121
Commit: d51f4127888d1dbdedde4a33fe50d75e6e351427
Parents: 36cfaad
Author: AKuznetsov <ak...@gridgain.com>
Authored: Mon Jul 20 18:11:38 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Mon Jul 20 18:11:38 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/metadata-controller.js    | 15 +++++++++++++++
 .../nodejs/controllers/models/metadata.json      |  2 +-
 modules/web-control-center/nodejs/db.js          |  2 +-
 .../nodejs/views/includes/controls.jade          | 19 +++++++++++++++++--
 4 files changed, 34 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d51f4127/modules/web-control-center/nodejs/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/metadata-controller.js b/modules/web-control-center/nodejs/controllers/metadata-controller.js
index b56b94e..65229da 100644
--- a/modules/web-control-center/nodejs/controllers/metadata-controller.js
+++ b/modules/web-control-center/nodejs/controllers/metadata-controller.js
@@ -303,6 +303,21 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
         // Add new metadata.
         $scope.createItem = function () {
             $scope.backupItem = angular.copy($scope.template);
+
+            $scope.backupItem.groups = [{
+                name: "index1",
+                fields: [
+                    {name: "fld1", className: "Integer", direction: "ASC"},
+                    {name: "fld2", className: "String", direction: "DESC"}]
+            },
+                {
+                    name: "index1",
+                    fields: [
+                        {name: "fld3", className: "Integer", direction: "ASC"},
+                        {name: "fld4", className: "Data", direction: "DESC"}]
+                }
+            ];
+
             $scope.backupItem.space = $scope.spaces[0]._id;
         };
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d51f4127/modules/web-control-center/nodejs/controllers/models/metadata.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/metadata.json b/modules/web-control-center/nodejs/controllers/models/metadata.json
index 3315835..d32d546 100644
--- a/modules/web-control-center/nodejs/controllers/models/metadata.json
+++ b/modules/web-control-center/nodejs/controllers/models/metadata.json
@@ -121,7 +121,7 @@
     },
     {
       "label": "Groups",
-      "type": "groupsMetadata",
+      "type": "queryGroups",
       "model": "groups",
       "hide": "backupItem.kind != 'query'",
       "tip": ["Collection of group indexes."]

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d51f4127/modules/web-control-center/nodejs/db.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/db.js b/modules/web-control-center/nodejs/db.js
index ae34573..e34272c 100644
--- a/modules/web-control-center/nodejs/db.js
+++ b/modules/web-control-center/nodejs/db.js
@@ -76,7 +76,7 @@ var CacheTypeMetadataSchema = new Schema({
     ascendingFields: [{name: String, className: String}],
     descendingFields:  [{name: String, className: String}],
     textFields: [String],
-    groups: [{name: String, fields: [{field: String, className: String, direction: String}]}]
+    groups: [{name: String, fields: [{name: String, className: String, direction: String}]}]
 });
 
 exports.CacheTypeMetadata = mongoose.model('CacheTypeMetadata', CacheTypeMetadataSchema);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d51f4127/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 aedee2c..d803e08 100644
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ b/modules/web-control-center/nodejs/views/includes/controls.jade
@@ -267,5 +267,20 @@ mixin form-row-custom(lblClasses, fieldClasses)
                     +btn-save('tableDbFieldSaveVisible(newDbName, newDbType, newJavaName, newJavaType)', 'tableDbFieldSave(field, newDbName, newDbType, newJavaName, newJavaType, -1)')
                     .input-tip
                         +table-db-field-edit('newDbName', 'newDbType', 'newJavaName', 'newJavaType')
-        div(ng-switch-when='groupsMetadata' ng-hide=fieldHide)&attributes(fieldCommon)
-            label.table-header {{field.label}}:
+        div(ng-switch-when='queryGroups' ng-hide=fieldHide)
+            .col-sm-6
+                label.table-header {{field.label}}:
+                +tipLabel('field.tip')
+                button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
+            table.links-edit.col-sm-12(st-table=fieldMdl ng-show='#{fieldMdl}.length > 0')
+                tbody
+                    tr.col-sm-12(ng-repeat='item in #{fieldMdl}')
+                        td.col-sm-6
+                            div
+                                a(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{item.name}}
+                                +btn-remove('tableRemove(backupItem, field, $index)')
+                                table
+                                    tr(ng-repeat='z in item.fields')
+                                        td
+                                            label {{$index + 1}}) {{z.name}} / {{z.className}} / {{z.direction}}
+


[13/50] [abbrv] incubator-ignite git commit: # ignite-843 Fixed layout for metadata.

Posted by an...@apache.org.
# ignite-843 Fixed layout for metadata.


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

Branch: refs/heads/ignite-1121
Commit: a4ca8b710f4c0e53d7014710b424c8354d2fd581
Parents: b34fb93
Author: Andrey <an...@gridgain.com>
Authored: Tue Jul 21 10:28:09 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Tue Jul 21 10:28:09 2015 +0700

----------------------------------------------------------------------
 .../nodejs/public/stylesheets/style.less        | 42 +++-------------
 .../nodejs/views/includes/controls.jade         | 50 ++++++++------------
 2 files changed, 26 insertions(+), 66 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a4ca8b71/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 ca4d72f..e4369e4 100644
--- a/modules/web-control-center/nodejs/public/stylesheets/style.less
+++ b/modules/web-control-center/nodejs/public/stylesheets/style.less
@@ -860,6 +860,12 @@ label {
   margin-left: 5px;
 }
 
+.fieldSep {
+  float: right;
+  line-height: @input-height;
+  margin: 0 5px;
+}
+
 .fieldButton {
   float: right;
   margin-left: 5px;
@@ -1068,40 +1074,4 @@ a {
   height: 400px;
 }
 
-.grid {
-  display: flex;
-  flex-wrap: nowrap;
-  list-style: none;
-  margin: 0;
-  padding: 0;
-
-  label {
-    line-height: @input-height;
-  }
-}
-
-.grid-cell-1 {
-  flex-basis: 100%;
-}
-
-.grid-cell-2 {
-  flex-basis: 50%;
-}
-
-.grid-cell-3 {
-  flex-basis: 33%;
-}
-
-.grid-cell-4 {
-  flex-basis: 25%;
-}
-
-.grid-cell-fa {
-  flex-basis: 16px;
-}
-
-.grid-fixed-cell {
-  flex-basis: 10px;
-}
-
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a4ca8b71/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 aaed1a1..6c81489 100644
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ b/modules/web-control-center/nodejs/views/includes/controls.jade
@@ -38,13 +38,11 @@ mixin btn-down(show, click)
     i.tipField.fa.fa-arrow-down(ng-show=show ng-click=click)
 
 mixin table-pair-edit(keyModel, valModel, keyPlaceholder, valPlaceholder)
-    .grid
-        .grid-cell-2
-            input.form-control(type='text' ng-model=keyModel placeholder=keyPlaceholder)
-        div
-            label &nbsp;/&nbsp;
-        .grid-cell-2
-            input.form-control(type='text' ng-model=valModel placeholder=valPlaceholder)
+    .col-sm-6(style='float: right')
+        input.form-control(type='text' ng-model=valModel placeholder=valPlaceholder)
+    label.fieldSep /
+    .input-tip
+        input.form-control(type='text' ng-model=keyModel placeholder=keyPlaceholder)
 
 mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
     .col-sm-6
@@ -61,13 +59,11 @@ mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
                     div(ng-show='tableEditing(field, $index)')
                         label.labelField {{$index + 1}})
                         +btn-save('tablePairSaveVisible(curKey, curValue)', 'tablePairSave(tablePairValid, backupItem, field, curKey, curValue, $index)')
-                        .input-tip
-                            +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder)
+                        +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder)
     .settings-row(ng-show='tableNewItemActive(field)')
         .col-sm-6
             +btn-save('tablePairSaveVisible(newKey, newValue)', 'tablePairSave(tablePairValid, backupItem, field, newKey, newValue, -1)')
-            .input-tip
-                +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder)
+            +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder)
 
 mixin details-row
     - var lblDetailClasses = ['col-sm-4', 'details-label']
@@ -137,21 +133,17 @@ mixin details-row
                 +ico-exclamation('{{detail.model}}', 'ipaddress', 'Invalid address, see help for format description.')
 
 mixin table-db-field-edit(dbName, dbType, javaName, javaType)
-    .grid
-        .grid-cell-4
-            input.form-control(type='text' ng-model=dbName placeholder='DB name')
-        div
-            label &nbsp;/&nbsp;
-        .grid-cell-4
-            button.form-control(ng-model=dbType bs-select data-placeholder='JDBC type' bs-options='item.value as item.label for item in {{jdbcTypes}}')
-        div
-            label &nbsp;/&nbsp;
-        .grid-cell-4
-            input.form-control(type='text' ng-model=javaName placeholder='Java name')
-        div
-            label &nbsp;/&nbsp;
-        .grid-cell-4
-            button.form-control(ng-model=javaType bs-select data-placeholder='Java type' bs-options='item.value as item.label for item in {{javaTypes}}')
+    div(style='width: 20%; float: right')
+        button.form-control(ng-model=javaType bs-select data-placeholder='Java type' bs-options='item.value as item.label for item in {{javaTypes}}')
+    label.fieldSep /
+    div(style='width: 22%; float: right')
+        input.form-control(type='text' ng-model=javaName placeholder='Java name')
+    label.fieldSep /
+    div(style='width: 20%; float: right')
+        button.form-control(ng-model=dbType bs-select data-placeholder='JDBC type' bs-options='item.value as item.label for item in {{jdbcTypes}}')
+    label.fieldSep /
+    .input-tip
+        input.form-control(type='text' ng-model=dbName placeholder='DB name')
 
 mixin form-row
     +form-row-custom(['col-sm-2'], ['col-sm-4'])
@@ -259,13 +251,11 @@ mixin form-row-custom(lblClasses, fieldClasses)
                             div(ng-if='tableEditing(field, $index)')
                                 label.labelField {{$index + 1}})
                                 +btn-save('tableDbFieldSaveVisible(curDbName, curDbType, curJavaName, curJavaType)', 'tableDbFieldSave(field, curDbName, curDbType, curJavaName, curJavaType, $index)')
-                                .input-tip
-                                    +table-db-field-edit('curDbName', 'curDbType', 'curJavaName', 'curJavaType')
+                                +table-db-field-edit('curDbName', 'curDbType', 'curJavaName', 'curJavaType')
             .settings-row(ng-show='tableNewItemActive(field)')
                 .col-sm-6
                     +btn-save('tableDbFieldSaveVisible(newDbName, newDbType, newJavaName, newJavaType)', 'tableDbFieldSave(field, newDbName, newDbType, newJavaName, newJavaType, -1)')
-                    .input-tip
-                        +table-db-field-edit('newDbName', 'newDbType', 'newJavaName', 'newJavaType')
+                    +table-db-field-edit('newDbName', 'newDbType', 'newJavaName', 'newJavaType')
         div(ng-switch-when='queryGroups' ng-hide=fieldHide)
             .col-sm-6
                 label.table-header {{field.label}}:


[16/50] [abbrv] incubator-ignite git commit: IGNITE-843 Groups minor.

Posted by an...@apache.org.
IGNITE-843 Groups minor.


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

Branch: refs/heads/ignite-1121
Commit: 27b6f9532fdcef81fec11cd94cac1ea92a57d72f
Parents: 9499ee2
Author: AKuznetsov <ak...@gridgain.com>
Authored: Tue Jul 21 13:01:13 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Tue Jul 21 13:01:13 2015 +0700

----------------------------------------------------------------------
 .../nodejs/public/stylesheets/style.less        |  3 +-
 .../nodejs/views/includes/controls.jade         | 47 ++++++++++----------
 2 files changed, 26 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/27b6f953/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 a16318d..da6ffae 100644
--- a/modules/web-control-center/nodejs/public/stylesheets/style.less
+++ b/modules/web-control-center/nodejs/public/stylesheets/style.less
@@ -740,7 +740,8 @@ button .caret, .btn .caret {
 }
 
 .theme-line table.links-edit:extend(.theme-line .links table all) {
-  margin-bottom: 10px;
+  margin-top: 5px;
+  margin-bottom: 5px;
 
   label {
     line-height: @input-height;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/27b6f953/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 f45b60e..141a198 100644
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ b/modules/web-control-center/nodejs/views/includes/controls.jade
@@ -52,7 +52,7 @@ mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
         label.table-header #{header}:
         +tipLabel('field.tip')
         button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-    table.links-edit.col-sm-12(st-table=tblMdl ng-show='#{tblMdl}.length > 0')
+    table.links-edit.col-sm-12(st-table=tblMdl)
         tbody
             tr.col-sm-12(ng-repeat='item in #{tblMdl}')
                 td.col-sm-6
@@ -63,10 +63,10 @@ mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
                         label.labelField {{$index + 1}})
                         +btn-save('tablePairSaveVisible(curKey, curValue)', 'tablePairSave(tablePairValid, backupItem, field, curKey, curValue, $index)')
                         +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder)
-    .settings-row(ng-show='tableNewItemActive(field)')
-        .col-sm-6
-            +btn-save('tablePairSaveVisible(newKey, newValue)', 'tablePairSave(tablePairValid, backupItem, field, newKey, newValue, -1)')
-            +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder)
+            tr.col-sm-12(ng-show='tableNewItemActive(field)')
+                td.col-sm-6
+                    +btn-save('tablePairSaveVisible(newKey, newValue)', 'tablePairSave(tablePairValid, backupItem, field, newKey, newValue, -1)')
+                    +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder)
 
 mixin details-row
     - var lblDetailClasses = ['col-sm-4', 'details-label']
@@ -226,7 +226,7 @@ mixin form-row-custom(lblClasses, fieldClasses)
                 label.table-header {{field.label}}:
                 +tipLabel('field.tableTip')
                 button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-            table.links-edit.col-sm-12(st-table='#{fieldMdl}' ng-show='#{fieldMdl}.length > 0')
+            table.links-edit.col-sm-12(st-table='#{fieldMdl}')
                 tbody
                     tr.col-sm-12(ng-repeat='item in #{fieldMdl} track by $index')
                         td.col-sm-6
@@ -240,11 +240,11 @@ mixin form-row-custom(lblClasses, fieldClasses)
                                 +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, curValue, $index)')
                                 .input-tip
                                     input.form-control(type='text' ng-model='curValue' placeholder='{{field.placeholder}}')
-            .settings-row(ng-show='tableNewItemActive(field)')
-                .col-sm-6
-                    +btn-save('tableSimpleSaveVisible(newValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)')
-                    .input-tip
-                        input.form-control(type='text' ng-model='newValue' placeholder='{{field.placeholder}}')
+                    tr.col-sm-12(ng-show='tableNewItemActive(field)')
+                        td.col-sm-6
+                            +btn-save('tableSimpleSaveVisible(newValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)')
+                            .input-tip
+                                input.form-control(type='text' ng-model='newValue' placeholder='{{field.placeholder}}')
         div(ng-switch-when='indexedTypes')
             +table-pair('Index key-value type pairs', fieldMdl, 'keyClass', 'valueClass', 'Key class full name', 'Value class full name')
         div(ng-switch-when='queryFields' ng-hide=fieldHide)
@@ -265,10 +265,10 @@ mixin form-row-custom(lblClasses, fieldClasses)
                                 label.labelField {{$index + 1}})
                                 +btn-save('tableDbFieldSaveVisible(curDbName, curDbType, curJavaName, curJavaType)', 'tableDbFieldSave(field, curDbName, curDbType, curJavaName, curJavaType, $index)')
                                 +table-db-field-edit('curDbName', 'curDbType', 'curJavaName', 'curJavaType')
-            .settings-row(ng-show='tableNewItemActive(field)')
-                .col-sm-6
-                    +btn-save('tableDbFieldSaveVisible(newDbName, newDbType, newJavaName, newJavaType)', 'tableDbFieldSave(field, newDbName, newDbType, newJavaName, newJavaType, -1)')
-                    +table-db-field-edit('newDbName', 'newDbType', 'newJavaName', 'newJavaType')
+                    tr(ng-show='tableNewItemActive(field)')
+                        td.col-sm-6
+                            +btn-save('tableDbFieldSaveVisible(newDbName, newDbType, newJavaName, newJavaType)', 'tableDbFieldSave(field, newDbName, newDbType, newJavaName, newJavaType, -1)')
+                            +table-db-field-edit('newDbName', 'newDbType', 'newJavaName', 'newJavaType')
         div(ng-switch-when='queryGroups' ng-hide=fieldHide)
             .col-sm-6
                 label.table-header {{field.label}}:
@@ -299,14 +299,15 @@ mixin form-row-custom(lblClasses, fieldClasses)
                                                     label.labelField {{$index + 1}})
                                                     +btn-save('tableGroupItemSaveVisible(curFieldName, curClassName)', 'tableGroupItemSave(curFieldName, curClassName, curDirection, groupIndex, $index)')
                                                     +table-group-item-edit('curFieldName', 'curClassName', 'curDirection')
-                                    .settings-row(style='padding-left: 18px' ng-show='tableGroupNewItemActive(groupIndex)')
-                                        +btn-save('tableGroupItemSaveVisible(newFieldName, newClassName)', 'tableGroupItemSave(newFieldName, newClassName, newDirection, groupIndex, -1)')
-                                        +table-group-item-edit('newFieldName', 'newClassName', 'newDirection')
-            .settings-row(ng-show='tableNewItemActive(field)')
-                .col-sm-6
-                    +btn-save('tableGroupSaveVisible(newGroupName)', 'tableGroupSave(newGroupName, -1)')
-                    .input-tip
-                        input.form-control(type='text' ng-model='newGroupName' placeholder='Group name')
+                                        tr.col-sm-12(style='padding-left: 18px' ng-show='tableGroupNewItemActive(groupIndex)')
+                                            td
+                                                +btn-save('tableGroupItemSaveVisible(newFieldName, newClassName)', 'tableGroupItemSave(newFieldName, newClassName, newDirection, groupIndex, -1)')
+                                                +table-group-item-edit('newFieldName', 'newClassName', 'newDirection')
+                    tr.col-sm-12(ng-show='tableNewItemActive(field)')
+                        td.col-sm-6
+                            +btn-save('tableGroupSaveVisible(newGroupName)', 'tableGroupSave(newGroupName, -1)')
+                            .input-tip
+                                input.form-control(type='text' ng-model='newGroupName' placeholder='Group name')
 
 
 


[03/50] [abbrv] incubator-ignite git commit: Merge remote-tracking branch 'origin/ignite-843' into ignite-843

Posted by an...@apache.org.
Merge remote-tracking branch 'origin/ignite-843' into ignite-843


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

Branch: refs/heads/ignite-1121
Commit: 85062e304840bf8865a253c8fed3c91f40de961b
Parents: 94b581f 36cfaad
Author: Andrey <an...@gridgain.com>
Authored: Mon Jul 20 17:56:12 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Mon Jul 20 17:56:12 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/common-module.js         | 11 ++-
 .../nodejs/controllers/metadata-controller.js   | 88 ++++++++++++++++++++
 .../nodejs/controllers/models/metadata.json     | 41 +++++----
 .../nodejs/controllers/summary-controller.js    |  2 +-
 modules/web-control-center/nodejs/db.js         |  4 +-
 .../nodejs/public/stylesheets/style.less        | 20 +++++
 .../nodejs/views/includes/controls.jade         | 45 +++++++++-
 7 files changed, 185 insertions(+), 26 deletions(-)
----------------------------------------------------------------------



[38/50] [abbrv] incubator-ignite git commit: # ignite-843 moved

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/common-module.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/common-module.js b/modules/web-control-center/src/main/js/controllers/common-module.js
new file mode 100644
index 0000000..75af155
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/common-module.js
@@ -0,0 +1,422 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var controlCenterModule = angular.module('ignite-web-control-center', ['smart-table', 'mgcrea.ngStrap', 'ui.ace', 'ngSanitize']);
+
+// Modal popup configuration.
+controlCenterModule.config(function ($modalProvider) {
+    angular.extend($modalProvider.defaults, {
+        html: true
+    });
+});
+
+// Tooltips configuration.
+controlCenterModule.config(function ($tooltipProvider) {
+    angular.extend($tooltipProvider.defaults, {
+        container: 'body',
+        placement: 'right',
+        html: 'true',
+        trigger: 'click hover'
+    });
+});
+
+// Comboboxes configuration.
+controlCenterModule.config(function ($selectProvider) {
+    angular.extend($selectProvider.defaults, {
+        maxLength: '1',
+        allText: 'Select All',
+        noneText: 'Clear All',
+        templateUrl: '/select',
+        iconCheckmark: 'fa fa-check',
+        caretHtml: '<span class="caret"></span>'
+    });
+});
+
+// Alerts configuration.
+controlCenterModule.config(function ($alertProvider) {
+    angular.extend($alertProvider.defaults, {
+        container: 'body',
+        placement: 'top-right',
+        duration: '5',
+        type: 'danger'
+    });
+});
+
+// Common functions to be used in controllers.
+controlCenterModule.service('$common', ['$alert', function ($alert) {
+    var msgModal = undefined;
+
+    function errorMessage(errMsg) {
+        return errMsg ? errMsg : 'Internal server error.';
+    }
+
+    function isDefined(v) {
+        return !(v === undefined || v === null);
+    }
+
+    return {
+        getModel: function (obj, field) {
+            var path = field.path;
+
+            if (!isDefined(path))
+                return obj;
+
+            path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
+            path = path.replace(/^\./, '');           // strip a leading dot
+
+            var segs = path.split('.');
+            var root = obj;
+
+            while (segs.length > 0) {
+                var pathStep = segs.shift();
+
+                if (typeof root[pathStep] === 'undefined')
+                    root[pathStep] = {};
+
+                root = root[pathStep];
+            }
+
+            return root;
+        },
+        joinTip: function (arr) {
+            if (!arr) {
+                return arr;
+            }
+
+            var lines = arr.map(function (line) {
+                var rtrimmed = line.replace(/\s+$/g, '');
+
+                if (rtrimmed.indexOf('>', this.length - 1) == -1) {
+                    rtrimmed = rtrimmed + '<br/>';
+                }
+
+                return rtrimmed;
+            });
+
+            return lines.join("");
+        },
+        isDefined: isDefined,
+        isNonEmpty: function (s) {
+            return isDefined(s) && s.trim().length > 0;
+        },
+        errorMessage: errorMessage,
+        showError: function (msg) {
+            if (msgModal)
+                msgModal.hide();
+
+            msgModal = $alert({title: errorMessage(msg)});
+        },
+        showInfo: function (msg) {
+            if (msgModal)
+                msgModal.hide();
+
+            msgModal = $alert({
+                type: 'success',
+                title: msg,
+                duration: 2
+            });
+        }
+    }
+}]);
+
+// Confirm popup service.
+controlCenterModule.service('$confirm', function ($modal, $rootScope, $q) {
+    var scope = $rootScope.$new();
+
+    var deferred;
+
+    scope.ok = function () {
+        deferred.resolve();
+
+        confirmModal.hide();
+    };
+
+    var confirmModal = $modal({templateUrl: '/confirm', scope: scope, placement: 'center', show: false});
+
+    var parentShow = confirmModal.show;
+
+    confirmModal.show = function (content) {
+        scope.content = content || 'Confirm deletion?';
+
+        deferred = $q.defer();
+
+        parentShow();
+
+        return deferred.promise;
+    };
+
+    return confirmModal;
+});
+
+// "Save as" popup service.
+controlCenterModule.service('$copy', function ($modal, $rootScope, $q) {
+    var scope = $rootScope.$new();
+
+    var deferred;
+
+    scope.ok = function (newName) {
+        deferred.resolve(newName);
+
+        copyModal.hide();
+    };
+
+    var copyModal = $modal({templateUrl: '/copy', scope: scope, placement: 'center', show: false});
+
+    var parentShow = copyModal.show;
+
+    copyModal.show = function (oldName) {
+        scope.newName = oldName + '(1)';
+
+        deferred = $q.defer();
+
+        parentShow();
+
+        return deferred.promise;
+    };
+
+    return copyModal;
+});
+
+// Tables support service.
+controlCenterModule.service('$table', ['$common', function ($common) {
+    function _swapSimpleItems(a, ix1, ix2) {
+        var tmp = a[ix1];
+
+        a[ix1] = a[ix2];
+        a[ix2] = tmp;
+    }
+
+    function _model(item, field) {
+        return $common.getModel(item, field);
+    }
+
+    var table = {name: 'none', editIndex: -1};
+
+    function _tableReset() {
+        table.name = 'none';
+        table.editIndex = -1;
+    }
+
+    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)) {
+                _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][index] = newValue;
+            }
+        },
+        tableSimpleSaveVisible: function (newValue) {
+            return $common.isNonEmpty(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)) {
+                _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;
+                }
+            }
+        },
+        tablePairSaveVisible: function (newKey, newValue) {
+            return $common.isNonEmpty(newKey) && $common.isNonEmpty(newValue);
+        }
+    }
+}]);
+
+
+// Filter to decode name using map(value, label).
+controlCenterModule.filter('displayValue', function () {
+    return function (v, m, dflt) {
+        var i = _.findIndex(m, function (item) {
+            return item.value == v;
+        });
+
+        if (i >= 0) {
+            return m[i].label;
+        }
+
+        if (dflt) {
+            return dflt;
+        }
+
+        return 'Unknown value';
+    }
+});
+
+/**
+ * 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])';
+    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])';
+
+    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;
+            }
+        }
+    }
+});
+
+// Directive to enable validation to match specified value.
+controlCenterModule.directive('match', function ($parse) {
+    return {
+        require: 'ngModel',
+        link: function (scope, elem, attrs, ctrl) {
+            scope.$watch(function () {
+                return $parse(attrs.match)(scope) === ctrl.$modelValue;
+            }, function (currentValue) {
+                ctrl.$setValidity('mismatch', currentValue);
+            });
+        }
+    };
+});
+
+// Navigation bar controller.
+controlCenterModule.controller('activeLink', [
+    '$scope', function ($scope) {
+        $scope.isActive = function (path) {
+            return window.location.pathname.substr(0, path.length) == path;
+        };
+    }]);
+
+// Login popup controller.
+controlCenterModule.controller('auth', [
+    '$scope', '$modal', '$alert', '$http', '$window', '$common',
+    function ($scope, $modal, $alert, $http, $window, $common) {
+        $scope.errorMessage = $common.errorMessage;
+
+        $scope.action = 'login';
+
+        $scope.valid = false;
+
+        $scope.userDropdown = [{"text": "Profile", "href": "/profile"}];
+
+        if (!$scope.becomeUsed) {
+            if ($scope.user && $scope.user.admin)
+                $scope.userDropdown.push({"text": "Admin Panel", "href": "/admin"});
+
+            $scope.userDropdown.push({"text": "Log Out", "href": "/logout"});
+        }
+
+        // Pre-fetch an external template populated with a custom scope
+        var authModal = $modal({scope: $scope, templateUrl: '/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.auth = function (action, user_info) {
+            $http.post('/' + action, user_info)
+                .success(function () {
+                    authModal.hide();
+
+                    $window.location = '/configuration/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/8a335724/modules/web-control-center/src/main/js/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/metadata-controller.js b/modules/web-control-center/src/main/js/controllers/metadata-controller.js
new file mode 100644
index 0000000..b62cde5
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/metadata-controller.js
@@ -0,0 +1,678 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+controlCenterModule.controller('metadataController', ['$scope', '$http', '$common', '$confirm', '$copy', '$table', function ($scope, $http, $common, $confirm, $copy, $table) {
+        $scope.joinTip = $common.joinTip;
+        $scope.getModel = $common.getModel;
+
+        $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.templates = [
+            {value: {kind: 'query'}, label: 'query'},
+            {value: {kind: 'store'}, label: 'store'},
+            {value: {kind: 'both'}, label: 'both'}
+        ];
+
+        $scope.template = $scope.templates[0].value;
+
+        $scope.kinds = [
+            {value: 'query', label: 'query'},
+            {value: 'store', label: 'store'},
+            {value: 'both', label: 'both'}
+        ];
+
+        $scope.databases = [
+            {value: 'oracle', label: 'Oracle database'},
+            {value: 'db2', label: 'IBM DB2'},
+            {value: 'mssql', label: 'MS SQL Server'},
+            {value: 'postgre', label: 'PostgreSQL'},
+            {value: 'mysql', label: 'MySQL'},
+            {value: 'h2', label: 'H2 database'}
+        ];
+
+        $scope.jdbcTypes = [
+            {value: 'BIT', label: 'BIT'},
+            {value: 'BOOLEAN', label: 'BOOLEAN'},
+            {value: 'TINYINT', label: 'TINYINT'},
+            {value: 'SMALLINT', label: 'SMALLINT'},
+            {value: 'INTEGER', label: 'INTEGER'},
+            {value: 'BIGINT', label: 'BIGINT'},
+            {value: 'REAL', label: 'REAL'},
+            {value: 'FLOAT', label: 'FLOAT'},
+            {value: 'DOUBLE', label: 'DOUBLE'},
+            {value: 'NUMERIC', label: 'NUMERIC'},
+            {value: 'DECIMAL', label: 'DECIMAL'},
+            {value: 'CHAR', label: 'CHAR'},
+            {value: 'VARCHAR', label: 'VARCHAR'},
+            {value: 'LONGVARCHAR', label: 'LONGVARCHAR'},
+            {value: 'NCHAR', label: 'NCHAR'},
+            {value: 'NVARCHAR', label: 'NVARCHAR'},
+            {value: 'LONGNVARCHAR', label: 'LONGNVARCHAR'},
+            {value: 'DATE', label: 'DATE'},
+            {value: 'TIME', label: 'TIME'},
+            {value: 'TIMESTAMP', label: 'TIMESTAMP'}
+        ];
+
+        $scope.javaTypes = [
+            {value: 'boolean', label: 'boolean'},
+            {value: 'Boolean', label: 'Boolean'},
+            {value: 'byte', label: 'byte'},
+            {value: 'Byte', label: 'Byte'},
+            {value: 'short', label: 'short'},
+            {value: 'Short', label: 'Short'},
+            {value: 'int', label: 'int'},
+            {value: 'Integer', label: 'Integer'},
+            {value: 'long', label: 'long'},
+            {value: 'Long', label: 'Long'},
+            {value: 'float', label: 'float'},
+            {value: 'Float', label: 'Float'},
+            {value: 'double', label: 'double'},
+            {value: 'Double', label: 'Double'},
+            {value: 'BigDecimal', label: 'BigDecimal'},
+            {value: 'String', label: 'String'},
+            {value: 'Date', label: 'Date'},
+            {value: 'Time', label: 'Time'},
+            {value: 'Timestamp', label: 'Timestamp'}
+        ];
+
+        $scope.sortDirections = [
+            {value: 'ASC', label: 'ASC'},
+            {value: 'DESC', label: 'DESC'}
+        ];
+
+        $scope.data = {
+            curTableIdx: 0,
+            curFieldIdx: 0,
+            curKeyClass: '',
+            curValueClass: '',
+            curJavaName: '',
+            curJavaType: '',
+            tables: [
+                {schemaName: 'Schema1', use: true},
+                {
+                    schemaName: 'Schema1',
+                    use: true,
+                    tableName: 'Table1',
+                    keyClass: 'KeyClass1',
+                    valueClass: 'ValueClass1',
+                    fields: [
+                        {
+                            use: true,
+                            key: true,
+                            ak: true,
+                            dbName: 'name1',
+                            dbType: 'dbType1',
+                            javaName: 'javaName1',
+                            javaType: 'javaType1'
+                        },
+                        {
+                            use: true,
+                            key: false,
+                            ak: false,
+                            dbName: 'name2',
+                            dbType: 'dbType2',
+                            javaName: 'javaName2',
+                            javaType: 'javaType2'
+                        },
+                        {
+                            use: false,
+                            key: false,
+                            ak: false,
+                            dbName: 'name3',
+                            dbType: 'dbType3',
+                            javaName: 'javaName3',
+                            javaType: 'javaType3'
+                        }
+                    ]
+                },
+                {schemaName: 'Schema2 with very long name', use: false},
+                {
+                    schemaName: 'Schema2',
+                    use: false,
+                    tableName: 'Table2',
+                    keyClass: 'KeyClass2',
+                    valueClass: 'ValueClass2',
+                    fields: [
+                        {
+                            use: true,
+                            key: true,
+                            ak: true,
+                            dbName: 'name4',
+                            dbType: 'dbType4',
+                            javaName: 'javaName4',
+                            javaType: 'javaType4'
+                        },
+                        {
+                            use: true,
+                            key: false,
+                            ak: false,
+                            dbName: 'name5',
+                            dbType: 'dbType5',
+                            javaName: 'javaName5',
+                            javaType: 'javaType5'
+                        },
+                        {
+                            use: false,
+                            key: false,
+                            ak: false,
+                            dbName: 'name6',
+                            dbType: 'dbType6',
+                            javaName: 'javaName6',
+                            javaType: 'javaType6'
+                        }
+                    ]
+                },
+                {
+                    schemaName: 'Schema2',
+                    use: false,
+                    tableName: 'Table3',
+                    keyClass: 'KeyClass3',
+                    valueClass: 'ValueClass3',
+                    fields: [
+                        {
+                            use: true,
+                            key: true,
+                            ak: true,
+                            dbName: 'name7',
+                            dbType: 'dbType7',
+                            javaName: 'javaName7',
+                            javaType: 'javaType7'
+                        },
+                        {
+                            use: true,
+                            key: false,
+                            ak: false,
+                            dbName: 'name8',
+                            dbType: 'dbType8',
+                            javaName: 'javaName8',
+                            javaType: 'javaType8'
+                        },
+                        {
+                            use: false,
+                            key: false,
+                            ak: false,
+                            dbName: 'name9',
+                            dbType: 'dbType9',
+                            javaName: 'javaName9',
+                            javaType: 'javaType9'
+                        },
+                        {
+                            use: false,
+                            key: false,
+                            ak: false,
+                            dbName: 'name10',
+                            dbType: 'dbType10',
+                            javaName: 'javaName10',
+                            javaType: 'javaType10'
+                        },
+                        {
+                            use: false,
+                            key: false,
+                            ak: false,
+                            dbName: 'name11',
+                            dbType: 'dbType11',
+                            javaName: 'javaName11',
+                            javaType: 'javaType11'
+                        },
+                        {
+                            use: false,
+                            key: false,
+                            ak: false,
+                            dbName: 'name12',
+                            dbType: 'dbType12',
+                            javaName: 'javaName12',
+                            javaType: 'javaType12'
+                        }
+                    ]
+                }]
+        };
+
+        $scope.metadatas = [];
+
+        $http.get('/models/metadata.json')
+            .success(function (data) {
+                $scope.screenTip = data.screenTip;
+                $scope.templateTip = data.templateTip;
+                $scope.metadataManual = data.metadataManual;
+                $scope.metadataDb = data.metadataDb;
+            })
+            .error(function (errMsg) {
+                $common.showError(errMsg);
+            });
+
+        // When landing on the page, get metadatas and show them.
+        $http.post('metadata/list')
+            .success(function (data) {
+                $scope.spaces = data.spaces;
+                $scope.metadatas = data.metadatas;
+
+                var restoredItem = angular.fromJson(sessionStorage.metadataBackupItem);
+
+                if (restoredItem && restoredItem._id) {
+                    var idx = _.findIndex($scope.metadatas, function (metadata) {
+                        return metadata._id == restoredItem._id;
+                    });
+
+                    if (idx >= 0) {
+                        $scope.selectedItem = $scope.metadatas[idx];
+
+                        $scope.backupItem = restoredItem;
+                    }
+                    else
+                        sessionStorage.removeItem('metadataBackupItem');
+                }
+                else
+                    $scope.backupItem = restoredItem;
+
+                $scope.$watch('backupItem', function (val) {
+                    if (val)
+                        sessionStorage.metadataBackupItem = angular.toJson(val);
+                }, true);
+            })
+            .error(function (errMsg) {
+                $common.showError(errMsg);
+            });
+
+        $scope.selectItem = function (item) {
+            $table.tableReset();
+
+            $scope.selectedItem = item;
+            $scope.backupItem = angular.copy(item);
+        };
+
+        // Add new metadata.
+        $scope.createItem = function () {
+            $table.tableReset();
+
+            $scope.backupItem = angular.copy($scope.template);
+            $scope.backupItem.space = $scope.spaces[0]._id;
+        };
+
+        // Check cache type metadata logical consistency.
+        function validate(item) {
+            return true;
+        }
+
+        // Save cache type metadata into database.
+        function save(item) {
+            $http.post('metadata/save', item)
+                .success(function (_id) {
+                    $common.showInfo('Metadata "' + item.name + '" saved.');
+
+                    var idx = _.findIndex($scope.metadatas, function (metadata) {
+                        return metadata._id == _id;
+                    });
+
+                    if (idx >= 0)
+                        angular.extend($scope.metadatas[idx], item);
+                    else {
+                        item._id = _id;
+
+                        $scope.metadatas.push(item);
+                    }
+
+                    $scope.selectItem(item);
+
+                    $common.showInfo('Cache type metadata"' + item.name + '" saved.');
+                })
+                .error(function (errMsg) {
+                    $common.showError(errMsg);
+                });
+        }
+
+        // Save cache type metadata.
+        $scope.saveItem = function () {
+            $table.tableReset();
+
+            var item = $scope.backupItem;
+
+            if (validate(item))
+                save(item);
+        };
+
+        // Save cache type metadata 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);
+
+                    item._id = undefined;
+                    item.name = newName;
+
+                    save(item);
+                });
+        };
+
+        $scope.removeItem = function () {
+            $table.tableReset();
+
+            var selectedItem = $scope.selectedItem;
+
+            $confirm.show('Are you sure you want to remove cache type metadata: "' + selectedItem.name + '"?').then(
+                function () {
+                    var _id = selectedItem._id;
+
+                    $http.post('metadata/remove', {_id: _id})
+                        .success(function () {
+                            $common.showInfo('Cache type metadata has been removed: ' + selectedItem.name);
+
+                            var metadatas = $scope.metadatas;
+
+                            var idx = _.findIndex(metadatas, function (metadata) {
+                                return metadata._id == _id;
+                            });
+
+                            if (idx >= 0) {
+                                metadatas.splice(idx, 1);
+
+                                if (metadatas.length > 0)
+                                    $scope.selectItem(metadatas[0]);
+                                else {
+                                    $scope.selectedItem = undefined;
+                                    $scope.backupItem = undefined;
+                                }
+                            }
+                        })
+                        .error(function (errMsg) {
+                            $common.showError(errMsg);
+                        });
+                });
+        };
+
+        $scope.tableSimpleValid = function (item, field, name, index) {
+            var model = item[field.model];
+
+            if ($common.isDefined(model)) {
+                var idx = _.indexOf(model, name);
+
+                // Found itself.
+                if (index >= 0 && index == idx)
+                    return true;
+
+                // Found duplicate.
+                if (idx >= 0) {
+                    $common.showError('Field with such name already exists!');
+
+                    return false;
+                }
+            }
+
+            return true;
+        };
+
+        $scope.tablePairValid = function (item, field, name, clsName, index) {
+            var model = item[field.model];
+
+            if ($common.isDefined(model)) {
+                var idx = _.findIndex(model, function (pair) {
+                    return pair.name == name
+                });
+
+                // Found itself.
+                if (index >= 0 && index == idx)
+                    return true;
+
+                // Found duplicate.
+                if (idx >= 0) {
+                    $common.showError('Field with such name already exists!');
+
+                    return false;
+                }
+            }
+
+            return true;
+        };
+
+        $scope.tableDbFieldSaveVisible = function (dbName, dbType, javaName, javaType) {
+            return $common.isNonEmpty(dbName) && $common.isDefined(dbType) &&
+                $common.isNonEmpty(javaName) && $common.isDefined(javaType);
+        };
+
+        $scope.tableDbFieldSave = function (field, newDbName, newDbType, newJavaName, newJavaType, index) {
+            var item = $scope.backupItem;
+
+            var model = item[field.model];
+
+            var newItem = {dbName: newDbName, dbType: newDbType, javaName: newJavaName, javaType: newJavaType};
+
+            if ($common.isDefined(model)) {
+                var idx = _.findIndex(model, function (dbMeta) {
+                    return dbMeta.dbName == newDbName
+                });
+
+                // Found duplicate.
+                if (idx >= 0 && index != idx) {
+                    $common.showError('DB field with such name already exists!');
+
+                    return;
+                }
+
+                if (index < 0) {
+                    if (model)
+                        model.push(newItem);
+                    else
+                        item[field.model] = [newItem];
+                }
+                else {
+                    var dbField = model[index];
+
+                    dbField.dbName = newDbName;
+                    dbField.dbType = newDbType;
+                    dbField.javaName = newJavaName;
+                    dbField.javaType = newJavaType;
+                }
+            }
+            else
+                item[field.model] = [newItem];
+
+            $table.tableReset();
+        };
+
+        $scope.tableGroupSaveVisible = function (group) {
+            return $common.isNonEmpty(group);
+        };
+
+        function tableGroupValid(groupName, index) {
+            var groups = $scope.backupItem.groups;
+
+            if ($common.isDefined(groups)) {
+                var idx = _.findIndex(groups, function (group) {
+                    return group.name == groupName;
+                });
+
+                // Found itself.
+                if (index >= 0 && index == idx)
+                    return true;
+
+                // Found duplicate.
+                if (idx >= 0) {
+                    $common.showError('Group with such name already exists!');
+
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        $scope.tableGroupSave = function (groupName, index) {
+            if (tableGroupValid(groupName, index)) {
+                $table.tableReset();
+
+                var item = $scope.backupItem;
+
+                if (index < 0) {
+                    var newGroup = {name: groupName};
+
+                    if (item.groups)
+                        item.groups.push(newGroup);
+                    else
+                        item.groups = [newGroup];
+                }
+                else
+                    item.groups[index].name = groupName;
+            }
+        };
+
+        $scope.tableGroupNewItem = function (groupIndex) {
+            var groupName = $scope.backupItem.groups[groupIndex].name;
+
+            return $table.tableNewItem({model: groupName});
+        };
+
+        $scope.tableGroupNewItemActive = function (groupIndex) {
+            var groupName = $scope.backupItem.groups[groupIndex].name;
+
+            return $table.tableNewItemActive({model: groupName});
+        };
+
+        $scope.tableGroupItemEditing = function (groupIndex, index) {
+            var groups = $scope.backupItem.groups;
+
+            if (groups)
+                return $table.tableEditing({model: groups[groupIndex].name}, index);
+
+            return false;
+        };
+
+        $scope.tableGroupItemStartEdit = function (groupIndex, index) {
+            var groups = $scope.backupItem.groups;
+
+            $table.tableState(groups[groupIndex].name, index);
+
+            return groups[groupIndex].fields[index];
+        };
+
+        $scope.tableGroupItemSaveVisible = function (fieldName, className) {
+            return $common.isNonEmpty(fieldName) && $common.isNonEmpty(className);
+        };
+
+        function tableGroupItemValid(fieldName, groupIndex, index) {
+            var groupItems = $scope.backupItem.groups[groupIndex].fields;
+
+            if ($common.isDefined(groupItems)) {
+                var idx = _.findIndex(groupItems, function (groupItem) {
+                    return groupItem.name == fieldName;
+                });
+
+                // Found itself.
+                if (index >= 0 && index == idx)
+                    return true;
+
+                // Found duplicate.
+                if (idx >= 0) {
+                    $common.showError('Field with such name already exists in group!');
+
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        $scope.tableGroupItemSave = function (fieldName, className, direction, groupIndex, index) {
+            if (tableGroupItemValid(fieldName, groupIndex, index)) {
+                $table.tableReset();
+
+                var group = $scope.backupItem.groups[groupIndex];
+
+                if (index < 0) {
+                    var newGroupItem = {name: fieldName, className: className, direction: direction};
+
+                    if (group.fields)
+                        group.fields.push(newGroupItem);
+                    else
+                        group.fields = [newGroupItem];
+                }
+                else {
+                    var groupItem = group.fields[index];
+
+                    groupItem.name = fieldName;
+                    groupItem.className = className;
+                    groupItem.direction = direction;
+                }
+            }
+        };
+
+        $scope.tableRemoveGroupItem = function (group, index) {
+            $table.tableReset();
+
+            group.fields.splice(index, 1);
+        };
+
+        $scope.selectSchema = function (idx) {
+            var data = $scope.data;
+            var tables = data.tables;
+            var schemaName = tables[idx].schemaName;
+            var use = tables[idx].use;
+
+            for (var i = idx + 1; i < tables.length; i++) {
+                var item = tables[i];
+
+                if (item.schemaName == schemaName && item.tableName)
+                    item.use = use;
+                else
+                    break;
+            }
+
+            data.curTableIdx = -1;
+            data.curFieldIdx = -1;
+        };
+
+        $scope.selectTable = function (idx) {
+            var data = $scope.data;
+
+            data.curTableIdx = idx;
+            data.curFieldIdx = -1;
+
+            if (idx >= 0) {
+                var tbl = data.tables[idx];
+
+                data.curKeyClass = tbl.keyClass;
+                data.curValueClass = tbl.valueClass;
+            }
+        };
+
+        $scope.selectField = function (idx) {
+            var data = $scope.data;
+
+            data.curFieldIdx = idx;
+
+            if (idx >= 0) {
+                var fld = data.tables[data.curTableIdx].fields[idx];
+
+                data.curJavaName = fld.javaName;
+                data.curJavaType = fld.javaType;
+            }
+        };
+    }]
+);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/models/caches.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/models/caches.json b/modules/web-control-center/src/main/js/controllers/models/caches.json
new file mode 100644
index 0000000..0ffc9d4
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/models/caches.json
@@ -0,0 +1,918 @@
+{
+  "screenTip": {
+    "workflowTitle": "Use Caches view to:",
+    "workflowContent": [
+      "<ul>",
+      "  <li>Configure caches.</li>",
+      "  <li>Associate metadata with cache queries and/or cache store.</li>",
+      "</ul>"
+    ],
+    "whatsNextTitle": "What's next:",
+    "whatsNextContent": [
+      "<ul>",
+      "  <li>Configure clusters.</li>",
+      "  <li>Configure cache type metadata.</li>",
+      "  <li>Generate XML and java code on Summary view.</li>",
+      "</ul>"
+    ]
+  },
+  "general": [
+    {
+      "label": "Name",
+      "type": "text",
+      "model": "name",
+      "required": true,
+      "placeholder": "Input name"
+    },
+    {
+      "label": "Mode",
+      "type": "dropdown",
+      "model": "mode",
+      "placeholder": "PARTITIONED",
+      "items": "modes",
+      "tip": [
+        "Cache modes:",
+        "<ul>",
+        "  <li>Partitioned - in this mode the overall key set will be divided into partitions and all partitions will be split equally between participating nodes.</li>",
+        "  <li>Replicated - in this mode all the keys are distributed to all participating nodes.</li>",
+        "  <li>Local - in this mode caches residing on different grid nodes will not know about each other.</li>",
+        "</ul>"
+      ]
+    },
+    {
+      "label": "Atomicity",
+      "type": "dropdown",
+      "model": "atomicityMode",
+      "placeholder": "ATOMIC",
+      "items": "atomicities",
+      "tip": [
+        "Atomicity:",
+        "<ul>",
+        "  <li>Transactional - in this mode specified fully ACID-compliant transactional cache behavior.</li>",
+        "  <li>Atomic - in this mode distributed transactions and distributed locking are not supported.</li>",
+        "</ul>"
+      ]
+    },
+    {
+      "label": "Backups",
+      "type": "number",
+      "model": "backups",
+      "hide": "backupItem.mode == 'LOCAL'",
+      "placeholder": 0,
+      "tip": [
+        "Number of nodes used to back up single partition for partitioned cache."
+      ]
+    },
+    {
+      "label": "Read from backup",
+      "type": "check",
+      "model": "readFromBackup",
+      "placeholder": true,
+      "hide": "!backupItem.backups || backupItem.mode == 'LOCAL'",
+      "tip": [
+        "Flag indicating whether data can be read from backup.",
+        "If not set then always get data from primary node (never from backup)."
+      ]
+    },
+    {
+      "label": "Copy on read",
+      "type": "check",
+      "model": "copyOnRead",
+      "placeholder": true,
+      "tip": [
+        "Flag indicating whether copy of of the value stored in cache should be created for cache operation implying return value.",
+        "Also if this flag is set copies are created for values passed to CacheInterceptor and to CacheEntryProcessor."
+      ]
+    },
+    {
+      "label": "Invalidate near cache",
+      "type": "check",
+      "model": "invalidate",
+      "tip": [
+        "Invalidation flag for near cache entries in transaction.",
+        "If set then values will be invalidated (nullified) upon commit in near cache."
+      ]
+    }
+  ],
+  "advanced": [
+    {
+      "label": "Concurrency control",
+      "tip": [
+        "Cache concurrent usage settings."
+      ],
+      "fields": [
+        {
+          "label": "Max async operations",
+          "type": "number",
+          "model": "maxConcurrentAsyncOperations",
+          "placeholder": 500,
+          "tip": [
+            "Maximum number of allowed concurrent asynchronous operations.",
+            "If 0 then number of concurrent asynchronous operations is unlimited."
+          ]
+        },
+        {
+          "label": "Default lock timeout",
+          "type": "number",
+          "model": "defaultLockTimeout",
+          "placeholder": 0,
+          "tip": [
+            "Default lock acquisition timeout.",
+            "If 0 then lock acquisition will never timeout."
+          ]
+        },
+        {
+          "label": "Entry versioning",
+          "type": "dropdown",
+          "model": "atomicWriteOrderMode",
+          "placeholder": "Choose versioning",
+          "items": "atomicWriteOrderModes",
+          "hide": "backupItem.atomicityMode == 'TRANSACTIONAL'",
+          "tip": [
+            "Write ordering mode determines which node assigns the write version, sender or the primary node.",
+            "<ul>",
+            "  <li>CLOCK - in this mode write versions are assigned on a sender node which generally leads to better performance.</li>",
+            "  <li>PRIMARY - in this mode version is assigned only on primary node. This means that sender will only send write request to primary node, which in turn will assign write version and forward it to backups.</li>",
+            "</ul>"
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Memory",
+      "tip": [
+        "Cache memory settings."
+      ],
+      "fields": [
+        {
+          "label": "Mode",
+          "type": "dropdown",
+          "model": "memoryMode",
+          "placeholder": "ONHEAP_TIERED",
+          "items": "memoryModes",
+          "tip": [
+            "Memory modes:",
+            "<ul>",
+            "  <li>ONHEAP_TIERED - entries are cached on heap memory first.",
+            "    <ul>",
+            "      <li>If offheap memory is enabled and eviction policy evicts an entry from heap memory, entry will be moved to offheap memory. If offheap memory is disabled, then entry is simply discarded.</li>",
+            "      <li>If swap space is enabled and offheap memory fills up, then entry will be evicted into swap space. If swap space is disabled, then entry will be discarded. If swap is enabled and offheap memory is disabled, then entry will be evicted directly from heap memory into swap.</li>",
+            "    </ul>",
+            "  </li>",
+            "  <li>OFFHEAP_TIERED - works the same as ONHEAP_TIERED, except that entries never end up in heap memory and get stored in offheap memory right away. Entries get cached in offheap memory first and then get evicted to swap, if one is configured.</li>",
+            "  <li>OFFHEAP_VALUES - entry keys will be stored on heap memory, and values will be stored in offheap memory. Note that in this mode entries can be evicted only to swap.</li>",
+            "</ul>"
+          ]
+        },
+        {
+          "label": "Off-heap max memory",
+          "type": "number",
+          "model": "offHeapMaxMemory",
+          "min": -1,
+          "placeholder": -1,
+          "hide": "backupItem.memoryMode == 'OFFHEAP_VALUES'",
+          "tip": [
+            "Sets maximum amount of memory available to off-heap storage.",
+            "Possible values are:",
+            "<ul>",
+            "  <li>-1 - means that off-heap storage is disabled.</li>",
+            "  <li>0 - Ignite will not limit off-heap storage (it's up to user to properly add and remove entries from cache to ensure that off-heap storage does not grow infinitely.</li>",
+            "  <li>Any positive value specifies the limit of off-heap storage in bytes.</li>",
+            "</ul>"
+          ]
+        },
+        {
+          "label": "Eviction policy",
+          "type": "dropdown-details",
+          "path": "evictionPolicy",
+          "model": "kind",
+          "placeholder": "Choose eviction policy",
+          "items": "evictionPolicies",
+          "hide": "backupItem.memoryMode == 'OFFHEAP_TIERED'",
+          "tip": [
+            "Optional cache eviction policy. Must be set for entries to be evicted from on-heap to off-heap or swap."
+          ],
+          "details": {
+            "LRU": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Batch size",
+                  "type": "number",
+                  "path": "evictionPolicy.LRU",
+                  "model": "batchSize",
+                  "placeholder": 1,
+                  "tip": [
+                    "Number of entries to remove on shrink."
+                  ]
+                },
+                {
+                  "label": "Max memory size",
+                  "type": "number",
+                  "path": "evictionPolicy.LRU",
+                  "model": "maxMemorySize",
+                  "placeholder": 0,
+                  "tip": [
+                    "Maximum allowed cache size in bytes."
+                  ]
+                },
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "evictionPolicy.LRU",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start getting evicted."
+                  ]
+                }
+              ]
+            },
+            "RND": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "evictionPolicy.RND",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start getting evicted."
+                  ]
+                }
+              ]
+            },
+            "FIFO": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Batch size",
+                  "type": "number",
+                  "path": "evictionPolicy.FIFO",
+                  "model": "batchSize",
+                  "placeholder": 1,
+                  "tip": [
+                    "Number of entries to remove on shrink."
+                  ]
+                },
+                {
+                  "label": "Max memory size",
+                  "type": "number",
+                  "path": "evictionPolicy.FIFO",
+                  "model": "maxMemorySize",
+                  "placeholder": 0,
+                  "tip": [
+                    "Maximum allowed cache size in bytes."
+                  ]
+                },
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "evictionPolicy.FIFO",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start getting evicted."
+                  ]
+                }
+              ]
+            },
+            "SORTED": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Batch size",
+                  "type": "number",
+                  "path": "evictionPolicy.SORTED",
+                  "model": "batchSize",
+                  "placeholder": 1,
+                  "tip": [
+                    "Number of entries to remove on shrink."
+                  ]
+                },
+                {
+                  "label": "Max memory size",
+                  "type": "number",
+                  "path": "evictionPolicy.SORTED",
+                  "model": "maxMemorySize",
+                  "placeholder": 0,
+                  "tip": [
+                    "Maximum allowed cache size in bytes."
+                  ]
+                },
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "evictionPolicy.SORTED",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start getting evicted."
+                  ]
+                }
+              ]
+            }
+          }
+        },
+        {
+          "label": "Start size",
+          "type": "number",
+          "model": "startSize",
+          "placeholder": 1500000,
+          "tip": [
+            "Initial cache size which will be used to pre-create internal hash table after start."
+          ]
+        },
+        {
+          "label": "Swap enabled",
+          "type": "check",
+          "model": "swapEnabled",
+          "tip": [
+            "Flag indicating whether swap storage is enabled or not for this cache."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Query",
+      "tip": [
+        "Cache query settings."
+      ],
+      "fields": [
+        {
+          "label": "Escape table and filed names",
+          "type": "check",
+          "model": "sqlEscapeAll",
+          "tip": [
+            "If set then all the SQL table and field names will be escaped with double quotes.",
+            "This enforces case sensitivity for field names and also allows having special characters in table and field names."
+          ]
+        },
+        {
+          "label": "On-heap cache for off-heap indexes",
+          "type": "number",
+          "model": "sqlOnheapRowCacheSize",
+          "placeholder": 10240,
+          "tip": [
+            "Number of SQL rows which will be cached onheap to avoid deserialization on each SQL index access."
+          ]
+        },
+        {
+          "label": "Long query timeout",
+          "type": "number",
+          "model": "longQueryWarningTimeout",
+          "placeholder": 3000,
+          "tip": [
+            "Timeout in milliseconds after which long query warning will be printed."
+          ]
+        },
+        {
+          "type": "indexedTypes",
+          "model": "indexedTypes",
+          "keyName": "keyClass",
+          "valueName": "valueClass",
+          "tip": [
+            "Collection of types to index."
+          ]
+        },
+        {
+          "label": "SQL functions",
+          "type": "table-simple",
+          "model": "sqlFunctionClasses",
+          "editIdx": -1,
+          "placeholder": "SQL function full class name",
+          "tableTip": [
+            "Collections of classes with user-defined functions for SQL queries."
+          ],
+          "tip": [
+            "Class with user-defined functions for SQL queries."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Rebalance",
+      "tip": [
+        "Cache rebalance settings."
+      ],
+      "fields": [
+        {
+          "label": "Mode",
+          "type": "dropdown",
+          "model": "rebalanceMode",
+          "placeholder": "ASYNC",
+          "items": "rebalanceModes",
+          "tip": [
+            "Rebalance modes:",
+            "<ul>",
+            "  <li>Synchronous - in this mode distributed caches will not start until all necessary data is loaded from other available grid nodes.</li>",
+            "  <li>Asynchronous - in this mode distributed caches will start immediately and will load all necessary data from other available grid nodes in the background.</li>",
+            "  <li>None - in this mode no rebalancing will take place which means that caches will be either loaded on demand from persistent store whenever data is accessed, or will be populated explicitly.</li>",
+            "</ul>"
+          ]
+        },
+        {
+          "label": "Pool size",
+          "type": "number",
+          "model": "rebalanceThreadPoolSize",
+          "placeholder": 2,
+          "tip": [
+            "Size of rebalancing thread pool.<br>",
+            "Note that size serves as a hint and implementation may create more threads for rebalancing than specified here (but never less threads)."
+          ]
+        },
+        {
+          "label": "Batch size",
+          "type": "number",
+          "model": "rebalanceBatchSize",
+          "placeholder": "512 * 1024",
+          "tip": [
+            "Size (in bytes) to be loaded within a single rebalance message.",
+            "Rebalancing algorithm will split total data set on every node into multiple batches prior to sending data."
+          ]
+        },
+        {
+          "label": "Order",
+          "type": "number",
+          "model": "rebalanceOrder",
+          "placeholder": 0,
+          "tip": [
+            "If cache rebalance order is positive, rebalancing for this cache will be started only when rebalancing for all caches with smaller rebalance order (except caches with rebalance order 0) will be completed."
+          ]
+        },
+        {
+          "label": "Delay",
+          "type": "number",
+          "model": "rebalanceDelay",
+          "placeholder": 0,
+          "tip": [
+            "Delay in milliseconds upon a node joining or leaving topology (or crash) after which rebalancing should be started automatically."
+          ]
+        },
+        {
+          "label": "Timeout",
+          "type": "number",
+          "model": "rebalanceTimeout",
+          "placeholder": 10000,
+          "tip": [
+            "Rebalance timeout in milliseconds."
+          ]
+        },
+        {
+          "label": "Throttle",
+          "type": "number",
+          "model": "rebalanceThrottle",
+          "placeholder": 0,
+          "tip": [
+            "Time in milliseconds to wait between rebalance messages to avoid overloading of CPU or network."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Server near cache",
+      "tip": [
+        "Near cache settings.",
+        "Near cache is a small local cache that stores most recently or most frequently accessed data.",
+        "Should be used in case when it is impossible to send computations to remote nodes."
+      ],
+      "fields": [
+        {
+          "label": "Enabled",
+          "type": "check",
+          "model": "nearCacheEnabled",
+          "tip": [
+            "Flag indicating whether to configure near cache."
+          ]
+        },
+        {
+          "label": "Start size",
+          "type": "number",
+          "path": "nearConfiguration",
+          "model": "nearStartSize",
+          "hide": "!backupItem.nearCacheEnabled",
+          "placeholder": 375000,
+          "tip": [
+            "Initial cache size for near cache which will be used to pre-create internal hash table after start."
+          ]
+        },
+        {
+          "label": "Eviction policy",
+          "type": "dropdown-details",
+          "path": "nearConfiguration.nearEvictionPolicy",
+          "model": "kind",
+          "placeholder": "Choose eviction policy",
+          "items": "evictionPolicies",
+          "hide": "!backupItem.nearCacheEnabled",
+          "tip": [
+            "Cache expiration policy."
+          ],
+          "details": {
+            "LRU": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Batch size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.LRU",
+                  "model": "batchSize",
+                  "placeholder": 1,
+                  "tip": [
+                    "Number of entries to remove on shrink."
+                  ]
+                },
+                {
+                  "label": "Max memory size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.LRU",
+                  "model": "maxMemorySize",
+                  "placeholder": 0,
+                  "tip": [
+                    "Maximum allowed cache size in bytes."
+                  ]
+                },
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.LRU",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start getting evicted."
+                  ]
+                }
+              ]
+            },
+            "RND": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.RND",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start getting evicted."
+                  ]
+                }
+              ]
+            },
+            "FIFO": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Batch size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.FIFO",
+                  "model": "batchSize",
+                  "placeholder": 1,
+                  "tip": [
+                    "Number of entries to remove on shrink."
+                  ]
+                },
+                {
+                  "label": "Max memory size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.FIFO",
+                  "model": "maxMemorySize",
+                  "placeholder": 0,
+                  "tip": [
+                    "Maximum allowed cache size in bytes."
+                  ]
+                },
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.FIFO",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start getting evicted."
+                  ]
+                }
+              ]
+            },
+            "SORTED": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Batch size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.SORTED",
+                  "model": "batchSize",
+                  "placeholder": 1,
+                  "tip": [
+                    "Number of entries to remove on shrink."
+                  ]
+                },
+                {
+                  "label": "Max memory size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.SORTED",
+                  "model": "maxMemorySize",
+                  "placeholder": 0,
+                  "tip": [
+                    "Maximum allowed cache size in bytes."
+                  ]
+                },
+                {
+                  "label": "Max size",
+                  "type": "number",
+                  "path": "nearConfiguration.nearEvictionPolicy.SORTED",
+                  "model": "maxSize",
+                  "placeholder": 100000,
+                  "tip": [
+                    "Maximum allowed size of cache before entry will start getting evicted."
+                  ]
+                }
+              ]
+            }
+          }
+        }
+      ]
+    },
+    {
+      "label": "Statistics",
+      "tip": [
+        "Cache statistics and management settings."
+      ],
+      "fields": [
+        {
+          "label": "Statistics enabled",
+          "type": "check",
+          "model": "statisticsEnabled",
+          "tip": [
+            "Flag indicating whether statistics gathering is enabled on a cache."
+          ]
+        },
+        {
+          "label": "Management enabled",
+          "type": "check",
+          "model": "managementEnabled",
+          "tip": [
+            "Flag indicating whether management is enabled on this cache."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Store",
+      "tip": [
+        "Cache store settings."
+      ],
+      "fields": [
+        {
+          "label": "Store factory",
+          "type": "dropdown-details",
+          "path": "cacheStoreFactory",
+          "model": "kind",
+          "placeholder": "Choose store factory",
+          "items": "cacheStoreFactories",
+          "tip": [
+            "Factory for persistent storage for cache data."
+          ],
+          "details": {
+            "CacheJdbcPojoStoreFactory": {
+              "expanded": true,
+              "fields": [
+                {
+                  "label": "Data source bean",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcPojoStoreFactory",
+                  "model": "dataSourceBean",
+                  "required": true,
+                  "placeholder": "Bean name in Spring context",
+                  "tip": [
+                    "Name of the data source bean in Spring context."
+                  ]
+                },
+                {
+                  "label": "Dialect",
+                  "type": "dropdown",
+                  "path": "cacheStoreFactory.CacheJdbcPojoStoreFactory",
+                  "model": "dialect",
+                  "required": true,
+                  "placeholder": "Choose JDBC dialect",
+                  "items": "cacheStoreJdbcDialects",
+                  "tip": [
+                    "Dialect of SQL implemented by a particular RDBMS:",
+                    "<ul>",
+                    "  <li>Generic JDBC dialect.</li>",
+                    "  <li>Oracle database.</li>",
+                    "  <li>IBM DB2.</li>",
+                    "  <li>Microsoft SQL Server.</li>",
+                    "  <li>My SQL.</li>",
+                    "  <li>H2 database.</li>",
+                    "</ul>"
+                  ]
+                }
+              ]
+            },
+            "CacheJdbcBlobStoreFactory": {
+              "expanded": true,
+              "fields": [
+                {
+                  "label": "user",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "user",
+                  "required": true,
+                  "tip": [
+                    "User name for database access."
+                  ]
+                },
+                {
+                  "label": "Data source bean",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "dataSourceBean",
+                  "required": true,
+                  "placeholder": "Bean name in Spring context",
+                  "tip": [
+                    "Name of the data source bean in Spring context."
+                  ]
+                },
+                {
+                  "label": "Init schema",
+                  "type": "check",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "initSchema",
+                  "tip": [
+                    "Flag indicating whether DB schema should be initialized by Ignite (default behaviour) or was explicitly created by user."
+                  ]
+                },
+                {
+                  "label": "Create query",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "createTableQuery",
+                  "placeholder": "SQL for table creation",
+                  "tip": [
+                    "Query for table creation in underlying database.",
+                    "Default value: create table if not exists ENTRIES (key binary primary key, val binary)"
+                  ]
+                },
+                {
+                  "label": "Load query",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "loadQuery",
+                  "placeholder": "SQL for load entry",
+                  "tip": [
+                    "Query for entry load from underlying database.",
+                    "Default value: select * from ENTRIES where key=?"
+                  ]
+                },
+                {
+                  "label": "Insert query",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "insertQuery",
+                  "placeholder": "SQL for insert entry",
+                  "tip": [
+                    "Query for insert entry into underlying database.",
+                    "Default value: insert into ENTRIES (key, val) values (?, ?)"
+                  ]
+                },
+                {
+                  "label": "Update query",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "updateQuery",
+                  "placeholder": "SQL for update entry",
+                  "tip": [
+                    "Query fpr update entry in underlying database.",
+                    "Default value: update ENTRIES set val=? where key=?"
+                  ]
+                },
+                {
+                  "label": "Delete query",
+                  "type": "text",
+                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
+                  "model": "deleteQuery",
+                  "placeholder": "SQL for delete entry",
+                  "tip": [
+                    "Query for delete entry from underlying database.",
+                    "Default value: delete from ENTRIES where key=?"
+                  ]
+                }
+              ]
+            },
+            "CacheHibernateBlobStoreFactory": {
+              "expanded": true,
+              "fields": [
+                {
+                  "label": "Hibernate properties",
+                  "type": "table-simple",
+                  "path": "cacheStoreFactory.CacheHibernateBlobStoreFactory",
+                  "model": "hibernateProperties",
+                  "editIdx": -1,
+                  "placeholder": "key=value",
+                  "tip": [
+                    "List of Hibernate properties.",
+                    "For example: connection.url=jdbc:h2:mem:"
+                  ]
+                }
+              ]
+            }
+          }
+        },
+        {
+          "label": "Load previous value",
+          "type": "check",
+          "model": "loadPreviousValue",
+          "tip": [
+            "Flag indicating whether value should be loaded from store if it is not in the cache for following cache operations:",
+            "<ul>",
+            "  <li>IgniteCache.putIfAbsent()</li>",
+            "  <li>IgniteCache.replace()</li>",
+            "  <li>IgniteCache.replace()</li>",
+            "  <li>IgniteCache.remove()</li>",
+            "  <li>IgniteCache.getAndPut()</li>",
+            "  <li>IgniteCache.getAndRemove()</li>",
+            "  <li>IgniteCache.getAndReplace()</li>",
+            "  <li>IgniteCache.getAndPutIfAbsent()</li>",
+            "</ul>"
+          ]
+        },
+        {
+          "label": "Read-through",
+          "type": "check",
+          "model": "readThrough",
+          "tip": [
+            "Flag indicating whether read-through caching should be used."
+          ]
+        },
+        {
+          "label": "Write-through",
+          "type": "check",
+          "model": "writeThrough",
+          "tip": [
+            "Flag indicating whether write-through caching should be used."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Write behind",
+      "tip": [
+        "Cache write behind settings.",
+        "Write-behind is a special mode when updates to cache accumulated and then asynchronously flushed to persistent store as a bulk operation."
+      ],
+      "fields": [
+        {
+          "label": "Enabled",
+          "type": "check",
+          "model": "writeBehindEnabled",
+          "tip": [
+            "Flag indicating whether Ignite should use write-behind behaviour for the cache store."
+          ]
+        },
+        {
+          "label": "Batch size",
+          "type": "number",
+          "model": "writeBehindBatchSize",
+          "hide": "!backupItem.writeBehindEnabled",
+          "placeholder": 512,
+          "tip": [
+            "Maximum batch size for write-behind cache store operations.",
+            "Store operations (get or remove) are combined in a batch of this size to be passed to cache store."
+          ]
+        },
+        {
+          "label": "Flush size",
+          "type": "number",
+          "model": "writeBehindFlushSize",
+          "hide": "!backupItem.writeBehindEnabled",
+          "placeholder": 10240,
+          "tip": [
+            "Maximum size of the write-behind cache.<br>",
+            "If cache size exceeds this value, all cached items are flushed to the cache store and write cache is cleared."
+          ]
+        },
+        {
+          "label": "Flush frequency",
+          "type": "number",
+          "model": "writeBehindFlushFrequency",
+          "hide": "!backupItem.writeBehindEnabled",
+          "placeholder": 5000,
+          "tip": [
+            "Frequency with which write-behind cache is flushed to the cache store in milliseconds."
+          ]
+        },
+        {
+          "label": "Flush threads count",
+          "type": "number",
+          "model": "writeBehindFlushThreadCount",
+          "hide": "!backupItem.writeBehindEnabled",
+          "placeholder": 1,
+          "tip": [
+            "Number of threads that will perform cache flushing."
+          ]
+        }
+      ]
+    }
+  ]
+}


[33/50] [abbrv] incubator-ignite git commit: # ignite-843 revert

Posted by an...@apache.org.
# ignite-843 revert


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

Branch: refs/heads/ignite-1121
Commit: 31e401c845a146b6fa44c19a004a7714ffd1cf51
Parents: fe43275
Author: Andrey <an...@gridgain.com>
Authored: Wed Jul 22 17:40:29 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Wed Jul 22 17:56:38 2015 +0700

----------------------------------------------------------------------
 .../nodejs/agents/agent-manager.js              |  4 -
 .../controllers/cache-viewer-controller.js      | 77 ----------------
 .../nodejs/controllers/models/sql.json          |  5 ++
 .../nodejs/controllers/sql-controller.js        | 60 +++++++++++++
 .../nodejs/controllers/summary-controller.js    |  6 ++
 .../nodejs/public/stylesheets/style.less        | 17 +++-
 .../web-control-center/nodejs/routes/agent.js   | 27 ++----
 .../nodejs/tests/routes/agent.js                | 94 ++++++++++++++++++++
 .../nodejs/views/configuration/summary.jade     | 80 ++++++++---------
 .../nodejs/views/includes/header.jade           |  2 +-
 .../nodejs/views/sql/sql.jade                   | 87 ++++++++++--------
 .../nodejs/views/templates/layout.jade          |  2 +-
 12 files changed, 277 insertions(+), 184 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/31e401c8/modules/web-control-center/nodejs/agents/agent-manager.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/agents/agent-manager.js b/modules/web-control-center/nodejs/agents/agent-manager.js
index 39d81bb..252b984 100644
--- a/modules/web-control-center/nodejs/agents/agent-manager.js
+++ b/modules/web-control-center/nodejs/agents/agent-manager.js
@@ -17,10 +17,6 @@
 
 var WebSocketServer = require('ws').Server;
 
-var config = require('../helpers/configuration-loader.js');
-
-var https = require('https');
-
 var ignite = require('apache-ignite');
 
 var db = require('../db');

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/31e401c8/modules/web-control-center/nodejs/controllers/cache-viewer-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/cache-viewer-controller.js b/modules/web-control-center/nodejs/controllers/cache-viewer-controller.js
deleted file mode 100644
index 6e0c130..0000000
--- a/modules/web-control-center/nodejs/controllers/cache-viewer-controller.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var demoResults = [
-    {
-        id: 256,
-        s: 'com.foo.User@3213',
-        fields: {
-            id: 256,
-            firstName: 'Ivan',
-            lastName: 'Ivanov',
-            old: 23
-        }
-    },
-
-    {
-        id: 384,
-        s: 'com.foo.User@23214',
-        fields: {
-            id: 384,
-            firstName: 'Sergey',
-            lastName: 'Petrov',
-            old: 28
-        }
-    },
-
-    {
-        id: 923,
-        s: 'com.foo.User@93494',
-        fields: {
-            id: 923,
-            firstName: 'Andrey',
-            lastName: 'Sidorov',
-            old: 28
-        }
-    }
-];
-
-var demoCaches = ['Users', 'Organizations', 'Cities'];
-
-controlCenterModule.controller('cacheViewerController', ['$scope', '$http', '$common', function ($scope, $http, $common) {
-    $scope.results = demoResults;
-
-    $scope.caches = demoCaches;
-
-    $scope.defCache = $scope.caches.length > 0 ? $scope.caches[0] : null;
-
-    var sqlEditor = ace.edit('querySql');
-
-    sqlEditor.setOptions({
-        highlightActiveLine: false,
-        showPrintMargin: false,
-        showGutter: true,
-        theme: "ace/theme/chrome",
-        mode: "ace/mode/sql",
-        fontSize: 14
-    });
-
-    sqlEditor.setValue("select u.id from User u where u.name like 'aaaa';");
-
-    sqlEditor.selection.clearSelection()
-
-}]);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/31e401c8/modules/web-control-center/nodejs/controllers/models/sql.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/sql.json b/modules/web-control-center/nodejs/controllers/models/sql.json
new file mode 100644
index 0000000..b00e5dd
--- /dev/null
+++ b/modules/web-control-center/nodejs/controllers/models/sql.json
@@ -0,0 +1,5 @@
+{
+  "screenTip": [
+    "Execute SQL queries."
+  ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/31e401c8/modules/web-control-center/nodejs/controllers/sql-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/sql-controller.js b/modules/web-control-center/nodejs/controllers/sql-controller.js
new file mode 100644
index 0000000..2562117
--- /dev/null
+++ b/modules/web-control-center/nodejs/controllers/sql-controller.js
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var demoResults = [
+    {
+        id: 256,
+        firstName: 'Ivan',
+        lastName: 'Ivanov'
+    },
+    {
+        id: 384,
+        firstName: 'Sergey',
+        lastName: 'Petrov'
+    },
+    {
+        id: 923,
+        firstName: 'Andrey',
+        lastName: 'Sidorov'
+    }
+];
+
+var demoCaches = [{_id: '1', name: 'Users', mode: 'LOCAL'}, {_id: '2', name: 'Organizations', mode: 'REPLICATED'}, {_id: '3', name: 'Cities', mode: 'PARTITIONED'}];
+
+controlCenterModule.controller('sqlController', ['$scope', '$http', '$common', function ($scope, $http, $common) {
+    $scope.joinTip = $common.joinTip;
+
+    $scope.modes = [
+        {value: 'PARTITIONED', label: 'PARTITIONED'},
+        {value: 'REPLICATED', label: 'REPLICATED'},
+        {value: 'LOCAL', label: 'LOCAL'}
+    ];
+
+    $http.get('/models/sql.json')
+        .success(function (data) {
+            $scope.screenTip = data.screenTip;
+        })
+        .error(function (errMsg) {
+            $common.showError(errMsg);
+        });
+
+    $scope.query = "select u.id, u.firstName, u.lastName from User u where u.name like 'aaaa';";
+
+    $scope.results = demoResults;
+
+    $scope.caches = demoCaches;
+}]);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/31e401c8/modules/web-control-center/nodejs/controllers/summary-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/summary-controller.js b/modules/web-control-center/nodejs/controllers/summary-controller.js
index 2872a58..208166c 100644
--- a/modules/web-control-center/nodejs/controllers/summary-controller.js
+++ b/modules/web-control-center/nodejs/controllers/summary-controller.js
@@ -53,6 +53,12 @@ controlCenterModule.controller('summaryController', ['$scope', '$http', '$common
         editor.setReadOnly(true);
         editor.setOption("highlightActiveLine", false);
 
+        var renderer = editor.renderer;
+
+        renderer.setHighlightGutterLine(false);
+        renderer.setShowPrintMargin(false);
+        renderer.setOption('fontSize', '14px');
+
         editor.setTheme('ace/theme/chrome');
     };
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/31e401c8/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 f858df5..d180988 100644
--- a/modules/web-control-center/nodejs/public/stylesheets/style.less
+++ b/modules/web-control-center/nodejs/public/stylesheets/style.less
@@ -593,7 +593,7 @@ h1.ignite-logo {
 }
 
 .greedy {
-  min-height: 200px;
+  min-height: 100%;
   height: ~"calc(100vh - 290px)";
 }
 
@@ -1052,7 +1052,7 @@ input.ng-dirty.ng-invalid, button.ng-dirty.ng-invalid {
   margin-top: 10px;
 }
 
-.configBox .nav > li > a {
+.nav-tabs > li > a {
   padding: 5px 5px;
 }
 
@@ -1107,8 +1107,19 @@ a {
 }
 
 .ace_editor, #ace_document {
+  margin:  0.65em 0 0 0;
+
   width: 100%;
   height: 400px;
-}
 
+  .ace_gutter {
+    background: transparent !important;
+    border: 1px #ddd;
+    border-right-style: solid;
+  }
 
+  .ace_gutter-cell, .ace_folding-enabled > .ace_gutter-cell {
+    padding-left: 0.65em;
+    padding-right: 0.9em;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/31e401c8/modules/web-control-center/nodejs/routes/agent.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/agent.js b/modules/web-control-center/nodejs/routes/agent.js
index 1d3c199..19379e2 100644
--- a/modules/web-control-center/nodejs/routes/agent.js
+++ b/modules/web-control-center/nodejs/routes/agent.js
@@ -18,32 +18,19 @@
 var router = require('express').Router();
 var agentManager = require('../agents/agent-manager');
 
-
-
 /* GET summary page. */
-router.get('/', function(req, res) {
+router.post('/topology', function(req, res) {
     var c = agentManager.getAgentManager().getOneClient();
 
-    if (!c) {
-        return res.send("Client not found");
-    }
-
-    var html = "";
+    if (!c)
+        return res.status(500).send("Client not found");
 
     var ignite = c.ignite();
 
-    ignite.version().then(function (ver) {
-        html += "version: " + ver + "<br>";
-
-        return ignite.cluster()
-    }).then(function (cluster) {
-        html += "cluster size: " + cluster.length + "<br>";
-
-        for (var i = 0; i < cluster.length; i++) {
-            html += "#" + cluster[i].nodeId();
-        }
-
-        res.send(html);
+    ignite.cluster().then(function (cluster) {
+        res.json(cluster);
+    }, function (err) {
+        res.send(err);
     });
 });
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/31e401c8/modules/web-control-center/nodejs/tests/routes/agent.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/tests/routes/agent.js b/modules/web-control-center/nodejs/tests/routes/agent.js
new file mode 100644
index 0000000..6a7fa2c
--- /dev/null
+++ b/modules/web-control-center/nodejs/tests/routes/agent.js
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var request = require('supertest'),
+    should = require('should'),
+    app = require('../../app'),
+    fs = require('fs'),
+    https = require('https'),
+    config = require('../../helpers/configuration-loader.js'),
+    agentManager = require('../../agents/agent-manager');
+
+/**
+ * Create HTTP server.
+ */
+/**
+ * Start agent server.
+ */
+var agentServer = https.createServer({
+    key: fs.readFileSync(config.get('monitor:server:key')),
+    cert: fs.readFileSync(config.get('monitor:server:cert')),
+    passphrase: config.get('monitor:server:keyPassphrase')
+});
+
+agentServer.listen(config.get('monitor:server:port'));
+
+agentManager.createManager(agentServer);
+
+describe('request from agent', function() {
+    var agent = request.agent(app);
+
+    before(function (done) {
+        this.timeout(10000);
+
+        agent
+            .post('/login')
+            .send({email: 'anovikov@gridgain.com', password: 'extHB2aXgb'})
+            .expect(302)
+            .end(function (err) {
+                if (err)
+                    throw err;
+
+                setTimeout(done, 5000);
+            });
+    });
+
+    it('should return topology snapshot', function(done){
+        agent
+            .post('/agent/topology')
+            .send({})
+            .end(function(err, nodes) {
+                if (err) {
+                    console.log(err.response.text);
+
+                    throw err;
+                }
+
+                console.log(nodes);
+
+                done();
+            });
+    });
+
+    //it('should query result', function(done){
+    //    agent
+    //        .post('/agent/query')
+    //        .send({
+    //            username: 'nva',
+    //            password: 'nva.141',
+    //            host: 'localhost',
+    //            port: '5432',
+    //            dbName: 'ggmonitor'
+    //        })
+    //        .end(function(err, res) {
+    //            if (err)
+    //                throw err;
+    //
+    //            done();
+    //        });
+    //});
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/31e401c8/modules/web-control-center/nodejs/views/configuration/summary.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/summary.jade b/modules/web-control-center/nodejs/views/configuration/summary.jade
index 0b5a298..2fe679f 100644
--- a/modules/web-control-center/nodejs/views/configuration/summary.jade
+++ b/modules/web-control-center/nodejs/views/configuration/summary.jade
@@ -63,33 +63,32 @@ block content
                             a(bs-collapse-toggle) Server
                             button.btn.btn-primary.pull-right(type='submit' style='margin-top: -5px') Download
                     .panel-collapse(role="tabpanel" bs-collapse-target)
-                        .panel-body
-                            .configBox(ng-show='selectedItem' bs-tabs)
-                                div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
-                                    .configBox(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlServer' style='margin: 0.65em 0;')
-                                div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
-                                    .settings-row
-                                        .col-sm-1
-                                            label Generate:
-                                        .col-sm-3
-                                            button.form-control(type='button' ng-model='configServer.javaClassServer'  bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
-                                    .configBox(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaServer')
-                                div(title='<img src="/images/docker.png" width="16px" height="16px"/> Dockerfile' bs-pane)
-                                    .settings-row
-                                        p
-                                            +hard-link('https://docs.docker.com/reference/builder', 'Docker')
-                                            | &nbsp;file is a text file with instructions to create Docker image.<br/>
-                                            | To build image you have to store following Docker file with your Ignite XML configuration to the same directory.<br>
-                                            | Also you could use predefined&nbsp;
-                                            +hard-link('https://ignite.incubator.apache.org/download.html#docker', 'Apache Ignite docker image')
-                                            | . For more information about using Ignite with Docker please read&nbsp;
-                                            +hard-link('http://apacheignite.readme.io/docs/docker-deployment', 'documentation')
-                                            |.
-                                        .col-sm-2
-                                            label(for='os') Operation System:
-                                        .col-sm-4
-                                            input#os.form-control(type='text', ng-model='configServer.os' placeholder='debian:8' data-min-length="0" data-html="1" data-auto-select="true" data-animation="am-flip-x" bs-typeahead bs-options='os for os in oss')
-                                    div(ui-ace='{ onLoad: aceInit, mode: "dockerfile" }' ng-model='dockerServer')
+                        div(ng-show='selectedItem' bs-tabs style='margin-top: 0.65em')
+                            div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
+                                div(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlServer')
+                            div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
+                                .details-row
+                                    .col-sm-1
+                                        label Generate:
+                                    .col-sm-3
+                                        button.form-control(type='button' ng-model='configServer.javaClassServer'  bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
+                                div(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaServer')
+                            div(title='<img src="/images/docker.png" width="16px" height="16px"/> Dockerfile' bs-pane)
+                                .details-row
+                                    p
+                                        +hard-link('https://docs.docker.com/reference/builder', 'Docker')
+                                        | &nbsp;file is a text file with instructions to create Docker image.<br/>
+                                        | To build image you have to store following Docker file with your Ignite XML configuration to the same directory.<br>
+                                        | Also you could use predefined&nbsp;
+                                        +hard-link('https://ignite.incubator.apache.org/download.html#docker', 'Apache Ignite docker image')
+                                        | . For more information about using Ignite with Docker please read&nbsp;
+                                        +hard-link('http://apacheignite.readme.io/docs/docker-deployment', 'documentation')
+                                        |.
+                                    .col-sm-2
+                                        label(for='os') Operation System:
+                                    .col-sm-4
+                                        input#os.form-control(type='text', ng-model='configServer.os' placeholder='debian:8' data-min-length="0" data-html="1" data-auto-select="true" data-animation="am-flip-x" bs-typeahead bs-options='os for os in oss')
+                                div(ui-ace='{ onLoad: aceInit, mode: "dockerfile" }' ng-model='dockerServer')
             div(bs-collapse data-start-collapsed='false')
                 .panel.panel-default
                     form.panel-heading(role='tab' method='post' action='summary/download')
@@ -101,17 +100,16 @@ block content
                             a(bs-collapse-toggle) Client
                             button.btn.btn-primary.pull-right(type='submit' style='margin-top: -5px') Download
                     .panel-collapse(role="tabpanel" bs-collapse-target)
-                        .panel-body
-                            div(ng-show='selectedItem')
-                                .settings-row(ng-repeat='field in clientFields')
-                                    +form-row-custom(['col-sm-3'], ['col-sm-3'])
-                                .configBox(bs-tabs)
-                                    div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
-                                        .configBox(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlClient' style='margin: 0.65em 0;')
-                                    div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
-                                        .settings-row
-                                            .col-sm-1
-                                                label Generate:
-                                            .col-sm-4
-                                                button.form-control(type='button' ng-model='backupItem.javaClassClient' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
-                                        div(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaClient')
+                        div(ng-show='selectedItem')
+                            .details-row(ng-repeat='field in clientFields')
+                                +form-row-custom(['col-sm-3'], ['col-sm-3'])
+                            div(bs-tabs style='margin-top: 0.65em')
+                                div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
+                                    div(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlClient')
+                                div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
+                                    .details-row
+                                        .col-sm-1
+                                            label Generate:
+                                        .col-sm-4
+                                            button.form-control(type='button' ng-model='backupItem.javaClassClient' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
+                                    div(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaClient')

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/31e401c8/modules/web-control-center/nodejs/views/includes/header.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/includes/header.jade b/modules/web-control-center/nodejs/views/includes/header.jade
index ab2d31e..bfd5275 100644
--- a/modules/web-control-center/nodejs/views/includes/header.jade
+++ b/modules/web-control-center/nodejs/views/includes/header.jade
@@ -29,7 +29,7 @@ header.header(id='header')
             ul.nav.navbar-nav(ng-controller='activeLink' ng-show='user')
                 +header-item('/configuration', '/configuration/clusters', 'Configuration')
                 //+header-item('/monitoring', '/monitoring', 'Monitoring')
-                //+header-item('/sql', '/sql', 'SQL')
+                +header-item('/sql', '/sql', 'SQL')
                 //+header-item('/deploy', '/deploy', 'Deploy')
             ul.nav.navbar-nav.pull-right
                 li(ng-if='user')

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/31e401c8/modules/web-control-center/nodejs/views/sql/sql.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/sql/sql.jade b/modules/web-control-center/nodejs/views/sql/sql.jade
index 7c4ddaf..9ba3056 100644
--- a/modules/web-control-center/nodejs/views/sql/sql.jade
+++ b/modules/web-control-center/nodejs/views/sql/sql.jade
@@ -1,4 +1,3 @@
-
 //-
     Licensed to the Apache Software Foundation (ASF) under one or more
     contributor license agreements.  See the NOTICE file distributed with
@@ -15,43 +14,57 @@
 extends ../templates/layout
 
 append scripts
-    script(src='/cache-viewer-controller.js')
-    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js')
+    script(src='/sql-controller.js')
 
-append css
-    link(rel='stylesheet', href='/stylesheets/sql-console.css')
+    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/theme-chrome.js')
+    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-sql.js')
+    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ext-language_tools.js')
 
 block container
-    .docs-header
-        h1 Connect to Ignite and execute SQL queries
-        hr
-    div(ng-controller='cacheViewerController')
-        h4 Sql console
-
-        table#queryTable(cellpadding=0, cellspacing=0, ng-init='queryType = "sql"')
-            tr
-                td
-                    label(for='queryTypeSelect') Query&nbsp;type:
-                    select#queryTypeSelect(ng-model='queryType')
-                        option(value='sql') Sql query
-                        option(value='id') Get by ID
-                        option(value='scane') Scan cache
-
-                td.queryTd
-                    div(ng-show='queryType == "sql"')
-                        #querySql
-
-                td
-                    | Default&nbsp;cache:
-                    div#defCacheSelect
-                        div(ng-repeat='c in caches', ng-class='{def: defCache == c}', ng-click='defCache = c') {{c}}
-
-        #resultPanel
-            strong Results
-
-            #queryResult
-                div(ng-repeat='r in results')
-                    .resultRow
-                        | {{r.id}} -> {{r.s}}
-                        span.props  {{r.fields}}
+    .row
+        .col-sm-12
+            .docs-content
+                .docs-header
+                    h1 Connect to Ignite and execute SQL queries
+                    hr
+                .docs-body(ng-controller='sqlController')
+                    .block-callout
+                        p(ng-bind-html='joinTip(screenTip)')
+                    .tabs-below(bs-tabs bs-active-pane='tabs.activeTab')
+                        div(title='Query #1' bs-pane)
+                            .row
+                                .col-sm-9
+                                    div(style='height: 200px' ui-ace='{ theme: "chrome", mode: "sql",' +
+                                        'require: ["ace/ext/language_tools"],' +
+                                        'rendererOptions: {showPrintMargin: false, highlightGutterLine: false, fontSize: 14},' +
+                                        'advanced: {enableSnippets: false, enableBasicAutocompletion: true, enableLiveAutocompletion: true}}'  ng-model='query')
+                                .col-sm-3
+                                    .links(ng-hide='caches.length == 0' style='margin-top: 0.65em')
+                                        lable.labelHeader Caches:
+                                        table(st-table='caches')
+                                            tbody
+                                                tr(ng-repeat='row in caches track by row._id')
+                                                    td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
+                                                        a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}}
+                        div(title='Query #2' bs-pane)
+                            .row
+                    .settings-row
+                        button.btn.btn-primary(ng-click='') Explain
+                        button.btn.btn-primary(ng-click='') Execute
+                        button.btn.btn-primary(ng-click='' disabled) Scan
+                    //#resultPanel
+                    //    strong Results
+                    //
+                    //    #queryResult
+                    //        div(ng-repeat='r in results')
+                    //            .resultRow
+                    //                | {{r.id}} -> {{r.s}}
+                    //                span.props  {{r.fields}}
 
+                    div(ng-hide='results.length == 0' style='margin-top: 0.65em')
+                        lable.labelHeader Results:
+                        table.table-bordered(st-table='results')
+                            tbody
+                                tr(ng-repeat='row in results')
+                                    td
+                                        a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/31e401c8/modules/web-control-center/nodejs/views/templates/layout.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/templates/layout.jade b/modules/web-control-center/nodejs/views/templates/layout.jade
index a4191ae..8fbcd7e 100644
--- a/modules/web-control-center/nodejs/views/templates/layout.jade
+++ b/modules/web-control-center/nodejs/views/templates/layout.jade
@@ -49,7 +49,7 @@ html(ng-app='ignite-web-control-center', ng-init='user = #{JSON.stringify(user)}
             script(src='/common-module.js')
             script(src='/data-structures.js')
 
-    body.theme-line.body-overlap
+    body.theme-line.body-overlap.greedy
         .wrapper
             include ../includes/header
 


[39/50] [abbrv] incubator-ignite git commit: # ignite-843 moved

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/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
deleted file mode 100644
index 4a618fa..0000000
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ /dev/null
@@ -1,322 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-mixin block-callout(titleWorkflow, contentWorkflow, whatsNextWorkflow, whatsNextContent)
-    .block-callout-parent.block-callout-border.margin-bottom-dflt
-        .block-callout
-            i.fa.fa-check-square
-            label #{titleWorkflow}
-            p(ng-bind-html=contentWorkflow)
-        .block-callout
-            i.fa.fa-check-square
-            label #{whatsNextWorkflow}
-            p(ng-bind-html=whatsNextContent)
-
-
-mixin tipField(lines)
-    i.tipField.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')
-    i.tipField.fa.fa-question-circle.blank(ng-if='!#{lines}')
-
-mixin tipLabel(lines)
-    i.tipLabel.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')
-    i.tipLabel.fa.fa-question-circle.blank(ng-if='!#{lines}')
-
-mixin ico-exclamation(mdl, err, msg)
-    i.fa.fa-exclamation-triangle.form-control-feedback(ng-show='inputForm["#{mdl}"].$error.#{err}' bs-tooltip data-title='#{msg}' type='button')
-
-mixin btn-save(show, click)
-    i.tipField.fa.fa-floppy-o(ng-show=show ng-click=click)
-
-mixin btn-add(click)
-    i.tipField.fa.fa-plus(ng-click=click)
-
-mixin btn-remove(click)
-    i.tipField.fa.fa-remove(ng-click=click)
-
-mixin btn-up(show, click)
-    i.tipField.fa.fa-arrow-up(ng-show=show ng-click=click)
-
-mixin btn-down(show, click)
-    i.tipField.fa.fa-arrow-down(ng-show=show ng-click=click)
-
-mixin table-pair-edit(keyModel, valModel, keyPlaceholder, valPlaceholder)
-    .col-sm-6(style='float: right')
-        input.form-control(type='text' ng-model=valModel placeholder=valPlaceholder)
-    label.fieldSep /
-    .input-tip
-        input.form-control(type='text' ng-model=keyModel placeholder=keyPlaceholder)
-
-mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
-    .col-sm-6
-        label.table-header #{header}:
-        +tipLabel('field.tip')
-        button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-    table.links-edit.col-sm-12(st-table=tblMdl)
-        tbody
-            tr.col-sm-12(ng-repeat='item in #{tblMdl}')
-                td.col-sm-6
-                    div(ng-show='!tableEditing(field, $index)')
-                        a.labelFormField(ng-click='curPair = tableStartEdit(backupItem, field, $index); curKey = curPair.#{keyFld}; curValue = curPair.#{valFld}') {{$index + 1}}) {{item.#{keyFld}}} / {{item.#{valFld}}}
-                        +btn-remove('tableRemove(backupItem, field, $index)')
-                    div(ng-show='tableEditing(field, $index)')
-                        label.labelField {{$index + 1}})
-                        +btn-save('tablePairSaveVisible(curKey, curValue)', 'tablePairSave(tablePairValid, backupItem, field, curKey, curValue, $index)')
-                        +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder)
-            tr.col-sm-12(ng-show='tableNewItemActive(field)')
-                td.col-sm-6
-                    +btn-save('tablePairSaveVisible(newKey, newValue)', 'tablePairSave(tablePairValid, backupItem, field, newKey, newValue, -1)')
-                    +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder)
-
-mixin details-row
-    - var lblDetailClasses = ['col-sm-4', 'details-label']
-
-    - var detailMdl = 'getModel(backupItem, detail)[detail.model]';
-    - var detailCommon = {'ng-model': detailMdl, 'ng-required': 'detail.required'};
-
-    - var customValidators = {'ng-attr-ipaddress': '{{detail.ipaddress}}'}
-
-    div(ng-switch='detail.type')
-        div(ng-switch-when='label')
-            label {{detail.label}}
-        div.checkbox(ng-switch-when='check')
-            label
-                input(type='checkbox')&attributes(detailCommon)
-                |{{detail.label}}
-                +tipLabel('detail.tip')
-        div(ng-switch-when='text')
-            label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
-            .col-sm-8
-                +tipField('detail.tip')
-                .input-tip
-                    input.form-control(type='text' placeholder='{{detail.placeholder}}')&attributes(detailCommon)
-        div(ng-switch-when='number' )
-            label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
-            .col-sm-8
-                +tipField('detail.tip')
-                .input-tip
-                    input.form-control(name='{{detail.model}}' type='number' placeholder='{{detail.placeholder}}' min='{{detail.min ? detail.min : 0}}' max='{{detail.max ? detail.max : Number.MAX_VALUE}}')&attributes(detailCommon)
-                    +ico-exclamation('{{detail.model}}', 'min', 'Value is less than allowable minimum.')
-                    +ico-exclamation('{{detail.model}}', 'max', 'Value is more than allowable maximum.')
-                    +ico-exclamation('{{detail.model}}', 'number', 'Invalid value. Only numbers allowed.')
-        div(ng-switch-when='dropdown')
-            label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
-            .col-sm-8
-                +tipField('detail.tip')
-                .input-tip
-                    button.form-control(bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in {{detail.items}}')&attributes(detailCommon)
-        div(ng-switch-when='dropdown-multiple')
-            label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
-            .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')&attributes(detailCommon)
-            div(ng-if='detail.label')
-                label.table-header {{detail.label}}:
-                +tipLabel('detail.tableTip')
-            table.col-sm-12.links-edit-details(st-table='#{detailMdl}')
-                tbody
-                    tr(ng-repeat='item in #{detailMdl} track by $index')
-                        td
-                            div(ng-show='!tableEditing(detail, $index)')
-                                a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, detail, $index)') {{$index + 1}}) {{item}}
-                                +btn-remove('tableRemove(backupItem, detail, $index)')
-                                +btn-down('detail.reordering && tableSimpleDownVisible(backupItem, detail, $index)', 'tableSimpleDown(backupItem, detail, $index)')
-                                +btn-up('detail.reordering && $index > 0', 'tableSimpleUp(backupItem, detail, $index)')
-                            div(ng-show='tableEditing(detail, $index)')
-                                label.labelField {{$index + 1}})
-                                +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, detail, curValue, $index)')
-                                .input-tip.form-group.has-feedback
-                                    input.form-control(name='{{detail.model}}.edit' type='text' ng-model='curValue' placeholder='{{detail.placeholder}}')&attributes(customValidators)
-                                    +ico-exclamation('{{detail.model}}.edit', 'ipaddress', 'Invalid address, see help for format description.')
-            button.btn.btn-primary.fieldButton(ng-disabled='!newValue' ng-click='tableSimpleSave(tableSimpleValid, backupItem, detail, newValue, -1)') Add
-            +tipField('detail.tip')
-            .input-tip.form-group.has-feedback
-                input.form-control(name='{{detail.model}}' type='text' ng-model='newValue' ng-focus='tableNewItem(detail)' placeholder='{{detail.placeholder}}')&attributes(customValidators)
-                +ico-exclamation('{{detail.model}}', 'ipaddress', 'Invalid address, see help for format description.')
-
-mixin table-db-field-edit(dbName, dbType, javaName, javaType)
-    div(style='width: 22%; float: right')
-        button.form-control(ng-model=javaType bs-select data-placeholder='Java type' bs-options='item.value as item.label for item in {{javaTypes}}')
-    label.fieldSep /
-    div(style='width: 20%; float: right')
-        input.form-control(type='text' ng-model=javaName placeholder='Java name')
-    label.fieldSep /
-    div(style='width: 22%; float: right')
-        button.form-control(ng-model=dbType bs-select data-placeholder='JDBC type' bs-options='item.value as item.label for item in {{jdbcTypes}}')
-    label.fieldSep /
-    .input-tip
-        input.form-control(type='text' ng-model=dbName placeholder='DB name')
-
-mixin table-group-item-edit(fieldName, className, direction)
-    div(style='width: 15%; float: right')
-        button.form-control(ng-model=direction bs-select data-placeholder='Sort' bs-options='item.value as item.label for item in {{sortDirections}}')
-    label.fieldSep /
-    div(style='width: 38%; float: right')
-        input.form-control(type='text' ng-model=className placeholder='Class name')
-    label.fieldSep /
-    .input-tip
-        input.form-control(type='text' ng-model=fieldName placeholder='Field name')
-
-mixin form-row
-    +form-row-custom(['col-sm-2'], ['col-sm-4'])
-
-mixin form-row-custom(lblClasses, fieldClasses)
-    - var fieldMdl = 'getModel(backupItem, field)[field.model]';
-    - var fieldCommon = {'ng-model': fieldMdl, 'ng-required': 'field.required || required(field)'};
-    - var fieldRequiredClass = '{true: "required"}[field.required || required(field)]'
-    - var fieldHide = '{{field.hide}}'
-
-    div(ng-switch='field.type')
-        div.col-sm-6(ng-switch-when='label')
-            label {{field.label}}
-        div.checkbox.col-sm-6(ng-switch-when='check' ng-hide=fieldHide)
-            label
-                input(type='checkbox')&attributes(fieldCommon)
-                | {{field.label}}
-                +tipLabel('field.tip')
-        div(ng-switch-when='text' ng-hide=fieldHide)
-            label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
-            div(class=fieldClasses)
-                +tipField('field.tip')
-                .input-tip
-                    input.form-control(type='text' placeholder='{{field.placeholder}}')&attributes(fieldCommon)
-        div(ng-switch-when='password' ng-hide=fieldHide)
-            label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
-            div(class=fieldClasses)
-                +tipField('field.tip')
-                .input-tip
-                    input.form-control(type='password' placeholder='{{field.placeholder}}')&attributes(fieldCommon)
-        div(ng-switch-when='number' ng-hide=fieldHide)
-            label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
-            div(class=fieldClasses)
-                +tipField('field.tip')
-                .input-tip
-                    input.form-control(name='{{field.model}}' type='number' placeholder='{{field.placeholder}}' min='{{field.min ? field.min : 0}}' max='{{field.max ? field.max : Number.MAX_VALUE}}')&attributes(fieldCommon)
-                    +ico-exclamation('{{field.model}}', 'min', 'Value is less than allowable minimum.')
-                    +ico-exclamation('{{field.model}}', 'max', 'Value is more than allowable maximum.')
-                    +ico-exclamation('{{field.model}}', 'number', 'Invalid value. Only numbers allowed.')
-        div(ng-switch-when='dropdown' ng-hide=fieldHide)
-            label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
-            div(class=fieldClasses)
-                +tipField('field.tip')
-                .input-tip
-                    button.form-control(bs-select data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label for item in {{field.items}}')&attributes(fieldCommon)
-        div(ng-switch-when='dropdown-multiple' ng-hide=fieldHide)
-            label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
-            div(class=fieldClasses)
-                +tipField('field.tip')
-                .input-tip
-                    button.form-control(bs-select ng-disabled='{{field.items}}.length == 0' data-multiple='1' data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label for item in {{field.items}}')&attributes(fieldCommon)
-            a.customize(ng-show='field.addLink' ng-href='{{field.addLink.ref}}') {{field.addLink.label}}
-        div(ng-switch-when='dropdown-details' ng-hide=fieldHide)
-            - var expanded = 'field.details[' + fieldMdl + '].expanded'
-
-            label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
-            div(class=fieldClasses)
-                +tipField('field.tip')
-                .input-tip
-                    button.form-control(bs-select data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label for item in {{field.items}}')&attributes(fieldCommon)
-            a.customize(ng-show='#{fieldMdl} && field.details[#{fieldMdl}].fields' ng-click='#{expanded} = !#{expanded}') {{#{expanded} ? "Hide settings" : "Show settings"}}
-            .col-sm-6.panel-details(ng-show='#{expanded} && #{fieldMdl}')
-                .details-row(ng-repeat='detail in field.details[#{fieldMdl}].fields')
-                    +details-row
-        div(ng-switch-when='table-simple' ng-hide=fieldHide)&attributes(fieldCommon)
-            .col-sm-6
-                label.table-header {{field.label}}:
-                +tipLabel('field.tableTip')
-                button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-            table.links-edit.col-sm-12(st-table='#{fieldMdl}')
-                tbody
-                    tr.col-sm-12(ng-repeat='item in #{fieldMdl} track by $index')
-                        td.col-sm-6
-                            div(ng-show='!tableEditing(field, $index)')
-                                a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, field, $index)') {{$index + 1}}) {{item | compact}}
-                                +btn-remove('tableRemove(backupItem, field, $index)')
-                                +btn-down('field.reordering && tableSimpleDownVisible(backupItem, field, $index)', 'tableSimpleDown(backupItem, field, $index)')
-                                +btn-up('field.reordering && $index > 0', 'tableSimpleUp(backupItem, field, $index)')
-                            div(ng-show='tableEditing(field, $index)')
-                                label.labelField {{$index + 1}})
-                                +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, curValue, $index)')
-                                .input-tip
-                                    input.form-control(type='text' ng-model='curValue' placeholder='{{field.placeholder}}')
-                    tr.col-sm-12(ng-show='tableNewItemActive(field)')
-                        td.col-sm-6
-                            +btn-save('tableSimpleSaveVisible(newValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)')
-                            .input-tip
-                                input.form-control(type='text' ng-model='newValue' placeholder='{{field.placeholder}}')
-        div(ng-switch-when='indexedTypes')
-            +table-pair('Index key-value type pairs', fieldMdl, 'keyClass', 'valueClass', 'Key class full name', 'Value class full name')
-        div(ng-switch-when='queryFields' ng-hide=fieldHide)
-            +table-pair('{{field.label}}', fieldMdl, 'name', 'className', 'Field name', 'Field class full name')
-        div(ng-switch-when='dbFields' ng-hide=fieldHide)
-            .col-sm-6
-                label.table-header {{field.label}}:
-                +tipLabel('field.tip')
-                button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-            table.links-edit.col-sm-12(st-table=fieldMdl)
-                tbody
-                    tr.col-sm-12(ng-repeat='item in #{fieldMdl}')
-                        td.col-sm-6
-                            div(ng-show='!tableEditing(field, $index)')
-                                a.labelFormField(ng-click='curField = tableStartEdit(backupItem, field, $index); curDbName = curField.dbName; curDbType = curField.dbType; curJavaName = curField.javaName; curJavaType = curField.javaType') {{$index + 1}}) {{item.dbName}} / {{item.dbType}} / {{item.javaName}} / {{item.javaType}}
-                                +btn-remove('tableRemove(backupItem, field, $index)')
-                            div(ng-if='tableEditing(field, $index)')
-                                label.labelField {{$index + 1}})
-                                +btn-save('tableDbFieldSaveVisible(curDbName, curDbType, curJavaName, curJavaType)', 'tableDbFieldSave(field, curDbName, curDbType, curJavaName, curJavaType, $index)')
-                                +table-db-field-edit('curDbName', 'curDbType', 'curJavaName', 'curJavaType')
-                    tr(ng-show='tableNewItemActive(field)')
-                        td.col-sm-6
-                            +btn-save('tableDbFieldSaveVisible(newDbName, newDbType, newJavaName, newJavaType)', 'tableDbFieldSave(field, newDbName, newDbType, newJavaName, newJavaType, -1)')
-                            +table-db-field-edit('newDbName', 'newDbType', 'newJavaName', 'newJavaType')
-        div(ng-switch-when='queryGroups' ng-hide=fieldHide)
-            .col-sm-6
-                label.table-header {{field.label}}:
-                +tipLabel('field.tip')
-                button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-            table.links-edit.col-sm-12(st-table=fieldMdl)
-                tbody
-                    tr.col-sm-12(ng-repeat='group in #{fieldMdl}')
-                        td.col-sm-6
-                            div
-                                .col-sm-12(ng-show='!tableEditing(field, $index)')
-                                    a.labelFormField(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curGroupName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{group.name}}
-                                    +btn-remove('tableRemove(backupItem, field, $index)')
-                                    +btn-add('tableGroupNewItem($index); newDirection = "ASC"')
-                                div(ng-show='tableEditing(field, $index)')
-                                    label.labelField {{$index + 1}})
-                                    +btn-save('tableGroupSaveVisible(curGroupName)', 'tableGroupSave(curGroupName, $index)')
-                                    .input-tip
-                                        input.form-control(type='text' ng-model='curGroupName' placeholder='Index name')
-                                div
-                                    table.links-edit.col-sm-12(st-table='group.fields' ng-init='groupIndex = $index')
-                                        tr(ng-repeat='groupItem in group.fields')
-                                            td
-                                                div(ng-show='!tableGroupItemEditing(groupIndex, $index)')
-                                                    a.labelFormField(ng-click='curGroupItem = tableGroupItemStartEdit(groupIndex, $index); curFieldName = curGroupItem.name; curClassName = curGroupItem.className; curDirection = curGroupItem.direction') {{$index + 1}}) {{groupItem.name}} / {{groupItem.className}} / {{groupItem.direction}}
-                                                    +btn-remove('tableRemoveGroupItem(group, $index)')
-                                                div(ng-show='tableGroupItemEditing(groupIndex, $index)')
-                                                    label.labelField {{$index + 1}})
-                                                    +btn-save('tableGroupItemSaveVisible(curFieldName, curClassName)', 'tableGroupItemSave(curFieldName, curClassName, curDirection, groupIndex, $index)')
-                                                    +table-group-item-edit('curFieldName', 'curClassName', 'curDirection')
-                                        tr.col-sm-12(style='padding-left: 18px' ng-show='tableGroupNewItemActive(groupIndex)')
-                                            td
-                                                +btn-save('tableGroupItemSaveVisible(newFieldName, newClassName)', 'tableGroupItemSave(newFieldName, newClassName, newDirection, groupIndex, -1)')
-                                                +table-group-item-edit('newFieldName', 'newClassName', 'newDirection')
-                    tr.col-sm-12(ng-show='tableNewItemActive(field)')
-                        td.col-sm-6
-                            +btn-save('tableGroupSaveVisible(newGroupName)', 'tableGroupSave(newGroupName, -1)')
-                            .input-tip
-                                input.form-control(type='text' ng-model='newGroupName' placeholder='Group name')
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/includes/footer.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/includes/footer.jade b/modules/web-control-center/nodejs/views/includes/footer.jade
deleted file mode 100644
index d8ff5d7..0000000
--- a/modules/web-control-center/nodejs/views/includes/footer.jade
+++ /dev/null
@@ -1,22 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-.container.container-footer
-    footer
-        center
-            p Apache Ignite Control Center, version 1.0.0
-            p © 2015 The Apache Software Foundation.
-            p Apache, Apache Ignite, the Apache feather and the Apache Ignite logo are trademarks of The Apache Software Foundation.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/includes/header.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/includes/header.jade b/modules/web-control-center/nodejs/views/includes/header.jade
deleted file mode 100644
index ab2d31e..0000000
--- a/modules/web-control-center/nodejs/views/includes/header.jade
+++ /dev/null
@@ -1,39 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-mixin header-item(active, ref, txt)
-    li
-        a(ng-class='{active: isActive("#{active}")}' href='#{ref}') #{txt}
-
-header.header(id='header')
-    .viewedUser(ng-show='becomeUsed') Currently assuming "
-        strong {{user.username}}
-        | ",&nbsp;&nbsp;
-        a(href='/admin/become') revert to your identity.
-    .container
-        h1.navbar-brand
-            a(href='/') Apache Ignite Web Configurator
-        .navbar-collapse.collapse(ng-controller='auth')
-            ul.nav.navbar-nav(ng-controller='activeLink' ng-show='user')
-                +header-item('/configuration', '/configuration/clusters', 'Configuration')
-                //+header-item('/monitoring', '/monitoring', 'Monitoring')
-                //+header-item('/sql', '/sql', 'SQL')
-                //+header-item('/deploy', '/deploy', 'Deploy')
-            ul.nav.navbar-nav.pull-right
-                li(ng-if='user')
-                    a.dropdown-toggle(data-toggle='dropdown' bs-dropdown='userDropdown' data-placement='bottom-right') {{user.username}}
-                        span.caret
-                li.nav-login(ng-if='!user')
-                    a(ng-click='login()' href='#') Log In
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/index.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/index.jade b/modules/web-control-center/nodejs/views/index.jade
deleted file mode 100644
index 999c4f8..0000000
--- a/modules/web-control-center/nodejs/views/index.jade
+++ /dev/null
@@ -1,30 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-extends templates/layout
-
-block container
-    .row
-        .docs-content
-            div
-                p
-                    | Apache Ignite<sup>tm</sup> In-Memory Data Fabric is a high-performance,
-                    | integrated and distributed in-memory platform for computing and transacting on large-scale data
-                    | sets in real-time, orders of magnitude faster than possible with traditional disk-based or flash technologies.
-        .block-image.block-display-image
-                img(ng-src='https://www.filepicker.io/api/file/lydEeGB6Rs9hwbpcQxiw' alt='Apache Ignite stack')
-        .text-center(ng-controller='auth')
-            button.btn.btn-primary(ng-click='login()' href='#') Configure Now

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/login.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/login.jade b/modules/web-control-center/nodejs/views/login.jade
deleted file mode 100644
index 5bb39dd..0000000
--- a/modules/web-control-center/nodejs/views/login.jade
+++ /dev/null
@@ -1,55 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-mixin lbl(txt)
-    label.col-sm-3.required #{txt}
-
-.modal.center(role='dialog')
-    .modal-dialog
-        .modal-content
-            .modal-header.header
-                div(id='errors-container')
-                button.close(type='button', ng-click='$hide()', aria-hidden='true') &times;
-                h1.navbar-brand
-                    a(href='/') Apache Ignite Web Configurator
-                h4.modal-title(style='padding-right: 55px') Authentication
-                p(style='padding-right: 55px') Log in or register in order to collaborate
-            form.form-horizontal(name='loginForm')
-                .modal-body.row
-                    .col-sm-9.login.col-sm-offset-1
-                        .details-row(ng-show='action == "register"')
-                            +lbl('Full Name:')
-                            .col-sm-9
-                                input.form-control(type='text', ng-model='user_info.username', placeholder='John Smith', focus-me='action=="register"', ng-required='action=="register"')
-                        .details-row
-                            +lbl('Email:')
-                            .col-sm-9
-                                input.form-control(type='email', ng-model='user_info.email', placeholder='you@domain.com', focus-me='action=="login"', required)
-                        .details-row
-                            +lbl('Password:')
-                            .col-sm-9
-                                input.form-control(type='password', ng-model='user_info.password', placeholder='Password', required, ng-keyup='action == "login" && $event.keyCode == 13 ? auth(action, user_info) : null')
-                        .details-row(ng-show='action == "register"')
-                            +lbl('Confirm:')
-                            .col-sm-9.input-tip.has-feedback
-                                input.form-control(type='password', ng-model='user_info.confirm', match="user_info.password" placeholder='Confirm password', required, ng-keyup='$event.keyCode == 13 ? auth(action, user_info) : null')
-
-            .modal-footer
-                a.show-signup.ng-hide(ng-show='action != "login"', ng-click='action = "login";') log in
-                a.show-signup(ng-show="action != 'register'", ng-click='action = "register";') sign up
-                | &nbsp;or&nbsp;
-                button.btn.btn-primary(ng-show='action == "login"' ng-click='auth(action, user_info)') Log In
-                button.btn.btn-primary(ng-show='action == "register"' ng-disabled='loginForm.$invalid || user_info.password != user_info.confirm' ng-click='auth(action, user_info)') Sign Up

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/settings/admin.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/settings/admin.jade b/modules/web-control-center/nodejs/views/settings/admin.jade
deleted file mode 100644
index 4d50631..0000000
--- a/modules/web-control-center/nodejs/views/settings/admin.jade
+++ /dev/null
@@ -1,58 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-         http://www.apache.org/licenses/LICENSE-2.0
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-extends ../templates/layout
-
-append scripts
-    script(src='/admin-controller.js')
-
-block container
-    .row(ng-controller='adminController')
-        .docs-content
-            .docs-header
-                h1 List of registered users
-                hr
-            .docs-body
-                table.table.table-striped.admin(st-table='displayedUsers' st-safe-src='users')
-                    thead
-                        tr
-                            th.header(colspan='5')
-                                .col-sm-2.pull-right
-                                    input.form-control(type='text' st-search='' placeholder='Filter users...')
-                        tr
-                            th(st-sort='username') User name
-                            th(st-sort='email') Email
-                            th.col-sm-2(st-sort='lastLogin') Last login
-                            th(width='1%'  st-sort='admin') Admin
-                            th(width='1%') Actions
-                    tbody
-                        tr(ng-repeat='row in displayedUsers')
-                            td {{row.username}}
-                            td
-                                a(ng-href='mailto:{{row.email}}') {{row.email}}
-                            td
-                                span {{row.lastLogin | date:'medium'}}
-                            td(style='text-align: center;')
-                                input(type='checkbox' ng-disabled='row.adminChanging || row._id == user._id'
-                                    ng-model='row.admin' ng-change='toggleAdmin(row)')
-                            td(style='text-align: center;')
-                                a(ng-click='removeUser(row)' ng-show='row._id != user._id' bs-tooltip data-title='Remove user')
-                                    i.fa.fa-remove
-                                a(style='margin-left: 5px' ng-href='admin/become?viewedUserId={{row._id}}' ng-show='row._id != user._id' bs-tooltip data-title='Become this user')
-                                    i.fa.fa-eye
-                    tfoot
-                        tr
-                            td(colspan='5' class="text-right")
-                                div(st-pagination st-items-by-page='15' st-displayed-pages='5')
-

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/settings/profile.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/settings/profile.jade b/modules/web-control-center/nodejs/views/settings/profile.jade
deleted file mode 100644
index dbc6dea..0000000
--- a/modules/web-control-center/nodejs/views/settings/profile.jade
+++ /dev/null
@@ -1,58 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-extends ../templates/layout
-
-mixin lbl(txt)
-    label.col-sm-2.required.labelFormField #{txt}
-
-append scripts
-    script(src='/profile-controller.js')
-
-block container
-    .row(ng-controller='profileController')
-        .docs-content
-            .docs-header
-                h1 User profile
-                hr
-            .docs-body
-                form.form-horizontal(name='profileForm' novalidate)
-                    .col-sm-10(style='padding: 0')
-                        .details-row
-                            +lbl('User name:')
-                            .col-sm-4
-                                input.form-control(type='text' ng-model='profileUser.username' placeholder='Input name' required)
-                        .details-row
-                            +lbl('Email:')
-                            .col-sm-4
-                                input.form-control(type='email' ng-model='profileUser.email' placeholder='you@domain.com' required)
-                        .details-row
-                            .checkbox
-                                label
-                                    input(type="checkbox" ng-model='profileUser.changePassword')
-                                    | Change password
-                        div(ng-show='profileUser.changePassword')
-                            .details-row
-                                +lbl('New password:')
-                                .col-sm-4
-                                    input.form-control(type='password', ng-model='profileUser.newPassword' placeholder='New password' ng-required='profileUser.changePassword')
-                            .details-row
-                                +lbl('Confirm:')
-                                .col-sm-4
-                                    input.form-control(type='password', ng-model='profileUser.confirmPassword' match='profileUser.newPassword' placeholder='Confirm new password' ng-required='profileUser.changePassword')
-                    .col-sm-12.details-row
-                        button.btn.btn-primary(ng-disabled='profileForm.$invalid' ng-click='saveUser()') Save
-

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/templates/confirm.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/templates/confirm.jade b/modules/web-control-center/nodejs/views/templates/confirm.jade
deleted file mode 100644
index bdaf9bf..0000000
--- a/modules/web-control-center/nodejs/views/templates/confirm.jade
+++ /dev/null
@@ -1,27 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-.modal(tabindex='-1' role='dialog')
-    .modal-dialog
-        .modal-content
-            .modal-header
-                button.close(type="button" ng-click="$hide()") &times;
-                h4.modal-title Confirmation
-            .modal-body(ng-show='content')
-                p(ng-bind-html='content' style='text-align: center;')
-            .modal-footer
-                button.btn.btn-default(type="button" ng-click="$hide()") Cancel
-                button.btn.btn-primary(type="button" ng-click="ok()") Confirm
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/templates/copy.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/templates/copy.jade b/modules/web-control-center/nodejs/views/templates/copy.jade
deleted file mode 100644
index 22cc64c..0000000
--- a/modules/web-control-center/nodejs/views/templates/copy.jade
+++ /dev/null
@@ -1,31 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-.modal(tabindex='-1' role='dialog')
-    .modal-dialog
-        .modal-content
-            .modal-header
-                button.close(type="button" ng-click="$hide()") &times;
-                h4.modal-title Copy
-            form.form-horizontal(name='inputForm' novalidate)
-                .modal-body.row
-                    .col-sm-9.login.col-sm-offset-1
-                        label.required.labelFormField() New name:&nbsp;
-                        .col-sm-9
-                            input.form-control(type="text" ng-model='newName' required)
-            .modal-footer
-                button.btn.btn-default(type="button" ng-click="$hide()") Cancel
-                button.btn.btn-primary(type="button" ng-disabled='inputForm.$invalid' ng-click="ok(newName)") Confirm
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/templates/layout.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/templates/layout.jade b/modules/web-control-center/nodejs/views/templates/layout.jade
deleted file mode 100644
index a4191ae..0000000
--- a/modules/web-control-center/nodejs/views/templates/layout.jade
+++ /dev/null
@@ -1,61 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-doctype html
-html(ng-app='ignite-web-control-center', ng-init='user = #{JSON.stringify(user)}; becomeUsed = #{becomeUsed}')
-    head
-        title= title
-
-        block css
-            // Bootstrap
-            link(rel='stylesheet', href='//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.css')
-
-            // Font Awesome Icons
-            link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.css')
-
-            // Font
-            link(rel='stylesheet', href='//fonts.googleapis.com/css?family=Roboto+Slab:700:serif|Roboto+Slab:400:serif')
-
-            link(rel='stylesheet', href='/stylesheets/style.css')
-
-        block scripts
-            script(src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js')
-
-            script(src='//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min.js')
-
-            script(src='//ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.js')
-            script(src='//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.2/angular-sanitize.js')
-            script(src='//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.0/angular-strap.js')
-            script(src='//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.0/angular-strap.tpl.min.js')
-
-            script(src='//cdnjs.cloudflare.com/ajax/libs/angular-smart-table/2.0.3/smart-table.js')
-
-            script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js')
-            script(src='//angular-ui.github.io/ui-ace/dist/ui-ace.min.js')
-
-            script(src='/common-module.js')
-            script(src='/data-structures.js')
-
-    body.theme-line.body-overlap
-        .wrapper
-            include ../includes/header
-
-            block main-container
-                .container.body-container
-                    .main-content
-                        block container
-
-            include ../includes/footer

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/templates/select.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/templates/select.jade b/modules/web-control-center/nodejs/views/templates/select.jade
deleted file mode 100644
index 10c1946..0000000
--- a/modules/web-control-center/nodejs/views/templates/select.jade
+++ /dev/null
@@ -1,26 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-ul.select.dropdown-menu(tabindex='-1', ng-show='$isVisible()', role='select')
-    li(role='presentation', ng-repeat='match in $matches')
-        hr(ng-if='match.value == undefined' style='margin: 5px 0')
-        a(style='cursor: default; padding: 3px 6px;', role='menuitem', tabindex='-1', ng-class='{active: $isActive($index)}' ng-click='$select($index, $event)')
-            i(class='{{$iconCheckmark}}', ng-if='$isActive($index)' ng-class='{active: $isActive($index)}' style='color: #ec1c24; margin-left: 15px; line-height: 20px; float: right;background-color: transparent;')
-            span(ng-bind='match.label')
-    li(ng-if='$showAllNoneButtons || ($isMultiple && $matches.length > 5)')
-        hr(style='margin: 5px 0')
-        a(ng-click='$selectAll()') {{$allText}}
-        a(ng-click='$selectNone()') {{$noneText}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/.gitignore
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/.gitignore b/modules/web-control-center/src/main/js/.gitignore
new file mode 100644
index 0000000..65f2596
--- /dev/null
+++ b/modules/web-control-center/src/main/js/.gitignore
@@ -0,0 +1,4 @@
+node_modules
+*.idea
+*.log
+*.css
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/DEVNOTES.txt
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/DEVNOTES.txt b/modules/web-control-center/src/main/js/DEVNOTES.txt
new file mode 100644
index 0000000..aa56011
--- /dev/null
+++ b/modules/web-control-center/src/main/js/DEVNOTES.txt
@@ -0,0 +1,21 @@
+Ignite Web Control Center Instructions
+======================================
+
+How to deploy:
+
+1. Install locally NodeJS using installer from site https://nodejs.org for your OS.
+2. Install locally MongoDB folow instructions from site http://docs.mongodb.org/manual/installation
+3. Checkout ignite-843 branch.
+4. Change directory '$IGNITE_HOME/modules/web-control-center/nodejs'.
+5. Run "npm install" in terminal for download all dependencies.
+
+Steps 1 - 5 should be executed once.
+
+How to run:
+
+1. Run MongoDB.
+ 1.1 In terminal change dir to $MONGO_ISNTALL_DIR/server/3.0/bin.
+ 1.2 Run "mongod".
+2. In new terminal change directory '$IGNITE_HOME/modules/web-control-center/nodejs'.
+3. Start application by executing "npm start".
+4. In browser open: http://localhost:3000
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/app.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/app.js b/modules/web-control-center/src/main/js/app.js
new file mode 100644
index 0000000..8c347db
--- /dev/null
+++ b/modules/web-control-center/src/main/js/app.js
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var flash = require('connect-flash');
+var express = require('express');
+var path = require('path');
+var favicon = require('serve-favicon');
+var logger = require('morgan');
+var cookieParser = require('cookie-parser');
+var bodyParser = require('body-parser');
+var session = require('express-session');
+var mongoStore = require('connect-mongo')(session);
+
+var publicRoutes = require('./routes/public');
+var clustersRouter = require('./routes/clusters');
+var cachesRouter = require('./routes/caches');
+var metadataRouter = require('./routes/metadata');
+var summary = require('./routes/summary');
+var adminRouter = require('./routes/admin');
+var profileRouter = require('./routes/profile');
+var sqlRouter = require('./routes/sql');
+
+var passport = require('passport');
+
+var db = require('./db');
+
+var app = express();
+
+// Views engine setup.
+app.set('views', path.join(__dirname, 'views'));
+app.set('view engine', 'jade');
+
+// Site favicon.
+app.use(favicon(__dirname + '/public/favicon.ico'));
+
+app.use(logger('dev'));
+
+app.use(bodyParser.json());
+app.use(bodyParser.urlencoded({extended: false}));
+
+app.use(require('less-middleware')(path.join(__dirname, 'public'), {
+    render: {
+        compress: false
+    }
+}));
+
+app.use(express.static(path.join(__dirname, 'public')));
+app.use(express.static(path.join(__dirname, 'controllers')));
+app.use(express.static(path.join(__dirname, 'helpers')));
+
+app.use(cookieParser('keyboard cat'));
+
+app.use(session({
+    secret: 'keyboard cat',
+    resave: false,
+    saveUninitialized: true,
+    store: new mongoStore({
+        mongooseConnection: db.mongoose.connection
+    })
+}));
+
+app.use(flash());
+
+app.use(passport.initialize());
+app.use(passport.session());
+
+passport.serializeUser(db.Account.serializeUser());
+passport.deserializeUser(db.Account.deserializeUser());
+
+passport.use(db.Account.createStrategy());
+
+var mustAuthenticated = function (req, res, next) {
+    req.isAuthenticated() ? next() : res.redirect('/');
+};
+
+var adminOnly = function(req, res, next) {
+    req.isAuthenticated() && req.user.admin ? next() : res.sendStatus(403);
+};
+
+app.all('/configuration/*', mustAuthenticated);
+
+app.all('*', function(req, res, next) {
+    var becomeUsed = req.session.viewedUser && req.user.admin;
+
+    res.locals.user = becomeUsed ? req.session.viewedUser : req.user;
+    res.locals.becomeUsed = becomeUsed;
+
+    req.currentUserId = function() {
+        if (!req.user)
+            return null;
+
+        if (req.session.viewedUser && req.user.admin)
+            return req.session.viewedUser._id;
+
+        return req.user._id;
+    };
+
+    next();
+});
+
+app.use('/', publicRoutes);
+app.use('/admin', mustAuthenticated, adminOnly, adminRouter);
+app.use('/profile', mustAuthenticated, profileRouter);
+
+app.use('/configuration/clusters', clustersRouter);
+app.use('/configuration/caches', cachesRouter);
+app.use('/configuration/metadata', metadataRouter);
+app.use('/configuration/summary', summary);
+app.use('/sql', sqlRouter);
+
+// Catch 404 and forward to error handler.
+app.use(function (req, res, next) {
+    var err = new Error('Not Found: ' + req.originalUrl);
+    err.status = 404;
+    next(err);
+});
+
+// Error handlers.
+
+// Development error handler: will print stacktrace.
+if (app.get('env') === 'development') {
+    app.use(function (err, req, res) {
+        res.status(err.status || 500);
+        res.render('error', {
+            message: err.message,
+            error: err
+        });
+    });
+}
+
+// Production error handler: no stacktraces leaked to user.
+app.use(function (err, req, res) {
+    res.status(err.status || 500);
+    res.render('error', {
+        message: err.message,
+        error: {}
+    });
+});
+
+module.exports = app;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/bin/www
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/bin/www b/modules/web-control-center/src/main/js/bin/www
new file mode 100644
index 0000000..4cf0583
--- /dev/null
+++ b/modules/web-control-center/src/main/js/bin/www
@@ -0,0 +1,85 @@
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+var app = require('../app');
+var config = require('../helpers/configuration-loader.js');
+var debug = require('debug')('ignite-web-control-center:server');
+var http = require('http');
+
+/**
+ * Get port from environment and store in Express.
+ */
+var port = normalizePort(process.env.PORT || config.get('express:port'));
+app.set('port', port);
+
+/**
+ * Create HTTP server.
+ */
+var server = http.createServer(app);
+
+/**
+ * Listen on provided port, on all network interfaces.
+ */
+server.listen(port);
+server.on('error', onError);
+server.on('listening', onListening);
+
+/**
+ * Normalize a port into a number, string, or false.
+ */
+function normalizePort(val) {
+  var port = parseInt(val, 10);
+
+  if (isNaN(port)) {
+    // named pipe
+    return val;
+  }
+
+  if (port >= 0) {
+    // port number
+    return port;
+  }
+
+  return false;
+}
+
+/**
+ * Event listener for HTTP server "error" event.
+ */
+function onError(error) {
+  if (error.syscall !== 'listen') {
+    throw error;
+  }
+
+  var bind = typeof port === 'string'
+    ? 'Pipe ' + port
+    : 'Port ' + port;
+
+  // handle specific listen errors with friendly messages
+  switch (error.code) {
+    case 'EACCES':
+      console.error(bind + ' requires elevated privileges');
+      process.exit(1);
+      break;
+    case 'EADDRINUSE':
+      console.error(bind + ' is already in use');
+      process.exit(1);
+      break;
+    default:
+      throw error;
+  }
+}
+
+/**
+ * Event listener for HTTP server "listening" event.
+ */
+function onListening() {
+  var addr = server.address();
+  var bind = typeof addr === 'string'
+    ? 'pipe ' + addr
+    : 'port ' + addr.port;
+
+  debug('Listening on ' + bind);
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/config/default.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/config/default.json b/modules/web-control-center/src/main/js/config/default.json
new file mode 100644
index 0000000..72dbd4e
--- /dev/null
+++ b/modules/web-control-center/src/main/js/config/default.json
@@ -0,0 +1,8 @@
+{
+    "express": {
+        "port": 3000
+    },
+    "mongoDB": {
+        "url": "mongodb://localhost/web-control-center"
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/admin-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/admin-controller.js b/modules/web-control-center/src/main/js/controllers/admin-controller.js
new file mode 100644
index 0000000..09490fe
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/admin-controller.js
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+controlCenterModule.controller('adminController', ['$scope', '$http', '$common', '$confirm', function ($scope, $http, $common, $confirm) {
+    $scope.users = null;
+
+    function reload() {
+        $http.post('admin/list')
+            .success(function (data) {
+                $scope.users = data;
+            })
+            .error(function (errMsg) {
+                $common.showError($common.errorMessage(errMsg));
+            });
+    }
+
+    reload();
+
+    $scope.removeUser = function (user) {
+        $confirm.show('Are you sure you want to remove user: "' + user.username + '"?').then(function () {
+            $http.post('admin/remove', {userId: user._id}).success(
+                function () {
+                    var i = _.findIndex($scope.users, function (u) {
+                        return u._id == user._id;
+                    });
+
+                    if (i >= 0)
+                        $scope.users.splice(i, 1);
+
+                    $common.showInfo('User has been removed: "' + user.username + '"');
+                }).error(function (errMsg) {
+                    $common.showError('Failed to remove user: "' + $common.errorMessage(errMsg) + '"');
+                });
+        });
+    };
+
+    $scope.toggleAdmin = function (user) {
+        if (user.adminChanging)
+            return;
+
+        user.adminChanging = true;
+
+        $http.post('admin/save', {userId: user._id, adminFlag: user.admin}).success(
+            function () {
+                $common.showInfo('Admin right was successfully toggled for user: "' + user.username + '"');
+
+                user.adminChanging = false;
+            }).error(function (errMsg) {
+                $common.showError('Failed to toggle admin right for user: "' + $common.errorMessage(errMsg) + '"');
+
+                user.adminChanging = false;
+            });
+    }
+}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/cache-viewer-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/cache-viewer-controller.js b/modules/web-control-center/src/main/js/controllers/cache-viewer-controller.js
new file mode 100644
index 0000000..6e0c130
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/cache-viewer-controller.js
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var demoResults = [
+    {
+        id: 256,
+        s: 'com.foo.User@3213',
+        fields: {
+            id: 256,
+            firstName: 'Ivan',
+            lastName: 'Ivanov',
+            old: 23
+        }
+    },
+
+    {
+        id: 384,
+        s: 'com.foo.User@23214',
+        fields: {
+            id: 384,
+            firstName: 'Sergey',
+            lastName: 'Petrov',
+            old: 28
+        }
+    },
+
+    {
+        id: 923,
+        s: 'com.foo.User@93494',
+        fields: {
+            id: 923,
+            firstName: 'Andrey',
+            lastName: 'Sidorov',
+            old: 28
+        }
+    }
+];
+
+var demoCaches = ['Users', 'Organizations', 'Cities'];
+
+controlCenterModule.controller('cacheViewerController', ['$scope', '$http', '$common', function ($scope, $http, $common) {
+    $scope.results = demoResults;
+
+    $scope.caches = demoCaches;
+
+    $scope.defCache = $scope.caches.length > 0 ? $scope.caches[0] : null;
+
+    var sqlEditor = ace.edit('querySql');
+
+    sqlEditor.setOptions({
+        highlightActiveLine: false,
+        showPrintMargin: false,
+        showGutter: true,
+        theme: "ace/theme/chrome",
+        mode: "ace/mode/sql",
+        fontSize: 14
+    });
+
+    sqlEditor.setValue("select u.id from User u where u.name like 'aaaa';");
+
+    sqlEditor.selection.clearSelection()
+
+}]);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/caches-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/caches-controller.js b/modules/web-control-center/src/main/js/controllers/caches-controller.js
new file mode 100644
index 0000000..0c23e3b
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/caches-controller.js
@@ -0,0 +1,333 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+controlCenterModule.controller('cachesController', ['$scope', '$http', '$common', '$confirm', '$copy', '$table', function ($scope, $http, $common, $confirm, $copy, $table) {
+        $scope.joinTip = $common.joinTip;
+        $scope.getModel = $common.getModel;
+
+        $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.atomicities = [
+            {value: 'ATOMIC', label: 'ATOMIC'},
+            {value: 'TRANSACTIONAL', label: 'TRANSACTIONAL'}
+        ];
+
+        $scope.modes = [
+            {value: 'PARTITIONED', label: 'PARTITIONED'},
+            {value: 'REPLICATED', label: 'REPLICATED'},
+            {value: 'LOCAL', label: 'LOCAL'}
+        ];
+
+        $scope.atomicWriteOrderModes = [
+            {value: 'CLOCK', label: 'CLOCK'},
+            {value: 'PRIMARY', label: 'PRIMARY'}
+        ];
+
+        $scope.memoryModes = [
+            {value: 'ONHEAP_TIERED', label: 'ONHEAP_TIERED'},
+            {value: 'OFFHEAP_TIERED', label: 'OFFHEAP_TIERED'},
+            {value: 'OFFHEAP_VALUES', label: '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 = [
+            {value: 'SYNC', label: 'SYNC'},
+            {value: 'ASYNC', label: 'ASYNC'},
+            {value: 'NONE', label: '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.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.required = function (field) {
+            var model = $common.isDefined(field.path) ? field.path + '.' + field.model : field.model;
+
+            var backupItem = $scope.backupItem;
+
+            var memoryMode = backupItem.memoryMode;
+
+            var onHeapTired = memoryMode == 'ONHEAP_TIERED';
+            var offHeapTired = memoryMode == 'OFFHEAP_TIERED';
+
+            var offHeapMaxMemory = backupItem.offHeapMaxMemory;
+
+            if (model == 'offHeapMaxMemory' && offHeapTired)
+                return true;
+
+            if (model == 'evictionPolicy.kind' && onHeapTired)
+                return backupItem.swapEnabled || ($common.isDefined(offHeapMaxMemory) && offHeapMaxMemory >= 0);
+
+            return false;
+        };
+
+        $scope.tableSimpleValid = function (item, field, fx, index) {
+            var model = item[field.model];
+
+            if ($common.isDefined(model)) {
+                var idx = _.indexOf(model, fx);
+
+                // Found itself.
+                if (index >= 0 && index == idx)
+                    return true;
+
+                // Found duplicate.
+                if (idx >= 0) {
+                    $common.showError('SQL function such class name already exists!');
+
+                    return false;
+                }
+            }
+
+            return true;
+        };
+
+        $scope.tablePairValid = function (item, field, keyCls, valCls, index) {
+            var model = item[field.model];
+
+            if ($common.isDefined(model)) {
+                var idx = _.findIndex(model, function (pair) {
+                    return pair.keyClass == keyCls
+                });
+
+                // Found itself.
+                if (index >= 0 && index == idx)
+                    return true;
+
+                // Found duplicate.
+                if (idx >= 0) {
+                    $common.showError('Indexed type with such key class already exists!');
+
+                    return false;
+                }
+            }
+
+            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;
+
+                var restoredItem = angular.fromJson(sessionStorage.cacheBackupItem);
+
+                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;
+                        }
+                        else
+                            sessionStorage.removeItem('cacheBackupItem');
+                    }
+                    else
+                        $scope.backupItem = restoredItem;
+                }
+                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.selectItem = function (item) {
+            $table.tableReset();
+
+            $scope.selectedItem = item;
+            $scope.backupItem = angular.copy(item);
+        };
+
+        // Add new cache.
+        $scope.createItem = function () {
+            $table.tableReset();
+
+            $scope.backupItem = {mode: 'PARTITIONED', atomicityMode: 'ATOMIC', readFromBackup: true, copyOnRead: true};
+            $scope.backupItem.space = $scope.spaces[0]._id;
+        };
+
+        // 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!');
+
+                return false;
+            }
+
+            if ((item.readThrough || item.writeThrough) && !cacheStoreFactorySelected) {
+                $common.showError('Read / write through are enabled but store is not configured!');
+
+                return false;
+            }
+
+            if (item.writeBehindEnabled && !cacheStoreFactorySelected) {
+                $common.showError('Write behind enabled but store is not configured!');
+
+                return false;
+            }
+
+            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;
+                    });
+
+                    if (idx >= 0)
+                        angular.extend($scope.caches[idx], item);
+                    else {
+                        item._id = _id;
+
+                        $scope.caches.push(item);
+                    }
+
+                    $scope.selectItem(item);
+
+                    $common.showInfo('Cache "' + item.name + '" saved.');
+                })
+                .error(function (errMsg) {
+                    $common.showError(errMsg);
+                });
+        }
+
+        // Save cache.
+        $scope.saveItem = function () {
+            $table.tableReset();
+
+            var item = $scope.backupItem;
+
+            if (validate(item))
+                save(item);
+        };
+
+        // 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);
+
+                    item._id = undefined;
+                    item.name = newName;
+
+                    save(item);
+                });
+        };
+
+        // Remove cache from db.
+        $scope.removeItem = function () {
+            $table.tableReset();
+
+            var selectedItem = $scope.selectedItem;
+
+            $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);
+
+                            var caches = $scope.caches;
+
+                            var idx = _.findIndex(caches, function (cache) {
+                                return cache._id == _id;
+                            });
+
+                            if (idx >= 0) {
+                                caches.splice(idx, 1);
+
+                                if (caches.length > 0)
+                                    $scope.selectItem(caches[0]);
+                                else {
+                                    $scope.selectedItem = undefined;
+                                    $scope.backupItem = undefined;
+                                }
+                            }
+                        })
+                        .error(function (errMsg) {
+                            $common.showError(errMsg);
+                        });
+                }
+            );
+        };
+    }]
+);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/clusters-controller.js b/modules/web-control-center/src/main/js/controllers/clusters-controller.js
new file mode 100644
index 0000000..1ec78a1
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/clusters-controller.js
@@ -0,0 +1,309 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+controlCenterModule.controller('clustersController', ['$scope', '$http', '$common', '$confirm', '$copy', '$table', function ($scope, $http, $common, $confirm, $copy, $table) {
+        $scope.joinTip = $common.joinTip;
+        $scope.getModel = $common.getModel;
+
+        $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.templates = [
+            {
+                value: {discovery: {kind: 'Multicast', Vm: {addresses: ['127.0.0.1:47500..47510']}, Multicast: {}}},
+                label: 'multicast'
+            },
+            {value: {discovery: {kind: 'Vm', Vm: {addresses: ['127.0.0.1:47500..47510']}}}, label: 'local'}
+        ];
+
+        $scope.discoveries = [
+            {value: 'Vm', label: 'static IPs'},
+            {value: 'Multicast', label: 'multicast'},
+            {value: 'S3', label: 'AWS S3'},
+            {value: 'Cloud', label: 'apache jclouds'},
+            {value: 'GoogleStorage', label: 'google cloud storage'},
+            {value: 'Jdbc', label: 'JDBC'},
+            {value: 'SharedFs', label: 'shared filesystem'}
+        ];
+
+        $scope.swapSpaceSpis = [
+            {value: 'FileSwapSpaceSpi', label: 'File-based swap'},
+            {value: undefined, label: 'Not set'}
+        ];
+
+        $scope.events = [];
+
+        for (var eventGroupName in eventGroups) {
+            if (eventGroups.hasOwnProperty(eventGroupName)) {
+                $scope.events.push({value: eventGroupName, label: eventGroupName});
+            }
+        }
+
+        $scope.cacheModes = [
+            {value: 'LOCAL', label: 'LOCAL'},
+            {value: 'REPLICATED', label: 'REPLICATED'},
+            {value: 'PARTITIONED', label: 'PARTITIONED'}
+        ];
+
+        $scope.deploymentModes = [
+            {value: 'PRIVATE', label: 'PRIVATE'},
+            {value: 'ISOLATED', label: 'ISOLATED'},
+            {value: 'SHARED', label: 'SHARED'},
+            {value: 'CONTINUOUS', label: 'CONTINUOUS'}
+        ];
+
+        $scope.transactionConcurrency = [
+            {value: 'OPTIMISTIC', label: 'OPTIMISTIC'},
+            {value: 'PESSIMISTIC', label: 'PESSIMISTIC'}
+        ];
+
+        $scope.transactionIsolation = [
+            {value: 'READ_COMMITTED', label: 'READ_COMMITTED'},
+            {value: 'REPEATABLE_READ', label: 'REPEATABLE_READ'},
+            {value: 'SERIALIZABLE', label: 'SERIALIZABLE'}
+        ];
+
+        $scope.segmentationPolicy = [
+            {value: 'RESTART_JVM', label: 'RESTART_JVM'},
+            {value: 'STOP', label: 'STOP'},
+            {value: 'NOOP', label: 'NOOP'}
+        ];
+
+        $scope.marshallers = [
+            {value: 'OptimizedMarshaller', label: 'OptimizedMarshaller'},
+            {value: 'JdkMarshaller', label: 'JdkMarshaller'}
+        ];
+
+        $scope.tableSimpleValid = function (item, field, val, index) {
+            var model = $common.getModel(item, field)[field.model];
+
+            if ($common.isDefined(model)) {
+                var idx = _.indexOf(model, val);
+
+                // Found itself.
+                if (index >= 0 && index == idx)
+                    return true;
+
+                // Found duplicate.
+                if (idx >= 0) {
+                    var msg = 'Such IP address already exists!';
+
+                    if (field.model == 'regions')
+                        msg = 'Such region already exists!';
+                    if (field.model == 'zones')
+                        msg = 'Such zone already exists!';
+
+                    $common.showError(msg);
+
+                    return false;
+                }
+            }
+
+            return true;
+        };
+
+        $scope.clusters = [];
+
+        $http.get('/models/clusters.json')
+            .success(function (data) {
+                $scope.screenTip = data.screenTip;
+                $scope.templateTip = data.templateTip;
+
+                $scope.general = data.general;
+                $scope.advanced = data.advanced;
+            })
+            .error(function (errMsg) {
+                $common.showError(errMsg);
+            });
+
+        // When landing on the page, get clusters and show them.
+        $http.post('clusters/list')
+            .success(function (data) {
+                $scope.caches = data.caches;
+                $scope.spaces = data.spaces;
+                $scope.clusters = data.clusters;
+
+                var restoredItem = angular.fromJson(sessionStorage.clusterBackupItem);
+
+                if (restoredItem) {
+                    if (restoredItem._id) {
+                        var idx = _.findIndex($scope.clusters, function (cluster) {
+                            return cluster._id == restoredItem._id;
+                        });
+
+                        if (idx >= 0) {
+                            $scope.selectedItem = $scope.clusters[idx];
+                            $scope.backupItem = restoredItem;
+                        }
+                        else
+                            sessionStorage.removeItem('clusterBackupItem');
+                    }
+                    else
+                        $scope.backupItem = restoredItem;
+                }
+                else if ($scope.clusters.length > 0)
+                    $scope.selectItem($scope.clusters[0]);
+
+                $scope.$watch('backupItem', function (val) {
+                    if (val)
+                        sessionStorage.clusterBackupItem = angular.toJson(val);
+                }, true);
+            })
+            .error(function (errMsg) {
+                $common.showError(errMsg);
+            });
+
+        $scope.selectItem = function (item) {
+            $table.tableReset();
+
+            $scope.selectedItem = item;
+            $scope.backupItem = angular.copy(item);
+        };
+
+        // Add new cluster.
+        $scope.createItem = function () {
+            $table.tableReset();
+
+            $scope.backupItem = angular.copy($scope.create.template);
+            $scope.backupItem.space = $scope.spaces[0]._id;
+        };
+
+        $scope.indexOfCache = function (cacheId) {
+            return _.findIndex($scope.caches, function (cache) {
+                return cache.value == cacheId;
+            });
+        };
+
+        // Check cluster logical consistency.
+        function validate(item) {
+            if (!item.swapSpaceSpi || !item.swapSpaceSpi.kind && item.caches) {
+                for (var i = 0; i < item.caches.length; i++) {
+                    var idx = $scope.indexOfCache(item.caches[i]);
+
+                    if (idx >= 0) {
+                        var cache = $scope.caches[idx];
+
+                        if (cache.swapEnabled) {
+                            $common.showError('Swap space SPI is not configured, but cache "' + cache.label + '" configured to use swap!');
+
+                            return false;
+                        }
+                    }
+                }
+            }
+
+            return true;
+        }
+
+        // Save cluster in database.
+        function save(item) {
+            $http.post('clusters/save', item)
+                .success(function (_id) {
+                    var idx = _.findIndex($scope.clusters, function (cluster) {
+                        return cluster._id == _id;
+                    });
+
+                    if (idx >= 0)
+                        angular.extend($scope.clusters[idx], item);
+                    else {
+                        item._id = _id;
+
+                        $scope.clusters.push(item);
+                    }
+
+                    $scope.selectItem(item);
+
+                    $common.showInfo('Cluster "' + item.name + '" saved.');
+                })
+                .error(function (errMsg) {
+                    $common.showError(errMsg);
+                });
+        }
+
+        // Save cluster.
+        $scope.saveItem = function () {
+            $table.tableReset();
+
+            var item = $scope.backupItem;
+
+            if (validate(item))
+                save(item);
+        };
+
+        // Save cluster 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);
+
+                    item._id = undefined;
+                    item.name = newName;
+
+                    save(item);
+                });
+        };
+
+        // Remove cluster from db.
+        $scope.removeItem = function () {
+            $table.tableReset();
+
+            var selectedItem = $scope.selectedItem;
+
+            $confirm.show('Are you sure you want to remove cluster: "' + selectedItem.name + '"?').then(
+                function () {
+                    var _id = selectedItem._id;
+
+                    $http.post('clusters/remove', {_id: _id})
+                        .success(function () {
+                            $common.showInfo('Cluster has been removed: ' + selectedItem.name);
+
+                            var clusters = $scope.clusters;
+
+                            var idx = _.findIndex(clusters, function (cluster) {
+                                return cluster._id == _id;
+                            });
+
+                            if (idx >= 0) {
+                                clusters.splice(idx, 1);
+
+                                if (clusters.length > 0)
+                                    $scope.selectItem(clusters[0]);
+                                else {
+                                    $scope.selectedItem = undefined;
+                                    $scope.backupItem = undefined;
+                                }
+                            }
+                        })
+                        .error(function (errMsg) {
+                            $common.showError(errMsg);
+                        });
+                }
+            );
+        };
+    }]
+);
\ No newline at end of file



[11/50] [abbrv] incubator-ignite git commit: Merge remote-tracking branch 'origin/ignite-1121' into ignite-1121

Posted by an...@apache.org.
Merge remote-tracking branch 'origin/ignite-1121' into ignite-1121


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

Branch: refs/heads/ignite-1121
Commit: 1db37366eb522f803e33e7b05bc1be2c7f8e6752
Parents: 01bc127c aef4919
Author: Andrey <an...@gridgain.com>
Authored: Tue Jul 21 09:12:29 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Tue Jul 21 09:12:29 2015 +0700

----------------------------------------------------------------------
 examples/config/js/example-query.xml            |  91 ++++
 examples/pom.xml                                |   6 +
 .../ignite/examples/ExampleNodeStartup.java     |   2 +-
 examples/src/main/js/cache-query-example.js     |  20 +-
 .../JettyRestProcessorAbstractSelfTest.java     | 506 ++++++++++++++++++-
 .../ignite/compute/ComputeJobResultPolicy.java  |   3 +-
 .../ignite/internal/GridKernalContext.java      |   6 +
 .../ignite/internal/GridKernalContextImpl.java  |  14 +-
 .../ignite/internal/IgniteComponentType.java    |   8 +
 .../apache/ignite/internal/IgniteKernal.java    |   1 +
 .../failover/GridFailoverContextImpl.java       |  28 +-
 .../managers/failover/GridFailoverManager.java  |  13 +-
 .../processors/cache/GridCacheUtils.java        |   4 +-
 .../IgniteCacheObjectProcessorImpl.java         |  10 +
 .../processors/closure/AffinityTask.java        |  35 ++
 .../closure/GridClosureProcessor.java           |  63 ++-
 .../json/IgniteJsonNoopProcessor.java           |  67 +++
 .../processors/json/IgniteJsonProcessor.java    |  71 +++
 .../processors/query/GridQueryProcessor.java    | 235 ++++++++-
 .../handlers/query/QueryCommandHandler.java     |   3 +
 .../processors/task/GridTaskWorker.java         |  24 +-
 .../ignite/internal/util/IgniteUtils.java       |   4 +-
 .../plugin/security/SecurityPermission.java     |   7 +-
 .../ignite/spi/discovery/tcp/ServerImpl.java    |   8 +-
 .../ignite/spi/failover/FailoverContext.java    |  18 +
 .../spi/failover/always/AlwaysFailoverSpi.java  |  25 +
 .../IgniteClientReconnectFailoverTest.java      |  47 +-
 .../cache/CacheAffinityCallSelfTest.java        | 172 +++++++
 .../cache/GridCacheAffinityRoutingSelfTest.java | 157 +++++-
 .../cache/IgniteCacheNearLockValueSelfTest.java |   2 +
 .../spi/failover/GridFailoverTestContext.java   |  10 +
 .../ignite/testsuites/IgniteCacheTestSuite.java |   1 +
 .../org/apache/ignite/JsonArrayBuilderImpl.java | 130 -----
 .../java/org/apache/ignite/JsonArrayImpl.java   | 131 -----
 .../org/apache/ignite/JsonGeneratorImpl.java    | 500 ------------------
 .../org/apache/ignite/JsonLocationImpl.java     |  60 ---
 .../java/org/apache/ignite/JsonNumberImpl.java  | 116 -----
 .../apache/ignite/JsonObjectBuilderImpl.java    | 141 ------
 .../java/org/apache/ignite/JsonObjectImpl.java  | 116 -----
 .../org/apache/ignite/JsonProviderImpl.java     | 104 ----
 .../java/org/apache/ignite/JsonStringImpl.java  |  71 ---
 .../processors/json/IgniteJsonArray.java        | 132 +++++
 .../processors/json/IgniteJsonArrayBuilder.java | 130 +++++
 .../processors/json/IgniteJsonGenerator.java    | 500 ++++++++++++++++++
 .../processors/json/IgniteJsonLocation.java     |  60 +++
 .../json/IgniteJsonMessageFactory.java          |  36 ++
 .../processors/json/IgniteJsonNumber.java       | 116 +++++
 .../processors/json/IgniteJsonObject.java       | 117 +++++
 .../json/IgniteJsonObjectBuilder.java           | 141 ++++++
 .../json/IgniteJsonProcessorImpl.java           | 115 +++++
 .../processors/json/IgniteJsonProvider.java     | 104 ++++
 .../processors/json/IgniteJsonString.java       |  77 +++
 .../processors/json/JsonCacheObject.java        | 103 ++++
 .../java/org/apache/ignite/json/IgniteJson.java |  36 ++
 .../processors/json/IgniteJsonCacheTest.java    | 196 +++++++
 .../http/jetty/GridJettyRestHandler.java        |  46 +-
 .../ignite/schema/ui/SchemaImportApp.java       |  36 +-
 .../nodejs/agents/agent-manager.js              |  37 +-
 modules/web-control-center/nodejs/bin/www       |  15 +-
 .../web-control-center/nodejs/routes/agent.js   |   2 +-
 60 files changed, 3524 insertions(+), 1505 deletions(-)
----------------------------------------------------------------------



[34/50] [abbrv] incubator-ignite git commit: # ignite-843 moved

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/templates/copy.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/templates/copy.jade b/modules/web-control-center/src/main/js/views/templates/copy.jade
new file mode 100644
index 0000000..22cc64c
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/templates/copy.jade
@@ -0,0 +1,31 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+.modal(tabindex='-1' role='dialog')
+    .modal-dialog
+        .modal-content
+            .modal-header
+                button.close(type="button" ng-click="$hide()") &times;
+                h4.modal-title Copy
+            form.form-horizontal(name='inputForm' novalidate)
+                .modal-body.row
+                    .col-sm-9.login.col-sm-offset-1
+                        label.required.labelFormField() New name:&nbsp;
+                        .col-sm-9
+                            input.form-control(type="text" ng-model='newName' required)
+            .modal-footer
+                button.btn.btn-default(type="button" ng-click="$hide()") Cancel
+                button.btn.btn-primary(type="button" ng-disabled='inputForm.$invalid' ng-click="ok(newName)") Confirm
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/templates/layout.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/templates/layout.jade b/modules/web-control-center/src/main/js/views/templates/layout.jade
new file mode 100644
index 0000000..a4191ae
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/templates/layout.jade
@@ -0,0 +1,61 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+doctype html
+html(ng-app='ignite-web-control-center', ng-init='user = #{JSON.stringify(user)}; becomeUsed = #{becomeUsed}')
+    head
+        title= title
+
+        block css
+            // Bootstrap
+            link(rel='stylesheet', href='//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.css')
+
+            // Font Awesome Icons
+            link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.css')
+
+            // Font
+            link(rel='stylesheet', href='//fonts.googleapis.com/css?family=Roboto+Slab:700:serif|Roboto+Slab:400:serif')
+
+            link(rel='stylesheet', href='/stylesheets/style.css')
+
+        block scripts
+            script(src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js')
+
+            script(src='//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min.js')
+
+            script(src='//ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.js')
+            script(src='//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.2/angular-sanitize.js')
+            script(src='//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.0/angular-strap.js')
+            script(src='//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.0/angular-strap.tpl.min.js')
+
+            script(src='//cdnjs.cloudflare.com/ajax/libs/angular-smart-table/2.0.3/smart-table.js')
+
+            script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js')
+            script(src='//angular-ui.github.io/ui-ace/dist/ui-ace.min.js')
+
+            script(src='/common-module.js')
+            script(src='/data-structures.js')
+
+    body.theme-line.body-overlap
+        .wrapper
+            include ../includes/header
+
+            block main-container
+                .container.body-container
+                    .main-content
+                        block container
+
+            include ../includes/footer

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/templates/select.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/templates/select.jade b/modules/web-control-center/src/main/js/views/templates/select.jade
new file mode 100644
index 0000000..10c1946
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/templates/select.jade
@@ -0,0 +1,26 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+ul.select.dropdown-menu(tabindex='-1', ng-show='$isVisible()', role='select')
+    li(role='presentation', ng-repeat='match in $matches')
+        hr(ng-if='match.value == undefined' style='margin: 5px 0')
+        a(style='cursor: default; padding: 3px 6px;', role='menuitem', tabindex='-1', ng-class='{active: $isActive($index)}' ng-click='$select($index, $event)')
+            i(class='{{$iconCheckmark}}', ng-if='$isActive($index)' ng-class='{active: $isActive($index)}' style='color: #ec1c24; margin-left: 15px; line-height: 20px; float: right;background-color: transparent;')
+            span(ng-bind='match.label')
+    li(ng-if='$showAllNoneButtons || ($isMultiple && $matches.length > 5)')
+        hr(style='margin: 5px 0')
+        a(ng-click='$selectAll()') {{$allText}}
+        a(ng-click='$selectNone()') {{$noneText}}
\ No newline at end of file


[48/50] [abbrv] incubator-ignite git commit: Merge remote-tracking branch 'origin/ignite-1121' into ignite-1121

Posted by an...@apache.org.
Merge remote-tracking branch 'origin/ignite-1121' into ignite-1121


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

Branch: refs/heads/ignite-1121
Commit: 71b313c635dc9cf0b9c40d28a141d21e10e96056
Parents: 31e401c 679e328
Author: Andrey <an...@gridgain.com>
Authored: Thu Jul 23 10:25:08 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Thu Jul 23 10:25:08 2015 +0700

----------------------------------------------------------------------
 modules/control-center-agent/pom.xml            |  19 +++-
 .../apache/ignite/agent/AgentCommandLine.java   | 113 +++++++++++++++++++
 .../apache/ignite/agent/AgentConfiguration.java |  60 ++++++++--
 .../org/apache/ignite/agent/AgentLauncher.java  |  83 +++++++-------
 .../org/apache/ignite/agent/AgentSocket.java    |  25 ++--
 .../src/main/resources/config.properties        |   2 +
 .../src/main/resources/logging.properties       |   4 +
 modules/web-control-center/nodejs/bin/www       |  17 ++-
 .../nodejs/config/default.json                  |   3 +-
 9 files changed, 257 insertions(+), 69 deletions(-)
----------------------------------------------------------------------



[15/50] [abbrv] incubator-ignite git commit: IGNITE-843 Groups beta.

Posted by an...@apache.org.
IGNITE-843 Groups beta.


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

Branch: refs/heads/ignite-1121
Commit: 9499ee2eb74af8ad8f067c89f9ded1188f8768b8
Parents: a4ca8b7
Author: AKuznetsov <ak...@gridgain.com>
Authored: Tue Jul 21 11:43:46 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Tue Jul 21 11:43:46 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/caches-controller.js     |  10 ++
 .../nodejs/controllers/clusters-controller.js   |  10 ++
 .../nodejs/controllers/common-module.js         |   3 +
 .../nodejs/controllers/metadata-controller.js   | 130 ++++++++++++++++---
 .../nodejs/public/stylesheets/style.less        |   4 +
 .../nodejs/views/includes/controls.jade         |  49 +++++--
 6 files changed, 179 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/9499ee2e/modules/web-control-center/nodejs/controllers/caches-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/caches-controller.js b/modules/web-control-center/nodejs/controllers/caches-controller.js
index 505ecc0..3cef598 100644
--- a/modules/web-control-center/nodejs/controllers/caches-controller.js
+++ b/modules/web-control-center/nodejs/controllers/caches-controller.js
@@ -201,12 +201,16 @@ controlCenterModule.controller('cachesController', ['$scope', '$http', '$common'
             });
 
         $scope.selectItem = function (item) {
+            $table.tableReset();
+
             $scope.selectedItem = item;
             $scope.backupItem = angular.copy(item);
         };
 
         // Add new cache.
         $scope.createItem = function () {
+            $table.tableReset();
+
             $scope.backupItem = {mode: 'PARTITIONED', atomicityMode: 'ATOMIC', readFromBackup: true, copyOnRead: true};
             $scope.backupItem.space = $scope.spaces[0]._id;
         };
@@ -263,6 +267,8 @@ controlCenterModule.controller('cachesController', ['$scope', '$http', '$common'
 
         // Save cache.
         $scope.saveItem = function () {
+            $table.tableReset();
+
             var item = $scope.backupItem;
 
             if (validate(item))
@@ -271,6 +277,8 @@ controlCenterModule.controller('cachesController', ['$scope', '$http', '$common'
 
         // Save cache with new name.
         $scope.saveItemAs = function () {
+            $table.tableReset();
+
             if (validate($scope.backupItem))
                 $saveAs.show($scope.backupItem.name).then(function (newName) {
                     var item = angular.copy($scope.backupItem);
@@ -284,6 +292,8 @@ controlCenterModule.controller('cachesController', ['$scope', '$http', '$common'
 
         // Remove cache from db.
         $scope.removeItem = function () {
+            $table.tableReset();
+
             var selectedItem = $scope.selectedItem;
 
             $confirm.show('Are you sure you want to remove cache: "' + selectedItem.name + '"?').then(

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/9499ee2e/modules/web-control-center/nodejs/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/clusters-controller.js b/modules/web-control-center/nodejs/controllers/clusters-controller.js
index 36f783a..996e2a3 100644
--- a/modules/web-control-center/nodejs/controllers/clusters-controller.js
+++ b/modules/web-control-center/nodejs/controllers/clusters-controller.js
@@ -177,12 +177,16 @@ controlCenterModule.controller('clustersController', ['$scope', '$http', '$commo
             });
 
         $scope.selectItem = function (item) {
+            $table.tableReset();
+
             $scope.selectedItem = item;
             $scope.backupItem = angular.copy(item);
         };
 
         // Add new cluster.
         $scope.createItem = function () {
+            $table.tableReset();
+
             $scope.backupItem = angular.copy($scope.create.template);
             $scope.backupItem.space = $scope.spaces[0]._id;
         };
@@ -241,6 +245,8 @@ controlCenterModule.controller('clustersController', ['$scope', '$http', '$commo
 
         // Save cluster.
         $scope.saveItem = function () {
+            $table.tableReset();
+
             var item = $scope.backupItem;
 
             if (validate(item))
@@ -249,6 +255,8 @@ controlCenterModule.controller('clustersController', ['$scope', '$http', '$commo
 
         // Save cluster with new name.
         $scope.saveItemAs = function () {
+            $table.tableReset();
+
             if (validate($scope.backupItem))
                 $saveAs.show($scope.backupItem.name).then(function (newName) {
                     var item = angular.copy($scope.backupItem);
@@ -262,6 +270,8 @@ controlCenterModule.controller('clustersController', ['$scope', '$http', '$commo
 
         // Remove cluster from db.
         $scope.removeItem = function () {
+            $table.tableReset();
+
             var selectedItem = $scope.selectedItem;
 
             $confirm.show('Are you sure you want to remove cluster: "' + selectedItem.name + '"?').then(

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/9499ee2e/modules/web-control-center/nodejs/controllers/common-module.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/common-module.js b/modules/web-control-center/nodejs/controllers/common-module.js
index f0667c2..f011a59 100644
--- a/modules/web-control-center/nodejs/controllers/common-module.js
+++ b/modules/web-control-center/nodejs/controllers/common-module.js
@@ -217,6 +217,9 @@ controlCenterModule.service('$table', ['$common', function ($common) {
     }
 
     return {
+        tableState: function (name, editIndex) {
+            _tableState(name, editIndex);
+        },
         tableReset: function () {
             _tableReset();
         },

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/9499ee2e/modules/web-control-center/nodejs/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/metadata-controller.js b/modules/web-control-center/nodejs/controllers/metadata-controller.js
index 25e8156..1064f3a 100644
--- a/modules/web-control-center/nodejs/controllers/metadata-controller.js
+++ b/modules/web-control-center/nodejs/controllers/metadata-controller.js
@@ -102,6 +102,11 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             {value: 'Timestamp', label: 'Timestamp'}
         ];
 
+        $scope.sortDirections = [
+            {value: 'ASC', label: 'ASC'},
+            {value: 'DESC', label: 'DESC'}
+        ];
+
         $scope.data = {
             curTableIdx: 0,
             curFieldIdx: 0,
@@ -296,28 +301,17 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             });
 
         $scope.selectItem = function (item) {
+            $table.tableReset();
+
             $scope.selectedItem = item;
             $scope.backupItem = angular.copy(item);
         };
 
         // Add new metadata.
         $scope.createItem = function () {
-            $scope.backupItem = angular.copy($scope.template);
-
-            $scope.backupItem.groups = [{
-                name: "index1",
-                fields: [
-                    {name: "fld1", className: "Integer", direction: "ASC"},
-                    {name: "fld2", className: "String", direction: "DESC"}]
-            },
-                {
-                    name: "index2",
-                    fields: [
-                        {name: "fld3", className: "Integer", direction: "ASC"},
-                        {name: "fld4", className: "Data", direction: "DESC"}]
-                }
-            ];
+            $table.tableReset();
 
+            $scope.backupItem = angular.copy($scope.template);
             $scope.backupItem.space = $scope.spaces[0]._id;
         };
 
@@ -355,6 +349,8 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
 
         // Save cache type metadata.
         $scope.saveItem = function () {
+            $table.tableReset();
+
             var item = $scope.backupItem;
 
             if (validate(item))
@@ -363,6 +359,8 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
 
         // Save cache type metadata with new name.
         $scope.saveItemAs = function () {
+            $table.tableReset();
+
             if (validate($scope.backupItem))
                 $saveAs.show($scope.backupItem.name).then(function (newName) {
                     var item = angular.copy($scope.backupItem);
@@ -375,6 +373,8 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
         };
 
         $scope.removeItem = function () {
+            $table.tableReset();
+
             var selectedItem = $scope.selectedItem;
 
             $confirm.show('Are you sure you want to remove cache type metadata: "' + selectedItem.name + '"?').then(
@@ -495,9 +495,105 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             return $common.isNonEmpty(group);
         };
 
+        function tableGroupValid(groupName, index) {
+            var groups = $scope.backupItem.groups;
+
+            if ($common.isDefined(groups)) {
+                var idx = _.findIndex(groups, function (group) {return group.name == groupName});
+
+                // Found itself.
+                if (index >= 0 && index == idx)
+                    return true;
+
+                // Found duplicate.
+                if (idx >= 0) {
+                    $common.showError('Group with such name already exists!');
+
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        $scope.tableGroupSave = function(groupName, index) {
+            if (tableGroupValid(groupName, index)) {
+                $table.tableReset();
+
+                var item = $scope.backupItem;
+
+                if (index < 0) {
+                    var newGroup = {name: groupName};
+
+                    if (item.groups)
+                        item.groups.push(newGroup);
+                    else
+                        item.groups = [newGroup];
+                }
+                else
+                    item.groups[index].name = groupName;
+            }
+        };
+
+        $scope.tableGroupNewItem = function(groupIndex) {
+            var groupName = $scope.backupItem.groups[groupIndex].name;
+
+            return $table.tableNewItem({model: groupName});
+        };
+
+        $scope.tableGroupNewItemActive = function(groupIndex) {
+            var groupName = $scope.backupItem.groups[groupIndex].name;
+
+            return $table.tableNewItemActive({model: groupName});
+        };
+
+        $scope.tableGroupItemEditing = function (groupIndex, index) {
+            var groups = $scope.backupItem.groups;
+
+            if (groups)
+                return $table.tableEditing({model: groups[groupIndex].name}, index);
+
+            return false;
+        };
+
+        $scope.tableGroupItemStartEdit = function(groupIndex, index) {
+            var groups = $scope.backupItem.groups;
+
+            $table.tableState(groups[groupIndex].name, index);
+
+            return groups[groupIndex].fields[index];
+        };
+
+        $scope.tableGroupItemSaveVisible = function(fieldName, className) {
+            return $common.isNonEmpty(fieldName) && $common.isNonEmpty(className);
+        };
+
+        $scope.tableGroupItemSave = function(fieldName, className, direction, groupIndex, index) {
+            $table.tableReset();
+
+            var group = $scope.backupItem.groups[groupIndex];
+
+            if (index < 0) {
+                var newGroupItem = {name: fieldName, className: className, direction: direction};
+
+                if (group.fields)
+                    group.fields.push(newGroupItem);
+                else
+                    group.fields = [newGroupItem];
+            }
+            else {
+                var groupItem = group.fields[index];
+
+                groupItem.name = fieldName;
+                groupItem.className = className;
+                groupItem.direction = direction;
+            }
+        };
+
         $scope.tableRemoveGroupItem = function(group, index) {
-            console.log("group: " + group.name);
-            console.log("index: " + index);
+            $table.tableReset();
+
+            group.fields.splice(index, 1);
         };
 
         $scope.selectSchema = function (idx) {

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/9499ee2e/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 e4369e4..a16318d 100644
--- a/modules/web-control-center/nodejs/public/stylesheets/style.less
+++ b/modules/web-control-center/nodejs/public/stylesheets/style.less
@@ -872,6 +872,10 @@ label {
   margin-right: 0;
 }
 
+.fa-plus {
+  cursor: pointer;
+}
+
 .fa-remove {
   color: @ignite-red;
   cursor: pointer;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/9499ee2e/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 6c81489..f45b60e 100644
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ b/modules/web-control-center/nodejs/views/includes/controls.jade
@@ -28,6 +28,9 @@ mixin ico-exclamation(mdl, err, msg)
 mixin btn-save(show, click)
     i.tipField.fa.fa-floppy-o(ng-show=show ng-click=click)
 
+mixin btn-add(click)
+    i.tipField.fa.fa-plus(ng-click=click)
+
 mixin btn-remove(click)
     i.tipField.fa.fa-remove(ng-click=click)
 
@@ -145,6 +148,16 @@ mixin table-db-field-edit(dbName, dbType, javaName, javaType)
     .input-tip
         input.form-control(type='text' ng-model=dbName placeholder='DB name')
 
+mixin table-group-item-edit(fieldName, className, direction)
+    div(style='width: 15%; float: right')
+        button.form-control(ng-model=direction bs-select data-placeholder='Sort' bs-options='item.value as item.label for item in {{sortDirections}}')
+    label.fieldSep /
+    div(style='width: 38%; float: right')
+        input.form-control(type='text' ng-model=className placeholder='Class name')
+    label.fieldSep /
+    .input-tip
+        input.form-control(type='text' ng-model=fieldName placeholder='Field name')
+
 mixin form-row
     +form-row-custom(['col-sm-2'], ['col-sm-4'])
 
@@ -246,7 +259,7 @@ mixin form-row-custom(lblClasses, fieldClasses)
                     tr.col-sm-12(ng-repeat='item in #{fieldMdl}')
                         td.col-sm-6
                             div(ng-show='!tableEditing(field, $index)')
-                                a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, field, $index)') {{$index + 1}}) {{item | compact}}(ng-click='curDbFldMeta = tableStartEdit(backupItem, field, $index); curDbName = curDbFldMeta.dbName; curDbType = curDbFldMeta.dbType; curJavaName = curDbFldMeta.javaName; curJavaType = curDbFldMeta.javaType') {{$index + 1}}) {{item.dbName}} / {{item.dbType}} / {{item.javaName}} / {{item.javaType}}
+                                a.labelFormField(ng-click='curField = tableStartEdit(backupItem, field, $index); curDbName = curField.dbName; curDbType = curField.dbType; curJavaName = curField.javaName; curJavaType = curField.javaType') {{$index + 1}}) {{item.dbName}} / {{item.dbType}} / {{item.javaName}} / {{item.javaType}}
                                 +btn-remove('tableRemove(backupItem, field, $index)')
                             div(ng-if='tableEditing(field, $index)')
                                 label.labelField {{$index + 1}})
@@ -266,18 +279,34 @@ mixin form-row-custom(lblClasses, fieldClasses)
                     tr.col-sm-12(ng-repeat='group in #{fieldMdl}')
                         td.col-sm-6
                             div
-                                div(ng-show='!tableEditing(field, $index)')
-                                    a.labelFormField(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{group.name}}
+                                .col-sm-12(ng-show='!tableEditing(field, $index)')
+                                    a.labelFormField(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curGroupName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{group.name}}
                                     +btn-remove('tableRemove(backupItem, field, $index)')
+                                    +btn-add('tableGroupNewItem($index); newDirection = "ASC"')
                                 div(ng-show='tableEditing(field, $index)')
                                     label.labelField {{$index + 1}})
-                                    +btn-save('tableGroupSaveVisible(curName)', 'tableGroupSave(field, curDbName, curDbType, curJavaName, curJavaType, $index)')
+                                    +btn-save('tableGroupSaveVisible(curGroupName)', 'tableGroupSave(curGroupName, $index)')
                                     .input-tip
-                                        input.form-control(type='text' ng-model='curName' placeholder='Index name')
-                                table.links-edit.col-sm-12(st-table='group.fields' ng-show='group.fields.length > 0')
-                                    tr(ng-repeat='groupItem in group.fields')
-                                        td
-                                            a.labelFormField('') {{$index + 1}}) {{groupItem.name}} / {{groupItem.className}} / {{groupItem.direction}}
-                                            +btn-remove('tableRemoveGroupItem(group, $index)')
+                                        input.form-control(type='text' ng-model='curGroupName' placeholder='Index name')
+                                div
+                                    table.links-edit.col-sm-12(st-table='group.fields' ng-show='group.fields.length > 0' ng-init='groupIndex = $index')
+                                        tr(ng-repeat='groupItem in group.fields')
+                                            td
+                                                div(ng-show='!tableGroupItemEditing(groupIndex, $index)')
+                                                    a.labelFormField(ng-click='curGroupItem = tableGroupItemStartEdit(groupIndex, $index); curFieldName = curGroupItem.name; curClassName = curGroupItem.className; curDirection = curGroupItem.direction') {{$index + 1}}) {{groupItem.name}} / {{groupItem.className}} / {{groupItem.direction}}
+                                                    +btn-remove('tableRemoveGroupItem(group, $index)')
+                                                div(ng-show='tableGroupItemEditing(groupIndex, $index)')
+                                                    label.labelField {{$index + 1}})
+                                                    +btn-save('tableGroupItemSaveVisible(curFieldName, curClassName)', 'tableGroupItemSave(curFieldName, curClassName, curDirection, groupIndex, $index)')
+                                                    +table-group-item-edit('curFieldName', 'curClassName', 'curDirection')
+                                    .settings-row(style='padding-left: 18px' ng-show='tableGroupNewItemActive(groupIndex)')
+                                        +btn-save('tableGroupItemSaveVisible(newFieldName, newClassName)', 'tableGroupItemSave(newFieldName, newClassName, newDirection, groupIndex, -1)')
+                                        +table-group-item-edit('newFieldName', 'newClassName', 'newDirection')
+            .settings-row(ng-show='tableNewItemActive(field)')
+                .col-sm-6
+                    +btn-save('tableGroupSaveVisible(newGroupName)', 'tableGroupSave(newGroupName, -1)')
+                    .input-tip
+                        input.form-control(type='text' ng-model='newGroupName' placeholder='Group name')
+
 
 


[41/50] [abbrv] incubator-ignite git commit: # ignite-843 moved

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/db.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/db.js b/modules/web-control-center/nodejs/db.js
deleted file mode 100644
index e34272c..0000000
--- a/modules/web-control-center/nodejs/db.js
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var config = require('./helpers/configuration-loader.js');
-
-// Mongoose for mongodb.
-var mongoose = require('mongoose'),
-    Schema = mongoose.Schema,
-    ObjectId = mongoose.Schema.Types.ObjectId,
-    passportLocalMongoose = require('passport-local-mongoose');
-
-// Connect to mongoDB database.
-mongoose.connect(config.get('mongoDB:url'), {server: {poolSize: 4}});
-
-// Define account model.
-var AccountSchema = new Schema({
-    username: String,
-    email: String,
-    lastLogin: Date,
-    admin: Boolean
-});
-
-AccountSchema.plugin(passportLocalMongoose, {usernameField: 'email', limitAttempts: true, lastLoginField: 'lastLogin',
-    usernameLowerCase: true});
-
-AccountSchema.set('toJSON', {
-    transform: function(doc, ret) {
-        return {
-            _id: ret._id,
-            email: ret.email,
-            username: ret.username,
-            admin: ret.admin,
-            lastLogin: ret.lastLogin
-        };
-    }
-});
-
-exports.Account = mongoose.model('Account', AccountSchema);
-
-// Define space model.
-exports.Space = mongoose.model('Space', new Schema({
-    name: String,
-    owner: {type: ObjectId, ref: 'Account'},
-    usedBy: [{
-        permission: {type: String, enum: ['VIEW', 'FULL']},
-        account: {type: ObjectId, ref: 'Account'}
-    }]
-}));
-
-// Define cache type metadata model.
-var CacheTypeMetadataSchema = new Schema({
-    space: {type: ObjectId, ref: 'Space'},
-    name: String,
-    kind: {type: String, enum: ['query', 'store', 'both']},
-    databaseSchema: String,
-    databaseTable: String,
-    keyType: String,
-    valueType: String,
-    keyFields: [{dbName: String, dbType: String, javaName: String, javaType: String}],
-    valueFields: [{dbName: String, dbType: String, javaName: String, javaType: String}],
-    queryFields: [{name: String, className: String}],
-    ascendingFields: [{name: String, className: String}],
-    descendingFields:  [{name: String, className: String}],
-    textFields: [String],
-    groups: [{name: String, fields: [{name: String, className: String, direction: String}]}]
-});
-
-exports.CacheTypeMetadata = mongoose.model('CacheTypeMetadata', CacheTypeMetadataSchema);
-
-// Define cache model.
-var CacheSchema = new Schema({
-    space: {type: ObjectId, ref: 'Space'},
-    name: String,
-    mode: {type: String, enum: ['PARTITIONED', 'REPLICATED', 'LOCAL']},
-    atomicityMode: {type: String, enum: ['ATOMIC', 'TRANSACTIONAL']},
-
-    backups: Number,
-    memoryMode: {type: String, enum: ['ONHEAP_TIERED', 'OFFHEAP_TIERED', 'OFFHEAP_VALUES']},
-    offHeapMaxMemory: Number,
-    startSize: Number,
-    swapEnabled: Boolean,
-
-    evictionPolicy: {
-        kind: {type: String, enum: ['LRU', 'RND', 'FIFO', 'Sorted']},
-        LRU: {
-            batchSize: Number,
-            maxMemorySize: Number,
-            maxSize: Number
-        },
-        RND: {
-            maxSize: Number
-        },
-        FIFO: {
-            batchSize: Number,
-            maxMemorySize: Number,
-            maxSize: Number
-        },
-        SORTED: {
-            batchSize: Number,
-            maxMemorySize: Number,
-            maxSize: Number
-        }
-    },
-
-    rebalanceMode: {type: String, enum: ['SYNC', 'ASYNC', 'NONE']},
-    rebalanceThreadPoolSize: Number,
-    rebalanceBatchSize: Number,
-    rebalanceOrder: Number,
-    rebalanceDelay: Number,
-    rebalanceTimeout: Number,
-    rebalanceThrottle: Number,
-
-    cacheStoreFactory: {
-        kind: {
-            type: String,
-            enum: ['CacheJdbcPojoStoreFactory', 'CacheJdbcBlobStoreFactory', 'CacheHibernateBlobStoreFactory']
-        },
-        CacheJdbcPojoStoreFactory: {
-            dataSourceBean: String,
-            dialect: {
-                type: String,
-                enum: ['Oracle', 'DB2', 'SQLServer', 'MySQL', 'PosgreSQL', 'H2']
-            }
-        },
-        CacheJdbcBlobStoreFactory: {
-            user: String,
-            dataSourceBean: String,
-            initSchema: Boolean,
-            createTableQuery: String,
-            loadQuery: String,
-            insertQuery: String,
-            updateQuery: String,
-            deleteQuery: String
-        },
-        CacheHibernateBlobStoreFactory: {
-            hibernateProperties: [String]
-        }
-    },
-    loadPreviousValue: Boolean,
-    readThrough: Boolean,
-    writeThrough: Boolean,
-
-    writeBehindEnabled: Boolean,
-    writeBehindBatchSize: Number,
-    writeBehindFlushSize: Number,
-    writeBehindFlushFrequency: Number,
-    writeBehindFlushThreadCount: Number,
-
-    invalidate: Boolean,
-    defaultLockTimeout: Number,
-    transactionManagerLookupClassName: String,
-
-    sqlEscapeAll: Boolean,
-    sqlOnheapRowCacheSize: Number,
-    longQueryWarningTimeout: Number,
-    indexedTypes: [{keyClass: String, valueClass: String}],
-    sqlFunctionClasses: [String],
-    statisticsEnabled: Boolean,
-    managementEnabled: Boolean,
-    readFromBackup: Boolean,
-    copyOnRead: Boolean,
-    maxConcurrentAsyncOperations: Number,
-    nearConfiguration: {
-        nearStartSize: Number,
-        nearEvictionPolicy: {
-            kind: {type: String, enum: ['LRU', 'RND', 'FIFO', 'Sorted']},
-            LRU: {
-                batchSize: Number,
-                maxMemorySize: Number,
-                maxSize: Number
-            },
-            RND: {
-                maxSize: Number
-            },
-            FIFO: {
-                batchSize: Number,
-                maxMemorySize: Number,
-                maxSize: Number
-            },
-            SORTED: {
-                batchSize: Number,
-                maxMemorySize: Number,
-                maxSize: Number
-            }
-        }
-    }
-});
-
-exports.Cache = mongoose.model('Cache', CacheSchema);
-
-// Define cluster schema.
-var ClusterSchema = new Schema({
-    space: {type: ObjectId, ref: 'Space'},
-    name: String,
-    discovery: {
-        kind: {type: String, enum: ['Vm', 'Multicast', 'S3', 'Cloud', 'GoogleStorage', 'Jdbc', 'SharedFs']},
-        Vm: {
-            addresses: [String]
-        },
-        Multicast: {
-            multicastGroup: String,
-            multicastPort: Number,
-            responseWaitTime: Number,
-            addressRequestAttempts: Number,
-            localAddress: String
-        },
-        S3: {
-            bucketName: String
-        },
-        Cloud: {
-            credential: String,
-            credentialPath: String,
-            identity: String,
-            provider: String,
-            regions: [String],
-            zones:  [String]
-        },
-        GoogleStorage: {
-            projectName: String,
-            bucketName: String,
-            serviceAccountP12FilePath: String,
-            addrReqAttempts: String
-        },
-        Jdbc: {
-            initSchema: Boolean
-        },
-        SharedFs: {
-            path: String
-        }
-    },
-    atomicConfiguration: {
-        backups: Number,
-        cacheMode: {type: String, enum: ['LOCAL', 'REPLICATED', 'PARTITIONED']},
-        atomicSequenceReserveSize: Number
-    },
-    caches: [{type: ObjectId, ref: 'Cache'}],
-    cacheSanityCheckEnabled: Boolean,
-    clockSyncSamples: Number,
-    clockSyncFrequency: Number,
-    deploymentMode: {type: String, enum: ['PRIVATE', 'ISOLATED', 'SHARED', 'CONTINUOUS']},
-    discoveryStartupDelay: Number,
-    igfsThreadPoolSize: Number,
-    includeEventTypes: [{
-        type: String, enum: ['EVTS_CHECKPOINT', 'EVTS_DEPLOYMENT', 'EVTS_ERROR', 'EVTS_DISCOVERY',
-            'EVTS_JOB_EXECUTION', 'EVTS_TASK_EXECUTION', 'EVTS_CACHE', 'EVTS_CACHE_REBALANCE', 'EVTS_CACHE_LIFECYCLE',
-            'EVTS_CACHE_QUERY', 'EVTS_SWAPSPACE', 'EVTS_IGFS']
-    }],
-    managementThreadPoolSize: Number,
-    marshaller: {
-        kind: {type: String, enum: ['OptimizedMarshaller', 'JdkMarshaller']},
-        OptimizedMarshaller: {
-            poolSize: Number,
-            requireSerializable: Boolean
-        }
-    },
-    marshalLocalJobs: Boolean,
-    marshallerCacheKeepAliveTime: Number,
-    marshallerCacheThreadPoolSize: Number,
-    metricsExpireTime: Number,
-    metricsHistorySize: Number,
-    metricsLogFrequency: Number,
-    metricsUpdateFrequency: Number,
-    networkTimeout: Number,
-    networkSendRetryDelay: Number,
-    networkSendRetryCount: Number,
-    peerClassLoadingEnabled: Boolean,
-    peerClassLoadingLocalClassPathExclude: [String],
-    peerClassLoadingMissedResourcesCacheSize: Number,
-    peerClassLoadingThreadPoolSize: Number,
-    publicThreadPoolSize: Number,
-    segmentCheckFrequency: Number,
-    segmentationPolicy: {type: String, enum: ['RESTART_JVM', 'STOP', 'NOOP']},
-    allSegmentationResolversPassRequired: Boolean,
-    segmentationResolveAttempts: Number,
-    swapSpaceSpi: {
-        kind: {type: String, enum: ['FileSwapSpaceSpi']},
-        FileSwapSpaceSpi: {
-            baseDirectory: String,
-            readStripesNumber: Number,
-            maximumSparsity: Number,
-            maxWriteQueueSize: Number,
-            writeBufferSize: Number
-        }
-    },
-    systemThreadPoolSize: Number,
-    timeServerPortBase: Number,
-    timeServerPortRange: Number,
-    transactionConfiguration: {
-        defaultTxConcurrency: {type: String, enum: ['OPTIMISTIC', 'PESSIMISTIC']},
-        transactionIsolation: {type: String, enum: ['READ_COMMITTED', 'REPEATABLE_READ', 'SERIALIZABLE']},
-        defaultTxTimeout: Number,
-        pessimisticTxLogLinger: Number,
-        pessimisticTxLogSize: Number,
-        txSerializableEnabled: Boolean
-    },
-    waitForSegmentOnStart: Boolean
-});
-
-// Define cluster model.
-exports.Cluster = mongoose.model('Cluster', ClusterSchema);
-
-// Define persistence schema.
-var PersistenceSchema = new Schema({
-    space: {type: ObjectId, ref: 'Space'},
-    name: String,
-    dbType: {type: String, enum: ['oracle', 'db2', 'mssql', 'postgre', 'mysql', 'h2']},
-    dbName: String,
-    host: String,
-    user: String,
-    tables: [{
-        use: Boolean,
-        schemaName: String,
-        tableName: String,
-        keyClass: String,
-        valueClass: String,
-        columns: [{
-            use: Boolean,
-            pk: Boolean,
-            ak: Boolean,
-            notNull: Boolean,
-            dbName: String,
-            dbType: Number,
-            javaName: String,
-            javaType: String
-        }]
-    }]
-});
-
-// Define persistence model.
-exports.Persistence = mongoose.model('Persistence', PersistenceSchema);
-
-exports.upsert = function (model, data, cb) {
-    if (data._id) {
-        var id = data._id;
-
-        delete data._id;
-
-        model.findOneAndUpdate({_id: id}, data, cb);
-    }
-    else
-        new model(data).save(cb);
-};
-
-exports.mongoose = mongoose;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/helpers/configuration-loader.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/helpers/configuration-loader.js b/modules/web-control-center/nodejs/helpers/configuration-loader.js
deleted file mode 100644
index 6dbb577..0000000
--- a/modules/web-control-center/nodejs/helpers/configuration-loader.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var config = require('nconf');
-
-config.file({'file': 'config/default.json'});
-
-module.exports = config;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/helpers/data-structures.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/helpers/data-structures.js b/modules/web-control-center/nodejs/helpers/data-structures.js
deleted file mode 100644
index 2462708..0000000
--- a/modules/web-control-center/nodejs/helpers/data-structures.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-eventGroups = {
-    EVTS_CHECKPOINT: ['EVT_CHECKPOINT_SAVED', 'EVT_CHECKPOINT_LOADED', 'EVT_CHECKPOINT_REMOVED'],
-    EVTS_DEPLOYMENT: ['EVT_CLASS_DEPLOYED', 'EVT_CLASS_UNDEPLOYED', 'EVT_CLASS_DEPLOY_FAILED', 'EVT_TASK_DEPLOYED',
-        'EVT_TASK_UNDEPLOYED', 'EVT_TASK_DEPLOY_FAILED'],
-    EVTS_ERROR: ['EVT_JOB_TIMEDOUT', 'EVT_JOB_FAILED', 'EVT_JOB_FAILED_OVER', 'EVT_JOB_REJECTED', 'EVT_JOB_CANCELLED',
-        'EVT_TASK_TIMEDOUT', 'EVT_TASK_FAILED', 'EVT_CLASS_DEPLOY_FAILED', 'EVT_TASK_DEPLOY_FAILED',
-        'EVT_TASK_DEPLOYED', 'EVT_TASK_UNDEPLOYED', 'EVT_CACHE_REBALANCE_STARTED', 'EVT_CACHE_REBALANCE_STOPPED'],
-    EVTS_DISCOVERY: ['EVT_NODE_JOINED', 'EVT_NODE_LEFT', 'EVT_NODE_FAILED', 'EVT_NODE_SEGMENTED',
-        'EVT_CLIENT_NODE_DISCONNECTED', 'EVT_CLIENT_NODE_RECONNECTED'],
-    EVTS_JOB_EXECUTION: ['EVT_JOB_MAPPED', 'EVT_JOB_RESULTED', 'EVT_JOB_FAILED_OVER', 'EVT_JOB_STARTED',
-        'EVT_JOB_FINISHED', 'EVT_JOB_TIMEDOUT', 'EVT_JOB_REJECTED', 'EVT_JOB_FAILED', 'EVT_JOB_QUEUED',
-        'EVT_JOB_CANCELLED'],
-    EVTS_TASK_EXECUTION: ['EVT_TASK_STARTED', 'EVT_TASK_FINISHED', 'EVT_TASK_FAILED', 'EVT_TASK_TIMEDOUT',
-        'EVT_TASK_SESSION_ATTR_SET', 'EVT_TASK_REDUCED'],
-    EVTS_CACHE: ['EVT_CACHE_ENTRY_CREATED', 'EVT_CACHE_ENTRY_DESTROYED', 'EVT_CACHE_OBJECT_PUT',
-        'EVT_CACHE_OBJECT_READ', 'EVT_CACHE_OBJECT_REMOVED', 'EVT_CACHE_OBJECT_LOCKED', 'EVT_CACHE_OBJECT_UNLOCKED',
-        'EVT_CACHE_OBJECT_SWAPPED', 'EVT_CACHE_OBJECT_UNSWAPPED', 'EVT_CACHE_OBJECT_EXPIRED'],
-    EVTS_CACHE_REBALANCE: ['EVT_CACHE_REBALANCE_STARTED', 'EVT_CACHE_REBALANCE_STOPPED',
-        'EVT_CACHE_REBALANCE_PART_LOADED', 'EVT_CACHE_REBALANCE_PART_UNLOADED', 'EVT_CACHE_REBALANCE_OBJECT_LOADED',
-        'EVT_CACHE_REBALANCE_OBJECT_UNLOADED', 'EVT_CACHE_REBALANCE_PART_DATA_LOST'],
-    EVTS_CACHE_LIFECYCLE: ['EVT_CACHE_STARTED', 'EVT_CACHE_STOPPED', 'EVT_CACHE_NODES_LEFT'],
-    EVTS_CACHE_QUERY: ['EVT_CACHE_QUERY_EXECUTED', 'EVT_CACHE_QUERY_OBJECT_READ'],
-    EVTS_SWAPSPACE: ['EVT_SWAP_SPACE_CLEARED', 'EVT_SWAP_SPACE_DATA_REMOVED', 'EVT_SWAP_SPACE_DATA_READ',
-        'EVT_SWAP_SPACE_DATA_STORED', 'EVT_SWAP_SPACE_DATA_EVICTED'],
-    EVTS_IGFS: ['EVT_IGFS_FILE_CREATED', 'EVT_IGFS_FILE_RENAMED', 'EVT_IGFS_FILE_DELETED', 'EVT_IGFS_FILE_OPENED_READ',
-        'EVT_IGFS_FILE_OPENED_WRITE', 'EVT_IGFS_FILE_CLOSED_WRITE', 'EVT_IGFS_FILE_CLOSED_READ', 'EVT_IGFS_FILE_PURGED',
-        'EVT_IGFS_META_UPDATED', 'EVT_IGFS_DIR_CREATED', 'EVT_IGFS_DIR_RENAMED', 'EVT_IGFS_DIR_DELETED']
-};
-
-jdbcTypes = {
-    BIT: {value: "BIT", code: -7, label: "BIT"},
-    TINYINT: {value: "TINYINT", code: -6, label: "TINYINT"},
-    SMALLINT: {value: "SMALLINT", code: 5, label: "SMALLINT"},
-    INTEGER: {value: "INTEGER", code: 4, label: "INTEGER"},
-    BIGINT: {value: "BIGINT", code: -5, label: "BIGINT"},
-    FLOAT: {value: "FLOAT", code: 6, label: "FLOAT"},
-    REAL: {value: "REAL", code: 7, label: "REAL"},
-    DOUBLE: {value: "DOUBLE", code: 8, label: "DOUBLE"},
-    NUMERIC: {value: "NUMERIC", code: 2, label: "NUMERIC"},
-    DECIMAL: {value: "DECIMAL", code: 3, label: "DECIMAL"},
-    CHAR: {value: "CHAR", code: 1, label: "CHAR"},
-    VARCHAR: {value: "VARCHAR", code: 12, label: "VARCHAR"},
-    DATE: {value: "DATE", code: 91, label: "DATE"},
-    TIME: {value: "TIME", code: 92, label: "TIME"},
-    TIMESTAMP: {value: "TIMESTAMP", code: 93, label: "TIMESTAMP"},
-    BINARY: {value: "BINARY", code: -2, label: "BINARY"}
-};
-
-javaTypes = {
-    INTEGER: {value: "java.lang.Integer", label: "Integer"},
-    LONG: {value: "java.lang.Long", label: "Long"},
-    BIGDECIMAL: {value: "java.math.BigDecimal", label: "BigDecimal"},
-    FLOAT: {value: "java.lang.Float", label: "Float"},
-    DOUBLE: {value: "java.lang.Double", label: "Double"},
-    STRING: {value: "java.lang.String", label: "String"},
-    BOOLEAN: {value: "java.lang.Boolean", label: "Boolean"},
-    BYTE_ARRAY: {value: "byte[]", label: "byte[]"},
-    DATE: {value: "java.sql.Date", label: "Date"},
-    TIME: {value: "java.sql.Time", label: "Time"},
-    TIMESTAMP: {value: "java.sql.Timestamp", label: "Timestamp"}
-};
-
-if (typeof window === 'undefined') {
-    exports.eventGroups = eventGroups;
-    exports.jdbcTypes = jdbcTypes;
-    exports.javaTypes = javaTypes;
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/package.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/package.json b/modules/web-control-center/nodejs/package.json
deleted file mode 100644
index 5e5463c..0000000
--- a/modules/web-control-center/nodejs/package.json
+++ /dev/null
@@ -1,50 +0,0 @@
-{
-  "name": "ignite-web-control-center",
-  "version": "1.0.0",
-  "description": "Web application for configuration, monitoring Ignite Cluster",
-  "private": true,
-  "scripts": {
-    "start": "node ./bin/www"
-  },
-  "author": "",
-  "contributors": [
-    {
-      "name": "",
-      "email": ""
-    }
-  ],
-  "license": "Apache-2.0",
-  "keywords": "grid",
-  "homepage": "https://ignite.incubator.apache.org/",
-  "engines": {
-    "node": ">=0.12.4"
-  },
-  "dependencies": {
-    "angular-ui-ace": "^0.2.3",
-    "archiver": "^0.14.4",
-    "body-parser": "~1.12.0",
-    "connect-flash": "^0.1.1",
-    "connect-mongo": "^0.8.1",
-    "cookie-parser": "~1.3.4",
-    "debug": "~2.1.1",
-    "express": "~4.12.2",
-    "express-session": "^1.11.1",
-    "jade": "~1.9.2",
-    "less-middleware": "1.0.x",
-    "lodash": "3.10.0",
-    "mongoose": "^4.0.2",
-    "nconf": "^0.7.1",
-    "passport": "^0.2.1",
-    "passport-local": "^1.0.0",
-    "passport-local-mongoose": "^1.0.0",
-    "pg": "^4.4.0",
-    "serve-favicon": "~2.2.0",
-    "util": "^0.10.3"
-  },
-  "devDependencies": {
-    "morgan": "~1.5.1",
-    "supertest": "^1.0.1",
-    "mocha": "~2.0.1",
-    "should": "~3.1.3"
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/public/favicon.ico
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/public/favicon.ico b/modules/web-control-center/nodejs/public/favicon.ico
deleted file mode 100644
index 74ec626..0000000
Binary files a/modules/web-control-center/nodejs/public/favicon.ico and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/public/images/docker.png
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/public/images/docker.png b/modules/web-control-center/nodejs/public/images/docker.png
deleted file mode 100644
index 7ec3aef..0000000
Binary files a/modules/web-control-center/nodejs/public/images/docker.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/public/images/java.png
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/public/images/java.png b/modules/web-control-center/nodejs/public/images/java.png
deleted file mode 100644
index ddb3b8e..0000000
Binary files a/modules/web-control-center/nodejs/public/images/java.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/public/images/logo.png
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/public/images/logo.png b/modules/web-control-center/nodejs/public/images/logo.png
deleted file mode 100644
index c3577c5..0000000
Binary files a/modules/web-control-center/nodejs/public/images/logo.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/public/images/xml.png
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/public/images/xml.png b/modules/web-control-center/nodejs/public/images/xml.png
deleted file mode 100644
index 029065e..0000000
Binary files a/modules/web-control-center/nodejs/public/images/xml.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/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
deleted file mode 100644
index 4900581..0000000
--- a/modules/web-control-center/nodejs/public/stylesheets/style.less
+++ /dev/null
@@ -1,1172 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@logo-path: "https://www.filepicker.io/api/file/QagunjDGRFul2JgNCAli";
-@input-height: 28px;
-@ignite-red: #ec1c24;
-@ignite-block-callout-background: #f3f8f3;
-@ignite-block-callout: #50af51;
-
-hr {
-  margin-top: 20px;
-  margin-bottom: 20px;
-}
-
-.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;
-  &.ng-enter {
-    opacity: 0;
-    &.ng-enter-active {
-      opacity: .5;
-    }
-  }
-  &.ng-leave {
-    opacity: .5;
-    &.ng-leave-active {
-      opacity: 0;
-    }
-  }
-}
-
-.modal.center .modal-dialog {
-  position: fixed;
-  top: 50%;
-  left: 50%;
-  -webkit-transform: translateX(-50%) translateY(-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, 255, 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: 5px 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: 22px;
-}
-
-.theme-line .btn-primary {
-  border: 0 none;
-  background-color: @ignite-red;
-}
-
-.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: 5px solid #ddd;
-}
-
-.theme-line .main-content .nav-horizontal a.active {
-  border-bottom: 5px solid #888;
-}
-
-.theme-line .navbar-nav, .theme-line .sidebar-nav {
-  ul li > a.active {
-    cursor: default;
-    pointer-events: none;
-  }
-}
-
-.theme-line .sidebar-nav {
-  color: #474a54;
-  padding-bottom: 30px;
-
-  ul {
-    padding: 0;
-    list-style: none;
-    font-size: 14px;
-    margin: 3px 0 0;
-    li {
-      color: #666;
-      line-height: @input-height;
-
-      span.fa-stack {
-        margin-right: 5px;
-        font-size: 12px;
-        height: 26px;
-      }
-
-      a {
-        font-size: 18px;
-        color: #666;
-        position: relative;
-        white-space: nowrap;
-        overflow: hidden;
-        -o-text-overflow: ellipsis;
-        text-overflow: ellipsis;
-      }
-    }
-  }
-}
-
-.theme-line .sidebar-nav ul li a:hover {
-  text-decoration: none;
-}
-
-.theme-line .select,
-.theme-line .typeahead {
-  li a {
-    color: #666;
-    background-color: transparent;
-  }
-
-  li a:hover {
-    color: @ignite-red;
-  }
-
-  .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: 5px;
-  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;
-}
-
-.header .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: @ignite-red;
-}
-
-.theme-line .navbar-nav {
-  color: #888;
-}
-
-.theme-line .navbar-nav a {
-  color: #bbb;
-}
-
-.theme-line header a.btn {
-  background-color: @ignite-red;
-}
-
-.theme-line header a.btn:hover {
-  background-color: #950d12;
-}
-
-.theme-line header .navbar-nav .tt-cursor {
-  background-color: @ignite-red;
-}
-
-.theme-line header .navbar-nav a:hover, .theme-line header .navbar-nav .open > a {
-  color: @ignite-red;
-}
-
-.theme-line .navbar-nav .active a {
-  //font-weight: bold;
-  color: @ignite-red;
-}
-
-.theme-line .navbar-nav .active a:hover {
-  color: #950d12;
-}
-
-.theme-line .main-links .links a:hover {
-  color: @ignite-red;
-}
-
-.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: @ignite-red;
-}
-
-.theme-line .sidebar-nav ul li a.active {
-  color: @ignite-red;
-}
-
-.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: @ignite-red;
-  color: @ignite-red;
-}
-
-.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 strong, .theme-line #versions-list li a.active .current, .theme-line #versions-list li a:active .current {
-  color: @ignite-red;
-}
-
-.theme-line header .navbar-nav a {
-  font-size: 18px;
-}
-
-.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: @ignite-red;
-  border-color: @ignite-red;
-}
-
-.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;
-  margin-bottom: 10px;
-}
-
-.submit-vote.submit-vote-parent.voted a.submit-vote-button, .submit-vote.submit-vote-parent a.submit-vote-button:hover {
-  background-color: @ignite-red;
-}
-
-div.submit-vote.submit-vote-parent.voted a.submit-vote-button:hover {
-  background-color: #950d12;
-}
-
-a, .link .title {
-  color: @ignite-red;
-}
-
-a:hover, .link:hover .title {
-  color: #950d12;
-}
-
-.header h1.navbar-brand a {
-  background-image: url("@{logo-path}");
-}
-
-.header h1.navbar-brand {
-  width: 96px;
-}
-
-.block-edit-parameters {
-  text-align: right;
-  padding-bottom: 5px;
-}
-
-.container-footer {
-  margin-top: 20px;
-}
-
-/* Modal */
-.modal {
-  display: block;
-  overflow: hidden;
-}
-
-.modal .close {
-  position: absolute;
-  top: 10px;
-  right: 10px;
-  float: none;
-}
-
-// Close icon
-.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: 15px;
-  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 .modal-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("@{logo-path}");
-}
-
-.block-display-image img {
-  max-width: 100%;
-  max-height: 450px;
-  margin: auto;
-  display: block;
-}
-
-.greedy {
-  min-height: 200px;
-  height: ~"calc(100vh - 290px)";
-}
-
-@media (min-width: 768px) {
-  .navbar-nav > li > a {
-    padding-top: 18px;
-    padding-bottom: 10px;
-  }
-}
-
-.details-row {
-  padding: 0 10px;
-}
-
-.details-row, .settings-row {
-  display: block;
-  margin: 10px 0;
-
-  label.table-header {
-    line-height: @input-height;
-  }
-
-  [class*="col-"] {
-    display: inline-block;
-    vertical-align: middle;
-    float: none;
-
-    padding-left: 0 !important;
-    padding-right: 0 !important;
-  }
-
-  input[type="checkbox"] {
-    line-height: 20px;
-    margin-right: 5px;
-  }
-
-  .checkbox label {
-    line-height: 20px;
-    vertical-align: middle;
-  }
-}
-
-button {
-  margin-right: 5px;
-}
-
-h1,
-h2,
-h3 {
-  user-select: none;
-  font-weight: normal;
-  /* Makes the vertical size of the text the same for all fonts. */
-  line-height: 1;
-}
-
-h3 {
-  color: black;
-  font-size: 1.2em;
-  margin-top: 0;
-  margin-bottom: 1.5em;
-}
-
-table tr:hover {
-  cursor: pointer;
-}
-
-.btn {
-  padding: 3px 6px;
-}
-
-button .caret, .btn .caret {
-  float: right;
-  margin-left: 5px;
-  margin-top: 7px;
-}
-
-.base-control {
-  text-align: left;
-  padding: 3px 3px;
-  height: @input-height;
-}
-
-.form-control:extend(.base-control all) {
-  display: inline-block;
-
-  button {
-    text-align: left;
-  }
-}
-
-.theme-line .panel-heading {
-  padding: 10px 10px;
-  margin: 0;
-
-  h3 {
-    margin-bottom: 0;
-  }
-
-  h3 > a {
-    color: black;
-  }
-}
-
-.theme-line .panel-title {
-  a {
-    color: @ignite-red;
-  }
-
-  h3 {
-    margin-bottom: 20px;
-  }
-}
-
-.theme-line .panel-body {
-  padding: 10px 20px;
-}
-
-.theme-line .main-content a.customize {
-  margin-left: 5px;
-  color: @ignite-red;
-}
-
-.theme-line .panel-collapse {
-  margin: 0;
-}
-
-.theme-line .links table {
-  display: table;
-  table-layout: fixed;
-
-  td {
-    padding-left: 18px;
-  }
-
-  .active a {
-    color: @ignite-red;
-    font-weight: bold;
-  }
-
-  a:hover {
-    color: #950d12;
-  }
-
-  a {
-    color: #666;
-  }
-}
-
-.theme-line table.links-edit:extend(.theme-line .links table all) {
-  margin-top: 5px;
-  margin-bottom: 5px;
-
-  label {
-    line-height: @input-height;
-    color: #666;
-  }
-}
-
-.theme-line table.links-edit-details:extend(.theme-line .links table all) {
-  margin-bottom: 10px;
-
-  label {
-    line-height: @input-height;
-    color: #666;
-  }
-
-  td {
-    padding: 0;
-
-    .input-tip {
-      padding: 0;
-    }
-  }
-}
-
-.theme-line table.admin {
-  tr:hover {
-    cursor: default;
-  }
-
-  thead > tr th.header {
-    padding: 0 0 10px;
-
-    div {
-      padding: 0
-    }
-  }
-
-  margin-bottom: 10px;
-
-  label {
-    line-height: @input-height;
-    color: #666;
-  }
-
-  thead > tr th, td {
-    padding: 10px 10px;
-
-    .input-tip {
-      padding: 0;
-    }
-  }
-
-  tfoot > tr > td {
-    padding: 0;
-
-    .pagination {
-      margin: 10px 0;
-
-      > .active > a {
-        color: @ignite-red;
-        font-weight: bold;
-        border-color: #ddd;
-        background-color: #eee;
-      }
-    }
-  }
-}
-
-.panel-title a {
-  font-size: 14px;
-}
-
-.panel-details {
-  margin-top: 10px;
-
-  padding: 0;
-
-  border-radius: 5px;
-  border: thin dotted lightgrey;
-}
-
-.tooltip.right .tooltip-arrow {
-  border-right-color: @ignite-red;
-}
-
-.tooltip > .tooltip-inner {
-  max-width: 400px;
-  text-align: left;
-  background-color: @ignite-red;
-}
-
-label {
-  font-weight: normal;
-  margin-bottom: 0;
-}
-
-.form-horizontal .checkbox {
-  padding-top: 0;
-}
-
-.input-tip {
-  display: block;
-  overflow: hidden;
-}
-
-.labelField {
-  float: left;
-  margin-right: 5px;
-}
-
-.labelFormField {
-  float: left;
-  line-height: @input-height;
-}
-
-.form-horizontal .form-group {
-  margin: 0;
-}
-
-.form-horizontal .has-feedback .form-control-feedback {
-  right: 0;
-}
-
-.tipField {
-  float: right;
-  line-height: @input-height;
-  margin-left: 5px;
-}
-
-.tipLabel {
-  font-size: 14px;
-  margin-left: 5px;
-}
-
-.fieldSep {
-  float: right;
-  line-height: @input-height;
-  margin: 0 5px;
-}
-
-.fieldButton {
-  float: right;
-  margin-left: 5px;
-  margin-right: 0;
-}
-
-.fa-plus {
-  cursor: pointer;
-}
-
-.fa-remove {
-  color: @ignite-red;
-  cursor: pointer;
-}
-
-.fa-floppy-o {
-  cursor: pointer;
-}
-
-.fa-arrow-up {
-  cursor: pointer;
-}
-
-.fa-arrow-down {
-  cursor: pointer;
-}
-
-label.required:after {
-  color: @ignite-red;
-  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
-}
-
-//  Summary page
-#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, button.ng-dirty.ng-invalid {
-  border-color: @ignite-red;
-
-  :focus {
-    border-color: @ignite-red;
-  }
-}
-
-.form-control-feedback {
-  display: inline-block;
-  color: @ignite-red;
-  right: 18px;
-  line-height: @input-height;
-  pointer-events: initial;
-}
-
-.syntaxhighlighter {
-  padding: 10px 5px;
-  border-radius: 6px;
-}
-
-.theme-line table.links-edit-small-padding:extend(.theme-line .links table all) {
-  label {
-    line-height: @input-height;
-    color: #666;
-  }
-
-  a {
-    line-height: @input-height;
-  }
-
-  input[type="checkbox"] {
-    line-height: 20px;
-    margin-right: 5px;
-  }
-
-  .checkbox label {
-    line-height: 20px;
-    vertical-align: middle;
-  }
-
-  th {
-    text-align: center;
-  }
-
-  td {
-    padding-left: 10px;
-  }
-
-  margin-top: 10px;
-}
-
-.configBox .nav > li > a {
-  padding: 5px 5px;
-}
-
-.viewedUser {
-  position: absolute;
-  width: 100%;
-  left: 0;
-
-  text-align: center;
-
-  margin-top: -15px;
-
-  background-color: #f8d5d8;
-}
-
-a {
-  cursor: pointer;
-}
-
-.st-sort-ascent:after {
-  content: '\25B2';
-}
-
-.st-sort-descent:after {
-  content: '\25BC';
-}
-
-.panel {
-  margin-bottom: 0;
-}
-
-.panel-group {
-  margin-bottom: 0;
-}
-
-.panel-group .panel + .panel {
-  margin-top: 20px;
-}
-
-.margin-top-dflt {
-  margin-top: 10px;
-}
-
-.margin-bottom-dflt {
-  margin-bottom: 10px;
-}
-
-.margin-dflt {
-  margin-top: 10px;
-  margin-bottom: 10px;
-}
-
-.padding-top-dflt {
-  padding-top: 10px;
-}
-
-.padding-bottom-dflt {
-  padding-bottom: 10px;
-}
-
-.padding-dflt {
-  padding-top: 10px;
-  padding-bottom: 10px;
-}
-
-.theme-line .panel-title h3 {
-  margin-top: 20px;
-  margin-bottom: 20px;
-}
-
-.block-callout-parent {
-  background-color: @ignite-block-callout-background;
-  overflow: hidden;
-}
-
-.block-callout {
-  background-color: @ignite-block-callout-background;
-  display: inline-block;
-  vertical-align: top;
-  width: 50%;
-
-  i {
-    padding: 10px 5px 0 10px;
-    color: @ignite-block-callout;
-  }
-
-  ul {
-    padding-left: 20px;
-    margin-bottom: 0;
-  }
-
-  p {
-    padding: 5px 0 10px 20px;
-    margin: 0;
-  }
-
-  label {
-    font-weight: bold;
-    color: @ignite-block-callout;
-  }
-}
-
-.block-callout-border {
-  border-left: 5px solid;
-  border-color: @ignite-block-callout;
-}
-
-.labelHeader {
-  font-weight: bold;
-}
-
-.ace_editor, #ace_document {
-  width: 100%;
-  height: 400px;
-}
-
-

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/routes/admin.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/admin.js b/modules/web-control-center/nodejs/routes/admin.js
deleted file mode 100644
index 5af72f7..0000000
--- a/modules/web-control-center/nodejs/routes/admin.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var router = require('express').Router();
-var db = require('../db');
-
-router.get('/', function (req, res) {
-    res.render('settings/admin');
-});
-
-/**
- * Get list of user accounts.
- */
-router.post('/list', function (req, res) {
-    db.Account.find({}).sort('username').exec(function (err, users) {
-        if (err)
-            return res.status(500).send(err.message);
-
-        res.json(users);
-    });
-});
-
-router.post('/remove', function (req, res) {
-    var userId = req.body.userId;
-
-    db.Account.findByIdAndRemove(userId, function (err) {
-        if (err)
-            return res.status(500).send(err);
-
-        res.sendStatus(200);
-    });
-});
-
-router.post('/save', function (req, res) {
-    var userId = req.body.userId;
-    var adminFlag = req.body.adminFlag;
-
-    db.Account.findByIdAndUpdate(userId, {admin: adminFlag}, function (err) {
-        if (err)
-            return res.status(500).send(err.message);
-
-        res.sendStatus(200);
-    });
-});
-
-router.get('/become', function (req, res) {
-    var viewedUserId = req.query.viewedUserId;
-
-    if (!viewedUserId) {
-        req.session.viewedUser = null;
-
-        return res.redirect('/admin');
-    }
-
-    db.Account.findById(viewedUserId).exec(function (err, viewedUser) {
-        if (err)
-            return res.sendStatus(404);
-
-        req.session.viewedUser = viewedUser;
-
-        res.redirect('/');
-    })
-});
-
-module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/routes/caches.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/caches.js b/modules/web-control-center/nodejs/routes/caches.js
deleted file mode 100644
index 3fefd37..0000000
--- a/modules/web-control-center/nodejs/routes/caches.js
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var router = require('express').Router();
-var db = require('../db');
-
-/* GET caches page. */
-router.get('/', function (req, res) {
-    res.render('configuration/caches');
-});
-
-/**
- * Get spaces and caches accessed for user account.
- *
- * @param req Request.
- * @param res Response.
- */
-router.post('/list', function (req, res) {
-    var user_id = req.currentUserId();
-
-    // Get owned space and all accessed space.
-    db.Space.find({$or: [{owner: user_id}, {usedBy: {$elemMatch: {account: user_id}}}]}, function (err, spaces) {
-        if (err)
-            return res.status(500).send(err.message);
-
-        var space_ids = spaces.map(function (value) {
-            return value._id;
-        });
-
-        // Get all caches for spaces.
-        db.Cache.find({space: {$in: space_ids}}).sort('name').exec(function (err, caches) {
-            if (err)
-                return res.status(500).send(err.message);
-
-            res.json({spaces: spaces, caches: caches});
-        });
-    });
-});
-
-/**
- * Save cache.
- */
-router.post('/save', function (req, res) {
-    if (req.body._id)
-        db.Cache.update({_id: req.body._id}, req.body, {upsert: true}, function (err) {
-            if (err)
-                return res.status(500).send(err.message);
-
-            res.send(req.body._id);
-        });
-    else {
-        db.Cache.findOne({name: req.body.name}, function (err, cache) {
-            if (err)
-                return res.status(500).send(err.message);
-
-            if (cache)
-                return res.status(500).send('Cache with name: "' + cache.name + '" already exist.');
-
-            (new db.Cache(req.body)).save(function (err, cache) {
-                if (err)
-                    return res.status(500).send(err.message);
-
-                res.send(cache._id);
-            });
-        });
-    }
-});
-
-/**
- * Remove cache by ._id.
- */
-router.post('/remove', function (req, res) {
-    db.Cache.remove(req.body, function (err) {
-        if (err)
-            return res.status(500).send(err.message);
-
-        res.sendStatus(200);
-    })
-});
-
-module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/routes/clusters.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/clusters.js b/modules/web-control-center/nodejs/routes/clusters.js
deleted file mode 100644
index 182130d..0000000
--- a/modules/web-control-center/nodejs/routes/clusters.js
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var router = require('express').Router();
-var db = require('../db');
-
-/* GET clusters page. */
-router.get('/', function (req, res) {
-    res.render('configuration/clusters');
-});
-
-/**
- * Get spaces and clusters accessed for user account.
- *
- * @param req Request.
- * @param res Response.
- */
-router.post('/list', function (req, res) {
-    var user_id = req.currentUserId();
-
-    // Get owned space and all accessed space.
-    db.Space.find({$or: [{owner: user_id}, {usedBy: {$elemMatch: {account: user_id}}}]}, function (err, spaces) {
-        if (err)
-            return res.status(500).send(err.message);
-
-        var space_ids = spaces.map(function (value) {
-            return value._id;
-        });
-
-        db.Cache.find({space: {$in: space_ids}}, '_id name swapEnabled', function (err, caches) {
-            if (err)
-                return res.status(500).send(err);
-
-            // Get all clusters for spaces.
-            db.Cluster.find({space: {$in: space_ids}}).sort('name').exec(function (err, clusters) {
-                if (err)
-                    return res.status(500).send(err.message);
-
-                var cachesJson = caches.map(function (cache) {
-                    return {value: cache._id, label: cache.name, swapEnabled: cache.swapEnabled};
-                });
-
-                res.json({spaces: spaces, caches: cachesJson, clusters: clusters});
-            });
-        });
-    });
-});
-
-/**
- * Save cluster.
- */
-router.post('/save', function (req, res) {
-    if (req.body._id)
-        db.Cluster.update({_id: req.body._id}, req.body, {upsert: true}, function (err) {
-            if (err)
-                return res.status(500).send(err.message);
-
-            res.send(req.body._id);
-        });
-    else {
-        db.Cluster.findOne({name: req.body.name}, function (err, cluster) {
-            if (err)
-                return res.status(500).send(err.message);
-
-            if (cluster)
-                return res.status(500).send('Cluster with name: "' + cluster.name + '" already exist.');
-
-            (new db.Cluster(req.body)).save(function (err, cluster) {
-                if (err)
-                    return res.status(500).send(err.message);
-
-                res.send(cluster._id);
-            });
-        });
-    }
-});
-
-/**
- * Remove cluster by ._id.
- */
-router.post('/remove', function (req, res) {
-    db.Cluster.remove(req.body, function (err) {
-        if (err)
-            return res.status(500).send(err.message);
-
-        res.sendStatus(200);
-    })
-});
-
-module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/routes/generator/common.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/generator/common.js b/modules/web-control-center/nodejs/routes/generator/common.js
deleted file mode 100644
index dcbf156..0000000
--- a/modules/web-control-center/nodejs/routes/generator/common.js
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var _ = require('lodash');
-
-exports.isDefined = function (v) {
-    return !(v === undefined || v === null);
-};
-
-exports.mainComment = mainComment;
-
-function mainComment() {
-    return 'This configuration was generated by Ignite Control Center ('
-        + formatDate(new Date()) + ')';
-}
-
-function addLeadingZero(numberStr, minSize) {
-    if (typeof (numberStr) != 'string')
-        numberStr = '' + numberStr;
-
-    while (numberStr.length < minSize) {
-        numberStr = '0' + numberStr;
-    }
-
-    return numberStr;
-}
-
-exports.formatDate = formatDate;
-
-function formatDate(date) {
-    var dd = addLeadingZero(date.getDate(), 2);
-    var mm = addLeadingZero(date.getMonth() + 1, 2);
-
-    var yyyy = date.getFullYear();
-
-    return mm + '/' + dd + '/' + yyyy + ' ' + addLeadingZero(date.getHours(), 2) + ':' + addLeadingZero(date.getMinutes(), 2);
-}
-
-exports.builder = function () {
-    var res = [];
-
-    res.deep = 0;
-    res.lineStart = true;
-
-    res.append = function (s) {
-        if (this.lineStart) {
-            for (var i = 0; i < this.deep; i++)
-                this.push('    ');
-
-            this.lineStart = false;
-        }
-
-        this.push(s);
-
-        return this;
-    };
-
-    res.line = function (s) {
-        if (s)
-            this.append(s);
-
-        this.push('\n');
-        this.lineStart = true;
-
-        return this;
-    };
-
-    res.startBlock = function (s) {
-        if (s)
-            this.append(s);
-
-        this.push('\n');
-        this.lineStart = true;
-        this.deep++;
-
-        return this;
-    };
-
-    res.endBlock = function (s) {
-        this.deep--;
-
-        if (s)
-            this.append(s);
-
-        this.push('\n');
-        this.lineStart = true;
-
-        return this;
-    };
-
-    res.emptyLineIfNeeded = function () {
-        if (this.needEmptyLine) {
-            this.line();
-
-            this.needEmptyLine = false;
-
-            return true;
-        }
-
-        return false;
-    };
-
-    res.imports = {};
-
-    res.importClass = function (fullClassName) {
-        var dotIdx = fullClassName.lastIndexOf('.');
-
-        var shortName;
-
-        if (dotIdx > 0)
-            shortName = fullClassName.substr(dotIdx + 1);
-        else
-            shortName = fullClassName;
-
-        if (this.imports[shortName]) {
-            if (this.imports[shortName] != fullClassName)
-                throw "Class name conflict: " + this.imports[shortName] + ' and ' + fullClassName;
-        }
-        else {
-            this.imports[shortName] = fullClassName;
-        }
-
-        return shortName;
-    };
-
-    res.generateImports = function () {
-        var res = [];
-
-        for (var clsName in this.imports) {
-            if (this.imports.hasOwnProperty(clsName))
-                res.push('import ' + this.imports[clsName] + ';');
-        }
-
-        return res.join('\n')
-    };
-
-    return res;
-};
-
-function ClassDescriptor(className, fields) {
-    this.className = className;
-    this.fields = fields;
-}
-
-exports.evictionPolicies = {
-    'LRU': new ClassDescriptor('org.apache.ignite.cache.eviction.lru.LruEvictionPolicy',
-        {batchSize: null, maxMemorySize: null, maxSize: null}),
-    'RND': new ClassDescriptor('org.apache.ignite.cache.eviction.random.RandomEvictionPolicy', {maxSize: null}),
-    'FIFO': new ClassDescriptor('org.apache.ignite.cache.eviction.fifo.FifoEvictionPolicy',
-        {batchSize: null, maxMemorySize: null, maxSize: null}),
-    'SORTED': new ClassDescriptor('org.apache.ignite.cache.eviction.sorted.SortedEvictionPolicy',
-        {batchSize: null, maxMemorySize: null, maxSize: null})
-};
-
-exports.marshallers = {
-    OptimizedMarshaller: new ClassDescriptor('org.apache.ignite.marshaller.optimized.OptimizedMarshaller', {
-        poolSize: null,
-        requireSerializable: null
-    }),
-    JdkMarshaller: new ClassDescriptor('org.apache.ignite.marshaller.jdk.JdkMarshaller', {})
-};
-
-exports.knownClasses = {
-    Oracle: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.OracleDialect', {}),
-    DB2: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.DB2Dialect', {}),
-    SQLServer: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.SQLServerDialect', {}),
-    MySQL: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.MySQLDialect', {}),
-    PostgreSQL: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect', {}),
-    H2: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.H2Dialect', {})
-};
-
-exports.dataSources = {
-    Oracle: 'oracle.jdbc.pool.OracleDataSource',
-    DB2: 'com.ibm.db2.jcc.DB2ConnectionPoolDataSource',
-    SQLServer: 'com.microsoft.sqlserver.jdbc.SQLServerDataSource',
-    MySQL: 'com.mysql.jdbc.jdbc2.optional.MysqlDataSource',
-    PostgreSQL: 'org.postgresql.ds.PGPoolingDataSource',
-    H2: 'org.h2.jdbcx.JdbcDataSource'
-};
-
-exports.storeFactories = {
-    CacheJdbcPojoStoreFactory: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory', {
-        dataSourceBean: null,
-        dialect: {type: 'className'}
-    }),
-
-    CacheJdbcBlobStoreFactory: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.CacheJdbcBlobStoreFactory', {
-        user: null,
-        dataSourceBean: null,
-        initSchema: null,
-        createTableQuery: null,
-        loadQuery: null,
-        insertQuery: null,
-        updateQuery: null,
-        deleteQuery: null
-    }),
-
-    CacheHibernateBlobStoreFactory: new ClassDescriptor('org.apache.ignite.cache.store.hibernate.CacheHibernateBlobStoreFactory', {
-        hibernateProperties: {type: 'propertiesAsList', propVarName: 'props'}
-    })
-};
-
-exports.atomicConfiguration = new ClassDescriptor('org.apache.ignite.configuration.AtomicConfiguration', {
-    backups: null,
-    cacheMode: {type: 'enum', enumClass: 'CacheMode'},
-    atomicSequenceReserveSize: null
-});
-
-exports.swapSpaceSpi = new ClassDescriptor('org.apache.ignite.spi.swapspace.file.FileSwapSpaceSpi', {
-    baseDirectory: null,
-    readStripesNumber: null,
-    maximumSparsity: {type: 'float'},
-    maxWriteQueueSize: null,
-    writeBufferSize: null
-});
-
-exports.transactionConfiguration = new ClassDescriptor('org.apache.ignite.configuration.TransactionConfiguration', {
-    defaultTxConcurrency: {type: 'enum', enumClass: 'TransactionConcurrency'},
-    transactionIsolation: {type: 'TransactionIsolation', setterName: 'defaultTxIsolation'},
-    defaultTxTimeout: null,
-    pessimisticTxLogLinger: null,
-    pessimisticTxLogSize: null,
-    txSerializableEnabled: null
-});
-
-exports.hasProperty = function (obj, props) {
-    for (var propName in props) {
-        if (props.hasOwnProperty(propName)) {
-            if (obj[propName])
-                return true;
-        }
-    }
-
-    return false;
-};
-
-/**
- * Convert some name to valid java name.
- *
- * @param name to convert.
- * @returns {string} Valid java name.
- */
-exports.toJavaName = function (name) {
-    var javaName = name.replace(/[^A-Za-z_0-9]+/, '_');
-
-    return javaName.charAt(0).toLocaleUpperCase() + javaName.slice(1);
-};
-
-/**
- * Generate properties file with properties stubs for stores data sources.
- *
- * @param cluster Configuration to process.
- * @returns {string} Generated content.
- */
-exports.generateProperties = function (cluster) {
-    var res = exports.builder();
-
-    var datasources = [];
-
-    if (cluster.caches && cluster.caches.length > 0) {
-        _.forEach(cluster.caches, function (cache) {
-            if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind) {
-                var storeFactory = cache.cacheStoreFactory[cache.cacheStoreFactory.kind];
-
-                if (storeFactory.dialect) {
-                    var beanId = storeFactory.dataSourceBean;
-
-                    if (!_.contains(datasources, beanId)) {
-                        datasources.push(beanId);
-
-                        res.line(beanId + '.jdbc.url=YOUR_JDBC_URL');
-                        res.line(beanId + '.jdbc.username=YOUR_USER_NAME');
-                        res.line(beanId + '.jdbc.password=YOUR_PASSWORD');
-                        res.line();
-                    }
-                }
-            }
-        });
-    }
-
-    if (datasources.length > 0)
-        return '# ' + mainComment() + '\n\n' + res.join();
-
-    return undefined;
-};

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/routes/generator/docker.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/generator/docker.js b/modules/web-control-center/nodejs/routes/generator/docker.js
deleted file mode 100644
index 93faf8e..0000000
--- a/modules/web-control-center/nodejs/routes/generator/docker.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-exports.generateClusterConfiguration = function(cluster, os) {
-    if (!os)
-        os = 'debian:8';
-
-    return "" +
-        "# Start from a OS image.\n"+
-        "FROM " + os + "\n"+
-        "\n"+
-        "# Install tools.\n"+
-        "RUN apt-get update && apt-get install -y --fix-missing \\\n"+
-        "  wget \\\n"+
-        "  dstat \\\n"+
-        "  maven \\\n"+
-        "  git\n"+
-        "\n"+
-        "# Install Oracle JDK.\n"+
-        "RUN mkdir /opt/jdk\n"+
-        "\n"+
-        "RUN wget --header \"Cookie: oraclelicense=accept-securebackup-cookie\" \\\n"+
-        "  http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.tar.gz\n"+
-        "\n"+
-        "RUN tar -zxf jdk-7u79-linux-x64.tar.gz -C /opt/jdk\n"+
-        "\n"+
-        "RUN rm jdk-7u79-linux-x64.tar.gz\n"+
-        "\n"+
-        "RUN update-alternatives --install /usr/bin/java java /opt/jdk/jdk1.7.0_79/bin/java 100\n"+
-        "\n"+
-        "RUN update-alternatives --install /usr/bin/javac javac /opt/jdk/jdk1.7.0_79/bin/javac 100\n"+
-        "\n"+
-        "# Sets java variables.\n"+
-        "ENV JAVA_HOME /opt/jdk/jdk1.7.0_79/\n"+
-        "\n"+
-        "# Create working directory\n"+
-        "WORKDIR /home\n"+
-        "\n"+
-        "RUN wget -O ignite.zip http://tiny.cc/updater/download_ignite.php && unzip ignite.zip && rm ignite.zip\n"+
-        "\n"+
-        "COPY *.xml /tmp/\n"+
-        "\n"+
-        "RUN mv /tmp/*.xml /home/$(ls)/config";
-};

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/routes/generator/java.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/generator/java.js b/modules/web-control-center/nodejs/routes/generator/java.js
deleted file mode 100644
index 31cd2ac..0000000
--- a/modules/web-control-center/nodejs/routes/generator/java.js
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var _ = require('lodash');
-
-var generatorUtils = require("./common");
-
-exports.generateClusterConfiguration = function(cluster, javaClass, clientNearConfiguration) {
-    var res = generatorUtils.builder();
-
-    res.datasourceBeans = [];
-
-    if (javaClass) {
-        res.line('/**');
-        res.line(' * ' + generatorUtils.mainComment());
-        res.line(' */');
-        res.startBlock('public class ConfigurationFactory {');
-        res.line('/**');
-        res.line(' * Configure grid.');
-        res.line(' */');
-        res.startBlock('public IgniteConfiguration createConfiguration() {');
-    }
-    
-    res.importClass('org.apache.ignite.configuration.IgniteConfiguration');
-    
-    res.line('IgniteConfiguration cfg = new IgniteConfiguration();');
-    res.line();
-
-    if (clientNearConfiguration) {
-        res.line('cfg.setClientMode(true);');
-
-        res.line();
-    }
-
-    if (cluster.discovery) {
-        var d = cluster.discovery;
-
-        res.importClass('org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi');
-        res.line('TcpDiscoverySpi discovery = new TcpDiscoverySpi();');
-
-        switch (d.kind) {
-            case 'Multicast':
-                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder');
-
-                addBeanWithProperties(res, d.Multicast, 'discovery', 'ipFinder', 'ipFinder',
-                    'TcpDiscoveryMulticastIpFinder', {
-                        multicastGroup: null,
-                        multicastPort: null,
-                        responseWaitTime: null,
-                        addressRequestAttempts: null,
-                        localAddress: null
-                    }, true);
-
-                break;
-
-            case 'Vm':
-                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder');
-
-                addBeanWithProperties(res, d.Vm, 'discovery', 'ipFinder', 'ipFinder', 'TcpDiscoveryVmIpFinder', {
-                        addresses: {type: 'list'}
-                    }, true);
-
-                break;
-
-            case 'S3':
-                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.s3.TcpDiscoveryS3IpFinder');
-
-                if (d.S3)
-                    addBeanWithProperties(res, d.S3, 'discovery', 'ipFinder', 'ipFinder', 'TcpDiscoveryS3IpFinder',
-                        {bucketName: null}, true);
-                else
-                    res.line('discovery.setIpFinder(new TcpDiscoveryS3IpFinder());');
-
-                break;
-
-            case 'Cloud':
-                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.cloud.TcpDiscoveryCloudIpFinder');
-
-                addBeanWithProperties(res, d.Cloud, 'discovery', 'ipFinder', 'ipFinder', 'TcpDiscoveryCloudIpFinder', {
-                        credential: null,
-                        credentialPath: null,
-                        identity: null,
-                        provider: null,
-                        regions: {type: 'list'},
-                        zones: {type: 'list'}
-                    }, true);
-
-                break;
-
-            case 'GoogleStorage':
-                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.gce.TcpDiscoveryGoogleStorageIpFinder');
-
-                addBeanWithProperties(res, d.GoogleStorage, 'discovery', 'ipFinder', 'ipFinder',
-                    'TcpDiscoveryGoogleStorageIpFinder', {
-                        projectName: null,
-                        bucketName: null,
-                        serviceAccountP12FilePath: null
-                    }, true);
-
-                //if (d.GoogleStorage.addrReqAttempts) todo ????
-                //    res.line('<property name="serviceAccountP12FilePath" value="' + escapeAttr(d.GoogleStorage.addrReqAttempts) + '"/>');
-
-                break;
-
-            case 'Jdbc':
-                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.jdbc.TcpDiscoveryJdbcIpFinder');
-                
-                res.line();
-                res.line('TcpDiscoveryJdbcIpFinder ipFinder = new TcpDiscoveryJdbcIpFinder();');
-                res.line('ipFinder.setInitSchema(' + (d.Jdbc.initSchema != null || d.Jdbc.initSchema) + ');');
-                res.line('discovery.setIpFinder(ipFinder);');
-                res.needEmptyLine = true;
-
-                break;
-
-            case 'SharedFs':
-                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.sharedfs.TcpDiscoverySharedFsIpFinder');
-
-                addBeanWithProperties(res, d.SharedFs, 'discovery', 'ipFinder', 'ipFinder',
-                    'TcpDiscoverySharedFsIpFinder', {path: null}, true);
-
-                break;
-
-            default:
-                throw "Unknown discovery kind: " + d.kind;
-        }
-
-        res.emptyLineIfNeeded();
-
-        res.line('cfg.setDiscoverySpi(discovery);');
-
-        res.needEmptyLine = true;
-    }
-
-    if (cluster.caches && cluster.caches.length > 0) {
-        res.emptyLineIfNeeded();
-
-        var names = [];
-
-        for (var i = 0; i < cluster.caches.length; i++) {
-            res.emptyLineIfNeeded();
-
-            var cache = cluster.caches[i];
-
-            var cacheName = 'cache' + generatorUtils.toJavaName(cache.name);
-
-            names.push(cacheName);
-
-            generateCacheConfiguration(cache, cacheName, res);
-
-            res.needEmptyLine = true;
-        }
-
-        res.emptyLineIfNeeded();
-
-        res.append('cfg.setCacheConfiguration(');
-
-        for (i = 0; i < names.length; i++) {
-            if (i > 0)
-                res.append(', ');
-
-            res.append(names[i]);
-        }
-
-        res.line(');');
-
-        res.needEmptyLine = true;
-    }
-
-    addBeanWithProperties(res, cluster.atomicConfiguration, 'cfg', 'atomicConfiguration', 'atomicCfg',
-        generatorUtils.atomicConfiguration.className, generatorUtils.atomicConfiguration.fields);
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cluster, 'cfg', 'networkTimeout');
-    addProperty(res, cluster, 'cfg', 'networkSendRetryDelay');
-    addProperty(res, cluster, 'cfg', 'networkSendRetryCount');
-    addProperty(res, cluster, 'cfg', 'segmentCheckFrequency');
-    addProperty(res, cluster, 'cfg', 'waitForSegmentOnStart');
-    addProperty(res, cluster, 'cfg', 'discoveryStartupDelay');
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cluster, 'cfg', 'deploymentMode', 'DeploymentMode');
-
-    res.needEmptyLine = true;
-
-    if (cluster.includeEventTypes && cluster.includeEventTypes.length > 0) {
-        res.emptyLineIfNeeded();
-        
-        if (cluster.includeEventTypes.length == 1) {
-            res.importClass('org.apache.ignite.events.EventType');
-            
-            res.line('cfg.setIncludeEventTypes(EventType.' + cluster.includeEventTypes[0] + ');');
-        }
-        else {
-            res.append('int[] events = new int[EventType.' + cluster.includeEventTypes[0] + '.length');
-            
-            for (i = 1; i < cluster.includeEventTypes.length; i++) {
-                res.line();
-                
-                res.append('    + EventType.' + cluster.includeEventTypes[i] + '.length');
-            }
-            
-            res.line('];');
-            res.line();
-            res.line('int k = 0;');
-
-            for (i = 0; i < cluster.includeEventTypes.length; i++) {
-                res.line();
-
-                var e = cluster.includeEventTypes[i];
-                
-                res.line('System.arraycopy(EventType.' + e + ', 0, events, k, EventType.' + e + '.length);');
-                res.line('k += EventType.' + e + '.length;');
-            }
-            
-            res.line();
-            res.line('cfg.setIncludeEventTypes(events);');
-        }
-
-        res.needEmptyLine = true;
-    }
-
-    res.needEmptyLine = true;
-
-    var marshaller = cluster.marshaller;
-
-    if (marshaller && marshaller.kind) {
-        var marshallerDesc = generatorUtils.marshallers[marshaller.kind];
-
-        addBeanWithProperties(res, marshaller[marshaller.kind], 'cfg', 'marshaller', 'marshaller',
-            marshallerDesc.className, marshallerDesc.fields, true);
-
-        addBeanWithProperties(res, marshaller[marshaller.kind], 'marshaller', marshallerDesc.className, marshallerDesc.fields, true);
-    }
-
-    addProperty(res, cluster, 'cfg', 'marshalLocalJobs');
-    addProperty(res, cluster, 'cfg', 'marshallerCacheKeepAliveTime');
-    addProperty(res, cluster, 'cfg', 'marshallerCacheThreadPoolSize');
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cluster, 'cfg', 'metricsExpireTime');
-    addProperty(res, cluster, 'cfg', 'metricsHistorySize');
-    addProperty(res, cluster, 'cfg', 'metricsLogFrequency');
-    addProperty(res, cluster, 'cfg', 'metricsUpdateFrequency');
-    res.needEmptyLine = true;
-
-    addProperty(res, cluster, 'cfg', 'peerClassLoadingEnabled');
-    addMultiparamProperty(res, cluster, 'cfg', 'peerClassLoadingLocalClassPathExclude');
-    addProperty(res, cluster, 'cfg', 'peerClassLoadingMissedResourcesCacheSize');
-    addProperty(res, cluster, 'cfg', 'peerClassLoadingThreadPoolSize');
-    res.needEmptyLine = true;
-
-    if (cluster.swapSpaceSpi && cluster.swapSpaceSpi.kind == 'FileSwapSpaceSpi') {
-        addBeanWithProperties(res, cluster.swapSpaceSpi.FileSwapSpaceSpi, 'cfg', 'swapSpaceSpi', 'swapSpi',
-            generatorUtils.swapSpaceSpi.className, generatorUtils.swapSpaceSpi.fields, true);
-
-        res.needEmptyLine = true;
-    }
-
-    addProperty(res, cluster, 'cfg', 'clockSyncSamples');
-    addProperty(res, cluster, 'cfg', 'clockSyncFrequency');
-    addProperty(res, cluster, 'cfg', 'timeServerPortBase');
-    addProperty(res, cluster, 'cfg', 'timeServerPortRange');
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cluster, 'cfg', 'publicThreadPoolSize');
-    addProperty(res, cluster, 'cfg', 'systemThreadPoolSize');
-    addProperty(res, cluster, 'cfg', 'managementThreadPoolSize');
-    addProperty(res, cluster, 'cfg', 'igfsThreadPoolSize');
-
-    res.needEmptyLine = true;
-
-    addBeanWithProperties(res, cluster.transactionConfiguration, 'cfg', 'transactionConfiguration',
-        'transactionConfiguration', generatorUtils.transactionConfiguration.className,
-        generatorUtils.transactionConfiguration.fields);
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cluster, 'cfg', 'cacheSanityCheckEnabled');
-
-    res.needEmptyLine = true;
-
-    if (javaClass) {
-        res.line();
-        res.line('return cfg;');
-        res.endBlock('}');
-        res.endBlock('}');
-        
-        return res.generateImports() + '\n\n' + res.join('')
-    }
-    
-    return res.join('');
-};
-
-function createEvictionPolicy(res, evictionPolicy, varName, propertyName) {
-    if (evictionPolicy && evictionPolicy.kind) {
-        var e = generatorUtils.evictionPolicies[evictionPolicy.kind];
-
-        var obj = evictionPolicy[evictionPolicy.kind.toUpperCase()];
-
-        addBeanWithProperties(res, obj, varName, propertyName, propertyName, e.className, e.fields, true);
-    }
-}
-
-exports.generateCacheConfiguration = generateCacheConfiguration;
-
-/**
- * Generate java code for cache configuration.
- *
- * @param cacheCfg Cache config.
- * @param varName Variable name.
- * @param res Result builder.
- * @returns {*} Append generated java code to builder and return it.
- */
-function generateCacheConfiguration(cacheCfg, varName, res) {
-    if (!res)
-        res = generatorUtils.builder();
-
-    res.emptyLineIfNeeded();
-
-    res.importClass('org.apache.ignite.cache.CacheAtomicityMode');
-    res.importClass('org.apache.ignite.cache.CacheMode');
-    res.importClass('org.apache.ignite.configuration.CacheConfiguration');
-
-    res.line('CacheConfiguration ' + varName + ' = new CacheConfiguration();');
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, varName, 'name');
-    
-    addProperty(res, cacheCfg, varName, 'mode', 'CacheMode', 'cacheMode');
-
-    addProperty(res, cacheCfg, varName, 'atomicityMode', 'CacheAtomicityMode');
-    addProperty(res, cacheCfg, varName, 'backups');
-    addProperty(res, cacheCfg, varName, 'startSize');
-    addProperty(res, cacheCfg, varName, 'readFromBackup');
-
-    res.needEmptyLine = true;
-    
-    addProperty(res, cacheCfg, varName, 'memoryMode', 'CacheMemoryMode');
-    addProperty(res, cacheCfg, varName, 'offHeapMaxMemory');
-    addProperty(res, cacheCfg, varName, 'swapEnabled');
-    addProperty(res, cacheCfg, varName, 'copyOnRead');
-
-    res.needEmptyLine = true;
-
-    createEvictionPolicy(res, cacheCfg.evictionPolicy, varName, 'evictionPolicy');
-
-    if (cacheCfg.nearCacheEnabled) {
-        res.needEmptyLine = true;
-
-        res.importClass('org.apache.ignite.configuration.NearCacheConfiguration');
-
-        addBeanWithProperties(res, cacheCfg.nearConfiguration, varName, 'nearConfiguration', 'nearConfiguration',
-            'NearCacheConfiguration', {nearStartSize: null}, true);
-
-        if (cacheCfg.nearConfiguration && cacheCfg.nearConfiguration.nearEvictionPolicy && cacheCfg.nearConfiguration.nearEvictionPolicy.kind) {
-            createEvictionPolicy(res, cacheCfg.nearConfiguration.nearEvictionPolicy, 'nearConfiguration', 'nearEvictionPolicy');
-        }
-    }
-
-    res.needEmptyLine = true;
-    
-    addProperty(res, cacheCfg, varName, 'sqlEscapeAll');
-    addProperty(res, cacheCfg, varName, 'sqlOnheapRowCacheSize');
-    addProperty(res, cacheCfg, varName, 'longQueryWarningTimeout');
-    
-    if (cacheCfg.indexedTypes && cacheCfg.indexedTypes.length > 0) {
-        res.emptyLineIfNeeded();
-        
-        res.append(varName + '.setIndexedTypes(');
-        
-        for (var i = 0; i < cacheCfg.indexedTypes.length; i++) {
-            if (i > 0)
-                res.append(', ');
-
-            var pair = cacheCfg.indexedTypes[i];
-            
-            res.append(toJavaCode(pair.keyClass, 'class')).append(', ').append(toJavaCode(pair.valueClass, 'class'))
-        }
-        
-        res.line(');');
-    }
-
-    addMultiparamProperty(res, cacheCfg, varName, 'sqlFunctionClasses', 'class');
-    
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, varName, 'rebalanceMode', 'CacheRebalanceMode');
-    addProperty(res, cacheCfg, varName, 'rebalanceThreadPoolSize');
-    addProperty(res, cacheCfg, varName, 'rebalanceBatchSize');
-    addProperty(res, cacheCfg, varName, 'rebalanceOrder');
-    addProperty(res, cacheCfg, varName, 'rebalanceDelay');
-    addProperty(res, cacheCfg, varName, 'rebalanceTimeout');
-    addProperty(res, cacheCfg, varName, 'rebalanceThrottle');
-
-    res.needEmptyLine = true;
-    
-    if (cacheCfg.cacheStoreFactory && cacheCfg.cacheStoreFactory.kind) {
-        var storeFactory = cacheCfg.cacheStoreFactory[cacheCfg.cacheStoreFactory.kind];
-        var data = generatorUtils.storeFactories[cacheCfg.cacheStoreFactory.kind];
-
-        var sfVarName = 'storeFactory' + generatorUtils.toJavaName(cacheCfg.name);
-        var dsVarName = 'none';
-
-        if (storeFactory.dialect) {
-            var dataSourceBean = storeFactory.dataSourceBean;
-
-            dsVarName = 'dataSource' + generatorUtils.toJavaName(dataSourceBean);
-
-            if (!_.contains(res.datasourceBeans, dataSourceBean)) {
-                res.datasourceBeans.push(dataSourceBean);
-
-                var dataSource = generatorUtils.dataSources[storeFactory.dialect];
-
-                res.line();
-                res.line(dataSource.className + ' ' + dsVarName + ' = new ' + dataSource.className + '();');
-                res.line(dsVarName + '.setURL(_URL_);');
-                res.line(dsVarName + '.setUsername(_User_Name_);');
-                res.line(dsVarName + '.setPassword(_Password_);');
-            }
-        }
-
-        addBeanWithProperties(res, storeFactory, varName, 'cacheStoreFactory', sfVarName, data.className,
-            data.fields, true);
-
-        if (dsVarName != 'none')
-            res.line(sfVarName + '.setDataSource(' + dsVarName + ');');
-    }
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, varName, 'loadPreviousValue');
-    addProperty(res, cacheCfg, varName, 'readThrough');
-    addProperty(res, cacheCfg, varName, 'writeThrough');
-
-    res.needEmptyLine = true;
-    
-    addProperty(res, cacheCfg, varName, 'invalidate');
-    addProperty(res, cacheCfg, varName, 'defaultLockTimeout');
-    addProperty(res, cacheCfg, varName, 'transactionManagerLookupClassName');
-    
-    res.needEmptyLine = true;
-    
-    addProperty(res, cacheCfg, varName, 'writeBehindEnabled');
-    addProperty(res, cacheCfg, varName, 'writeBehindBatchSize');
-    addProperty(res, cacheCfg, varName, 'writeBehindFlushSize');
-    addProperty(res, cacheCfg, varName, 'writeBehindFlushFrequency');
-    addProperty(res, cacheCfg, varName, 'writeBehindFlushThreadCount');
-    
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, varName, 'statisticsEnabled');
-    addProperty(res, cacheCfg, varName, 'managementEnabled');
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, varName, 'maxConcurrentAsyncOperations');
-    
-    return res;
-}
-
-function toJavaCode(val, type) {
-    if (val == null)
-       return 'null';
-
-    if (type == 'float')
-        return val + 'f';
-    
-    if (type == 'class')
-        return val + '.class';
-    
-    if (type)
-        return type + '.' + val;
-    
-    if (typeof(val) == 'string')
-        return '"' + val.replace('"', '\\"') + '"';
-
-    if (typeof(val) == 'number' || typeof(val) == 'boolean')
-        return '' + val;
-
-    throw "Unknown type: " + typeof(val) + ' (' + val + ')';
-}
-
-function addProperty(res, obj, objVariableName, propName, enumType, setterName) {
-    var val = obj[propName];
-    
-    if (generatorUtils.isDefined(val)) {
-        res.emptyLineIfNeeded();
-
-        res.line(objVariableName + '.' + getSetterName(setterName ? setterName : propName)
-            + '(' + toJavaCode(val, enumType)  + ');');
-    }
-}
-
-function getSetterName(propName) {
-    return 'set' + propName.charAt(0).toLocaleUpperCase() + propName.slice(1);
-}
-
-function addListProperty(res, obj, objVariableName, propName, enumType, setterName) {
-    var val = obj[propName];
-    
-    if (val && val.length > 0) {
-        res.append(objVariableName + '.' + getSetterName(setterName ? setterName : propName) + '(Arrays.asList(');
-
-        for (var i = 0; i < val.length; i++) {
-            if (i > 0)
-                res.append(', ');
-            
-            res.append(toJavaCode(val[i], enumType));
-        }
-        
-        res.line('));');
-    }
-}
-
-function addMultiparamProperty(res, obj, objVariableName, propName, type, setterName) {
-    var val = obj[propName];
-    
-    if (val && val.length > 0) {
-        res.append(objVariableName + '.' + getSetterName(setterName ? setterName : propName) + '(');
-
-        for (var i = 0; i < val.length; i++) {
-            if (i > 0)
-                res.append(', ');
-            
-            res.append(toJavaCode(val[i], type));
-        }
-        
-        res.line(');');
-    }
-}
-
-function addBeanWithProperties(res, bean, objVarName, beanPropName, beanVarName, beanClass, props, createBeanAlthoughNoProps) {
-    if (bean && generatorUtils.hasProperty(bean, props)) {
-        if (!res.emptyLineIfNeeded()) {
-            res.line();
-        }
-        
-        res.line(beanClass + ' ' + beanVarName + ' = new ' + beanClass + '();');
-
-        for (var propName in props) {
-            if (props.hasOwnProperty(propName)) {
-                var descr = props[propName];
-
-                if (descr) {
-                    switch (descr.type) {
-                        case 'list':
-                            addListProperty(res, bean, beanVarName, propName, descr.elementsType, descr.setterName);
-                            break;
-                        
-                        case 'enum':
-                            addProperty(res, bean, beanVarName, propName, descr.enumClass, descr.setterName);
-                            break;
-                        
-                        case 'float':
-                            addProperty(res, bean, beanVarName, propName, 'float', descr.setterName);
-                            break;
-                        
-                        case 'propertiesAsList':
-                            var val = bean[propName];
-                            
-                            if (val && val.length > 0) {
-                                res.line('Properties ' + descr.propVarName + ' = new Properties();');
-                                
-                                for (var i = 0; i < val.length; i++) {
-                                    var nameAndValue = val[i];
-                                    
-                                    var eqIndex = nameAndValue.indexOf('=');
-                                    if (eqIndex >= 0) {
-                                        res.line(descr.propVarName + '.setProperty(' 
-                                            + nameAndValue.substring(0, eqIndex) + ', ' 
-                                            + nameAndValue.substr(eqIndex + 1) + ');');
-                                    }
-
-                                }
-                                
-                                res.line(beanVarName + '.' + getSetterName(propName) + '(' + descr.propVarName + ');');
-                            }
-                            break;
-                        
-                        case 'className':
-                            if (bean[propName]) {
-                                res.line(beanVarName + '.' + getSetterName(propName) + '(new ' + generatorUtils.knownClasses[bean[propName]].className + '());');
-                            }
-
-                            break;
-                        
-                        default:
-                            addProperty(res, bean, beanVarName, propName, null, descr.setterName);
-                    }
-                }
-                else {
-                    addProperty(res, bean, beanVarName, propName);
-                }
-            }
-        }
-        
-        res.line(objVarName + '.' + getSetterName(beanPropName) + '(' + beanVarName + ');');
-        
-        res.needEmptyLine = true;
-    }
-    else if (createBeanAlthoughNoProps) {
-        res.emptyLineIfNeeded();
-        
-        res.line(objVarName + '.' + getSetterName(beanPropName) + '(new ' + beanClass + '());');
-    }
-}



[17/50] [abbrv] incubator-ignite git commit: IGNITE-843 Code format.

Posted by an...@apache.org.
IGNITE-843 Code format.


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

Branch: refs/heads/ignite-1121
Commit: 576c87d2f9688fca8b94a6f95ec12a8e599d9728
Parents: 27b6f95
Author: AKuznetsov <ak...@gridgain.com>
Authored: Tue Jul 21 13:11:19 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Tue Jul 21 13:11:19 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/caches-controller.js     |  4 +-
 .../nodejs/controllers/common-module.js         |  4 +-
 .../nodejs/controllers/metadata-controller.js   | 36 +++++++++------
 .../nodejs/controllers/models/clusters.json     | 24 +++++++---
 .../nodejs/controllers/models/metadata.json     | 47 +++++++++++++++-----
 .../nodejs/controllers/profile-controller.js    |  2 +-
 .../nodejs/controllers/summary-controller.js    | 26 ++++++-----
 7 files changed, 96 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/576c87d2/modules/web-control-center/nodejs/controllers/caches-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/caches-controller.js b/modules/web-control-center/nodejs/controllers/caches-controller.js
index 3cef598..b050103 100644
--- a/modules/web-control-center/nodejs/controllers/caches-controller.js
+++ b/modules/web-control-center/nodejs/controllers/caches-controller.js
@@ -147,7 +147,9 @@ controlCenterModule.controller('cachesController', ['$scope', '$http', '$common'
             var model = item[field.model];
 
             if ($common.isDefined(model)) {
-                var idx = _.findIndex(model, function (pair) {return pair.keyClass == keyCls});
+                var idx = _.findIndex(model, function (pair) {
+                    return pair.keyClass == keyCls
+                });
 
                 // Found itself.
                 if (index >= 0 && index == idx)

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/576c87d2/modules/web-control-center/nodejs/controllers/common-module.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/common-module.js b/modules/web-control-center/nodejs/controllers/common-module.js
index f011a59..5118af8 100644
--- a/modules/web-control-center/nodejs/controllers/common-module.js
+++ b/modules/web-control-center/nodejs/controllers/common-module.js
@@ -256,7 +256,7 @@ controlCenterModule.service('$table', ['$common', function ($common) {
                     _model(item, field)[field.model][index] = newValue;
             }
         },
-        tableSimpleSaveVisible: function(newValue) {
+        tableSimpleSaveVisible: function (newValue) {
             return $common.isNonEmpty(newValue);
         },
         tableSimpleUp: function (item, field, index) {
@@ -295,7 +295,7 @@ controlCenterModule.service('$table', ['$common', function ($common) {
                 }
             }
         },
-        tablePairSaveVisible: function(newKey, newValue) {
+        tablePairSaveVisible: function (newKey, newValue) {
             return $common.isNonEmpty(newKey) && $common.isNonEmpty(newValue);
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/576c87d2/modules/web-control-center/nodejs/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/metadata-controller.js b/modules/web-control-center/nodejs/controllers/metadata-controller.js
index 1064f3a..f577dea 100644
--- a/modules/web-control-center/nodejs/controllers/metadata-controller.js
+++ b/modules/web-control-center/nodejs/controllers/metadata-controller.js
@@ -387,7 +387,9 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
 
                             var metadatas = $scope.metadatas;
 
-                            var idx = _.findIndex(metadatas, function (metadata) { return metadata._id == _id; });
+                            var idx = _.findIndex(metadatas, function (metadata) {
+                                return metadata._id == _id;
+                            });
 
                             if (idx >= 0) {
                                 metadatas.splice(i, idx);
@@ -431,7 +433,9 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             var model = item[field.model];
 
             if ($common.isDefined(model)) {
-                var idx = _.findIndex(model, function (pair) {return pair.name == name});
+                var idx = _.findIndex(model, function (pair) {
+                    return pair.name == name
+                });
 
                 // Found itself.
                 if (index >= 0 && index == idx)
@@ -448,12 +452,12 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             return true;
         };
 
-        $scope.tableDbFieldSaveVisible = function(dbName, dbType, javaName, javaType){
+        $scope.tableDbFieldSaveVisible = function (dbName, dbType, javaName, javaType) {
             return $common.isNonEmpty(dbName) && $common.isDefined(dbType) &&
                 $common.isNonEmpty(javaName) && $common.isDefined(javaType);
         };
 
-        $scope.tableDbFieldSave = function(field, newDbName, newDbType, newJavaName, newJavaType, index) {
+        $scope.tableDbFieldSave = function (field, newDbName, newDbType, newJavaName, newJavaType, index) {
             var item = $scope.backupItem;
 
             var model = item[field.model];
@@ -461,7 +465,9 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             var newItem = {dbName: newDbName, dbType: newDbType, javaName: newJavaName, javaType: newJavaType};
 
             if ($common.isDefined(model)) {
-                var idx = _.findIndex(model, function (dbMeta) {return dbMeta.dbName == newDbName});
+                var idx = _.findIndex(model, function (dbMeta) {
+                    return dbMeta.dbName == newDbName
+                });
 
                 // Found duplicate.
                 if (idx >= 0 && index != idx) {
@@ -491,7 +497,7 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             $table.tableReset();
         };
 
-        $scope.tableGroupSaveVisible = function(group) {
+        $scope.tableGroupSaveVisible = function (group) {
             return $common.isNonEmpty(group);
         };
 
@@ -499,7 +505,9 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             var groups = $scope.backupItem.groups;
 
             if ($common.isDefined(groups)) {
-                var idx = _.findIndex(groups, function (group) {return group.name == groupName});
+                var idx = _.findIndex(groups, function (group) {
+                    return group.name == groupName
+                });
 
                 // Found itself.
                 if (index >= 0 && index == idx)
@@ -516,7 +524,7 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             return true;
         }
 
-        $scope.tableGroupSave = function(groupName, index) {
+        $scope.tableGroupSave = function (groupName, index) {
             if (tableGroupValid(groupName, index)) {
                 $table.tableReset();
 
@@ -535,13 +543,13 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             }
         };
 
-        $scope.tableGroupNewItem = function(groupIndex) {
+        $scope.tableGroupNewItem = function (groupIndex) {
             var groupName = $scope.backupItem.groups[groupIndex].name;
 
             return $table.tableNewItem({model: groupName});
         };
 
-        $scope.tableGroupNewItemActive = function(groupIndex) {
+        $scope.tableGroupNewItemActive = function (groupIndex) {
             var groupName = $scope.backupItem.groups[groupIndex].name;
 
             return $table.tableNewItemActive({model: groupName});
@@ -556,7 +564,7 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             return false;
         };
 
-        $scope.tableGroupItemStartEdit = function(groupIndex, index) {
+        $scope.tableGroupItemStartEdit = function (groupIndex, index) {
             var groups = $scope.backupItem.groups;
 
             $table.tableState(groups[groupIndex].name, index);
@@ -564,11 +572,11 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             return groups[groupIndex].fields[index];
         };
 
-        $scope.tableGroupItemSaveVisible = function(fieldName, className) {
+        $scope.tableGroupItemSaveVisible = function (fieldName, className) {
             return $common.isNonEmpty(fieldName) && $common.isNonEmpty(className);
         };
 
-        $scope.tableGroupItemSave = function(fieldName, className, direction, groupIndex, index) {
+        $scope.tableGroupItemSave = function (fieldName, className, direction, groupIndex, index) {
             $table.tableReset();
 
             var group = $scope.backupItem.groups[groupIndex];
@@ -590,7 +598,7 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             }
         };
 
-        $scope.tableRemoveGroupItem = function(group, index) {
+        $scope.tableRemoveGroupItem = function (group, index) {
             $table.tableReset();
 
             group.fields.splice(index, 1);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/576c87d2/modules/web-control-center/nodejs/controllers/models/clusters.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/clusters.json b/modules/web-control-center/nodejs/controllers/models/clusters.json
index fbafc59..b1955d1 100644
--- a/modules/web-control-center/nodejs/controllers/models/clusters.json
+++ b/modules/web-control-center/nodejs/controllers/models/clusters.json
@@ -546,7 +546,9 @@
     },
     {
       "label": "Metrics",
-      "tip": ["Cluster runtime metrics settings."],
+      "tip": [
+        "Cluster runtime metrics settings."
+      ],
       "fields": [
         {
           "label": "Elapsed time",
@@ -595,7 +597,9 @@
     },
     {
       "label": "Peer Class Loading",
-      "tip": ["Cluster peer class loading settings."],
+      "tip": [
+        "Cluster peer class loading settings."
+      ],
       "fields": [
         {
           "label": "Enable peer class loading",
@@ -638,7 +642,9 @@
     },
     {
       "label": "Swap",
-      "tip": ["Settings for overflow data to disk if it cannot fit in memory."],
+      "tip": [
+        "Settings for overflow data to disk if it cannot fit in memory."
+      ],
       "fields": [
         {
           "label": "Swap space SPI",
@@ -715,7 +721,9 @@
     },
     {
       "label": "Time configuration",
-      "tip": ["Time settings for CLOCK write ordering mode."],
+      "tip": [
+        "Time settings for CLOCK write ordering mode."
+      ],
       "fields": [
         {
           "label": "Samples size",
@@ -761,7 +769,9 @@
     },
     {
       "label": "Thread pools size",
-      "tip": ["Settings for node thread pools."],
+      "tip": [
+        "Settings for node thread pools."
+      ],
       "fields": [
         {
           "label": "Public",
@@ -803,7 +813,9 @@
     },
     {
       "label": "Transactions",
-      "tip": ["Settings for transactions."],
+      "tip": [
+        "Settings for transactions."
+      ],
       "fields": [
         {
           "label": "Concurrency",

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/576c87d2/modules/web-control-center/nodejs/controllers/models/metadata.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/metadata.json b/modules/web-control-center/nodejs/controllers/models/metadata.json
index d32d546..d2d0bea 100644
--- a/modules/web-control-center/nodejs/controllers/models/metadata.json
+++ b/modules/web-control-center/nodejs/controllers/models/metadata.json
@@ -40,7 +40,9 @@
       "model": "databaseSchema",
       "hide": "backupItem.kind == 'query'",
       "placeholder": "Input DB schema name",
-      "tip": ["Schema name in database."]
+      "tip": [
+        "Schema name in database."
+      ]
     },
     {
       "label": "Database table",
@@ -48,7 +50,9 @@
       "model": "databaseTable",
       "hide": "backupItem.kind == 'query'",
       "placeholder": "Input DB table name",
-      "tip": ["Table name in database."]
+      "tip": [
+        "Table name in database."
+      ]
     },
     {
       "label": "Key type",
@@ -56,7 +60,9 @@
       "model": "keyType",
       "required": true,
       "placeholder": "Full class name for Key",
-      "tip": ["Key class used to store key in cache."]
+      "tip": [
+        "Key class used to store key in cache."
+      ]
     },
     {
       "label": "Value type",
@@ -64,7 +70,9 @@
       "model": "valueType",
       "required": true,
       "placeholder": "Full class name for Value",
-      "tip": ["Value class used to store value in cache."]
+      "tip": [
+        "Value class used to store value in cache."
+      ]
     },
     {
       "label": "Key fields",
@@ -73,7 +81,9 @@
       "keyName": "name",
       "valueName": "className",
       "hide": "backupItem.kind == 'query'",
-      "tip": ["Collection of key fields descriptions for CacheJdbcPojoStore."]
+      "tip": [
+        "Collection of key fields descriptions for CacheJdbcPojoStore."
+      ]
     },
     {
       "label": "Value fields",
@@ -82,7 +92,9 @@
       "keyName": "name",
       "valueName": "className",
       "hide": "backupItem.kind == 'query'",
-      "tip": ["Collection of value fields descriptions for CacheJdbcPojoStore.."]
+      "tip": [
+        "Collection of value fields descriptions for CacheJdbcPojoStore.."
+      ]
     },
     {
       "label": "Query fields",
@@ -91,7 +103,9 @@
       "keyName": "name",
       "valueName": "className",
       "hide": "backupItem.kind != 'query'",
-      "tip": ["Collection of name-to-type mappings to be queried, in addition to indexed fields."]
+      "tip": [
+        "Collection of name-to-type mappings to be queried, in addition to indexed fields."
+      ]
     },
     {
       "label": "Ascending fields",
@@ -100,7 +114,9 @@
       "keyName": "name",
       "valueName": "className",
       "hide": "backupItem.kind != 'query'",
-      "tip": ["Collection of name-to-type mappings to index in ascending order."]
+      "tip": [
+        "Collection of name-to-type mappings to index in ascending order."
+      ]
     },
     {
       "label": "Descending fields",
@@ -109,7 +125,9 @@
       "keyName": "name",
       "valueName": "className",
       "hide": "backupItem.kind != 'query'",
-      "tip": ["Collection of name-to-type mappings to index in descending order."]
+      "tip": [
+        "Collection of name-to-type mappings to index in descending order."
+      ]
     },
     {
       "label": "Text fields",
@@ -117,14 +135,21 @@
       "model": "textFields",
       "hide": "backupItem.kind != 'query'",
       "placeholder": "Field name",
-      "tip": ["Fields to index as text."]
+      "tableTip": [
+        "Fields to index as text."
+      ],
+      "tip": [
+        "Field to index as text."
+      ]
     },
     {
       "label": "Groups",
       "type": "queryGroups",
       "model": "groups",
       "hide": "backupItem.kind != 'query'",
-      "tip": ["Collection of group indexes."]
+      "tip": [
+        "Collection of group indexes."
+      ]
     }
   ],
   "metadataDb": [

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/576c87d2/modules/web-control-center/nodejs/controllers/profile-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/profile-controller.js b/modules/web-control-center/nodejs/controllers/profile-controller.js
index 2f57274..a67df63 100644
--- a/modules/web-control-center/nodejs/controllers/profile-controller.js
+++ b/modules/web-control-center/nodejs/controllers/profile-controller.js
@@ -18,7 +18,7 @@
 controlCenterModule.controller('profileController', ['$scope', '$http', '$common', function ($scope, $http, $common) {
     $scope.profileUser = angular.copy($scope.user);
 
-    $scope.saveUser = function() {
+    $scope.saveUser = function () {
         var profile = $scope.profileUser;
 
         if (profile) {

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/576c87d2/modules/web-control-center/nodejs/controllers/summary-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/summary-controller.js b/modules/web-control-center/nodejs/controllers/summary-controller.js
index 7761bb4..2872a58 100644
--- a/modules/web-control-center/nodejs/controllers/summary-controller.js
+++ b/modules/web-control-center/nodejs/controllers/summary-controller.js
@@ -20,8 +20,8 @@ controlCenterModule.controller('summaryController', ['$scope', '$http', '$common
     $scope.getModel = $common.getModel;
 
     $scope.javaClassItems = [
-        { label: 'snippet',value: false},
-        { label: 'factory class',value: true}
+        {label: 'snippet', value: false},
+        {label: 'factory class', value: true}
     ];
 
     $scope.evictionPolicies = [
@@ -49,14 +49,14 @@ controlCenterModule.controller('summaryController', ['$scope', '$http', '$common
 
     $scope.clusters = [];
 
-    $scope.aceInit = function(editor) {
+    $scope.aceInit = function (editor) {
         editor.setReadOnly(true);
         editor.setOption("highlightActiveLine", false);
 
         editor.setTheme('ace/theme/chrome');
     };
 
-    $scope.reloadServer = function() {
+    $scope.reloadServer = function () {
         $scope.javaServer = $scope.configServer.javaClassServer ? $scope.configServer.javaClass : $scope.configServer.javaSnippet;
 
         if ($scope.configServer.docker) {
@@ -66,7 +66,7 @@ controlCenterModule.controller('summaryController', ['$scope', '$http', '$common
         }
     };
 
-    $scope.selectItem = function(cluster) {
+    $scope.selectItem = function (cluster) {
         if (!cluster)
             return;
 
@@ -79,16 +79,16 @@ controlCenterModule.controller('summaryController', ['$scope', '$http', '$common
 
         $scope.reloadServer();
 
-        $scope.$watch('configServer', function() {
+        $scope.$watch('configServer', function () {
             $scope.reloadServer();
         }, true);
 
-        $scope.$watch('backupItem', function() {
+        $scope.$watch('backupItem', function () {
             $scope.generateClient();
         }, true);
     };
 
-    $scope.generateServer = function(cluster) {
+    $scope.generateServer = function (cluster) {
         $http.post('summary/generator', {_id: cluster._id})
             .success(function (data) {
                 $scope.xmlServer = data.xmlServer;
@@ -101,9 +101,11 @@ controlCenterModule.controller('summaryController', ['$scope', '$http', '$common
             });
     };
 
-    $scope.generateClient = function() {
-        $http.post('summary/generator', {_id: $scope.selectedItem._id, javaClass: $scope.backupItem.javaClassClient,
-            clientNearConfiguration: $scope.backupItem.nearConfiguration})
+    $scope.generateClient = function () {
+        $http.post('summary/generator', {
+            _id: $scope.selectedItem._id, javaClass: $scope.backupItem.javaClassClient,
+            clientNearConfiguration: $scope.backupItem.nearConfiguration
+        })
             .success(function (data) {
                 $scope.xmlClient = data.xmlClient;
                 $scope.javaClient = data.javaClient;
@@ -112,7 +114,7 @@ controlCenterModule.controller('summaryController', ['$scope', '$http', '$common
             });
     };
 
-    $scope.download = function() {
+    $scope.download = function () {
         $http.post('summary/download', {_id: $scope.selectedItem._id, javaClass: $scope.javaClass, os: $scope.os})
             .success(function (data) {
                 var file = document.createElement('a');


[30/50] [abbrv] incubator-ignite git commit: Merge branch 'ignite-843' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-1121

Posted by an...@apache.org.
Merge branch 'ignite-843' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-1121


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

Branch: refs/heads/ignite-1121
Commit: fe4327565b272631bfd9f0578ae2c02e9d6b634d
Parents: 6265e3a ff3cebc
Author: Andrey <an...@gridgain.com>
Authored: Wed Jul 22 09:44:07 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Wed Jul 22 09:44:07 2015 +0700

----------------------------------------------------------------------
 .../nodejs/public/stylesheets/style.less           |  7 ++++++-
 .../nodejs/views/configuration/metadata.jade       |  3 ++-
 .../nodejs/views/includes/controls.jade            | 17 +++++++----------
 3 files changed, 15 insertions(+), 12 deletions(-)
----------------------------------------------------------------------



[47/50] [abbrv] incubator-ignite git commit: # ignite-843 Fixed ui

Posted by an...@apache.org.
# ignite-843 Fixed ui


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

Branch: refs/heads/ignite-1121
Commit: 14fa6f65fd12c47b23e2b9755f62c607d85b5c77
Parents: e7088d5
Author: Andrey <an...@gridgain.com>
Authored: Thu Jul 23 09:57:58 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Thu Jul 23 09:57:58 2015 +0700

----------------------------------------------------------------------
 .../src/main/js/views/includes/controls.jade          | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/14fa6f65/modules/web-control-center/src/main/js/views/includes/controls.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/includes/controls.jade b/modules/web-control-center/src/main/js/views/includes/controls.jade
index 00ab6fa..d8bf89e 100644
--- a/modules/web-control-center/src/main/js/views/includes/controls.jade
+++ b/modules/web-control-center/src/main/js/views/includes/controls.jade
@@ -76,7 +76,8 @@ mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
                                 label.labelField {{$index + 1}})
                                 +btn-save('tablePairSaveVisible(curKey, curValue)', 'tablePairSave(tablePairValid, backupItem, field, curKey, curValue, $index)')
                                 +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder)
-                    tr(ng-show='tableNewItemActive(field)')
+                tfoot(ng-show='tableNewItemActive(field)')
+                    tr
                         td.col-sm-12
                             +btn-save('tablePairSaveVisible(newKey, newValue)', 'tablePairSave(tablePairValid, backupItem, field, newKey, newValue, -1)')
                             +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder)
@@ -256,7 +257,8 @@ mixin form-row-custom(lblClasses, fieldClasses)
                                             +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, curValue, $index)')
                                             .input-tip
                                                 input.form-control(type='text' ng-model='curValue' placeholder='{{field.placeholder}}')
-                                tr(ng-show='tableNewItemActive(field)')
+                            tfoot(ng-show='tableNewItemActive(field)')
+                                tr
                                     td.col-sm-12
                                         +btn-save('tableSimpleSaveVisible(newValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)')
                                         .input-tip
@@ -284,7 +286,8 @@ mixin form-row-custom(lblClasses, fieldClasses)
                                             label.labelField {{$index + 1}})
                                             +btn-save('tableDbFieldSaveVisible(curDbName, curDbType, curJavaName, curJavaType)', 'tableDbFieldSave(field, curDbName, curDbType, curJavaName, curJavaType, $index)')
                                             +table-db-field-edit('curDbName', 'curDbType', 'curJavaName', 'curJavaType')
-                                tr(ng-show='tableNewItemActive(field)')
+                            tfoot(ng-show='tableNewItemActive(field)')
+                                tr
                                     td.col-sm-12
                                         +btn-save('tableDbFieldSaveVisible(newDbName, newDbType, newJavaName, newJavaType)', 'tableDbFieldSave(field, newDbName, newDbType, newJavaName, newJavaType, -1)')
                                         +table-db-field-edit('newDbName', 'newDbType', 'newJavaName', 'newJavaType')
@@ -296,7 +299,7 @@ mixin form-row-custom(lblClasses, fieldClasses)
             .col-sm-12(ng-show='(#{fieldMdl} && #{fieldMdl}.length > 0) || tableNewItemActive(field)')
                 .col-sm-6
                     .table-details
-                        table.links-edit(st-table=fieldMdl)
+                        table.links-edit.col-sm-12(st-table=fieldMdl)
                             tbody
                                 tr(ng-repeat='group in #{fieldMdl}')
                                     td.col-sm-12
@@ -325,7 +328,8 @@ mixin form-row-custom(lblClasses, fieldClasses)
                                                         td
                                                             +btn-save('tableGroupItemSaveVisible(newFieldName, newClassName)', 'tableGroupItemSave(newFieldName, newClassName, newDirection, groupIndex, -1)')
                                                             +table-group-item-edit('newFieldName', 'newClassName', 'newDirection')
-                                tr(ng-show='tableNewItemActive(field)')
+                            tfoot(ng-show='tableNewItemActive(field)')
+                                tr
                                     td.col-sm-12
                                         +btn-save('tableGroupSaveVisible(newGroupName)', 'tableGroupSave(newGroupName, -1)')
                                         .input-tip


[22/50] [abbrv] incubator-ignite git commit: IGNITE-843 UI Fixes after review.

Posted by an...@apache.org.
IGNITE-843 UI Fixes after review.


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

Branch: refs/heads/ignite-1121
Commit: 56db3f32dc2b27ac336507a9c045bb27845119d7
Parents: 677f5e4
Author: AKuznetsov <ak...@gridgain.com>
Authored: Tue Jul 21 17:29:58 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Tue Jul 21 17:29:58 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/models/clusters.json     |  5 +++-
 .../nodejs/public/stylesheets/style.less        | 25 ++++++++++++++++----
 .../nodejs/views/configuration/caches.jade      |  6 ++---
 .../nodejs/views/configuration/clusters.jade    |  8 +++----
 .../nodejs/views/configuration/metadata.jade    | 18 +++++++-------
 .../nodejs/views/configuration/summary.jade     |  8 +++----
 .../nodejs/views/includes/controls.jade         |  6 +++++
 7 files changed, 49 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/56db3f32/modules/web-control-center/nodejs/controllers/models/clusters.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/clusters.json b/modules/web-control-center/nodejs/controllers/models/clusters.json
index b1955d1..a0f66b5 100644
--- a/modules/web-control-center/nodejs/controllers/models/clusters.json
+++ b/modules/web-control-center/nodejs/controllers/models/clusters.json
@@ -1,6 +1,9 @@
 {
   "screenTip": [
-    "Configure cluster, link caches to them and go to Summary for configuration generation."
+    "1. Configure cluster.",
+    "2. Configure cache type metadata (optional).",
+    "3. Configure caches and link them to cluster.",
+    "4. Generate XML and java code."
   ],
   "templateTip": [
     "Use following template to add a new cluster:",

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/56db3f32/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 61b09d5..495567c 100644
--- a/modules/web-control-center/nodejs/public/stylesheets/style.less
+++ b/modules/web-control-center/nodejs/public/stylesheets/style.less
@@ -19,7 +19,7 @@
 @input-height: 28px;
 @ignite-red: #ec1c24;
 @ignite-block-callout-background: #f3f8f3;
-@ignite-block-callout-border: #50af51;
+@ignite-block-callout: #50af51;
 
 .main-header .logo {
   height: auto;
@@ -719,7 +719,7 @@ button .caret, .btn .caret {
 .theme-line .links table {
   display: table;
   table-layout: fixed;
-  margin-bottom: 20px;
+  margin-bottom: 10px;
 
   td {
     padding-left: 18px;
@@ -1064,12 +1064,27 @@ a {
 .block-callout {
   background-color: @ignite-block-callout-background;
   border-left: 5px solid;
-  border-color: @ignite-block-callout-border;
-  margin-bottom: 20px;
+  border-color: @ignite-block-callout;
+
+  margin-bottom: 10px;
 
   p {
-    padding: 10px 0 10px 10px;
+    padding: 5px 0 10px 15px;
   }
+
+  i {
+    padding: 10px 5px 0 10px;
+    color: @ignite-block-callout;
+  }
+
+  label {
+    font-weight: bold;
+    color: @ignite-block-callout;
+  }
+}
+
+.labelHeader {
+  font-weight: bold;
 }
 
 .ace_editor, #ace_document {

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/56db3f32/modules/web-control-center/nodejs/views/configuration/caches.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/caches.jade b/modules/web-control-center/nodejs/views/configuration/caches.jade
index 8f0fc68..d775eb0 100644
--- a/modules/web-control-center/nodejs/views/configuration/caches.jade
+++ b/modules/web-control-center/nodejs/views/configuration/caches.jade
@@ -23,12 +23,12 @@ include ../includes/controls
 
 block content
     .docs-header
-        h1 Create and configure Ignite caches
+        h1 Create and Configure Ignite Caches
         hr
     .docs-body(ng-controller='cachesController')
-        .block-callout
-            p(ng-bind-html='joinTip(screenTip)')
+        +block-callout('joinTip(screenTip)')
         .links(ng-hide='caches.length == 0')
+            lable.labelHeader Clusters:
             table(st-table='caches')
                 tbody
                     tr(ng-repeat='row in caches track by row._id')

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/56db3f32/modules/web-control-center/nodejs/views/configuration/clusters.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/clusters.jade b/modules/web-control-center/nodejs/views/configuration/clusters.jade
index 02557e9..2ea5498 100644
--- a/modules/web-control-center/nodejs/views/configuration/clusters.jade
+++ b/modules/web-control-center/nodejs/views/configuration/clusters.jade
@@ -23,19 +23,19 @@ include ../includes/controls
 
 block content
     .docs-header
-        h1 Create and configure Ignite clusters
+        h1 Create and Configure Ignite Clusters
         hr
     .docs-body(ng-controller='clustersController')
-        .block-callout
-            p(ng-bind-html='joinTip(screenTip)')
+        +block-callout('joinTip(screenTip)')
         .links(ng-hide='clusters.length == 0')
+            lable.labelHeader Clusters:
             table(st-table='clusters')
                 tbody
                     tr(ng-repeat='row in clusters track by row._id')
                         td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
                             a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.discovery.kind | displayValue:discoveries:'Discovery not set'}}
         button.btn.btn-primary(ng-click='createItem()') &nbspAdd cluster
-        label(style='margin-left: 15px; margin-right: 10px') Use template:
+        label(style='margin-left: 10px; margin-right: 10px') Use template:
         button.btn.btn-default.base-control(ng-init='create.template = templates[0].value' ng-model='create.template' data-template='/select' data-placeholder='Choose cluster template' bs-options='item.value as item.label for item in templates' bs-select)
         i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')
         hr

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/56db3f32/modules/web-control-center/nodejs/views/configuration/metadata.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/metadata.jade b/modules/web-control-center/nodejs/views/configuration/metadata.jade
index bd3eb05..5dd4841 100644
--- a/modules/web-control-center/nodejs/views/configuration/metadata.jade
+++ b/modules/web-control-center/nodejs/views/configuration/metadata.jade
@@ -23,29 +23,29 @@ include ../includes/controls
 
 block content
     .docs-header
-        h1 Create and configure cache type metadata
+        h1 Create and Configure Cache Type Metadata
         hr
     .docs-body(ng-controller='metadataController')
-        .block-callout
-            p(ng-bind-html='joinTip(screenTip)')
+        +block-callout('joinTip(screenTip)')
         .links(ng-hide='metadatas.length == 0')
+            lable.labelHeader Types metadata:
             table(st-table='metadatas')
                 tbody
                     tr(ng-repeat='row in metadatas track by row._id')
                         td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
                             a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
-                hr
-        panel-group(bs-collapse data-allow-multiple="false")
+            button.btn.btn-primary(ng-click='panels.activePanel = [0]; createItem()') &nbspAdd metadata
+            label(style='margin-left: 6px; margin-right: 10px') For:
+            button.btn.btn-default(ng-model='template' data-template='/select' data-placeholder='Choose metadata type' bs-options='item.value as item.label for item in templates' bs-select)
+            i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')
+            hr
+        .panel-group(bs-collapse ng-model="panels.activePanel" data-allow-multiple="false")
             .panel.panel-default
                 .panel-heading
                     h3
                         a(bs-collapse-toggle) Manual
                 .panel-collapse(role="tabpanel" bs-collapse-target)
                     .panel-body
-                        button.btn.btn-primary(ng-click='createItem()') &nbspAdd metadata
-                        label(style='margin-left: 6px; margin-right: 10px') for:
-                        button.btn.btn-default(ng-model='template' data-template='/select' data-placeholder='Choose metadata type' bs-options='item.value as item.label for item in templates' bs-select)
-                        i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')
                         form.form-horizontal(name='manualForm' ng-if='backupItem' novalidate)
                             .settings-row(ng-repeat='field in metadataManual')
                                 +form-row

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/56db3f32/modules/web-control-center/nodejs/views/configuration/summary.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/summary.jade b/modules/web-control-center/nodejs/views/configuration/summary.jade
index 901d72b..0b5a298 100644
--- a/modules/web-control-center/nodejs/views/configuration/summary.jade
+++ b/modules/web-control-center/nodejs/views/configuration/summary.jade
@@ -36,18 +36,16 @@ mixin hard-link(ref, txt)
 
 block content
     .docs-header
-        h1 Configurations summary
+        h1 Configurations Summary
         hr
     .docs-body(ng-controller='summaryController')
-        div
-            .block-callout
-                p(ng-bind-html='joinTip(screenTip)')
+        +block-callout('joinTip(screenTip)')
         div(ng-if='clusters.length == 0')
             | No cluster configured. You can&nbsp;
             a(href='clusters') configure
             | &nbsp;it.
         div(ng-if='clusters.length > 0')
-            p Following cluster configurations were created, you can download them as XML, java code or as docker file.
+            lable.labelHeader Clusters:
             .links
                 table(st-table='clusters')
                     tbody

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/56db3f32/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 53560a8..5aded25 100644
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ b/modules/web-control-center/nodejs/views/includes/controls.jade
@@ -14,6 +14,12 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 
+mixin block-callout(tip)
+    .block-callout
+        i.fa.fa-check-square
+        label Workflow
+        p(ng-bind-html=tip)
+
 mixin tipField(lines)
     i.tipField.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')
     i.tipField.fa.fa-question-circle.blank(ng-if='!#{lines}')


[32/50] [abbrv] incubator-ignite git commit: IGNITE-843 Fixed paddings and margins.

Posted by an...@apache.org.
IGNITE-843 Fixed paddings and margins.


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

Branch: refs/heads/ignite-1121
Commit: e7ebf452ffc6dd49fc93890f37a7a655ccecae86
Parents: 5577b38
Author: AKuznetsov <ak...@gridgain.com>
Authored: Wed Jul 22 17:52:13 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Wed Jul 22 17:52:13 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/models/caches.json       | 21 ++++-
 .../nodejs/controllers/models/clusters.json     | 23 +++--
 .../nodejs/controllers/models/metadata.json     | 22 +++--
 .../nodejs/controllers/models/summary.json      | 19 +++-
 .../nodejs/controllers/summary-controller.js    |  3 +-
 .../nodejs/public/stylesheets/style.less        | 94 +++++++++++++++-----
 .../nodejs/views/configuration/caches.jade      | 54 +++++------
 .../nodejs/views/configuration/clusters.jade    | 52 +++++------
 .../nodejs/views/configuration/metadata.jade    |  6 +-
 .../nodejs/views/configuration/summary.jade     | 10 +--
 .../nodejs/views/includes/controls.jade         | 13 ++-
 11 files changed, 210 insertions(+), 107 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7ebf452/modules/web-control-center/nodejs/controllers/models/caches.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/caches.json b/modules/web-control-center/nodejs/controllers/models/caches.json
index 290013a..0ffc9d4 100644
--- a/modules/web-control-center/nodejs/controllers/models/caches.json
+++ b/modules/web-control-center/nodejs/controllers/models/caches.json
@@ -1,8 +1,21 @@
 {
-  "screenTip": [
-    "Optional cache configuration.",
-    "Configure caches, link them to clusters and go to Summary page for configuration generation."
-  ],
+  "screenTip": {
+    "workflowTitle": "Use Caches view to:",
+    "workflowContent": [
+      "<ul>",
+      "  <li>Configure caches.</li>",
+      "  <li>Associate metadata with cache queries and/or cache store.</li>",
+      "</ul>"
+    ],
+    "whatsNextTitle": "What's next:",
+    "whatsNextContent": [
+      "<ul>",
+      "  <li>Configure clusters.</li>",
+      "  <li>Configure cache type metadata.</li>",
+      "  <li>Generate XML and java code on Summary view.</li>",
+      "</ul>"
+    ]
+  },
   "general": [
     {
       "label": "Name",

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7ebf452/modules/web-control-center/nodejs/controllers/models/clusters.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/clusters.json b/modules/web-control-center/nodejs/controllers/models/clusters.json
index a0f66b5..d6d7d23 100644
--- a/modules/web-control-center/nodejs/controllers/models/clusters.json
+++ b/modules/web-control-center/nodejs/controllers/models/clusters.json
@@ -1,10 +1,21 @@
 {
-  "screenTip": [
-    "1. Configure cluster.",
-    "2. Configure cache type metadata (optional).",
-    "3. Configure caches and link them to cluster.",
-    "4. Generate XML and java code."
-  ],
+  "screenTip": {
+    "workflowTitle": "Use Clusters view to:",
+    "workflowContent": [
+      "<ul>",
+      "  <li>Configure clusters.</li>",
+      "  <li>Associate clusters with caches.</li>",
+      "</ul>"
+    ],
+    "whatsNextTitle": "What's next:",
+    "whatsNextContent": [
+      "<ul>",
+      "  <li>Configure cache type metadata.</li>",
+      "  <li>Configure caches.</li>",
+      "  <li>Generate XML and java code on Summary view.</li>",
+      "</ul>"
+    ]
+  },
   "templateTip": [
     "Use following template to add a new cluster:",
     "<ul>",

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7ebf452/modules/web-control-center/nodejs/controllers/models/metadata.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/metadata.json b/modules/web-control-center/nodejs/controllers/models/metadata.json
index d2d0bea..3248f7a 100644
--- a/modules/web-control-center/nodejs/controllers/models/metadata.json
+++ b/modules/web-control-center/nodejs/controllers/models/metadata.json
@@ -1,9 +1,21 @@
 {
-  "screenTip": [
-    "Optional cache type metadata configuration.",
-    "Enter metadata manually or load from database.",
-    "Generate cache for metadata if needed."
-  ],
+  "screenTip": {
+    "workflowTitle": "Use Cache Type Metadata view to:",
+    "workflowContent": [
+      "<ul>",
+      "  <li>Manually configure metadata for queries and/or store.</li>",
+      "  <li>Configure metadata from database tables metadata.</li>",
+      "</ul>"
+    ],
+    "whatsNextTitle": "What's next:",
+    "whatsNextContent": [
+      "<ul>",
+      "  <li>Configure clusters.</li>",
+      "  <li>Associate caches with metadata.</li>",
+      "  <li>Generate XML and java code on Summary view.</li>",
+      "</ul>"
+    ]
+  },
   "templateTip": [
     "Use following template for metadata:",
     "<ul>",

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7ebf452/modules/web-control-center/nodejs/controllers/models/summary.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/summary.json b/modules/web-control-center/nodejs/controllers/models/summary.json
index 245448c..056291c 100644
--- a/modules/web-control-center/nodejs/controllers/models/summary.json
+++ b/modules/web-control-center/nodejs/controllers/models/summary.json
@@ -1,7 +1,20 @@
 {
-  "screenTip": [
-    "Overview and download XML and java code for cluster configurations."
-  ],
+  "screenTip": {
+    "workflowTitle": "Use Summary view to:",
+    "workflowContent": [
+      "<ul>",
+      "  <li>See XML and java code for server nodes configurations.</li>",
+      "  <li>See XML and java code for client nodes configurations.</li>",
+      "</ul>"
+    ],
+    "whatsNextTitle": "What's next:",
+    "whatsNextContent": [
+      "<ul>",
+      "  <li>Download XML or java code configuration.</li>",
+      "  <li>Start Ignite cluster with downloaded configuration.</li>",
+      "</ul>"
+    ]
+  },
   "clientFields": [
     {
       "label": "Near cache start size",

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7ebf452/modules/web-control-center/nodejs/controllers/summary-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/summary-controller.js b/modules/web-control-center/nodejs/controllers/summary-controller.js
index 2872a58..1291683 100644
--- a/modules/web-control-center/nodejs/controllers/summary-controller.js
+++ b/modules/web-control-center/nodejs/controllers/summary-controller.js
@@ -39,9 +39,8 @@ controlCenterModule.controller('summaryController', ['$scope', '$http', '$common
 
     $http.get('/models/summary.json')
         .success(function (data) {
-            $scope.clientFields = data.clientFields;
-
             $scope.screenTip = data.screenTip;
+            $scope.clientFields = data.clientFields;
         })
         .error(function (errMsg) {
             $common.showError(errMsg);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7ebf452/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 904a807..4900581 100644
--- a/modules/web-control-center/nodejs/public/stylesheets/style.less
+++ b/modules/web-control-center/nodejs/public/stylesheets/style.less
@@ -22,8 +22,8 @@
 @ignite-block-callout: #50af51;
 
 hr {
-  margin-top: 0.65em;
-  margin-bottom: 0.65em;
+  margin-top: 20px;
+  margin-bottom: 20px;
 }
 
 .main-header .logo {
@@ -481,7 +481,7 @@ body {
 h1, h2, h3, h4, h5, h6 {
   font-weight: 700;
   font-family: Roboto Slab, serif;
-  margin-bottom: 0.65em;
+  margin-bottom: 10px;
 }
 
 .submit-vote.submit-vote-parent.voted a.submit-vote-button, .submit-vote.submit-vote-parent a.submit-vote-button:hover {
@@ -525,8 +525,8 @@ a:hover, .link:hover .title {
 
 .modal .close {
   position: absolute;
-  top: 0.65em;
-  right: 0.65em;
+  top: 10px;
+  right: 10px;
   float: none;
 }
 
@@ -606,12 +606,12 @@ h1.ignite-logo {
 }
 
 .details-row {
-  padding: 0 0.65em;
+  padding: 0 10px;
 }
 
 .details-row, .settings-row {
   display: block;
-  margin: 0.65em 0;
+  margin: 10px 0;
 
   label.table-header {
     line-height: @input-height;
@@ -704,12 +704,12 @@ button .caret, .btn .caret {
   }
 
   h3 {
-    margin-bottom: 1.3em;
+    margin-bottom: 20px;
   }
 }
 
 .theme-line .panel-body {
-  padding: 0.65em 1.3em;
+  padding: 10px 20px;
 }
 
 .theme-line .main-content a.customize {
@@ -776,7 +776,7 @@ button .caret, .btn .caret {
   }
 
   thead > tr th.header {
-    padding: 0 0 0.65em;
+    padding: 0 0 10px;
 
     div {
       padding: 0
@@ -791,7 +791,7 @@ button .caret, .btn .caret {
   }
 
   thead > tr th, td {
-    padding: 0.65em 0.65em;
+    padding: 10px 10px;
 
     .input-tip {
       padding: 0;
@@ -802,7 +802,7 @@ button .caret, .btn .caret {
     padding: 0;
 
     .pagination {
-      margin: 0.65em 0;
+      margin: 10px 0;
 
       > .active > a {
         color: @ignite-red;
@@ -819,7 +819,7 @@ button .caret, .btn .caret {
 }
 
 .panel-details {
-  margin-top: 0.65em;
+  margin-top: 10px;
 
   padding: 0;
 
@@ -1081,39 +1081,85 @@ a {
 }
 
 .panel {
-  margin-bottom: 0.65em;
+  margin-bottom: 0;
+}
+
+.panel-group {
+  margin-bottom: 0;
 }
 
 .panel-group .panel + .panel {
-  margin-top: 1.3em;
+  margin-top: 20px;
+}
+
+.margin-top-dflt {
+  margin-top: 10px;
+}
+
+.margin-bottom-dflt {
+  margin-bottom: 10px;
+}
+
+.margin-dflt {
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+
+.padding-top-dflt {
+  padding-top: 10px;
+}
+
+.padding-bottom-dflt {
+  padding-bottom: 10px;
 }
 
 .padding-dflt {
-  padding-top: 0.65em;
-  padding-bottom: 0.65em;
+  padding-top: 10px;
+  padding-bottom: 10px;
 }
 
-.block-callout {
+.theme-line .panel-title h3 {
+  margin-top: 20px;
+  margin-bottom: 20px;
+}
+
+.block-callout-parent {
   background-color: @ignite-block-callout-background;
-  border-left: 5px solid;
-  border-color: @ignite-block-callout;
+  overflow: hidden;
+}
 
-  p {
-    padding: 5px 0 10px 15px;
-    margin: 0;
-  }
+.block-callout {
+  background-color: @ignite-block-callout-background;
+  display: inline-block;
+  vertical-align: top;
+  width: 50%;
 
   i {
     padding: 10px 5px 0 10px;
     color: @ignite-block-callout;
   }
 
+  ul {
+    padding-left: 20px;
+    margin-bottom: 0;
+  }
+
+  p {
+    padding: 5px 0 10px 20px;
+    margin: 0;
+  }
+
   label {
     font-weight: bold;
     color: @ignite-block-callout;
   }
 }
 
+.block-callout-border {
+  border-left: 5px solid;
+  border-color: @ignite-block-callout;
+}
+
 .labelHeader {
   font-weight: bold;
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7ebf452/modules/web-control-center/nodejs/views/configuration/caches.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/caches.jade b/modules/web-control-center/nodejs/views/configuration/caches.jade
index 88521f2..3a011fc 100644
--- a/modules/web-control-center/nodejs/views/configuration/caches.jade
+++ b/modules/web-control-center/nodejs/views/configuration/caches.jade
@@ -26,20 +26,20 @@ block content
         h1 Create and Configure Ignite Caches
         hr
     .docs-body(ng-controller='cachesController')
-        +block-callout('joinTip(screenTip)')
+        +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
         .links(ng-hide='caches.length == 0')
             .padding-dflt
-                lable.labelHeader Clusters:
+                lable.labelHeader Caches:
                 table(st-table='caches')
                     tbody
                         tr(ng-repeat='row in caches track by row._id')
                             td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
                                 a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}}, {{row.atomicityMode | displayValue:atomicities:'Cache atomicity not set'}}
-        .padding-dflt
+        .padding-top-dflt
             button.btn.btn-primary(ng-click='createItem()') Add cache
         hr
         form.form-horizontal(name='inputForm' ng-if='backupItem' novalidate)
-            .padding-dflt(bs-collapse data-start-collapsed='false')
+            div(bs-collapse data-start-collapsed='false')
                 .panel.panel-default
                     .panel-heading
                         h3
@@ -48,25 +48,27 @@ block content
                         .panel-body
                             .settings-row(ng-repeat='field in general')
                                 +form-row(['col-sm-3'], ['col-sm-3'])
-            div(bs-collapse data-start-collapsed='true')
-                .panel-title(ng-show='expanded')
-                    h3
-                        a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
-                .panel-collapse(bs-collapse-target)
-                    .span(bs-collapse data-start-collapsed='true' data-allow-multiple='true')
-                        .panel.panel-default(ng-repeat='group in advanced')
-                            .panel-heading
-                                h3
-                                    a(bs-collapse-toggle) {{group.label}}
-                                    i.tipLabel.fa.fa-question-circle(ng-if='group.tip' bs-tooltip='joinTip(group.tip)' type='button')
-                                    i.tipLabel.fa.fa-question-circle.blank(ng-if='!group.tip')
-                            .panel-collapse(bs-collapse-target)
-                                .panel-body
-                                    .settings-row(ng-repeat='field in group.fields')
-                                        +form-row
-                .panel-title
-                    h3
-                        a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
-            button.btn.btn-primary(ng-disabled='inputForm.$invalid' ng-click='saveItem()') Save
-            button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
-            button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove
+            .panel-group(bs-collapse data-allow-multiple="true")
+                div(bs-collapse data-start-collapsed='true')
+                    .panel-title(ng-show='expanded')
+                        h3
+                            a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
+                    .panel-collapse(bs-collapse-target)
+                        .span(bs-collapse data-start-collapsed='true' data-allow-multiple='true')
+                            .panel.panel-default(ng-repeat='group in advanced')
+                                .panel-heading
+                                    h3
+                                        a(bs-collapse-toggle) {{group.label}}
+                                        i.tipLabel.fa.fa-question-circle(ng-if='group.tip' bs-tooltip='joinTip(group.tip)' type='button')
+                                        i.tipLabel.fa.fa-question-circle.blank(ng-if='!group.tip')
+                                .panel-collapse(bs-collapse-target)
+                                    .panel-body
+                                        .settings-row(ng-repeat='field in group.fields')
+                                            +form-row
+                    .panel-title
+                        h3
+                            a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
+            div
+                button.btn.btn-primary(ng-disabled='inputForm.$invalid' ng-click='saveItem()') Save
+                button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
+                button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7ebf452/modules/web-control-center/nodejs/views/configuration/clusters.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/clusters.jade b/modules/web-control-center/nodejs/views/configuration/clusters.jade
index 576ee4d..81acfed 100644
--- a/modules/web-control-center/nodejs/views/configuration/clusters.jade
+++ b/modules/web-control-center/nodejs/views/configuration/clusters.jade
@@ -26,7 +26,7 @@ block content
         h1 Create and Configure Ignite Clusters
         hr
     .docs-body(ng-controller='clustersController')
-        +block-callout('joinTip(screenTip)')
+        +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
         .links(ng-hide='clusters.length == 0')
             .padding-dflt
                 lable.labelHeader Clusters:
@@ -35,14 +35,14 @@ block content
                         tr(ng-repeat='row in clusters track by row._id')
                             td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
                                 a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.discovery.kind | displayValue:discoveries:'Discovery not set'}}
-        .padding-dflt
+        .padding-top-dflt
             button.btn.btn-primary(ng-click='createItem()') &nbspAdd cluster
             label(style='margin-left: 10px; margin-right: 10px') Use template:
             button.btn.btn-default.base-control(ng-init='create.template = templates[0].value' ng-model='create.template' data-template='/select' data-placeholder='Choose cluster template' bs-options='item.value as item.label for item in templates' bs-select)
             i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')
         hr
         form.form-horizontal(name='inputForm' ng-if='backupItem' novalidate)
-            .padding-dflt(bs-collapse data-start-collapsed='false')
+            div(bs-collapse data-start-collapsed='false')
                 .panel.panel-default
                     .panel-heading
                         h3
@@ -51,25 +51,27 @@ block content
                         .panel-body
                             .settings-row(ng-repeat='field in general')
                                 +form-row
-            div(bs-collapse data-start-collapsed='true')
-                .panel-title(ng-show='expanded')
-                    h3
-                        a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
-                .panel-collapse(bs-collapse-target)
-                    .span(bs-collapse data-start-collapsed='true' data-allow-multiple='true')
-                        .panel.panel-default(ng-repeat='group in advanced')
-                            .panel-heading
-                                h3
-                                    a(bs-collapse-toggle) {{group.label}}
-                                    i.tipLabel.fa.fa-question-circle(ng-if='group.tip' bs-tooltip='joinTip(group.tip)' type='button')
-                                    i.tipLabel.fa.fa-question-circle.blank(ng-if='!group.tip')
-                            .panel-collapse(bs-collapse-target)
-                                .panel-body
-                                    .settings-row(ng-repeat='field in group.fields')
-                                        +form-row
-                .panel-title
-                    h3
-                        a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
-            button.btn.btn-primary(ng-disabled='inputForm.$invalid' ng-click='saveItem()') Save
-            button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
-            button.btn.btn-primary(ng-show='backupItem._id' ng-click='removeItem()') Remove
\ No newline at end of file
+            .panel-group(bs-collapse data-allow-multiple="true")
+                div(bs-collapse data-start-collapsed='true')
+                    .panel-title(ng-show='expanded')
+                        h3
+                            a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
+                    .panel-collapse(bs-collapse-target)
+                        .span(bs-collapse data-start-collapsed='true' data-allow-multiple='true')
+                            .panel.panel-default(ng-repeat='group in advanced')
+                                .panel-heading
+                                    h3
+                                        a(bs-collapse-toggle) {{group.label}}
+                                        i.tipLabel.fa.fa-question-circle(ng-if='group.tip' bs-tooltip='joinTip(group.tip)' type='button')
+                                        i.tipLabel.fa.fa-question-circle.blank(ng-if='!group.tip')
+                                .panel-collapse(bs-collapse-target)
+                                    .panel-body
+                                        .settings-row(ng-repeat='field in group.fields')
+                                            +form-row
+                    .panel-title
+                        h3
+                            a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
+            div
+                button.btn.btn-primary(ng-disabled='inputForm.$invalid' ng-click='saveItem()') Save
+                button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
+                button.btn.btn-primary(ng-show='backupItem._id' ng-click='removeItem()') Remove
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7ebf452/modules/web-control-center/nodejs/views/configuration/metadata.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/metadata.jade b/modules/web-control-center/nodejs/views/configuration/metadata.jade
index 12fb616..d5bac06 100644
--- a/modules/web-control-center/nodejs/views/configuration/metadata.jade
+++ b/modules/web-control-center/nodejs/views/configuration/metadata.jade
@@ -26,7 +26,7 @@ block content
         h1 Create and Configure Cache Type Metadata
         hr
     .docs-body(ng-controller='metadataController')
-        +block-callout('joinTip(screenTip)')
+        +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
         .links(ng-hide='metadatas.length == 0')
             .padding-dflt
                 lable.labelHeader Types metadata:
@@ -35,13 +35,13 @@ block content
                         tr(ng-repeat='row in metadatas track by row._id')
                             td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
                                 a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
-        .padding-dflt
+        .padding-top-dflt
             button.btn.btn-primary(ng-click='panels.activePanel = [0]; createItem()') &nbspAdd metadata
             label(style='margin-left: 6px; margin-right: 10px') For:
             button.btn.btn-default(ng-model='template' data-template='/select' data-placeholder='Choose metadata type' bs-options='item.value as item.label for item in templates' bs-select)
             i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')
         hr
-        .panel-group.padding-dflt(bs-collapse ng-model='panels.activePanel' data-allow-multiple="false")
+        .panel-group(bs-collapse ng-model='panels.activePanel' data-allow-multiple="false")
             .panel.panel-default
                 .panel-heading
                     h3

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7ebf452/modules/web-control-center/nodejs/views/configuration/summary.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/summary.jade b/modules/web-control-center/nodejs/views/configuration/summary.jade
index 0b5a298..6f2f6d8 100644
--- a/modules/web-control-center/nodejs/views/configuration/summary.jade
+++ b/modules/web-control-center/nodejs/views/configuration/summary.jade
@@ -39,12 +39,12 @@ block content
         h1 Configurations Summary
         hr
     .docs-body(ng-controller='summaryController')
-        +block-callout('joinTip(screenTip)')
-        div(ng-if='clusters.length == 0')
+        +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
+        .padding-dflt(ng-if='clusters.length == 0')
             | No cluster configured. You can&nbsp;
             a(href='clusters') configure
             | &nbsp;it.
-        div(ng-if='clusters.length > 0')
+        .padding-dflt(ng-if='clusters.length > 0')
             lable.labelHeader Clusters:
             .links
                 table(st-table='clusters')
@@ -53,7 +53,7 @@ block content
                             td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
                                 a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
         div(ng-show='selectedItem' role="tab" method='post' action='summary/download')
-            div(bs-collapse data-start-collapsed='false')
+            .padding-dflt(bs-collapse data-start-collapsed='false')
                 .panel.panel-default
                     form.panel-heading(role='tab' method='post' action='summary/download')
                         input(type="hidden" name="_id" value="{{selectedItem._id}}")
@@ -90,7 +90,7 @@ block content
                                         .col-sm-4
                                             input#os.form-control(type='text', ng-model='configServer.os' placeholder='debian:8' data-min-length="0" data-html="1" data-auto-select="true" data-animation="am-flip-x" bs-typeahead bs-options='os for os in oss')
                                     div(ui-ace='{ onLoad: aceInit, mode: "dockerfile" }' ng-model='dockerServer')
-            div(bs-collapse data-start-collapsed='false')
+            .padding-dflt(bs-collapse data-start-collapsed='false')
                 .panel.panel-default
                     form.panel-heading(role='tab' method='post' action='summary/download')
                         input(type="hidden" name="_id" value="{{selectedItem._id}}")

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7ebf452/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 26f6bf9..4a618fa 100644
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ b/modules/web-control-center/nodejs/views/includes/controls.jade
@@ -14,12 +14,17 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 
-mixin block-callout(tip)
-    .padding-dflt
+mixin block-callout(titleWorkflow, contentWorkflow, whatsNextWorkflow, whatsNextContent)
+    .block-callout-parent.block-callout-border.margin-bottom-dflt
         .block-callout
             i.fa.fa-check-square
-            label Workflow
-            p(ng-bind-html=tip)
+            label #{titleWorkflow}
+            p(ng-bind-html=contentWorkflow)
+        .block-callout
+            i.fa.fa-check-square
+            label #{whatsNextWorkflow}
+            p(ng-bind-html=whatsNextContent)
+
 
 mixin tipField(lines)
     i.tipField.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')


[29/50] [abbrv] incubator-ignite git commit: IGNITE-843 css padding.

Posted by an...@apache.org.
IGNITE-843 css padding.


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

Branch: refs/heads/ignite-1121
Commit: ff3cebce76edbb0848ff01704a6a421a9b2ec245
Parents: 7ad2c82
Author: AKuznetsov <ak...@gridgain.com>
Authored: Wed Jul 22 09:35:28 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Wed Jul 22 09:35:28 2015 +0700

----------------------------------------------------------------------
 .../web-control-center/nodejs/public/stylesheets/style.less   | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/ff3cebce/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 f2cb9bc..f858df5 100644
--- a/modules/web-control-center/nodejs/public/stylesheets/style.less
+++ b/modules/web-control-center/nodejs/public/stylesheets/style.less
@@ -21,6 +21,11 @@
 @ignite-block-callout-background: #f3f8f3;
 @ignite-block-callout: #50af51;
 
+hr {
+  margin-top: 1.3em;
+  margin-bottom: 1.3em;
+}
+
 .main-header .logo {
   height: auto;
 }
@@ -1080,7 +1085,7 @@ a {
   border-left: 5px solid;
   border-color: @ignite-block-callout;
 
-  margin-bottom: 10px;
+  margin-bottom: 1.3em;
 
   p {
     padding: 5px 0 10px 15px;


[20/50] [abbrv] incubator-ignite git commit: IGNITE-843 Fixed tables editors.

Posted by an...@apache.org.
IGNITE-843 Fixed tables editors.


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

Branch: refs/heads/ignite-1121
Commit: 692cee9a35d1de254bff7fdfa198ccbc70b58c6e
Parents: 53cd4b3
Author: AKuznetsov <ak...@gridgain.com>
Authored: Tue Jul 21 14:19:00 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Tue Jul 21 14:19:00 2015 +0700

----------------------------------------------------------------------
 .../nodejs/views/includes/controls.jade               | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/692cee9a/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 141a198..53560a8 100644
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ b/modules/web-control-center/nodejs/views/includes/controls.jade
@@ -114,7 +114,7 @@ mixin details-row
             div(ng-if='detail.label')
                 label.table-header {{detail.label}}:
                 +tipLabel('detail.tableTip')
-            table.col-sm-12.links-edit-details(st-table='#{detailMdl}' ng-show='#{detailMdl}.length > 0')
+            table.col-sm-12.links-edit-details(st-table='#{detailMdl}')
                 tbody
                     tr(ng-repeat='item in #{detailMdl} track by $index')
                         td
@@ -136,13 +136,13 @@ mixin details-row
                 +ico-exclamation('{{detail.model}}', 'ipaddress', 'Invalid address, see help for format description.')
 
 mixin table-db-field-edit(dbName, dbType, javaName, javaType)
-    div(style='width: 20%; float: right')
+    div(style='width: 22%; float: right')
         button.form-control(ng-model=javaType bs-select data-placeholder='Java type' bs-options='item.value as item.label for item in {{javaTypes}}')
     label.fieldSep /
-    div(style='width: 22%; float: right')
+    div(style='width: 20%; float: right')
         input.form-control(type='text' ng-model=javaName placeholder='Java name')
     label.fieldSep /
-    div(style='width: 20%; float: right')
+    div(style='width: 22%; float: right')
         button.form-control(ng-model=dbType bs-select data-placeholder='JDBC type' bs-options='item.value as item.label for item in {{jdbcTypes}}')
     label.fieldSep /
     .input-tip
@@ -254,7 +254,7 @@ mixin form-row-custom(lblClasses, fieldClasses)
                 label.table-header {{field.label}}:
                 +tipLabel('field.tip')
                 button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-            table.links-edit.col-sm-12(st-table=fieldMdl ng-show='#{fieldMdl}.length > 0')
+            table.links-edit.col-sm-12(st-table=fieldMdl)
                 tbody
                     tr.col-sm-12(ng-repeat='item in #{fieldMdl}')
                         td.col-sm-6
@@ -274,7 +274,7 @@ mixin form-row-custom(lblClasses, fieldClasses)
                 label.table-header {{field.label}}:
                 +tipLabel('field.tip')
                 button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-            table.links-edit.col-sm-12(st-table=fieldMdl ng-show='#{fieldMdl}.length > 0')
+            table.links-edit.col-sm-12(st-table=fieldMdl)
                 tbody
                     tr.col-sm-12(ng-repeat='group in #{fieldMdl}')
                         td.col-sm-6
@@ -289,7 +289,7 @@ mixin form-row-custom(lblClasses, fieldClasses)
                                     .input-tip
                                         input.form-control(type='text' ng-model='curGroupName' placeholder='Index name')
                                 div
-                                    table.links-edit.col-sm-12(st-table='group.fields' ng-show='group.fields.length > 0' ng-init='groupIndex = $index')
+                                    table.links-edit.col-sm-12(st-table='group.fields' ng-init='groupIndex = $index')
                                         tr(ng-repeat='groupItem in group.fields')
                                             td
                                                 div(ng-show='!tableGroupItemEditing(groupIndex, $index)')


[28/50] [abbrv] incubator-ignite git commit: Merge remote-tracking branch 'origin/ignite-843' into ignite-843

Posted by an...@apache.org.
Merge remote-tracking branch 'origin/ignite-843' into ignite-843


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

Branch: refs/heads/ignite-1121
Commit: 7ad2c82b563f4f2bf964e1e9f341ad5042c40242
Parents: 74c1a5f fe13f02
Author: AKuznetsov <ak...@gridgain.com>
Authored: Wed Jul 22 09:25:06 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Wed Jul 22 09:25:06 2015 +0700

----------------------------------------------------------------------
 .../nodejs/views/includes/controls.jade            | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)
----------------------------------------------------------------------



[31/50] [abbrv] incubator-ignite git commit: IGNITE-843 Rename "saveAs" to "copy".

Posted by an...@apache.org.
IGNITE-843 Rename "saveAs" to "copy".


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

Branch: refs/heads/ignite-1121
Commit: 5577b3898eda48ecfac840bbe0835c02357f5c9e
Parents: ff3cebc
Author: AKuznetsov <ak...@gridgain.com>
Authored: Wed Jul 22 13:38:56 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Wed Jul 22 13:38:56 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/caches-controller.js     |  4 +--
 .../nodejs/controllers/clusters-controller.js   |  4 +--
 .../nodejs/controllers/common-module.js         | 12 ++++----
 .../nodejs/controllers/metadata-controller.js   |  4 +--
 .../nodejs/public/stylesheets/style.less        | 22 ++++++++++----
 .../web-control-center/nodejs/routes/public.js  |  4 +--
 .../nodejs/views/configuration/caches.jade      | 20 +++++++------
 .../nodejs/views/configuration/clusters.jade    | 26 ++++++++--------
 .../nodejs/views/configuration/metadata.jade    | 21 ++++++-------
 .../nodejs/views/includes/controls.jade         |  9 +++---
 .../nodejs/views/templates/copy.jade            | 31 ++++++++++++++++++++
 .../nodejs/views/templates/saveAs.jade          | 31 --------------------
 12 files changed, 103 insertions(+), 85 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5577b389/modules/web-control-center/nodejs/controllers/caches-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/caches-controller.js b/modules/web-control-center/nodejs/controllers/caches-controller.js
index b050103..0c23e3b 100644
--- a/modules/web-control-center/nodejs/controllers/caches-controller.js
+++ b/modules/web-control-center/nodejs/controllers/caches-controller.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-controlCenterModule.controller('cachesController', ['$scope', '$http', '$common', '$confirm', '$saveAs', '$table', function ($scope, $http, $common, $confirm, $saveAs, $table) {
+controlCenterModule.controller('cachesController', ['$scope', '$http', '$common', '$confirm', '$copy', '$table', function ($scope, $http, $common, $confirm, $copy, $table) {
         $scope.joinTip = $common.joinTip;
         $scope.getModel = $common.getModel;
 
@@ -282,7 +282,7 @@ controlCenterModule.controller('cachesController', ['$scope', '$http', '$common'
             $table.tableReset();
 
             if (validate($scope.backupItem))
-                $saveAs.show($scope.backupItem.name).then(function (newName) {
+                $copy.show($scope.backupItem.name).then(function (newName) {
                     var item = angular.copy($scope.backupItem);
 
                     item._id = undefined;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5577b389/modules/web-control-center/nodejs/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/clusters-controller.js b/modules/web-control-center/nodejs/controllers/clusters-controller.js
index 996e2a3..1ec78a1 100644
--- a/modules/web-control-center/nodejs/controllers/clusters-controller.js
+++ b/modules/web-control-center/nodejs/controllers/clusters-controller.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-controlCenterModule.controller('clustersController', ['$scope', '$http', '$common', '$confirm', '$saveAs', '$table', function ($scope, $http, $common, $confirm, $saveAs, $table) {
+controlCenterModule.controller('clustersController', ['$scope', '$http', '$common', '$confirm', '$copy', '$table', function ($scope, $http, $common, $confirm, $copy, $table) {
         $scope.joinTip = $common.joinTip;
         $scope.getModel = $common.getModel;
 
@@ -258,7 +258,7 @@ controlCenterModule.controller('clustersController', ['$scope', '$http', '$commo
             $table.tableReset();
 
             if (validate($scope.backupItem))
-                $saveAs.show($scope.backupItem.name).then(function (newName) {
+                $copy.show($scope.backupItem.name).then(function (newName) {
                     var item = angular.copy($scope.backupItem);
 
                     item._id = undefined;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5577b389/modules/web-control-center/nodejs/controllers/common-module.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/common-module.js b/modules/web-control-center/nodejs/controllers/common-module.js
index 5118af8..75af155 100644
--- a/modules/web-control-center/nodejs/controllers/common-module.js
+++ b/modules/web-control-center/nodejs/controllers/common-module.js
@@ -163,7 +163,7 @@ controlCenterModule.service('$confirm', function ($modal, $rootScope, $q) {
 });
 
 // "Save as" popup service.
-controlCenterModule.service('$saveAs', function ($modal, $rootScope, $q) {
+controlCenterModule.service('$copy', function ($modal, $rootScope, $q) {
     var scope = $rootScope.$new();
 
     var deferred;
@@ -171,14 +171,14 @@ controlCenterModule.service('$saveAs', function ($modal, $rootScope, $q) {
     scope.ok = function (newName) {
         deferred.resolve(newName);
 
-        saveAsModal.hide();
+        copyModal.hide();
     };
 
-    var saveAsModal = $modal({templateUrl: '/saveAs', scope: scope, placement: 'center', show: false});
+    var copyModal = $modal({templateUrl: '/copy', scope: scope, placement: 'center', show: false});
 
-    var parentShow = saveAsModal.show;
+    var parentShow = copyModal.show;
 
-    saveAsModal.show = function (oldName) {
+    copyModal.show = function (oldName) {
         scope.newName = oldName + '(1)';
 
         deferred = $q.defer();
@@ -188,7 +188,7 @@ controlCenterModule.service('$saveAs', function ($modal, $rootScope, $q) {
         return deferred.promise;
     };
 
-    return saveAsModal;
+    return copyModal;
 });
 
 // Tables support service.

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5577b389/modules/web-control-center/nodejs/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/metadata-controller.js b/modules/web-control-center/nodejs/controllers/metadata-controller.js
index eb48494..b62cde5 100644
--- a/modules/web-control-center/nodejs/controllers/metadata-controller.js
+++ b/modules/web-control-center/nodejs/controllers/metadata-controller.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-controlCenterModule.controller('metadataController', ['$scope', '$http', '$common', '$confirm', '$saveAs', '$table', function ($scope, $http, $common, $confirm, $saveAs, $table) {
+controlCenterModule.controller('metadataController', ['$scope', '$http', '$common', '$confirm', '$copy', '$table', function ($scope, $http, $common, $confirm, $copy, $table) {
         $scope.joinTip = $common.joinTip;
         $scope.getModel = $common.getModel;
 
@@ -362,7 +362,7 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             $table.tableReset();
 
             if (validate($scope.backupItem))
-                $saveAs.show($scope.backupItem.name).then(function (newName) {
+                $copy.show($scope.backupItem.name).then(function (newName) {
                     var item = angular.copy($scope.backupItem);
 
                     item._id = undefined;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5577b389/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 f858df5..904a807 100644
--- a/modules/web-control-center/nodejs/public/stylesheets/style.less
+++ b/modules/web-control-center/nodejs/public/stylesheets/style.less
@@ -22,8 +22,8 @@
 @ignite-block-callout: #50af51;
 
 hr {
-  margin-top: 1.3em;
-  margin-bottom: 1.3em;
+  margin-top: 0.65em;
+  margin-bottom: 0.65em;
 }
 
 .main-header .logo {
@@ -481,6 +481,7 @@ body {
 h1, h2, h3, h4, h5, h6 {
   font-weight: 700;
   font-family: Roboto Slab, serif;
+  margin-bottom: 0.65em;
 }
 
 .submit-vote.submit-vote-parent.voted a.submit-vote-button, .submit-vote.submit-vote-parent a.submit-vote-button:hover {
@@ -723,7 +724,6 @@ button .caret, .btn .caret {
 .theme-line .links table {
   display: table;
   table-layout: fixed;
-  margin-bottom: 10px;
 
   td {
     padding-left: 18px;
@@ -1080,15 +1080,27 @@ a {
   content: '\25BC';
 }
 
+.panel {
+  margin-bottom: 0.65em;
+}
+
+.panel-group .panel + .panel {
+  margin-top: 1.3em;
+}
+
+.padding-dflt {
+  padding-top: 0.65em;
+  padding-bottom: 0.65em;
+}
+
 .block-callout {
   background-color: @ignite-block-callout-background;
   border-left: 5px solid;
   border-color: @ignite-block-callout;
 
-  margin-bottom: 1.3em;
-
   p {
     padding: 5px 0 10px 15px;
+    margin: 0;
   }
 
   i {

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5577b389/modules/web-control-center/nodejs/routes/public.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/public.js b/modules/web-control-center/nodejs/routes/public.js
index 71cf406..290ba90 100644
--- a/modules/web-control-center/nodejs/routes/public.js
+++ b/modules/web-control-center/nodejs/routes/public.js
@@ -35,8 +35,8 @@ router.get('/confirm', function (req, res) {
 });
 
 // GET save as dialog.
-router.get('/saveAs', function (req, res) {
-    res.render('templates/saveAs', {});
+router.get('/copy', function (req, res) {
+    res.render('templates/copy', {});
 });
 
 /* GET login page. */

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5577b389/modules/web-control-center/nodejs/views/configuration/caches.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/caches.jade b/modules/web-control-center/nodejs/views/configuration/caches.jade
index d775eb0..88521f2 100644
--- a/modules/web-control-center/nodejs/views/configuration/caches.jade
+++ b/modules/web-control-center/nodejs/views/configuration/caches.jade
@@ -28,16 +28,18 @@ block content
     .docs-body(ng-controller='cachesController')
         +block-callout('joinTip(screenTip)')
         .links(ng-hide='caches.length == 0')
-            lable.labelHeader Clusters:
-            table(st-table='caches')
-                tbody
-                    tr(ng-repeat='row in caches track by row._id')
-                        td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
-                            a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}}, {{row.atomicityMode | displayValue:atomicities:'Cache atomicity not set'}}
-        button.btn.btn-primary(ng-click='createItem()') Add cache
+            .padding-dflt
+                lable.labelHeader Clusters:
+                table(st-table='caches')
+                    tbody
+                        tr(ng-repeat='row in caches track by row._id')
+                            td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
+                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}}, {{row.atomicityMode | displayValue:atomicities:'Cache atomicity not set'}}
+        .padding-dflt
+            button.btn.btn-primary(ng-click='createItem()') Add cache
         hr
         form.form-horizontal(name='inputForm' ng-if='backupItem' novalidate)
-            div(bs-collapse data-start-collapsed='false')
+            .padding-dflt(bs-collapse data-start-collapsed='false')
                 .panel.panel-default
                     .panel-heading
                         h3
@@ -66,5 +68,5 @@ block content
                     h3
                         a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
             button.btn.btn-primary(ng-disabled='inputForm.$invalid' ng-click='saveItem()') Save
-            button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Save As
+            button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
             button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5577b389/modules/web-control-center/nodejs/views/configuration/clusters.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/clusters.jade b/modules/web-control-center/nodejs/views/configuration/clusters.jade
index 2ea5498..576ee4d 100644
--- a/modules/web-control-center/nodejs/views/configuration/clusters.jade
+++ b/modules/web-control-center/nodejs/views/configuration/clusters.jade
@@ -28,19 +28,21 @@ block content
     .docs-body(ng-controller='clustersController')
         +block-callout('joinTip(screenTip)')
         .links(ng-hide='clusters.length == 0')
-            lable.labelHeader Clusters:
-            table(st-table='clusters')
-                tbody
-                    tr(ng-repeat='row in clusters track by row._id')
-                        td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
-                            a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.discovery.kind | displayValue:discoveries:'Discovery not set'}}
-        button.btn.btn-primary(ng-click='createItem()') &nbspAdd cluster
-        label(style='margin-left: 10px; margin-right: 10px') Use template:
-        button.btn.btn-default.base-control(ng-init='create.template = templates[0].value' ng-model='create.template' data-template='/select' data-placeholder='Choose cluster template' bs-options='item.value as item.label for item in templates' bs-select)
-        i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')
+            .padding-dflt
+                lable.labelHeader Clusters:
+                table(st-table='clusters')
+                    tbody
+                        tr(ng-repeat='row in clusters track by row._id')
+                            td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
+                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.discovery.kind | displayValue:discoveries:'Discovery not set'}}
+        .padding-dflt
+            button.btn.btn-primary(ng-click='createItem()') &nbspAdd cluster
+            label(style='margin-left: 10px; margin-right: 10px') Use template:
+            button.btn.btn-default.base-control(ng-init='create.template = templates[0].value' ng-model='create.template' data-template='/select' data-placeholder='Choose cluster template' bs-options='item.value as item.label for item in templates' bs-select)
+            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')
+            .padding-dflt(bs-collapse data-start-collapsed='false')
                 .panel.panel-default
                     .panel-heading
                         h3
@@ -69,5 +71,5 @@ block content
                     h3
                         a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
             button.btn.btn-primary(ng-disabled='inputForm.$invalid' ng-click='saveItem()') Save
-            button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Save As
+            button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
             button.btn.btn-primary(ng-show='backupItem._id' ng-click='removeItem()') Remove
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5577b389/modules/web-control-center/nodejs/views/configuration/metadata.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/metadata.jade b/modules/web-control-center/nodejs/views/configuration/metadata.jade
index 0a601d8..12fb616 100644
--- a/modules/web-control-center/nodejs/views/configuration/metadata.jade
+++ b/modules/web-control-center/nodejs/views/configuration/metadata.jade
@@ -28,19 +28,20 @@ block content
     .docs-body(ng-controller='metadataController')
         +block-callout('joinTip(screenTip)')
         .links(ng-hide='metadatas.length == 0')
-            lable.labelHeader Types metadata:
-            table(st-table='metadatas')
-                tbody
-                    tr(ng-repeat='row in metadatas track by row._id')
-                        td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
-                            a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
-        div
+            .padding-dflt
+                lable.labelHeader Types metadata:
+                table(st-table='metadatas')
+                    tbody
+                        tr(ng-repeat='row in metadatas track by row._id')
+                            td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
+                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
+        .padding-dflt
             button.btn.btn-primary(ng-click='panels.activePanel = [0]; createItem()') &nbspAdd metadata
             label(style='margin-left: 6px; margin-right: 10px') For:
             button.btn.btn-default(ng-model='template' data-template='/select' data-placeholder='Choose metadata type' bs-options='item.value as item.label for item in templates' bs-select)
             i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')
-            hr
-        .panel-group(bs-collapse ng-model='panels.activePanel' data-allow-multiple="false")
+        hr
+        .panel-group.padding-dflt(bs-collapse ng-model='panels.activePanel' data-allow-multiple="false")
             .panel.panel-default
                 .panel-heading
                     h3
@@ -51,7 +52,7 @@ block content
                             .settings-row(ng-repeat='field in metadataManual')
                                 +form-row
                             button.btn.btn-primary(ng-disabled='manualForm.$invalid' ng-click='saveItem()') Save
-                            button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Save As
+                            button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
                             button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove
             .panel.panel-default
                 .panel-heading

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5577b389/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 0ed22b6..26f6bf9 100644
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ b/modules/web-control-center/nodejs/views/includes/controls.jade
@@ -15,10 +15,11 @@
     limitations under the License.
 
 mixin block-callout(tip)
-    .block-callout
-        i.fa.fa-check-square
-        label Workflow
-        p(ng-bind-html=tip)
+    .padding-dflt
+        .block-callout
+            i.fa.fa-check-square
+            label Workflow
+            p(ng-bind-html=tip)
 
 mixin tipField(lines)
     i.tipField.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5577b389/modules/web-control-center/nodejs/views/templates/copy.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/templates/copy.jade b/modules/web-control-center/nodejs/views/templates/copy.jade
new file mode 100644
index 0000000..22cc64c
--- /dev/null
+++ b/modules/web-control-center/nodejs/views/templates/copy.jade
@@ -0,0 +1,31 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+.modal(tabindex='-1' role='dialog')
+    .modal-dialog
+        .modal-content
+            .modal-header
+                button.close(type="button" ng-click="$hide()") &times;
+                h4.modal-title Copy
+            form.form-horizontal(name='inputForm' novalidate)
+                .modal-body.row
+                    .col-sm-9.login.col-sm-offset-1
+                        label.required.labelFormField() New name:&nbsp;
+                        .col-sm-9
+                            input.form-control(type="text" ng-model='newName' required)
+            .modal-footer
+                button.btn.btn-default(type="button" ng-click="$hide()") Cancel
+                button.btn.btn-primary(type="button" ng-disabled='inputForm.$invalid' ng-click="ok(newName)") Confirm
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5577b389/modules/web-control-center/nodejs/views/templates/saveAs.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/templates/saveAs.jade b/modules/web-control-center/nodejs/views/templates/saveAs.jade
deleted file mode 100644
index 83f93bd..0000000
--- a/modules/web-control-center/nodejs/views/templates/saveAs.jade
+++ /dev/null
@@ -1,31 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-.modal(tabindex='-1' role='dialog')
-    .modal-dialog
-        .modal-content
-            .modal-header
-                button.close(type="button" ng-click="$hide()") &times;
-                h4.modal-title Save as
-            form.form-horizontal(name='inputForm' novalidate)
-                .modal-body.row
-                    .col-sm-9.login.col-sm-offset-1
-                        label.required.labelFormField() New name:&nbsp;
-                        .col-sm-9
-                            input.form-control(type="text" ng-model='newName' required)
-            .modal-footer
-                button.btn.btn-default(type="button" ng-click="$hide()") Cancel
-                button.btn.btn-primary(type="button" ng-disabled='inputForm.$invalid' ng-click="ok(newName)") Confirm
\ No newline at end of file


[40/50] [abbrv] incubator-ignite git commit: # ignite-843 moved

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/routes/generator/xml.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/generator/xml.js b/modules/web-control-center/nodejs/routes/generator/xml.js
deleted file mode 100644
index 16ef23b..0000000
--- a/modules/web-control-center/nodejs/routes/generator/xml.js
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var _ = require('lodash');
-
-var generatorUtils = require("./common");
-var dataStructures = require("../../helpers/data-structures.js");
-
-exports.generateClusterConfiguration = function(cluster, clientNearConfiguration) {
-    var res = generatorUtils.builder();
-
-    res.datasources = [];
-    res.deep = 1;
-
-    if (clientNearConfiguration) {
-        res.startBlock('<bean id="nearCacheBean" class="org.apache.ignite.configuration.NearCacheConfiguration">');
-
-        if (clientNearConfiguration.nearStartSize)
-            addProperty(res, clientNearConfiguration, 'nearStartSize');
-
-        if (clientNearConfiguration.nearEvictionPolicy && clientNearConfiguration.nearEvictionPolicy.kind)
-            createEvictionPolicy(res, clientNearConfiguration.nearEvictionPolicy, 'nearEvictionPolicy');
-
-        res.endBlock('</bean>');
-
-        res.line();
-    }
-
-    // Generate Ignite Configuration.
-    res.startBlock('<bean class="org.apache.ignite.configuration.IgniteConfiguration">');
-
-    if (clientNearConfiguration) {
-        res.line('<property name="clientMode" value="true" />');
-
-        res.line();
-    }
-
-    // Generate discovery.
-    if (cluster.discovery) {
-        res.startBlock('<property name="discoverySpi">');
-        res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">');
-        res.startBlock('<property name="ipFinder">');
-
-        var d = cluster.discovery;
-
-        switch (d.kind) {
-            case 'Multicast':
-                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">');
-
-                addProperty(res, d.Multicast, 'multicastGroup');
-                addProperty(res, d.Multicast, 'multicastPort');
-                addProperty(res, d.Multicast, 'responseWaitTime');
-                addProperty(res, d.Multicast, 'addressRequestAttempts');
-                addProperty(res, d.Multicast, 'localAddress');
-
-                res.endBlock('</bean>');
-
-                break;
-
-            case 'Vm':
-                if (d.Vm.addresses.length > 0) {
-                    res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">');
-
-                    addListProperty(res, d.Vm, 'addresses');
-
-                    res.endBlock('</bean>');
-                }
-                else {
-                    res.line('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder"/>');
-                }
-
-                break;
-
-            case 'S3':
-                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.s3.TcpDiscoveryS3IpFinder">');
-
-                if (d.S3 && d.S3.bucketName)
-                    res.line('<property name="bucketName" value="' + escapeAttr(d.S3.bucketName) + '" />');
-
-                res.endBlock('</bean>');
-
-                break;
-
-            case 'Cloud':
-                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.cloud.TcpDiscoveryCloudIpFinder">');
-
-                addProperty(res, d.Cloud, 'credential');
-                addProperty(res, d.Cloud, 'credentialPath');
-                addProperty(res, d.Cloud, 'identity');
-                addProperty(res, d.Cloud, 'provider');
-                addListProperty(res, d.Cloud, 'regions');
-                addListProperty(res, d.Cloud, 'zones');
-
-                res.endBlock('</bean>');
-
-                break;
-
-            case 'GoogleStorage':
-                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.gce.TcpDiscoveryGoogleStorageIpFinder">');
-
-                addProperty(res, d.GoogleStorage, 'projectName');
-                addProperty(res, d.GoogleStorage, 'bucketName');
-                addProperty(res, d.GoogleStorage, 'serviceAccountP12FilePath');
-
-                //if (d.GoogleStorage.addrReqAttempts) todo ????
-                //    res.line('<property name="serviceAccountP12FilePath" value="' + escapeAttr(d.GoogleStorage.addrReqAttempts) + '"/>');
-
-                res.endBlock('</bean>');
-
-                break;
-
-            case 'Jdbc':
-                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.jdbc.TcpDiscoveryJdbcIpFinder">');
-                res.line('<property name="initSchema" value="' + (d.Jdbc.initSchema != null || d.Jdbc.initSchema) + '"/>');
-                res.endBlock('</bean>');
-
-                break;
-
-            case 'SharedFs':
-                if (d.SharedFs.path) {
-                    res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.sharedfs.TcpDiscoverySharedFsIpFinder">');
-                    addProperty(res, d.SharedFs, 'path');
-                    res.endBlock('</bean>');
-                }
-                else {
-                    res.line('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.sharedfs.TcpDiscoverySharedFsIpFinder"/>');
-                }
-
-                break;
-
-            default:
-                throw "Unknown discovery kind: " + d.kind;
-        }
-
-        res.endBlock('</property>');
-        res.endBlock('</bean>');
-        res.endBlock('</property>');
-
-        res.needEmptyLine = true
-    }
-
-    // Generate atomics group.
-    addBeanWithProperties(res, cluster.atomicConfiguration, 'atomicConfiguration',
-        generatorUtils.atomicConfiguration.className, generatorUtils.atomicConfiguration.fields);
-    res.needEmptyLine = true;
-
-    // Generate communication group.
-    addProperty(res, cluster, 'networkTimeout');
-    addProperty(res, cluster, 'networkSendRetryDelay');
-    addProperty(res, cluster, 'networkSendRetryCount');
-    addProperty(res, cluster, 'segmentCheckFrequency');
-    addProperty(res, cluster, 'waitForSegmentOnStart');
-    addProperty(res, cluster, 'discoveryStartupDelay');
-    res.needEmptyLine = true;
-
-    // Generate deployment group.
-    addProperty(res, cluster, 'deploymentMode');
-    res.needEmptyLine = true;
-
-    // Generate events group.
-    if (cluster.includeEventTypes && cluster.includeEventTypes.length > 0) {
-        res.emptyLineIfNeeded();
-        
-        res.startBlock('<property name="includeEventTypes">');
-        
-        if (cluster.includeEventTypes.length == 1)
-            res.line('<util:constant static-field="org.apache.ignite.events.EventType.' + cluster.includeEventTypes[0] + '"/>');
-        else {
-            res.startBlock('<array>');
-
-            for (i = 0; i < cluster.includeEventTypes.length; i++) {
-                if (i > 0)
-                    res.line();
-
-                var eventGroup = cluster.includeEventTypes[i];
-
-                res.line('<!-- EventType.' + eventGroup + ' -->');
-
-                var eventList = dataStructures.eventGroups[eventGroup];
-
-                for (var k = 0; k < eventList.length; k++) {
-                    res.line('<util:constant static-field="org.apache.ignite.events.EventType.' + eventList[k] + '"/>')
-                }
-            }
-
-            res.endBlock('</array>');
-        }
-        
-        res.endBlock('</property>');
-
-        res.needEmptyLine = true;
-    }
-
-    // Generate marshaller group.
-    var marshaller = cluster.marshaller;
-
-    if (marshaller && marshaller.kind) {
-        var marshallerDesc = generatorUtils.marshallers[marshaller.kind];
-
-        addBeanWithProperties(res, marshaller[marshaller.kind], 'marshaller', marshallerDesc.className, marshallerDesc.fields, true);
-        res.needEmptyLine = true;
-    }
-
-    addProperty(res, cluster, 'marshalLocalJobs');
-    addProperty(res, cluster, 'marshallerCacheKeepAliveTime');
-    addProperty(res, cluster, 'marshallerCacheThreadPoolSize');
-    res.needEmptyLine = true;
-
-    // Generate metrics group.
-    addProperty(res, cluster, 'metricsExpireTime');
-    addProperty(res, cluster, 'metricsHistorySize');
-    addProperty(res, cluster, 'metricsLogFrequency');
-    addProperty(res, cluster, 'metricsUpdateFrequency');
-    res.needEmptyLine = true;
-
-    // Generate PeerClassLoading group.
-    addProperty(res, cluster, 'peerClassLoadingEnabled');
-    addListProperty(res, cluster, 'peerClassLoadingLocalClassPathExclude');
-    addProperty(res, cluster, 'peerClassLoadingMissedResourcesCacheSize');
-    addProperty(res, cluster, 'peerClassLoadingThreadPoolSize');
-    res.needEmptyLine = true;
-
-    // Generate swap group.
-    if (cluster.swapSpaceSpi && cluster.swapSpaceSpi.kind == 'FileSwapSpaceSpi') {
-        addBeanWithProperties(res, cluster.swapSpaceSpi.FileSwapSpaceSpi, 'swapSpaceSpi',
-            generatorUtils.swapSpaceSpi.className, generatorUtils.swapSpaceSpi.fields, true);
-
-        res.needEmptyLine = true;
-    }
-
-    // Generate time group.
-    addProperty(res, cluster, 'clockSyncSamples');
-    addProperty(res, cluster, 'clockSyncFrequency');
-    addProperty(res, cluster, 'timeServerPortBase');
-    addProperty(res, cluster, 'timeServerPortRange');
-    res.needEmptyLine = true;
-
-    // Generate thread pools group.
-    addProperty(res, cluster, 'publicThreadPoolSize');
-    addProperty(res, cluster, 'systemThreadPoolSize');
-    addProperty(res, cluster, 'managementThreadPoolSize');
-    addProperty(res, cluster, 'igfsThreadPoolSize');
-    res.needEmptyLine = true;
-
-    // Generate transactions group.
-    addBeanWithProperties(res, cluster.transactionConfiguration, 'transactionConfiguration',
-        generatorUtils.transactionConfiguration.className, generatorUtils.transactionConfiguration.fields);
-    res.needEmptyLine = true;
-
-    // Generate caches configs.
-    if (cluster.caches && cluster.caches.length > 0) {
-        res.emptyLineIfNeeded();
-
-        res.startBlock('<property name="cacheConfiguration">');
-        res.startBlock('<list>');
-
-        for (var i = 0; i < cluster.caches.length; i++) {
-            if (i > 0)
-                res.line();
-
-            var cache = cluster.caches[i];
-
-            generateCacheConfiguration(cache, res);
-        }
-
-        res.endBlock('</list>');
-        res.endBlock('</property>');
-
-        res.needEmptyLine = true;
-    }
-
-    res.endBlock('</bean>');
-
-    // Build final XML:
-    // 1. Add header.
-    var xml = '<?xml version="1.0" encoding="UTF-8"?>\n\n';
-
-    xml += '<!-- ' + generatorUtils.mainComment() + ' -->\n';
-    xml += '<beans xmlns="http://www.springframework.org/schema/beans"\n';
-    xml += '       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n';
-    xml += '       xmlns:util="http://www.springframework.org/schema/util"\n';
-    xml += '       xsi:schemaLocation="http://www.springframework.org/schema/beans\n';
-    xml += '                           http://www.springframework.org/schema/beans/spring-beans.xsd\n';
-    xml += '                           http://www.springframework.org/schema/util\n';
-    xml += '                           http://www.springframework.org/schema/util/spring-util.xsd">\n';
-
-    // 2. Add external property file and all data sources.
-    if (res.datasources.length > 0) {
-        xml += '    <!-- Load external properties file. -->\n';
-        xml += '    <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">\n';
-        xml += '        <property name="location" value="classpath:secret.properties"/>\n';
-        xml += '    </bean>\n\n';
-
-        xml += '    <!-- Data source beans will be initialized from external properties file. -->\n';
-
-        _.forEach(res.datasources, function(item) {
-            var beanId = item.dataSourceBean;
-
-            xml += '    <bean id= "' + beanId + '" class="' + item.className + '">\n';
-            xml += '        <property name="URL" value="${' + beanId + '.jdbc.url}" />\n';
-            xml += '        <property name="user" value="${' + beanId + '.jdbc.username}" />\n';
-            xml += '        <property name="password" value="${' + beanId + '.jdbc.password}" />\n';
-            xml += '    </bean>\n\n';
-        });
-    }
-
-    // 3. Add main content.
-    xml += res.join('');
-
-    // 4. Add footer.
-    xml += '</beans>\n';
-
-    return xml;
-};
-
-function createEvictionPolicy(res, evictionPolicy, propertyName) {
-    if (evictionPolicy && evictionPolicy.kind) {
-        var e = generatorUtils.evictionPolicies[evictionPolicy.kind];
-
-        var obj = evictionPolicy[evictionPolicy.kind.toUpperCase()];
-
-        addBeanWithProperties(res, obj, propertyName, e.className, e.fields, true);
-    }
-}
-
-function generateCacheConfiguration(cacheCfg, res) {
-    if (!res)
-        res = generatorUtils.builder();
-
-    res.startBlock('<bean class="org.apache.ignite.configuration.CacheConfiguration">');
-
-    addProperty(res, cacheCfg, 'name');
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, 'mode', 'cacheMode');
-
-    addProperty(res, cacheCfg, 'atomicityMode');
-    addProperty(res, cacheCfg, 'backups');
-    addProperty(res, cacheCfg, 'startSize');
-    addProperty(res, cacheCfg, 'readFromBackup');
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, 'memoryMode');
-    addProperty(res, cacheCfg, 'offHeapMaxMemory');
-    addProperty(res, cacheCfg, 'swapEnabled');
-    addProperty(res, cacheCfg, 'copyOnRead');
-
-    res.needEmptyLine = true;
-
-    createEvictionPolicy(res, cacheCfg.evictionPolicy, 'evictionPolicy');
-
-    res.needEmptyLine = true;
-
-    if (cacheCfg.nearCacheEnabled) {
-        res.emptyLineIfNeeded();
-
-        res.startBlock('<property name="nearConfiguration">');
-        res.startBlock('<bean class="org.apache.ignite.configuration.NearCacheConfiguration">');
-
-        if (cacheCfg.nearConfiguration && cacheCfg.nearConfiguration.nearStartSize)
-            addProperty(res, cacheCfg.nearConfiguration, 'nearStartSize');
-
-        if (cacheCfg.nearConfiguration && cacheCfg.nearConfiguration.nearEvictionPolicy.kind)
-            createEvictionPolicy(res, cacheCfg.nearConfiguration.nearEvictionPolicy, 'nearEvictionPolicy');
-
-        res.endBlock('</bean>');
-        res.endBlock('</property>');
-    }
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, 'sqlEscapeAll');
-    addProperty(res, cacheCfg, 'sqlOnheapRowCacheSize');
-    addProperty(res, cacheCfg, 'longQueryWarningTimeout');
-
-    if (cacheCfg.indexedTypes && cacheCfg.indexedTypes.length > 0) {
-        res.startBlock('<property name="indexedTypes">');
-        res.startBlock('<list>');
-
-        for (var i = 0; i < cacheCfg.indexedTypes.length; i++) {
-            var pair = cacheCfg.indexedTypes[i];
-
-            res.line('<value>' + escape(pair.keyClass) + '</value>');
-            res.line('<value>' + escape(pair.valueClass) + '</value>');
-        }
-
-        res.endBlock('</list>');
-        res.endBlock('</property>');
-    }
-
-    addListProperty(res, cacheCfg, 'sqlFunctionClasses', 'array');
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, 'rebalanceMode');
-    addProperty(res, cacheCfg, 'rebalanceThreadPoolSize');
-    addProperty(res, cacheCfg, 'rebalanceBatchSize');
-    addProperty(res, cacheCfg, 'rebalanceOrder');
-    addProperty(res, cacheCfg, 'rebalanceDelay');
-    addProperty(res, cacheCfg, 'rebalanceTimeout');
-    addProperty(res, cacheCfg, 'rebalanceThrottle');
-
-    res.needEmptyLine = true;
-
-    if (cacheCfg.cacheStoreFactory && cacheCfg.cacheStoreFactory.kind) {
-        var storeFactory = cacheCfg.cacheStoreFactory[cacheCfg.cacheStoreFactory.kind];
-        var data = generatorUtils.storeFactories[cacheCfg.cacheStoreFactory.kind];
-
-        addBeanWithProperties(res, storeFactory, 'cacheStoreFactory', data.className, data.fields, true);
-
-        if (storeFactory.dialect) {
-            if (_.findIndex(res.datasources, function (ds) {
-                    return ds.dataSourceBean == storeFactory.dataSourceBean;
-                }) < 0) {
-                res.datasources.push({
-                    dataSourceBean: storeFactory.dataSourceBean,
-                    className: generatorUtils.dataSources[storeFactory.dialect]
-                });
-            }
-        }
-    }
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, 'loadPreviousValue');
-    addProperty(res, cacheCfg, 'readThrough');
-    addProperty(res, cacheCfg, 'writeThrough');
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, 'invalidate');
-    addProperty(res, cacheCfg, 'defaultLockTimeout');
-    addProperty(res, cacheCfg, 'transactionManagerLookupClassName');
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, 'writeBehindEnabled');
-    addProperty(res, cacheCfg, 'writeBehindBatchSize');
-    addProperty(res, cacheCfg, 'writeBehindFlushSize');
-    addProperty(res, cacheCfg, 'writeBehindFlushFrequency');
-    addProperty(res, cacheCfg, 'writeBehindFlushThreadCount');
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, 'statisticsEnabled');
-    addProperty(res, cacheCfg, 'managementEnabled');
-
-    res.needEmptyLine = true;
-
-    addProperty(res, cacheCfg, 'maxConcurrentAsyncOperations');
-    
-    res.endBlock('</bean>');
-
-    return res;
-}
-
-exports.generateCacheConfiguration = generateCacheConfiguration;
-
-function addProperty(res, obj, propName, setterName) {
-    var val = obj[propName];
-
-    if (generatorUtils.isDefined(val)) {
-        res.emptyLineIfNeeded();
-
-        res.line('<property name="' + (setterName ? setterName : propName) + '" value="' + escapeAttr(val) + '"/>');
-    }
-}
-
-function addBeanWithProperties(res, bean, beanPropName, beanClass, props, createBeanAlthoughNoProps) {
-    if (bean && generatorUtils.hasProperty(bean, props)) {
-        res.emptyLineIfNeeded();
-        res.startBlock('<property name="' + beanPropName + '">');
-        res.startBlock('<bean class="' + beanClass + '">');
-
-        for (var propName in props) {
-            if (props.hasOwnProperty(propName)) {
-                var descr = props[propName];
-
-                if (descr) {
-                    if (descr.type == 'list') {
-                        addListProperty(res, bean, propName, descr.setterName);
-                    }
-                    else if (descr.type == 'className') {
-                        if (bean[propName]) {
-                            res.startBlock('<property name="' + propName + '">');
-                            res.line('<bean class="' + generatorUtils.knownClasses[bean[propName]].className + '"/>');
-                            res.endBlock('</property>');
-                        }
-                    }
-                    else if (descr.type == 'propertiesAsList') {
-                        var val = bean[propName];
-
-                        if (val && val.length > 0) {
-                            res.startBlock('<property name="' + propName + '">');
-                            res.startBlock('<props>');
-
-                            for (var i = 0; i < val.length; i++) {
-                                var nameAndValue = val[i];
-
-                                var eqIndex = nameAndValue.indexOf('=');
-                                if (eqIndex >= 0) {
-                                    res.line('<prop key="' + escapeAttr(nameAndValue.substring(0, eqIndex)) + '">' +
-                                            + escape(nameAndValue.substr(eqIndex + 1)) + '</prop>');
-                                }
-                            }
-
-                            res.endBlock('</props>');
-                            res.endBlock('</property>');
-                        }
-                    }
-                    else
-                        addProperty(res, bean, propName, descr.setterName);
-                }
-                else
-                    addProperty(res, bean, propName);
-            }
-        }
-
-        res.endBlock('</bean>');
-        res.endBlock('</property>');
-    }
-    else if (createBeanAlthoughNoProps) {
-        res.emptyLineIfNeeded();
-        res.line('<property name="' + beanPropName + '">');
-        res.line('    <bean class="' + beanClass + '"/>');
-        res.line('</property>');
-    }
-}
-function addListProperty(res, obj, propName, listType, rowFactory) {
-    var val = obj[propName];
-
-    if (val && val.length > 0) {
-        res.emptyLineIfNeeded();
-
-        if (!listType)
-            listType = 'list';
-
-        if (!rowFactory)
-            rowFactory = function(val) { return '<value>' + escape(val) + '</value>' };
-
-        res.startBlock('<property name="' + propName + '">');
-        res.startBlock('<' + listType + '>');
-
-        for (var i = 0; i < val.length; i++)
-            res.line(rowFactory(val[i]));
-
-        res.endBlock('</' + listType + '>');
-        res.endBlock('</property>');
-    }
-}
-
-function escapeAttr(s) {
-    if (typeof(s) != 'string')
-        return s;
-
-    return s.replace(/&/g, '&amp;').replace(/"/g, '&quot;');
-}
-
-function escape(s) {
-    if (typeof(s) != 'string')
-        return s;
-
-    return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/routes/metadata.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/metadata.js b/modules/web-control-center/nodejs/routes/metadata.js
deleted file mode 100644
index 64b8763..0000000
--- a/modules/web-control-center/nodejs/routes/metadata.js
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var router = require('express').Router();
-var db = require('../db');
-
-/* GET metadata page. */
-router.get('/', function (req, res) {
-    res.render('configuration/metadata');
-});
-
-/**
- * Get spaces and metadata accessed for user account.
- *
- * @param req Request.
- * @param res Response.
- */
-router.post('/list', function (req, res) {
-    var user_id = req.currentUserId();
-
-    // Get owned space and all accessed space.
-    db.Space.find({$or: [{owner: user_id}, {usedBy: {$elemMatch: {account: user_id}}}]}, function (err, spaces) {
-        if (err)
-            return res.status(500).send(err.message);
-
-        var space_ids = spaces.map(function (value) {
-            return value._id;
-        });
-
-        // Get all metadata for spaces.
-        db.CacheTypeMetadata.find({space: {$in: space_ids}}).sort('name').exec(function (err, metadatas) {
-            if (err)
-                return res.status(500).send(err.message);
-
-            res.json({spaces: spaces, metadatas: metadatas});
-        });
-    });
-});
-
-/**
- * Save metadata.
- */
-router.post('/save', function (req, res) {
-    if (req.body._id)
-        db.CacheTypeMetadata.update({_id: req.body._id}, req.body, {upsert: true}, function (err) {
-            if (err)
-                return res.status(500).send(err.message);
-
-            res.send(req.body._id);
-        });
-    else {
-        db.CacheTypeMetadata.findOne({name: req.body.name}, function (err, metadata) {
-            if (err)
-                return res.status(500).send(err.message);
-
-            if (metadata)
-                return res.status(500).send('Cache type metadata with name: "' + metadata.name + '" already exist.');
-
-            (new db.CacheTypeMetadata(req.body)).save(function (err, metadata) {
-                if (err)
-                    return res.status(500).send(err.message);
-
-                res.send(metadata._id);
-            });
-        });
-    }
-});
-
-/**
- * Remove metadata by ._id.
- */
-router.post('/remove', function (req, res) {
-    db.CacheTypeMetadata.remove(req.body, function (err) {
-        if (err)
-            return res.status(500).send(err.message);
-
-        res.sendStatus(200);
-    })
-});
-
-module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/routes/profile.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/profile.js b/modules/web-control-center/nodejs/routes/profile.js
deleted file mode 100644
index 0269e7d..0000000
--- a/modules/web-control-center/nodejs/routes/profile.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var router = require('express').Router();
-var db = require('../db');
-
-router.all('/profile/*', function (req, res, next) {
-    var userId = req.body._id;
-
-    if (userId != req.currentUserId() && userId != req.user._id)
-        return res.sendStatus(403);
-    else
-        next();
-});
-
-/**
- * Get user profile page.
- */
-router.get('/', function (req, res) {
-    var user_id = req.currentUserId();
-
-    db.Account.findById(user_id, function (err) {
-        if (err)
-            return res.status(500).send(err.message);
-
-        res.render('settings/profile');
-    });
-});
-
-/**
- * Save user profile.
- */
-router.post('/saveUser', function (req, res) {
-    var params = req.body;
-
-    if (params.newPassword) {
-        var newPassword = params.newPassword;
-
-        if (!newPassword || newPassword.length == 0)
-            return res.status(500).send('Wrong value for new password');
-
-        db.Account.findById(params._id, function (err, user) {
-            if (err)
-                return res.status(500).send(err);
-
-            user.setPassword(newPassword, function (err, updatedUser) {
-                if (err)
-                    return res.status(500).send(err.message);
-
-                if (params.userName)
-                    updatedUser.username = params.userName;
-
-                if (params.email)
-                    updatedUser.email = params.email;
-
-                updatedUser.save(function (err) {
-                    if (err)
-                        return res.status(500).send(err.message);
-
-                    res.json(user);
-                });
-            });
-        });
-    }
-    else if (params.userName || params.email) {
-        var upd = {};
-
-        if (params.userName)
-            upd.username = params.userName;
-
-        if (params.email)
-            upd.email = params.email;
-
-        db.Account.findByIdAndUpdate(params._id, upd, {new: true}, function (err, val) {
-            if (err)
-                return res.status(500).send(err.message);
-
-            res.json(val);
-        })
-    }
-});
-
-module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/routes/public.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/public.js b/modules/web-control-center/nodejs/routes/public.js
deleted file mode 100644
index 290ba90..0000000
--- a/modules/web-control-center/nodejs/routes/public.js
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var router = require('express').Router();
-var passport = require('passport');
-var db = require('../db');
-
-// GET dropdown-menu template.
-router.get('/select', function (req, res) {
-    res.render('templates/select', {});
-});
-
-// GET tabs template.
-router.get('/tab', function (req, res) {
-    res.render('templates/tab', {});
-});
-
-// GET confirmation dialog.
-router.get('/confirm', function (req, res) {
-    res.render('templates/confirm', {});
-});
-
-// GET save as dialog.
-router.get('/copy', function (req, res) {
-    res.render('templates/copy', {});
-});
-
-/* GET login page. */
-router.get('/login', function (req, res) {
-    res.render('login');
-});
-
-/**
- * Register new account.
- */
-router.post('/register', function (req, res) {
-    db.Account.count(function (err, cnt) {
-        if (err)
-            return res.status(401).send(err.message);
-
-        req.body.admin = cnt == 0;
-
-        db.Account.register(new db.Account(req.body), req.body.password, function (err, account) {
-            if (err)
-                return res.status(401).send(err.message);
-
-            if (!account)
-                return res.status(500).send('Failed to create account.');
-
-            new db.Space({name: 'Personal space', owner: account._id}).save();
-
-            req.logIn(account, {}, function (err) {
-                if (err)
-                    return res.status(401).send(err.message);
-
-                return res.redirect('/configuration/clusters');
-            });
-        });
-    });
-});
-
-/**
- * Login in exist account.
- */
-router.post('/login', function (req, res, next) {
-    passport.authenticate('local', function (err, user) {
-        if (err)
-            return res.status(401).send(err.message);
-
-        if (!user)
-            return res.status(401).send('Invalid email or password');
-
-        req.logIn(user, {}, function (err) {
-            if (err)
-                return res.status(401).send(err.message);
-
-            res.redirect('/configuration/clusters');
-        });
-    })(req, res, next);
-});
-
-/**
- * Logout.
- */
-router.get('/logout', function (req, res) {
-    req.logout();
-
-    res.redirect('/');
-});
-
-/* GET home page. */
-router.get('/', function (req, res) {
-    if (req.isAuthenticated())
-        res.redirect('/configuration/clusters');
-    else
-        res.render('index');
-});
-
-///* GET sql page. */
-//router.get('/sql', function(req, res) {
-//    res.render('sql', { user: req.user });
-//});
-//
-///* GET clients page. */
-//router.get('/clients', function(req, res) {
-//    res.render('clients', { user: req.user });
-//});
-
-module.exports = router;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/routes/sql.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/sql.js b/modules/web-control-center/nodejs/routes/sql.js
deleted file mode 100644
index ce4565d..0000000
--- a/modules/web-control-center/nodejs/routes/sql.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var router = require('express').Router();
-var db = require('../db');
-router.get('/', function(req, res) {
-    res.render('sql/sql');
-});
-
-module.exports = router;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/routes/summary.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/summary.js b/modules/web-control-center/nodejs/routes/summary.js
deleted file mode 100644
index f766945..0000000
--- a/modules/web-control-center/nodejs/routes/summary.js
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var db = require('../db');
-
-var router = require('express').Router();
-
-var generatorXml = require('./generator/xml');
-var generatorJava = require('./generator/java');
-var generatorDocker = require('./generator/docker');
-
-/* GET summary page. */
-router.get('/', function (req, res) {
-    res.render('configuration/summary');
-});
-
-router.post('/generator', function (req, res) {
-    // Get cluster.
-    db.Cluster.findById(req.body._id).populate('caches').exec(function (err, cluster) {
-        if (err)
-            return res.status(500).send(err.message);
-
-        if (!cluster)
-            return res.sendStatus(404);
-
-        var clientCache = req.body.clientNearConfiguration;
-
-        if (clientCache)
-            return res.send({
-                xmlClient: generatorXml.generateClusterConfiguration(cluster, clientCache),
-                javaClient: generatorJava.generateClusterConfiguration(cluster, req.body.javaClass, clientCache)
-            });
-
-        return res.send({
-            xmlServer: generatorXml.generateClusterConfiguration(cluster),
-            javaSnippetServer: generatorJava.generateClusterConfiguration(cluster, false),
-            javaClassServer: generatorJava.generateClusterConfiguration(cluster, true),
-            docker: generatorDocker.generateClusterConfiguration(cluster, '%OS%')
-        });
-    });
-});
-
-router.post('/download', function (req, res) {
-    // Get cluster.
-    db.Cluster.findById(req.body._id).populate('caches').exec(function (err, cluster) {
-        if (err)
-            return res.status(500).send(err.message);
-
-        if (!cluster)
-            return res.sendStatus(404);
-
-        var clientNearConfiguration = req.body.clientNearConfiguration;
-
-        var archiver = require('archiver');
-
-        // Creating archive.
-        var zip = archiver('zip');
-
-        zip.on('error', function (err) {
-            res.status(500).send({error: err.message});
-        });
-
-        // On stream closed we can end the request.
-        res.on('close', function () {
-            return res.status(200).send('OK').end();
-        });
-
-        // Set the archive name.
-        res.attachment(cluster.name + (clientNearConfiguration ? '-client' : '') + '-configuration.zip');
-
-        var generatorCommon = require('./generator/common');
-
-        // Send the file to the page output.
-        zip.pipe(res);
-
-        var javaClass = req.body.javaClass;
-
-        if (!clientNearConfiguration) {
-            zip.append(generatorDocker.generateClusterConfiguration(cluster, req.body.os), {name: "Dockerfile"});
-
-            var props = generatorCommon.generateProperties(cluster);
-
-            if (props)
-                zip.append(props, {name: "secret.properties"});
-        }
-
-        zip.append(generatorXml.generateClusterConfiguration(cluster, clientNearConfiguration), {name: cluster.name + ".xml"})
-            .append(generatorJava.generateClusterConfiguration(cluster, javaClass, clientNearConfiguration),
-                {name: javaClass ? 'ConfigurationFactory.java' : cluster.name + '.snipplet.java'})
-            .finalize();
-    });
-});
-
-module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/configuration/caches.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/caches.jade b/modules/web-control-center/nodejs/views/configuration/caches.jade
deleted file mode 100644
index 3a011fc..0000000
--- a/modules/web-control-center/nodejs/views/configuration/caches.jade
+++ /dev/null
@@ -1,74 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-extends sidebar
-
-append scripts
-    script(src='/caches-controller.js')
-
-include ../includes/controls
-
-block content
-    .docs-header
-        h1 Create and Configure Ignite Caches
-        hr
-    .docs-body(ng-controller='cachesController')
-        +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
-        .links(ng-hide='caches.length == 0')
-            .padding-dflt
-                lable.labelHeader Caches:
-                table(st-table='caches')
-                    tbody
-                        tr(ng-repeat='row in caches track by row._id')
-                            td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
-                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}}, {{row.atomicityMode | displayValue:atomicities:'Cache atomicity not set'}}
-        .padding-top-dflt
-            button.btn.btn-primary(ng-click='createItem()') Add cache
-        hr
-        form.form-horizontal(name='inputForm' ng-if='backupItem' novalidate)
-            div(bs-collapse data-start-collapsed='false')
-                .panel.panel-default
-                    .panel-heading
-                        h3
-                            a(bs-collapse-toggle) General
-                    .panel-collapse(bs-collapse-target)
-                        .panel-body
-                            .settings-row(ng-repeat='field in general')
-                                +form-row(['col-sm-3'], ['col-sm-3'])
-            .panel-group(bs-collapse data-allow-multiple="true")
-                div(bs-collapse data-start-collapsed='true')
-                    .panel-title(ng-show='expanded')
-                        h3
-                            a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
-                    .panel-collapse(bs-collapse-target)
-                        .span(bs-collapse data-start-collapsed='true' data-allow-multiple='true')
-                            .panel.panel-default(ng-repeat='group in advanced')
-                                .panel-heading
-                                    h3
-                                        a(bs-collapse-toggle) {{group.label}}
-                                        i.tipLabel.fa.fa-question-circle(ng-if='group.tip' bs-tooltip='joinTip(group.tip)' type='button')
-                                        i.tipLabel.fa.fa-question-circle.blank(ng-if='!group.tip')
-                                .panel-collapse(bs-collapse-target)
-                                    .panel-body
-                                        .settings-row(ng-repeat='field in group.fields')
-                                            +form-row
-                    .panel-title
-                        h3
-                            a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
-            div
-                button.btn.btn-primary(ng-disabled='inputForm.$invalid' ng-click='saveItem()') Save
-                button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
-                button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/configuration/clusters.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/clusters.jade b/modules/web-control-center/nodejs/views/configuration/clusters.jade
deleted file mode 100644
index 81acfed..0000000
--- a/modules/web-control-center/nodejs/views/configuration/clusters.jade
+++ /dev/null
@@ -1,77 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-extends sidebar
-
-append scripts
-    script(src='/clusters-controller.js')
-
-include ../includes/controls
-
-block content
-    .docs-header
-        h1 Create and Configure Ignite Clusters
-        hr
-    .docs-body(ng-controller='clustersController')
-        +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
-        .links(ng-hide='clusters.length == 0')
-            .padding-dflt
-                lable.labelHeader Clusters:
-                table(st-table='clusters')
-                    tbody
-                        tr(ng-repeat='row in clusters track by row._id')
-                            td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
-                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.discovery.kind | displayValue:discoveries:'Discovery not set'}}
-        .padding-top-dflt
-            button.btn.btn-primary(ng-click='createItem()') &nbspAdd cluster
-            label(style='margin-left: 10px; margin-right: 10px') Use template:
-            button.btn.btn-default.base-control(ng-init='create.template = templates[0].value' ng-model='create.template' data-template='/select' data-placeholder='Choose cluster template' bs-options='item.value as item.label for item in templates' bs-select)
-            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.panel-default
-                    .panel-heading
-                        h3
-                            a(bs-collapse-toggle) General
-                    .panel-collapse(bs-collapse-target)
-                        .panel-body
-                            .settings-row(ng-repeat='field in general')
-                                +form-row
-            .panel-group(bs-collapse data-allow-multiple="true")
-                div(bs-collapse data-start-collapsed='true')
-                    .panel-title(ng-show='expanded')
-                        h3
-                            a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
-                    .panel-collapse(bs-collapse-target)
-                        .span(bs-collapse data-start-collapsed='true' data-allow-multiple='true')
-                            .panel.panel-default(ng-repeat='group in advanced')
-                                .panel-heading
-                                    h3
-                                        a(bs-collapse-toggle) {{group.label}}
-                                        i.tipLabel.fa.fa-question-circle(ng-if='group.tip' bs-tooltip='joinTip(group.tip)' type='button')
-                                        i.tipLabel.fa.fa-question-circle.blank(ng-if='!group.tip')
-                                .panel-collapse(bs-collapse-target)
-                                    .panel-body
-                                        .settings-row(ng-repeat='field in group.fields')
-                                            +form-row
-                    .panel-title
-                        h3
-                            a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
-            div
-                button.btn.btn-primary(ng-disabled='inputForm.$invalid' ng-click='saveItem()') Save
-                button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
-                button.btn.btn-primary(ng-show='backupItem._id' ng-click='removeItem()') Remove
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/configuration/metadata.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/metadata.jade b/modules/web-control-center/nodejs/views/configuration/metadata.jade
deleted file mode 100644
index d5bac06..0000000
--- a/modules/web-control-center/nodejs/views/configuration/metadata.jade
+++ /dev/null
@@ -1,121 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-extends sidebar
-
-append scripts
-    script(src='/metadata-controller.js')
-
-include ../includes/controls
-
-block content
-    .docs-header
-        h1 Create and Configure Cache Type Metadata
-        hr
-    .docs-body(ng-controller='metadataController')
-        +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
-        .links(ng-hide='metadatas.length == 0')
-            .padding-dflt
-                lable.labelHeader Types metadata:
-                table(st-table='metadatas')
-                    tbody
-                        tr(ng-repeat='row in metadatas track by row._id')
-                            td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
-                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
-        .padding-top-dflt
-            button.btn.btn-primary(ng-click='panels.activePanel = [0]; createItem()') &nbspAdd metadata
-            label(style='margin-left: 6px; margin-right: 10px') For:
-            button.btn.btn-default(ng-model='template' data-template='/select' data-placeholder='Choose metadata type' bs-options='item.value as item.label for item in templates' bs-select)
-            i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')
-        hr
-        .panel-group(bs-collapse ng-model='panels.activePanel' data-allow-multiple="false")
-            .panel.panel-default
-                .panel-heading
-                    h3
-                        a(bs-collapse-toggle) Manual
-                .panel-collapse(role="tabpanel" bs-collapse-target)
-                    .panel-body
-                        form.form-horizontal(name='manualForm' ng-if='backupItem' novalidate)
-                            .settings-row(ng-repeat='field in metadataManual')
-                                +form-row
-                            button.btn.btn-primary(ng-disabled='manualForm.$invalid' ng-click='saveItem()') Save
-                            button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
-                            button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove
-            .panel.panel-default
-                .panel-heading
-                    h3
-                        a(bs-collapse-toggle) Load from database
-                .panel-collapse(bs-collapse-target)
-                    .panel-body
-                        form.form-horizontal(name='dbForm' novalidate)
-                            .settings-row(ng-repeat='field in metadataDb')
-                                +form-row
-                        div(ng-hide='data.tables.length == 0')
-                            table.table-bordered.table-condensed.links-edit-small-padding.col-sm-12(st-table='data.tables')
-                                thead
-                                    tr
-                                        th.col-sm-3 Schema/Table
-                                        th Key class
-                                        th Value class
-                                tbody
-                                    tr(ng-repeat='row in data.tables')
-                                        td(colspan='{{row.tableName ? 1 : 3}}')
-                                            div.checkbox(ng-if='!row.tableName')
-                                                label(ng-click='selectSchema($index)')
-                                                    input(type='checkbox' ng-checked='row.use')
-                                                    | {{row.schemaName}}
-                                            div.checkbox(ng-if='row.tableName')
-                                                label(style='padding-left: 30px' ng-click='selectTable($index)')
-                                                    input(type='checkbox' ng-checked = 'row.use')
-                                                    | {{row.tableName}}
-                                        td(ng-if='row.tableName')
-                                            a(ng-show='data.curTableIdx != $index' ng-click='selectTable($index)') {{row.keyClass}}
-                                            input.form-control(type='text' ng-show='data.curTableIdx == $index' ng-model='data.curKeyClass' placeholder='Key class full name')
-                                        td(ng-if='row.tableName')
-                                            a(ng-show='data.curTableIdx != $index' ng-click='selectTable($index)') {{row.valueClass}}
-                                            input.form-control(type='text' ng-show='data.curTableIdx == $index' ng-model='data.curValueClass' placeholder='Value class full name')
-                        //div(ng-hide='data.curTableIdx < 0')
-                        //    table.table-bordered.table-condensed.links-edit-small-padding.col-sm-12(st-table='data.tables[data.curTableIdx].fields')
-                        //        thead
-                        //            tr
-                        //                th(style='width:45px') Use
-                        //                th(style='width:45px') Key
-                        //                th(style='width:45px') Ak
-                        //                th DB Name
-                        //                th DB Type
-                        //                th Java Name
-                        //                th Java Type
-                        //        tbody
-                        //            tr(ng-repeat='row in data.tables[data.curTableIdx].fields')
-                        //                td
-                        //                    +dbcheck('row.use')
-                        //                td
-                        //                    +dbcheck('row.key')
-                        //                td
-                        //                    +dbcheck('row.ak')
-                        //                td
-                        //                    label {{row.dbName}}
-                        //                td
-                        //                    label {{row.dbType}}
-                        //                td
-                        //                    a(ng-show='data.curFieldIdx != $index' ng-click='selectField($index)') {{row.javaName}}
-                        //                    input.form-control(type='text' ng-show='data.curFieldIdx == $index' ng-model='data.curJavaName' placeholder='Field Java name')
-                        //                td
-                        //                    a(ng-show='data.curFieldIdx != $index' ng-click='selectField($index)') {{row.javaType}}
-                        //                    input.form-control(type='text' ng-show='data.curFieldIdx == $index' ng-model='data.curJavaType' placeholder='Field Java type')
-                        button.btn.btn-primary(ng-disabled='dbForm.$invalid' ng-click='saveItem()') Save
-                        button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove
-                        button.btn.btn-primary.btn-second(ng-click='reloadMetadata()') Reload
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/configuration/sidebar.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/sidebar.jade b/modules/web-control-center/nodejs/views/configuration/sidebar.jade
deleted file mode 100644
index 7289f3e..0000000
--- a/modules/web-control-center/nodejs/views/configuration/sidebar.jade
+++ /dev/null
@@ -1,39 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-extends ../templates/layout
-
-mixin sidebar-item(ref, num, txt)
-    li
-        a(ng-class='{active: isActive("#{ref}")}' href='#{ref}')
-            span.fa-stack
-                i.fa.fa-circle-thin.fa-stack-2x
-                i.fa.fa-stack-1x #{num}
-            | #{txt}
-
-block container
-    .row
-        .col-sm-2.border-right.section-left.greedy
-            .sidebar-nav(bs-affix)
-                ul.menu(ng-controller='activeLink')
-                    +sidebar-item('/configuration/clusters', 1, 'Clusters')
-                    +sidebar-item('/configuration/metadata', 2, 'Metadata')
-                    +sidebar-item('/configuration/caches', 3, 'Caches')
-                    +sidebar-item('/configuration/summary', 4, 'Summary')
-
-        .col-sm-10.border-left.section-right
-            .docs-content
-                block content
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/configuration/summary.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/summary.jade b/modules/web-control-center/nodejs/views/configuration/summary.jade
deleted file mode 100644
index 6f2f6d8..0000000
--- a/modules/web-control-center/nodejs/views/configuration/summary.jade
+++ /dev/null
@@ -1,117 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-extends sidebar
-
-append scripts
-    script(src='/summary-controller.js')
-
-    script(src="//cdn.jsdelivr.net/angularjs/1.3.15/angular-animate.min.js")
-    script(src="//cdn.jsdelivr.net/angularjs/1.3.15/angular-sanitize.min.js")
-
-    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/theme-chrome.js')
-    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-xml.js')
-    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-java.js')
-    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-dockerfile.js')
-
-append css
-
-include ../includes/controls
-
-mixin hard-link(ref, txt)
-    a(style='color:#ec1c24' href=ref target="_blank") #{txt}
-
-block content
-    .docs-header
-        h1 Configurations Summary
-        hr
-    .docs-body(ng-controller='summaryController')
-        +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
-        .padding-dflt(ng-if='clusters.length == 0')
-            | No cluster configured. You can&nbsp;
-            a(href='clusters') configure
-            | &nbsp;it.
-        .padding-dflt(ng-if='clusters.length > 0')
-            lable.labelHeader Clusters:
-            .links
-                table(st-table='clusters')
-                    tbody
-                        tr(ng-repeat='row in clusters track by row._id')
-                            td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
-                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
-        div(ng-show='selectedItem' role="tab" method='post' action='summary/download')
-            .padding-dflt(bs-collapse data-start-collapsed='false')
-                .panel.panel-default
-                    form.panel-heading(role='tab' method='post' action='summary/download')
-                        input(type="hidden" name="_id" value="{{selectedItem._id}}")
-                        input(type="hidden" name="os" value="{{os}}")
-                        input(type="hidden" name="javaClass" value="{{javaClassServer}}")
-                        h3
-                            a(bs-collapse-toggle) Server
-                            button.btn.btn-primary.pull-right(type='submit' style='margin-top: -5px') Download
-                    .panel-collapse(role="tabpanel" bs-collapse-target)
-                        .panel-body
-                            .configBox(ng-show='selectedItem' bs-tabs)
-                                div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
-                                    .configBox(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlServer' style='margin: 0.65em 0;')
-                                div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
-                                    .settings-row
-                                        .col-sm-1
-                                            label Generate:
-                                        .col-sm-3
-                                            button.form-control(type='button' ng-model='configServer.javaClassServer'  bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
-                                    .configBox(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaServer')
-                                div(title='<img src="/images/docker.png" width="16px" height="16px"/> Dockerfile' bs-pane)
-                                    .settings-row
-                                        p
-                                            +hard-link('https://docs.docker.com/reference/builder', 'Docker')
-                                            | &nbsp;file is a text file with instructions to create Docker image.<br/>
-                                            | To build image you have to store following Docker file with your Ignite XML configuration to the same directory.<br>
-                                            | Also you could use predefined&nbsp;
-                                            +hard-link('https://ignite.incubator.apache.org/download.html#docker', 'Apache Ignite docker image')
-                                            | . For more information about using Ignite with Docker please read&nbsp;
-                                            +hard-link('http://apacheignite.readme.io/docs/docker-deployment', 'documentation')
-                                            |.
-                                        .col-sm-2
-                                            label(for='os') Operation System:
-                                        .col-sm-4
-                                            input#os.form-control(type='text', ng-model='configServer.os' placeholder='debian:8' data-min-length="0" data-html="1" data-auto-select="true" data-animation="am-flip-x" bs-typeahead bs-options='os for os in oss')
-                                    div(ui-ace='{ onLoad: aceInit, mode: "dockerfile" }' ng-model='dockerServer')
-            .padding-dflt(bs-collapse data-start-collapsed='false')
-                .panel.panel-default
-                    form.panel-heading(role='tab' method='post' action='summary/download')
-                        input(type="hidden" name="_id" value="{{selectedItem._id}}")
-                        input(type="hidden" name="javaClass" value="{{javaClassClient}}")
-                        input(type="hidden" name="clientNearConfiguration" value="{{backupItem}}")
-
-                        h3
-                            a(bs-collapse-toggle) Client
-                            button.btn.btn-primary.pull-right(type='submit' style='margin-top: -5px') Download
-                    .panel-collapse(role="tabpanel" bs-collapse-target)
-                        .panel-body
-                            div(ng-show='selectedItem')
-                                .settings-row(ng-repeat='field in clientFields')
-                                    +form-row-custom(['col-sm-3'], ['col-sm-3'])
-                                .configBox(bs-tabs)
-                                    div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
-                                        .configBox(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlClient' style='margin: 0.65em 0;')
-                                    div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
-                                        .settings-row
-                                            .col-sm-1
-                                                label Generate:
-                                            .col-sm-4
-                                                button.form-control(type='button' ng-model='backupItem.javaClassClient' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
-                                        div(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaClient')

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/error.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/error.jade b/modules/web-control-center/nodejs/views/error.jade
deleted file mode 100644
index b458fb7..0000000
--- a/modules/web-control-center/nodejs/views/error.jade
+++ /dev/null
@@ -1,22 +0,0 @@
-//-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-extends templates/layout
-
-block container
-  h1= message
-  h2= error.status
-  pre #{error.stack}


[43/50] [abbrv] incubator-ignite git commit: # ignite-843 moved

Posted by an...@apache.org.
# ignite-843 moved


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

Branch: refs/heads/ignite-1121
Commit: 8a33572426c877c690e788ee1f71f7ff79edae70
Parents: e7ebf45
Author: Andrey <an...@gridgain.com>
Authored: Wed Jul 22 18:01:16 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Wed Jul 22 18:01:16 2015 +0700

----------------------------------------------------------------------
 modules/web-control-center/nodejs/.gitignore    |    4 -
 modules/web-control-center/nodejs/DEVNOTES.txt  |   21 -
 modules/web-control-center/nodejs/app.js        |  154 ---
 modules/web-control-center/nodejs/bin/www       |   85 --
 .../nodejs/config/default.json                  |    8 -
 .../nodejs/controllers/admin-controller.js      |   68 -
 .../controllers/cache-viewer-controller.js      |   77 --
 .../nodejs/controllers/caches-controller.js     |  333 -----
 .../nodejs/controllers/clusters-controller.js   |  309 -----
 .../nodejs/controllers/common-module.js         |  422 -------
 .../nodejs/controllers/metadata-controller.js   |  678 ----------
 .../nodejs/controllers/models/caches.json       |  918 --------------
 .../nodejs/controllers/models/clusters.json     |  907 --------------
 .../nodejs/controllers/models/metadata.json     |  230 ----
 .../nodejs/controllers/models/summary.json      |  163 ---
 .../nodejs/controllers/profile-controller.js    |   51 -
 .../nodejs/controllers/summary-controller.js    |  164 ---
 modules/web-control-center/nodejs/db.js         |  358 ------
 .../nodejs/helpers/configuration-loader.js      |   22 -
 .../nodejs/helpers/data-structures.js           |   84 --
 modules/web-control-center/nodejs/package.json  |   50 -
 .../nodejs/public/favicon.ico                   |  Bin 1150 -> 0 bytes
 .../nodejs/public/images/docker.png             |  Bin 994 -> 0 bytes
 .../nodejs/public/images/java.png               |  Bin 170 -> 0 bytes
 .../nodejs/public/images/logo.png               |  Bin 8148 -> 0 bytes
 .../nodejs/public/images/xml.png                |  Bin 232 -> 0 bytes
 .../nodejs/public/stylesheets/style.less        | 1172 ------------------
 .../web-control-center/nodejs/routes/admin.js   |   79 --
 .../web-control-center/nodejs/routes/caches.js  |   95 --
 .../nodejs/routes/clusters.js                   |  104 --
 .../nodejs/routes/generator/common.js           |  299 -----
 .../nodejs/routes/generator/docker.js           |   58 -
 .../nodejs/routes/generator/java.js             |  626 ----------
 .../nodejs/routes/generator/xml.js              |  580 ---------
 .../nodejs/routes/metadata.js                   |   95 --
 .../web-control-center/nodejs/routes/profile.js |   97 --
 .../web-control-center/nodejs/routes/public.js  |  123 --
 modules/web-control-center/nodejs/routes/sql.js |   24 -
 .../web-control-center/nodejs/routes/summary.js |  108 --
 .../nodejs/views/configuration/caches.jade      |   74 --
 .../nodejs/views/configuration/clusters.jade    |   77 --
 .../nodejs/views/configuration/metadata.jade    |  121 --
 .../nodejs/views/configuration/sidebar.jade     |   39 -
 .../nodejs/views/configuration/summary.jade     |  117 --
 .../web-control-center/nodejs/views/error.jade  |   22 -
 .../nodejs/views/includes/controls.jade         |  322 -----
 .../nodejs/views/includes/footer.jade           |   22 -
 .../nodejs/views/includes/header.jade           |   39 -
 .../web-control-center/nodejs/views/index.jade  |   30 -
 .../web-control-center/nodejs/views/login.jade  |   55 -
 .../nodejs/views/settings/admin.jade            |   58 -
 .../nodejs/views/settings/profile.jade          |   58 -
 .../nodejs/views/templates/confirm.jade         |   27 -
 .../nodejs/views/templates/copy.jade            |   31 -
 .../nodejs/views/templates/layout.jade          |   61 -
 .../nodejs/views/templates/select.jade          |   26 -
 .../web-control-center/src/main/js/.gitignore   |    4 +
 .../web-control-center/src/main/js/DEVNOTES.txt |   21 +
 modules/web-control-center/src/main/js/app.js   |  154 +++
 modules/web-control-center/src/main/js/bin/www  |   85 ++
 .../src/main/js/config/default.json             |    8 +
 .../src/main/js/controllers/admin-controller.js |   68 +
 .../js/controllers/cache-viewer-controller.js   |   77 ++
 .../main/js/controllers/caches-controller.js    |  333 +++++
 .../main/js/controllers/clusters-controller.js  |  309 +++++
 .../src/main/js/controllers/common-module.js    |  422 +++++++
 .../main/js/controllers/metadata-controller.js  |  678 ++++++++++
 .../src/main/js/controllers/models/caches.json  |  918 ++++++++++++++
 .../main/js/controllers/models/clusters.json    |  907 ++++++++++++++
 .../main/js/controllers/models/metadata.json    |  230 ++++
 .../src/main/js/controllers/models/summary.json |  163 +++
 .../main/js/controllers/profile-controller.js   |   51 +
 .../main/js/controllers/summary-controller.js   |  164 +++
 modules/web-control-center/src/main/js/db.js    |  358 ++++++
 .../src/main/js/helpers/configuration-loader.js |   22 +
 .../src/main/js/helpers/data-structures.js      |   84 ++
 .../web-control-center/src/main/js/package.json |   50 +
 .../src/main/js/public/favicon.ico              |  Bin 0 -> 1150 bytes
 .../src/main/js/public/images/docker.png        |  Bin 0 -> 994 bytes
 .../src/main/js/public/images/java.png          |  Bin 0 -> 170 bytes
 .../src/main/js/public/images/logo.png          |  Bin 0 -> 8148 bytes
 .../src/main/js/public/images/xml.png           |  Bin 0 -> 232 bytes
 .../src/main/js/public/stylesheets/style.less   | 1172 ++++++++++++++++++
 .../src/main/js/routes/admin.js                 |   79 ++
 .../src/main/js/routes/caches.js                |   95 ++
 .../src/main/js/routes/clusters.js              |  104 ++
 .../src/main/js/routes/generator/common.js      |  299 +++++
 .../src/main/js/routes/generator/docker.js      |   58 +
 .../src/main/js/routes/generator/java.js        |  626 ++++++++++
 .../src/main/js/routes/generator/xml.js         |  580 +++++++++
 .../src/main/js/routes/metadata.js              |   95 ++
 .../src/main/js/routes/profile.js               |   97 ++
 .../src/main/js/routes/public.js                |  123 ++
 .../src/main/js/routes/sql.js                   |   24 +
 .../src/main/js/routes/summary.js               |  108 ++
 .../src/main/js/views/configuration/caches.jade |   74 ++
 .../main/js/views/configuration/clusters.jade   |   77 ++
 .../main/js/views/configuration/metadata.jade   |  121 ++
 .../main/js/views/configuration/sidebar.jade    |   39 +
 .../main/js/views/configuration/summary.jade    |  117 ++
 .../src/main/js/views/error.jade                |   22 +
 .../src/main/js/views/includes/controls.jade    |  322 +++++
 .../src/main/js/views/includes/footer.jade      |   22 +
 .../src/main/js/views/includes/header.jade      |   39 +
 .../src/main/js/views/index.jade                |   30 +
 .../src/main/js/views/login.jade                |   55 +
 .../src/main/js/views/settings/admin.jade       |   58 +
 .../src/main/js/views/settings/profile.jade     |   58 +
 .../src/main/js/views/templates/confirm.jade    |   27 +
 .../src/main/js/views/templates/copy.jade       |   31 +
 .../src/main/js/views/templates/layout.jade     |   61 +
 .../src/main/js/views/templates/select.jade     |   26 +
 112 files changed, 9745 insertions(+), 9745 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/.gitignore
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/.gitignore b/modules/web-control-center/nodejs/.gitignore
deleted file mode 100644
index 65f2596..0000000
--- a/modules/web-control-center/nodejs/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-node_modules
-*.idea
-*.log
-*.css
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/DEVNOTES.txt
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/DEVNOTES.txt b/modules/web-control-center/nodejs/DEVNOTES.txt
deleted file mode 100644
index aa56011..0000000
--- a/modules/web-control-center/nodejs/DEVNOTES.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Ignite Web Control Center Instructions
-======================================
-
-How to deploy:
-
-1. Install locally NodeJS using installer from site https://nodejs.org for your OS.
-2. Install locally MongoDB folow instructions from site http://docs.mongodb.org/manual/installation
-3. Checkout ignite-843 branch.
-4. Change directory '$IGNITE_HOME/modules/web-control-center/nodejs'.
-5. Run "npm install" in terminal for download all dependencies.
-
-Steps 1 - 5 should be executed once.
-
-How to run:
-
-1. Run MongoDB.
- 1.1 In terminal change dir to $MONGO_ISNTALL_DIR/server/3.0/bin.
- 1.2 Run "mongod".
-2. In new terminal change directory '$IGNITE_HOME/modules/web-control-center/nodejs'.
-3. Start application by executing "npm start".
-4. In browser open: http://localhost:3000
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/app.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/app.js b/modules/web-control-center/nodejs/app.js
deleted file mode 100644
index 8c347db..0000000
--- a/modules/web-control-center/nodejs/app.js
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var flash = require('connect-flash');
-var express = require('express');
-var path = require('path');
-var favicon = require('serve-favicon');
-var logger = require('morgan');
-var cookieParser = require('cookie-parser');
-var bodyParser = require('body-parser');
-var session = require('express-session');
-var mongoStore = require('connect-mongo')(session);
-
-var publicRoutes = require('./routes/public');
-var clustersRouter = require('./routes/clusters');
-var cachesRouter = require('./routes/caches');
-var metadataRouter = require('./routes/metadata');
-var summary = require('./routes/summary');
-var adminRouter = require('./routes/admin');
-var profileRouter = require('./routes/profile');
-var sqlRouter = require('./routes/sql');
-
-var passport = require('passport');
-
-var db = require('./db');
-
-var app = express();
-
-// Views engine setup.
-app.set('views', path.join(__dirname, 'views'));
-app.set('view engine', 'jade');
-
-// Site favicon.
-app.use(favicon(__dirname + '/public/favicon.ico'));
-
-app.use(logger('dev'));
-
-app.use(bodyParser.json());
-app.use(bodyParser.urlencoded({extended: false}));
-
-app.use(require('less-middleware')(path.join(__dirname, 'public'), {
-    render: {
-        compress: false
-    }
-}));
-
-app.use(express.static(path.join(__dirname, 'public')));
-app.use(express.static(path.join(__dirname, 'controllers')));
-app.use(express.static(path.join(__dirname, 'helpers')));
-
-app.use(cookieParser('keyboard cat'));
-
-app.use(session({
-    secret: 'keyboard cat',
-    resave: false,
-    saveUninitialized: true,
-    store: new mongoStore({
-        mongooseConnection: db.mongoose.connection
-    })
-}));
-
-app.use(flash());
-
-app.use(passport.initialize());
-app.use(passport.session());
-
-passport.serializeUser(db.Account.serializeUser());
-passport.deserializeUser(db.Account.deserializeUser());
-
-passport.use(db.Account.createStrategy());
-
-var mustAuthenticated = function (req, res, next) {
-    req.isAuthenticated() ? next() : res.redirect('/');
-};
-
-var adminOnly = function(req, res, next) {
-    req.isAuthenticated() && req.user.admin ? next() : res.sendStatus(403);
-};
-
-app.all('/configuration/*', mustAuthenticated);
-
-app.all('*', function(req, res, next) {
-    var becomeUsed = req.session.viewedUser && req.user.admin;
-
-    res.locals.user = becomeUsed ? req.session.viewedUser : req.user;
-    res.locals.becomeUsed = becomeUsed;
-
-    req.currentUserId = function() {
-        if (!req.user)
-            return null;
-
-        if (req.session.viewedUser && req.user.admin)
-            return req.session.viewedUser._id;
-
-        return req.user._id;
-    };
-
-    next();
-});
-
-app.use('/', publicRoutes);
-app.use('/admin', mustAuthenticated, adminOnly, adminRouter);
-app.use('/profile', mustAuthenticated, profileRouter);
-
-app.use('/configuration/clusters', clustersRouter);
-app.use('/configuration/caches', cachesRouter);
-app.use('/configuration/metadata', metadataRouter);
-app.use('/configuration/summary', summary);
-app.use('/sql', sqlRouter);
-
-// Catch 404 and forward to error handler.
-app.use(function (req, res, next) {
-    var err = new Error('Not Found: ' + req.originalUrl);
-    err.status = 404;
-    next(err);
-});
-
-// Error handlers.
-
-// Development error handler: will print stacktrace.
-if (app.get('env') === 'development') {
-    app.use(function (err, req, res) {
-        res.status(err.status || 500);
-        res.render('error', {
-            message: err.message,
-            error: err
-        });
-    });
-}
-
-// Production error handler: no stacktraces leaked to user.
-app.use(function (err, req, res) {
-    res.status(err.status || 500);
-    res.render('error', {
-        message: err.message,
-        error: {}
-    });
-});
-
-module.exports = app;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/bin/www
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/bin/www b/modules/web-control-center/nodejs/bin/www
deleted file mode 100644
index 4cf0583..0000000
--- a/modules/web-control-center/nodejs/bin/www
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Module dependencies.
- */
-var app = require('../app');
-var config = require('../helpers/configuration-loader.js');
-var debug = require('debug')('ignite-web-control-center:server');
-var http = require('http');
-
-/**
- * Get port from environment and store in Express.
- */
-var port = normalizePort(process.env.PORT || config.get('express:port'));
-app.set('port', port);
-
-/**
- * Create HTTP server.
- */
-var server = http.createServer(app);
-
-/**
- * Listen on provided port, on all network interfaces.
- */
-server.listen(port);
-server.on('error', onError);
-server.on('listening', onListening);
-
-/**
- * Normalize a port into a number, string, or false.
- */
-function normalizePort(val) {
-  var port = parseInt(val, 10);
-
-  if (isNaN(port)) {
-    // named pipe
-    return val;
-  }
-
-  if (port >= 0) {
-    // port number
-    return port;
-  }
-
-  return false;
-}
-
-/**
- * Event listener for HTTP server "error" event.
- */
-function onError(error) {
-  if (error.syscall !== 'listen') {
-    throw error;
-  }
-
-  var bind = typeof port === 'string'
-    ? 'Pipe ' + port
-    : 'Port ' + port;
-
-  // handle specific listen errors with friendly messages
-  switch (error.code) {
-    case 'EACCES':
-      console.error(bind + ' requires elevated privileges');
-      process.exit(1);
-      break;
-    case 'EADDRINUSE':
-      console.error(bind + ' is already in use');
-      process.exit(1);
-      break;
-    default:
-      throw error;
-  }
-}
-
-/**
- * Event listener for HTTP server "listening" event.
- */
-function onListening() {
-  var addr = server.address();
-  var bind = typeof addr === 'string'
-    ? 'pipe ' + addr
-    : 'port ' + addr.port;
-
-  debug('Listening on ' + bind);
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/config/default.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/config/default.json b/modules/web-control-center/nodejs/config/default.json
deleted file mode 100644
index 72dbd4e..0000000
--- a/modules/web-control-center/nodejs/config/default.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "express": {
-        "port": 3000
-    },
-    "mongoDB": {
-        "url": "mongodb://localhost/web-control-center"
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/controllers/admin-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/admin-controller.js b/modules/web-control-center/nodejs/controllers/admin-controller.js
deleted file mode 100644
index 09490fe..0000000
--- a/modules/web-control-center/nodejs/controllers/admin-controller.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-controlCenterModule.controller('adminController', ['$scope', '$http', '$common', '$confirm', function ($scope, $http, $common, $confirm) {
-    $scope.users = null;
-
-    function reload() {
-        $http.post('admin/list')
-            .success(function (data) {
-                $scope.users = data;
-            })
-            .error(function (errMsg) {
-                $common.showError($common.errorMessage(errMsg));
-            });
-    }
-
-    reload();
-
-    $scope.removeUser = function (user) {
-        $confirm.show('Are you sure you want to remove user: "' + user.username + '"?').then(function () {
-            $http.post('admin/remove', {userId: user._id}).success(
-                function () {
-                    var i = _.findIndex($scope.users, function (u) {
-                        return u._id == user._id;
-                    });
-
-                    if (i >= 0)
-                        $scope.users.splice(i, 1);
-
-                    $common.showInfo('User has been removed: "' + user.username + '"');
-                }).error(function (errMsg) {
-                    $common.showError('Failed to remove user: "' + $common.errorMessage(errMsg) + '"');
-                });
-        });
-    };
-
-    $scope.toggleAdmin = function (user) {
-        if (user.adminChanging)
-            return;
-
-        user.adminChanging = true;
-
-        $http.post('admin/save', {userId: user._id, adminFlag: user.admin}).success(
-            function () {
-                $common.showInfo('Admin right was successfully toggled for user: "' + user.username + '"');
-
-                user.adminChanging = false;
-            }).error(function (errMsg) {
-                $common.showError('Failed to toggle admin right for user: "' + $common.errorMessage(errMsg) + '"');
-
-                user.adminChanging = false;
-            });
-    }
-}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/controllers/cache-viewer-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/cache-viewer-controller.js b/modules/web-control-center/nodejs/controllers/cache-viewer-controller.js
deleted file mode 100644
index 6e0c130..0000000
--- a/modules/web-control-center/nodejs/controllers/cache-viewer-controller.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var demoResults = [
-    {
-        id: 256,
-        s: 'com.foo.User@3213',
-        fields: {
-            id: 256,
-            firstName: 'Ivan',
-            lastName: 'Ivanov',
-            old: 23
-        }
-    },
-
-    {
-        id: 384,
-        s: 'com.foo.User@23214',
-        fields: {
-            id: 384,
-            firstName: 'Sergey',
-            lastName: 'Petrov',
-            old: 28
-        }
-    },
-
-    {
-        id: 923,
-        s: 'com.foo.User@93494',
-        fields: {
-            id: 923,
-            firstName: 'Andrey',
-            lastName: 'Sidorov',
-            old: 28
-        }
-    }
-];
-
-var demoCaches = ['Users', 'Organizations', 'Cities'];
-
-controlCenterModule.controller('cacheViewerController', ['$scope', '$http', '$common', function ($scope, $http, $common) {
-    $scope.results = demoResults;
-
-    $scope.caches = demoCaches;
-
-    $scope.defCache = $scope.caches.length > 0 ? $scope.caches[0] : null;
-
-    var sqlEditor = ace.edit('querySql');
-
-    sqlEditor.setOptions({
-        highlightActiveLine: false,
-        showPrintMargin: false,
-        showGutter: true,
-        theme: "ace/theme/chrome",
-        mode: "ace/mode/sql",
-        fontSize: 14
-    });
-
-    sqlEditor.setValue("select u.id from User u where u.name like 'aaaa';");
-
-    sqlEditor.selection.clearSelection()
-
-}]);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/controllers/caches-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/caches-controller.js b/modules/web-control-center/nodejs/controllers/caches-controller.js
deleted file mode 100644
index 0c23e3b..0000000
--- a/modules/web-control-center/nodejs/controllers/caches-controller.js
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-controlCenterModule.controller('cachesController', ['$scope', '$http', '$common', '$confirm', '$copy', '$table', function ($scope, $http, $common, $confirm, $copy, $table) {
-        $scope.joinTip = $common.joinTip;
-        $scope.getModel = $common.getModel;
-
-        $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.atomicities = [
-            {value: 'ATOMIC', label: 'ATOMIC'},
-            {value: 'TRANSACTIONAL', label: 'TRANSACTIONAL'}
-        ];
-
-        $scope.modes = [
-            {value: 'PARTITIONED', label: 'PARTITIONED'},
-            {value: 'REPLICATED', label: 'REPLICATED'},
-            {value: 'LOCAL', label: 'LOCAL'}
-        ];
-
-        $scope.atomicWriteOrderModes = [
-            {value: 'CLOCK', label: 'CLOCK'},
-            {value: 'PRIMARY', label: 'PRIMARY'}
-        ];
-
-        $scope.memoryModes = [
-            {value: 'ONHEAP_TIERED', label: 'ONHEAP_TIERED'},
-            {value: 'OFFHEAP_TIERED', label: 'OFFHEAP_TIERED'},
-            {value: 'OFFHEAP_VALUES', label: '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 = [
-            {value: 'SYNC', label: 'SYNC'},
-            {value: 'ASYNC', label: 'ASYNC'},
-            {value: 'NONE', label: '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.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.required = function (field) {
-            var model = $common.isDefined(field.path) ? field.path + '.' + field.model : field.model;
-
-            var backupItem = $scope.backupItem;
-
-            var memoryMode = backupItem.memoryMode;
-
-            var onHeapTired = memoryMode == 'ONHEAP_TIERED';
-            var offHeapTired = memoryMode == 'OFFHEAP_TIERED';
-
-            var offHeapMaxMemory = backupItem.offHeapMaxMemory;
-
-            if (model == 'offHeapMaxMemory' && offHeapTired)
-                return true;
-
-            if (model == 'evictionPolicy.kind' && onHeapTired)
-                return backupItem.swapEnabled || ($common.isDefined(offHeapMaxMemory) && offHeapMaxMemory >= 0);
-
-            return false;
-        };
-
-        $scope.tableSimpleValid = function (item, field, fx, index) {
-            var model = item[field.model];
-
-            if ($common.isDefined(model)) {
-                var idx = _.indexOf(model, fx);
-
-                // Found itself.
-                if (index >= 0 && index == idx)
-                    return true;
-
-                // Found duplicate.
-                if (idx >= 0) {
-                    $common.showError('SQL function such class name already exists!');
-
-                    return false;
-                }
-            }
-
-            return true;
-        };
-
-        $scope.tablePairValid = function (item, field, keyCls, valCls, index) {
-            var model = item[field.model];
-
-            if ($common.isDefined(model)) {
-                var idx = _.findIndex(model, function (pair) {
-                    return pair.keyClass == keyCls
-                });
-
-                // Found itself.
-                if (index >= 0 && index == idx)
-                    return true;
-
-                // Found duplicate.
-                if (idx >= 0) {
-                    $common.showError('Indexed type with such key class already exists!');
-
-                    return false;
-                }
-            }
-
-            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;
-
-                var restoredItem = angular.fromJson(sessionStorage.cacheBackupItem);
-
-                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;
-                        }
-                        else
-                            sessionStorage.removeItem('cacheBackupItem');
-                    }
-                    else
-                        $scope.backupItem = restoredItem;
-                }
-                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.selectItem = function (item) {
-            $table.tableReset();
-
-            $scope.selectedItem = item;
-            $scope.backupItem = angular.copy(item);
-        };
-
-        // Add new cache.
-        $scope.createItem = function () {
-            $table.tableReset();
-
-            $scope.backupItem = {mode: 'PARTITIONED', atomicityMode: 'ATOMIC', readFromBackup: true, copyOnRead: true};
-            $scope.backupItem.space = $scope.spaces[0]._id;
-        };
-
-        // 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!');
-
-                return false;
-            }
-
-            if ((item.readThrough || item.writeThrough) && !cacheStoreFactorySelected) {
-                $common.showError('Read / write through are enabled but store is not configured!');
-
-                return false;
-            }
-
-            if (item.writeBehindEnabled && !cacheStoreFactorySelected) {
-                $common.showError('Write behind enabled but store is not configured!');
-
-                return false;
-            }
-
-            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;
-                    });
-
-                    if (idx >= 0)
-                        angular.extend($scope.caches[idx], item);
-                    else {
-                        item._id = _id;
-
-                        $scope.caches.push(item);
-                    }
-
-                    $scope.selectItem(item);
-
-                    $common.showInfo('Cache "' + item.name + '" saved.');
-                })
-                .error(function (errMsg) {
-                    $common.showError(errMsg);
-                });
-        }
-
-        // Save cache.
-        $scope.saveItem = function () {
-            $table.tableReset();
-
-            var item = $scope.backupItem;
-
-            if (validate(item))
-                save(item);
-        };
-
-        // 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);
-
-                    item._id = undefined;
-                    item.name = newName;
-
-                    save(item);
-                });
-        };
-
-        // Remove cache from db.
-        $scope.removeItem = function () {
-            $table.tableReset();
-
-            var selectedItem = $scope.selectedItem;
-
-            $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);
-
-                            var caches = $scope.caches;
-
-                            var idx = _.findIndex(caches, function (cache) {
-                                return cache._id == _id;
-                            });
-
-                            if (idx >= 0) {
-                                caches.splice(idx, 1);
-
-                                if (caches.length > 0)
-                                    $scope.selectItem(caches[0]);
-                                else {
-                                    $scope.selectedItem = undefined;
-                                    $scope.backupItem = undefined;
-                                }
-                            }
-                        })
-                        .error(function (errMsg) {
-                            $common.showError(errMsg);
-                        });
-                }
-            );
-        };
-    }]
-);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/clusters-controller.js b/modules/web-control-center/nodejs/controllers/clusters-controller.js
deleted file mode 100644
index 1ec78a1..0000000
--- a/modules/web-control-center/nodejs/controllers/clusters-controller.js
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-controlCenterModule.controller('clustersController', ['$scope', '$http', '$common', '$confirm', '$copy', '$table', function ($scope, $http, $common, $confirm, $copy, $table) {
-        $scope.joinTip = $common.joinTip;
-        $scope.getModel = $common.getModel;
-
-        $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.templates = [
-            {
-                value: {discovery: {kind: 'Multicast', Vm: {addresses: ['127.0.0.1:47500..47510']}, Multicast: {}}},
-                label: 'multicast'
-            },
-            {value: {discovery: {kind: 'Vm', Vm: {addresses: ['127.0.0.1:47500..47510']}}}, label: 'local'}
-        ];
-
-        $scope.discoveries = [
-            {value: 'Vm', label: 'static IPs'},
-            {value: 'Multicast', label: 'multicast'},
-            {value: 'S3', label: 'AWS S3'},
-            {value: 'Cloud', label: 'apache jclouds'},
-            {value: 'GoogleStorage', label: 'google cloud storage'},
-            {value: 'Jdbc', label: 'JDBC'},
-            {value: 'SharedFs', label: 'shared filesystem'}
-        ];
-
-        $scope.swapSpaceSpis = [
-            {value: 'FileSwapSpaceSpi', label: 'File-based swap'},
-            {value: undefined, label: 'Not set'}
-        ];
-
-        $scope.events = [];
-
-        for (var eventGroupName in eventGroups) {
-            if (eventGroups.hasOwnProperty(eventGroupName)) {
-                $scope.events.push({value: eventGroupName, label: eventGroupName});
-            }
-        }
-
-        $scope.cacheModes = [
-            {value: 'LOCAL', label: 'LOCAL'},
-            {value: 'REPLICATED', label: 'REPLICATED'},
-            {value: 'PARTITIONED', label: 'PARTITIONED'}
-        ];
-
-        $scope.deploymentModes = [
-            {value: 'PRIVATE', label: 'PRIVATE'},
-            {value: 'ISOLATED', label: 'ISOLATED'},
-            {value: 'SHARED', label: 'SHARED'},
-            {value: 'CONTINUOUS', label: 'CONTINUOUS'}
-        ];
-
-        $scope.transactionConcurrency = [
-            {value: 'OPTIMISTIC', label: 'OPTIMISTIC'},
-            {value: 'PESSIMISTIC', label: 'PESSIMISTIC'}
-        ];
-
-        $scope.transactionIsolation = [
-            {value: 'READ_COMMITTED', label: 'READ_COMMITTED'},
-            {value: 'REPEATABLE_READ', label: 'REPEATABLE_READ'},
-            {value: 'SERIALIZABLE', label: 'SERIALIZABLE'}
-        ];
-
-        $scope.segmentationPolicy = [
-            {value: 'RESTART_JVM', label: 'RESTART_JVM'},
-            {value: 'STOP', label: 'STOP'},
-            {value: 'NOOP', label: 'NOOP'}
-        ];
-
-        $scope.marshallers = [
-            {value: 'OptimizedMarshaller', label: 'OptimizedMarshaller'},
-            {value: 'JdkMarshaller', label: 'JdkMarshaller'}
-        ];
-
-        $scope.tableSimpleValid = function (item, field, val, index) {
-            var model = $common.getModel(item, field)[field.model];
-
-            if ($common.isDefined(model)) {
-                var idx = _.indexOf(model, val);
-
-                // Found itself.
-                if (index >= 0 && index == idx)
-                    return true;
-
-                // Found duplicate.
-                if (idx >= 0) {
-                    var msg = 'Such IP address already exists!';
-
-                    if (field.model == 'regions')
-                        msg = 'Such region already exists!';
-                    if (field.model == 'zones')
-                        msg = 'Such zone already exists!';
-
-                    $common.showError(msg);
-
-                    return false;
-                }
-            }
-
-            return true;
-        };
-
-        $scope.clusters = [];
-
-        $http.get('/models/clusters.json')
-            .success(function (data) {
-                $scope.screenTip = data.screenTip;
-                $scope.templateTip = data.templateTip;
-
-                $scope.general = data.general;
-                $scope.advanced = data.advanced;
-            })
-            .error(function (errMsg) {
-                $common.showError(errMsg);
-            });
-
-        // When landing on the page, get clusters and show them.
-        $http.post('clusters/list')
-            .success(function (data) {
-                $scope.caches = data.caches;
-                $scope.spaces = data.spaces;
-                $scope.clusters = data.clusters;
-
-                var restoredItem = angular.fromJson(sessionStorage.clusterBackupItem);
-
-                if (restoredItem) {
-                    if (restoredItem._id) {
-                        var idx = _.findIndex($scope.clusters, function (cluster) {
-                            return cluster._id == restoredItem._id;
-                        });
-
-                        if (idx >= 0) {
-                            $scope.selectedItem = $scope.clusters[idx];
-                            $scope.backupItem = restoredItem;
-                        }
-                        else
-                            sessionStorage.removeItem('clusterBackupItem');
-                    }
-                    else
-                        $scope.backupItem = restoredItem;
-                }
-                else if ($scope.clusters.length > 0)
-                    $scope.selectItem($scope.clusters[0]);
-
-                $scope.$watch('backupItem', function (val) {
-                    if (val)
-                        sessionStorage.clusterBackupItem = angular.toJson(val);
-                }, true);
-            })
-            .error(function (errMsg) {
-                $common.showError(errMsg);
-            });
-
-        $scope.selectItem = function (item) {
-            $table.tableReset();
-
-            $scope.selectedItem = item;
-            $scope.backupItem = angular.copy(item);
-        };
-
-        // Add new cluster.
-        $scope.createItem = function () {
-            $table.tableReset();
-
-            $scope.backupItem = angular.copy($scope.create.template);
-            $scope.backupItem.space = $scope.spaces[0]._id;
-        };
-
-        $scope.indexOfCache = function (cacheId) {
-            return _.findIndex($scope.caches, function (cache) {
-                return cache.value == cacheId;
-            });
-        };
-
-        // Check cluster logical consistency.
-        function validate(item) {
-            if (!item.swapSpaceSpi || !item.swapSpaceSpi.kind && item.caches) {
-                for (var i = 0; i < item.caches.length; i++) {
-                    var idx = $scope.indexOfCache(item.caches[i]);
-
-                    if (idx >= 0) {
-                        var cache = $scope.caches[idx];
-
-                        if (cache.swapEnabled) {
-                            $common.showError('Swap space SPI is not configured, but cache "' + cache.label + '" configured to use swap!');
-
-                            return false;
-                        }
-                    }
-                }
-            }
-
-            return true;
-        }
-
-        // Save cluster in database.
-        function save(item) {
-            $http.post('clusters/save', item)
-                .success(function (_id) {
-                    var idx = _.findIndex($scope.clusters, function (cluster) {
-                        return cluster._id == _id;
-                    });
-
-                    if (idx >= 0)
-                        angular.extend($scope.clusters[idx], item);
-                    else {
-                        item._id = _id;
-
-                        $scope.clusters.push(item);
-                    }
-
-                    $scope.selectItem(item);
-
-                    $common.showInfo('Cluster "' + item.name + '" saved.');
-                })
-                .error(function (errMsg) {
-                    $common.showError(errMsg);
-                });
-        }
-
-        // Save cluster.
-        $scope.saveItem = function () {
-            $table.tableReset();
-
-            var item = $scope.backupItem;
-
-            if (validate(item))
-                save(item);
-        };
-
-        // Save cluster 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);
-
-                    item._id = undefined;
-                    item.name = newName;
-
-                    save(item);
-                });
-        };
-
-        // Remove cluster from db.
-        $scope.removeItem = function () {
-            $table.tableReset();
-
-            var selectedItem = $scope.selectedItem;
-
-            $confirm.show('Are you sure you want to remove cluster: "' + selectedItem.name + '"?').then(
-                function () {
-                    var _id = selectedItem._id;
-
-                    $http.post('clusters/remove', {_id: _id})
-                        .success(function () {
-                            $common.showInfo('Cluster has been removed: ' + selectedItem.name);
-
-                            var clusters = $scope.clusters;
-
-                            var idx = _.findIndex(clusters, function (cluster) {
-                                return cluster._id == _id;
-                            });
-
-                            if (idx >= 0) {
-                                clusters.splice(idx, 1);
-
-                                if (clusters.length > 0)
-                                    $scope.selectItem(clusters[0]);
-                                else {
-                                    $scope.selectedItem = undefined;
-                                    $scope.backupItem = undefined;
-                                }
-                            }
-                        })
-                        .error(function (errMsg) {
-                            $common.showError(errMsg);
-                        });
-                }
-            );
-        };
-    }]
-);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/controllers/common-module.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/common-module.js b/modules/web-control-center/nodejs/controllers/common-module.js
deleted file mode 100644
index 75af155..0000000
--- a/modules/web-control-center/nodejs/controllers/common-module.js
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var controlCenterModule = angular.module('ignite-web-control-center', ['smart-table', 'mgcrea.ngStrap', 'ui.ace', 'ngSanitize']);
-
-// Modal popup configuration.
-controlCenterModule.config(function ($modalProvider) {
-    angular.extend($modalProvider.defaults, {
-        html: true
-    });
-});
-
-// Tooltips configuration.
-controlCenterModule.config(function ($tooltipProvider) {
-    angular.extend($tooltipProvider.defaults, {
-        container: 'body',
-        placement: 'right',
-        html: 'true',
-        trigger: 'click hover'
-    });
-});
-
-// Comboboxes configuration.
-controlCenterModule.config(function ($selectProvider) {
-    angular.extend($selectProvider.defaults, {
-        maxLength: '1',
-        allText: 'Select All',
-        noneText: 'Clear All',
-        templateUrl: '/select',
-        iconCheckmark: 'fa fa-check',
-        caretHtml: '<span class="caret"></span>'
-    });
-});
-
-// Alerts configuration.
-controlCenterModule.config(function ($alertProvider) {
-    angular.extend($alertProvider.defaults, {
-        container: 'body',
-        placement: 'top-right',
-        duration: '5',
-        type: 'danger'
-    });
-});
-
-// Common functions to be used in controllers.
-controlCenterModule.service('$common', ['$alert', function ($alert) {
-    var msgModal = undefined;
-
-    function errorMessage(errMsg) {
-        return errMsg ? errMsg : 'Internal server error.';
-    }
-
-    function isDefined(v) {
-        return !(v === undefined || v === null);
-    }
-
-    return {
-        getModel: function (obj, field) {
-            var path = field.path;
-
-            if (!isDefined(path))
-                return obj;
-
-            path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
-            path = path.replace(/^\./, '');           // strip a leading dot
-
-            var segs = path.split('.');
-            var root = obj;
-
-            while (segs.length > 0) {
-                var pathStep = segs.shift();
-
-                if (typeof root[pathStep] === 'undefined')
-                    root[pathStep] = {};
-
-                root = root[pathStep];
-            }
-
-            return root;
-        },
-        joinTip: function (arr) {
-            if (!arr) {
-                return arr;
-            }
-
-            var lines = arr.map(function (line) {
-                var rtrimmed = line.replace(/\s+$/g, '');
-
-                if (rtrimmed.indexOf('>', this.length - 1) == -1) {
-                    rtrimmed = rtrimmed + '<br/>';
-                }
-
-                return rtrimmed;
-            });
-
-            return lines.join("");
-        },
-        isDefined: isDefined,
-        isNonEmpty: function (s) {
-            return isDefined(s) && s.trim().length > 0;
-        },
-        errorMessage: errorMessage,
-        showError: function (msg) {
-            if (msgModal)
-                msgModal.hide();
-
-            msgModal = $alert({title: errorMessage(msg)});
-        },
-        showInfo: function (msg) {
-            if (msgModal)
-                msgModal.hide();
-
-            msgModal = $alert({
-                type: 'success',
-                title: msg,
-                duration: 2
-            });
-        }
-    }
-}]);
-
-// Confirm popup service.
-controlCenterModule.service('$confirm', function ($modal, $rootScope, $q) {
-    var scope = $rootScope.$new();
-
-    var deferred;
-
-    scope.ok = function () {
-        deferred.resolve();
-
-        confirmModal.hide();
-    };
-
-    var confirmModal = $modal({templateUrl: '/confirm', scope: scope, placement: 'center', show: false});
-
-    var parentShow = confirmModal.show;
-
-    confirmModal.show = function (content) {
-        scope.content = content || 'Confirm deletion?';
-
-        deferred = $q.defer();
-
-        parentShow();
-
-        return deferred.promise;
-    };
-
-    return confirmModal;
-});
-
-// "Save as" popup service.
-controlCenterModule.service('$copy', function ($modal, $rootScope, $q) {
-    var scope = $rootScope.$new();
-
-    var deferred;
-
-    scope.ok = function (newName) {
-        deferred.resolve(newName);
-
-        copyModal.hide();
-    };
-
-    var copyModal = $modal({templateUrl: '/copy', scope: scope, placement: 'center', show: false});
-
-    var parentShow = copyModal.show;
-
-    copyModal.show = function (oldName) {
-        scope.newName = oldName + '(1)';
-
-        deferred = $q.defer();
-
-        parentShow();
-
-        return deferred.promise;
-    };
-
-    return copyModal;
-});
-
-// Tables support service.
-controlCenterModule.service('$table', ['$common', function ($common) {
-    function _swapSimpleItems(a, ix1, ix2) {
-        var tmp = a[ix1];
-
-        a[ix1] = a[ix2];
-        a[ix2] = tmp;
-    }
-
-    function _model(item, field) {
-        return $common.getModel(item, field);
-    }
-
-    var table = {name: 'none', editIndex: -1};
-
-    function _tableReset() {
-        table.name = 'none';
-        table.editIndex = -1;
-    }
-
-    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)) {
-                _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][index] = newValue;
-            }
-        },
-        tableSimpleSaveVisible: function (newValue) {
-            return $common.isNonEmpty(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)) {
-                _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;
-                }
-            }
-        },
-        tablePairSaveVisible: function (newKey, newValue) {
-            return $common.isNonEmpty(newKey) && $common.isNonEmpty(newValue);
-        }
-    }
-}]);
-
-
-// Filter to decode name using map(value, label).
-controlCenterModule.filter('displayValue', function () {
-    return function (v, m, dflt) {
-        var i = _.findIndex(m, function (item) {
-            return item.value == v;
-        });
-
-        if (i >= 0) {
-            return m[i].label;
-        }
-
-        if (dflt) {
-            return dflt;
-        }
-
-        return 'Unknown value';
-    }
-});
-
-/**
- * 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])';
-    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])';
-
-    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;
-            }
-        }
-    }
-});
-
-// Directive to enable validation to match specified value.
-controlCenterModule.directive('match', function ($parse) {
-    return {
-        require: 'ngModel',
-        link: function (scope, elem, attrs, ctrl) {
-            scope.$watch(function () {
-                return $parse(attrs.match)(scope) === ctrl.$modelValue;
-            }, function (currentValue) {
-                ctrl.$setValidity('mismatch', currentValue);
-            });
-        }
-    };
-});
-
-// Navigation bar controller.
-controlCenterModule.controller('activeLink', [
-    '$scope', function ($scope) {
-        $scope.isActive = function (path) {
-            return window.location.pathname.substr(0, path.length) == path;
-        };
-    }]);
-
-// Login popup controller.
-controlCenterModule.controller('auth', [
-    '$scope', '$modal', '$alert', '$http', '$window', '$common',
-    function ($scope, $modal, $alert, $http, $window, $common) {
-        $scope.errorMessage = $common.errorMessage;
-
-        $scope.action = 'login';
-
-        $scope.valid = false;
-
-        $scope.userDropdown = [{"text": "Profile", "href": "/profile"}];
-
-        if (!$scope.becomeUsed) {
-            if ($scope.user && $scope.user.admin)
-                $scope.userDropdown.push({"text": "Admin Panel", "href": "/admin"});
-
-            $scope.userDropdown.push({"text": "Log Out", "href": "/logout"});
-        }
-
-        // Pre-fetch an external template populated with a custom scope
-        var authModal = $modal({scope: $scope, templateUrl: '/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.auth = function (action, user_info) {
-            $http.post('/' + action, user_info)
-                .success(function () {
-                    authModal.hide();
-
-                    $window.location = '/configuration/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/8a335724/modules/web-control-center/nodejs/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/metadata-controller.js b/modules/web-control-center/nodejs/controllers/metadata-controller.js
deleted file mode 100644
index b62cde5..0000000
--- a/modules/web-control-center/nodejs/controllers/metadata-controller.js
+++ /dev/null
@@ -1,678 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-controlCenterModule.controller('metadataController', ['$scope', '$http', '$common', '$confirm', '$copy', '$table', function ($scope, $http, $common, $confirm, $copy, $table) {
-        $scope.joinTip = $common.joinTip;
-        $scope.getModel = $common.getModel;
-
-        $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.templates = [
-            {value: {kind: 'query'}, label: 'query'},
-            {value: {kind: 'store'}, label: 'store'},
-            {value: {kind: 'both'}, label: 'both'}
-        ];
-
-        $scope.template = $scope.templates[0].value;
-
-        $scope.kinds = [
-            {value: 'query', label: 'query'},
-            {value: 'store', label: 'store'},
-            {value: 'both', label: 'both'}
-        ];
-
-        $scope.databases = [
-            {value: 'oracle', label: 'Oracle database'},
-            {value: 'db2', label: 'IBM DB2'},
-            {value: 'mssql', label: 'MS SQL Server'},
-            {value: 'postgre', label: 'PostgreSQL'},
-            {value: 'mysql', label: 'MySQL'},
-            {value: 'h2', label: 'H2 database'}
-        ];
-
-        $scope.jdbcTypes = [
-            {value: 'BIT', label: 'BIT'},
-            {value: 'BOOLEAN', label: 'BOOLEAN'},
-            {value: 'TINYINT', label: 'TINYINT'},
-            {value: 'SMALLINT', label: 'SMALLINT'},
-            {value: 'INTEGER', label: 'INTEGER'},
-            {value: 'BIGINT', label: 'BIGINT'},
-            {value: 'REAL', label: 'REAL'},
-            {value: 'FLOAT', label: 'FLOAT'},
-            {value: 'DOUBLE', label: 'DOUBLE'},
-            {value: 'NUMERIC', label: 'NUMERIC'},
-            {value: 'DECIMAL', label: 'DECIMAL'},
-            {value: 'CHAR', label: 'CHAR'},
-            {value: 'VARCHAR', label: 'VARCHAR'},
-            {value: 'LONGVARCHAR', label: 'LONGVARCHAR'},
-            {value: 'NCHAR', label: 'NCHAR'},
-            {value: 'NVARCHAR', label: 'NVARCHAR'},
-            {value: 'LONGNVARCHAR', label: 'LONGNVARCHAR'},
-            {value: 'DATE', label: 'DATE'},
-            {value: 'TIME', label: 'TIME'},
-            {value: 'TIMESTAMP', label: 'TIMESTAMP'}
-        ];
-
-        $scope.javaTypes = [
-            {value: 'boolean', label: 'boolean'},
-            {value: 'Boolean', label: 'Boolean'},
-            {value: 'byte', label: 'byte'},
-            {value: 'Byte', label: 'Byte'},
-            {value: 'short', label: 'short'},
-            {value: 'Short', label: 'Short'},
-            {value: 'int', label: 'int'},
-            {value: 'Integer', label: 'Integer'},
-            {value: 'long', label: 'long'},
-            {value: 'Long', label: 'Long'},
-            {value: 'float', label: 'float'},
-            {value: 'Float', label: 'Float'},
-            {value: 'double', label: 'double'},
-            {value: 'Double', label: 'Double'},
-            {value: 'BigDecimal', label: 'BigDecimal'},
-            {value: 'String', label: 'String'},
-            {value: 'Date', label: 'Date'},
-            {value: 'Time', label: 'Time'},
-            {value: 'Timestamp', label: 'Timestamp'}
-        ];
-
-        $scope.sortDirections = [
-            {value: 'ASC', label: 'ASC'},
-            {value: 'DESC', label: 'DESC'}
-        ];
-
-        $scope.data = {
-            curTableIdx: 0,
-            curFieldIdx: 0,
-            curKeyClass: '',
-            curValueClass: '',
-            curJavaName: '',
-            curJavaType: '',
-            tables: [
-                {schemaName: 'Schema1', use: true},
-                {
-                    schemaName: 'Schema1',
-                    use: true,
-                    tableName: 'Table1',
-                    keyClass: 'KeyClass1',
-                    valueClass: 'ValueClass1',
-                    fields: [
-                        {
-                            use: true,
-                            key: true,
-                            ak: true,
-                            dbName: 'name1',
-                            dbType: 'dbType1',
-                            javaName: 'javaName1',
-                            javaType: 'javaType1'
-                        },
-                        {
-                            use: true,
-                            key: false,
-                            ak: false,
-                            dbName: 'name2',
-                            dbType: 'dbType2',
-                            javaName: 'javaName2',
-                            javaType: 'javaType2'
-                        },
-                        {
-                            use: false,
-                            key: false,
-                            ak: false,
-                            dbName: 'name3',
-                            dbType: 'dbType3',
-                            javaName: 'javaName3',
-                            javaType: 'javaType3'
-                        }
-                    ]
-                },
-                {schemaName: 'Schema2 with very long name', use: false},
-                {
-                    schemaName: 'Schema2',
-                    use: false,
-                    tableName: 'Table2',
-                    keyClass: 'KeyClass2',
-                    valueClass: 'ValueClass2',
-                    fields: [
-                        {
-                            use: true,
-                            key: true,
-                            ak: true,
-                            dbName: 'name4',
-                            dbType: 'dbType4',
-                            javaName: 'javaName4',
-                            javaType: 'javaType4'
-                        },
-                        {
-                            use: true,
-                            key: false,
-                            ak: false,
-                            dbName: 'name5',
-                            dbType: 'dbType5',
-                            javaName: 'javaName5',
-                            javaType: 'javaType5'
-                        },
-                        {
-                            use: false,
-                            key: false,
-                            ak: false,
-                            dbName: 'name6',
-                            dbType: 'dbType6',
-                            javaName: 'javaName6',
-                            javaType: 'javaType6'
-                        }
-                    ]
-                },
-                {
-                    schemaName: 'Schema2',
-                    use: false,
-                    tableName: 'Table3',
-                    keyClass: 'KeyClass3',
-                    valueClass: 'ValueClass3',
-                    fields: [
-                        {
-                            use: true,
-                            key: true,
-                            ak: true,
-                            dbName: 'name7',
-                            dbType: 'dbType7',
-                            javaName: 'javaName7',
-                            javaType: 'javaType7'
-                        },
-                        {
-                            use: true,
-                            key: false,
-                            ak: false,
-                            dbName: 'name8',
-                            dbType: 'dbType8',
-                            javaName: 'javaName8',
-                            javaType: 'javaType8'
-                        },
-                        {
-                            use: false,
-                            key: false,
-                            ak: false,
-                            dbName: 'name9',
-                            dbType: 'dbType9',
-                            javaName: 'javaName9',
-                            javaType: 'javaType9'
-                        },
-                        {
-                            use: false,
-                            key: false,
-                            ak: false,
-                            dbName: 'name10',
-                            dbType: 'dbType10',
-                            javaName: 'javaName10',
-                            javaType: 'javaType10'
-                        },
-                        {
-                            use: false,
-                            key: false,
-                            ak: false,
-                            dbName: 'name11',
-                            dbType: 'dbType11',
-                            javaName: 'javaName11',
-                            javaType: 'javaType11'
-                        },
-                        {
-                            use: false,
-                            key: false,
-                            ak: false,
-                            dbName: 'name12',
-                            dbType: 'dbType12',
-                            javaName: 'javaName12',
-                            javaType: 'javaType12'
-                        }
-                    ]
-                }]
-        };
-
-        $scope.metadatas = [];
-
-        $http.get('/models/metadata.json')
-            .success(function (data) {
-                $scope.screenTip = data.screenTip;
-                $scope.templateTip = data.templateTip;
-                $scope.metadataManual = data.metadataManual;
-                $scope.metadataDb = data.metadataDb;
-            })
-            .error(function (errMsg) {
-                $common.showError(errMsg);
-            });
-
-        // When landing on the page, get metadatas and show them.
-        $http.post('metadata/list')
-            .success(function (data) {
-                $scope.spaces = data.spaces;
-                $scope.metadatas = data.metadatas;
-
-                var restoredItem = angular.fromJson(sessionStorage.metadataBackupItem);
-
-                if (restoredItem && restoredItem._id) {
-                    var idx = _.findIndex($scope.metadatas, function (metadata) {
-                        return metadata._id == restoredItem._id;
-                    });
-
-                    if (idx >= 0) {
-                        $scope.selectedItem = $scope.metadatas[idx];
-
-                        $scope.backupItem = restoredItem;
-                    }
-                    else
-                        sessionStorage.removeItem('metadataBackupItem');
-                }
-                else
-                    $scope.backupItem = restoredItem;
-
-                $scope.$watch('backupItem', function (val) {
-                    if (val)
-                        sessionStorage.metadataBackupItem = angular.toJson(val);
-                }, true);
-            })
-            .error(function (errMsg) {
-                $common.showError(errMsg);
-            });
-
-        $scope.selectItem = function (item) {
-            $table.tableReset();
-
-            $scope.selectedItem = item;
-            $scope.backupItem = angular.copy(item);
-        };
-
-        // Add new metadata.
-        $scope.createItem = function () {
-            $table.tableReset();
-
-            $scope.backupItem = angular.copy($scope.template);
-            $scope.backupItem.space = $scope.spaces[0]._id;
-        };
-
-        // Check cache type metadata logical consistency.
-        function validate(item) {
-            return true;
-        }
-
-        // Save cache type metadata into database.
-        function save(item) {
-            $http.post('metadata/save', item)
-                .success(function (_id) {
-                    $common.showInfo('Metadata "' + item.name + '" saved.');
-
-                    var idx = _.findIndex($scope.metadatas, function (metadata) {
-                        return metadata._id == _id;
-                    });
-
-                    if (idx >= 0)
-                        angular.extend($scope.metadatas[idx], item);
-                    else {
-                        item._id = _id;
-
-                        $scope.metadatas.push(item);
-                    }
-
-                    $scope.selectItem(item);
-
-                    $common.showInfo('Cache type metadata"' + item.name + '" saved.');
-                })
-                .error(function (errMsg) {
-                    $common.showError(errMsg);
-                });
-        }
-
-        // Save cache type metadata.
-        $scope.saveItem = function () {
-            $table.tableReset();
-
-            var item = $scope.backupItem;
-
-            if (validate(item))
-                save(item);
-        };
-
-        // Save cache type metadata 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);
-
-                    item._id = undefined;
-                    item.name = newName;
-
-                    save(item);
-                });
-        };
-
-        $scope.removeItem = function () {
-            $table.tableReset();
-
-            var selectedItem = $scope.selectedItem;
-
-            $confirm.show('Are you sure you want to remove cache type metadata: "' + selectedItem.name + '"?').then(
-                function () {
-                    var _id = selectedItem._id;
-
-                    $http.post('metadata/remove', {_id: _id})
-                        .success(function () {
-                            $common.showInfo('Cache type metadata has been removed: ' + selectedItem.name);
-
-                            var metadatas = $scope.metadatas;
-
-                            var idx = _.findIndex(metadatas, function (metadata) {
-                                return metadata._id == _id;
-                            });
-
-                            if (idx >= 0) {
-                                metadatas.splice(idx, 1);
-
-                                if (metadatas.length > 0)
-                                    $scope.selectItem(metadatas[0]);
-                                else {
-                                    $scope.selectedItem = undefined;
-                                    $scope.backupItem = undefined;
-                                }
-                            }
-                        })
-                        .error(function (errMsg) {
-                            $common.showError(errMsg);
-                        });
-                });
-        };
-
-        $scope.tableSimpleValid = function (item, field, name, index) {
-            var model = item[field.model];
-
-            if ($common.isDefined(model)) {
-                var idx = _.indexOf(model, name);
-
-                // Found itself.
-                if (index >= 0 && index == idx)
-                    return true;
-
-                // Found duplicate.
-                if (idx >= 0) {
-                    $common.showError('Field with such name already exists!');
-
-                    return false;
-                }
-            }
-
-            return true;
-        };
-
-        $scope.tablePairValid = function (item, field, name, clsName, index) {
-            var model = item[field.model];
-
-            if ($common.isDefined(model)) {
-                var idx = _.findIndex(model, function (pair) {
-                    return pair.name == name
-                });
-
-                // Found itself.
-                if (index >= 0 && index == idx)
-                    return true;
-
-                // Found duplicate.
-                if (idx >= 0) {
-                    $common.showError('Field with such name already exists!');
-
-                    return false;
-                }
-            }
-
-            return true;
-        };
-
-        $scope.tableDbFieldSaveVisible = function (dbName, dbType, javaName, javaType) {
-            return $common.isNonEmpty(dbName) && $common.isDefined(dbType) &&
-                $common.isNonEmpty(javaName) && $common.isDefined(javaType);
-        };
-
-        $scope.tableDbFieldSave = function (field, newDbName, newDbType, newJavaName, newJavaType, index) {
-            var item = $scope.backupItem;
-
-            var model = item[field.model];
-
-            var newItem = {dbName: newDbName, dbType: newDbType, javaName: newJavaName, javaType: newJavaType};
-
-            if ($common.isDefined(model)) {
-                var idx = _.findIndex(model, function (dbMeta) {
-                    return dbMeta.dbName == newDbName
-                });
-
-                // Found duplicate.
-                if (idx >= 0 && index != idx) {
-                    $common.showError('DB field with such name already exists!');
-
-                    return;
-                }
-
-                if (index < 0) {
-                    if (model)
-                        model.push(newItem);
-                    else
-                        item[field.model] = [newItem];
-                }
-                else {
-                    var dbField = model[index];
-
-                    dbField.dbName = newDbName;
-                    dbField.dbType = newDbType;
-                    dbField.javaName = newJavaName;
-                    dbField.javaType = newJavaType;
-                }
-            }
-            else
-                item[field.model] = [newItem];
-
-            $table.tableReset();
-        };
-
-        $scope.tableGroupSaveVisible = function (group) {
-            return $common.isNonEmpty(group);
-        };
-
-        function tableGroupValid(groupName, index) {
-            var groups = $scope.backupItem.groups;
-
-            if ($common.isDefined(groups)) {
-                var idx = _.findIndex(groups, function (group) {
-                    return group.name == groupName;
-                });
-
-                // Found itself.
-                if (index >= 0 && index == idx)
-                    return true;
-
-                // Found duplicate.
-                if (idx >= 0) {
-                    $common.showError('Group with such name already exists!');
-
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        $scope.tableGroupSave = function (groupName, index) {
-            if (tableGroupValid(groupName, index)) {
-                $table.tableReset();
-
-                var item = $scope.backupItem;
-
-                if (index < 0) {
-                    var newGroup = {name: groupName};
-
-                    if (item.groups)
-                        item.groups.push(newGroup);
-                    else
-                        item.groups = [newGroup];
-                }
-                else
-                    item.groups[index].name = groupName;
-            }
-        };
-
-        $scope.tableGroupNewItem = function (groupIndex) {
-            var groupName = $scope.backupItem.groups[groupIndex].name;
-
-            return $table.tableNewItem({model: groupName});
-        };
-
-        $scope.tableGroupNewItemActive = function (groupIndex) {
-            var groupName = $scope.backupItem.groups[groupIndex].name;
-
-            return $table.tableNewItemActive({model: groupName});
-        };
-
-        $scope.tableGroupItemEditing = function (groupIndex, index) {
-            var groups = $scope.backupItem.groups;
-
-            if (groups)
-                return $table.tableEditing({model: groups[groupIndex].name}, index);
-
-            return false;
-        };
-
-        $scope.tableGroupItemStartEdit = function (groupIndex, index) {
-            var groups = $scope.backupItem.groups;
-
-            $table.tableState(groups[groupIndex].name, index);
-
-            return groups[groupIndex].fields[index];
-        };
-
-        $scope.tableGroupItemSaveVisible = function (fieldName, className) {
-            return $common.isNonEmpty(fieldName) && $common.isNonEmpty(className);
-        };
-
-        function tableGroupItemValid(fieldName, groupIndex, index) {
-            var groupItems = $scope.backupItem.groups[groupIndex].fields;
-
-            if ($common.isDefined(groupItems)) {
-                var idx = _.findIndex(groupItems, function (groupItem) {
-                    return groupItem.name == fieldName;
-                });
-
-                // Found itself.
-                if (index >= 0 && index == idx)
-                    return true;
-
-                // Found duplicate.
-                if (idx >= 0) {
-                    $common.showError('Field with such name already exists in group!');
-
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        $scope.tableGroupItemSave = function (fieldName, className, direction, groupIndex, index) {
-            if (tableGroupItemValid(fieldName, groupIndex, index)) {
-                $table.tableReset();
-
-                var group = $scope.backupItem.groups[groupIndex];
-
-                if (index < 0) {
-                    var newGroupItem = {name: fieldName, className: className, direction: direction};
-
-                    if (group.fields)
-                        group.fields.push(newGroupItem);
-                    else
-                        group.fields = [newGroupItem];
-                }
-                else {
-                    var groupItem = group.fields[index];
-
-                    groupItem.name = fieldName;
-                    groupItem.className = className;
-                    groupItem.direction = direction;
-                }
-            }
-        };
-
-        $scope.tableRemoveGroupItem = function (group, index) {
-            $table.tableReset();
-
-            group.fields.splice(index, 1);
-        };
-
-        $scope.selectSchema = function (idx) {
-            var data = $scope.data;
-            var tables = data.tables;
-            var schemaName = tables[idx].schemaName;
-            var use = tables[idx].use;
-
-            for (var i = idx + 1; i < tables.length; i++) {
-                var item = tables[i];
-
-                if (item.schemaName == schemaName && item.tableName)
-                    item.use = use;
-                else
-                    break;
-            }
-
-            data.curTableIdx = -1;
-            data.curFieldIdx = -1;
-        };
-
-        $scope.selectTable = function (idx) {
-            var data = $scope.data;
-
-            data.curTableIdx = idx;
-            data.curFieldIdx = -1;
-
-            if (idx >= 0) {
-                var tbl = data.tables[idx];
-
-                data.curKeyClass = tbl.keyClass;
-                data.curValueClass = tbl.valueClass;
-            }
-        };
-
-        $scope.selectField = function (idx) {
-            var data = $scope.data;
-
-            data.curFieldIdx = idx;
-
-            if (idx >= 0) {
-                var fld = data.tables[data.curTableIdx].fields[idx];
-
-                data.curJavaName = fld.javaName;
-                data.curJavaType = fld.javaType;
-            }
-        };
-    }]
-);
\ No newline at end of file


[08/50] [abbrv] incubator-ignite git commit: IGNITE-843: WIP: tables.

Posted by an...@apache.org.
IGNITE-843: WIP: tables.


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

Branch: refs/heads/ignite-1121
Commit: 3ab9a914e38cebacb5a2203b7bcb93b7a576cda3
Parents: fffdbdb
Author: AKuznetsov <ak...@gridgain.com>
Authored: Tue Jul 21 00:26:04 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Tue Jul 21 00:26:04 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/metadata-controller.js   |  7 ++++-
 .../nodejs/public/stylesheets/style.less        | 30 ++++++++++++++------
 .../nodejs/views/includes/controls.jade         | 25 ++++++++--------
 3 files changed, 40 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/3ab9a914/modules/web-control-center/nodejs/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/metadata-controller.js b/modules/web-control-center/nodejs/controllers/metadata-controller.js
index 65229da..5f20fb2 100644
--- a/modules/web-control-center/nodejs/controllers/metadata-controller.js
+++ b/modules/web-control-center/nodejs/controllers/metadata-controller.js
@@ -311,7 +311,7 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
                     {name: "fld2", className: "String", direction: "DESC"}]
             },
                 {
-                    name: "index1",
+                    name: "index2",
                     fields: [
                         {name: "fld3", className: "Integer", direction: "ASC"},
                         {name: "fld4", className: "Data", direction: "DESC"}]
@@ -455,6 +455,11 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             $table.tableReset();
         };
 
+        $scope.tableRemoveGroupItem = function(group, index) {
+            console.log("group: " + group.name);
+            console.log("index: " + index);
+        };
+
         $scope.selectSchema = function (idx) {
             var data = $scope.data;
             var tables = data.tables;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/3ab9a914/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 80bbbdb..ca4d72f 100644
--- a/modules/web-control-center/nodejs/public/stylesheets/style.less
+++ b/modules/web-control-center/nodejs/public/stylesheets/style.less
@@ -143,7 +143,7 @@
 }
 
 .theme-line #category-columns ul li a {
-  padding: 4px 0;
+  padding: 5px 0;
   display: block;
   font-size: 16px;
 }
@@ -184,11 +184,11 @@
 
 .theme-line .main-content .nav-horizontal a:hover {
   color: #999;
-  border-bottom: 4px solid #ddd;
+  border-bottom: 5px solid #ddd;
 }
 
 .theme-line .main-content .nav-horizontal a.active {
-  border-bottom: 4px solid #888;
+  border-bottom: 5px solid #888;
 }
 
 .theme-line .navbar-nav, .theme-line .sidebar-nav {
@@ -279,7 +279,7 @@
 }
 
 .theme-line .suggest {
-  padding: 4px;
+  padding: 5px;
   display: inline-block;
   font-size: 12px;
 }
@@ -623,7 +623,7 @@ h1.ignite-logo {
 
   input[type="checkbox"] {
     line-height: 20px;
-    margin-right: 4px;
+    margin-right: 5px;
   }
 
   .checkbox label {
@@ -633,7 +633,7 @@ h1.ignite-logo {
 }
 
 button {
-  margin-right: 4px;
+  margin-right: 5px;
 }
 
 h1,
@@ -803,7 +803,7 @@ button .caret, .btn .caret {
 
   padding: 0;
 
-  border-radius: 4px;
+  border-radius: 5px;
   border: thin dotted lightgrey;
 }
 
@@ -1052,7 +1052,7 @@ a {
 
 .block-callout {
   background-color: @ignite-block-callout-background;
-  border-left-width: 4px;
+  border-left-width: 5px;
   border-left-style: solid;
   border-color: @ignite-block-callout-border;
 
@@ -1080,14 +1080,26 @@ a {
   }
 }
 
-.grid-cell {
+.grid-cell-1 {
+  flex-basis: 100%;
+}
+
+.grid-cell-2 {
   flex-basis: 50%;
 }
 
+.grid-cell-3 {
+  flex-basis: 33%;
+}
+
 .grid-cell-4 {
   flex-basis: 25%;
 }
 
+.grid-cell-fa {
+  flex-basis: 16px;
+}
+
 .grid-fixed-cell {
   flex-basis: 10px;
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/3ab9a914/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 d803e08..ce476d7 100644
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ b/modules/web-control-center/nodejs/views/includes/controls.jade
@@ -39,11 +39,11 @@ mixin btn-down(show, click)
 
 mixin table-pair-edit(keyModel, valModel, keyPlaceholder, valPlaceholder)
     .grid
-        .grid-cell
+        .grid-cell-2
             input.form-control(type='text' ng-model=keyModel placeholder=keyPlaceholder)
         div
             label &nbsp;/&nbsp;
-        .grid-cell
+        .grid-cell-2
             input.form-control(type='text' ng-model=valModel placeholder=valPlaceholder)
 
 mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
@@ -56,7 +56,7 @@ mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
             tr.col-sm-12(ng-repeat='item in #{tblMdl}')
                 td.col-sm-6
                     div(ng-show='!tableEditing(field, $index)')
-                        a(ng-click='curPair = tableStartEdit(backupItem, field, $index); curKey = curPair.#{keyFld}; curValue = curPair.#{valFld}') {{$index + 1}}) {{item.#{keyFld}}} / {{item.#{valFld}}}
+                        a.labelFormField(ng-click='curPair = tableStartEdit(backupItem, field, $index); curKey = curPair.#{keyFld}; curValue = curPair.#{valFld}') {{$index + 1}}) {{item.#{keyFld}}} / {{item.#{valFld}}}
                         +btn-remove('tableRemove(backupItem, field, $index)')
                     div(ng-show='tableEditing(field, $index)')
                         label.labelField {{$index + 1}})
@@ -120,11 +120,10 @@ mixin details-row
                     tr(ng-repeat='item in #{detailMdl} track by $index')
                         td
                             div(ng-show='!tableEditing(detail, $index)')
+                                a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, detail, $index)') {{$index + 1}}) {{item}}
                                 +btn-remove('tableRemove(backupItem, detail, $index)')
                                 +btn-down('detail.reordering && tableSimpleDownVisible(backupItem, detail, $index)', 'tableSimpleDown(backupItem, detail, $index)')
                                 +btn-up('detail.reordering && $index > 0', 'tableSimpleUp(backupItem, detail, $index)')
-                                .input-tip
-                                    a(ng-click='curValue = tableStartEdit(backupItem, detail, $index)') {{$index + 1}}) {{item}}
                             div(ng-show='tableEditing(detail, $index)')
                                 label.labelField {{$index + 1}})
                                 +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, detail, curValue, $index)')
@@ -227,7 +226,7 @@ mixin form-row-custom(lblClasses, fieldClasses)
                     tr.col-sm-12(ng-repeat='item in #{fieldMdl} track by $index')
                         td.col-sm-6
                             div(ng-show='!tableEditing(field, $index)')
-                                a(ng-click='curValue = tableStartEdit(backupItem, field, $index)') {{$index + 1}}) {{item | compact}}
+                                a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, field, $index)') {{$index + 1}}) {{item | compact}}
                                 +btn-remove('tableRemove(backupItem, field, $index)')
                                 +btn-down('field.reordering && tableSimpleDownVisible(backupItem, field, $index)', 'tableSimpleDown(backupItem, field, $index)')
                                 +btn-up('field.reordering && $index > 0', 'tableSimpleUp(backupItem, field, $index)')
@@ -255,7 +254,7 @@ mixin form-row-custom(lblClasses, fieldClasses)
                     tr.col-sm-12(ng-repeat='item in #{fieldMdl}')
                         td.col-sm-6
                             div(ng-show='!tableEditing(field, $index)')
-                                a(ng-click='curDbFldMeta = tableStartEdit(backupItem, field, $index); curDbName = curDbFldMeta.dbName; curDbType = curDbFldMeta.dbType; curJavaName = curDbFldMeta.javaName; curJavaType = curDbFldMeta.javaType') {{$index + 1}}) {{item.dbName}} / {{item.dbType}} / {{item.javaName}} / {{item.javaType}}
+                                a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, field, $index)') {{$index + 1}}) {{item | compact}}(ng-click='curDbFldMeta = tableStartEdit(backupItem, field, $index); curDbName = curDbFldMeta.dbName; curDbType = curDbFldMeta.dbType; curJavaName = curDbFldMeta.javaName; curJavaType = curDbFldMeta.javaType') {{$index + 1}}) {{item.dbName}} / {{item.dbType}} / {{item.javaName}} / {{item.javaType}}
                                 +btn-remove('tableRemove(backupItem, field, $index)')
                             div(ng-if='tableEditing(field, $index)')
                                 label.labelField {{$index + 1}})
@@ -274,13 +273,15 @@ mixin form-row-custom(lblClasses, fieldClasses)
                 button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
             table.links-edit.col-sm-12(st-table=fieldMdl ng-show='#{fieldMdl}.length > 0')
                 tbody
-                    tr.col-sm-12(ng-repeat='item in #{fieldMdl}')
+                    tr.col-sm-12(ng-repeat='group in #{fieldMdl}')
                         td.col-sm-6
                             div
-                                a(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{item.name}}
+                                a.labelFormField(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{group.name}}
                                 +btn-remove('tableRemove(backupItem, field, $index)')
-                                table
-                                    tr(ng-repeat='z in item.fields')
+                                table.links-edit.col-sm-12(st-table='group.fields' ng-show='group.fields.length > 0')
+                                    tr(ng-repeat='groupItem in group.fields')
                                         td
-                                            label {{$index + 1}}) {{z.name}} / {{z.className}} / {{z.direction}}
+                                            a.labelFormField('') {{$index + 1}}) {{groupItem.name}} / {{groupItem.className}} / {{groupItem.direction}}
+                                            +btn-remove('tableRemoveGroupItem(group, $index)')
+
 


[37/50] [abbrv] incubator-ignite git commit: # ignite-843 moved

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/models/clusters.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/models/clusters.json b/modules/web-control-center/src/main/js/controllers/models/clusters.json
new file mode 100644
index 0000000..d6d7d23
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/models/clusters.json
@@ -0,0 +1,907 @@
+{
+  "screenTip": {
+    "workflowTitle": "Use Clusters view to:",
+    "workflowContent": [
+      "<ul>",
+      "  <li>Configure clusters.</li>",
+      "  <li>Associate clusters with caches.</li>",
+      "</ul>"
+    ],
+    "whatsNextTitle": "What's next:",
+    "whatsNextContent": [
+      "<ul>",
+      "  <li>Configure cache type metadata.</li>",
+      "  <li>Configure caches.</li>",
+      "  <li>Generate XML and java code on Summary view.</li>",
+      "</ul>"
+    ]
+  },
+  "templateTip": [
+    "Use following template to add a new cluster:",
+    "<ul>",
+    "  <li>multicast - cluster with multicast discovery.</li>",
+    "  <li>local - cluster with static ips discovery and pre-configured list of IP addresses.</li>",
+    "</ul>"
+  ],
+  "general": [
+    {
+      "label": "Name",
+      "type": "text",
+      "model": "name",
+      "required": true,
+      "placeholder": "Input name"
+    },
+    {
+      "label": "Caches",
+      "type": "dropdown-multiple",
+      "model": "caches",
+      "placeholder": "Choose caches",
+      "items": "caches",
+      "tip": [
+        "Select caches to start in cluster or add a new cache."
+      ],
+      "addLink": {
+        "label": "Add cache(s)",
+        "ref": "/configuration/caches"
+      }
+    },
+    {
+      "label": "Discovery",
+      "type": "dropdown-details",
+      "path": "discovery",
+      "model": "kind",
+      "required": true,
+      "placeholder": "Choose discovery",
+      "items": "discoveries",
+      "tip": [
+        "Discovery allows to discover remote nodes in grid."
+      ],
+      "details": {
+        "Vm": {
+          "expanded": true,
+          "fields": [
+            {
+              "type": "table-simple",
+              "path": "discovery.Vm",
+              "model": "addresses",
+              "editIdx": -1,
+              "reordering": true,
+              "ipaddress": true,
+              "placeholder": "IP address:port",
+              "tip": [
+                "Addresses may be represented as follows:",
+                "<ul>",
+                "  <li>IP address (e.g. 127.0.0.1, 9.9.9.9, etc);</li>",
+                "  <li>IP address and port (e.g. 127.0.0.1:47500, 9.9.9.9:47501, etc);</li>",
+                "  <li>IP address and port range (e.g. 127.0.0.1:47500..47510, 9.9.9.9:47501..47504, etc);</li>",
+                "  <li>Hostname (e.g. host1.com, host2, etc);</li>",
+                "  <li>Hostname and port (e.g. host1.com:47500, host2:47502, etc).</li>",
+                "  <li>Hostname and port range (e.g. host1.com:47500..47510, host2:47502..47508, etc).</li>",
+                "</ul>",
+                "If port is 0 or not provided then default port will be used (depends on discovery SPI configuration).",
+                "If port range is provided (e.g. host:port1..port2) the following should be considered:",
+                "<ul>",
+                "  <li>port1 < port2 should be true;</li>",
+                "  <li>Both port1 and port2 should be greater than 0.</li>",
+                "</ul>"
+              ]
+            }
+          ]
+        },
+        "Multicast": {
+          "expanded": false,
+          "fields": [
+            {
+              "label": "IP address",
+              "type": "text",
+              "path": "discovery.Multicast",
+              "model": "multicastGroup",
+              "placeholder": "228.1.2.4",
+              "tip": [
+                "IP address of multicast group."
+              ]
+            },
+            {
+              "label": "Port number",
+              "type": "number",
+              "path": "discovery.Multicast",
+              "model": "multicastPort",
+              "max": 65535,
+              "placeholder": 47400,
+              "tip": [
+                "Port number which multicast messages are sent to."
+              ]
+            },
+            {
+              "label": "Waits for reply",
+              "type": "number",
+              "path": "discovery.Multicast",
+              "model": "responseWaitTime",
+              "placeholder": 500,
+              "tip": [
+                "Time in milliseconds IP finder waits for reply to multicast address request."
+              ]
+            },
+            {
+              "label": "Attempts count",
+              "type": "number",
+              "path": "discovery.Multicast",
+              "model": "addressRequestAttempts",
+              "placeholder": 2,
+              "tip": [
+                "Number of attempts to send multicast address request.",
+                "IP finder re-sends request only in case if no reply for previous request is received."
+              ]
+            },
+            {
+              "label": "Local address",
+              "type": "text",
+              "path": "discovery.Multicast",
+              "model": "localAddress",
+              "tip": [
+                "Local host address used by this IP finder.",
+                "If provided address is non-loopback then multicast socket is bound to this interface.",
+                "If local address is not set or is any local address then IP finder creates multicast sockets for all found non-loopback addresses."
+              ]
+            }
+          ]
+        },
+        "S3": {
+          "expanded": true,
+          "fields": [
+            {
+              "label": "Bucket name",
+              "type": "text",
+              "required": true,
+              "path": "discovery.S3",
+              "model": "bucketName",
+              "placeholder": "",
+              "tip": [
+                "Bucket name for IP finder."
+              ]
+            },
+            {
+              "label": "Note, AWS credentials will be generated as stubs.",
+              "type": "label"
+            }
+          ]
+        },
+        "Cloud": {
+          "expanded": true,
+          "fields": [
+            {
+              "label": "Credential",
+              "type": "text",
+              "path": "discovery.Cloud",
+              "model": "credential",
+              "placeholder": "",
+              "tip": [
+                "Credential that is used during authentication on the cloud.",
+                "Depending on a cloud platform it can be a password or access key."
+              ]
+            },
+            {
+              "label": "Path to credential",
+              "type": "text",
+              "path": "discovery.Cloud",
+              "model": "credentialPath",
+              "placeholder": "",
+              "tip": [
+                "Path to a credential that is used during authentication on the cloud.",
+                "Access key or private key should be stored in a plain or PEM file without a passphrase."
+              ]
+            },
+            {
+              "label": "Identity",
+              "type": "text",
+              "required": true,
+              "path": "discovery.Cloud",
+              "model": "identity",
+              "placeholder": "",
+              "tip": [
+                "Identity that is used as a user name during a connection to the cloud.",
+                "Depending on a cloud platform it can be an email address, user name, etc."
+              ]
+            },
+            {
+              "label": "Provider",
+              "type": "text",
+              "required": true,
+              "path": "discovery.Cloud",
+              "model": "provider",
+              "placeholder": "",
+              "tip": [
+                "Cloud provider to use."
+              ]
+            },
+            {
+              "label": "Regions",
+              "type": "table-simple",
+              "path": "discovery.Cloud",
+              "model": "regions",
+              "editIdx": -1,
+              "placeholder": "",
+              "tableTip": [
+                "List of regions where VMs are located.",
+                "If the regions are not set then every region, that a cloud provider has, will be investigated. This could lead to significant performance degradation.",
+                "Note, that some cloud providers, like Google Compute Engine, doesn't have a notion of a region. For such providers a call to this method is redundant."
+              ],
+              "tip": [
+                "Region where VMs are located."
+              ]
+            },
+            {
+              "label": "Zones",
+              "type": "table-simple",
+              "path": "discovery.Cloud",
+              "model": "zones",
+              "editIdx": -1,
+              "placeholder": "",
+              "tableTip": [
+                "List of zones where VMs are located.",
+                "If the zones are not set then every zone from regions, set by {@link #setRegions(Collection)}}, will be taken into account.",
+                "Note, that some cloud providers, like Rackspace, doesn't have a notion of a zone. For such providers a call to this method is redundant."
+              ],
+              "tip": [
+                "Zone where VMs are located."
+              ]
+            }
+          ]
+        },
+        "GoogleStorage": {
+          "expanded": true,
+          "fields": [
+            {
+              "label": "Project name",
+              "type": "text",
+              "required": true,
+              "path": "discovery.GoogleStorage",
+              "model": "projectName",
+              "placeholder": "",
+              "tip": [
+                "Google Cloud Platforms project name.",
+                "Usually this is an auto generated project number (ex. 208709979073) that can be found in 'Overview' section of Google Developer Console."
+              ]
+            },
+            {
+              "label": "Bucket name",
+              "type": "text",
+              "required": true,
+              "path": "discovery.GoogleStorage",
+              "model": "bucketName",
+              "placeholder": "",
+              "tip": [
+                "Google Cloud Storage bucket name.",
+                "If the bucket doesn't exist Ignite will automatically create it.",
+                "However the name must be unique across whole Google Cloud Storage and Service Account Id must be authorized to perform this operation."
+              ]
+            },
+            {
+              "label": "Private key path",
+              "type": "text",
+              "required": true,
+              "path": "discovery.GoogleStorage",
+              "model": "serviceAccountP12FilePath",
+              "placeholder": "",
+              "tip": [
+                "Full path to the private key in PKCS12 format of the Service Account."
+              ]
+            },
+            {
+              "label": "Account id",
+              "type": "text",
+              "required": true,
+              "path": "discovery.GoogleStorage",
+              "model": "accountId",
+              "placeholder": "",
+              "tip": [
+                "Service account ID (typically an e-mail address)."
+              ]
+            }
+          ]
+        },
+        "Jdbc": {
+          "expanded": true,
+          "fields": [
+            {
+              "label": "DB schema should be initialized by Ignite",
+              "type": "check",
+              "path": "discovery.Jdbc",
+              "model": "initSchema",
+              "tip": [
+                "Flag indicating whether DB schema should be initialized by Ignite or was explicitly created by user."
+              ]
+            }
+          ]
+        },
+        "SharedFs": {
+          "expanded": false,
+          "fields": [
+            {
+              "label": "File path",
+              "type": "text",
+              "path": "discovery.SharedFs",
+              "model": "path",
+              "placeholder": "disco/tcp"
+            }
+          ]
+        }
+      }
+    }
+  ],
+  "advanced": [
+    {
+      "label": "Atomics configuration",
+      "tip": [
+        "Configuration for atomic data structures.",
+        "Atomics are distributed across the cluster, essentially enabling performing atomic operations (such as increment-and-get or compare-and-set) with the same globally-visible value."
+      ],
+      "fields": [
+        {
+          "label": "Backups",
+          "type": "number",
+          "path": "atomicConfiguration",
+          "model": "backups",
+          "placeholder": 0,
+          "tip": [
+            "Number of backup nodes."
+          ]
+        },
+        {
+          "label": "Cache mode",
+          "type": "dropdown",
+          "path": "atomicConfiguration",
+          "model": "cacheMode",
+          "placeholder": "PARTITIONED",
+          "items": "cacheModes",
+          "tip": [
+            "Cache modes:",
+            "<ul>",
+            "  <li>Partitioned - in this mode the overall key set will be divided into partitions and all partitions will be split equally between participating nodes.</li>",
+            "  <li>Replicated - in this mode all the keys are distributed to all participating nodes.</li>",
+            "  <li>Local - in this mode caches residing on different grid nodes will not know about each other.</li>",
+            "</ul>"
+          ]
+        },
+        {
+          "label": "Sequence reserve",
+          "type": "number",
+          "path": "atomicConfiguration",
+          "model": "atomicSequenceReserveSize",
+          "placeholder": 1000,
+          "tip": [
+            "Default number of sequence values reserved for IgniteAtomicSequence instances.",
+            "After a certain number has been reserved, consequent increments of sequence will happen locally, without communication with other nodes, until the next reservation has to be made."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Communication",
+      "tip": [
+        "Cluster communication network properties."
+      ],
+      "fields": [
+        {
+          "label": "Timeout",
+          "type": "number",
+          "model": "networkTimeout",
+          "placeholder": 5000,
+          "tip": [
+            "Maximum timeout in milliseconds for network requests."
+          ]
+        },
+        {
+          "label": "Send retry delay",
+          "type": "number",
+          "model": "networkSendRetryDelay",
+          "placeholder": 1000,
+          "tip": [
+            "Interval in milliseconds between message send retries."
+          ]
+        },
+        {
+          "label": "Send retry count",
+          "type": "number",
+          "model": "networkSendRetryCount",
+          "placeholder": 3,
+          "tip": [
+            "Message send retries count."
+          ]
+        },
+        {
+          "label": "Segment check frequency",
+          "type": "number",
+          "model": "segmentCheckFrequency",
+          "placeholder": 10000,
+          "tip": [
+            "Network segment check frequency in milliseconds.",
+            "If 0, periodic segment check is disabled and segment is checked only on topology changes (if segmentation resolvers are configured)."
+          ]
+        },
+        {
+          "label": "Wait for segment on start",
+          "type": "check",
+          "model": "waitForSegmentOnStart",
+          "tip": [
+            "Wait for segment on start flag.",
+            "<ul>",
+            "  <li>If enabled, node should wait for correct segment on start.</li>",
+            "  <li>If node detects that segment is incorrect on startup and enabled, node waits until segment becomes correct.</li>",
+            "  <li>If segment is incorrect on startup and disabled, exception is thrown.</li>",
+            "</ul>"
+          ]
+        },
+        {
+          "label": "Discovery startup delay",
+          "type": "number",
+          "model": "discoveryStartupDelay",
+          "placeholder": 600000,
+          "tip": [
+            "This value is used to expire messages from waiting list whenever node discovery discrepancies happen."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Deployment",
+      "tip": [
+        "Task and resources deployment in cluster."
+      ],
+      "fields": [
+        {
+          "label": "Mode",
+          "type": "dropdown",
+          "model": "deploymentMode",
+          "placeholder": "SHARED",
+          "items": "deploymentModes",
+          "tip": [
+            "Task classes and resources sharing mode."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Events",
+      "tip": [
+        " Grid events are used for notification about what happens within the grid."
+      ],
+      "fields": [
+        {
+          "label": "Include type",
+          "type": "dropdown-multiple",
+          "model": "includeEventTypes",
+          "placeholder": "Choose recorded event types",
+          "items": "events",
+          "tip": [
+            "Array of event types, which will be recorded by GridEventStorageManager#record(Event).",
+            "Note, that either the include event types or the exclude event types can be established."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Marshaller",
+      "tip": [
+        "Marshaller allows to marshal or unmarshal objects in grid.",
+        "It provides serialization/deserialization mechanism for all instances that are sent across networks or are otherwise serialized."
+      ],
+      "fields": [
+        {
+          "label": "Marshaller",
+          "type": "dropdown-details",
+          "path": "marshaller",
+          "model": "kind",
+          "placeholder": "Choose marshaller",
+          "items": "marshallers",
+          "tip": [
+            "Instance of marshaller to use in grid. If not provided, OptimizedMarshaller will be used on Java HotSpot VM, and JdkMarshaller will be used on other VMs."
+          ],
+          "details": {
+            "OptimizedMarshaller": {
+              "expanded": false,
+              "fields": [
+                {
+                  "label": "Streams pool size",
+                  "type": "number",
+                  "path": "marshaller.OptimizedMarshaller",
+                  "model": "poolSize",
+                  "placeholder": 0,
+                  "tip": [
+                    "Specifies size of cached object streams used by marshaller.",
+                    "Object streams are cached for performance reason to avoid costly recreation for every serialization routine.",
+                    "If 0 (default), pool is not used and each thread has its own cached object stream which it keeps reusing.",
+                    "Since each stream has an internal buffer, creating a stream for each thread can lead to high memory consumption if many large messages are marshalled or unmarshalled concurrently.",
+                    "Consider using pool in this case. This will limit number of streams that can be created and, therefore, decrease memory consumption.",
+                    "NOTE: Using streams pool can decrease performance since streams will be shared between different threads which will lead to more frequent context switching."
+                  ]
+                },
+                {
+                  "label": "Require serializable",
+                  "type": "check",
+                  "path": "marshaller.OptimizedMarshaller",
+                  "model": "requireSerializable",
+                  "tip": [
+                    "Whether marshaller should require Serializable interface or not."
+                  ]
+                }
+              ]
+            }
+          }
+        },
+        {
+          "label": "Marshal local jobs",
+          "type": "check",
+          "model": "marshalLocalJobs",
+          "placeholder": "false",
+          "tip": [
+            "If this flag is enabled, jobs mapped to local node will be marshalled as if it was remote node."
+          ]
+        },
+        {
+          "label": "Keep alive time",
+          "type": "number",
+          "model": "marshallerCacheKeepAliveTime",
+          "placeholder": 10000,
+          "tip": [
+            "Keep alive time of thread pool that is in charge of processing marshaller messages."
+          ]
+        },
+        {
+          "label": "Pool size",
+          "type": "number",
+          "model": "marshallerCacheThreadPoolSize",
+          "placeholder": "max(8, availableProcessors) * 2",
+          "tip": [
+            "Default size of thread pool that is in charge of processing marshaller messages."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Metrics",
+      "tip": [
+        "Cluster runtime metrics settings."
+      ],
+      "fields": [
+        {
+          "label": "Elapsed time",
+          "type": "number",
+          "model": "metricsExpireTime",
+          "placeholder": "Long.MAX_VALUE",
+          "min": 1,
+          "tip": [
+            "Time in milliseconds after which a certain metric value is considered expired."
+          ]
+        },
+        {
+          "label": "History size",
+          "type": "number",
+          "model": "metricsHistorySize",
+          "placeholder": 10000,
+          "min": 1,
+          "tip": [
+            "Number of metrics kept in history to compute totals and averages."
+          ]
+        },
+        {
+          "label": "Log frequency",
+          "type": "number",
+          "model": "metricsLogFrequency",
+          "placeholder": 60000,
+          "tip": [
+            "Frequency of metrics log print out. To disable set to 0"
+          ]
+        },
+        {
+          "label": "Update frequency",
+          "type": "number",
+          "model": "metricsUpdateFrequency",
+          "placeholder": 60000,
+          "tip": [
+            "Job metrics update frequency in milliseconds.",
+            "<ul>",
+            "  <li>If set to -1 job metrics are never updated.</li>",
+            "  <li>If set to 0 job metrics are updated on each job start and finish.</li>",
+            "  <li>Positive value defines the actual update frequency.</li>",
+            "</ul>"
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Peer Class Loading",
+      "tip": [
+        "Cluster peer class loading settings."
+      ],
+      "fields": [
+        {
+          "label": "Enable peer class loading",
+          "type": "check",
+          "model": "peerClassLoadingEnabled",
+          "tip": [
+            "Enables/disables peer class loading."
+          ]
+        },
+        {
+          "label": "Local class path exclude",
+          "type": "text",
+          "model": "peerClassLoadingLocalClassPathExclude",
+          "placeholder": "[]",
+          "tip": [
+            "List of packages separated by comma from the system classpath that need to be peer-to-peer loaded from task originating node.",
+            "'*' is supported at the end of the package name which means that all sub-packages and their classes are included like in Java package import clause."
+          ]
+        },
+        {
+          "label": "Missed resources cache size",
+          "type": "number",
+          "model": "peerClassLoadingMissedResourcesCacheSize",
+          "placeholder": 100,
+          "tip": [
+            "If size greater than 0, missed resources will be cached and next resource request ignored.",
+            "If size is 0, then request for the resource will be sent to the remote node every time this resource is requested."
+          ]
+        },
+        {
+          "label": "Pool size",
+          "type": "number",
+          "model": "peerClassLoadingThreadPoolSize",
+          "placeholder": "availableProcessors",
+          "tip": [
+            "Thread pool size to use for peer class loading."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Swap",
+      "tip": [
+        "Settings for overflow data to disk if it cannot fit in memory."
+      ],
+      "fields": [
+        {
+          "label": "Swap space SPI",
+          "type": "dropdown-details",
+          "path": "swapSpaceSpi",
+          "model": "kind",
+          "items": "swapSpaceSpis",
+          "placeholder": "Choose swap SPI",
+          "tip": [
+            "Provides a mechanism in grid for storing data on disk.",
+            "Ignite cache uses swap space to overflow data to disk if it cannot fit in memory."
+          ],
+          "details": {
+            "FileSwapSpaceSpi": {
+              "fields": [
+                {
+                  "label": "Base directory",
+                  "type": "text",
+                  "path": "swapSpaceSpi.FileSwapSpaceSpi",
+                  "model": "baseDirectory",
+                  "placeholder": "swapspace",
+                  "tip": [
+                    "Base directory where to write files."
+                  ]
+                },
+                {
+                  "label": "Read stripe size",
+                  "type": "number",
+                  "path": "swapSpaceSpi.FileSwapSpaceSpi",
+                  "model": "readStripesNumber",
+                  "placeholder": "available CPU cores",
+                  "tip": [
+                    "Read stripe size defines number of file channels to be used concurrently."
+                  ]
+                },
+                {
+                  "label": "Maximum sparsity",
+                  "type": "number",
+                  "path": "swapSpaceSpi.FileSwapSpaceSpi",
+                  "model": "maximumSparsity",
+                  "placeholder": 0.5,
+                  "tip": [
+                    "This property defines maximum acceptable wasted file space to whole file size ratio.",
+                    "When this ratio becomes higher than specified number compacting thread starts working."
+                  ]
+                },
+                {
+                  "label": "Max write queue size",
+                  "type": "number",
+                  "path": "swapSpaceSpi.FileSwapSpaceSpi",
+                  "model": "maxWriteQueueSize",
+                  "placeholder": "1024 * 1024",
+                  "tip": [
+                    "Max write queue size in bytes.",
+                    "If there are more values are waiting for being written to disk then specified size, SPI will block on store operation."
+                  ]
+                },
+                {
+                  "label": "Write buffer size",
+                  "type": "number",
+                  "path": "swapSpaceSpi.FileSwapSpaceSpi",
+                  "model": "writeBufferSize",
+                  "placeholder": "Available CPU cores",
+                  "tip": [
+                    "Write buffer size in bytes.",
+                    "Write to disk occurs only when this buffer is full."
+                  ]
+                }
+              ]
+            }
+          }
+        }
+      ]
+    },
+    {
+      "label": "Time configuration",
+      "tip": [
+        "Time settings for CLOCK write ordering mode."
+      ],
+      "fields": [
+        {
+          "label": "Samples size",
+          "type": "number",
+          "model": "clockSyncSamples",
+          "placeholder": 8,
+          "tip": [
+            "Number of samples used to synchronize clocks between different nodes.",
+            "Clock synchronization is used for cache version assignment in CLOCK order mode."
+          ]
+        },
+        {
+          "label": "Frequency",
+          "type": "number",
+          "model": "clockSyncFrequency",
+          "placeholder": 120000,
+          "tip": [
+            "Frequency at which clock is synchronized between nodes, in milliseconds.",
+            "Clock synchronization is used for cache version assignment in CLOCK order mode."
+          ]
+        },
+        {
+          "label": "Port base",
+          "type": "number",
+          "model": "timeServerPortBase",
+          "max": 65535,
+          "placeholder": 31100,
+          "tip": [
+            "Time server provides clock synchronization between nodes.",
+            "Base UPD port number for grid time server. Time server will be started on one of free ports in range."
+          ]
+        },
+        {
+          "label": "Port range",
+          "type": "number",
+          "model": "timeServerPortRange",
+          "placeholder": 100,
+          "tip": [
+            "Time server port range."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Thread pools size",
+      "tip": [
+        "Settings for node thread pools."
+      ],
+      "fields": [
+        {
+          "label": "Public",
+          "type": "number",
+          "model": "publicThreadPoolSize",
+          "placeholder": "max(8, availableProcessors) * 2",
+          "tip": [
+            "Thread pool that is in charge of processing ComputeJob, GridJobs and user messages sent to node."
+          ]
+        },
+        {
+          "label": "System",
+          "type": "number",
+          "model": "systemThreadPoolSize",
+          "placeholder": "max(8, availableProcessors) * 2",
+          "tip": [
+            "Thread pool that is in charge of processing internal system messages."
+          ]
+        },
+        {
+          "label": "Management",
+          "type": "number",
+          "model": "managementThreadPoolSize",
+          "placeholder": 4,
+          "tip": [
+            "Thread pool that is in charge of processing internal and Visor ComputeJob, GridJobs."
+          ]
+        },
+        {
+          "label": "IGFS",
+          "type": "number",
+          "model": "igfsThreadPoolSize",
+          "placeholder": "availableProcessors",
+          "tip": [
+            "Thread pool that is in charge of processing outgoing IGFS messages."
+          ]
+        }
+      ]
+    },
+    {
+      "label": "Transactions",
+      "tip": [
+        "Settings for transactions."
+      ],
+      "fields": [
+        {
+          "label": "Concurrency",
+          "type": "dropdown",
+          "path": "transactionConfiguration",
+          "model": "defaultTxConcurrency",
+          "placeholder": "PESSIMISTIC",
+          "items": "transactionConcurrency",
+          "tip": [
+            "Cache transaction concurrency to use when one is not explicitly specified."
+          ]
+        },
+        {
+          "label": "Isolation",
+          "type": "dropdown",
+          "path": "transactionConfiguration",
+          "model": "transactionIsolation",
+          "placeholder": "REPEATABLE_READ",
+          "items": "transactionIsolation",
+          "tip": [
+            "Default transaction isolation."
+          ]
+        },
+        {
+          "label": "Default timeout",
+          "type": "number",
+          "path": "transactionConfiguration",
+          "model": "defaultTxTimeout",
+          "placeholder": 0,
+          "tip": [
+            "Default transaction timeout."
+          ]
+        },
+        {
+          "label": "Pessimistic log cleanup delay",
+          "type": "number",
+          "path": "transactionConfiguration",
+          "model": "pessimisticTxLogLinger",
+          "placeholder": 10000,
+          "tip": [
+            "Delay, in milliseconds, after which pessimistic recovery entries will be cleaned up for failed node."
+          ]
+        },
+        {
+          "label": "Pessimistic log size",
+          "type": "number",
+          "path": "transactionConfiguration",
+          "model": "pessimisticTxLogSize",
+          "placeholder": 0,
+          "tip": [
+            "Size of pessimistic transactions log stored on node in order to recover transaction commit if originating node has left grid before it has sent all messages to transaction nodes."
+          ]
+        },
+        {
+          "label": "Manager lookup",
+          "type": "text",
+          "model": "txManagerLookupClassName",
+          "tip": [
+            "Class name of transaction manager finder for integration for JEE app servers."
+          ]
+        },
+        {
+          "label": "Enable serializable cache transactions",
+          "type": "check",
+          "path": "transactionConfiguration",
+          "model": "txSerializableEnabled",
+          "tip": [
+            "Flag to enable/disable isolation level for cache transactions.",
+            "Serializable level does carry certain overhead and if not used, should be disabled."
+          ]
+        }
+      ]
+    }
+  ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/models/metadata.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/models/metadata.json b/modules/web-control-center/src/main/js/controllers/models/metadata.json
new file mode 100644
index 0000000..3248f7a
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/models/metadata.json
@@ -0,0 +1,230 @@
+{
+  "screenTip": {
+    "workflowTitle": "Use Cache Type Metadata view to:",
+    "workflowContent": [
+      "<ul>",
+      "  <li>Manually configure metadata for queries and/or store.</li>",
+      "  <li>Configure metadata from database tables metadata.</li>",
+      "</ul>"
+    ],
+    "whatsNextTitle": "What's next:",
+    "whatsNextContent": [
+      "<ul>",
+      "  <li>Configure clusters.</li>",
+      "  <li>Associate caches with metadata.</li>",
+      "  <li>Generate XML and java code on Summary view.</li>",
+      "</ul>"
+    ]
+  },
+  "templateTip": [
+    "Use following template for metadata:",
+    "<ul>",
+    "  <li>query - Create cache type metadata to use with queries only.</li>",
+    "  <li>store - Create cache type metadata to use with JDBC POJO store only.</li>",
+    "  <li>both - Create cache type metadata to use with query and store.</li>",
+    "</ul>"
+  ],
+  "metadataManual": [
+    {
+      "label": "Name",
+      "type": "text",
+      "model": "name",
+      "required": true,
+      "placeholder": "Input name"
+    },
+    {
+      "label": "Metadata for",
+      "type": "dropdown",
+      "model": "kind",
+      "items": "kinds",
+      "tip": [
+        "Use following template for metadata:",
+        "<ul>",
+        "  <li>query - Create cache type metadata to use with queries only.</li>",
+        "  <li>store - Create cache type metadata to use with JDBC POJO store only.</li>",
+        "  <li>both - Create cache type metadata to use with query and store.</li>",
+        "</ul>"
+      ]
+    },
+    {
+      "label": "Database schema",
+      "type": "text",
+      "model": "databaseSchema",
+      "hide": "backupItem.kind == 'query'",
+      "placeholder": "Input DB schema name",
+      "tip": [
+        "Schema name in database."
+      ]
+    },
+    {
+      "label": "Database table",
+      "type": "text",
+      "model": "databaseTable",
+      "hide": "backupItem.kind == 'query'",
+      "placeholder": "Input DB table name",
+      "tip": [
+        "Table name in database."
+      ]
+    },
+    {
+      "label": "Key type",
+      "type": "text",
+      "model": "keyType",
+      "required": true,
+      "placeholder": "Full class name for Key",
+      "tip": [
+        "Key class used to store key in cache."
+      ]
+    },
+    {
+      "label": "Value type",
+      "type": "text",
+      "model": "valueType",
+      "required": true,
+      "placeholder": "Full class name for Value",
+      "tip": [
+        "Value class used to store value in cache."
+      ]
+    },
+    {
+      "label": "Key fields",
+      "type": "dbFields",
+      "model": "keyFields",
+      "keyName": "name",
+      "valueName": "className",
+      "hide": "backupItem.kind == 'query'",
+      "tip": [
+        "Collection of key fields descriptions for CacheJdbcPojoStore."
+      ]
+    },
+    {
+      "label": "Value fields",
+      "type": "dbFields",
+      "model": "valueFields",
+      "keyName": "name",
+      "valueName": "className",
+      "hide": "backupItem.kind == 'query'",
+      "tip": [
+        "Collection of value fields descriptions for CacheJdbcPojoStore.."
+      ]
+    },
+    {
+      "label": "Query fields",
+      "type": "queryFields",
+      "model": "queryFields",
+      "keyName": "name",
+      "valueName": "className",
+      "hide": "backupItem.kind != 'query'",
+      "tip": [
+        "Collection of name-to-type mappings to be queried, in addition to indexed fields."
+      ]
+    },
+    {
+      "label": "Ascending fields",
+      "type": "queryFields",
+      "model": "ascendingFields",
+      "keyName": "name",
+      "valueName": "className",
+      "hide": "backupItem.kind != 'query'",
+      "tip": [
+        "Collection of name-to-type mappings to index in ascending order."
+      ]
+    },
+    {
+      "label": "Descending fields",
+      "type": "queryFields",
+      "model": "descendingFields",
+      "keyName": "name",
+      "valueName": "className",
+      "hide": "backupItem.kind != 'query'",
+      "tip": [
+        "Collection of name-to-type mappings to index in descending order."
+      ]
+    },
+    {
+      "label": "Text fields",
+      "type": "table-simple",
+      "model": "textFields",
+      "hide": "backupItem.kind != 'query'",
+      "placeholder": "Field name",
+      "tableTip": [
+        "Fields to index as text."
+      ],
+      "tip": [
+        "Field to index as text."
+      ]
+    },
+    {
+      "label": "Groups",
+      "type": "queryGroups",
+      "model": "groups",
+      "hide": "backupItem.kind != 'query'",
+      "tip": [
+        "Collection of group indexes."
+      ]
+    }
+  ],
+  "metadataDb": [
+    {
+      "label": "Name",
+      "type": "text",
+      "model": "name"
+    },
+    {
+      "label": "Database type",
+      "type": "dropdown",
+      "model": "dbType",
+      "placeholder": "Choose database",
+      "items": "databases",
+      "tip": [
+        "Select database type to connect for loading tables metadata."
+      ]
+    },
+    {
+      "label": "Database name",
+      "type": "text",
+      "model": "dbName",
+      "tip": [
+        "Database name to connect for loading tables metadata."
+      ]
+    },
+    {
+      "label": "Host",
+      "type": "text",
+      "model": "host",
+      "placeholder": "IP address or host",
+      "tip": [
+        "IP address or host name where database server deployed."
+      ]
+    },
+    {
+      "label": "Port",
+      "type": "number",
+      "model": "port",
+      "max": 65535,
+      "placeholder": "",
+      "tip": [
+        "Port number for connecting to database."
+      ]
+    },
+    {
+      "label": "User",
+      "type": "text",
+      "model": "user",
+      "placeholder": "",
+      "tip": [
+        "User name for connecting to database."
+      ]
+    },
+    {
+      "label": "Password",
+      "type": "password",
+      "model": "password",
+      "placeholder": "",
+      "tip": [
+        "Password for connecting to database.",
+        "Note, password would not be saved."
+      ]
+    }
+  ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/models/summary.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/models/summary.json b/modules/web-control-center/src/main/js/controllers/models/summary.json
new file mode 100644
index 0000000..056291c
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/models/summary.json
@@ -0,0 +1,163 @@
+{
+  "screenTip": {
+    "workflowTitle": "Use Summary view to:",
+    "workflowContent": [
+      "<ul>",
+      "  <li>See XML and java code for server nodes configurations.</li>",
+      "  <li>See XML and java code for client nodes configurations.</li>",
+      "</ul>"
+    ],
+    "whatsNextTitle": "What's next:",
+    "whatsNextContent": [
+      "<ul>",
+      "  <li>Download XML or java code configuration.</li>",
+      "  <li>Start Ignite cluster with downloaded configuration.</li>",
+      "</ul>"
+    ]
+  },
+  "clientFields": [
+    {
+      "label": "Near cache start size",
+      "type": "number",
+      "path": "nearConfiguration",
+      "model": "nearStartSize",
+      "placeholder": 375000,
+      "tip": [
+        "Initial cache size for near cache which will be used to pre-create internal hash table after start."
+      ]
+    },
+    {
+      "label": "Near cache eviction policy",
+      "type": "dropdown-details",
+      "path": "nearConfiguration.nearEvictionPolicy",
+      "model": "kind",
+      "placeholder": "Choose eviction policy",
+      "items": "evictionPolicies",
+      "tip": [
+        "Cache expiration policy."
+      ],
+      "details": {
+        "LRU": {
+          "expanded": false,
+          "fields": [
+            {
+              "label": "Batch size",
+              "type": "number",
+              "path": "nearConfiguration.nearEvictionPolicy.LRU",
+              "model": "batchSize",
+              "placeholder": 1,
+              "tip": [
+                "Number of entries to remove on shrink."
+              ]
+            },
+            {
+              "label": "Max memory size",
+              "type": "number",
+              "path": "nearConfiguration.nearEvictionPolicy.LRU",
+              "model": "maxMemorySize",
+              "placeholder": 0,
+              "tip": [
+                "Maximum allowed cache size in bytes."
+              ]
+            },
+            {
+              "label": "Max size",
+              "type": "number",
+              "path": "nearConfiguration.nearEvictionPolicy.LRU",
+              "model": "maxSize",
+              "placeholder": 100000,
+              "tip": [
+                "Maximum allowed size of cache before entry will start getting evicted."
+              ]
+            }
+          ]
+        },
+        "RND": {
+          "expanded": false,
+          "fields": [
+            {
+              "label": "Max size",
+              "type": "number",
+              "path": "nearConfiguration.nearEvictionPolicy.RND",
+              "model": "maxSize",
+              "placeholder": 100000,
+              "tip": [
+                "Maximum allowed size of cache before entry will start getting evicted."
+              ]
+            }
+          ]
+        },
+        "FIFO": {
+          "expanded": false,
+          "fields": [
+            {
+              "label": "Batch size",
+              "type": "number",
+              "path": "nearConfiguration.nearEvictionPolicy.FIFO",
+              "model": "batchSize",
+              "placeholder": 1,
+              "tip": [
+                "Number of entries to remove on shrink."
+              ]
+            },
+            {
+              "label": "Max memory size",
+              "type": "number",
+              "path": "nearConfiguration.nearEvictionPolicy.FIFO",
+              "model": "maxMemorySize",
+              "placeholder": 0,
+              "tip": [
+                "Maximum allowed cache size in bytes."
+              ]
+            },
+            {
+              "label": "Max size",
+              "type": "number",
+              "path": "nearConfiguration.nearEvictionPolicy.FIFO",
+              "model": "maxSize",
+              "placeholder": 100000,
+              "tip": [
+                "Maximum allowed size of cache before entry will start getting evicted."
+              ]
+            }
+          ]
+        },
+        "SORTED": {
+          "expanded": false,
+          "fields": [
+            {
+              "label": "Batch size",
+              "type": "number",
+              "path": "nearConfiguration.nearEvictionPolicy.SORTED",
+              "model": "batchSize",
+              "placeholder": 1,
+              "tip": [
+                "Number of entries to remove on shrink."
+              ]
+            },
+            {
+              "label": "Max memory size",
+              "type": "number",
+              "path": "nearConfiguration.nearEvictionPolicy.SORTED",
+              "model": "maxMemorySize",
+              "placeholder": 0,
+              "tip": [
+                "Maximum allowed cache size in bytes."
+              ]
+            },
+            {
+              "label": "Max size",
+              "type": "number",
+              "path": "nearConfiguration.nearEvictionPolicy.SORTED",
+              "model": "maxSize",
+              "placeholder": 100000,
+              "tip": [
+                "Maximum allowed size of cache before entry will start getting evicted."
+              ]
+            }
+          ]
+        }
+      }
+    }
+  ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/profile-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/profile-controller.js b/modules/web-control-center/src/main/js/controllers/profile-controller.js
new file mode 100644
index 0000000..a67df63
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/profile-controller.js
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+controlCenterModule.controller('profileController', ['$scope', '$http', '$common', function ($scope, $http, $common) {
+    $scope.profileUser = angular.copy($scope.user);
+
+    $scope.saveUser = function () {
+        var profile = $scope.profileUser;
+
+        if (profile) {
+            var userName = profile.username;
+            var changeUsername = userName != $scope.user.username;
+
+            var email = profile.email;
+            var changeEmail = email != $scope.user.email;
+
+            if (changeUsername || changeEmail || profile.changePassword) {
+                $http.post('/profile/saveUser', {
+                    _id: profile._id,
+                    userName: changeUsername ? userName : undefined,
+                    email: changeEmail ? email : undefined,
+                    newPassword: profile.changePassword ? profile.newPassword : undefined
+                }).success(function (user) {
+                    $common.showInfo('Profile saved.');
+
+                    if (changeUsername)
+                        $scope.user.username = userName;
+
+                    if (changeEmail)
+                        $scope.user.email = email;
+                }).error(function (err) {
+                    $common.showError('Failed to save profile: ' + $common.errorMessage(err));
+                });
+            }
+        }
+    };
+}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/summary-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/summary-controller.js b/modules/web-control-center/src/main/js/controllers/summary-controller.js
new file mode 100644
index 0000000..1291683
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/summary-controller.js
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+controlCenterModule.controller('summaryController', ['$scope', '$http', '$common', function ($scope, $http, $common) {
+    $scope.joinTip = $common.joinTip;
+    $scope.getModel = $common.getModel;
+
+    $scope.javaClassItems = [
+        {label: 'snippet', value: false},
+        {label: 'factory class', value: true}
+    ];
+
+    $scope.evictionPolicies = [
+        {value: 'LRU', label: 'LRU'},
+        {value: 'RND', label: 'Random'},
+        {value: 'FIFO', label: 'FIFO'},
+        {value: 'SORTED', label: 'Sorted'},
+        {value: undefined, label: 'Not set'}
+    ];
+
+    $scope.oss = ['debian:8', 'ubuntu:14.10'];
+
+    $scope.configServer = {javaClassServer: false, os: undefined};
+    $scope.backupItem = {javaClassClient: false};
+
+    $http.get('/models/summary.json')
+        .success(function (data) {
+            $scope.screenTip = data.screenTip;
+            $scope.clientFields = data.clientFields;
+        })
+        .error(function (errMsg) {
+            $common.showError(errMsg);
+        });
+
+    $scope.clusters = [];
+
+    $scope.aceInit = function (editor) {
+        editor.setReadOnly(true);
+        editor.setOption("highlightActiveLine", false);
+
+        editor.setTheme('ace/theme/chrome');
+    };
+
+    $scope.reloadServer = function () {
+        $scope.javaServer = $scope.configServer.javaClassServer ? $scope.configServer.javaClass : $scope.configServer.javaSnippet;
+
+        if ($scope.configServer.docker) {
+            var os = $scope.configServer.os ? $scope.configServer.os : $scope.oss[0];
+
+            $scope.dockerServer = $scope.configServer.docker.replace(new RegExp('\%OS\%', 'g'), os);
+        }
+    };
+
+    $scope.selectItem = function (cluster) {
+        if (!cluster)
+            return;
+
+        $scope.selectedItem = cluster;
+
+        $scope.$watch('javaClassServer', $scope.reloadServer);
+        $scope.$watch('os', $scope.reloadServer);
+
+        $scope.generateServer(cluster);
+
+        $scope.reloadServer();
+
+        $scope.$watch('configServer', function () {
+            $scope.reloadServer();
+        }, true);
+
+        $scope.$watch('backupItem', function () {
+            $scope.generateClient();
+        }, true);
+    };
+
+    $scope.generateServer = function (cluster) {
+        $http.post('summary/generator', {_id: cluster._id})
+            .success(function (data) {
+                $scope.xmlServer = data.xmlServer;
+
+                $scope.configServer.javaClass = data.javaClassServer;
+                $scope.configServer.javaSnippet = data.javaSnippetServer;
+                $scope.configServer.docker = data.docker;
+            }).error(function (errMsg) {
+                $common.showError('Failed to generate config: ' + errMsg);
+            });
+    };
+
+    $scope.generateClient = function () {
+        $http.post('summary/generator', {
+            _id: $scope.selectedItem._id, javaClass: $scope.backupItem.javaClassClient,
+            clientNearConfiguration: $scope.backupItem.nearConfiguration
+        })
+            .success(function (data) {
+                $scope.xmlClient = data.xmlClient;
+                $scope.javaClient = data.javaClient;
+            }).error(function (errMsg) {
+                $common.showError('Failed to generate config: ' + errMsg);
+            });
+    };
+
+    $scope.download = function () {
+        $http.post('summary/download', {_id: $scope.selectedItem._id, javaClass: $scope.javaClass, os: $scope.os})
+            .success(function (data) {
+                var file = document.createElement('a');
+
+                file.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + data);
+                file.setAttribute('download', $scope.selectedItem.name + '-configuration.zip');
+
+                file.style.display = 'none';
+
+                document.body.appendChild(file);
+
+                file.click();
+
+                document.body.removeChild(file);
+            })
+            .error(function (errMsg) {
+                $common.showError('Failed to generate zip: ' + errMsg);
+            });
+    };
+
+    $http.post('clusters/list').success(function (data) {
+        $scope.clusters = data.clusters;
+
+        if ($scope.clusters.length > 0) {
+            var restoredId = sessionStorage.summarySelectedId;
+
+            var selectIdx = 0;
+
+            if (restoredId) {
+                var idx = _.findIndex($scope.clusters, function (cluster) {
+                    return cluster._id == restoredId;
+                });
+
+                if (idx >= 0)
+                    selectIdx = idx;
+                else
+                    delete sessionStorage.summarySelectedId;
+            }
+
+            $scope.selectItem($scope.clusters[selectIdx]);
+
+            $scope.$watch('selectedItem', function (val) {
+                if (val)
+                    sessionStorage.summarySelectedId = val._id;
+            }, true);
+        }
+    });
+}]);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/db.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/db.js b/modules/web-control-center/src/main/js/db.js
new file mode 100644
index 0000000..e34272c
--- /dev/null
+++ b/modules/web-control-center/src/main/js/db.js
@@ -0,0 +1,358 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var config = require('./helpers/configuration-loader.js');
+
+// Mongoose for mongodb.
+var mongoose = require('mongoose'),
+    Schema = mongoose.Schema,
+    ObjectId = mongoose.Schema.Types.ObjectId,
+    passportLocalMongoose = require('passport-local-mongoose');
+
+// Connect to mongoDB database.
+mongoose.connect(config.get('mongoDB:url'), {server: {poolSize: 4}});
+
+// Define account model.
+var AccountSchema = new Schema({
+    username: String,
+    email: String,
+    lastLogin: Date,
+    admin: Boolean
+});
+
+AccountSchema.plugin(passportLocalMongoose, {usernameField: 'email', limitAttempts: true, lastLoginField: 'lastLogin',
+    usernameLowerCase: true});
+
+AccountSchema.set('toJSON', {
+    transform: function(doc, ret) {
+        return {
+            _id: ret._id,
+            email: ret.email,
+            username: ret.username,
+            admin: ret.admin,
+            lastLogin: ret.lastLogin
+        };
+    }
+});
+
+exports.Account = mongoose.model('Account', AccountSchema);
+
+// Define space model.
+exports.Space = mongoose.model('Space', new Schema({
+    name: String,
+    owner: {type: ObjectId, ref: 'Account'},
+    usedBy: [{
+        permission: {type: String, enum: ['VIEW', 'FULL']},
+        account: {type: ObjectId, ref: 'Account'}
+    }]
+}));
+
+// Define cache type metadata model.
+var CacheTypeMetadataSchema = new Schema({
+    space: {type: ObjectId, ref: 'Space'},
+    name: String,
+    kind: {type: String, enum: ['query', 'store', 'both']},
+    databaseSchema: String,
+    databaseTable: String,
+    keyType: String,
+    valueType: String,
+    keyFields: [{dbName: String, dbType: String, javaName: String, javaType: String}],
+    valueFields: [{dbName: String, dbType: String, javaName: String, javaType: String}],
+    queryFields: [{name: String, className: String}],
+    ascendingFields: [{name: String, className: String}],
+    descendingFields:  [{name: String, className: String}],
+    textFields: [String],
+    groups: [{name: String, fields: [{name: String, className: String, direction: String}]}]
+});
+
+exports.CacheTypeMetadata = mongoose.model('CacheTypeMetadata', CacheTypeMetadataSchema);
+
+// Define cache model.
+var CacheSchema = new Schema({
+    space: {type: ObjectId, ref: 'Space'},
+    name: String,
+    mode: {type: String, enum: ['PARTITIONED', 'REPLICATED', 'LOCAL']},
+    atomicityMode: {type: String, enum: ['ATOMIC', 'TRANSACTIONAL']},
+
+    backups: Number,
+    memoryMode: {type: String, enum: ['ONHEAP_TIERED', 'OFFHEAP_TIERED', 'OFFHEAP_VALUES']},
+    offHeapMaxMemory: Number,
+    startSize: Number,
+    swapEnabled: Boolean,
+
+    evictionPolicy: {
+        kind: {type: String, enum: ['LRU', 'RND', 'FIFO', 'Sorted']},
+        LRU: {
+            batchSize: Number,
+            maxMemorySize: Number,
+            maxSize: Number
+        },
+        RND: {
+            maxSize: Number
+        },
+        FIFO: {
+            batchSize: Number,
+            maxMemorySize: Number,
+            maxSize: Number
+        },
+        SORTED: {
+            batchSize: Number,
+            maxMemorySize: Number,
+            maxSize: Number
+        }
+    },
+
+    rebalanceMode: {type: String, enum: ['SYNC', 'ASYNC', 'NONE']},
+    rebalanceThreadPoolSize: Number,
+    rebalanceBatchSize: Number,
+    rebalanceOrder: Number,
+    rebalanceDelay: Number,
+    rebalanceTimeout: Number,
+    rebalanceThrottle: Number,
+
+    cacheStoreFactory: {
+        kind: {
+            type: String,
+            enum: ['CacheJdbcPojoStoreFactory', 'CacheJdbcBlobStoreFactory', 'CacheHibernateBlobStoreFactory']
+        },
+        CacheJdbcPojoStoreFactory: {
+            dataSourceBean: String,
+            dialect: {
+                type: String,
+                enum: ['Oracle', 'DB2', 'SQLServer', 'MySQL', 'PosgreSQL', 'H2']
+            }
+        },
+        CacheJdbcBlobStoreFactory: {
+            user: String,
+            dataSourceBean: String,
+            initSchema: Boolean,
+            createTableQuery: String,
+            loadQuery: String,
+            insertQuery: String,
+            updateQuery: String,
+            deleteQuery: String
+        },
+        CacheHibernateBlobStoreFactory: {
+            hibernateProperties: [String]
+        }
+    },
+    loadPreviousValue: Boolean,
+    readThrough: Boolean,
+    writeThrough: Boolean,
+
+    writeBehindEnabled: Boolean,
+    writeBehindBatchSize: Number,
+    writeBehindFlushSize: Number,
+    writeBehindFlushFrequency: Number,
+    writeBehindFlushThreadCount: Number,
+
+    invalidate: Boolean,
+    defaultLockTimeout: Number,
+    transactionManagerLookupClassName: String,
+
+    sqlEscapeAll: Boolean,
+    sqlOnheapRowCacheSize: Number,
+    longQueryWarningTimeout: Number,
+    indexedTypes: [{keyClass: String, valueClass: String}],
+    sqlFunctionClasses: [String],
+    statisticsEnabled: Boolean,
+    managementEnabled: Boolean,
+    readFromBackup: Boolean,
+    copyOnRead: Boolean,
+    maxConcurrentAsyncOperations: Number,
+    nearConfiguration: {
+        nearStartSize: Number,
+        nearEvictionPolicy: {
+            kind: {type: String, enum: ['LRU', 'RND', 'FIFO', 'Sorted']},
+            LRU: {
+                batchSize: Number,
+                maxMemorySize: Number,
+                maxSize: Number
+            },
+            RND: {
+                maxSize: Number
+            },
+            FIFO: {
+                batchSize: Number,
+                maxMemorySize: Number,
+                maxSize: Number
+            },
+            SORTED: {
+                batchSize: Number,
+                maxMemorySize: Number,
+                maxSize: Number
+            }
+        }
+    }
+});
+
+exports.Cache = mongoose.model('Cache', CacheSchema);
+
+// Define cluster schema.
+var ClusterSchema = new Schema({
+    space: {type: ObjectId, ref: 'Space'},
+    name: String,
+    discovery: {
+        kind: {type: String, enum: ['Vm', 'Multicast', 'S3', 'Cloud', 'GoogleStorage', 'Jdbc', 'SharedFs']},
+        Vm: {
+            addresses: [String]
+        },
+        Multicast: {
+            multicastGroup: String,
+            multicastPort: Number,
+            responseWaitTime: Number,
+            addressRequestAttempts: Number,
+            localAddress: String
+        },
+        S3: {
+            bucketName: String
+        },
+        Cloud: {
+            credential: String,
+            credentialPath: String,
+            identity: String,
+            provider: String,
+            regions: [String],
+            zones:  [String]
+        },
+        GoogleStorage: {
+            projectName: String,
+            bucketName: String,
+            serviceAccountP12FilePath: String,
+            addrReqAttempts: String
+        },
+        Jdbc: {
+            initSchema: Boolean
+        },
+        SharedFs: {
+            path: String
+        }
+    },
+    atomicConfiguration: {
+        backups: Number,
+        cacheMode: {type: String, enum: ['LOCAL', 'REPLICATED', 'PARTITIONED']},
+        atomicSequenceReserveSize: Number
+    },
+    caches: [{type: ObjectId, ref: 'Cache'}],
+    cacheSanityCheckEnabled: Boolean,
+    clockSyncSamples: Number,
+    clockSyncFrequency: Number,
+    deploymentMode: {type: String, enum: ['PRIVATE', 'ISOLATED', 'SHARED', 'CONTINUOUS']},
+    discoveryStartupDelay: Number,
+    igfsThreadPoolSize: Number,
+    includeEventTypes: [{
+        type: String, enum: ['EVTS_CHECKPOINT', 'EVTS_DEPLOYMENT', 'EVTS_ERROR', 'EVTS_DISCOVERY',
+            'EVTS_JOB_EXECUTION', 'EVTS_TASK_EXECUTION', 'EVTS_CACHE', 'EVTS_CACHE_REBALANCE', 'EVTS_CACHE_LIFECYCLE',
+            'EVTS_CACHE_QUERY', 'EVTS_SWAPSPACE', 'EVTS_IGFS']
+    }],
+    managementThreadPoolSize: Number,
+    marshaller: {
+        kind: {type: String, enum: ['OptimizedMarshaller', 'JdkMarshaller']},
+        OptimizedMarshaller: {
+            poolSize: Number,
+            requireSerializable: Boolean
+        }
+    },
+    marshalLocalJobs: Boolean,
+    marshallerCacheKeepAliveTime: Number,
+    marshallerCacheThreadPoolSize: Number,
+    metricsExpireTime: Number,
+    metricsHistorySize: Number,
+    metricsLogFrequency: Number,
+    metricsUpdateFrequency: Number,
+    networkTimeout: Number,
+    networkSendRetryDelay: Number,
+    networkSendRetryCount: Number,
+    peerClassLoadingEnabled: Boolean,
+    peerClassLoadingLocalClassPathExclude: [String],
+    peerClassLoadingMissedResourcesCacheSize: Number,
+    peerClassLoadingThreadPoolSize: Number,
+    publicThreadPoolSize: Number,
+    segmentCheckFrequency: Number,
+    segmentationPolicy: {type: String, enum: ['RESTART_JVM', 'STOP', 'NOOP']},
+    allSegmentationResolversPassRequired: Boolean,
+    segmentationResolveAttempts: Number,
+    swapSpaceSpi: {
+        kind: {type: String, enum: ['FileSwapSpaceSpi']},
+        FileSwapSpaceSpi: {
+            baseDirectory: String,
+            readStripesNumber: Number,
+            maximumSparsity: Number,
+            maxWriteQueueSize: Number,
+            writeBufferSize: Number
+        }
+    },
+    systemThreadPoolSize: Number,
+    timeServerPortBase: Number,
+    timeServerPortRange: Number,
+    transactionConfiguration: {
+        defaultTxConcurrency: {type: String, enum: ['OPTIMISTIC', 'PESSIMISTIC']},
+        transactionIsolation: {type: String, enum: ['READ_COMMITTED', 'REPEATABLE_READ', 'SERIALIZABLE']},
+        defaultTxTimeout: Number,
+        pessimisticTxLogLinger: Number,
+        pessimisticTxLogSize: Number,
+        txSerializableEnabled: Boolean
+    },
+    waitForSegmentOnStart: Boolean
+});
+
+// Define cluster model.
+exports.Cluster = mongoose.model('Cluster', ClusterSchema);
+
+// Define persistence schema.
+var PersistenceSchema = new Schema({
+    space: {type: ObjectId, ref: 'Space'},
+    name: String,
+    dbType: {type: String, enum: ['oracle', 'db2', 'mssql', 'postgre', 'mysql', 'h2']},
+    dbName: String,
+    host: String,
+    user: String,
+    tables: [{
+        use: Boolean,
+        schemaName: String,
+        tableName: String,
+        keyClass: String,
+        valueClass: String,
+        columns: [{
+            use: Boolean,
+            pk: Boolean,
+            ak: Boolean,
+            notNull: Boolean,
+            dbName: String,
+            dbType: Number,
+            javaName: String,
+            javaType: String
+        }]
+    }]
+});
+
+// Define persistence model.
+exports.Persistence = mongoose.model('Persistence', PersistenceSchema);
+
+exports.upsert = function (model, data, cb) {
+    if (data._id) {
+        var id = data._id;
+
+        delete data._id;
+
+        model.findOneAndUpdate({_id: id}, data, cb);
+    }
+    else
+        new model(data).save(cb);
+};
+
+exports.mongoose = mongoose;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/helpers/configuration-loader.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/helpers/configuration-loader.js b/modules/web-control-center/src/main/js/helpers/configuration-loader.js
new file mode 100644
index 0000000..6dbb577
--- /dev/null
+++ b/modules/web-control-center/src/main/js/helpers/configuration-loader.js
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var config = require('nconf');
+
+config.file({'file': 'config/default.json'});
+
+module.exports = config;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/helpers/data-structures.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/helpers/data-structures.js b/modules/web-control-center/src/main/js/helpers/data-structures.js
new file mode 100644
index 0000000..2462708
--- /dev/null
+++ b/modules/web-control-center/src/main/js/helpers/data-structures.js
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+eventGroups = {
+    EVTS_CHECKPOINT: ['EVT_CHECKPOINT_SAVED', 'EVT_CHECKPOINT_LOADED', 'EVT_CHECKPOINT_REMOVED'],
+    EVTS_DEPLOYMENT: ['EVT_CLASS_DEPLOYED', 'EVT_CLASS_UNDEPLOYED', 'EVT_CLASS_DEPLOY_FAILED', 'EVT_TASK_DEPLOYED',
+        'EVT_TASK_UNDEPLOYED', 'EVT_TASK_DEPLOY_FAILED'],
+    EVTS_ERROR: ['EVT_JOB_TIMEDOUT', 'EVT_JOB_FAILED', 'EVT_JOB_FAILED_OVER', 'EVT_JOB_REJECTED', 'EVT_JOB_CANCELLED',
+        'EVT_TASK_TIMEDOUT', 'EVT_TASK_FAILED', 'EVT_CLASS_DEPLOY_FAILED', 'EVT_TASK_DEPLOY_FAILED',
+        'EVT_TASK_DEPLOYED', 'EVT_TASK_UNDEPLOYED', 'EVT_CACHE_REBALANCE_STARTED', 'EVT_CACHE_REBALANCE_STOPPED'],
+    EVTS_DISCOVERY: ['EVT_NODE_JOINED', 'EVT_NODE_LEFT', 'EVT_NODE_FAILED', 'EVT_NODE_SEGMENTED',
+        'EVT_CLIENT_NODE_DISCONNECTED', 'EVT_CLIENT_NODE_RECONNECTED'],
+    EVTS_JOB_EXECUTION: ['EVT_JOB_MAPPED', 'EVT_JOB_RESULTED', 'EVT_JOB_FAILED_OVER', 'EVT_JOB_STARTED',
+        'EVT_JOB_FINISHED', 'EVT_JOB_TIMEDOUT', 'EVT_JOB_REJECTED', 'EVT_JOB_FAILED', 'EVT_JOB_QUEUED',
+        'EVT_JOB_CANCELLED'],
+    EVTS_TASK_EXECUTION: ['EVT_TASK_STARTED', 'EVT_TASK_FINISHED', 'EVT_TASK_FAILED', 'EVT_TASK_TIMEDOUT',
+        'EVT_TASK_SESSION_ATTR_SET', 'EVT_TASK_REDUCED'],
+    EVTS_CACHE: ['EVT_CACHE_ENTRY_CREATED', 'EVT_CACHE_ENTRY_DESTROYED', 'EVT_CACHE_OBJECT_PUT',
+        'EVT_CACHE_OBJECT_READ', 'EVT_CACHE_OBJECT_REMOVED', 'EVT_CACHE_OBJECT_LOCKED', 'EVT_CACHE_OBJECT_UNLOCKED',
+        'EVT_CACHE_OBJECT_SWAPPED', 'EVT_CACHE_OBJECT_UNSWAPPED', 'EVT_CACHE_OBJECT_EXPIRED'],
+    EVTS_CACHE_REBALANCE: ['EVT_CACHE_REBALANCE_STARTED', 'EVT_CACHE_REBALANCE_STOPPED',
+        'EVT_CACHE_REBALANCE_PART_LOADED', 'EVT_CACHE_REBALANCE_PART_UNLOADED', 'EVT_CACHE_REBALANCE_OBJECT_LOADED',
+        'EVT_CACHE_REBALANCE_OBJECT_UNLOADED', 'EVT_CACHE_REBALANCE_PART_DATA_LOST'],
+    EVTS_CACHE_LIFECYCLE: ['EVT_CACHE_STARTED', 'EVT_CACHE_STOPPED', 'EVT_CACHE_NODES_LEFT'],
+    EVTS_CACHE_QUERY: ['EVT_CACHE_QUERY_EXECUTED', 'EVT_CACHE_QUERY_OBJECT_READ'],
+    EVTS_SWAPSPACE: ['EVT_SWAP_SPACE_CLEARED', 'EVT_SWAP_SPACE_DATA_REMOVED', 'EVT_SWAP_SPACE_DATA_READ',
+        'EVT_SWAP_SPACE_DATA_STORED', 'EVT_SWAP_SPACE_DATA_EVICTED'],
+    EVTS_IGFS: ['EVT_IGFS_FILE_CREATED', 'EVT_IGFS_FILE_RENAMED', 'EVT_IGFS_FILE_DELETED', 'EVT_IGFS_FILE_OPENED_READ',
+        'EVT_IGFS_FILE_OPENED_WRITE', 'EVT_IGFS_FILE_CLOSED_WRITE', 'EVT_IGFS_FILE_CLOSED_READ', 'EVT_IGFS_FILE_PURGED',
+        'EVT_IGFS_META_UPDATED', 'EVT_IGFS_DIR_CREATED', 'EVT_IGFS_DIR_RENAMED', 'EVT_IGFS_DIR_DELETED']
+};
+
+jdbcTypes = {
+    BIT: {value: "BIT", code: -7, label: "BIT"},
+    TINYINT: {value: "TINYINT", code: -6, label: "TINYINT"},
+    SMALLINT: {value: "SMALLINT", code: 5, label: "SMALLINT"},
+    INTEGER: {value: "INTEGER", code: 4, label: "INTEGER"},
+    BIGINT: {value: "BIGINT", code: -5, label: "BIGINT"},
+    FLOAT: {value: "FLOAT", code: 6, label: "FLOAT"},
+    REAL: {value: "REAL", code: 7, label: "REAL"},
+    DOUBLE: {value: "DOUBLE", code: 8, label: "DOUBLE"},
+    NUMERIC: {value: "NUMERIC", code: 2, label: "NUMERIC"},
+    DECIMAL: {value: "DECIMAL", code: 3, label: "DECIMAL"},
+    CHAR: {value: "CHAR", code: 1, label: "CHAR"},
+    VARCHAR: {value: "VARCHAR", code: 12, label: "VARCHAR"},
+    DATE: {value: "DATE", code: 91, label: "DATE"},
+    TIME: {value: "TIME", code: 92, label: "TIME"},
+    TIMESTAMP: {value: "TIMESTAMP", code: 93, label: "TIMESTAMP"},
+    BINARY: {value: "BINARY", code: -2, label: "BINARY"}
+};
+
+javaTypes = {
+    INTEGER: {value: "java.lang.Integer", label: "Integer"},
+    LONG: {value: "java.lang.Long", label: "Long"},
+    BIGDECIMAL: {value: "java.math.BigDecimal", label: "BigDecimal"},
+    FLOAT: {value: "java.lang.Float", label: "Float"},
+    DOUBLE: {value: "java.lang.Double", label: "Double"},
+    STRING: {value: "java.lang.String", label: "String"},
+    BOOLEAN: {value: "java.lang.Boolean", label: "Boolean"},
+    BYTE_ARRAY: {value: "byte[]", label: "byte[]"},
+    DATE: {value: "java.sql.Date", label: "Date"},
+    TIME: {value: "java.sql.Time", label: "Time"},
+    TIMESTAMP: {value: "java.sql.Timestamp", label: "Timestamp"}
+};
+
+if (typeof window === 'undefined') {
+    exports.eventGroups = eventGroups;
+    exports.jdbcTypes = jdbcTypes;
+    exports.javaTypes = javaTypes;
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/package.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/package.json b/modules/web-control-center/src/main/js/package.json
new file mode 100644
index 0000000..5e5463c
--- /dev/null
+++ b/modules/web-control-center/src/main/js/package.json
@@ -0,0 +1,50 @@
+{
+  "name": "ignite-web-control-center",
+  "version": "1.0.0",
+  "description": "Web application for configuration, monitoring Ignite Cluster",
+  "private": true,
+  "scripts": {
+    "start": "node ./bin/www"
+  },
+  "author": "",
+  "contributors": [
+    {
+      "name": "",
+      "email": ""
+    }
+  ],
+  "license": "Apache-2.0",
+  "keywords": "grid",
+  "homepage": "https://ignite.incubator.apache.org/",
+  "engines": {
+    "node": ">=0.12.4"
+  },
+  "dependencies": {
+    "angular-ui-ace": "^0.2.3",
+    "archiver": "^0.14.4",
+    "body-parser": "~1.12.0",
+    "connect-flash": "^0.1.1",
+    "connect-mongo": "^0.8.1",
+    "cookie-parser": "~1.3.4",
+    "debug": "~2.1.1",
+    "express": "~4.12.2",
+    "express-session": "^1.11.1",
+    "jade": "~1.9.2",
+    "less-middleware": "1.0.x",
+    "lodash": "3.10.0",
+    "mongoose": "^4.0.2",
+    "nconf": "^0.7.1",
+    "passport": "^0.2.1",
+    "passport-local": "^1.0.0",
+    "passport-local-mongoose": "^1.0.0",
+    "pg": "^4.4.0",
+    "serve-favicon": "~2.2.0",
+    "util": "^0.10.3"
+  },
+  "devDependencies": {
+    "morgan": "~1.5.1",
+    "supertest": "^1.0.1",
+    "mocha": "~2.0.1",
+    "should": "~3.1.3"
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/public/favicon.ico
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/public/favicon.ico b/modules/web-control-center/src/main/js/public/favicon.ico
new file mode 100644
index 0000000..74ec626
Binary files /dev/null and b/modules/web-control-center/src/main/js/public/favicon.ico differ

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/public/images/docker.png
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/public/images/docker.png b/modules/web-control-center/src/main/js/public/images/docker.png
new file mode 100644
index 0000000..7ec3aef
Binary files /dev/null and b/modules/web-control-center/src/main/js/public/images/docker.png differ

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/public/images/java.png
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/public/images/java.png b/modules/web-control-center/src/main/js/public/images/java.png
new file mode 100644
index 0000000..ddb3b8e
Binary files /dev/null and b/modules/web-control-center/src/main/js/public/images/java.png differ

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/public/images/logo.png
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/public/images/logo.png b/modules/web-control-center/src/main/js/public/images/logo.png
new file mode 100644
index 0000000..c3577c5
Binary files /dev/null and b/modules/web-control-center/src/main/js/public/images/logo.png differ

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/public/images/xml.png
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/public/images/xml.png b/modules/web-control-center/src/main/js/public/images/xml.png
new file mode 100644
index 0000000..029065e
Binary files /dev/null and b/modules/web-control-center/src/main/js/public/images/xml.png differ


[36/50] [abbrv] incubator-ignite git commit: # ignite-843 moved

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/public/stylesheets/style.less
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/public/stylesheets/style.less b/modules/web-control-center/src/main/js/public/stylesheets/style.less
new file mode 100644
index 0000000..4900581
--- /dev/null
+++ b/modules/web-control-center/src/main/js/public/stylesheets/style.less
@@ -0,0 +1,1172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@logo-path: "https://www.filepicker.io/api/file/QagunjDGRFul2JgNCAli";
+@input-height: 28px;
+@ignite-red: #ec1c24;
+@ignite-block-callout-background: #f3f8f3;
+@ignite-block-callout: #50af51;
+
+hr {
+  margin-top: 20px;
+  margin-bottom: 20px;
+}
+
+.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;
+  &.ng-enter {
+    opacity: 0;
+    &.ng-enter-active {
+      opacity: .5;
+    }
+  }
+  &.ng-leave {
+    opacity: .5;
+    &.ng-leave-active {
+      opacity: 0;
+    }
+  }
+}
+
+.modal.center .modal-dialog {
+  position: fixed;
+  top: 50%;
+  left: 50%;
+  -webkit-transform: translateX(-50%) translateY(-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, 255, 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: 5px 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: 22px;
+}
+
+.theme-line .btn-primary {
+  border: 0 none;
+  background-color: @ignite-red;
+}
+
+.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: 5px solid #ddd;
+}
+
+.theme-line .main-content .nav-horizontal a.active {
+  border-bottom: 5px solid #888;
+}
+
+.theme-line .navbar-nav, .theme-line .sidebar-nav {
+  ul li > a.active {
+    cursor: default;
+    pointer-events: none;
+  }
+}
+
+.theme-line .sidebar-nav {
+  color: #474a54;
+  padding-bottom: 30px;
+
+  ul {
+    padding: 0;
+    list-style: none;
+    font-size: 14px;
+    margin: 3px 0 0;
+    li {
+      color: #666;
+      line-height: @input-height;
+
+      span.fa-stack {
+        margin-right: 5px;
+        font-size: 12px;
+        height: 26px;
+      }
+
+      a {
+        font-size: 18px;
+        color: #666;
+        position: relative;
+        white-space: nowrap;
+        overflow: hidden;
+        -o-text-overflow: ellipsis;
+        text-overflow: ellipsis;
+      }
+    }
+  }
+}
+
+.theme-line .sidebar-nav ul li a:hover {
+  text-decoration: none;
+}
+
+.theme-line .select,
+.theme-line .typeahead {
+  li a {
+    color: #666;
+    background-color: transparent;
+  }
+
+  li a:hover {
+    color: @ignite-red;
+  }
+
+  .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: 5px;
+  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;
+}
+
+.header .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: @ignite-red;
+}
+
+.theme-line .navbar-nav {
+  color: #888;
+}
+
+.theme-line .navbar-nav a {
+  color: #bbb;
+}
+
+.theme-line header a.btn {
+  background-color: @ignite-red;
+}
+
+.theme-line header a.btn:hover {
+  background-color: #950d12;
+}
+
+.theme-line header .navbar-nav .tt-cursor {
+  background-color: @ignite-red;
+}
+
+.theme-line header .navbar-nav a:hover, .theme-line header .navbar-nav .open > a {
+  color: @ignite-red;
+}
+
+.theme-line .navbar-nav .active a {
+  //font-weight: bold;
+  color: @ignite-red;
+}
+
+.theme-line .navbar-nav .active a:hover {
+  color: #950d12;
+}
+
+.theme-line .main-links .links a:hover {
+  color: @ignite-red;
+}
+
+.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: @ignite-red;
+}
+
+.theme-line .sidebar-nav ul li a.active {
+  color: @ignite-red;
+}
+
+.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: @ignite-red;
+  color: @ignite-red;
+}
+
+.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 strong, .theme-line #versions-list li a.active .current, .theme-line #versions-list li a:active .current {
+  color: @ignite-red;
+}
+
+.theme-line header .navbar-nav a {
+  font-size: 18px;
+}
+
+.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: @ignite-red;
+  border-color: @ignite-red;
+}
+
+.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;
+  margin-bottom: 10px;
+}
+
+.submit-vote.submit-vote-parent.voted a.submit-vote-button, .submit-vote.submit-vote-parent a.submit-vote-button:hover {
+  background-color: @ignite-red;
+}
+
+div.submit-vote.submit-vote-parent.voted a.submit-vote-button:hover {
+  background-color: #950d12;
+}
+
+a, .link .title {
+  color: @ignite-red;
+}
+
+a:hover, .link:hover .title {
+  color: #950d12;
+}
+
+.header h1.navbar-brand a {
+  background-image: url("@{logo-path}");
+}
+
+.header h1.navbar-brand {
+  width: 96px;
+}
+
+.block-edit-parameters {
+  text-align: right;
+  padding-bottom: 5px;
+}
+
+.container-footer {
+  margin-top: 20px;
+}
+
+/* Modal */
+.modal {
+  display: block;
+  overflow: hidden;
+}
+
+.modal .close {
+  position: absolute;
+  top: 10px;
+  right: 10px;
+  float: none;
+}
+
+// Close icon
+.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: 15px;
+  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 .modal-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("@{logo-path}");
+}
+
+.block-display-image img {
+  max-width: 100%;
+  max-height: 450px;
+  margin: auto;
+  display: block;
+}
+
+.greedy {
+  min-height: 200px;
+  height: ~"calc(100vh - 290px)";
+}
+
+@media (min-width: 768px) {
+  .navbar-nav > li > a {
+    padding-top: 18px;
+    padding-bottom: 10px;
+  }
+}
+
+.details-row {
+  padding: 0 10px;
+}
+
+.details-row, .settings-row {
+  display: block;
+  margin: 10px 0;
+
+  label.table-header {
+    line-height: @input-height;
+  }
+
+  [class*="col-"] {
+    display: inline-block;
+    vertical-align: middle;
+    float: none;
+
+    padding-left: 0 !important;
+    padding-right: 0 !important;
+  }
+
+  input[type="checkbox"] {
+    line-height: 20px;
+    margin-right: 5px;
+  }
+
+  .checkbox label {
+    line-height: 20px;
+    vertical-align: middle;
+  }
+}
+
+button {
+  margin-right: 5px;
+}
+
+h1,
+h2,
+h3 {
+  user-select: none;
+  font-weight: normal;
+  /* Makes the vertical size of the text the same for all fonts. */
+  line-height: 1;
+}
+
+h3 {
+  color: black;
+  font-size: 1.2em;
+  margin-top: 0;
+  margin-bottom: 1.5em;
+}
+
+table tr:hover {
+  cursor: pointer;
+}
+
+.btn {
+  padding: 3px 6px;
+}
+
+button .caret, .btn .caret {
+  float: right;
+  margin-left: 5px;
+  margin-top: 7px;
+}
+
+.base-control {
+  text-align: left;
+  padding: 3px 3px;
+  height: @input-height;
+}
+
+.form-control:extend(.base-control all) {
+  display: inline-block;
+
+  button {
+    text-align: left;
+  }
+}
+
+.theme-line .panel-heading {
+  padding: 10px 10px;
+  margin: 0;
+
+  h3 {
+    margin-bottom: 0;
+  }
+
+  h3 > a {
+    color: black;
+  }
+}
+
+.theme-line .panel-title {
+  a {
+    color: @ignite-red;
+  }
+
+  h3 {
+    margin-bottom: 20px;
+  }
+}
+
+.theme-line .panel-body {
+  padding: 10px 20px;
+}
+
+.theme-line .main-content a.customize {
+  margin-left: 5px;
+  color: @ignite-red;
+}
+
+.theme-line .panel-collapse {
+  margin: 0;
+}
+
+.theme-line .links table {
+  display: table;
+  table-layout: fixed;
+
+  td {
+    padding-left: 18px;
+  }
+
+  .active a {
+    color: @ignite-red;
+    font-weight: bold;
+  }
+
+  a:hover {
+    color: #950d12;
+  }
+
+  a {
+    color: #666;
+  }
+}
+
+.theme-line table.links-edit:extend(.theme-line .links table all) {
+  margin-top: 5px;
+  margin-bottom: 5px;
+
+  label {
+    line-height: @input-height;
+    color: #666;
+  }
+}
+
+.theme-line table.links-edit-details:extend(.theme-line .links table all) {
+  margin-bottom: 10px;
+
+  label {
+    line-height: @input-height;
+    color: #666;
+  }
+
+  td {
+    padding: 0;
+
+    .input-tip {
+      padding: 0;
+    }
+  }
+}
+
+.theme-line table.admin {
+  tr:hover {
+    cursor: default;
+  }
+
+  thead > tr th.header {
+    padding: 0 0 10px;
+
+    div {
+      padding: 0
+    }
+  }
+
+  margin-bottom: 10px;
+
+  label {
+    line-height: @input-height;
+    color: #666;
+  }
+
+  thead > tr th, td {
+    padding: 10px 10px;
+
+    .input-tip {
+      padding: 0;
+    }
+  }
+
+  tfoot > tr > td {
+    padding: 0;
+
+    .pagination {
+      margin: 10px 0;
+
+      > .active > a {
+        color: @ignite-red;
+        font-weight: bold;
+        border-color: #ddd;
+        background-color: #eee;
+      }
+    }
+  }
+}
+
+.panel-title a {
+  font-size: 14px;
+}
+
+.panel-details {
+  margin-top: 10px;
+
+  padding: 0;
+
+  border-radius: 5px;
+  border: thin dotted lightgrey;
+}
+
+.tooltip.right .tooltip-arrow {
+  border-right-color: @ignite-red;
+}
+
+.tooltip > .tooltip-inner {
+  max-width: 400px;
+  text-align: left;
+  background-color: @ignite-red;
+}
+
+label {
+  font-weight: normal;
+  margin-bottom: 0;
+}
+
+.form-horizontal .checkbox {
+  padding-top: 0;
+}
+
+.input-tip {
+  display: block;
+  overflow: hidden;
+}
+
+.labelField {
+  float: left;
+  margin-right: 5px;
+}
+
+.labelFormField {
+  float: left;
+  line-height: @input-height;
+}
+
+.form-horizontal .form-group {
+  margin: 0;
+}
+
+.form-horizontal .has-feedback .form-control-feedback {
+  right: 0;
+}
+
+.tipField {
+  float: right;
+  line-height: @input-height;
+  margin-left: 5px;
+}
+
+.tipLabel {
+  font-size: 14px;
+  margin-left: 5px;
+}
+
+.fieldSep {
+  float: right;
+  line-height: @input-height;
+  margin: 0 5px;
+}
+
+.fieldButton {
+  float: right;
+  margin-left: 5px;
+  margin-right: 0;
+}
+
+.fa-plus {
+  cursor: pointer;
+}
+
+.fa-remove {
+  color: @ignite-red;
+  cursor: pointer;
+}
+
+.fa-floppy-o {
+  cursor: pointer;
+}
+
+.fa-arrow-up {
+  cursor: pointer;
+}
+
+.fa-arrow-down {
+  cursor: pointer;
+}
+
+label.required:after {
+  color: @ignite-red;
+  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
+}
+
+//  Summary page
+#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, button.ng-dirty.ng-invalid {
+  border-color: @ignite-red;
+
+  :focus {
+    border-color: @ignite-red;
+  }
+}
+
+.form-control-feedback {
+  display: inline-block;
+  color: @ignite-red;
+  right: 18px;
+  line-height: @input-height;
+  pointer-events: initial;
+}
+
+.syntaxhighlighter {
+  padding: 10px 5px;
+  border-radius: 6px;
+}
+
+.theme-line table.links-edit-small-padding:extend(.theme-line .links table all) {
+  label {
+    line-height: @input-height;
+    color: #666;
+  }
+
+  a {
+    line-height: @input-height;
+  }
+
+  input[type="checkbox"] {
+    line-height: 20px;
+    margin-right: 5px;
+  }
+
+  .checkbox label {
+    line-height: 20px;
+    vertical-align: middle;
+  }
+
+  th {
+    text-align: center;
+  }
+
+  td {
+    padding-left: 10px;
+  }
+
+  margin-top: 10px;
+}
+
+.configBox .nav > li > a {
+  padding: 5px 5px;
+}
+
+.viewedUser {
+  position: absolute;
+  width: 100%;
+  left: 0;
+
+  text-align: center;
+
+  margin-top: -15px;
+
+  background-color: #f8d5d8;
+}
+
+a {
+  cursor: pointer;
+}
+
+.st-sort-ascent:after {
+  content: '\25B2';
+}
+
+.st-sort-descent:after {
+  content: '\25BC';
+}
+
+.panel {
+  margin-bottom: 0;
+}
+
+.panel-group {
+  margin-bottom: 0;
+}
+
+.panel-group .panel + .panel {
+  margin-top: 20px;
+}
+
+.margin-top-dflt {
+  margin-top: 10px;
+}
+
+.margin-bottom-dflt {
+  margin-bottom: 10px;
+}
+
+.margin-dflt {
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+
+.padding-top-dflt {
+  padding-top: 10px;
+}
+
+.padding-bottom-dflt {
+  padding-bottom: 10px;
+}
+
+.padding-dflt {
+  padding-top: 10px;
+  padding-bottom: 10px;
+}
+
+.theme-line .panel-title h3 {
+  margin-top: 20px;
+  margin-bottom: 20px;
+}
+
+.block-callout-parent {
+  background-color: @ignite-block-callout-background;
+  overflow: hidden;
+}
+
+.block-callout {
+  background-color: @ignite-block-callout-background;
+  display: inline-block;
+  vertical-align: top;
+  width: 50%;
+
+  i {
+    padding: 10px 5px 0 10px;
+    color: @ignite-block-callout;
+  }
+
+  ul {
+    padding-left: 20px;
+    margin-bottom: 0;
+  }
+
+  p {
+    padding: 5px 0 10px 20px;
+    margin: 0;
+  }
+
+  label {
+    font-weight: bold;
+    color: @ignite-block-callout;
+  }
+}
+
+.block-callout-border {
+  border-left: 5px solid;
+  border-color: @ignite-block-callout;
+}
+
+.labelHeader {
+  font-weight: bold;
+}
+
+.ace_editor, #ace_document {
+  width: 100%;
+  height: 400px;
+}
+
+

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/admin.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/admin.js b/modules/web-control-center/src/main/js/routes/admin.js
new file mode 100644
index 0000000..5af72f7
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/admin.js
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var router = require('express').Router();
+var db = require('../db');
+
+router.get('/', function (req, res) {
+    res.render('settings/admin');
+});
+
+/**
+ * Get list of user accounts.
+ */
+router.post('/list', function (req, res) {
+    db.Account.find({}).sort('username').exec(function (err, users) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        res.json(users);
+    });
+});
+
+router.post('/remove', function (req, res) {
+    var userId = req.body.userId;
+
+    db.Account.findByIdAndRemove(userId, function (err) {
+        if (err)
+            return res.status(500).send(err);
+
+        res.sendStatus(200);
+    });
+});
+
+router.post('/save', function (req, res) {
+    var userId = req.body.userId;
+    var adminFlag = req.body.adminFlag;
+
+    db.Account.findByIdAndUpdate(userId, {admin: adminFlag}, function (err) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        res.sendStatus(200);
+    });
+});
+
+router.get('/become', function (req, res) {
+    var viewedUserId = req.query.viewedUserId;
+
+    if (!viewedUserId) {
+        req.session.viewedUser = null;
+
+        return res.redirect('/admin');
+    }
+
+    db.Account.findById(viewedUserId).exec(function (err, viewedUser) {
+        if (err)
+            return res.sendStatus(404);
+
+        req.session.viewedUser = viewedUser;
+
+        res.redirect('/');
+    })
+});
+
+module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/caches.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/caches.js b/modules/web-control-center/src/main/js/routes/caches.js
new file mode 100644
index 0000000..3fefd37
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/caches.js
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var router = require('express').Router();
+var db = require('../db');
+
+/* GET caches page. */
+router.get('/', function (req, res) {
+    res.render('configuration/caches');
+});
+
+/**
+ * Get spaces and caches accessed for user account.
+ *
+ * @param req Request.
+ * @param res Response.
+ */
+router.post('/list', function (req, res) {
+    var user_id = req.currentUserId();
+
+    // Get owned space and all accessed space.
+    db.Space.find({$or: [{owner: user_id}, {usedBy: {$elemMatch: {account: user_id}}}]}, function (err, spaces) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        var space_ids = spaces.map(function (value) {
+            return value._id;
+        });
+
+        // Get all caches for spaces.
+        db.Cache.find({space: {$in: space_ids}}).sort('name').exec(function (err, caches) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            res.json({spaces: spaces, caches: caches});
+        });
+    });
+});
+
+/**
+ * Save cache.
+ */
+router.post('/save', function (req, res) {
+    if (req.body._id)
+        db.Cache.update({_id: req.body._id}, req.body, {upsert: true}, function (err) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            res.send(req.body._id);
+        });
+    else {
+        db.Cache.findOne({name: req.body.name}, function (err, cache) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            if (cache)
+                return res.status(500).send('Cache with name: "' + cache.name + '" already exist.');
+
+            (new db.Cache(req.body)).save(function (err, cache) {
+                if (err)
+                    return res.status(500).send(err.message);
+
+                res.send(cache._id);
+            });
+        });
+    }
+});
+
+/**
+ * Remove cache by ._id.
+ */
+router.post('/remove', function (req, res) {
+    db.Cache.remove(req.body, function (err) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        res.sendStatus(200);
+    })
+});
+
+module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/clusters.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/clusters.js b/modules/web-control-center/src/main/js/routes/clusters.js
new file mode 100644
index 0000000..182130d
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/clusters.js
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var router = require('express').Router();
+var db = require('../db');
+
+/* GET clusters page. */
+router.get('/', function (req, res) {
+    res.render('configuration/clusters');
+});
+
+/**
+ * Get spaces and clusters accessed for user account.
+ *
+ * @param req Request.
+ * @param res Response.
+ */
+router.post('/list', function (req, res) {
+    var user_id = req.currentUserId();
+
+    // Get owned space and all accessed space.
+    db.Space.find({$or: [{owner: user_id}, {usedBy: {$elemMatch: {account: user_id}}}]}, function (err, spaces) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        var space_ids = spaces.map(function (value) {
+            return value._id;
+        });
+
+        db.Cache.find({space: {$in: space_ids}}, '_id name swapEnabled', function (err, caches) {
+            if (err)
+                return res.status(500).send(err);
+
+            // Get all clusters for spaces.
+            db.Cluster.find({space: {$in: space_ids}}).sort('name').exec(function (err, clusters) {
+                if (err)
+                    return res.status(500).send(err.message);
+
+                var cachesJson = caches.map(function (cache) {
+                    return {value: cache._id, label: cache.name, swapEnabled: cache.swapEnabled};
+                });
+
+                res.json({spaces: spaces, caches: cachesJson, clusters: clusters});
+            });
+        });
+    });
+});
+
+/**
+ * Save cluster.
+ */
+router.post('/save', function (req, res) {
+    if (req.body._id)
+        db.Cluster.update({_id: req.body._id}, req.body, {upsert: true}, function (err) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            res.send(req.body._id);
+        });
+    else {
+        db.Cluster.findOne({name: req.body.name}, function (err, cluster) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            if (cluster)
+                return res.status(500).send('Cluster with name: "' + cluster.name + '" already exist.');
+
+            (new db.Cluster(req.body)).save(function (err, cluster) {
+                if (err)
+                    return res.status(500).send(err.message);
+
+                res.send(cluster._id);
+            });
+        });
+    }
+});
+
+/**
+ * Remove cluster by ._id.
+ */
+router.post('/remove', function (req, res) {
+    db.Cluster.remove(req.body, function (err) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        res.sendStatus(200);
+    })
+});
+
+module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/generator/common.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/generator/common.js b/modules/web-control-center/src/main/js/routes/generator/common.js
new file mode 100644
index 0000000..dcbf156
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/generator/common.js
@@ -0,0 +1,299 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var _ = require('lodash');
+
+exports.isDefined = function (v) {
+    return !(v === undefined || v === null);
+};
+
+exports.mainComment = mainComment;
+
+function mainComment() {
+    return 'This configuration was generated by Ignite Control Center ('
+        + formatDate(new Date()) + ')';
+}
+
+function addLeadingZero(numberStr, minSize) {
+    if (typeof (numberStr) != 'string')
+        numberStr = '' + numberStr;
+
+    while (numberStr.length < minSize) {
+        numberStr = '0' + numberStr;
+    }
+
+    return numberStr;
+}
+
+exports.formatDate = formatDate;
+
+function formatDate(date) {
+    var dd = addLeadingZero(date.getDate(), 2);
+    var mm = addLeadingZero(date.getMonth() + 1, 2);
+
+    var yyyy = date.getFullYear();
+
+    return mm + '/' + dd + '/' + yyyy + ' ' + addLeadingZero(date.getHours(), 2) + ':' + addLeadingZero(date.getMinutes(), 2);
+}
+
+exports.builder = function () {
+    var res = [];
+
+    res.deep = 0;
+    res.lineStart = true;
+
+    res.append = function (s) {
+        if (this.lineStart) {
+            for (var i = 0; i < this.deep; i++)
+                this.push('    ');
+
+            this.lineStart = false;
+        }
+
+        this.push(s);
+
+        return this;
+    };
+
+    res.line = function (s) {
+        if (s)
+            this.append(s);
+
+        this.push('\n');
+        this.lineStart = true;
+
+        return this;
+    };
+
+    res.startBlock = function (s) {
+        if (s)
+            this.append(s);
+
+        this.push('\n');
+        this.lineStart = true;
+        this.deep++;
+
+        return this;
+    };
+
+    res.endBlock = function (s) {
+        this.deep--;
+
+        if (s)
+            this.append(s);
+
+        this.push('\n');
+        this.lineStart = true;
+
+        return this;
+    };
+
+    res.emptyLineIfNeeded = function () {
+        if (this.needEmptyLine) {
+            this.line();
+
+            this.needEmptyLine = false;
+
+            return true;
+        }
+
+        return false;
+    };
+
+    res.imports = {};
+
+    res.importClass = function (fullClassName) {
+        var dotIdx = fullClassName.lastIndexOf('.');
+
+        var shortName;
+
+        if (dotIdx > 0)
+            shortName = fullClassName.substr(dotIdx + 1);
+        else
+            shortName = fullClassName;
+
+        if (this.imports[shortName]) {
+            if (this.imports[shortName] != fullClassName)
+                throw "Class name conflict: " + this.imports[shortName] + ' and ' + fullClassName;
+        }
+        else {
+            this.imports[shortName] = fullClassName;
+        }
+
+        return shortName;
+    };
+
+    res.generateImports = function () {
+        var res = [];
+
+        for (var clsName in this.imports) {
+            if (this.imports.hasOwnProperty(clsName))
+                res.push('import ' + this.imports[clsName] + ';');
+        }
+
+        return res.join('\n')
+    };
+
+    return res;
+};
+
+function ClassDescriptor(className, fields) {
+    this.className = className;
+    this.fields = fields;
+}
+
+exports.evictionPolicies = {
+    'LRU': new ClassDescriptor('org.apache.ignite.cache.eviction.lru.LruEvictionPolicy',
+        {batchSize: null, maxMemorySize: null, maxSize: null}),
+    'RND': new ClassDescriptor('org.apache.ignite.cache.eviction.random.RandomEvictionPolicy', {maxSize: null}),
+    'FIFO': new ClassDescriptor('org.apache.ignite.cache.eviction.fifo.FifoEvictionPolicy',
+        {batchSize: null, maxMemorySize: null, maxSize: null}),
+    'SORTED': new ClassDescriptor('org.apache.ignite.cache.eviction.sorted.SortedEvictionPolicy',
+        {batchSize: null, maxMemorySize: null, maxSize: null})
+};
+
+exports.marshallers = {
+    OptimizedMarshaller: new ClassDescriptor('org.apache.ignite.marshaller.optimized.OptimizedMarshaller', {
+        poolSize: null,
+        requireSerializable: null
+    }),
+    JdkMarshaller: new ClassDescriptor('org.apache.ignite.marshaller.jdk.JdkMarshaller', {})
+};
+
+exports.knownClasses = {
+    Oracle: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.OracleDialect', {}),
+    DB2: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.DB2Dialect', {}),
+    SQLServer: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.SQLServerDialect', {}),
+    MySQL: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.MySQLDialect', {}),
+    PostgreSQL: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect', {}),
+    H2: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.H2Dialect', {})
+};
+
+exports.dataSources = {
+    Oracle: 'oracle.jdbc.pool.OracleDataSource',
+    DB2: 'com.ibm.db2.jcc.DB2ConnectionPoolDataSource',
+    SQLServer: 'com.microsoft.sqlserver.jdbc.SQLServerDataSource',
+    MySQL: 'com.mysql.jdbc.jdbc2.optional.MysqlDataSource',
+    PostgreSQL: 'org.postgresql.ds.PGPoolingDataSource',
+    H2: 'org.h2.jdbcx.JdbcDataSource'
+};
+
+exports.storeFactories = {
+    CacheJdbcPojoStoreFactory: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory', {
+        dataSourceBean: null,
+        dialect: {type: 'className'}
+    }),
+
+    CacheJdbcBlobStoreFactory: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.CacheJdbcBlobStoreFactory', {
+        user: null,
+        dataSourceBean: null,
+        initSchema: null,
+        createTableQuery: null,
+        loadQuery: null,
+        insertQuery: null,
+        updateQuery: null,
+        deleteQuery: null
+    }),
+
+    CacheHibernateBlobStoreFactory: new ClassDescriptor('org.apache.ignite.cache.store.hibernate.CacheHibernateBlobStoreFactory', {
+        hibernateProperties: {type: 'propertiesAsList', propVarName: 'props'}
+    })
+};
+
+exports.atomicConfiguration = new ClassDescriptor('org.apache.ignite.configuration.AtomicConfiguration', {
+    backups: null,
+    cacheMode: {type: 'enum', enumClass: 'CacheMode'},
+    atomicSequenceReserveSize: null
+});
+
+exports.swapSpaceSpi = new ClassDescriptor('org.apache.ignite.spi.swapspace.file.FileSwapSpaceSpi', {
+    baseDirectory: null,
+    readStripesNumber: null,
+    maximumSparsity: {type: 'float'},
+    maxWriteQueueSize: null,
+    writeBufferSize: null
+});
+
+exports.transactionConfiguration = new ClassDescriptor('org.apache.ignite.configuration.TransactionConfiguration', {
+    defaultTxConcurrency: {type: 'enum', enumClass: 'TransactionConcurrency'},
+    transactionIsolation: {type: 'TransactionIsolation', setterName: 'defaultTxIsolation'},
+    defaultTxTimeout: null,
+    pessimisticTxLogLinger: null,
+    pessimisticTxLogSize: null,
+    txSerializableEnabled: null
+});
+
+exports.hasProperty = function (obj, props) {
+    for (var propName in props) {
+        if (props.hasOwnProperty(propName)) {
+            if (obj[propName])
+                return true;
+        }
+    }
+
+    return false;
+};
+
+/**
+ * Convert some name to valid java name.
+ *
+ * @param name to convert.
+ * @returns {string} Valid java name.
+ */
+exports.toJavaName = function (name) {
+    var javaName = name.replace(/[^A-Za-z_0-9]+/, '_');
+
+    return javaName.charAt(0).toLocaleUpperCase() + javaName.slice(1);
+};
+
+/**
+ * Generate properties file with properties stubs for stores data sources.
+ *
+ * @param cluster Configuration to process.
+ * @returns {string} Generated content.
+ */
+exports.generateProperties = function (cluster) {
+    var res = exports.builder();
+
+    var datasources = [];
+
+    if (cluster.caches && cluster.caches.length > 0) {
+        _.forEach(cluster.caches, function (cache) {
+            if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind) {
+                var storeFactory = cache.cacheStoreFactory[cache.cacheStoreFactory.kind];
+
+                if (storeFactory.dialect) {
+                    var beanId = storeFactory.dataSourceBean;
+
+                    if (!_.contains(datasources, beanId)) {
+                        datasources.push(beanId);
+
+                        res.line(beanId + '.jdbc.url=YOUR_JDBC_URL');
+                        res.line(beanId + '.jdbc.username=YOUR_USER_NAME');
+                        res.line(beanId + '.jdbc.password=YOUR_PASSWORD');
+                        res.line();
+                    }
+                }
+            }
+        });
+    }
+
+    if (datasources.length > 0)
+        return '# ' + mainComment() + '\n\n' + res.join();
+
+    return undefined;
+};

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/generator/docker.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/generator/docker.js b/modules/web-control-center/src/main/js/routes/generator/docker.js
new file mode 100644
index 0000000..93faf8e
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/generator/docker.js
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+exports.generateClusterConfiguration = function(cluster, os) {
+    if (!os)
+        os = 'debian:8';
+
+    return "" +
+        "# Start from a OS image.\n"+
+        "FROM " + os + "\n"+
+        "\n"+
+        "# Install tools.\n"+
+        "RUN apt-get update && apt-get install -y --fix-missing \\\n"+
+        "  wget \\\n"+
+        "  dstat \\\n"+
+        "  maven \\\n"+
+        "  git\n"+
+        "\n"+
+        "# Install Oracle JDK.\n"+
+        "RUN mkdir /opt/jdk\n"+
+        "\n"+
+        "RUN wget --header \"Cookie: oraclelicense=accept-securebackup-cookie\" \\\n"+
+        "  http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.tar.gz\n"+
+        "\n"+
+        "RUN tar -zxf jdk-7u79-linux-x64.tar.gz -C /opt/jdk\n"+
+        "\n"+
+        "RUN rm jdk-7u79-linux-x64.tar.gz\n"+
+        "\n"+
+        "RUN update-alternatives --install /usr/bin/java java /opt/jdk/jdk1.7.0_79/bin/java 100\n"+
+        "\n"+
+        "RUN update-alternatives --install /usr/bin/javac javac /opt/jdk/jdk1.7.0_79/bin/javac 100\n"+
+        "\n"+
+        "# Sets java variables.\n"+
+        "ENV JAVA_HOME /opt/jdk/jdk1.7.0_79/\n"+
+        "\n"+
+        "# Create working directory\n"+
+        "WORKDIR /home\n"+
+        "\n"+
+        "RUN wget -O ignite.zip http://tiny.cc/updater/download_ignite.php && unzip ignite.zip && rm ignite.zip\n"+
+        "\n"+
+        "COPY *.xml /tmp/\n"+
+        "\n"+
+        "RUN mv /tmp/*.xml /home/$(ls)/config";
+};

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/generator/java.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/generator/java.js b/modules/web-control-center/src/main/js/routes/generator/java.js
new file mode 100644
index 0000000..31cd2ac
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/generator/java.js
@@ -0,0 +1,626 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var _ = require('lodash');
+
+var generatorUtils = require("./common");
+
+exports.generateClusterConfiguration = function(cluster, javaClass, clientNearConfiguration) {
+    var res = generatorUtils.builder();
+
+    res.datasourceBeans = [];
+
+    if (javaClass) {
+        res.line('/**');
+        res.line(' * ' + generatorUtils.mainComment());
+        res.line(' */');
+        res.startBlock('public class ConfigurationFactory {');
+        res.line('/**');
+        res.line(' * Configure grid.');
+        res.line(' */');
+        res.startBlock('public IgniteConfiguration createConfiguration() {');
+    }
+    
+    res.importClass('org.apache.ignite.configuration.IgniteConfiguration');
+    
+    res.line('IgniteConfiguration cfg = new IgniteConfiguration();');
+    res.line();
+
+    if (clientNearConfiguration) {
+        res.line('cfg.setClientMode(true);');
+
+        res.line();
+    }
+
+    if (cluster.discovery) {
+        var d = cluster.discovery;
+
+        res.importClass('org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi');
+        res.line('TcpDiscoverySpi discovery = new TcpDiscoverySpi();');
+
+        switch (d.kind) {
+            case 'Multicast':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder');
+
+                addBeanWithProperties(res, d.Multicast, 'discovery', 'ipFinder', 'ipFinder',
+                    'TcpDiscoveryMulticastIpFinder', {
+                        multicastGroup: null,
+                        multicastPort: null,
+                        responseWaitTime: null,
+                        addressRequestAttempts: null,
+                        localAddress: null
+                    }, true);
+
+                break;
+
+            case 'Vm':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder');
+
+                addBeanWithProperties(res, d.Vm, 'discovery', 'ipFinder', 'ipFinder', 'TcpDiscoveryVmIpFinder', {
+                        addresses: {type: 'list'}
+                    }, true);
+
+                break;
+
+            case 'S3':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.s3.TcpDiscoveryS3IpFinder');
+
+                if (d.S3)
+                    addBeanWithProperties(res, d.S3, 'discovery', 'ipFinder', 'ipFinder', 'TcpDiscoveryS3IpFinder',
+                        {bucketName: null}, true);
+                else
+                    res.line('discovery.setIpFinder(new TcpDiscoveryS3IpFinder());');
+
+                break;
+
+            case 'Cloud':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.cloud.TcpDiscoveryCloudIpFinder');
+
+                addBeanWithProperties(res, d.Cloud, 'discovery', 'ipFinder', 'ipFinder', 'TcpDiscoveryCloudIpFinder', {
+                        credential: null,
+                        credentialPath: null,
+                        identity: null,
+                        provider: null,
+                        regions: {type: 'list'},
+                        zones: {type: 'list'}
+                    }, true);
+
+                break;
+
+            case 'GoogleStorage':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.gce.TcpDiscoveryGoogleStorageIpFinder');
+
+                addBeanWithProperties(res, d.GoogleStorage, 'discovery', 'ipFinder', 'ipFinder',
+                    'TcpDiscoveryGoogleStorageIpFinder', {
+                        projectName: null,
+                        bucketName: null,
+                        serviceAccountP12FilePath: null
+                    }, true);
+
+                //if (d.GoogleStorage.addrReqAttempts) todo ????
+                //    res.line('<property name="serviceAccountP12FilePath" value="' + escapeAttr(d.GoogleStorage.addrReqAttempts) + '"/>');
+
+                break;
+
+            case 'Jdbc':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.jdbc.TcpDiscoveryJdbcIpFinder');
+                
+                res.line();
+                res.line('TcpDiscoveryJdbcIpFinder ipFinder = new TcpDiscoveryJdbcIpFinder();');
+                res.line('ipFinder.setInitSchema(' + (d.Jdbc.initSchema != null || d.Jdbc.initSchema) + ');');
+                res.line('discovery.setIpFinder(ipFinder);');
+                res.needEmptyLine = true;
+
+                break;
+
+            case 'SharedFs':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.sharedfs.TcpDiscoverySharedFsIpFinder');
+
+                addBeanWithProperties(res, d.SharedFs, 'discovery', 'ipFinder', 'ipFinder',
+                    'TcpDiscoverySharedFsIpFinder', {path: null}, true);
+
+                break;
+
+            default:
+                throw "Unknown discovery kind: " + d.kind;
+        }
+
+        res.emptyLineIfNeeded();
+
+        res.line('cfg.setDiscoverySpi(discovery);');
+
+        res.needEmptyLine = true;
+    }
+
+    if (cluster.caches && cluster.caches.length > 0) {
+        res.emptyLineIfNeeded();
+
+        var names = [];
+
+        for (var i = 0; i < cluster.caches.length; i++) {
+            res.emptyLineIfNeeded();
+
+            var cache = cluster.caches[i];
+
+            var cacheName = 'cache' + generatorUtils.toJavaName(cache.name);
+
+            names.push(cacheName);
+
+            generateCacheConfiguration(cache, cacheName, res);
+
+            res.needEmptyLine = true;
+        }
+
+        res.emptyLineIfNeeded();
+
+        res.append('cfg.setCacheConfiguration(');
+
+        for (i = 0; i < names.length; i++) {
+            if (i > 0)
+                res.append(', ');
+
+            res.append(names[i]);
+        }
+
+        res.line(');');
+
+        res.needEmptyLine = true;
+    }
+
+    addBeanWithProperties(res, cluster.atomicConfiguration, 'cfg', 'atomicConfiguration', 'atomicCfg',
+        generatorUtils.atomicConfiguration.className, generatorUtils.atomicConfiguration.fields);
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cluster, 'cfg', 'networkTimeout');
+    addProperty(res, cluster, 'cfg', 'networkSendRetryDelay');
+    addProperty(res, cluster, 'cfg', 'networkSendRetryCount');
+    addProperty(res, cluster, 'cfg', 'segmentCheckFrequency');
+    addProperty(res, cluster, 'cfg', 'waitForSegmentOnStart');
+    addProperty(res, cluster, 'cfg', 'discoveryStartupDelay');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cluster, 'cfg', 'deploymentMode', 'DeploymentMode');
+
+    res.needEmptyLine = true;
+
+    if (cluster.includeEventTypes && cluster.includeEventTypes.length > 0) {
+        res.emptyLineIfNeeded();
+        
+        if (cluster.includeEventTypes.length == 1) {
+            res.importClass('org.apache.ignite.events.EventType');
+            
+            res.line('cfg.setIncludeEventTypes(EventType.' + cluster.includeEventTypes[0] + ');');
+        }
+        else {
+            res.append('int[] events = new int[EventType.' + cluster.includeEventTypes[0] + '.length');
+            
+            for (i = 1; i < cluster.includeEventTypes.length; i++) {
+                res.line();
+                
+                res.append('    + EventType.' + cluster.includeEventTypes[i] + '.length');
+            }
+            
+            res.line('];');
+            res.line();
+            res.line('int k = 0;');
+
+            for (i = 0; i < cluster.includeEventTypes.length; i++) {
+                res.line();
+
+                var e = cluster.includeEventTypes[i];
+                
+                res.line('System.arraycopy(EventType.' + e + ', 0, events, k, EventType.' + e + '.length);');
+                res.line('k += EventType.' + e + '.length;');
+            }
+            
+            res.line();
+            res.line('cfg.setIncludeEventTypes(events);');
+        }
+
+        res.needEmptyLine = true;
+    }
+
+    res.needEmptyLine = true;
+
+    var marshaller = cluster.marshaller;
+
+    if (marshaller && marshaller.kind) {
+        var marshallerDesc = generatorUtils.marshallers[marshaller.kind];
+
+        addBeanWithProperties(res, marshaller[marshaller.kind], 'cfg', 'marshaller', 'marshaller',
+            marshallerDesc.className, marshallerDesc.fields, true);
+
+        addBeanWithProperties(res, marshaller[marshaller.kind], 'marshaller', marshallerDesc.className, marshallerDesc.fields, true);
+    }
+
+    addProperty(res, cluster, 'cfg', 'marshalLocalJobs');
+    addProperty(res, cluster, 'cfg', 'marshallerCacheKeepAliveTime');
+    addProperty(res, cluster, 'cfg', 'marshallerCacheThreadPoolSize');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cluster, 'cfg', 'metricsExpireTime');
+    addProperty(res, cluster, 'cfg', 'metricsHistorySize');
+    addProperty(res, cluster, 'cfg', 'metricsLogFrequency');
+    addProperty(res, cluster, 'cfg', 'metricsUpdateFrequency');
+    res.needEmptyLine = true;
+
+    addProperty(res, cluster, 'cfg', 'peerClassLoadingEnabled');
+    addMultiparamProperty(res, cluster, 'cfg', 'peerClassLoadingLocalClassPathExclude');
+    addProperty(res, cluster, 'cfg', 'peerClassLoadingMissedResourcesCacheSize');
+    addProperty(res, cluster, 'cfg', 'peerClassLoadingThreadPoolSize');
+    res.needEmptyLine = true;
+
+    if (cluster.swapSpaceSpi && cluster.swapSpaceSpi.kind == 'FileSwapSpaceSpi') {
+        addBeanWithProperties(res, cluster.swapSpaceSpi.FileSwapSpaceSpi, 'cfg', 'swapSpaceSpi', 'swapSpi',
+            generatorUtils.swapSpaceSpi.className, generatorUtils.swapSpaceSpi.fields, true);
+
+        res.needEmptyLine = true;
+    }
+
+    addProperty(res, cluster, 'cfg', 'clockSyncSamples');
+    addProperty(res, cluster, 'cfg', 'clockSyncFrequency');
+    addProperty(res, cluster, 'cfg', 'timeServerPortBase');
+    addProperty(res, cluster, 'cfg', 'timeServerPortRange');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cluster, 'cfg', 'publicThreadPoolSize');
+    addProperty(res, cluster, 'cfg', 'systemThreadPoolSize');
+    addProperty(res, cluster, 'cfg', 'managementThreadPoolSize');
+    addProperty(res, cluster, 'cfg', 'igfsThreadPoolSize');
+
+    res.needEmptyLine = true;
+
+    addBeanWithProperties(res, cluster.transactionConfiguration, 'cfg', 'transactionConfiguration',
+        'transactionConfiguration', generatorUtils.transactionConfiguration.className,
+        generatorUtils.transactionConfiguration.fields);
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cluster, 'cfg', 'cacheSanityCheckEnabled');
+
+    res.needEmptyLine = true;
+
+    if (javaClass) {
+        res.line();
+        res.line('return cfg;');
+        res.endBlock('}');
+        res.endBlock('}');
+        
+        return res.generateImports() + '\n\n' + res.join('')
+    }
+    
+    return res.join('');
+};
+
+function createEvictionPolicy(res, evictionPolicy, varName, propertyName) {
+    if (evictionPolicy && evictionPolicy.kind) {
+        var e = generatorUtils.evictionPolicies[evictionPolicy.kind];
+
+        var obj = evictionPolicy[evictionPolicy.kind.toUpperCase()];
+
+        addBeanWithProperties(res, obj, varName, propertyName, propertyName, e.className, e.fields, true);
+    }
+}
+
+exports.generateCacheConfiguration = generateCacheConfiguration;
+
+/**
+ * Generate java code for cache configuration.
+ *
+ * @param cacheCfg Cache config.
+ * @param varName Variable name.
+ * @param res Result builder.
+ * @returns {*} Append generated java code to builder and return it.
+ */
+function generateCacheConfiguration(cacheCfg, varName, res) {
+    if (!res)
+        res = generatorUtils.builder();
+
+    res.emptyLineIfNeeded();
+
+    res.importClass('org.apache.ignite.cache.CacheAtomicityMode');
+    res.importClass('org.apache.ignite.cache.CacheMode');
+    res.importClass('org.apache.ignite.configuration.CacheConfiguration');
+
+    res.line('CacheConfiguration ' + varName + ' = new CacheConfiguration();');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, varName, 'name');
+    
+    addProperty(res, cacheCfg, varName, 'mode', 'CacheMode', 'cacheMode');
+
+    addProperty(res, cacheCfg, varName, 'atomicityMode', 'CacheAtomicityMode');
+    addProperty(res, cacheCfg, varName, 'backups');
+    addProperty(res, cacheCfg, varName, 'startSize');
+    addProperty(res, cacheCfg, varName, 'readFromBackup');
+
+    res.needEmptyLine = true;
+    
+    addProperty(res, cacheCfg, varName, 'memoryMode', 'CacheMemoryMode');
+    addProperty(res, cacheCfg, varName, 'offHeapMaxMemory');
+    addProperty(res, cacheCfg, varName, 'swapEnabled');
+    addProperty(res, cacheCfg, varName, 'copyOnRead');
+
+    res.needEmptyLine = true;
+
+    createEvictionPolicy(res, cacheCfg.evictionPolicy, varName, 'evictionPolicy');
+
+    if (cacheCfg.nearCacheEnabled) {
+        res.needEmptyLine = true;
+
+        res.importClass('org.apache.ignite.configuration.NearCacheConfiguration');
+
+        addBeanWithProperties(res, cacheCfg.nearConfiguration, varName, 'nearConfiguration', 'nearConfiguration',
+            'NearCacheConfiguration', {nearStartSize: null}, true);
+
+        if (cacheCfg.nearConfiguration && cacheCfg.nearConfiguration.nearEvictionPolicy && cacheCfg.nearConfiguration.nearEvictionPolicy.kind) {
+            createEvictionPolicy(res, cacheCfg.nearConfiguration.nearEvictionPolicy, 'nearConfiguration', 'nearEvictionPolicy');
+        }
+    }
+
+    res.needEmptyLine = true;
+    
+    addProperty(res, cacheCfg, varName, 'sqlEscapeAll');
+    addProperty(res, cacheCfg, varName, 'sqlOnheapRowCacheSize');
+    addProperty(res, cacheCfg, varName, 'longQueryWarningTimeout');
+    
+    if (cacheCfg.indexedTypes && cacheCfg.indexedTypes.length > 0) {
+        res.emptyLineIfNeeded();
+        
+        res.append(varName + '.setIndexedTypes(');
+        
+        for (var i = 0; i < cacheCfg.indexedTypes.length; i++) {
+            if (i > 0)
+                res.append(', ');
+
+            var pair = cacheCfg.indexedTypes[i];
+            
+            res.append(toJavaCode(pair.keyClass, 'class')).append(', ').append(toJavaCode(pair.valueClass, 'class'))
+        }
+        
+        res.line(');');
+    }
+
+    addMultiparamProperty(res, cacheCfg, varName, 'sqlFunctionClasses', 'class');
+    
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, varName, 'rebalanceMode', 'CacheRebalanceMode');
+    addProperty(res, cacheCfg, varName, 'rebalanceThreadPoolSize');
+    addProperty(res, cacheCfg, varName, 'rebalanceBatchSize');
+    addProperty(res, cacheCfg, varName, 'rebalanceOrder');
+    addProperty(res, cacheCfg, varName, 'rebalanceDelay');
+    addProperty(res, cacheCfg, varName, 'rebalanceTimeout');
+    addProperty(res, cacheCfg, varName, 'rebalanceThrottle');
+
+    res.needEmptyLine = true;
+    
+    if (cacheCfg.cacheStoreFactory && cacheCfg.cacheStoreFactory.kind) {
+        var storeFactory = cacheCfg.cacheStoreFactory[cacheCfg.cacheStoreFactory.kind];
+        var data = generatorUtils.storeFactories[cacheCfg.cacheStoreFactory.kind];
+
+        var sfVarName = 'storeFactory' + generatorUtils.toJavaName(cacheCfg.name);
+        var dsVarName = 'none';
+
+        if (storeFactory.dialect) {
+            var dataSourceBean = storeFactory.dataSourceBean;
+
+            dsVarName = 'dataSource' + generatorUtils.toJavaName(dataSourceBean);
+
+            if (!_.contains(res.datasourceBeans, dataSourceBean)) {
+                res.datasourceBeans.push(dataSourceBean);
+
+                var dataSource = generatorUtils.dataSources[storeFactory.dialect];
+
+                res.line();
+                res.line(dataSource.className + ' ' + dsVarName + ' = new ' + dataSource.className + '();');
+                res.line(dsVarName + '.setURL(_URL_);');
+                res.line(dsVarName + '.setUsername(_User_Name_);');
+                res.line(dsVarName + '.setPassword(_Password_);');
+            }
+        }
+
+        addBeanWithProperties(res, storeFactory, varName, 'cacheStoreFactory', sfVarName, data.className,
+            data.fields, true);
+
+        if (dsVarName != 'none')
+            res.line(sfVarName + '.setDataSource(' + dsVarName + ');');
+    }
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, varName, 'loadPreviousValue');
+    addProperty(res, cacheCfg, varName, 'readThrough');
+    addProperty(res, cacheCfg, varName, 'writeThrough');
+
+    res.needEmptyLine = true;
+    
+    addProperty(res, cacheCfg, varName, 'invalidate');
+    addProperty(res, cacheCfg, varName, 'defaultLockTimeout');
+    addProperty(res, cacheCfg, varName, 'transactionManagerLookupClassName');
+    
+    res.needEmptyLine = true;
+    
+    addProperty(res, cacheCfg, varName, 'writeBehindEnabled');
+    addProperty(res, cacheCfg, varName, 'writeBehindBatchSize');
+    addProperty(res, cacheCfg, varName, 'writeBehindFlushSize');
+    addProperty(res, cacheCfg, varName, 'writeBehindFlushFrequency');
+    addProperty(res, cacheCfg, varName, 'writeBehindFlushThreadCount');
+    
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, varName, 'statisticsEnabled');
+    addProperty(res, cacheCfg, varName, 'managementEnabled');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, varName, 'maxConcurrentAsyncOperations');
+    
+    return res;
+}
+
+function toJavaCode(val, type) {
+    if (val == null)
+       return 'null';
+
+    if (type == 'float')
+        return val + 'f';
+    
+    if (type == 'class')
+        return val + '.class';
+    
+    if (type)
+        return type + '.' + val;
+    
+    if (typeof(val) == 'string')
+        return '"' + val.replace('"', '\\"') + '"';
+
+    if (typeof(val) == 'number' || typeof(val) == 'boolean')
+        return '' + val;
+
+    throw "Unknown type: " + typeof(val) + ' (' + val + ')';
+}
+
+function addProperty(res, obj, objVariableName, propName, enumType, setterName) {
+    var val = obj[propName];
+    
+    if (generatorUtils.isDefined(val)) {
+        res.emptyLineIfNeeded();
+
+        res.line(objVariableName + '.' + getSetterName(setterName ? setterName : propName)
+            + '(' + toJavaCode(val, enumType)  + ');');
+    }
+}
+
+function getSetterName(propName) {
+    return 'set' + propName.charAt(0).toLocaleUpperCase() + propName.slice(1);
+}
+
+function addListProperty(res, obj, objVariableName, propName, enumType, setterName) {
+    var val = obj[propName];
+    
+    if (val && val.length > 0) {
+        res.append(objVariableName + '.' + getSetterName(setterName ? setterName : propName) + '(Arrays.asList(');
+
+        for (var i = 0; i < val.length; i++) {
+            if (i > 0)
+                res.append(', ');
+            
+            res.append(toJavaCode(val[i], enumType));
+        }
+        
+        res.line('));');
+    }
+}
+
+function addMultiparamProperty(res, obj, objVariableName, propName, type, setterName) {
+    var val = obj[propName];
+    
+    if (val && val.length > 0) {
+        res.append(objVariableName + '.' + getSetterName(setterName ? setterName : propName) + '(');
+
+        for (var i = 0; i < val.length; i++) {
+            if (i > 0)
+                res.append(', ');
+            
+            res.append(toJavaCode(val[i], type));
+        }
+        
+        res.line(');');
+    }
+}
+
+function addBeanWithProperties(res, bean, objVarName, beanPropName, beanVarName, beanClass, props, createBeanAlthoughNoProps) {
+    if (bean && generatorUtils.hasProperty(bean, props)) {
+        if (!res.emptyLineIfNeeded()) {
+            res.line();
+        }
+        
+        res.line(beanClass + ' ' + beanVarName + ' = new ' + beanClass + '();');
+
+        for (var propName in props) {
+            if (props.hasOwnProperty(propName)) {
+                var descr = props[propName];
+
+                if (descr) {
+                    switch (descr.type) {
+                        case 'list':
+                            addListProperty(res, bean, beanVarName, propName, descr.elementsType, descr.setterName);
+                            break;
+                        
+                        case 'enum':
+                            addProperty(res, bean, beanVarName, propName, descr.enumClass, descr.setterName);
+                            break;
+                        
+                        case 'float':
+                            addProperty(res, bean, beanVarName, propName, 'float', descr.setterName);
+                            break;
+                        
+                        case 'propertiesAsList':
+                            var val = bean[propName];
+                            
+                            if (val && val.length > 0) {
+                                res.line('Properties ' + descr.propVarName + ' = new Properties();');
+                                
+                                for (var i = 0; i < val.length; i++) {
+                                    var nameAndValue = val[i];
+                                    
+                                    var eqIndex = nameAndValue.indexOf('=');
+                                    if (eqIndex >= 0) {
+                                        res.line(descr.propVarName + '.setProperty(' 
+                                            + nameAndValue.substring(0, eqIndex) + ', ' 
+                                            + nameAndValue.substr(eqIndex + 1) + ');');
+                                    }
+
+                                }
+                                
+                                res.line(beanVarName + '.' + getSetterName(propName) + '(' + descr.propVarName + ');');
+                            }
+                            break;
+                        
+                        case 'className':
+                            if (bean[propName]) {
+                                res.line(beanVarName + '.' + getSetterName(propName) + '(new ' + generatorUtils.knownClasses[bean[propName]].className + '());');
+                            }
+
+                            break;
+                        
+                        default:
+                            addProperty(res, bean, beanVarName, propName, null, descr.setterName);
+                    }
+                }
+                else {
+                    addProperty(res, bean, beanVarName, propName);
+                }
+            }
+        }
+        
+        res.line(objVarName + '.' + getSetterName(beanPropName) + '(' + beanVarName + ');');
+        
+        res.needEmptyLine = true;
+    }
+    else if (createBeanAlthoughNoProps) {
+        res.emptyLineIfNeeded();
+        
+        res.line(objVarName + '.' + getSetterName(beanPropName) + '(new ' + beanClass + '());');
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/generator/xml.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/generator/xml.js b/modules/web-control-center/src/main/js/routes/generator/xml.js
new file mode 100644
index 0000000..16ef23b
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/generator/xml.js
@@ -0,0 +1,580 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var _ = require('lodash');
+
+var generatorUtils = require("./common");
+var dataStructures = require("../../helpers/data-structures.js");
+
+exports.generateClusterConfiguration = function(cluster, clientNearConfiguration) {
+    var res = generatorUtils.builder();
+
+    res.datasources = [];
+    res.deep = 1;
+
+    if (clientNearConfiguration) {
+        res.startBlock('<bean id="nearCacheBean" class="org.apache.ignite.configuration.NearCacheConfiguration">');
+
+        if (clientNearConfiguration.nearStartSize)
+            addProperty(res, clientNearConfiguration, 'nearStartSize');
+
+        if (clientNearConfiguration.nearEvictionPolicy && clientNearConfiguration.nearEvictionPolicy.kind)
+            createEvictionPolicy(res, clientNearConfiguration.nearEvictionPolicy, 'nearEvictionPolicy');
+
+        res.endBlock('</bean>');
+
+        res.line();
+    }
+
+    // Generate Ignite Configuration.
+    res.startBlock('<bean class="org.apache.ignite.configuration.IgniteConfiguration">');
+
+    if (clientNearConfiguration) {
+        res.line('<property name="clientMode" value="true" />');
+
+        res.line();
+    }
+
+    // Generate discovery.
+    if (cluster.discovery) {
+        res.startBlock('<property name="discoverySpi">');
+        res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">');
+        res.startBlock('<property name="ipFinder">');
+
+        var d = cluster.discovery;
+
+        switch (d.kind) {
+            case 'Multicast':
+                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">');
+
+                addProperty(res, d.Multicast, 'multicastGroup');
+                addProperty(res, d.Multicast, 'multicastPort');
+                addProperty(res, d.Multicast, 'responseWaitTime');
+                addProperty(res, d.Multicast, 'addressRequestAttempts');
+                addProperty(res, d.Multicast, 'localAddress');
+
+                res.endBlock('</bean>');
+
+                break;
+
+            case 'Vm':
+                if (d.Vm.addresses.length > 0) {
+                    res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">');
+
+                    addListProperty(res, d.Vm, 'addresses');
+
+                    res.endBlock('</bean>');
+                }
+                else {
+                    res.line('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder"/>');
+                }
+
+                break;
+
+            case 'S3':
+                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.s3.TcpDiscoveryS3IpFinder">');
+
+                if (d.S3 && d.S3.bucketName)
+                    res.line('<property name="bucketName" value="' + escapeAttr(d.S3.bucketName) + '" />');
+
+                res.endBlock('</bean>');
+
+                break;
+
+            case 'Cloud':
+                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.cloud.TcpDiscoveryCloudIpFinder">');
+
+                addProperty(res, d.Cloud, 'credential');
+                addProperty(res, d.Cloud, 'credentialPath');
+                addProperty(res, d.Cloud, 'identity');
+                addProperty(res, d.Cloud, 'provider');
+                addListProperty(res, d.Cloud, 'regions');
+                addListProperty(res, d.Cloud, 'zones');
+
+                res.endBlock('</bean>');
+
+                break;
+
+            case 'GoogleStorage':
+                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.gce.TcpDiscoveryGoogleStorageIpFinder">');
+
+                addProperty(res, d.GoogleStorage, 'projectName');
+                addProperty(res, d.GoogleStorage, 'bucketName');
+                addProperty(res, d.GoogleStorage, 'serviceAccountP12FilePath');
+
+                //if (d.GoogleStorage.addrReqAttempts) todo ????
+                //    res.line('<property name="serviceAccountP12FilePath" value="' + escapeAttr(d.GoogleStorage.addrReqAttempts) + '"/>');
+
+                res.endBlock('</bean>');
+
+                break;
+
+            case 'Jdbc':
+                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.jdbc.TcpDiscoveryJdbcIpFinder">');
+                res.line('<property name="initSchema" value="' + (d.Jdbc.initSchema != null || d.Jdbc.initSchema) + '"/>');
+                res.endBlock('</bean>');
+
+                break;
+
+            case 'SharedFs':
+                if (d.SharedFs.path) {
+                    res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.sharedfs.TcpDiscoverySharedFsIpFinder">');
+                    addProperty(res, d.SharedFs, 'path');
+                    res.endBlock('</bean>');
+                }
+                else {
+                    res.line('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.sharedfs.TcpDiscoverySharedFsIpFinder"/>');
+                }
+
+                break;
+
+            default:
+                throw "Unknown discovery kind: " + d.kind;
+        }
+
+        res.endBlock('</property>');
+        res.endBlock('</bean>');
+        res.endBlock('</property>');
+
+        res.needEmptyLine = true
+    }
+
+    // Generate atomics group.
+    addBeanWithProperties(res, cluster.atomicConfiguration, 'atomicConfiguration',
+        generatorUtils.atomicConfiguration.className, generatorUtils.atomicConfiguration.fields);
+    res.needEmptyLine = true;
+
+    // Generate communication group.
+    addProperty(res, cluster, 'networkTimeout');
+    addProperty(res, cluster, 'networkSendRetryDelay');
+    addProperty(res, cluster, 'networkSendRetryCount');
+    addProperty(res, cluster, 'segmentCheckFrequency');
+    addProperty(res, cluster, 'waitForSegmentOnStart');
+    addProperty(res, cluster, 'discoveryStartupDelay');
+    res.needEmptyLine = true;
+
+    // Generate deployment group.
+    addProperty(res, cluster, 'deploymentMode');
+    res.needEmptyLine = true;
+
+    // Generate events group.
+    if (cluster.includeEventTypes && cluster.includeEventTypes.length > 0) {
+        res.emptyLineIfNeeded();
+        
+        res.startBlock('<property name="includeEventTypes">');
+        
+        if (cluster.includeEventTypes.length == 1)
+            res.line('<util:constant static-field="org.apache.ignite.events.EventType.' + cluster.includeEventTypes[0] + '"/>');
+        else {
+            res.startBlock('<array>');
+
+            for (i = 0; i < cluster.includeEventTypes.length; i++) {
+                if (i > 0)
+                    res.line();
+
+                var eventGroup = cluster.includeEventTypes[i];
+
+                res.line('<!-- EventType.' + eventGroup + ' -->');
+
+                var eventList = dataStructures.eventGroups[eventGroup];
+
+                for (var k = 0; k < eventList.length; k++) {
+                    res.line('<util:constant static-field="org.apache.ignite.events.EventType.' + eventList[k] + '"/>')
+                }
+            }
+
+            res.endBlock('</array>');
+        }
+        
+        res.endBlock('</property>');
+
+        res.needEmptyLine = true;
+    }
+
+    // Generate marshaller group.
+    var marshaller = cluster.marshaller;
+
+    if (marshaller && marshaller.kind) {
+        var marshallerDesc = generatorUtils.marshallers[marshaller.kind];
+
+        addBeanWithProperties(res, marshaller[marshaller.kind], 'marshaller', marshallerDesc.className, marshallerDesc.fields, true);
+        res.needEmptyLine = true;
+    }
+
+    addProperty(res, cluster, 'marshalLocalJobs');
+    addProperty(res, cluster, 'marshallerCacheKeepAliveTime');
+    addProperty(res, cluster, 'marshallerCacheThreadPoolSize');
+    res.needEmptyLine = true;
+
+    // Generate metrics group.
+    addProperty(res, cluster, 'metricsExpireTime');
+    addProperty(res, cluster, 'metricsHistorySize');
+    addProperty(res, cluster, 'metricsLogFrequency');
+    addProperty(res, cluster, 'metricsUpdateFrequency');
+    res.needEmptyLine = true;
+
+    // Generate PeerClassLoading group.
+    addProperty(res, cluster, 'peerClassLoadingEnabled');
+    addListProperty(res, cluster, 'peerClassLoadingLocalClassPathExclude');
+    addProperty(res, cluster, 'peerClassLoadingMissedResourcesCacheSize');
+    addProperty(res, cluster, 'peerClassLoadingThreadPoolSize');
+    res.needEmptyLine = true;
+
+    // Generate swap group.
+    if (cluster.swapSpaceSpi && cluster.swapSpaceSpi.kind == 'FileSwapSpaceSpi') {
+        addBeanWithProperties(res, cluster.swapSpaceSpi.FileSwapSpaceSpi, 'swapSpaceSpi',
+            generatorUtils.swapSpaceSpi.className, generatorUtils.swapSpaceSpi.fields, true);
+
+        res.needEmptyLine = true;
+    }
+
+    // Generate time group.
+    addProperty(res, cluster, 'clockSyncSamples');
+    addProperty(res, cluster, 'clockSyncFrequency');
+    addProperty(res, cluster, 'timeServerPortBase');
+    addProperty(res, cluster, 'timeServerPortRange');
+    res.needEmptyLine = true;
+
+    // Generate thread pools group.
+    addProperty(res, cluster, 'publicThreadPoolSize');
+    addProperty(res, cluster, 'systemThreadPoolSize');
+    addProperty(res, cluster, 'managementThreadPoolSize');
+    addProperty(res, cluster, 'igfsThreadPoolSize');
+    res.needEmptyLine = true;
+
+    // Generate transactions group.
+    addBeanWithProperties(res, cluster.transactionConfiguration, 'transactionConfiguration',
+        generatorUtils.transactionConfiguration.className, generatorUtils.transactionConfiguration.fields);
+    res.needEmptyLine = true;
+
+    // Generate caches configs.
+    if (cluster.caches && cluster.caches.length > 0) {
+        res.emptyLineIfNeeded();
+
+        res.startBlock('<property name="cacheConfiguration">');
+        res.startBlock('<list>');
+
+        for (var i = 0; i < cluster.caches.length; i++) {
+            if (i > 0)
+                res.line();
+
+            var cache = cluster.caches[i];
+
+            generateCacheConfiguration(cache, res);
+        }
+
+        res.endBlock('</list>');
+        res.endBlock('</property>');
+
+        res.needEmptyLine = true;
+    }
+
+    res.endBlock('</bean>');
+
+    // Build final XML:
+    // 1. Add header.
+    var xml = '<?xml version="1.0" encoding="UTF-8"?>\n\n';
+
+    xml += '<!-- ' + generatorUtils.mainComment() + ' -->\n';
+    xml += '<beans xmlns="http://www.springframework.org/schema/beans"\n';
+    xml += '       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n';
+    xml += '       xmlns:util="http://www.springframework.org/schema/util"\n';
+    xml += '       xsi:schemaLocation="http://www.springframework.org/schema/beans\n';
+    xml += '                           http://www.springframework.org/schema/beans/spring-beans.xsd\n';
+    xml += '                           http://www.springframework.org/schema/util\n';
+    xml += '                           http://www.springframework.org/schema/util/spring-util.xsd">\n';
+
+    // 2. Add external property file and all data sources.
+    if (res.datasources.length > 0) {
+        xml += '    <!-- Load external properties file. -->\n';
+        xml += '    <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">\n';
+        xml += '        <property name="location" value="classpath:secret.properties"/>\n';
+        xml += '    </bean>\n\n';
+
+        xml += '    <!-- Data source beans will be initialized from external properties file. -->\n';
+
+        _.forEach(res.datasources, function(item) {
+            var beanId = item.dataSourceBean;
+
+            xml += '    <bean id= "' + beanId + '" class="' + item.className + '">\n';
+            xml += '        <property name="URL" value="${' + beanId + '.jdbc.url}" />\n';
+            xml += '        <property name="user" value="${' + beanId + '.jdbc.username}" />\n';
+            xml += '        <property name="password" value="${' + beanId + '.jdbc.password}" />\n';
+            xml += '    </bean>\n\n';
+        });
+    }
+
+    // 3. Add main content.
+    xml += res.join('');
+
+    // 4. Add footer.
+    xml += '</beans>\n';
+
+    return xml;
+};
+
+function createEvictionPolicy(res, evictionPolicy, propertyName) {
+    if (evictionPolicy && evictionPolicy.kind) {
+        var e = generatorUtils.evictionPolicies[evictionPolicy.kind];
+
+        var obj = evictionPolicy[evictionPolicy.kind.toUpperCase()];
+
+        addBeanWithProperties(res, obj, propertyName, e.className, e.fields, true);
+    }
+}
+
+function generateCacheConfiguration(cacheCfg, res) {
+    if (!res)
+        res = generatorUtils.builder();
+
+    res.startBlock('<bean class="org.apache.ignite.configuration.CacheConfiguration">');
+
+    addProperty(res, cacheCfg, 'name');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'mode', 'cacheMode');
+
+    addProperty(res, cacheCfg, 'atomicityMode');
+    addProperty(res, cacheCfg, 'backups');
+    addProperty(res, cacheCfg, 'startSize');
+    addProperty(res, cacheCfg, 'readFromBackup');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'memoryMode');
+    addProperty(res, cacheCfg, 'offHeapMaxMemory');
+    addProperty(res, cacheCfg, 'swapEnabled');
+    addProperty(res, cacheCfg, 'copyOnRead');
+
+    res.needEmptyLine = true;
+
+    createEvictionPolicy(res, cacheCfg.evictionPolicy, 'evictionPolicy');
+
+    res.needEmptyLine = true;
+
+    if (cacheCfg.nearCacheEnabled) {
+        res.emptyLineIfNeeded();
+
+        res.startBlock('<property name="nearConfiguration">');
+        res.startBlock('<bean class="org.apache.ignite.configuration.NearCacheConfiguration">');
+
+        if (cacheCfg.nearConfiguration && cacheCfg.nearConfiguration.nearStartSize)
+            addProperty(res, cacheCfg.nearConfiguration, 'nearStartSize');
+
+        if (cacheCfg.nearConfiguration && cacheCfg.nearConfiguration.nearEvictionPolicy.kind)
+            createEvictionPolicy(res, cacheCfg.nearConfiguration.nearEvictionPolicy, 'nearEvictionPolicy');
+
+        res.endBlock('</bean>');
+        res.endBlock('</property>');
+    }
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'sqlEscapeAll');
+    addProperty(res, cacheCfg, 'sqlOnheapRowCacheSize');
+    addProperty(res, cacheCfg, 'longQueryWarningTimeout');
+
+    if (cacheCfg.indexedTypes && cacheCfg.indexedTypes.length > 0) {
+        res.startBlock('<property name="indexedTypes">');
+        res.startBlock('<list>');
+
+        for (var i = 0; i < cacheCfg.indexedTypes.length; i++) {
+            var pair = cacheCfg.indexedTypes[i];
+
+            res.line('<value>' + escape(pair.keyClass) + '</value>');
+            res.line('<value>' + escape(pair.valueClass) + '</value>');
+        }
+
+        res.endBlock('</list>');
+        res.endBlock('</property>');
+    }
+
+    addListProperty(res, cacheCfg, 'sqlFunctionClasses', 'array');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'rebalanceMode');
+    addProperty(res, cacheCfg, 'rebalanceThreadPoolSize');
+    addProperty(res, cacheCfg, 'rebalanceBatchSize');
+    addProperty(res, cacheCfg, 'rebalanceOrder');
+    addProperty(res, cacheCfg, 'rebalanceDelay');
+    addProperty(res, cacheCfg, 'rebalanceTimeout');
+    addProperty(res, cacheCfg, 'rebalanceThrottle');
+
+    res.needEmptyLine = true;
+
+    if (cacheCfg.cacheStoreFactory && cacheCfg.cacheStoreFactory.kind) {
+        var storeFactory = cacheCfg.cacheStoreFactory[cacheCfg.cacheStoreFactory.kind];
+        var data = generatorUtils.storeFactories[cacheCfg.cacheStoreFactory.kind];
+
+        addBeanWithProperties(res, storeFactory, 'cacheStoreFactory', data.className, data.fields, true);
+
+        if (storeFactory.dialect) {
+            if (_.findIndex(res.datasources, function (ds) {
+                    return ds.dataSourceBean == storeFactory.dataSourceBean;
+                }) < 0) {
+                res.datasources.push({
+                    dataSourceBean: storeFactory.dataSourceBean,
+                    className: generatorUtils.dataSources[storeFactory.dialect]
+                });
+            }
+        }
+    }
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'loadPreviousValue');
+    addProperty(res, cacheCfg, 'readThrough');
+    addProperty(res, cacheCfg, 'writeThrough');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'invalidate');
+    addProperty(res, cacheCfg, 'defaultLockTimeout');
+    addProperty(res, cacheCfg, 'transactionManagerLookupClassName');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'writeBehindEnabled');
+    addProperty(res, cacheCfg, 'writeBehindBatchSize');
+    addProperty(res, cacheCfg, 'writeBehindFlushSize');
+    addProperty(res, cacheCfg, 'writeBehindFlushFrequency');
+    addProperty(res, cacheCfg, 'writeBehindFlushThreadCount');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'statisticsEnabled');
+    addProperty(res, cacheCfg, 'managementEnabled');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'maxConcurrentAsyncOperations');
+    
+    res.endBlock('</bean>');
+
+    return res;
+}
+
+exports.generateCacheConfiguration = generateCacheConfiguration;
+
+function addProperty(res, obj, propName, setterName) {
+    var val = obj[propName];
+
+    if (generatorUtils.isDefined(val)) {
+        res.emptyLineIfNeeded();
+
+        res.line('<property name="' + (setterName ? setterName : propName) + '" value="' + escapeAttr(val) + '"/>');
+    }
+}
+
+function addBeanWithProperties(res, bean, beanPropName, beanClass, props, createBeanAlthoughNoProps) {
+    if (bean && generatorUtils.hasProperty(bean, props)) {
+        res.emptyLineIfNeeded();
+        res.startBlock('<property name="' + beanPropName + '">');
+        res.startBlock('<bean class="' + beanClass + '">');
+
+        for (var propName in props) {
+            if (props.hasOwnProperty(propName)) {
+                var descr = props[propName];
+
+                if (descr) {
+                    if (descr.type == 'list') {
+                        addListProperty(res, bean, propName, descr.setterName);
+                    }
+                    else if (descr.type == 'className') {
+                        if (bean[propName]) {
+                            res.startBlock('<property name="' + propName + '">');
+                            res.line('<bean class="' + generatorUtils.knownClasses[bean[propName]].className + '"/>');
+                            res.endBlock('</property>');
+                        }
+                    }
+                    else if (descr.type == 'propertiesAsList') {
+                        var val = bean[propName];
+
+                        if (val && val.length > 0) {
+                            res.startBlock('<property name="' + propName + '">');
+                            res.startBlock('<props>');
+
+                            for (var i = 0; i < val.length; i++) {
+                                var nameAndValue = val[i];
+
+                                var eqIndex = nameAndValue.indexOf('=');
+                                if (eqIndex >= 0) {
+                                    res.line('<prop key="' + escapeAttr(nameAndValue.substring(0, eqIndex)) + '">' +
+                                            + escape(nameAndValue.substr(eqIndex + 1)) + '</prop>');
+                                }
+                            }
+
+                            res.endBlock('</props>');
+                            res.endBlock('</property>');
+                        }
+                    }
+                    else
+                        addProperty(res, bean, propName, descr.setterName);
+                }
+                else
+                    addProperty(res, bean, propName);
+            }
+        }
+
+        res.endBlock('</bean>');
+        res.endBlock('</property>');
+    }
+    else if (createBeanAlthoughNoProps) {
+        res.emptyLineIfNeeded();
+        res.line('<property name="' + beanPropName + '">');
+        res.line('    <bean class="' + beanClass + '"/>');
+        res.line('</property>');
+    }
+}
+function addListProperty(res, obj, propName, listType, rowFactory) {
+    var val = obj[propName];
+
+    if (val && val.length > 0) {
+        res.emptyLineIfNeeded();
+
+        if (!listType)
+            listType = 'list';
+
+        if (!rowFactory)
+            rowFactory = function(val) { return '<value>' + escape(val) + '</value>' };
+
+        res.startBlock('<property name="' + propName + '">');
+        res.startBlock('<' + listType + '>');
+
+        for (var i = 0; i < val.length; i++)
+            res.line(rowFactory(val[i]));
+
+        res.endBlock('</' + listType + '>');
+        res.endBlock('</property>');
+    }
+}
+
+function escapeAttr(s) {
+    if (typeof(s) != 'string')
+        return s;
+
+    return s.replace(/&/g, '&amp;').replace(/"/g, '&quot;');
+}
+
+function escape(s) {
+    if (typeof(s) != 'string')
+        return s;
+
+    return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+}



[49/50] [abbrv] incubator-ignite git commit: #ignite-1121 Merged with ignite-843

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/test/js/routes/agent.js
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/test/js/routes/agent.js
index 0000000,0000000..6a7fa2c
new file mode 100644
--- /dev/null
+++ b/modules/web-control-center/src/test/js/routes/agent.js
@@@ -1,0 -1,0 +1,94 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License.  You may obtain a copy of the License at
++ *
++ *      http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++var request = require('supertest'),
++    should = require('should'),
++    app = require('../../app'),
++    fs = require('fs'),
++    https = require('https'),
++    config = require('../../helpers/configuration-loader.js'),
++    agentManager = require('../../agents/agent-manager');
++
++/**
++ * Create HTTP server.
++ */
++/**
++ * Start agent server.
++ */
++var agentServer = https.createServer({
++    key: fs.readFileSync(config.get('monitor:server:key')),
++    cert: fs.readFileSync(config.get('monitor:server:cert')),
++    passphrase: config.get('monitor:server:keyPassphrase')
++});
++
++agentServer.listen(config.get('monitor:server:port'));
++
++agentManager.createManager(agentServer);
++
++describe('request from agent', function() {
++    var agent = request.agent(app);
++
++    before(function (done) {
++        this.timeout(10000);
++
++        agent
++            .post('/login')
++            .send({email: 'anovikov@gridgain.com', password: 'extHB2aXgb'})
++            .expect(302)
++            .end(function (err) {
++                if (err)
++                    throw err;
++
++                setTimeout(done, 5000);
++            });
++    });
++
++    it('should return topology snapshot', function(done){
++        agent
++            .post('/agent/topology')
++            .send({})
++            .end(function(err, nodes) {
++                if (err) {
++                    console.log(err.response.text);
++
++                    throw err;
++                }
++
++                console.log(nodes);
++
++                done();
++            });
++    });
++
++    //it('should query result', function(done){
++    //    agent
++    //        .post('/agent/query')
++    //        .send({
++    //            username: 'nva',
++    //            password: 'nva.141',
++    //            host: 'localhost',
++    //            port: '5432',
++    //            dbName: 'ggmonitor'
++    //        })
++    //        .end(function(err, res) {
++    //            if (err)
++    //                throw err;
++    //
++    //            done();
++    //        });
++    //});
++});


[26/50] [abbrv] incubator-ignite git commit: # ignite-843 revert

Posted by an...@apache.org.
# ignite-843 revert


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

Branch: refs/heads/ignite-1121
Commit: fe13f0282e33a8bb701f38f40022ec105d48c644
Parents: 66e7328
Author: Andrey <an...@gridgain.com>
Authored: Wed Jul 22 09:23:54 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Wed Jul 22 09:23:54 2015 +0700

----------------------------------------------------------------------
 .../nodejs/views/includes/controls.jade            | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/fe13f028/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 0725749..0ed22b6 100644
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ b/modules/web-control-center/nodejs/views/includes/controls.jade
@@ -54,14 +54,14 @@ mixin table-pair-edit(keyModel, valModel, keyPlaceholder, valPlaceholder)
         input.form-control(type='text' ng-model=keyModel placeholder=keyPlaceholder)
 
 mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
-    .col-sm-12
+    .col-sm-6
         label.table-header #{header}:
         +tipLabel('field.tip')
         button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-    table.panel-details.links-edit.col-sm-12(st-table=tblMdl)
+    table.links-edit.col-sm-12(st-table=tblMdl)
         tbody
             tr.col-sm-12(ng-repeat='item in #{tblMdl}')
-                td.col-sm-12
+                td.col-sm-6
                     div(ng-show='!tableEditing(field, $index)')
                         a.labelFormField(ng-click='curPair = tableStartEdit(backupItem, field, $index); curKey = curPair.#{keyFld}; curValue = curPair.#{valFld}') {{$index + 1}}) {{item.#{keyFld}}} / {{item.#{valFld}}}
                         +btn-remove('tableRemove(backupItem, field, $index)')
@@ -70,7 +70,7 @@ mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
                         +btn-save('tablePairSaveVisible(curKey, curValue)', 'tablePairSave(tablePairValid, backupItem, field, curKey, curValue, $index)')
                         +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder)
             tr.col-sm-12(ng-show='tableNewItemActive(field)')
-                td.col-sm-12
+                td.col-sm-6
                     +btn-save('tablePairSaveVisible(newKey, newValue)', 'tablePairSave(tablePairValid, backupItem, field, newKey, newValue, -1)')
                     +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder)
 
@@ -251,9 +251,9 @@ mixin form-row-custom(lblClasses, fieldClasses)
                             +btn-save('tableSimpleSaveVisible(newValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)')
                             .input-tip
                                 input.form-control(type='text' ng-model='newValue' placeholder='{{field.placeholder}}')
-        .col-sm-6(ng-switch-when='indexedTypes')
+        div(ng-switch-when='indexedTypes')
             +table-pair('Index key-value type pairs', fieldMdl, 'keyClass', 'valueClass', 'Key class full name', 'Value class full name')
-        .col-sm-6(ng-switch-when='queryFields' ng-hide=fieldHide)
+        div(ng-switch-when='queryFields' ng-hide=fieldHide)
             +table-pair('{{field.label}}', fieldMdl, 'name', 'className', 'Field name', 'Field class full name')
         div(ng-switch-when='dbFields' ng-hide=fieldHide)
             .col-sm-6
@@ -313,7 +313,4 @@ mixin form-row-custom(lblClasses, fieldClasses)
                         td.col-sm-6
                             +btn-save('tableGroupSaveVisible(newGroupName)', 'tableGroupSave(newGroupName, -1)')
                             .input-tip
-                                input.form-control(type='text' ng-model='newGroupName' placeholder='Group name')
-
-
-
+                                input.form-control(type='text' ng-model='newGroupName' placeholder='Group name')
\ No newline at end of file


[23/50] [abbrv] incubator-ignite git commit: # ignite-843 Fixed admin page

Posted by an...@apache.org.
# ignite-843 Fixed admin page


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

Branch: refs/heads/ignite-1121
Commit: 6ed40f83d42ccc80105f2884f8b7faf512bdbc8d
Parents: 56db3f3
Author: Andrey <an...@gridgain.com>
Authored: Tue Jul 21 17:32:20 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Tue Jul 21 17:32:20 2015 +0700

----------------------------------------------------------------------
 .../nodejs/public/stylesheets/style.less            | 16 +++++++++++++++-
 .../nodejs/views/settings/admin.jade                |  9 +++++++--
 2 files changed, 22 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/6ed40f83/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 495567c..f2cb9bc 100644
--- a/modules/web-control-center/nodejs/public/stylesheets/style.less
+++ b/modules/web-control-center/nodejs/public/stylesheets/style.less
@@ -243,7 +243,6 @@
 
   li a:hover {
     color: @ignite-red;
-    //background-color: transparent;
   }
 
   .active {
@@ -793,6 +792,21 @@ button .caret, .btn .caret {
       padding: 0;
     }
   }
+
+  tfoot > tr > td {
+    padding: 0;
+
+    .pagination {
+      margin: 0.65em 0;
+
+      > .active > a {
+        color: @ignite-red;
+        font-weight: bold;
+        border-color: #ddd;
+        background-color: #eee;
+      }
+    }
+  }
 }
 
 .panel-title a {

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/6ed40f83/modules/web-control-center/nodejs/views/settings/admin.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/settings/admin.jade b/modules/web-control-center/nodejs/views/settings/admin.jade
index f8ced1c..fb0c0d1 100644
--- a/modules/web-control-center/nodejs/views/settings/admin.jade
+++ b/modules/web-control-center/nodejs/views/settings/admin.jade
@@ -47,7 +47,12 @@ block container
                                 input(type='checkbox' ng-disabled='row.adminChanging || row._id == user._id'
                                     ng-model='row.admin' ng-change='toggleAdmin(row)')
                             td(style='text-align: center;')
-                                a(ng-click='removeUser(row)' ng-show='row._id != user._id' title='Remove user')
+                                a(ng-click='removeUser(row)' ng-show='row._id != user._id' bs-tooltip data-title='Remove user')
                                     i.fa.fa-remove
-                                a(style='margin-left: 5px' ng-href='admin/become?viewedUserId={{row._id}}' ng-show='row._id != user._id' title='Become this user')
+                                a(style='margin-left: 5px' ng-href='admin/become?viewedUserId={{row._id}}' ng-show='row._id != user._id' bs-tooltip data-title='Become this user')
                                     i.fa.fa-eye
+                    tfoot
+                        tr
+                            td(colspan='5' class="text-right")
+                                div(st-pagination st-items-by-page='15' st-displayed-pages='5')
+


[18/50] [abbrv] incubator-ignite git commit: IGNITE-843 Added check for group item name.

Posted by an...@apache.org.
IGNITE-843 Added check for group item name.


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

Branch: refs/heads/ignite-1121
Commit: 2030dfb8fea41ae8efc38561f6c3bd961dcaa823
Parents: 576c87d
Author: AKuznetsov <ak...@gridgain.com>
Authored: Tue Jul 21 13:33:37 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Tue Jul 21 13:33:37 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/metadata-controller.js   | 55 ++++++++++++++------
 1 file changed, 40 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2030dfb8/modules/web-control-center/nodejs/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/metadata-controller.js b/modules/web-control-center/nodejs/controllers/metadata-controller.js
index f577dea..bf08194 100644
--- a/modules/web-control-center/nodejs/controllers/metadata-controller.js
+++ b/modules/web-control-center/nodejs/controllers/metadata-controller.js
@@ -506,7 +506,7 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
 
             if ($common.isDefined(groups)) {
                 var idx = _.findIndex(groups, function (group) {
-                    return group.name == groupName
+                    return group.name == groupName;
                 });
 
                 // Found itself.
@@ -576,25 +576,50 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             return $common.isNonEmpty(fieldName) && $common.isNonEmpty(className);
         };
 
-        $scope.tableGroupItemSave = function (fieldName, className, direction, groupIndex, index) {
-            $table.tableReset();
+        function tableGroupItemValid(fieldName, groupIndex, index) {
+            var groupItems = $scope.backupItem.groups[groupIndex].fields;
 
-            var group = $scope.backupItem.groups[groupIndex];
+            if ($common.isDefined(groupItems)) {
+                var idx = _.findIndex(groupItems, function (groupItem) {
+                    return groupItem.name == fieldName;
+                });
 
-            if (index < 0) {
-                var newGroupItem = {name: fieldName, className: className, direction: direction};
+                // Found itself.
+                if (index >= 0 && index == idx)
+                    return true;
 
-                if (group.fields)
-                    group.fields.push(newGroupItem);
-                else
-                    group.fields = [newGroupItem];
+                // Found duplicate.
+                if (idx >= 0) {
+                    $common.showError('Field with such name already exists in group!');
+
+                    return false;
+                }
             }
-            else {
-                var groupItem = group.fields[index];
 
-                groupItem.name = fieldName;
-                groupItem.className = className;
-                groupItem.direction = direction;
+            return true;
+        }
+
+        $scope.tableGroupItemSave = function (fieldName, className, direction, groupIndex, index) {
+            if (tableGroupItemValid(fieldName, groupIndex, index)) {
+                $table.tableReset();
+
+                var group = $scope.backupItem.groups[groupIndex];
+
+                if (index < 0) {
+                    var newGroupItem = {name: fieldName, className: className, direction: direction};
+
+                    if (group.fields)
+                        group.fields.push(newGroupItem);
+                    else
+                        group.fields = [newGroupItem];
+                }
+                else {
+                    var groupItem = group.fields[index];
+
+                    groupItem.name = fieldName;
+                    groupItem.className = className;
+                    groupItem.direction = direction;
+                }
             }
         };
 


[14/50] [abbrv] incubator-ignite git commit: Merge branch 'ignite-843' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-1121

Posted by an...@apache.org.
Merge branch 'ignite-843' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-1121


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

Branch: refs/heads/ignite-1121
Commit: 573dd093127ff8d8060ea5bf9c3206e81b391fc5
Parents: 4bc8237 a4ca8b7
Author: Andrey <an...@gridgain.com>
Authored: Tue Jul 21 10:38:00 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Tue Jul 21 10:38:00 2015 +0700

----------------------------------------------------------------------
 .../nodejs/public/stylesheets/style.less        | 42 +++-------------
 .../nodejs/views/includes/controls.jade         | 50 ++++++++------------
 2 files changed, 26 insertions(+), 66 deletions(-)
----------------------------------------------------------------------



[27/50] [abbrv] incubator-ignite git commit: IGNITE-843 Fix for add button on metadata screen.

Posted by an...@apache.org.
IGNITE-843 Fix for add button on metadata screen.


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

Branch: refs/heads/ignite-1121
Commit: 74c1a5f4adec96baa288fb15b8bc2540bd8744df
Parents: 66e7328
Author: AKuznetsov <ak...@gridgain.com>
Authored: Wed Jul 22 09:24:54 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Wed Jul 22 09:24:54 2015 +0700

----------------------------------------------------------------------
 .../web-control-center/nodejs/views/configuration/metadata.jade   | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/74c1a5f4/modules/web-control-center/nodejs/views/configuration/metadata.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/metadata.jade b/modules/web-control-center/nodejs/views/configuration/metadata.jade
index 5dd4841..0a601d8 100644
--- a/modules/web-control-center/nodejs/views/configuration/metadata.jade
+++ b/modules/web-control-center/nodejs/views/configuration/metadata.jade
@@ -34,12 +34,13 @@ block content
                     tr(ng-repeat='row in metadatas track by row._id')
                         td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
                             a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
+        div
             button.btn.btn-primary(ng-click='panels.activePanel = [0]; createItem()') &nbspAdd metadata
             label(style='margin-left: 6px; margin-right: 10px') For:
             button.btn.btn-default(ng-model='template' data-template='/select' data-placeholder='Choose metadata type' bs-options='item.value as item.label for item in templates' bs-select)
             i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')
             hr
-        .panel-group(bs-collapse ng-model="panels.activePanel" data-allow-multiple="false")
+        .panel-group(bs-collapse ng-model='panels.activePanel' data-allow-multiple="false")
             .panel.panel-default
                 .panel-heading
                     h3


[50/50] [abbrv] incubator-ignite git commit: #ignite-1121 Merged with ignite-843

Posted by an...@apache.org.
#ignite-1121 Merged with ignite-843


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

Branch: refs/heads/ignite-1121
Commit: a45a700c63b70c075df494fd080e668803387c32
Parents: 71b313c 14fa6f6
Author: Andrey <an...@gridgain.com>
Authored: Thu Jul 23 15:41:20 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Thu Jul 23 15:41:20 2015 +0700

----------------------------------------------------------------------
 modules/web-control-center/nodejs/.gitignore    |    4 -
 modules/web-control-center/nodejs/DEVNOTES.txt  |   21 -
 .../nodejs/agents/agent-manager.js              |  283 -----
 .../nodejs/agents/agent-server.js               |   90 --
 modules/web-control-center/nodejs/app.js        |  156 ---
 modules/web-control-center/nodejs/bin/www       |  110 --
 .../nodejs/config/default.json                  |   17 -
 .../nodejs/controllers/admin-controller.js      |   68 -
 .../nodejs/controllers/caches-controller.js     |  333 -----
 .../nodejs/controllers/clusters-controller.js   |  309 -----
 .../nodejs/controllers/common-module.js         |  422 -------
 .../nodejs/controllers/metadata-controller.js   |  678 ----------
 .../nodejs/controllers/models/caches.json       |  905 -------------
 .../nodejs/controllers/models/clusters.json     |  896 -------------
 .../nodejs/controllers/models/metadata.json     |  218 ----
 .../nodejs/controllers/models/sql.json          |    5 -
 .../nodejs/controllers/models/summary.json      |  150 ---
 .../nodejs/controllers/profile-controller.js    |   51 -
 .../nodejs/controllers/sql-controller.js        |   60 -
 .../nodejs/controllers/summary-controller.js    |  171 ---
 modules/web-control-center/nodejs/db.js         |  358 ------
 .../nodejs/helpers/configuration-loader.js      |   22 -
 .../nodejs/helpers/data-structures.js           |   84 --
 modules/web-control-center/nodejs/keys/test.crt |   13 -
 modules/web-control-center/nodejs/keys/test.key |   18 -
 modules/web-control-center/nodejs/package.json  |   51 -
 .../nodejs/public/favicon.ico                   |  Bin 1150 -> 0 bytes
 .../nodejs/public/images/docker.png             |  Bin 994 -> 0 bytes
 .../nodejs/public/images/java.png               |  Bin 170 -> 0 bytes
 .../nodejs/public/images/logo.png               |  Bin 8148 -> 0 bytes
 .../nodejs/public/images/xml.png                |  Bin 232 -> 0 bytes
 .../nodejs/public/stylesheets/style.less        | 1125 -----------------
 .../web-control-center/nodejs/routes/admin.js   |   79 --
 .../web-control-center/nodejs/routes/agent.js   |   37 -
 .../web-control-center/nodejs/routes/caches.js  |   95 --
 .../nodejs/routes/clusters.js                   |  104 --
 .../nodejs/routes/generator/common.js           |  299 -----
 .../nodejs/routes/generator/docker.js           |   58 -
 .../nodejs/routes/generator/java.js             |  626 ---------
 .../nodejs/routes/generator/xml.js              |  580 ---------
 .../nodejs/routes/metadata.js                   |   95 --
 .../web-control-center/nodejs/routes/profile.js |   97 --
 .../web-control-center/nodejs/routes/public.js  |  123 --
 modules/web-control-center/nodejs/routes/sql.js |   24 -
 .../web-control-center/nodejs/routes/summary.js |  108 --
 .../nodejs/tests/routes/agent.js                |   94 --
 .../nodejs/views/configuration/caches.jade      |   70 -
 .../nodejs/views/configuration/clusters.jade    |   73 --
 .../nodejs/views/configuration/metadata.jade    |  120 --
 .../nodejs/views/configuration/sidebar.jade     |   39 -
 .../nodejs/views/configuration/summary.jade     |  115 --
 .../web-control-center/nodejs/views/error.jade  |   22 -
 .../nodejs/views/includes/controls.jade         |  316 -----
 .../nodejs/views/includes/footer.jade           |   22 -
 .../nodejs/views/includes/header.jade           |   39 -
 .../web-control-center/nodejs/views/index.jade  |   30 -
 .../web-control-center/nodejs/views/login.jade  |   55 -
 .../nodejs/views/settings/admin.jade            |   58 -
 .../nodejs/views/settings/profile.jade          |   58 -
 .../nodejs/views/sql/sql.jade                   |   70 -
 .../nodejs/views/templates/confirm.jade         |   27 -
 .../nodejs/views/templates/layout.jade          |   61 -
 .../nodejs/views/templates/saveAs.jade          |   31 -
 .../nodejs/views/templates/select.jade          |   26 -
 .../web-control-center/src/main/js/.gitignore   |    4 +
 .../web-control-center/src/main/js/DEVNOTES.txt |   21 +
 .../src/main/js/agents/agent-manager.js         |  283 +++++
 .../src/main/js/agents/agent-server.js          |   90 ++
 modules/web-control-center/src/main/js/app.js   |  156 +++
 modules/web-control-center/src/main/js/bin/www  |  110 ++
 .../src/main/js/config/default.json             |   17 +
 .../src/main/js/controllers/admin-controller.js |   68 +
 .../js/controllers/cache-viewer-controller.js   |   77 ++
 .../main/js/controllers/caches-controller.js    |  333 +++++
 .../main/js/controllers/clusters-controller.js  |  309 +++++
 .../src/main/js/controllers/common-module.js    |  422 +++++++
 .../main/js/controllers/metadata-controller.js  |  680 ++++++++++
 .../src/main/js/controllers/models/caches.json  |  918 ++++++++++++++
 .../main/js/controllers/models/clusters.json    |  907 +++++++++++++
 .../main/js/controllers/models/metadata.json    |  230 ++++
 .../src/main/js/controllers/models/sql.json     |    5 +
 .../src/main/js/controllers/models/summary.json |  163 +++
 .../main/js/controllers/profile-controller.js   |   51 +
 .../src/main/js/controllers/sql-controller.js   |   60 +
 .../main/js/controllers/summary-controller.js   |  170 +++
 modules/web-control-center/src/main/js/db.js    |  358 ++++++
 .../src/main/js/helpers/configuration-loader.js |   22 +
 .../src/main/js/helpers/data-structures.js      |   84 ++
 .../src/main/js/keys/test.crt                   |   13 +
 .../src/main/js/keys/test.key                   |   18 +
 .../web-control-center/src/main/js/package.json |   51 +
 .../src/main/js/public/favicon.ico              |  Bin 0 -> 1150 bytes
 .../src/main/js/public/images/docker.png        |  Bin 0 -> 994 bytes
 .../src/main/js/public/images/java.png          |  Bin 0 -> 170 bytes
 .../src/main/js/public/images/logo.png          |  Bin 0 -> 8148 bytes
 .../src/main/js/public/images/xml.png           |  Bin 0 -> 232 bytes
 .../src/main/js/public/stylesheets/style.less   | 1193 ++++++++++++++++++
 .../src/main/js/routes/admin.js                 |   79 ++
 .../src/main/js/routes/agent.js                 |   37 +
 .../src/main/js/routes/caches.js                |   95 ++
 .../src/main/js/routes/clusters.js              |  104 ++
 .../src/main/js/routes/generator/common.js      |  299 +++++
 .../src/main/js/routes/generator/docker.js      |   58 +
 .../src/main/js/routes/generator/java.js        |  626 +++++++++
 .../src/main/js/routes/generator/xml.js         |  580 +++++++++
 .../src/main/js/routes/metadata.js              |   95 ++
 .../src/main/js/routes/profile.js               |   97 ++
 .../src/main/js/routes/public.js                |  123 ++
 .../src/main/js/routes/sql.js                   |   24 +
 .../src/main/js/routes/summary.js               |  108 ++
 .../src/main/js/views/configuration/caches.jade |   74 ++
 .../main/js/views/configuration/clusters.jade   |   77 ++
 .../main/js/views/configuration/metadata.jade   |  121 ++
 .../main/js/views/configuration/sidebar.jade    |   39 +
 .../main/js/views/configuration/summary.jade    |  115 ++
 .../src/main/js/views/error.jade                |   22 +
 .../src/main/js/views/includes/controls.jade    |  336 +++++
 .../src/main/js/views/includes/footer.jade      |   22 +
 .../src/main/js/views/includes/header.jade      |   39 +
 .../src/main/js/views/index.jade                |   30 +
 .../src/main/js/views/login.jade                |   55 +
 .../src/main/js/views/settings/admin.jade       |   58 +
 .../src/main/js/views/settings/profile.jade     |   58 +
 .../src/main/js/views/sql.jade                  |   70 +
 .../src/main/js/views/templates/confirm.jade    |   27 +
 .../src/main/js/views/templates/copy.jade       |   31 +
 .../src/main/js/views/templates/layout.jade     |   61 +
 .../src/main/js/views/templates/select.jade     |   26 +
 .../src/main/js/views/templates/tab.jade        |    3 +
 .../src/test/js/routes/agent.js                 |   94 ++
 130 files changed, 10496 insertions(+), 10269 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/agents/agent-manager.js
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/agents/agent-manager.js
index 0000000,0000000..252b984
new file mode 100644
--- /dev/null
+++ b/modules/web-control-center/src/main/js/agents/agent-manager.js
@@@ -1,0 -1,0 +1,283 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License.  You may obtain a copy of the License at
++ *
++ *      http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++var WebSocketServer = require('ws').Server;
++
++var ignite = require('apache-ignite');
++
++var db = require('../db');
++
++var AgentServer = require('./agent-server').AgentServer;
++
++/**
++ * @constructor
++ */
++function AgentManager(srv) {
++    this._clients = {};
++
++    this._server = srv;
++
++    this._wss = new WebSocketServer({ server: this._server });
++
++    var self = this;
++
++    this._wss.on('connection', function(ws) {
++        var client = new Client(ws, self);
++    });
++}
++
++/**
++ * @param userId
++ * @param {Client} client
++ */
++AgentManager.prototype._removeClient = function(userId, client) {
++    var connections = this._clients[userId];
++
++    if (connections) {
++        removeFromArray(connections, client);
++
++        if (connections.length == 0)
++            delete this._clients[userId];
++    }
++};
++
++/**
++ * @param userId
++ * @param {Client} client
++ */
++AgentManager.prototype._addClient = function(userId, client) {
++    var existingConnections = this._clients[userId];
++
++    if (!existingConnections) {
++        existingConnections = [];
++
++        this._clients[userId] = existingConnections;
++    }
++
++    existingConnections.push(client);
++};
++
++/**
++ * @param userId
++ * @return {Client}
++ */
++AgentManager.prototype.findClient = function(userId) {
++    var clientsList = this._clients[userId];
++
++    if (!clientsList)
++        return null;
++
++    return clientsList[0];
++};
++
++/**
++ * For tests only!!!
++ * @return {Client}
++ */
++AgentManager.prototype.getOneClient = function() {
++    for (var userId in this._clients) {
++        if (this._clients.hasOwnProperty(userId)) {
++            var m = this._clients[userId];
++
++            if (m.length > 0)
++                return m[0];
++        }
++    }
++
++    return null;
++};
++
++
++/**
++ * @constructor
++ * @param {AgentManager} manager
++ * @param {WebSocket} ws
++ */
++function Client(ws, manager) {
++    var self = this;
++
++    this._manager = manager;
++    this._ws = ws;
++
++    ws.on('close', function() {
++        if (self.user) {
++            self._manager._removeClient(self.user._id, self);
++        }
++    });
++
++    ws.on('message', function (msg) {
++        self._handleMessage(JSON.parse(msg))
++    });
++
++    this._restCounter = 0;
++
++    this._cbMap = {};
++}
++
++/**
++ * @param {String|Object} msg
++ * @param {Function} cb
++ */
++Client.prototype.sendMessage = function(msg, cb) {
++    if (typeof msg == 'object') {
++        msg = JSON.stringify(msg);
++    }
++
++    this._ws.send(msg, cb);
++};
++
++/**
++ * @param {String} path
++ * @param {Object} params
++ * @param {Function} cb
++ * @param {String} method
++ * @param {String} body
++ * @param {Object} headers
++ */
++Client.prototype.invokeRest = function(path, params, cb, method, body, headers) {
++    var self = this;
++
++    if (typeof(params) != 'object')
++        throw "'params' argument must be an object";
++
++    if (typeof(cb) != 'function')
++        throw "callback must be a function";
++
++    if (body && typeof(body) != 'string')
++        throw "body must be a string";
++
++    if (headers && typeof(headers) != 'object')
++        throw "headers must be an object";
++
++    if (!method)
++        method = 'GET';
++    else
++        method = method.toUpperCase();
++
++    if (method != 'GET' && method != 'POST')
++        throw "Unknown HTTP method: " + method;
++
++    var reqId = this._restCounter++;
++
++    this._cbMap[reqId] = cb;
++
++    this.sendMessage({
++        id: reqId,
++        type: 'RestRequest',
++        method: method,
++        params: params,
++        path: path,
++        body: body,
++        headers: headers
++    }, function(err) {
++        if (err) {
++            delete self._cbMap[reqId];
++
++            cb(err)
++        }
++    })
++};
++
++/**
++ * @param {Object} msg
++ */
++Client.prototype._handleMessage = function(msg) {
++    var self = this;
++
++    switch (msg.type) {
++        case 'AuthMessage':
++            var account = db.Account.findByUsername(msg.login, function(err, account) {
++                if (err) {
++                    ws.send("{type: 'AuthResult', success: false}");
++                }
++                else {
++                    account.authenticate(msg.password, function(err, user, res) {
++                        if (!user) {
++                            self._ws.send(JSON.stringify({type: 'AuthResult', success: false, message: res.message}));
++                        }
++                        else {
++                            self._ws.send("{type: 'AuthResult', success: true}");
++
++                            self._user = account;
++
++                            self._manager._addClient(account._id, self);
++
++                            self._ignite = new ignite.Ignite(new AgentServer(self));
++                        }
++                    });
++                }
++            });
++
++            break;
++
++        case 'RestResult':
++            var cb = this._cbMap[msg.requestId];
++
++            if (!cb)
++                break;
++
++            delete this._cbMap[msg.requestId];
++
++            if (!msg.executed) {
++                cb(msg.message)
++            }
++            else {
++                cb(null, msg.code, msg.message)
++            }
++
++            break;
++
++        default:
++            this._ws.close()
++    }
++};
++
++/**
++ * @return {Ignite}
++ */
++Client.prototype.ignite = function() {
++    return this._ignite;
++};
++
++function removeFromArray(arr, val) {
++    var idx;
++
++    while ((idx = arr.indexOf(val)) !== -1) {
++        arr.splice(idx, 1);
++    }
++}
++
++exports.AgentManager = AgentManager;
++
++/**
++ * @type {AgentManager}
++ */
++var manager = null;
++
++exports.createManager = function(srv) {
++    if (manager)
++        throw "Agent manager already cleared!";
++
++    manager = new AgentManager(srv);
++};
++
++/**
++ * @return {AgentManager}
++ */
++exports.getAgentManager = function() {
++    return manager;
++};

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/agents/agent-server.js
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/agents/agent-server.js
index 0000000,0000000..31dee5a
new file mode 100644
--- /dev/null
+++ b/modules/web-control-center/src/main/js/agents/agent-server.js
@@@ -1,0 -1,0 +1,90 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License.  You may obtain a copy of the License at
++ *
++ *      http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++/**
++ * Creates an instance of server for Ignite
++ *
++ * @constructor
++ * @this {AgentServer}
++ * @param {Client} client connected client
++ */
++function AgentServer(client) {
++    this._client = client;
++}
++
++/**
++ * Run http request
++ *
++ * @this {AgentServer}
++ * @param {Command} cmd Command
++ * @param {callback} callback on finish
++ */
++AgentServer.prototype.runCommand = function(cmd, callback) {
++    var params = {cmd: cmd.name()};
++
++    for (var p of cmd._params) {
++        params[p.key] = p.value;
++    }
++
++    var body = undefined;
++
++    var headers = undefined;
++
++    if (cmd._isPost()) {
++        body = cmd.postData();
++
++        headers = {'Content-Length': body.length, 'JSONObject': 'application/json'};
++    }
++
++    this._client.invokeRest("ignite", params, function(error, code, message) {
++        if (error) {
++            callback(error);
++            return
++        }
++
++        if (code !== 200) {
++            if (code === 401) {
++                callback.call(null, "Authentication failed. Status code 401.");
++            }
++            else {
++                callback.call(null, "Request failed. Status code " + code);
++            }
++
++            return;
++        }
++
++        var igniteResponse;
++
++        try {
++            igniteResponse = JSON.parse(message);
++        }
++        catch (e) {
++            callback.call(null, e, null);
++
++            return;
++        }
++
++        if (igniteResponse.successStatus) {
++            callback.call(null, igniteResponse.error, null)
++        }
++        else {
++            callback.call(null, null, igniteResponse.response);
++        }
++    }, cmd._method(), body, headers);
++};
++
++exports.AgentServer = AgentServer;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/app.js
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/app.js
index 0000000,8c347db..8cd8494
mode 000000,100644..100644
--- a/modules/web-control-center/src/main/js/app.js
+++ b/modules/web-control-center/src/main/js/app.js
@@@ -1,0 -1,154 +1,156 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *      http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ 
+ var flash = require('connect-flash');
+ var express = require('express');
+ var path = require('path');
+ var favicon = require('serve-favicon');
+ var logger = require('morgan');
+ var cookieParser = require('cookie-parser');
+ var bodyParser = require('body-parser');
+ var session = require('express-session');
+ var mongoStore = require('connect-mongo')(session);
+ 
+ var publicRoutes = require('./routes/public');
+ var clustersRouter = require('./routes/clusters');
+ var cachesRouter = require('./routes/caches');
+ var metadataRouter = require('./routes/metadata');
+ var summary = require('./routes/summary');
+ var adminRouter = require('./routes/admin');
+ var profileRouter = require('./routes/profile');
+ var sqlRouter = require('./routes/sql');
++var agentRouter = require('./routes/agent');
+ 
+ var passport = require('passport');
+ 
+ var db = require('./db');
+ 
+ var app = express();
+ 
+ // Views engine setup.
+ app.set('views', path.join(__dirname, 'views'));
+ app.set('view engine', 'jade');
+ 
+ // Site favicon.
+ app.use(favicon(__dirname + '/public/favicon.ico'));
+ 
+ app.use(logger('dev'));
+ 
+ app.use(bodyParser.json());
+ app.use(bodyParser.urlencoded({extended: false}));
+ 
+ app.use(require('less-middleware')(path.join(__dirname, 'public'), {
+     render: {
+         compress: false
+     }
+ }));
+ 
+ app.use(express.static(path.join(__dirname, 'public')));
+ app.use(express.static(path.join(__dirname, 'controllers')));
+ app.use(express.static(path.join(__dirname, 'helpers')));
+ 
+ app.use(cookieParser('keyboard cat'));
+ 
+ app.use(session({
+     secret: 'keyboard cat',
+     resave: false,
+     saveUninitialized: true,
+     store: new mongoStore({
+         mongooseConnection: db.mongoose.connection
+     })
+ }));
+ 
+ app.use(flash());
+ 
+ app.use(passport.initialize());
+ app.use(passport.session());
+ 
+ passport.serializeUser(db.Account.serializeUser());
+ passport.deserializeUser(db.Account.deserializeUser());
+ 
+ passport.use(db.Account.createStrategy());
+ 
+ var mustAuthenticated = function (req, res, next) {
+     req.isAuthenticated() ? next() : res.redirect('/');
+ };
+ 
+ var adminOnly = function(req, res, next) {
+     req.isAuthenticated() && req.user.admin ? next() : res.sendStatus(403);
+ };
+ 
+ app.all('/configuration/*', mustAuthenticated);
+ 
+ app.all('*', function(req, res, next) {
+     var becomeUsed = req.session.viewedUser && req.user.admin;
+ 
+     res.locals.user = becomeUsed ? req.session.viewedUser : req.user;
+     res.locals.becomeUsed = becomeUsed;
+ 
+     req.currentUserId = function() {
+         if (!req.user)
+             return null;
+ 
+         if (req.session.viewedUser && req.user.admin)
+             return req.session.viewedUser._id;
+ 
+         return req.user._id;
+     };
+ 
+     next();
+ });
+ 
+ app.use('/', publicRoutes);
+ app.use('/admin', mustAuthenticated, adminOnly, adminRouter);
+ app.use('/profile', mustAuthenticated, profileRouter);
+ 
+ app.use('/configuration/clusters', clustersRouter);
+ app.use('/configuration/caches', cachesRouter);
+ app.use('/configuration/metadata', metadataRouter);
+ app.use('/configuration/summary', summary);
+ app.use('/sql', sqlRouter);
++app.use('/agent', agentRouter);
+ 
+ // Catch 404 and forward to error handler.
+ app.use(function (req, res, next) {
+     var err = new Error('Not Found: ' + req.originalUrl);
+     err.status = 404;
+     next(err);
+ });
+ 
+ // Error handlers.
+ 
+ // Development error handler: will print stacktrace.
+ if (app.get('env') === 'development') {
+     app.use(function (err, req, res) {
+         res.status(err.status || 500);
+         res.render('error', {
+             message: err.message,
+             error: err
+         });
+     });
+ }
+ 
+ // Production error handler: no stacktraces leaked to user.
+ app.use(function (err, req, res) {
+     res.status(err.status || 500);
+     res.render('error', {
+         message: err.message,
+         error: {}
+     });
+ });
+ 
+ module.exports = app;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/bin/www
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/bin/www
index 0000000,4cf0583..cbc637a
mode 000000,100644..100644
--- a/modules/web-control-center/src/main/js/bin/www
+++ b/modules/web-control-center/src/main/js/bin/www
@@@ -1,0 -1,85 +1,110 @@@
+ #!/usr/bin/env node
+ 
+ /**
+  * Module dependencies.
+  */
 -var app = require('../app');
++var http = require('http');
++var https = require('https');
+ var config = require('../helpers/configuration-loader.js');
++var app = require('../app');
++var agentManager = require('../agents/agent-manager');
++
++var fs = require('fs');
++
+ var debug = require('debug')('ignite-web-control-center:server');
 -var http = require('http');
+ 
+ /**
+  * Get port from environment and store in Express.
+  */
+ var port = normalizePort(process.env.PORT || config.get('express:port'));
+ app.set('port', port);
+ 
+ /**
+  * Create HTTP server.
+  */
+ var server = http.createServer(app);
+ 
+ /**
+  * Listen on provided port, on all network interfaces.
+  */
+ server.listen(port);
+ server.on('error', onError);
+ server.on('listening', onListening);
+ 
+ /**
++ * Start agent server.
++ */
++var agentServer;
++
++if (config.get('monitor:server:ssl')) {
++    agentServer = https.createServer({
++    key: fs.readFileSync(config.get('monitor:server:key')),
++    cert: fs.readFileSync(config.get('monitor:server:cert')),
++    passphrase: config.get('monitor:server:keyPassphrase')
++  });
++}
++else {
++  agentServer = http.createServer();
++}
++
++agentServer.listen(config.get('monitor:server:port'));
++
++agentManager.createManager(agentServer);
++
++/**
+  * Normalize a port into a number, string, or false.
+  */
+ function normalizePort(val) {
+   var port = parseInt(val, 10);
+ 
+   if (isNaN(port)) {
+     // named pipe
+     return val;
+   }
+ 
+   if (port >= 0) {
+     // port number
+     return port;
+   }
+ 
+   return false;
+ }
+ 
+ /**
+  * Event listener for HTTP server "error" event.
+  */
+ function onError(error) {
+   if (error.syscall !== 'listen') {
+     throw error;
+   }
+ 
+   var bind = typeof port === 'string'
+     ? 'Pipe ' + port
+     : 'Port ' + port;
+ 
+   // handle specific listen errors with friendly messages
+   switch (error.code) {
+     case 'EACCES':
+       console.error(bind + ' requires elevated privileges');
+       process.exit(1);
+       break;
+     case 'EADDRINUSE':
+       console.error(bind + ' is already in use');
+       process.exit(1);
+       break;
+     default:
+       throw error;
+   }
+ }
+ 
+ /**
+  * Event listener for HTTP server "listening" event.
+  */
+ function onListening() {
+   var addr = server.address();
+   var bind = typeof addr === 'string'
+     ? 'pipe ' + addr
+     : 'port ' + addr.port;
+ 
+   debug('Listening on ' + bind);
+ }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/config/default.json
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/config/default.json
index 0000000,72dbd4e..f7f7a02
mode 000000,100644..100644
--- a/modules/web-control-center/src/main/js/config/default.json
+++ b/modules/web-control-center/src/main/js/config/default.json
@@@ -1,0 -1,8 +1,17 @@@
+ {
+     "express": {
+         "port": 3000
+     },
+     "mongoDB": {
+         "url": "mongodb://localhost/web-control-center"
++    },
++    "monitor": {
++        "server": {
++            "port": 3001,
++            "ssl": true,
++            "key": "keys/test.key",
++            "cert": "keys/test.crt",
++            "keyPassphrase": "password"
++        }
+     }
 -}
++}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/controllers/models/sql.json
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/controllers/models/sql.json
index 0000000,0000000..b00e5dd
new file mode 100644
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/models/sql.json
@@@ -1,0 -1,0 +1,5 @@@
++{
++  "screenTip": [
++    "Execute SQL queries."
++  ]
++}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/controllers/sql-controller.js
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/controllers/sql-controller.js
index 0000000,0000000..2562117
new file mode 100644
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/sql-controller.js
@@@ -1,0 -1,0 +1,60 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License.  You may obtain a copy of the License at
++ *
++ *      http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++var demoResults = [
++    {
++        id: 256,
++        firstName: 'Ivan',
++        lastName: 'Ivanov'
++    },
++    {
++        id: 384,
++        firstName: 'Sergey',
++        lastName: 'Petrov'
++    },
++    {
++        id: 923,
++        firstName: 'Andrey',
++        lastName: 'Sidorov'
++    }
++];
++
++var demoCaches = [{_id: '1', name: 'Users', mode: 'LOCAL'}, {_id: '2', name: 'Organizations', mode: 'REPLICATED'}, {_id: '3', name: 'Cities', mode: 'PARTITIONED'}];
++
++controlCenterModule.controller('sqlController', ['$scope', '$http', '$common', function ($scope, $http, $common) {
++    $scope.joinTip = $common.joinTip;
++
++    $scope.modes = [
++        {value: 'PARTITIONED', label: 'PARTITIONED'},
++        {value: 'REPLICATED', label: 'REPLICATED'},
++        {value: 'LOCAL', label: 'LOCAL'}
++    ];
++
++    $http.get('/models/sql.json')
++        .success(function (data) {
++            $scope.screenTip = data.screenTip;
++        })
++        .error(function (errMsg) {
++            $common.showError(errMsg);
++        });
++
++    $scope.query = "select u.id, u.firstName, u.lastName from User u where u.name like 'aaaa';";
++
++    $scope.results = demoResults;
++
++    $scope.caches = demoCaches;
++}]);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/controllers/summary-controller.js
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/controllers/summary-controller.js
index 0000000,1291683..531dc83
mode 000000,100644..100644
--- a/modules/web-control-center/src/main/js/controllers/summary-controller.js
+++ b/modules/web-control-center/src/main/js/controllers/summary-controller.js
@@@ -1,0 -1,164 +1,170 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *      http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ 
+ controlCenterModule.controller('summaryController', ['$scope', '$http', '$common', function ($scope, $http, $common) {
+     $scope.joinTip = $common.joinTip;
+     $scope.getModel = $common.getModel;
+ 
+     $scope.javaClassItems = [
+         {label: 'snippet', value: false},
+         {label: 'factory class', value: true}
+     ];
+ 
+     $scope.evictionPolicies = [
+         {value: 'LRU', label: 'LRU'},
+         {value: 'RND', label: 'Random'},
+         {value: 'FIFO', label: 'FIFO'},
+         {value: 'SORTED', label: 'Sorted'},
+         {value: undefined, label: 'Not set'}
+     ];
+ 
+     $scope.oss = ['debian:8', 'ubuntu:14.10'];
+ 
+     $scope.configServer = {javaClassServer: false, os: undefined};
+     $scope.backupItem = {javaClassClient: false};
+ 
+     $http.get('/models/summary.json')
+         .success(function (data) {
+             $scope.screenTip = data.screenTip;
+             $scope.clientFields = data.clientFields;
+         })
+         .error(function (errMsg) {
+             $common.showError(errMsg);
+         });
+ 
+     $scope.clusters = [];
+ 
+     $scope.aceInit = function (editor) {
+         editor.setReadOnly(true);
+         editor.setOption("highlightActiveLine", false);
+ 
++        var renderer = editor.renderer;
++
++        renderer.setHighlightGutterLine(false);
++        renderer.setShowPrintMargin(false);
++        renderer.setOption('fontSize', '14px');
++
+         editor.setTheme('ace/theme/chrome');
+     };
+ 
+     $scope.reloadServer = function () {
+         $scope.javaServer = $scope.configServer.javaClassServer ? $scope.configServer.javaClass : $scope.configServer.javaSnippet;
+ 
+         if ($scope.configServer.docker) {
+             var os = $scope.configServer.os ? $scope.configServer.os : $scope.oss[0];
+ 
+             $scope.dockerServer = $scope.configServer.docker.replace(new RegExp('\%OS\%', 'g'), os);
+         }
+     };
+ 
+     $scope.selectItem = function (cluster) {
+         if (!cluster)
+             return;
+ 
+         $scope.selectedItem = cluster;
+ 
+         $scope.$watch('javaClassServer', $scope.reloadServer);
+         $scope.$watch('os', $scope.reloadServer);
+ 
+         $scope.generateServer(cluster);
+ 
+         $scope.reloadServer();
+ 
+         $scope.$watch('configServer', function () {
+             $scope.reloadServer();
+         }, true);
+ 
+         $scope.$watch('backupItem', function () {
+             $scope.generateClient();
+         }, true);
+     };
+ 
+     $scope.generateServer = function (cluster) {
+         $http.post('summary/generator', {_id: cluster._id})
+             .success(function (data) {
+                 $scope.xmlServer = data.xmlServer;
+ 
+                 $scope.configServer.javaClass = data.javaClassServer;
+                 $scope.configServer.javaSnippet = data.javaSnippetServer;
+                 $scope.configServer.docker = data.docker;
+             }).error(function (errMsg) {
+                 $common.showError('Failed to generate config: ' + errMsg);
+             });
+     };
+ 
+     $scope.generateClient = function () {
+         $http.post('summary/generator', {
+             _id: $scope.selectedItem._id, javaClass: $scope.backupItem.javaClassClient,
+             clientNearConfiguration: $scope.backupItem.nearConfiguration
+         })
+             .success(function (data) {
+                 $scope.xmlClient = data.xmlClient;
+                 $scope.javaClient = data.javaClient;
+             }).error(function (errMsg) {
+                 $common.showError('Failed to generate config: ' + errMsg);
+             });
+     };
+ 
+     $scope.download = function () {
+         $http.post('summary/download', {_id: $scope.selectedItem._id, javaClass: $scope.javaClass, os: $scope.os})
+             .success(function (data) {
+                 var file = document.createElement('a');
+ 
+                 file.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + data);
+                 file.setAttribute('download', $scope.selectedItem.name + '-configuration.zip');
+ 
+                 file.style.display = 'none';
+ 
+                 document.body.appendChild(file);
+ 
+                 file.click();
+ 
+                 document.body.removeChild(file);
+             })
+             .error(function (errMsg) {
+                 $common.showError('Failed to generate zip: ' + errMsg);
+             });
+     };
+ 
+     $http.post('clusters/list').success(function (data) {
+         $scope.clusters = data.clusters;
+ 
+         if ($scope.clusters.length > 0) {
+             var restoredId = sessionStorage.summarySelectedId;
+ 
+             var selectIdx = 0;
+ 
+             if (restoredId) {
+                 var idx = _.findIndex($scope.clusters, function (cluster) {
+                     return cluster._id == restoredId;
+                 });
+ 
+                 if (idx >= 0)
+                     selectIdx = idx;
+                 else
+                     delete sessionStorage.summarySelectedId;
+             }
+ 
+             $scope.selectItem($scope.clusters[selectIdx]);
+ 
+             $scope.$watch('selectedItem', function (val) {
+                 if (val)
+                     sessionStorage.summarySelectedId = val._id;
+             }, true);
+         }
+     });
+ }]);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/keys/test.crt
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/keys/test.crt
index 0000000,0000000..50c6d5c
new file mode 100644
--- /dev/null
+++ b/modules/web-control-center/src/main/js/keys/test.crt
@@@ -1,0 -1,0 +1,13 @@@
++-----BEGIN CERTIFICATE-----
++MIIB6zCCAVQCCQDcAphbU6UcLjANBgkqhkiG9w0BAQsFADA6MRIwEAYDVQQDDAls
++b2NhbGhvc3QxJDAiBgkqhkiG9w0BCQEWFXNldmRva2ltb3ZAYXBhY2hlLm9yZzAe
++Fw0xNTA3MTQxMzAyNTNaFw0xODA2MjMxMzAyNTNaMDoxEjAQBgNVBAMMCWxvY2Fs
++aG9zdDEkMCIGCSqGSIb3DQEJARYVc2V2ZG9raW1vdkBhcGFjaGUub3JnMIGfMA0G
++CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDP/zpJrdHqCj6lPpeFF6LQtzKef6UiyBBo
++rbuOtCCgW8KMJJciluBWk2126qLt9smBN4jBpSNU3pq0r9gBMUTd/LSe7aY4D5ED
++Pjp7XsypNVKeHaHbFi7KhfHy0LYxsWiNPmmHJv4dtYOp+pGK25rkXNfyJxxjgxN6
++wo34+MnZIQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAFk9XEjcdyihws+fVmdGGUFo
++bVxI9YGH6agiNbU3WNF4B4VRzcPPW8z2mEo7eF9kgYmq/YzH4T8tgi/qkL/u8eZV
++Wmi9bg6RThLN6/hj3wVoOFKykbDQ05FFdhIJXN5UOjPmxYM97EKqg6J0W2HAb8SG
+++UekPnmAo/2HTKsLykH8
++-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/keys/test.key
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/keys/test.key
index 0000000,0000000..1b395c0
new file mode 100644
--- /dev/null
+++ b/modules/web-control-center/src/main/js/keys/test.key
@@@ -1,0 -1,0 +1,18 @@@
++-----BEGIN RSA PRIVATE KEY-----
++Proc-Type: 4,ENCRYPTED
++DEK-Info: DES-EDE3-CBC,6798185330CE2EE2
++
++sOwkmD8rvjx11l09V26dJhLhl+SyPIhyeZ3TqHXrYCATKoXlzidT+uPu1jVYtrwr
++nBLA6TrIDYRrBNlEsqGZ0cSvWTIczzVW1xZKHEJo5q2vUT/W8u/Q1QQtS3P3GeKF
++dEzx496rpZqwwVw59GNbuIwyYoVvQf3iEXzfhplGmLPELYIplDFOLgNuXQyXSGx6
++rwKsCxXMLsDyrA6DCz0Odf08p2HvWk/s5Ne3DFcQlqRNtIrBVGD2O0/Fp8ZZ2I4E
++Yn2OIIWJff3HanOjLOWKdN8YAn5UleNmlEUdIHeS5qaQ68mabOxLkSef9qglV+sd
++FHTtUq0cG6t6nhxZBziexha6v1yl/xABAHHhNPOfak+HthWxRD4N9f1yFYAeTmkn
++4kwBWoSUe12XRf2pGNqhEUKN/KhDmWk85wI55i/Cu2XmNoiBFlS9BXrRYU8uVCJw
++KlxjKTDWl1opCyvxTDxJnMkt44ZT445LRePKVueGIIKSUIXNQypOE+C1I0CL0N2W
++Ts3m9nthquvLeMx92k7b8yW69BER5uac3SIlGCOJObQXsHgyk8wYiyd/zLKfjctG
++PXieaW81UKjp+GqWpvWPz3VqnKwoyUWeVOOTviurli6kYOrHuySTMqMb6hxJctw9
++grAQTT0UPiAKWcM7InLzZnRjco+v9QLLEokjVngXPba16K/CItFY16xuGlaFLW7Y
++XTc67AkL8b76HBZelMjmCsqjvSoULhuMFwTOvUMm/mSM8rMoi9asrJRLQHRMWCST
++/6RENPLzPlOMnNLBujpBbn8V3/aYzEZsHMI+6S3d27WYlTJIqpabSA==
++-----END RSA PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/package.json
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/package.json
index 0000000,5e5463c..477266a
mode 000000,100644..100644
--- a/modules/web-control-center/src/main/js/package.json
+++ b/modules/web-control-center/src/main/js/package.json
@@@ -1,0 -1,50 +1,51 @@@
+ {
+   "name": "ignite-web-control-center",
+   "version": "1.0.0",
+   "description": "Web application for configuration, monitoring Ignite Cluster",
+   "private": true,
+   "scripts": {
+     "start": "node ./bin/www"
+   },
+   "author": "",
+   "contributors": [
+     {
+       "name": "",
+       "email": ""
+     }
+   ],
+   "license": "Apache-2.0",
+   "keywords": "grid",
+   "homepage": "https://ignite.incubator.apache.org/",
+   "engines": {
+     "node": ">=0.12.4"
+   },
+   "dependencies": {
+     "angular-ui-ace": "^0.2.3",
+     "archiver": "^0.14.4",
+     "body-parser": "~1.12.0",
+     "connect-flash": "^0.1.1",
+     "connect-mongo": "^0.8.1",
+     "cookie-parser": "~1.3.4",
+     "debug": "~2.1.1",
+     "express": "~4.12.2",
+     "express-session": "^1.11.1",
+     "jade": "~1.9.2",
+     "less-middleware": "1.0.x",
+     "lodash": "3.10.0",
+     "mongoose": "^4.0.2",
+     "nconf": "^0.7.1",
+     "passport": "^0.2.1",
+     "passport-local": "^1.0.0",
+     "passport-local-mongoose": "^1.0.0",
+     "pg": "^4.4.0",
+     "serve-favicon": "~2.2.0",
 -    "util": "^0.10.3"
++    "util": "^0.10.3",
++    "ws": "~0.7.2"
+   },
+   "devDependencies": {
+     "morgan": "~1.5.1",
+     "supertest": "^1.0.1",
+     "mocha": "~2.0.1",
+     "should": "~3.1.3"
+   }
+ }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/public/stylesheets/style.less
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/public/stylesheets/style.less
index 0000000,e05f0ff..3d0ede7
mode 000000,100644..100644
--- a/modules/web-control-center/src/main/js/public/stylesheets/style.less
+++ b/modules/web-control-center/src/main/js/public/stylesheets/style.less
@@@ -1,0 -1,1182 +1,1193 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *      http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ 
+ @logo-path: "https://www.filepicker.io/api/file/QagunjDGRFul2JgNCAli";
+ @input-height: 28px;
+ @ignite-red: #ec1c24;
+ @ignite-block-callout-background: #f3f8f3;
+ @ignite-block-callout: #50af51;
+ 
+ hr {
+   margin-top: 20px;
+   margin-bottom: 20px;
+ }
+ 
+ .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;
+   &.ng-enter {
+     opacity: 0;
+     &.ng-enter-active {
+       opacity: .5;
+     }
+   }
+   &.ng-leave {
+     opacity: .5;
+     &.ng-leave-active {
+       opacity: 0;
+     }
+   }
+ }
+ 
+ .modal.center .modal-dialog {
+   position: fixed;
+   top: 50%;
+   left: 50%;
+   -webkit-transform: translateX(-50%) translateY(-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, 255, 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: 5px 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: 22px;
+ }
+ 
+ .theme-line .btn-primary {
+   border: 0 none;
+   background-color: @ignite-red;
+ }
+ 
+ .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: 5px solid #ddd;
+ }
+ 
+ .theme-line .main-content .nav-horizontal a.active {
+   border-bottom: 5px solid #888;
+ }
+ 
+ .theme-line .navbar-nav, .theme-line .sidebar-nav {
+   ul li > a.active {
+     cursor: default;
+     pointer-events: none;
+   }
+ }
+ 
+ .theme-line .sidebar-nav {
+   color: #474a54;
+   padding-bottom: 30px;
+ 
+   ul {
+     padding: 0;
+     list-style: none;
+     font-size: 14px;
+     margin: 3px 0 0;
+     li {
+       color: #666;
+       line-height: @input-height;
+ 
+       span.fa-stack {
+         margin-right: 5px;
+         font-size: 12px;
+         height: 26px;
+       }
+ 
+       a {
+         font-size: 18px;
+         color: #666;
+         position: relative;
+         white-space: nowrap;
+         overflow: hidden;
+         -o-text-overflow: ellipsis;
+         text-overflow: ellipsis;
+       }
+     }
+   }
+ }
+ 
+ .theme-line .sidebar-nav ul li a:hover {
+   text-decoration: none;
+ }
+ 
+ .theme-line .select,
+ .theme-line .typeahead {
+   li a {
+     color: #666;
+     background-color: transparent;
+   }
+ 
+   li a:hover {
+     color: @ignite-red;
+   }
+ 
+   .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: 5px;
+   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;
+ }
+ 
+ .header .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: @ignite-red;
+ }
+ 
+ .theme-line .navbar-nav {
+   color: #888;
+ }
+ 
+ .theme-line .navbar-nav a {
+   color: #bbb;
+ }
+ 
+ .theme-line header a.btn {
+   background-color: @ignite-red;
+ }
+ 
+ .theme-line header a.btn:hover {
+   background-color: #950d12;
+ }
+ 
+ .theme-line header .navbar-nav .tt-cursor {
+   background-color: @ignite-red;
+ }
+ 
+ .theme-line header .navbar-nav a:hover, .theme-line header .navbar-nav .open > a {
+   color: @ignite-red;
+ }
+ 
+ .theme-line .navbar-nav .active a {
+   //font-weight: bold;
+   color: @ignite-red;
+ }
+ 
+ .theme-line .navbar-nav .active a:hover {
+   color: #950d12;
+ }
+ 
+ .theme-line .main-links .links a:hover {
+   color: @ignite-red;
+ }
+ 
+ .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: @ignite-red;
+ }
+ 
+ .theme-line .sidebar-nav ul li a.active {
+   color: @ignite-red;
+ }
+ 
+ .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: @ignite-red;
+   color: @ignite-red;
+ }
+ 
+ .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 strong, .theme-line #versions-list li a.active .current, .theme-line #versions-list li a:active .current {
+   color: @ignite-red;
+ }
+ 
+ .theme-line header .navbar-nav a {
+   font-size: 18px;
+ }
+ 
+ .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: @ignite-red;
+   border-color: @ignite-red;
+ }
+ 
+ .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;
+   margin-bottom: 10px;
+ }
+ 
+ .submit-vote.submit-vote-parent.voted a.submit-vote-button, .submit-vote.submit-vote-parent a.submit-vote-button:hover {
+   background-color: @ignite-red;
+ }
+ 
+ div.submit-vote.submit-vote-parent.voted a.submit-vote-button:hover {
+   background-color: #950d12;
+ }
+ 
+ a, .link .title {
+   color: @ignite-red;
+ }
+ 
+ a:hover, .link:hover .title {
+   color: #950d12;
+ }
+ 
+ .header h1.navbar-brand a {
+   background-image: url("@{logo-path}");
+ }
+ 
+ .header h1.navbar-brand {
+   width: 96px;
+ }
+ 
+ .block-edit-parameters {
+   text-align: right;
+   padding-bottom: 5px;
+ }
+ 
+ .container-footer {
+   margin-top: 20px;
+ }
+ 
+ /* Modal */
+ .modal {
+   display: block;
+   overflow: hidden;
+ }
+ 
+ .modal .close {
+   position: absolute;
+   top: 10px;
+   right: 10px;
+   float: none;
+ }
+ 
+ // Close icon
+ .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: 15px;
+   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 .modal-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("@{logo-path}");
+ }
+ 
+ .block-display-image img {
+   max-width: 100%;
+   max-height: 450px;
+   margin: auto;
+   display: block;
+ }
+ 
+ .greedy {
 -  min-height: 200px;
++  min-height: 100%;
+   height: ~"calc(100vh - 290px)";
+ }
+ 
+ @media (min-width: 768px) {
+   .navbar-nav > li > a {
+     padding-top: 18px;
+     padding-bottom: 10px;
+   }
+ }
+ 
+ .details-row {
+   padding: 0 10px;
+ }
+ 
+ .details-row, .settings-row {
+   display: block;
+   margin: 10px 0;
+ 
+   label.table-header {
+     line-height: @input-height;
+   }
+ 
+   [class*="col-"] {
+     display: inline-block;
+     vertical-align: middle;
+     float: none;
+ 
+     padding-left: 0 !important;
+     padding-right: 0 !important;
+   }
+ 
+   input[type="checkbox"] {
+     line-height: 20px;
+     margin-right: 5px;
+   }
+ 
+   .checkbox label {
+     line-height: 20px;
+     vertical-align: middle;
+   }
+ }
+ 
+ button {
+   margin-right: 5px;
+ }
+ 
+ h1,
+ h2,
+ h3 {
+   user-select: none;
+   font-weight: normal;
+   /* Makes the vertical size of the text the same for all fonts. */
+   line-height: 1;
+ }
+ 
+ h3 {
+   color: black;
+   font-size: 1.2em;
+   margin-top: 0;
+   margin-bottom: 1.5em;
+ }
+ 
+ table tr:hover {
+   cursor: pointer;
+ }
+ 
+ .btn {
+   padding: 3px 6px;
+ }
+ 
+ button .caret, .btn .caret {
+   float: right;
+   margin-left: 5px;
+   margin-top: 7px;
+ }
+ 
+ .base-control {
+   text-align: left;
+   padding: 3px 3px;
+   height: @input-height;
+ }
+ 
+ .form-control:extend(.base-control all) {
+   display: inline-block;
+ 
+   button {
+     text-align: left;
+   }
+ }
+ 
+ .theme-line .panel-heading {
+   padding: 10px 10px;
+   margin: 0;
+ 
+   h3 {
+     margin-bottom: 0;
+   }
+ 
+   h3 > a {
+     color: black;
+   }
+ }
+ 
+ .theme-line .panel-title {
+   a {
+     color: @ignite-red;
+   }
+ 
+   h3 {
+     margin-bottom: 20px;
+   }
+ }
+ 
+ .theme-line .panel-body {
+   padding: 10px 20px;
+ }
+ 
+ .theme-line .main-content a.customize {
+   margin-left: 5px;
+   color: @ignite-red;
+ }
+ 
+ .theme-line .panel-collapse {
+   margin: 0;
+ }
+ 
+ .theme-line .links table {
+   display: table;
+   table-layout: fixed;
+ 
+   td {
+     padding-left: 18px;
+   }
+ 
+   .active a {
+     color: @ignite-red;
+     font-weight: bold;
+   }
+ 
+   a:hover {
+     color: #950d12;
+   }
+ 
+   a {
+     color: #666;
+   }
+ }
+ 
+ .theme-line table.links-edit:extend(.theme-line .links table all) {
+   margin-top: 5px;
+   margin-bottom: 5px;
+ 
+   label {
+     line-height: @input-height;
+     color: #666;
+   }
+ }
+ 
+ .theme-line table.links-edit-details:extend(.theme-line .links table all) {
+   margin-bottom: 10px;
+ 
+   label {
+     line-height: @input-height;
+     color: #666;
+   }
+ 
+   td {
+     padding: 0;
+ 
+     .input-tip {
+       padding: 0;
+     }
+   }
+ }
+ 
+ .theme-line table.admin {
+   tr:hover {
+     cursor: default;
+   }
+ 
+   thead > tr th.header {
+     padding: 0 0 10px;
+ 
+     div {
+       padding: 0
+     }
+   }
+ 
+   margin-bottom: 10px;
+ 
+   label {
+     line-height: @input-height;
+     color: #666;
+   }
+ 
+   thead > tr th, td {
+     padding: 10px 10px;
+ 
+     .input-tip {
+       padding: 0;
+     }
+   }
+ 
+   tfoot > tr > td {
+     padding: 0;
+ 
+     .pagination {
+       margin: 10px 0;
+ 
+       > .active > a {
+         color: @ignite-red;
+         font-weight: bold;
+         border-color: #ddd;
+         background-color: #eee;
+       }
+     }
+   }
+ }
+ 
+ .panel-title a {
+   font-size: 14px;
+ }
+ 
+ .panel-details {
+   margin-top: 10px;
+ 
+   padding: 0;
+ 
+   border-radius: 5px;
+   border: thin dotted lightgrey;
+ }
+ 
+ .table-details {
+   border-radius: 5px;
+   border: thin dotted lightgrey;
+ 
+   margin-top: 10px;
+ 
+   padding-left: 10px;
+   padding-right: 5px;
+ }
+ 
+ .tooltip.right .tooltip-arrow {
+   border-right-color: @ignite-red;
+ }
+ 
+ .tooltip > .tooltip-inner {
+   max-width: 400px;
+   text-align: left;
+   background-color: @ignite-red;
+ }
+ 
+ label {
+   font-weight: normal;
+   margin-bottom: 0;
+ }
+ 
+ .form-horizontal .checkbox {
+   padding-top: 0;
+ }
+ 
+ .input-tip {
+   display: block;
+   overflow: hidden;
+ }
+ 
+ .labelField {
+   float: left;
+   margin-right: 5px;
+ }
+ 
+ .labelFormField {
+   float: left;
+   line-height: @input-height;
+ }
+ 
+ .form-horizontal .form-group {
+   margin: 0;
+ }
+ 
+ .form-horizontal .has-feedback .form-control-feedback {
+   right: 0;
+ }
+ 
+ .tipField {
+   float: right;
+   line-height: @input-height;
+   margin-left: 5px;
+ }
+ 
+ .tipLabel {
+   font-size: 14px;
+   margin-left: 5px;
+ }
+ 
+ .fieldSep {
+   float: right;
+   line-height: @input-height;
+   margin: 0 5px;
+ }
+ 
+ .fieldButton {
+   float: right;
+   margin-left: 5px;
+   margin-right: 0;
+ }
+ 
+ .fa-plus {
+   cursor: pointer;
+ }
+ 
+ .fa-remove {
+   color: @ignite-red;
+   cursor: pointer;
+ }
+ 
+ .fa-floppy-o {
+   cursor: pointer;
+ }
+ 
+ .fa-arrow-up {
+   cursor: pointer;
+ }
+ 
+ .fa-arrow-down {
+   cursor: pointer;
+ }
+ 
+ label.required:after {
+   color: @ignite-red;
+   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
+ }
+ 
+ //  Summary page
+ #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, button.ng-dirty.ng-invalid {
+   border-color: @ignite-red;
+ 
+   :focus {
+     border-color: @ignite-red;
+   }
+ }
+ 
+ .form-control-feedback {
+   display: inline-block;
+   color: @ignite-red;
+   right: 18px;
+   line-height: @input-height;
+   pointer-events: initial;
+ }
+ 
+ .syntaxhighlighter {
+   padding: 10px 5px;
+   border-radius: 6px;
+ }
+ 
+ .theme-line table.links-edit-small-padding:extend(.theme-line .links table all) {
+   label {
+     line-height: @input-height;
+     color: #666;
+   }
+ 
+   a {
+     line-height: @input-height;
+   }
+ 
+   input[type="checkbox"] {
+     line-height: 20px;
+     margin-right: 5px;
+   }
+ 
+   .checkbox label {
+     line-height: 20px;
+     vertical-align: middle;
+   }
+ 
+   th {
+     text-align: center;
+   }
+ 
+   td {
+     padding-left: 10px;
+   }
+ 
+   margin-top: 10px;
+ }
+ 
 -.configBox .nav > li > a {
++.nav-tabs > li > a {
+   padding: 5px 5px;
+ }
+ 
+ .viewedUser {
+   position: absolute;
+   width: 100%;
+   left: 0;
+ 
+   text-align: center;
+ 
+   margin-top: -15px;
+ 
+   background-color: #f8d5d8;
+ }
+ 
+ a {
+   cursor: pointer;
+ }
+ 
+ .st-sort-ascent:after {
+   content: '\25B2';
+ }
+ 
+ .st-sort-descent:after {
+   content: '\25BC';
+ }
+ 
+ .panel {
+   margin-bottom: 0;
+ }
+ 
+ .panel-group {
+   margin-bottom: 0;
+ }
+ 
+ .panel-group .panel + .panel {
+   margin-top: 20px;
+ }
+ 
+ .margin-top-dflt {
+   margin-top: 10px;
+ }
+ 
+ .margin-bottom-dflt {
+   margin-bottom: 10px;
+ }
+ 
+ .margin-dflt {
+   margin-top: 10px;
+   margin-bottom: 10px;
+ }
+ 
+ .padding-top-dflt {
+   padding-top: 10px;
+ }
+ 
+ .padding-bottom-dflt {
+   padding-bottom: 10px;
+ }
+ 
+ .padding-dflt {
+   padding-top: 10px;
+   padding-bottom: 10px;
+ }
+ 
+ .theme-line .panel-title h3 {
+   margin-top: 20px;
+   margin-bottom: 20px;
+ }
+ 
+ .block-callout-parent {
+   background-color: @ignite-block-callout-background;
+   overflow: hidden;
+ }
+ 
+ .block-callout {
+   background-color: @ignite-block-callout-background;
+   display: inline-block;
+   vertical-align: top;
+   width: 50%;
+ 
+   i {
+     padding: 10px 5px 0 10px;
+     color: @ignite-block-callout;
+   }
+ 
+   ul {
+     padding-left: 20px;
+     margin-bottom: 0;
+   }
+ 
+   p {
+     padding: 5px 0 10px 20px;
+     margin: 0;
+   }
+ 
+   label {
+     font-weight: bold;
+     color: @ignite-block-callout;
+   }
+ }
+ 
+ .block-callout-border {
+   border-left: 5px solid;
+   border-color: @ignite-block-callout;
+ }
+ 
+ .labelHeader {
+   font-weight: bold;
+ }
+ 
+ .ace_editor, #ace_document {
++  margin:  0.65em 0 0 0;
++
+   width: 100%;
+   height: 400px;
 -}
+ 
++  .ace_gutter {
++    background: transparent !important;
++    border: 1px #ddd;
++    border-right-style: solid;
++  }
+ 
++  .ace_gutter-cell, .ace_folding-enabled > .ace_gutter-cell {
++    padding-left: 0.65em;
++    padding-right: 0.9em;
++  }
++}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/routes/agent.js
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/routes/agent.js
index 0000000,0000000..19379e2
new file mode 100644
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/agent.js
@@@ -1,0 -1,0 +1,37 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License.  You may obtain a copy of the License at
++ *
++ *      http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++var router = require('express').Router();
++var agentManager = require('../agents/agent-manager');
++
++/* GET summary page. */
++router.post('/topology', function(req, res) {
++    var c = agentManager.getAgentManager().getOneClient();
++
++    if (!c)
++        return res.status(500).send("Client not found");
++
++    var ignite = c.ignite();
++
++    ignite.cluster().then(function (cluster) {
++        res.json(cluster);
++    }, function (err) {
++        res.send(err);
++    });
++});
++
++module.exports = router;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/views/configuration/summary.jade
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/views/configuration/summary.jade
index 0000000,6f2f6d8..0370ef4
mode 000000,100644..100644
--- a/modules/web-control-center/src/main/js/views/configuration/summary.jade
+++ b/modules/web-control-center/src/main/js/views/configuration/summary.jade
@@@ -1,0 -1,117 +1,115 @@@
+ //-
+     Licensed to the Apache Software Foundation (ASF) under one or more
+     contributor license agreements.  See the NOTICE file distributed with
+     this work for additional information regarding copyright ownership.
+     The ASF licenses this file to You under the Apache License, Version 2.0
+     (the "License"); you may not use this file except in compliance with
+     the License.  You may obtain a copy of the License at
+ 
+          http://www.apache.org/licenses/LICENSE-2.0
+ 
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ 
+ extends sidebar
+ 
+ append scripts
+     script(src='/summary-controller.js')
+ 
+     script(src="//cdn.jsdelivr.net/angularjs/1.3.15/angular-animate.min.js")
+     script(src="//cdn.jsdelivr.net/angularjs/1.3.15/angular-sanitize.min.js")
+ 
+     script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/theme-chrome.js')
+     script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-xml.js')
+     script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-java.js')
+     script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-dockerfile.js')
+ 
+ append css
+ 
+ include ../includes/controls
+ 
+ mixin hard-link(ref, txt)
+     a(style='color:#ec1c24' href=ref target="_blank") #{txt}
+ 
+ block content
+     .docs-header
+         h1 Configurations Summary
+         hr
+     .docs-body(ng-controller='summaryController')
+         +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
+         .padding-dflt(ng-if='clusters.length == 0')
+             | No cluster configured. You can&nbsp;
+             a(href='clusters') configure
+             | &nbsp;it.
+         .padding-dflt(ng-if='clusters.length > 0')
+             lable.labelHeader Clusters:
+             .links
+                 table(st-table='clusters')
+                     tbody
+                         tr(ng-repeat='row in clusters track by row._id')
+                             td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
+                                 a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
+         div(ng-show='selectedItem' role="tab" method='post' action='summary/download')
+             .padding-dflt(bs-collapse data-start-collapsed='false')
+                 .panel.panel-default
+                     form.panel-heading(role='tab' method='post' action='summary/download')
+                         input(type="hidden" name="_id" value="{{selectedItem._id}}")
+                         input(type="hidden" name="os" value="{{os}}")
+                         input(type="hidden" name="javaClass" value="{{javaClassServer}}")
+                         h3
+                             a(bs-collapse-toggle) Server
+                             button.btn.btn-primary.pull-right(type='submit' style='margin-top: -5px') Download
+                     .panel-collapse(role="tabpanel" bs-collapse-target)
 -                        .panel-body
 -                            .configBox(ng-show='selectedItem' bs-tabs)
 -                                div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
 -                                    .configBox(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlServer' style='margin: 0.65em 0;')
 -                                div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
 -                                    .settings-row
 -                                        .col-sm-1
 -                                            label Generate:
 -                                        .col-sm-3
 -                                            button.form-control(type='button' ng-model='configServer.javaClassServer'  bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
 -                                    .configBox(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaServer')
 -                                div(title='<img src="/images/docker.png" width="16px" height="16px"/> Dockerfile' bs-pane)
 -                                    .settings-row
 -                                        p
 -                                            +hard-link('https://docs.docker.com/reference/builder', 'Docker')
 -                                            | &nbsp;file is a text file with instructions to create Docker image.<br/>
 -                                            | To build image you have to store following Docker file with your Ignite XML configuration to the same directory.<br>
 -                                            | Also you could use predefined&nbsp;
 -                                            +hard-link('https://ignite.incubator.apache.org/download.html#docker', 'Apache Ignite docker image')
 -                                            | . For more information about using Ignite with Docker please read&nbsp;
 -                                            +hard-link('http://apacheignite.readme.io/docs/docker-deployment', 'documentation')
 -                                            |.
 -                                        .col-sm-2
 -                                            label(for='os') Operation System:
 -                                        .col-sm-4
 -                                            input#os.form-control(type='text', ng-model='configServer.os' placeholder='debian:8' data-min-length="0" data-html="1" data-auto-select="true" data-animation="am-flip-x" bs-typeahead bs-options='os for os in oss')
 -                                    div(ui-ace='{ onLoad: aceInit, mode: "dockerfile" }' ng-model='dockerServer')
++                        div(ng-show='selectedItem' bs-tabs style='margin-top: 0.65em')
++                            div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
++                                div(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlServer')
++                            div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
++                                .details-row
++                                    .col-sm-1
++                                        label Generate:
++                                    .col-sm-3
++                                        button.form-control(type='button' ng-model='configServer.javaClassServer'  bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
++                                div(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaServer')
++                            div(title='<img src="/images/docker.png" width="16px" height="16px"/> Dockerfile' bs-pane)
++                                .details-row
++                                    p
++                                        +hard-link('https://docs.docker.com/reference/builder', 'Docker')
++                                        | &nbsp;file is a text file with instructions to create Docker image.<br/>
++                                        | To build image you have to store following Docker file with your Ignite XML configuration to the same directory.<br>
++                                        | Also you could use predefined&nbsp;
++                                        +hard-link('https://ignite.incubator.apache.org/download.html#docker', 'Apache Ignite docker image')
++                                        | . For more information about using Ignite with Docker please read&nbsp;
++                                        +hard-link('http://apacheignite.readme.io/docs/docker-deployment', 'documentation')
++                                        |.
++                                    .col-sm-2
++                                        label(for='os') Operation System:
++                                    .col-sm-4
++                                        input#os.form-control(type='text', ng-model='configServer.os' placeholder='debian:8' data-min-length="0" data-html="1" data-auto-select="true" data-animation="am-flip-x" bs-typeahead bs-options='os for os in oss')
++                                div(ui-ace='{ onLoad: aceInit, mode: "dockerfile" }' ng-model='dockerServer')
+             .padding-dflt(bs-collapse data-start-collapsed='false')
+                 .panel.panel-default
+                     form.panel-heading(role='tab' method='post' action='summary/download')
+                         input(type="hidden" name="_id" value="{{selectedItem._id}}")
+                         input(type="hidden" name="javaClass" value="{{javaClassClient}}")
+                         input(type="hidden" name="clientNearConfiguration" value="{{backupItem}}")
+ 
+                         h3
+                             a(bs-collapse-toggle) Client
+                             button.btn.btn-primary.pull-right(type='submit' style='margin-top: -5px') Download
+                     .panel-collapse(role="tabpanel" bs-collapse-target)
 -                        .panel-body
 -                            div(ng-show='selectedItem')
 -                                .settings-row(ng-repeat='field in clientFields')
 -                                    +form-row-custom(['col-sm-3'], ['col-sm-3'])
 -                                .configBox(bs-tabs)
 -                                    div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
 -                                        .configBox(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlClient' style='margin: 0.65em 0;')
 -                                    div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
 -                                        .settings-row
 -                                            .col-sm-1
 -                                                label Generate:
 -                                            .col-sm-4
 -                                                button.form-control(type='button' ng-model='backupItem.javaClassClient' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
 -                                        div(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaClient')
++                        div(ng-show='selectedItem')
++                            .details-row(ng-repeat='field in clientFields')
++                                +form-row-custom(['col-sm-3'], ['col-sm-3'])
++                            div(bs-tabs style='margin-top: 0.65em')
++                                div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
++                                    div(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlClient')
++                                div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
++                                    .details-row
++                                        .col-sm-1
++                                            label Generate:
++                                        .col-sm-4
++                                            button.form-control(type='button' ng-model='backupItem.javaClassClient' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
++                                    div(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaClient')

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/views/includes/header.jade
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/views/includes/header.jade
index 0000000,ab2d31e..bfd5275
mode 000000,100644..100644
--- a/modules/web-control-center/src/main/js/views/includes/header.jade
+++ b/modules/web-control-center/src/main/js/views/includes/header.jade
@@@ -1,0 -1,39 +1,39 @@@
+ //-
+     Licensed to the Apache Software Foundation (ASF) under one or more
+     contributor license agreements.  See the NOTICE file distributed with
+     this work for additional information regarding copyright ownership.
+     The ASF licenses this file to You under the Apache License, Version 2.0
+     (the "License"); you may not use this file except in compliance with
+     the License.  You may obtain a copy of the License at
+ 
+          http://www.apache.org/licenses/LICENSE-2.0
+ 
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ mixin header-item(active, ref, txt)
+     li
+         a(ng-class='{active: isActive("#{active}")}' href='#{ref}') #{txt}
+ 
+ header.header(id='header')
+     .viewedUser(ng-show='becomeUsed') Currently assuming "
+         strong {{user.username}}
+         | ",&nbsp;&nbsp;
+         a(href='/admin/become') revert to your identity.
+     .container
+         h1.navbar-brand
+             a(href='/') Apache Ignite Web Configurator
+         .navbar-collapse.collapse(ng-controller='auth')
+             ul.nav.navbar-nav(ng-controller='activeLink' ng-show='user')
+                 +header-item('/configuration', '/configuration/clusters', 'Configuration')
+                 //+header-item('/monitoring', '/monitoring', 'Monitoring')
 -                //+header-item('/sql', '/sql', 'SQL')
++                +header-item('/sql', '/sql', 'SQL')
+                 //+header-item('/deploy', '/deploy', 'Deploy')
+             ul.nav.navbar-nav.pull-right
+                 li(ng-if='user')
+                     a.dropdown-toggle(data-toggle='dropdown' bs-dropdown='userDropdown' data-placement='bottom-right') {{user.username}}
+                         span.caret
+                 li.nav-login(ng-if='!user')
+                     a(ng-click='login()' href='#') Log In

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/views/sql.jade
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/views/sql.jade
index 0000000,0000000..9ba3056
new file mode 100644
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/sql.jade
@@@ -1,0 -1,0 +1,70 @@@
++//-
++    Licensed to the Apache Software Foundation (ASF) under one or more
++    contributor license agreements.  See the NOTICE file distributed with
++    this work for additional information regarding copyright ownership.
++    The ASF licenses this file to You under the Apache License, Version 2.0
++    (the "License"); you may not use this file except in compliance with
++    the License.  You may obtain a copy of the License at
++         http://www.apache.org/licenses/LICENSE-2.0
++    Unless required by applicable law or agreed to in writing, software
++    distributed under the License is distributed on an "AS IS" BASIS,
++    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++    See the License for the specific language governing permissions and
++    limitations under the License.
++extends ../templates/layout
++
++append scripts
++    script(src='/sql-controller.js')
++
++    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/theme-chrome.js')
++    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-sql.js')
++    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ext-language_tools.js')
++
++block container
++    .row
++        .col-sm-12
++            .docs-content
++                .docs-header
++                    h1 Connect to Ignite and execute SQL queries
++                    hr
++                .docs-body(ng-controller='sqlController')
++                    .block-callout
++                        p(ng-bind-html='joinTip(screenTip)')
++                    .tabs-below(bs-tabs bs-active-pane='tabs.activeTab')
++                        div(title='Query #1' bs-pane)
++                            .row
++                                .col-sm-9
++                                    div(style='height: 200px' ui-ace='{ theme: "chrome", mode: "sql",' +
++                                        'require: ["ace/ext/language_tools"],' +
++                                        'rendererOptions: {showPrintMargin: false, highlightGutterLine: false, fontSize: 14},' +
++                                        'advanced: {enableSnippets: false, enableBasicAutocompletion: true, enableLiveAutocompletion: true}}'  ng-model='query')
++                                .col-sm-3
++                                    .links(ng-hide='caches.length == 0' style='margin-top: 0.65em')
++                                        lable.labelHeader Caches:
++                                        table(st-table='caches')
++                                            tbody
++                                                tr(ng-repeat='row in caches track by row._id')
++                                                    td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
++                                                        a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}}
++                        div(title='Query #2' bs-pane)
++                            .row
++                    .settings-row
++                        button.btn.btn-primary(ng-click='') Explain
++                        button.btn.btn-primary(ng-click='') Execute
++                        button.btn.btn-primary(ng-click='' disabled) Scan
++                    //#resultPanel
++                    //    strong Results
++                    //
++                    //    #queryResult
++                    //        div(ng-repeat='r in results')
++                    //            .resultRow
++                    //                | {{r.id}} -> {{r.s}}
++                    //                span.props  {{r.fields}}
++
++                    div(ng-hide='results.length == 0' style='margin-top: 0.65em')
++                        lable.labelHeader Results:
++                        table.table-bordered(st-table='results')
++                            tbody
++                                tr(ng-repeat='row in results')
++                                    td
++                                        a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/views/templates/layout.jade
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/views/templates/layout.jade
index 0000000,a4191ae..8fbcd7e
mode 000000,100644..100644
--- a/modules/web-control-center/src/main/js/views/templates/layout.jade
+++ b/modules/web-control-center/src/main/js/views/templates/layout.jade
@@@ -1,0 -1,61 +1,61 @@@
+ //-
+     Licensed to the Apache Software Foundation (ASF) under one or more
+     contributor license agreements.  See the NOTICE file distributed with
+     this work for additional information regarding copyright ownership.
+     The ASF licenses this file to You under the Apache License, Version 2.0
+     (the "License"); you may not use this file except in compliance with
+     the License.  You may obtain a copy of the License at
+ 
+          http://www.apache.org/licenses/LICENSE-2.0
+ 
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ 
+ doctype html
+ html(ng-app='ignite-web-control-center', ng-init='user = #{JSON.stringify(user)}; becomeUsed = #{becomeUsed}')
+     head
+         title= title
+ 
+         block css
+             // Bootstrap
+             link(rel='stylesheet', href='//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.css')
+ 
+             // Font Awesome Icons
+             link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.css')
+ 
+             // Font
+             link(rel='stylesheet', href='//fonts.googleapis.com/css?family=Roboto+Slab:700:serif|Roboto+Slab:400:serif')
+ 
+             link(rel='stylesheet', href='/stylesheets/style.css')
+ 
+         block scripts
+             script(src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js')
+ 
+             script(src='//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min.js')
+ 
+             script(src='//ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.js')
+             script(src='//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.2/angular-sanitize.js')
+             script(src='//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.0/angular-strap.js')
+             script(src='//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.0/angular-strap.tpl.min.js')
+ 
+             script(src='//cdnjs.cloudflare.com/ajax/libs/angular-smart-table/2.0.3/smart-table.js')
+ 
+             script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js')
+             script(src='//angular-ui.github.io/ui-ace/dist/ui-ace.min.js')
+ 
+             script(src='/common-module.js')
+             script(src='/data-structures.js')
+ 
 -    body.theme-line.body-overlap
++    body.theme-line.body-overlap.greedy
+         .wrapper
+             include ../includes/header
+ 
+             block main-container
+                 .container.body-container
+                     .main-content
+                         block container
+ 
+             include ../includes/footer

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/views/templates/tab.jade
----------------------------------------------------------------------
diff --cc modules/web-control-center/src/main/js/views/templates/tab.jade
index 0000000,0000000..ce62bd6
new file mode 100644
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/templates/tab.jade
@@@ -1,0 -1,0 +1,3 @@@
++//
++   Created by nva on 23/07/15.
++



[10/50] [abbrv] incubator-ignite git commit: IGNITE-843: WIP cache type metadata: added support for $confirm, $saveAs.

Posted by an...@apache.org.
IGNITE-843: WIP cache type metadata: added support for $confirm, $saveAs.


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

Branch: refs/heads/ignite-1121
Commit: b34fb931bfea89c46625a945d723ab7fd8826f11
Parents: 18f554d
Author: AKuznetsov <ak...@gridgain.com>
Authored: Tue Jul 21 01:03:55 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Tue Jul 21 01:03:55 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/metadata-controller.js   | 74 +++++++++++++++-----
 .../nodejs/views/configuration/metadata.jade    |  1 +
 2 files changed, 56 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b34fb931/modules/web-control-center/nodejs/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/metadata-controller.js b/modules/web-control-center/nodejs/controllers/metadata-controller.js
index 9b100af..25e8156 100644
--- a/modules/web-control-center/nodejs/controllers/metadata-controller.js
+++ b/modules/web-control-center/nodejs/controllers/metadata-controller.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-controlCenterModule.controller('metadataController', ['$scope', '$http', '$common', '$table', function ($scope, $http, $common, $table) {
+controlCenterModule.controller('metadataController', ['$scope', '$http', '$common', '$confirm', '$saveAs', '$table', function ($scope, $http, $common, $confirm, $saveAs, $table) {
         $scope.joinTip = $common.joinTip;
         $scope.getModel = $common.getModel;
 
@@ -321,10 +321,13 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
             $scope.backupItem.space = $scope.spaces[0]._id;
         };
 
-        // Save metadata in db.
-        $scope.saveItem = function () {
-            var item = $scope.backupItem;
+        // Check cache type metadata logical consistency.
+        function validate(item) {
+            return true;
+        }
 
+        // Save cache type metadata into database.
+        function save(item) {
             $http.post('metadata/save', item)
                 .success(function (_id) {
                     $common.showInfo('Metadata "' + item.name + '" saved.');
@@ -343,30 +346,63 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
 
                     $scope.selectItem(item);
 
+                    $common.showInfo('Cache type metadata"' + item.name + '" saved.');
                 })
                 .error(function (errMsg) {
                     $common.showError(errMsg);
                 });
+        }
+
+        // Save cache type metadata.
+        $scope.saveItem = function () {
+            var item = $scope.backupItem;
+
+            if (validate(item))
+                save(item);
         };
 
-        $scope.removeItem = function () {
-            var _id = $scope.selectedItem._id;
+        // Save cache type metadata with new name.
+        $scope.saveItemAs = function () {
+            if (validate($scope.backupItem))
+                $saveAs.show($scope.backupItem.name).then(function (newName) {
+                    var item = angular.copy($scope.backupItem);
 
-            $http.post('metadata/remove', {_id: _id})
-                .success(function () {
-                    var i = _.findIndex($scope.metadatas, function (metadata) {
-                        return metadata._id == _id;
-                    });
+                    item._id = undefined;
+                    item.name = newName;
 
-                    if (i >= 0) {
-                        $scope.metadatas.splice(i, 1);
+                    save(item);
+                });
+        };
 
-                        $scope.selectedItem = undefined;
-                        $scope.backupItem = undefined;
-                    }
-                })
-                .error(function (errMsg) {
-                    $common.showError(errMsg);
+        $scope.removeItem = function () {
+            var selectedItem = $scope.selectedItem;
+
+            $confirm.show('Are you sure you want to remove cache type metadata: "' + selectedItem.name + '"?').then(
+                function () {
+                    var _id = selectedItem._id;
+
+                    $http.post('metadata/remove', {_id: _id})
+                        .success(function () {
+                            $common.showInfo('Cache type metadata has been removed: ' + selectedItem.name);
+
+                            var metadatas = $scope.metadatas;
+
+                            var idx = _.findIndex(metadatas, function (metadata) { return metadata._id == _id; });
+
+                            if (idx >= 0) {
+                                metadatas.splice(i, idx);
+
+                                if (metadatas.length > 0)
+                                    $scope.selectItem(metadatas[0]);
+                                else {
+                                    $scope.selectedItem = undefined;
+                                    $scope.backupItem = undefined;
+                                }
+                            }
+                        })
+                        .error(function (errMsg) {
+                            $common.showError(errMsg);
+                        });
                 });
         };
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b34fb931/modules/web-control-center/nodejs/views/configuration/metadata.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/configuration/metadata.jade b/modules/web-control-center/nodejs/views/configuration/metadata.jade
index 7eec682..bd3eb05 100644
--- a/modules/web-control-center/nodejs/views/configuration/metadata.jade
+++ b/modules/web-control-center/nodejs/views/configuration/metadata.jade
@@ -50,6 +50,7 @@ block content
                             .settings-row(ng-repeat='field in metadataManual')
                                 +form-row
                             button.btn.btn-primary(ng-disabled='manualForm.$invalid' ng-click='saveItem()') Save
+                            button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Save As
                             button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove
             .panel.panel-default
                 .panel-heading


[46/50] [abbrv] incubator-ignite git commit: IGNITE-843: Reworked tables L&F.

Posted by an...@apache.org.
IGNITE-843: Reworked tables L&F.


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

Branch: refs/heads/ignite-1121
Commit: e7088d5dc8ee352270813233d0c4d7d7b475ad91
Parents: 766a6c2
Author: AKuznetsov <ak...@gridgain.com>
Authored: Thu Jul 23 09:38:30 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Thu Jul 23 09:38:30 2015 +0700

----------------------------------------------------------------------
 .../main/js/controllers/metadata-controller.js  |   2 +
 .../src/main/js/public/stylesheets/style.less   |  10 +
 .../src/main/js/views/includes/controls.jade    | 194 ++++++++++---------
 3 files changed, 114 insertions(+), 92 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7088d5d/modules/web-control-center/src/main/js/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/metadata-controller.js b/modules/web-control-center/src/main/js/controllers/metadata-controller.js
index b62cde5..74ece5c 100644
--- a/modules/web-control-center/src/main/js/controllers/metadata-controller.js
+++ b/modules/web-control-center/src/main/js/controllers/metadata-controller.js
@@ -305,6 +305,8 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
 
             $scope.selectedItem = item;
             $scope.backupItem = angular.copy(item);
+
+            $scope.panels.activePanel = [0];
         };
 
         // Add new metadata.

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7088d5d/modules/web-control-center/src/main/js/public/stylesheets/style.less
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/public/stylesheets/style.less b/modules/web-control-center/src/main/js/public/stylesheets/style.less
index 4900581..e05f0ff 100644
--- a/modules/web-control-center/src/main/js/public/stylesheets/style.less
+++ b/modules/web-control-center/src/main/js/public/stylesheets/style.less
@@ -827,6 +827,16 @@ button .caret, .btn .caret {
   border: thin dotted lightgrey;
 }
 
+.table-details {
+  border-radius: 5px;
+  border: thin dotted lightgrey;
+
+  margin-top: 10px;
+
+  padding-left: 10px;
+  padding-right: 5px;
+}
+
 .tooltip.right .tooltip-arrow {
   border-right-color: @ignite-red;
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e7088d5d/modules/web-control-center/src/main/js/views/includes/controls.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/includes/controls.jade b/modules/web-control-center/src/main/js/views/includes/controls.jade
index 4a618fa..00ab6fa 100644
--- a/modules/web-control-center/src/main/js/views/includes/controls.jade
+++ b/modules/web-control-center/src/main/js/views/includes/controls.jade
@@ -38,19 +38,19 @@ mixin ico-exclamation(mdl, err, msg)
     i.fa.fa-exclamation-triangle.form-control-feedback(ng-show='inputForm["#{mdl}"].$error.#{err}' bs-tooltip data-title='#{msg}' type='button')
 
 mixin btn-save(show, click)
-    i.tipField.fa.fa-floppy-o(ng-show=show ng-click=click)
+    i.tipField.fa.fa-floppy-o(ng-show=show ng-click=click bs-tooltip data-title='Save item')
 
 mixin btn-add(click)
-    i.tipField.fa.fa-plus(ng-click=click)
+    i.tipField.fa.fa-plus(ng-click=click bs-tooltip data-title='Add new item')
 
 mixin btn-remove(click)
-    i.tipField.fa.fa-remove(ng-click=click)
+    i.tipField.fa.fa-remove(ng-click=click bs-tooltip data-title='Remove item')
 
 mixin btn-up(show, click)
-    i.tipField.fa.fa-arrow-up(ng-show=show ng-click=click)
+    i.tipField.fa.fa-arrow-up(ng-show=show ng-click=click bs-tooltip data-title='Move item up')
 
 mixin btn-down(show, click)
-    i.tipField.fa.fa-arrow-down(ng-show=show ng-click=click)
+    i.tipField.fa.fa-arrow-down(ng-show=show ng-click=click bs-tooltip data-title='Move item down')
 
 mixin table-pair-edit(keyModel, valModel, keyPlaceholder, valPlaceholder)
     .col-sm-6(style='float: right')
@@ -63,22 +63,23 @@ mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
     .col-sm-6
         label.table-header #{header}:
         +tipLabel('field.tip')
-        button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-    table.links-edit.col-sm-12(st-table=tblMdl)
-        tbody
-            tr.col-sm-12(ng-repeat='item in #{tblMdl}')
-                td.col-sm-6
-                    div(ng-show='!tableEditing(field, $index)')
-                        a.labelFormField(ng-click='curPair = tableStartEdit(backupItem, field, $index); curKey = curPair.#{keyFld}; curValue = curPair.#{valFld}') {{$index + 1}}) {{item.#{keyFld}}} / {{item.#{valFld}}}
-                        +btn-remove('tableRemove(backupItem, field, $index)')
-                    div(ng-show='tableEditing(field, $index)')
-                        label.labelField {{$index + 1}})
-                        +btn-save('tablePairSaveVisible(curKey, curValue)', 'tablePairSave(tablePairValid, backupItem, field, curKey, curValue, $index)')
-                        +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder)
-            tr.col-sm-12(ng-show='tableNewItemActive(field)')
-                td.col-sm-6
-                    +btn-save('tablePairSaveVisible(newKey, newValue)', 'tablePairSave(tablePairValid, backupItem, field, newKey, newValue, -1)')
-                    +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder)
+        +btn-add('tableNewItem(field)')
+        .table-details(ng-show='(#{tblMdl} && #{tblMdl}.length > 0) || tableNewItemActive(field)')
+            table.links-edit.col-sm-12(st-table=tblMdl)
+                tbody
+                    tr(ng-repeat='item in #{tblMdl}')
+                        td.col-sm-12
+                            div(ng-show='!tableEditing(field, $index)')
+                                a.labelFormField(ng-click='curPair = tableStartEdit(backupItem, field, $index); curKey = curPair.#{keyFld}; curValue = curPair.#{valFld}') {{$index + 1}}) {{item.#{keyFld}}} / {{item.#{valFld}}}
+                                +btn-remove('tableRemove(backupItem, field, $index)')
+                            div(ng-show='tableEditing(field, $index)')
+                                label.labelField {{$index + 1}})
+                                +btn-save('tablePairSaveVisible(curKey, curValue)', 'tablePairSave(tablePairValid, backupItem, field, curKey, curValue, $index)')
+                                +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder)
+                    tr(ng-show='tableNewItemActive(field)')
+                        td.col-sm-12
+                            +btn-save('tablePairSaveVisible(newKey, newValue)', 'tablePairSave(tablePairValid, backupItem, field, newKey, newValue, -1)')
+                            +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder)
 
 mixin details-row
     - var lblDetailClasses = ['col-sm-4', 'details-label']
@@ -237,26 +238,29 @@ mixin form-row-custom(lblClasses, fieldClasses)
             .col-sm-6
                 label.table-header {{field.label}}:
                 +tipLabel('field.tableTip')
-                button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-            table.links-edit.col-sm-12(st-table='#{fieldMdl}')
-                tbody
-                    tr.col-sm-12(ng-repeat='item in #{fieldMdl} track by $index')
-                        td.col-sm-6
-                            div(ng-show='!tableEditing(field, $index)')
-                                a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, field, $index)') {{$index + 1}}) {{item | compact}}
-                                +btn-remove('tableRemove(backupItem, field, $index)')
-                                +btn-down('field.reordering && tableSimpleDownVisible(backupItem, field, $index)', 'tableSimpleDown(backupItem, field, $index)')
-                                +btn-up('field.reordering && $index > 0', 'tableSimpleUp(backupItem, field, $index)')
-                            div(ng-show='tableEditing(field, $index)')
-                                label.labelField {{$index + 1}})
-                                +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, curValue, $index)')
-                                .input-tip
-                                    input.form-control(type='text' ng-model='curValue' placeholder='{{field.placeholder}}')
-                    tr.col-sm-12(ng-show='tableNewItemActive(field)')
-                        td.col-sm-6
-                            +btn-save('tableSimpleSaveVisible(newValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)')
-                            .input-tip
-                                input.form-control(type='text' ng-model='newValue' placeholder='{{field.placeholder}}')
+                +btn-add('tableNewItem(field)')
+            .col-sm-12(ng-show='(#{fieldMdl} && #{fieldMdl}.length > 0) || tableNewItemActive(field)')
+                .col-sm-6
+                    .table-details
+                        table.links-edit.col-sm-12(st-table='#{fieldMdl}')
+                            tbody
+                                tr(ng-repeat='item in #{fieldMdl} track by $index')
+                                    td.col-sm-12
+                                        div(ng-show='!tableEditing(field, $index)')
+                                            a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, field, $index)') {{$index + 1}}) {{item | compact}}
+                                            +btn-remove('tableRemove(backupItem, field, $index)')
+                                            +btn-down('field.reordering && tableSimpleDownVisible(backupItem, field, $index)', 'tableSimpleDown(backupItem, field, $index)')
+                                            +btn-up('field.reordering && $index > 0', 'tableSimpleUp(backupItem, field, $index)')
+                                        div(ng-show='tableEditing(field, $index)')
+                                            label.labelField {{$index + 1}})
+                                            +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, curValue, $index)')
+                                            .input-tip
+                                                input.form-control(type='text' ng-model='curValue' placeholder='{{field.placeholder}}')
+                                tr(ng-show='tableNewItemActive(field)')
+                                    td.col-sm-12
+                                        +btn-save('tableSimpleSaveVisible(newValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)')
+                                        .input-tip
+                                            input.form-control(type='text' ng-model='newValue' placeholder='{{field.placeholder}}')
         div(ng-switch-when='indexedTypes')
             +table-pair('Index key-value type pairs', fieldMdl, 'keyClass', 'valueClass', 'Key class full name', 'Value class full name')
         div(ng-switch-when='queryFields' ng-hide=fieldHide)
@@ -265,58 +269,64 @@ mixin form-row-custom(lblClasses, fieldClasses)
             .col-sm-6
                 label.table-header {{field.label}}:
                 +tipLabel('field.tip')
-                button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-            table.links-edit.col-sm-12(st-table=fieldMdl)
-                tbody
-                    tr.col-sm-12(ng-repeat='item in #{fieldMdl}')
-                        td.col-sm-6
-                            div(ng-show='!tableEditing(field, $index)')
-                                a.labelFormField(ng-click='curField = tableStartEdit(backupItem, field, $index); curDbName = curField.dbName; curDbType = curField.dbType; curJavaName = curField.javaName; curJavaType = curField.javaType') {{$index + 1}}) {{item.dbName}} / {{item.dbType}} / {{item.javaName}} / {{item.javaType}}
-                                +btn-remove('tableRemove(backupItem, field, $index)')
-                            div(ng-if='tableEditing(field, $index)')
-                                label.labelField {{$index + 1}})
-                                +btn-save('tableDbFieldSaveVisible(curDbName, curDbType, curJavaName, curJavaType)', 'tableDbFieldSave(field, curDbName, curDbType, curJavaName, curJavaType, $index)')
-                                +table-db-field-edit('curDbName', 'curDbType', 'curJavaName', 'curJavaType')
-                    tr(ng-show='tableNewItemActive(field)')
-                        td.col-sm-6
-                            +btn-save('tableDbFieldSaveVisible(newDbName, newDbType, newJavaName, newJavaType)', 'tableDbFieldSave(field, newDbName, newDbType, newJavaName, newJavaType, -1)')
-                            +table-db-field-edit('newDbName', 'newDbType', 'newJavaName', 'newJavaType')
+                +btn-add('tableNewItem(field)')
+            .col-sm-12(ng-show='(#{fieldMdl} && #{fieldMdl}.length > 0) || tableNewItemActive(field)')
+                .col-sm-6
+                    .table-details
+                        table.links-edit.col-sm-12(st-table=fieldMdl)
+                            tbody
+                                tr(ng-repeat='item in #{fieldMdl}')
+                                    td.col-sm-12
+                                        div(ng-show='!tableEditing(field, $index)')
+                                            a.labelFormField(ng-click='curField = tableStartEdit(backupItem, field, $index); curDbName = curField.dbName; curDbType = curField.dbType; curJavaName = curField.javaName; curJavaType = curField.javaType') {{$index + 1}}) {{item.dbName}} / {{item.dbType}} / {{item.javaName}} / {{item.javaType}}
+                                            +btn-remove('tableRemove(backupItem, field, $index)')
+                                        div(ng-if='tableEditing(field, $index)')
+                                            label.labelField {{$index + 1}})
+                                            +btn-save('tableDbFieldSaveVisible(curDbName, curDbType, curJavaName, curJavaType)', 'tableDbFieldSave(field, curDbName, curDbType, curJavaName, curJavaType, $index)')
+                                            +table-db-field-edit('curDbName', 'curDbType', 'curJavaName', 'curJavaType')
+                                tr(ng-show='tableNewItemActive(field)')
+                                    td.col-sm-12
+                                        +btn-save('tableDbFieldSaveVisible(newDbName, newDbType, newJavaName, newJavaType)', 'tableDbFieldSave(field, newDbName, newDbType, newJavaName, newJavaType, -1)')
+                                        +table-db-field-edit('newDbName', 'newDbType', 'newJavaName', 'newJavaType')
         div(ng-switch-when='queryGroups' ng-hide=fieldHide)
             .col-sm-6
                 label.table-header {{field.label}}:
                 +tipLabel('field.tip')
-                button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-            table.links-edit.col-sm-12(st-table=fieldMdl)
-                tbody
-                    tr.col-sm-12(ng-repeat='group in #{fieldMdl}')
-                        td.col-sm-6
-                            div
-                                .col-sm-12(ng-show='!tableEditing(field, $index)')
-                                    a.labelFormField(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curGroupName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{group.name}}
-                                    +btn-remove('tableRemove(backupItem, field, $index)')
-                                    +btn-add('tableGroupNewItem($index); newDirection = "ASC"')
-                                div(ng-show='tableEditing(field, $index)')
-                                    label.labelField {{$index + 1}})
-                                    +btn-save('tableGroupSaveVisible(curGroupName)', 'tableGroupSave(curGroupName, $index)')
-                                    .input-tip
-                                        input.form-control(type='text' ng-model='curGroupName' placeholder='Index name')
-                                div
-                                    table.links-edit.col-sm-12(st-table='group.fields' ng-init='groupIndex = $index')
-                                        tr(ng-repeat='groupItem in group.fields')
-                                            td
-                                                div(ng-show='!tableGroupItemEditing(groupIndex, $index)')
-                                                    a.labelFormField(ng-click='curGroupItem = tableGroupItemStartEdit(groupIndex, $index); curFieldName = curGroupItem.name; curClassName = curGroupItem.className; curDirection = curGroupItem.direction') {{$index + 1}}) {{groupItem.name}} / {{groupItem.className}} / {{groupItem.direction}}
-                                                    +btn-remove('tableRemoveGroupItem(group, $index)')
-                                                div(ng-show='tableGroupItemEditing(groupIndex, $index)')
-                                                    label.labelField {{$index + 1}})
-                                                    +btn-save('tableGroupItemSaveVisible(curFieldName, curClassName)', 'tableGroupItemSave(curFieldName, curClassName, curDirection, groupIndex, $index)')
-                                                    +table-group-item-edit('curFieldName', 'curClassName', 'curDirection')
-                                        tr.col-sm-12(style='padding-left: 18px' ng-show='tableGroupNewItemActive(groupIndex)')
-                                            td
-                                                +btn-save('tableGroupItemSaveVisible(newFieldName, newClassName)', 'tableGroupItemSave(newFieldName, newClassName, newDirection, groupIndex, -1)')
-                                                +table-group-item-edit('newFieldName', 'newClassName', 'newDirection')
-                    tr.col-sm-12(ng-show='tableNewItemActive(field)')
-                        td.col-sm-6
-                            +btn-save('tableGroupSaveVisible(newGroupName)', 'tableGroupSave(newGroupName, -1)')
-                            .input-tip
-                                input.form-control(type='text' ng-model='newGroupName' placeholder='Group name')
\ No newline at end of file
+                +btn-add('tableNewItem(field)')
+            .col-sm-12(ng-show='(#{fieldMdl} && #{fieldMdl}.length > 0) || tableNewItemActive(field)')
+                .col-sm-6
+                    .table-details
+                        table.links-edit(st-table=fieldMdl)
+                            tbody
+                                tr(ng-repeat='group in #{fieldMdl}')
+                                    td.col-sm-12
+                                        div
+                                            .col-sm-12(ng-show='!tableEditing(field, $index)')
+                                                a.labelFormField(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curGroupName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{group.name}}
+                                                +btn-remove('tableRemove(backupItem, field, $index)')
+                                                +btn-add('tableGroupNewItem($index); newDirection = "ASC"')
+                                            div(ng-show='tableEditing(field, $index)')
+                                                label.labelField {{$index + 1}})
+                                                +btn-save('tableGroupSaveVisible(curGroupName)', 'tableGroupSave(curGroupName, $index)')
+                                                .input-tip
+                                                    input.form-control(type='text' ng-model='curGroupName' placeholder='Index name')
+                                            div
+                                                table.links-edit.col-sm-12(st-table='group.fields' ng-init='groupIndex = $index')
+                                                    tr(ng-repeat='groupItem in group.fields')
+                                                        td
+                                                            div(ng-show='!tableGroupItemEditing(groupIndex, $index)')
+                                                                a.labelFormField(ng-click='curGroupItem = tableGroupItemStartEdit(groupIndex, $index); curFieldName = curGroupItem.name; curClassName = curGroupItem.className; curDirection = curGroupItem.direction') {{$index + 1}}) {{groupItem.name}} / {{groupItem.className}} / {{groupItem.direction}}
+                                                                +btn-remove('tableRemoveGroupItem(group, $index)')
+                                                            div(ng-show='tableGroupItemEditing(groupIndex, $index)')
+                                                                label.labelField {{$index + 1}})
+                                                                +btn-save('tableGroupItemSaveVisible(curFieldName, curClassName)', 'tableGroupItemSave(curFieldName, curClassName, curDirection, groupIndex, $index)')
+                                                                +table-group-item-edit('curFieldName', 'curClassName', 'curDirection')
+                                                    tr.col-sm-12(style='padding-left: 18px' ng-show='tableGroupNewItemActive(groupIndex)')
+                                                        td
+                                                            +btn-save('tableGroupItemSaveVisible(newFieldName, newClassName)', 'tableGroupItemSave(newFieldName, newClassName, newDirection, groupIndex, -1)')
+                                                            +table-group-item-edit('newFieldName', 'newClassName', 'newDirection')
+                                tr(ng-show='tableNewItemActive(field)')
+                                    td.col-sm-12
+                                        +btn-save('tableGroupSaveVisible(newGroupName)', 'tableGroupSave(newGroupName, -1)')
+                                        .input-tip
+                                            input.form-control(type='text' ng-model='newGroupName' placeholder='Group name')
\ No newline at end of file


[04/50] [abbrv] incubator-ignite git commit: Merge branches 'ignite-1121' and 'ignite-843' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-1121

Posted by an...@apache.org.
Merge branches 'ignite-1121' and 'ignite-843' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-1121


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

Branch: refs/heads/ignite-1121
Commit: 01bc127c9a3bb8163d089f87e3a48ed2b2b4243b
Parents: 91f1fdc 85062e3
Author: Andrey <an...@gridgain.com>
Authored: Mon Jul 20 17:57:24 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Mon Jul 20 17:57:24 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/admin-controller.js      |  12 +-
 .../controllers/cache-viewer-controller.js      |   2 +-
 .../nodejs/controllers/caches-controller.js     | 128 ++++++-----
 .../nodejs/controllers/clusters-controller.js   |  66 +++++-
 .../nodejs/controllers/common-module.js         | 220 ++++++++++++++-----
 .../nodejs/controllers/metadata-controller.js   | 170 +++++++++++---
 .../nodejs/controllers/models/caches.json       |   2 +
 .../nodejs/controllers/models/metadata.json     |  54 +++--
 .../nodejs/controllers/profile-controller.js    |   6 +-
 .../nodejs/controllers/summary-controller.js    |  44 ++--
 modules/web-control-center/nodejs/db.js         |   5 +-
 modules/web-control-center/nodejs/package.json  |  22 +-
 .../nodejs/public/stylesheets/style.less        |  55 ++++-
 .../nodejs/routes/generator/java.js             |   4 +-
 .../nodejs/routes/generator/xml.js              |  14 +-
 .../web-control-center/nodejs/routes/public.js  |   5 +
 .../web-control-center/nodejs/routes/summary.js |  12 +-
 .../nodejs/views/configuration/summary.jade     |   8 +-
 .../nodejs/views/includes/controls.jade         | 157 ++++++++-----
 19 files changed, 685 insertions(+), 301 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/01bc127c/modules/web-control-center/nodejs/package.json
----------------------------------------------------------------------


[42/50] [abbrv] incubator-ignite git commit: # ignite-843 moved

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/controllers/models/caches.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/caches.json b/modules/web-control-center/nodejs/controllers/models/caches.json
deleted file mode 100644
index 0ffc9d4..0000000
--- a/modules/web-control-center/nodejs/controllers/models/caches.json
+++ /dev/null
@@ -1,918 +0,0 @@
-{
-  "screenTip": {
-    "workflowTitle": "Use Caches view to:",
-    "workflowContent": [
-      "<ul>",
-      "  <li>Configure caches.</li>",
-      "  <li>Associate metadata with cache queries and/or cache store.</li>",
-      "</ul>"
-    ],
-    "whatsNextTitle": "What's next:",
-    "whatsNextContent": [
-      "<ul>",
-      "  <li>Configure clusters.</li>",
-      "  <li>Configure cache type metadata.</li>",
-      "  <li>Generate XML and java code on Summary view.</li>",
-      "</ul>"
-    ]
-  },
-  "general": [
-    {
-      "label": "Name",
-      "type": "text",
-      "model": "name",
-      "required": true,
-      "placeholder": "Input name"
-    },
-    {
-      "label": "Mode",
-      "type": "dropdown",
-      "model": "mode",
-      "placeholder": "PARTITIONED",
-      "items": "modes",
-      "tip": [
-        "Cache modes:",
-        "<ul>",
-        "  <li>Partitioned - in this mode the overall key set will be divided into partitions and all partitions will be split equally between participating nodes.</li>",
-        "  <li>Replicated - in this mode all the keys are distributed to all participating nodes.</li>",
-        "  <li>Local - in this mode caches residing on different grid nodes will not know about each other.</li>",
-        "</ul>"
-      ]
-    },
-    {
-      "label": "Atomicity",
-      "type": "dropdown",
-      "model": "atomicityMode",
-      "placeholder": "ATOMIC",
-      "items": "atomicities",
-      "tip": [
-        "Atomicity:",
-        "<ul>",
-        "  <li>Transactional - in this mode specified fully ACID-compliant transactional cache behavior.</li>",
-        "  <li>Atomic - in this mode distributed transactions and distributed locking are not supported.</li>",
-        "</ul>"
-      ]
-    },
-    {
-      "label": "Backups",
-      "type": "number",
-      "model": "backups",
-      "hide": "backupItem.mode == 'LOCAL'",
-      "placeholder": 0,
-      "tip": [
-        "Number of nodes used to back up single partition for partitioned cache."
-      ]
-    },
-    {
-      "label": "Read from backup",
-      "type": "check",
-      "model": "readFromBackup",
-      "placeholder": true,
-      "hide": "!backupItem.backups || backupItem.mode == 'LOCAL'",
-      "tip": [
-        "Flag indicating whether data can be read from backup.",
-        "If not set then always get data from primary node (never from backup)."
-      ]
-    },
-    {
-      "label": "Copy on read",
-      "type": "check",
-      "model": "copyOnRead",
-      "placeholder": true,
-      "tip": [
-        "Flag indicating whether copy of of the value stored in cache should be created for cache operation implying return value.",
-        "Also if this flag is set copies are created for values passed to CacheInterceptor and to CacheEntryProcessor."
-      ]
-    },
-    {
-      "label": "Invalidate near cache",
-      "type": "check",
-      "model": "invalidate",
-      "tip": [
-        "Invalidation flag for near cache entries in transaction.",
-        "If set then values will be invalidated (nullified) upon commit in near cache."
-      ]
-    }
-  ],
-  "advanced": [
-    {
-      "label": "Concurrency control",
-      "tip": [
-        "Cache concurrent usage settings."
-      ],
-      "fields": [
-        {
-          "label": "Max async operations",
-          "type": "number",
-          "model": "maxConcurrentAsyncOperations",
-          "placeholder": 500,
-          "tip": [
-            "Maximum number of allowed concurrent asynchronous operations.",
-            "If 0 then number of concurrent asynchronous operations is unlimited."
-          ]
-        },
-        {
-          "label": "Default lock timeout",
-          "type": "number",
-          "model": "defaultLockTimeout",
-          "placeholder": 0,
-          "tip": [
-            "Default lock acquisition timeout.",
-            "If 0 then lock acquisition will never timeout."
-          ]
-        },
-        {
-          "label": "Entry versioning",
-          "type": "dropdown",
-          "model": "atomicWriteOrderMode",
-          "placeholder": "Choose versioning",
-          "items": "atomicWriteOrderModes",
-          "hide": "backupItem.atomicityMode == 'TRANSACTIONAL'",
-          "tip": [
-            "Write ordering mode determines which node assigns the write version, sender or the primary node.",
-            "<ul>",
-            "  <li>CLOCK - in this mode write versions are assigned on a sender node which generally leads to better performance.</li>",
-            "  <li>PRIMARY - in this mode version is assigned only on primary node. This means that sender will only send write request to primary node, which in turn will assign write version and forward it to backups.</li>",
-            "</ul>"
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Memory",
-      "tip": [
-        "Cache memory settings."
-      ],
-      "fields": [
-        {
-          "label": "Mode",
-          "type": "dropdown",
-          "model": "memoryMode",
-          "placeholder": "ONHEAP_TIERED",
-          "items": "memoryModes",
-          "tip": [
-            "Memory modes:",
-            "<ul>",
-            "  <li>ONHEAP_TIERED - entries are cached on heap memory first.",
-            "    <ul>",
-            "      <li>If offheap memory is enabled and eviction policy evicts an entry from heap memory, entry will be moved to offheap memory. If offheap memory is disabled, then entry is simply discarded.</li>",
-            "      <li>If swap space is enabled and offheap memory fills up, then entry will be evicted into swap space. If swap space is disabled, then entry will be discarded. If swap is enabled and offheap memory is disabled, then entry will be evicted directly from heap memory into swap.</li>",
-            "    </ul>",
-            "  </li>",
-            "  <li>OFFHEAP_TIERED - works the same as ONHEAP_TIERED, except that entries never end up in heap memory and get stored in offheap memory right away. Entries get cached in offheap memory first and then get evicted to swap, if one is configured.</li>",
-            "  <li>OFFHEAP_VALUES - entry keys will be stored on heap memory, and values will be stored in offheap memory. Note that in this mode entries can be evicted only to swap.</li>",
-            "</ul>"
-          ]
-        },
-        {
-          "label": "Off-heap max memory",
-          "type": "number",
-          "model": "offHeapMaxMemory",
-          "min": -1,
-          "placeholder": -1,
-          "hide": "backupItem.memoryMode == 'OFFHEAP_VALUES'",
-          "tip": [
-            "Sets maximum amount of memory available to off-heap storage.",
-            "Possible values are:",
-            "<ul>",
-            "  <li>-1 - means that off-heap storage is disabled.</li>",
-            "  <li>0 - Ignite will not limit off-heap storage (it's up to user to properly add and remove entries from cache to ensure that off-heap storage does not grow infinitely.</li>",
-            "  <li>Any positive value specifies the limit of off-heap storage in bytes.</li>",
-            "</ul>"
-          ]
-        },
-        {
-          "label": "Eviction policy",
-          "type": "dropdown-details",
-          "path": "evictionPolicy",
-          "model": "kind",
-          "placeholder": "Choose eviction policy",
-          "items": "evictionPolicies",
-          "hide": "backupItem.memoryMode == 'OFFHEAP_TIERED'",
-          "tip": [
-            "Optional cache eviction policy. Must be set for entries to be evicted from on-heap to off-heap or swap."
-          ],
-          "details": {
-            "LRU": {
-              "expanded": false,
-              "fields": [
-                {
-                  "label": "Batch size",
-                  "type": "number",
-                  "path": "evictionPolicy.LRU",
-                  "model": "batchSize",
-                  "placeholder": 1,
-                  "tip": [
-                    "Number of entries to remove on shrink."
-                  ]
-                },
-                {
-                  "label": "Max memory size",
-                  "type": "number",
-                  "path": "evictionPolicy.LRU",
-                  "model": "maxMemorySize",
-                  "placeholder": 0,
-                  "tip": [
-                    "Maximum allowed cache size in bytes."
-                  ]
-                },
-                {
-                  "label": "Max size",
-                  "type": "number",
-                  "path": "evictionPolicy.LRU",
-                  "model": "maxSize",
-                  "placeholder": 100000,
-                  "tip": [
-                    "Maximum allowed size of cache before entry will start getting evicted."
-                  ]
-                }
-              ]
-            },
-            "RND": {
-              "expanded": false,
-              "fields": [
-                {
-                  "label": "Max size",
-                  "type": "number",
-                  "path": "evictionPolicy.RND",
-                  "model": "maxSize",
-                  "placeholder": 100000,
-                  "tip": [
-                    "Maximum allowed size of cache before entry will start getting evicted."
-                  ]
-                }
-              ]
-            },
-            "FIFO": {
-              "expanded": false,
-              "fields": [
-                {
-                  "label": "Batch size",
-                  "type": "number",
-                  "path": "evictionPolicy.FIFO",
-                  "model": "batchSize",
-                  "placeholder": 1,
-                  "tip": [
-                    "Number of entries to remove on shrink."
-                  ]
-                },
-                {
-                  "label": "Max memory size",
-                  "type": "number",
-                  "path": "evictionPolicy.FIFO",
-                  "model": "maxMemorySize",
-                  "placeholder": 0,
-                  "tip": [
-                    "Maximum allowed cache size in bytes."
-                  ]
-                },
-                {
-                  "label": "Max size",
-                  "type": "number",
-                  "path": "evictionPolicy.FIFO",
-                  "model": "maxSize",
-                  "placeholder": 100000,
-                  "tip": [
-                    "Maximum allowed size of cache before entry will start getting evicted."
-                  ]
-                }
-              ]
-            },
-            "SORTED": {
-              "expanded": false,
-              "fields": [
-                {
-                  "label": "Batch size",
-                  "type": "number",
-                  "path": "evictionPolicy.SORTED",
-                  "model": "batchSize",
-                  "placeholder": 1,
-                  "tip": [
-                    "Number of entries to remove on shrink."
-                  ]
-                },
-                {
-                  "label": "Max memory size",
-                  "type": "number",
-                  "path": "evictionPolicy.SORTED",
-                  "model": "maxMemorySize",
-                  "placeholder": 0,
-                  "tip": [
-                    "Maximum allowed cache size in bytes."
-                  ]
-                },
-                {
-                  "label": "Max size",
-                  "type": "number",
-                  "path": "evictionPolicy.SORTED",
-                  "model": "maxSize",
-                  "placeholder": 100000,
-                  "tip": [
-                    "Maximum allowed size of cache before entry will start getting evicted."
-                  ]
-                }
-              ]
-            }
-          }
-        },
-        {
-          "label": "Start size",
-          "type": "number",
-          "model": "startSize",
-          "placeholder": 1500000,
-          "tip": [
-            "Initial cache size which will be used to pre-create internal hash table after start."
-          ]
-        },
-        {
-          "label": "Swap enabled",
-          "type": "check",
-          "model": "swapEnabled",
-          "tip": [
-            "Flag indicating whether swap storage is enabled or not for this cache."
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Query",
-      "tip": [
-        "Cache query settings."
-      ],
-      "fields": [
-        {
-          "label": "Escape table and filed names",
-          "type": "check",
-          "model": "sqlEscapeAll",
-          "tip": [
-            "If set then all the SQL table and field names will be escaped with double quotes.",
-            "This enforces case sensitivity for field names and also allows having special characters in table and field names."
-          ]
-        },
-        {
-          "label": "On-heap cache for off-heap indexes",
-          "type": "number",
-          "model": "sqlOnheapRowCacheSize",
-          "placeholder": 10240,
-          "tip": [
-            "Number of SQL rows which will be cached onheap to avoid deserialization on each SQL index access."
-          ]
-        },
-        {
-          "label": "Long query timeout",
-          "type": "number",
-          "model": "longQueryWarningTimeout",
-          "placeholder": 3000,
-          "tip": [
-            "Timeout in milliseconds after which long query warning will be printed."
-          ]
-        },
-        {
-          "type": "indexedTypes",
-          "model": "indexedTypes",
-          "keyName": "keyClass",
-          "valueName": "valueClass",
-          "tip": [
-            "Collection of types to index."
-          ]
-        },
-        {
-          "label": "SQL functions",
-          "type": "table-simple",
-          "model": "sqlFunctionClasses",
-          "editIdx": -1,
-          "placeholder": "SQL function full class name",
-          "tableTip": [
-            "Collections of classes with user-defined functions for SQL queries."
-          ],
-          "tip": [
-            "Class with user-defined functions for SQL queries."
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Rebalance",
-      "tip": [
-        "Cache rebalance settings."
-      ],
-      "fields": [
-        {
-          "label": "Mode",
-          "type": "dropdown",
-          "model": "rebalanceMode",
-          "placeholder": "ASYNC",
-          "items": "rebalanceModes",
-          "tip": [
-            "Rebalance modes:",
-            "<ul>",
-            "  <li>Synchronous - in this mode distributed caches will not start until all necessary data is loaded from other available grid nodes.</li>",
-            "  <li>Asynchronous - in this mode distributed caches will start immediately and will load all necessary data from other available grid nodes in the background.</li>",
-            "  <li>None - in this mode no rebalancing will take place which means that caches will be either loaded on demand from persistent store whenever data is accessed, or will be populated explicitly.</li>",
-            "</ul>"
-          ]
-        },
-        {
-          "label": "Pool size",
-          "type": "number",
-          "model": "rebalanceThreadPoolSize",
-          "placeholder": 2,
-          "tip": [
-            "Size of rebalancing thread pool.<br>",
-            "Note that size serves as a hint and implementation may create more threads for rebalancing than specified here (but never less threads)."
-          ]
-        },
-        {
-          "label": "Batch size",
-          "type": "number",
-          "model": "rebalanceBatchSize",
-          "placeholder": "512 * 1024",
-          "tip": [
-            "Size (in bytes) to be loaded within a single rebalance message.",
-            "Rebalancing algorithm will split total data set on every node into multiple batches prior to sending data."
-          ]
-        },
-        {
-          "label": "Order",
-          "type": "number",
-          "model": "rebalanceOrder",
-          "placeholder": 0,
-          "tip": [
-            "If cache rebalance order is positive, rebalancing for this cache will be started only when rebalancing for all caches with smaller rebalance order (except caches with rebalance order 0) will be completed."
-          ]
-        },
-        {
-          "label": "Delay",
-          "type": "number",
-          "model": "rebalanceDelay",
-          "placeholder": 0,
-          "tip": [
-            "Delay in milliseconds upon a node joining or leaving topology (or crash) after which rebalancing should be started automatically."
-          ]
-        },
-        {
-          "label": "Timeout",
-          "type": "number",
-          "model": "rebalanceTimeout",
-          "placeholder": 10000,
-          "tip": [
-            "Rebalance timeout in milliseconds."
-          ]
-        },
-        {
-          "label": "Throttle",
-          "type": "number",
-          "model": "rebalanceThrottle",
-          "placeholder": 0,
-          "tip": [
-            "Time in milliseconds to wait between rebalance messages to avoid overloading of CPU or network."
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Server near cache",
-      "tip": [
-        "Near cache settings.",
-        "Near cache is a small local cache that stores most recently or most frequently accessed data.",
-        "Should be used in case when it is impossible to send computations to remote nodes."
-      ],
-      "fields": [
-        {
-          "label": "Enabled",
-          "type": "check",
-          "model": "nearCacheEnabled",
-          "tip": [
-            "Flag indicating whether to configure near cache."
-          ]
-        },
-        {
-          "label": "Start size",
-          "type": "number",
-          "path": "nearConfiguration",
-          "model": "nearStartSize",
-          "hide": "!backupItem.nearCacheEnabled",
-          "placeholder": 375000,
-          "tip": [
-            "Initial cache size for near cache which will be used to pre-create internal hash table after start."
-          ]
-        },
-        {
-          "label": "Eviction policy",
-          "type": "dropdown-details",
-          "path": "nearConfiguration.nearEvictionPolicy",
-          "model": "kind",
-          "placeholder": "Choose eviction policy",
-          "items": "evictionPolicies",
-          "hide": "!backupItem.nearCacheEnabled",
-          "tip": [
-            "Cache expiration policy."
-          ],
-          "details": {
-            "LRU": {
-              "expanded": false,
-              "fields": [
-                {
-                  "label": "Batch size",
-                  "type": "number",
-                  "path": "nearConfiguration.nearEvictionPolicy.LRU",
-                  "model": "batchSize",
-                  "placeholder": 1,
-                  "tip": [
-                    "Number of entries to remove on shrink."
-                  ]
-                },
-                {
-                  "label": "Max memory size",
-                  "type": "number",
-                  "path": "nearConfiguration.nearEvictionPolicy.LRU",
-                  "model": "maxMemorySize",
-                  "placeholder": 0,
-                  "tip": [
-                    "Maximum allowed cache size in bytes."
-                  ]
-                },
-                {
-                  "label": "Max size",
-                  "type": "number",
-                  "path": "nearConfiguration.nearEvictionPolicy.LRU",
-                  "model": "maxSize",
-                  "placeholder": 100000,
-                  "tip": [
-                    "Maximum allowed size of cache before entry will start getting evicted."
-                  ]
-                }
-              ]
-            },
-            "RND": {
-              "expanded": false,
-              "fields": [
-                {
-                  "label": "Max size",
-                  "type": "number",
-                  "path": "nearConfiguration.nearEvictionPolicy.RND",
-                  "model": "maxSize",
-                  "placeholder": 100000,
-                  "tip": [
-                    "Maximum allowed size of cache before entry will start getting evicted."
-                  ]
-                }
-              ]
-            },
-            "FIFO": {
-              "expanded": false,
-              "fields": [
-                {
-                  "label": "Batch size",
-                  "type": "number",
-                  "path": "nearConfiguration.nearEvictionPolicy.FIFO",
-                  "model": "batchSize",
-                  "placeholder": 1,
-                  "tip": [
-                    "Number of entries to remove on shrink."
-                  ]
-                },
-                {
-                  "label": "Max memory size",
-                  "type": "number",
-                  "path": "nearConfiguration.nearEvictionPolicy.FIFO",
-                  "model": "maxMemorySize",
-                  "placeholder": 0,
-                  "tip": [
-                    "Maximum allowed cache size in bytes."
-                  ]
-                },
-                {
-                  "label": "Max size",
-                  "type": "number",
-                  "path": "nearConfiguration.nearEvictionPolicy.FIFO",
-                  "model": "maxSize",
-                  "placeholder": 100000,
-                  "tip": [
-                    "Maximum allowed size of cache before entry will start getting evicted."
-                  ]
-                }
-              ]
-            },
-            "SORTED": {
-              "expanded": false,
-              "fields": [
-                {
-                  "label": "Batch size",
-                  "type": "number",
-                  "path": "nearConfiguration.nearEvictionPolicy.SORTED",
-                  "model": "batchSize",
-                  "placeholder": 1,
-                  "tip": [
-                    "Number of entries to remove on shrink."
-                  ]
-                },
-                {
-                  "label": "Max memory size",
-                  "type": "number",
-                  "path": "nearConfiguration.nearEvictionPolicy.SORTED",
-                  "model": "maxMemorySize",
-                  "placeholder": 0,
-                  "tip": [
-                    "Maximum allowed cache size in bytes."
-                  ]
-                },
-                {
-                  "label": "Max size",
-                  "type": "number",
-                  "path": "nearConfiguration.nearEvictionPolicy.SORTED",
-                  "model": "maxSize",
-                  "placeholder": 100000,
-                  "tip": [
-                    "Maximum allowed size of cache before entry will start getting evicted."
-                  ]
-                }
-              ]
-            }
-          }
-        }
-      ]
-    },
-    {
-      "label": "Statistics",
-      "tip": [
-        "Cache statistics and management settings."
-      ],
-      "fields": [
-        {
-          "label": "Statistics enabled",
-          "type": "check",
-          "model": "statisticsEnabled",
-          "tip": [
-            "Flag indicating whether statistics gathering is enabled on a cache."
-          ]
-        },
-        {
-          "label": "Management enabled",
-          "type": "check",
-          "model": "managementEnabled",
-          "tip": [
-            "Flag indicating whether management is enabled on this cache."
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Store",
-      "tip": [
-        "Cache store settings."
-      ],
-      "fields": [
-        {
-          "label": "Store factory",
-          "type": "dropdown-details",
-          "path": "cacheStoreFactory",
-          "model": "kind",
-          "placeholder": "Choose store factory",
-          "items": "cacheStoreFactories",
-          "tip": [
-            "Factory for persistent storage for cache data."
-          ],
-          "details": {
-            "CacheJdbcPojoStoreFactory": {
-              "expanded": true,
-              "fields": [
-                {
-                  "label": "Data source bean",
-                  "type": "text",
-                  "path": "cacheStoreFactory.CacheJdbcPojoStoreFactory",
-                  "model": "dataSourceBean",
-                  "required": true,
-                  "placeholder": "Bean name in Spring context",
-                  "tip": [
-                    "Name of the data source bean in Spring context."
-                  ]
-                },
-                {
-                  "label": "Dialect",
-                  "type": "dropdown",
-                  "path": "cacheStoreFactory.CacheJdbcPojoStoreFactory",
-                  "model": "dialect",
-                  "required": true,
-                  "placeholder": "Choose JDBC dialect",
-                  "items": "cacheStoreJdbcDialects",
-                  "tip": [
-                    "Dialect of SQL implemented by a particular RDBMS:",
-                    "<ul>",
-                    "  <li>Generic JDBC dialect.</li>",
-                    "  <li>Oracle database.</li>",
-                    "  <li>IBM DB2.</li>",
-                    "  <li>Microsoft SQL Server.</li>",
-                    "  <li>My SQL.</li>",
-                    "  <li>H2 database.</li>",
-                    "</ul>"
-                  ]
-                }
-              ]
-            },
-            "CacheJdbcBlobStoreFactory": {
-              "expanded": true,
-              "fields": [
-                {
-                  "label": "user",
-                  "type": "text",
-                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
-                  "model": "user",
-                  "required": true,
-                  "tip": [
-                    "User name for database access."
-                  ]
-                },
-                {
-                  "label": "Data source bean",
-                  "type": "text",
-                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
-                  "model": "dataSourceBean",
-                  "required": true,
-                  "placeholder": "Bean name in Spring context",
-                  "tip": [
-                    "Name of the data source bean in Spring context."
-                  ]
-                },
-                {
-                  "label": "Init schema",
-                  "type": "check",
-                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
-                  "model": "initSchema",
-                  "tip": [
-                    "Flag indicating whether DB schema should be initialized by Ignite (default behaviour) or was explicitly created by user."
-                  ]
-                },
-                {
-                  "label": "Create query",
-                  "type": "text",
-                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
-                  "model": "createTableQuery",
-                  "placeholder": "SQL for table creation",
-                  "tip": [
-                    "Query for table creation in underlying database.",
-                    "Default value: create table if not exists ENTRIES (key binary primary key, val binary)"
-                  ]
-                },
-                {
-                  "label": "Load query",
-                  "type": "text",
-                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
-                  "model": "loadQuery",
-                  "placeholder": "SQL for load entry",
-                  "tip": [
-                    "Query for entry load from underlying database.",
-                    "Default value: select * from ENTRIES where key=?"
-                  ]
-                },
-                {
-                  "label": "Insert query",
-                  "type": "text",
-                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
-                  "model": "insertQuery",
-                  "placeholder": "SQL for insert entry",
-                  "tip": [
-                    "Query for insert entry into underlying database.",
-                    "Default value: insert into ENTRIES (key, val) values (?, ?)"
-                  ]
-                },
-                {
-                  "label": "Update query",
-                  "type": "text",
-                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
-                  "model": "updateQuery",
-                  "placeholder": "SQL for update entry",
-                  "tip": [
-                    "Query fpr update entry in underlying database.",
-                    "Default value: update ENTRIES set val=? where key=?"
-                  ]
-                },
-                {
-                  "label": "Delete query",
-                  "type": "text",
-                  "path": "cacheStoreFactory.CacheJdbcBlobStoreFactory",
-                  "model": "deleteQuery",
-                  "placeholder": "SQL for delete entry",
-                  "tip": [
-                    "Query for delete entry from underlying database.",
-                    "Default value: delete from ENTRIES where key=?"
-                  ]
-                }
-              ]
-            },
-            "CacheHibernateBlobStoreFactory": {
-              "expanded": true,
-              "fields": [
-                {
-                  "label": "Hibernate properties",
-                  "type": "table-simple",
-                  "path": "cacheStoreFactory.CacheHibernateBlobStoreFactory",
-                  "model": "hibernateProperties",
-                  "editIdx": -1,
-                  "placeholder": "key=value",
-                  "tip": [
-                    "List of Hibernate properties.",
-                    "For example: connection.url=jdbc:h2:mem:"
-                  ]
-                }
-              ]
-            }
-          }
-        },
-        {
-          "label": "Load previous value",
-          "type": "check",
-          "model": "loadPreviousValue",
-          "tip": [
-            "Flag indicating whether value should be loaded from store if it is not in the cache for following cache operations:",
-            "<ul>",
-            "  <li>IgniteCache.putIfAbsent()</li>",
-            "  <li>IgniteCache.replace()</li>",
-            "  <li>IgniteCache.replace()</li>",
-            "  <li>IgniteCache.remove()</li>",
-            "  <li>IgniteCache.getAndPut()</li>",
-            "  <li>IgniteCache.getAndRemove()</li>",
-            "  <li>IgniteCache.getAndReplace()</li>",
-            "  <li>IgniteCache.getAndPutIfAbsent()</li>",
-            "</ul>"
-          ]
-        },
-        {
-          "label": "Read-through",
-          "type": "check",
-          "model": "readThrough",
-          "tip": [
-            "Flag indicating whether read-through caching should be used."
-          ]
-        },
-        {
-          "label": "Write-through",
-          "type": "check",
-          "model": "writeThrough",
-          "tip": [
-            "Flag indicating whether write-through caching should be used."
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Write behind",
-      "tip": [
-        "Cache write behind settings.",
-        "Write-behind is a special mode when updates to cache accumulated and then asynchronously flushed to persistent store as a bulk operation."
-      ],
-      "fields": [
-        {
-          "label": "Enabled",
-          "type": "check",
-          "model": "writeBehindEnabled",
-          "tip": [
-            "Flag indicating whether Ignite should use write-behind behaviour for the cache store."
-          ]
-        },
-        {
-          "label": "Batch size",
-          "type": "number",
-          "model": "writeBehindBatchSize",
-          "hide": "!backupItem.writeBehindEnabled",
-          "placeholder": 512,
-          "tip": [
-            "Maximum batch size for write-behind cache store operations.",
-            "Store operations (get or remove) are combined in a batch of this size to be passed to cache store."
-          ]
-        },
-        {
-          "label": "Flush size",
-          "type": "number",
-          "model": "writeBehindFlushSize",
-          "hide": "!backupItem.writeBehindEnabled",
-          "placeholder": 10240,
-          "tip": [
-            "Maximum size of the write-behind cache.<br>",
-            "If cache size exceeds this value, all cached items are flushed to the cache store and write cache is cleared."
-          ]
-        },
-        {
-          "label": "Flush frequency",
-          "type": "number",
-          "model": "writeBehindFlushFrequency",
-          "hide": "!backupItem.writeBehindEnabled",
-          "placeholder": 5000,
-          "tip": [
-            "Frequency with which write-behind cache is flushed to the cache store in milliseconds."
-          ]
-        },
-        {
-          "label": "Flush threads count",
-          "type": "number",
-          "model": "writeBehindFlushThreadCount",
-          "hide": "!backupItem.writeBehindEnabled",
-          "placeholder": 1,
-          "tip": [
-            "Number of threads that will perform cache flushing."
-          ]
-        }
-      ]
-    }
-  ]
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/controllers/models/clusters.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/clusters.json b/modules/web-control-center/nodejs/controllers/models/clusters.json
deleted file mode 100644
index d6d7d23..0000000
--- a/modules/web-control-center/nodejs/controllers/models/clusters.json
+++ /dev/null
@@ -1,907 +0,0 @@
-{
-  "screenTip": {
-    "workflowTitle": "Use Clusters view to:",
-    "workflowContent": [
-      "<ul>",
-      "  <li>Configure clusters.</li>",
-      "  <li>Associate clusters with caches.</li>",
-      "</ul>"
-    ],
-    "whatsNextTitle": "What's next:",
-    "whatsNextContent": [
-      "<ul>",
-      "  <li>Configure cache type metadata.</li>",
-      "  <li>Configure caches.</li>",
-      "  <li>Generate XML and java code on Summary view.</li>",
-      "</ul>"
-    ]
-  },
-  "templateTip": [
-    "Use following template to add a new cluster:",
-    "<ul>",
-    "  <li>multicast - cluster with multicast discovery.</li>",
-    "  <li>local - cluster with static ips discovery and pre-configured list of IP addresses.</li>",
-    "</ul>"
-  ],
-  "general": [
-    {
-      "label": "Name",
-      "type": "text",
-      "model": "name",
-      "required": true,
-      "placeholder": "Input name"
-    },
-    {
-      "label": "Caches",
-      "type": "dropdown-multiple",
-      "model": "caches",
-      "placeholder": "Choose caches",
-      "items": "caches",
-      "tip": [
-        "Select caches to start in cluster or add a new cache."
-      ],
-      "addLink": {
-        "label": "Add cache(s)",
-        "ref": "/configuration/caches"
-      }
-    },
-    {
-      "label": "Discovery",
-      "type": "dropdown-details",
-      "path": "discovery",
-      "model": "kind",
-      "required": true,
-      "placeholder": "Choose discovery",
-      "items": "discoveries",
-      "tip": [
-        "Discovery allows to discover remote nodes in grid."
-      ],
-      "details": {
-        "Vm": {
-          "expanded": true,
-          "fields": [
-            {
-              "type": "table-simple",
-              "path": "discovery.Vm",
-              "model": "addresses",
-              "editIdx": -1,
-              "reordering": true,
-              "ipaddress": true,
-              "placeholder": "IP address:port",
-              "tip": [
-                "Addresses may be represented as follows:",
-                "<ul>",
-                "  <li>IP address (e.g. 127.0.0.1, 9.9.9.9, etc);</li>",
-                "  <li>IP address and port (e.g. 127.0.0.1:47500, 9.9.9.9:47501, etc);</li>",
-                "  <li>IP address and port range (e.g. 127.0.0.1:47500..47510, 9.9.9.9:47501..47504, etc);</li>",
-                "  <li>Hostname (e.g. host1.com, host2, etc);</li>",
-                "  <li>Hostname and port (e.g. host1.com:47500, host2:47502, etc).</li>",
-                "  <li>Hostname and port range (e.g. host1.com:47500..47510, host2:47502..47508, etc).</li>",
-                "</ul>",
-                "If port is 0 or not provided then default port will be used (depends on discovery SPI configuration).",
-                "If port range is provided (e.g. host:port1..port2) the following should be considered:",
-                "<ul>",
-                "  <li>port1 < port2 should be true;</li>",
-                "  <li>Both port1 and port2 should be greater than 0.</li>",
-                "</ul>"
-              ]
-            }
-          ]
-        },
-        "Multicast": {
-          "expanded": false,
-          "fields": [
-            {
-              "label": "IP address",
-              "type": "text",
-              "path": "discovery.Multicast",
-              "model": "multicastGroup",
-              "placeholder": "228.1.2.4",
-              "tip": [
-                "IP address of multicast group."
-              ]
-            },
-            {
-              "label": "Port number",
-              "type": "number",
-              "path": "discovery.Multicast",
-              "model": "multicastPort",
-              "max": 65535,
-              "placeholder": 47400,
-              "tip": [
-                "Port number which multicast messages are sent to."
-              ]
-            },
-            {
-              "label": "Waits for reply",
-              "type": "number",
-              "path": "discovery.Multicast",
-              "model": "responseWaitTime",
-              "placeholder": 500,
-              "tip": [
-                "Time in milliseconds IP finder waits for reply to multicast address request."
-              ]
-            },
-            {
-              "label": "Attempts count",
-              "type": "number",
-              "path": "discovery.Multicast",
-              "model": "addressRequestAttempts",
-              "placeholder": 2,
-              "tip": [
-                "Number of attempts to send multicast address request.",
-                "IP finder re-sends request only in case if no reply for previous request is received."
-              ]
-            },
-            {
-              "label": "Local address",
-              "type": "text",
-              "path": "discovery.Multicast",
-              "model": "localAddress",
-              "tip": [
-                "Local host address used by this IP finder.",
-                "If provided address is non-loopback then multicast socket is bound to this interface.",
-                "If local address is not set or is any local address then IP finder creates multicast sockets for all found non-loopback addresses."
-              ]
-            }
-          ]
-        },
-        "S3": {
-          "expanded": true,
-          "fields": [
-            {
-              "label": "Bucket name",
-              "type": "text",
-              "required": true,
-              "path": "discovery.S3",
-              "model": "bucketName",
-              "placeholder": "",
-              "tip": [
-                "Bucket name for IP finder."
-              ]
-            },
-            {
-              "label": "Note, AWS credentials will be generated as stubs.",
-              "type": "label"
-            }
-          ]
-        },
-        "Cloud": {
-          "expanded": true,
-          "fields": [
-            {
-              "label": "Credential",
-              "type": "text",
-              "path": "discovery.Cloud",
-              "model": "credential",
-              "placeholder": "",
-              "tip": [
-                "Credential that is used during authentication on the cloud.",
-                "Depending on a cloud platform it can be a password or access key."
-              ]
-            },
-            {
-              "label": "Path to credential",
-              "type": "text",
-              "path": "discovery.Cloud",
-              "model": "credentialPath",
-              "placeholder": "",
-              "tip": [
-                "Path to a credential that is used during authentication on the cloud.",
-                "Access key or private key should be stored in a plain or PEM file without a passphrase."
-              ]
-            },
-            {
-              "label": "Identity",
-              "type": "text",
-              "required": true,
-              "path": "discovery.Cloud",
-              "model": "identity",
-              "placeholder": "",
-              "tip": [
-                "Identity that is used as a user name during a connection to the cloud.",
-                "Depending on a cloud platform it can be an email address, user name, etc."
-              ]
-            },
-            {
-              "label": "Provider",
-              "type": "text",
-              "required": true,
-              "path": "discovery.Cloud",
-              "model": "provider",
-              "placeholder": "",
-              "tip": [
-                "Cloud provider to use."
-              ]
-            },
-            {
-              "label": "Regions",
-              "type": "table-simple",
-              "path": "discovery.Cloud",
-              "model": "regions",
-              "editIdx": -1,
-              "placeholder": "",
-              "tableTip": [
-                "List of regions where VMs are located.",
-                "If the regions are not set then every region, that a cloud provider has, will be investigated. This could lead to significant performance degradation.",
-                "Note, that some cloud providers, like Google Compute Engine, doesn't have a notion of a region. For such providers a call to this method is redundant."
-              ],
-              "tip": [
-                "Region where VMs are located."
-              ]
-            },
-            {
-              "label": "Zones",
-              "type": "table-simple",
-              "path": "discovery.Cloud",
-              "model": "zones",
-              "editIdx": -1,
-              "placeholder": "",
-              "tableTip": [
-                "List of zones where VMs are located.",
-                "If the zones are not set then every zone from regions, set by {@link #setRegions(Collection)}}, will be taken into account.",
-                "Note, that some cloud providers, like Rackspace, doesn't have a notion of a zone. For such providers a call to this method is redundant."
-              ],
-              "tip": [
-                "Zone where VMs are located."
-              ]
-            }
-          ]
-        },
-        "GoogleStorage": {
-          "expanded": true,
-          "fields": [
-            {
-              "label": "Project name",
-              "type": "text",
-              "required": true,
-              "path": "discovery.GoogleStorage",
-              "model": "projectName",
-              "placeholder": "",
-              "tip": [
-                "Google Cloud Platforms project name.",
-                "Usually this is an auto generated project number (ex. 208709979073) that can be found in 'Overview' section of Google Developer Console."
-              ]
-            },
-            {
-              "label": "Bucket name",
-              "type": "text",
-              "required": true,
-              "path": "discovery.GoogleStorage",
-              "model": "bucketName",
-              "placeholder": "",
-              "tip": [
-                "Google Cloud Storage bucket name.",
-                "If the bucket doesn't exist Ignite will automatically create it.",
-                "However the name must be unique across whole Google Cloud Storage and Service Account Id must be authorized to perform this operation."
-              ]
-            },
-            {
-              "label": "Private key path",
-              "type": "text",
-              "required": true,
-              "path": "discovery.GoogleStorage",
-              "model": "serviceAccountP12FilePath",
-              "placeholder": "",
-              "tip": [
-                "Full path to the private key in PKCS12 format of the Service Account."
-              ]
-            },
-            {
-              "label": "Account id",
-              "type": "text",
-              "required": true,
-              "path": "discovery.GoogleStorage",
-              "model": "accountId",
-              "placeholder": "",
-              "tip": [
-                "Service account ID (typically an e-mail address)."
-              ]
-            }
-          ]
-        },
-        "Jdbc": {
-          "expanded": true,
-          "fields": [
-            {
-              "label": "DB schema should be initialized by Ignite",
-              "type": "check",
-              "path": "discovery.Jdbc",
-              "model": "initSchema",
-              "tip": [
-                "Flag indicating whether DB schema should be initialized by Ignite or was explicitly created by user."
-              ]
-            }
-          ]
-        },
-        "SharedFs": {
-          "expanded": false,
-          "fields": [
-            {
-              "label": "File path",
-              "type": "text",
-              "path": "discovery.SharedFs",
-              "model": "path",
-              "placeholder": "disco/tcp"
-            }
-          ]
-        }
-      }
-    }
-  ],
-  "advanced": [
-    {
-      "label": "Atomics configuration",
-      "tip": [
-        "Configuration for atomic data structures.",
-        "Atomics are distributed across the cluster, essentially enabling performing atomic operations (such as increment-and-get or compare-and-set) with the same globally-visible value."
-      ],
-      "fields": [
-        {
-          "label": "Backups",
-          "type": "number",
-          "path": "atomicConfiguration",
-          "model": "backups",
-          "placeholder": 0,
-          "tip": [
-            "Number of backup nodes."
-          ]
-        },
-        {
-          "label": "Cache mode",
-          "type": "dropdown",
-          "path": "atomicConfiguration",
-          "model": "cacheMode",
-          "placeholder": "PARTITIONED",
-          "items": "cacheModes",
-          "tip": [
-            "Cache modes:",
-            "<ul>",
-            "  <li>Partitioned - in this mode the overall key set will be divided into partitions and all partitions will be split equally between participating nodes.</li>",
-            "  <li>Replicated - in this mode all the keys are distributed to all participating nodes.</li>",
-            "  <li>Local - in this mode caches residing on different grid nodes will not know about each other.</li>",
-            "</ul>"
-          ]
-        },
-        {
-          "label": "Sequence reserve",
-          "type": "number",
-          "path": "atomicConfiguration",
-          "model": "atomicSequenceReserveSize",
-          "placeholder": 1000,
-          "tip": [
-            "Default number of sequence values reserved for IgniteAtomicSequence instances.",
-            "After a certain number has been reserved, consequent increments of sequence will happen locally, without communication with other nodes, until the next reservation has to be made."
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Communication",
-      "tip": [
-        "Cluster communication network properties."
-      ],
-      "fields": [
-        {
-          "label": "Timeout",
-          "type": "number",
-          "model": "networkTimeout",
-          "placeholder": 5000,
-          "tip": [
-            "Maximum timeout in milliseconds for network requests."
-          ]
-        },
-        {
-          "label": "Send retry delay",
-          "type": "number",
-          "model": "networkSendRetryDelay",
-          "placeholder": 1000,
-          "tip": [
-            "Interval in milliseconds between message send retries."
-          ]
-        },
-        {
-          "label": "Send retry count",
-          "type": "number",
-          "model": "networkSendRetryCount",
-          "placeholder": 3,
-          "tip": [
-            "Message send retries count."
-          ]
-        },
-        {
-          "label": "Segment check frequency",
-          "type": "number",
-          "model": "segmentCheckFrequency",
-          "placeholder": 10000,
-          "tip": [
-            "Network segment check frequency in milliseconds.",
-            "If 0, periodic segment check is disabled and segment is checked only on topology changes (if segmentation resolvers are configured)."
-          ]
-        },
-        {
-          "label": "Wait for segment on start",
-          "type": "check",
-          "model": "waitForSegmentOnStart",
-          "tip": [
-            "Wait for segment on start flag.",
-            "<ul>",
-            "  <li>If enabled, node should wait for correct segment on start.</li>",
-            "  <li>If node detects that segment is incorrect on startup and enabled, node waits until segment becomes correct.</li>",
-            "  <li>If segment is incorrect on startup and disabled, exception is thrown.</li>",
-            "</ul>"
-          ]
-        },
-        {
-          "label": "Discovery startup delay",
-          "type": "number",
-          "model": "discoveryStartupDelay",
-          "placeholder": 600000,
-          "tip": [
-            "This value is used to expire messages from waiting list whenever node discovery discrepancies happen."
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Deployment",
-      "tip": [
-        "Task and resources deployment in cluster."
-      ],
-      "fields": [
-        {
-          "label": "Mode",
-          "type": "dropdown",
-          "model": "deploymentMode",
-          "placeholder": "SHARED",
-          "items": "deploymentModes",
-          "tip": [
-            "Task classes and resources sharing mode."
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Events",
-      "tip": [
-        " Grid events are used for notification about what happens within the grid."
-      ],
-      "fields": [
-        {
-          "label": "Include type",
-          "type": "dropdown-multiple",
-          "model": "includeEventTypes",
-          "placeholder": "Choose recorded event types",
-          "items": "events",
-          "tip": [
-            "Array of event types, which will be recorded by GridEventStorageManager#record(Event).",
-            "Note, that either the include event types or the exclude event types can be established."
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Marshaller",
-      "tip": [
-        "Marshaller allows to marshal or unmarshal objects in grid.",
-        "It provides serialization/deserialization mechanism for all instances that are sent across networks or are otherwise serialized."
-      ],
-      "fields": [
-        {
-          "label": "Marshaller",
-          "type": "dropdown-details",
-          "path": "marshaller",
-          "model": "kind",
-          "placeholder": "Choose marshaller",
-          "items": "marshallers",
-          "tip": [
-            "Instance of marshaller to use in grid. If not provided, OptimizedMarshaller will be used on Java HotSpot VM, and JdkMarshaller will be used on other VMs."
-          ],
-          "details": {
-            "OptimizedMarshaller": {
-              "expanded": false,
-              "fields": [
-                {
-                  "label": "Streams pool size",
-                  "type": "number",
-                  "path": "marshaller.OptimizedMarshaller",
-                  "model": "poolSize",
-                  "placeholder": 0,
-                  "tip": [
-                    "Specifies size of cached object streams used by marshaller.",
-                    "Object streams are cached for performance reason to avoid costly recreation for every serialization routine.",
-                    "If 0 (default), pool is not used and each thread has its own cached object stream which it keeps reusing.",
-                    "Since each stream has an internal buffer, creating a stream for each thread can lead to high memory consumption if many large messages are marshalled or unmarshalled concurrently.",
-                    "Consider using pool in this case. This will limit number of streams that can be created and, therefore, decrease memory consumption.",
-                    "NOTE: Using streams pool can decrease performance since streams will be shared between different threads which will lead to more frequent context switching."
-                  ]
-                },
-                {
-                  "label": "Require serializable",
-                  "type": "check",
-                  "path": "marshaller.OptimizedMarshaller",
-                  "model": "requireSerializable",
-                  "tip": [
-                    "Whether marshaller should require Serializable interface or not."
-                  ]
-                }
-              ]
-            }
-          }
-        },
-        {
-          "label": "Marshal local jobs",
-          "type": "check",
-          "model": "marshalLocalJobs",
-          "placeholder": "false",
-          "tip": [
-            "If this flag is enabled, jobs mapped to local node will be marshalled as if it was remote node."
-          ]
-        },
-        {
-          "label": "Keep alive time",
-          "type": "number",
-          "model": "marshallerCacheKeepAliveTime",
-          "placeholder": 10000,
-          "tip": [
-            "Keep alive time of thread pool that is in charge of processing marshaller messages."
-          ]
-        },
-        {
-          "label": "Pool size",
-          "type": "number",
-          "model": "marshallerCacheThreadPoolSize",
-          "placeholder": "max(8, availableProcessors) * 2",
-          "tip": [
-            "Default size of thread pool that is in charge of processing marshaller messages."
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Metrics",
-      "tip": [
-        "Cluster runtime metrics settings."
-      ],
-      "fields": [
-        {
-          "label": "Elapsed time",
-          "type": "number",
-          "model": "metricsExpireTime",
-          "placeholder": "Long.MAX_VALUE",
-          "min": 1,
-          "tip": [
-            "Time in milliseconds after which a certain metric value is considered expired."
-          ]
-        },
-        {
-          "label": "History size",
-          "type": "number",
-          "model": "metricsHistorySize",
-          "placeholder": 10000,
-          "min": 1,
-          "tip": [
-            "Number of metrics kept in history to compute totals and averages."
-          ]
-        },
-        {
-          "label": "Log frequency",
-          "type": "number",
-          "model": "metricsLogFrequency",
-          "placeholder": 60000,
-          "tip": [
-            "Frequency of metrics log print out. To disable set to 0"
-          ]
-        },
-        {
-          "label": "Update frequency",
-          "type": "number",
-          "model": "metricsUpdateFrequency",
-          "placeholder": 60000,
-          "tip": [
-            "Job metrics update frequency in milliseconds.",
-            "<ul>",
-            "  <li>If set to -1 job metrics are never updated.</li>",
-            "  <li>If set to 0 job metrics are updated on each job start and finish.</li>",
-            "  <li>Positive value defines the actual update frequency.</li>",
-            "</ul>"
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Peer Class Loading",
-      "tip": [
-        "Cluster peer class loading settings."
-      ],
-      "fields": [
-        {
-          "label": "Enable peer class loading",
-          "type": "check",
-          "model": "peerClassLoadingEnabled",
-          "tip": [
-            "Enables/disables peer class loading."
-          ]
-        },
-        {
-          "label": "Local class path exclude",
-          "type": "text",
-          "model": "peerClassLoadingLocalClassPathExclude",
-          "placeholder": "[]",
-          "tip": [
-            "List of packages separated by comma from the system classpath that need to be peer-to-peer loaded from task originating node.",
-            "'*' is supported at the end of the package name which means that all sub-packages and their classes are included like in Java package import clause."
-          ]
-        },
-        {
-          "label": "Missed resources cache size",
-          "type": "number",
-          "model": "peerClassLoadingMissedResourcesCacheSize",
-          "placeholder": 100,
-          "tip": [
-            "If size greater than 0, missed resources will be cached and next resource request ignored.",
-            "If size is 0, then request for the resource will be sent to the remote node every time this resource is requested."
-          ]
-        },
-        {
-          "label": "Pool size",
-          "type": "number",
-          "model": "peerClassLoadingThreadPoolSize",
-          "placeholder": "availableProcessors",
-          "tip": [
-            "Thread pool size to use for peer class loading."
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Swap",
-      "tip": [
-        "Settings for overflow data to disk if it cannot fit in memory."
-      ],
-      "fields": [
-        {
-          "label": "Swap space SPI",
-          "type": "dropdown-details",
-          "path": "swapSpaceSpi",
-          "model": "kind",
-          "items": "swapSpaceSpis",
-          "placeholder": "Choose swap SPI",
-          "tip": [
-            "Provides a mechanism in grid for storing data on disk.",
-            "Ignite cache uses swap space to overflow data to disk if it cannot fit in memory."
-          ],
-          "details": {
-            "FileSwapSpaceSpi": {
-              "fields": [
-                {
-                  "label": "Base directory",
-                  "type": "text",
-                  "path": "swapSpaceSpi.FileSwapSpaceSpi",
-                  "model": "baseDirectory",
-                  "placeholder": "swapspace",
-                  "tip": [
-                    "Base directory where to write files."
-                  ]
-                },
-                {
-                  "label": "Read stripe size",
-                  "type": "number",
-                  "path": "swapSpaceSpi.FileSwapSpaceSpi",
-                  "model": "readStripesNumber",
-                  "placeholder": "available CPU cores",
-                  "tip": [
-                    "Read stripe size defines number of file channels to be used concurrently."
-                  ]
-                },
-                {
-                  "label": "Maximum sparsity",
-                  "type": "number",
-                  "path": "swapSpaceSpi.FileSwapSpaceSpi",
-                  "model": "maximumSparsity",
-                  "placeholder": 0.5,
-                  "tip": [
-                    "This property defines maximum acceptable wasted file space to whole file size ratio.",
-                    "When this ratio becomes higher than specified number compacting thread starts working."
-                  ]
-                },
-                {
-                  "label": "Max write queue size",
-                  "type": "number",
-                  "path": "swapSpaceSpi.FileSwapSpaceSpi",
-                  "model": "maxWriteQueueSize",
-                  "placeholder": "1024 * 1024",
-                  "tip": [
-                    "Max write queue size in bytes.",
-                    "If there are more values are waiting for being written to disk then specified size, SPI will block on store operation."
-                  ]
-                },
-                {
-                  "label": "Write buffer size",
-                  "type": "number",
-                  "path": "swapSpaceSpi.FileSwapSpaceSpi",
-                  "model": "writeBufferSize",
-                  "placeholder": "Available CPU cores",
-                  "tip": [
-                    "Write buffer size in bytes.",
-                    "Write to disk occurs only when this buffer is full."
-                  ]
-                }
-              ]
-            }
-          }
-        }
-      ]
-    },
-    {
-      "label": "Time configuration",
-      "tip": [
-        "Time settings for CLOCK write ordering mode."
-      ],
-      "fields": [
-        {
-          "label": "Samples size",
-          "type": "number",
-          "model": "clockSyncSamples",
-          "placeholder": 8,
-          "tip": [
-            "Number of samples used to synchronize clocks between different nodes.",
-            "Clock synchronization is used for cache version assignment in CLOCK order mode."
-          ]
-        },
-        {
-          "label": "Frequency",
-          "type": "number",
-          "model": "clockSyncFrequency",
-          "placeholder": 120000,
-          "tip": [
-            "Frequency at which clock is synchronized between nodes, in milliseconds.",
-            "Clock synchronization is used for cache version assignment in CLOCK order mode."
-          ]
-        },
-        {
-          "label": "Port base",
-          "type": "number",
-          "model": "timeServerPortBase",
-          "max": 65535,
-          "placeholder": 31100,
-          "tip": [
-            "Time server provides clock synchronization between nodes.",
-            "Base UPD port number for grid time server. Time server will be started on one of free ports in range."
-          ]
-        },
-        {
-          "label": "Port range",
-          "type": "number",
-          "model": "timeServerPortRange",
-          "placeholder": 100,
-          "tip": [
-            "Time server port range."
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Thread pools size",
-      "tip": [
-        "Settings for node thread pools."
-      ],
-      "fields": [
-        {
-          "label": "Public",
-          "type": "number",
-          "model": "publicThreadPoolSize",
-          "placeholder": "max(8, availableProcessors) * 2",
-          "tip": [
-            "Thread pool that is in charge of processing ComputeJob, GridJobs and user messages sent to node."
-          ]
-        },
-        {
-          "label": "System",
-          "type": "number",
-          "model": "systemThreadPoolSize",
-          "placeholder": "max(8, availableProcessors) * 2",
-          "tip": [
-            "Thread pool that is in charge of processing internal system messages."
-          ]
-        },
-        {
-          "label": "Management",
-          "type": "number",
-          "model": "managementThreadPoolSize",
-          "placeholder": 4,
-          "tip": [
-            "Thread pool that is in charge of processing internal and Visor ComputeJob, GridJobs."
-          ]
-        },
-        {
-          "label": "IGFS",
-          "type": "number",
-          "model": "igfsThreadPoolSize",
-          "placeholder": "availableProcessors",
-          "tip": [
-            "Thread pool that is in charge of processing outgoing IGFS messages."
-          ]
-        }
-      ]
-    },
-    {
-      "label": "Transactions",
-      "tip": [
-        "Settings for transactions."
-      ],
-      "fields": [
-        {
-          "label": "Concurrency",
-          "type": "dropdown",
-          "path": "transactionConfiguration",
-          "model": "defaultTxConcurrency",
-          "placeholder": "PESSIMISTIC",
-          "items": "transactionConcurrency",
-          "tip": [
-            "Cache transaction concurrency to use when one is not explicitly specified."
-          ]
-        },
-        {
-          "label": "Isolation",
-          "type": "dropdown",
-          "path": "transactionConfiguration",
-          "model": "transactionIsolation",
-          "placeholder": "REPEATABLE_READ",
-          "items": "transactionIsolation",
-          "tip": [
-            "Default transaction isolation."
-          ]
-        },
-        {
-          "label": "Default timeout",
-          "type": "number",
-          "path": "transactionConfiguration",
-          "model": "defaultTxTimeout",
-          "placeholder": 0,
-          "tip": [
-            "Default transaction timeout."
-          ]
-        },
-        {
-          "label": "Pessimistic log cleanup delay",
-          "type": "number",
-          "path": "transactionConfiguration",
-          "model": "pessimisticTxLogLinger",
-          "placeholder": 10000,
-          "tip": [
-            "Delay, in milliseconds, after which pessimistic recovery entries will be cleaned up for failed node."
-          ]
-        },
-        {
-          "label": "Pessimistic log size",
-          "type": "number",
-          "path": "transactionConfiguration",
-          "model": "pessimisticTxLogSize",
-          "placeholder": 0,
-          "tip": [
-            "Size of pessimistic transactions log stored on node in order to recover transaction commit if originating node has left grid before it has sent all messages to transaction nodes."
-          ]
-        },
-        {
-          "label": "Manager lookup",
-          "type": "text",
-          "model": "txManagerLookupClassName",
-          "tip": [
-            "Class name of transaction manager finder for integration for JEE app servers."
-          ]
-        },
-        {
-          "label": "Enable serializable cache transactions",
-          "type": "check",
-          "path": "transactionConfiguration",
-          "model": "txSerializableEnabled",
-          "tip": [
-            "Flag to enable/disable isolation level for cache transactions.",
-            "Serializable level does carry certain overhead and if not used, should be disabled."
-          ]
-        }
-      ]
-    }
-  ]
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/controllers/models/metadata.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/metadata.json b/modules/web-control-center/nodejs/controllers/models/metadata.json
deleted file mode 100644
index 3248f7a..0000000
--- a/modules/web-control-center/nodejs/controllers/models/metadata.json
+++ /dev/null
@@ -1,230 +0,0 @@
-{
-  "screenTip": {
-    "workflowTitle": "Use Cache Type Metadata view to:",
-    "workflowContent": [
-      "<ul>",
-      "  <li>Manually configure metadata for queries and/or store.</li>",
-      "  <li>Configure metadata from database tables metadata.</li>",
-      "</ul>"
-    ],
-    "whatsNextTitle": "What's next:",
-    "whatsNextContent": [
-      "<ul>",
-      "  <li>Configure clusters.</li>",
-      "  <li>Associate caches with metadata.</li>",
-      "  <li>Generate XML and java code on Summary view.</li>",
-      "</ul>"
-    ]
-  },
-  "templateTip": [
-    "Use following template for metadata:",
-    "<ul>",
-    "  <li>query - Create cache type metadata to use with queries only.</li>",
-    "  <li>store - Create cache type metadata to use with JDBC POJO store only.</li>",
-    "  <li>both - Create cache type metadata to use with query and store.</li>",
-    "</ul>"
-  ],
-  "metadataManual": [
-    {
-      "label": "Name",
-      "type": "text",
-      "model": "name",
-      "required": true,
-      "placeholder": "Input name"
-    },
-    {
-      "label": "Metadata for",
-      "type": "dropdown",
-      "model": "kind",
-      "items": "kinds",
-      "tip": [
-        "Use following template for metadata:",
-        "<ul>",
-        "  <li>query - Create cache type metadata to use with queries only.</li>",
-        "  <li>store - Create cache type metadata to use with JDBC POJO store only.</li>",
-        "  <li>both - Create cache type metadata to use with query and store.</li>",
-        "</ul>"
-      ]
-    },
-    {
-      "label": "Database schema",
-      "type": "text",
-      "model": "databaseSchema",
-      "hide": "backupItem.kind == 'query'",
-      "placeholder": "Input DB schema name",
-      "tip": [
-        "Schema name in database."
-      ]
-    },
-    {
-      "label": "Database table",
-      "type": "text",
-      "model": "databaseTable",
-      "hide": "backupItem.kind == 'query'",
-      "placeholder": "Input DB table name",
-      "tip": [
-        "Table name in database."
-      ]
-    },
-    {
-      "label": "Key type",
-      "type": "text",
-      "model": "keyType",
-      "required": true,
-      "placeholder": "Full class name for Key",
-      "tip": [
-        "Key class used to store key in cache."
-      ]
-    },
-    {
-      "label": "Value type",
-      "type": "text",
-      "model": "valueType",
-      "required": true,
-      "placeholder": "Full class name for Value",
-      "tip": [
-        "Value class used to store value in cache."
-      ]
-    },
-    {
-      "label": "Key fields",
-      "type": "dbFields",
-      "model": "keyFields",
-      "keyName": "name",
-      "valueName": "className",
-      "hide": "backupItem.kind == 'query'",
-      "tip": [
-        "Collection of key fields descriptions for CacheJdbcPojoStore."
-      ]
-    },
-    {
-      "label": "Value fields",
-      "type": "dbFields",
-      "model": "valueFields",
-      "keyName": "name",
-      "valueName": "className",
-      "hide": "backupItem.kind == 'query'",
-      "tip": [
-        "Collection of value fields descriptions for CacheJdbcPojoStore.."
-      ]
-    },
-    {
-      "label": "Query fields",
-      "type": "queryFields",
-      "model": "queryFields",
-      "keyName": "name",
-      "valueName": "className",
-      "hide": "backupItem.kind != 'query'",
-      "tip": [
-        "Collection of name-to-type mappings to be queried, in addition to indexed fields."
-      ]
-    },
-    {
-      "label": "Ascending fields",
-      "type": "queryFields",
-      "model": "ascendingFields",
-      "keyName": "name",
-      "valueName": "className",
-      "hide": "backupItem.kind != 'query'",
-      "tip": [
-        "Collection of name-to-type mappings to index in ascending order."
-      ]
-    },
-    {
-      "label": "Descending fields",
-      "type": "queryFields",
-      "model": "descendingFields",
-      "keyName": "name",
-      "valueName": "className",
-      "hide": "backupItem.kind != 'query'",
-      "tip": [
-        "Collection of name-to-type mappings to index in descending order."
-      ]
-    },
-    {
-      "label": "Text fields",
-      "type": "table-simple",
-      "model": "textFields",
-      "hide": "backupItem.kind != 'query'",
-      "placeholder": "Field name",
-      "tableTip": [
-        "Fields to index as text."
-      ],
-      "tip": [
-        "Field to index as text."
-      ]
-    },
-    {
-      "label": "Groups",
-      "type": "queryGroups",
-      "model": "groups",
-      "hide": "backupItem.kind != 'query'",
-      "tip": [
-        "Collection of group indexes."
-      ]
-    }
-  ],
-  "metadataDb": [
-    {
-      "label": "Name",
-      "type": "text",
-      "model": "name"
-    },
-    {
-      "label": "Database type",
-      "type": "dropdown",
-      "model": "dbType",
-      "placeholder": "Choose database",
-      "items": "databases",
-      "tip": [
-        "Select database type to connect for loading tables metadata."
-      ]
-    },
-    {
-      "label": "Database name",
-      "type": "text",
-      "model": "dbName",
-      "tip": [
-        "Database name to connect for loading tables metadata."
-      ]
-    },
-    {
-      "label": "Host",
-      "type": "text",
-      "model": "host",
-      "placeholder": "IP address or host",
-      "tip": [
-        "IP address or host name where database server deployed."
-      ]
-    },
-    {
-      "label": "Port",
-      "type": "number",
-      "model": "port",
-      "max": 65535,
-      "placeholder": "",
-      "tip": [
-        "Port number for connecting to database."
-      ]
-    },
-    {
-      "label": "User",
-      "type": "text",
-      "model": "user",
-      "placeholder": "",
-      "tip": [
-        "User name for connecting to database."
-      ]
-    },
-    {
-      "label": "Password",
-      "type": "password",
-      "model": "password",
-      "placeholder": "",
-      "tip": [
-        "Password for connecting to database.",
-        "Note, password would not be saved."
-      ]
-    }
-  ]
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/controllers/models/summary.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/models/summary.json b/modules/web-control-center/nodejs/controllers/models/summary.json
deleted file mode 100644
index 056291c..0000000
--- a/modules/web-control-center/nodejs/controllers/models/summary.json
+++ /dev/null
@@ -1,163 +0,0 @@
-{
-  "screenTip": {
-    "workflowTitle": "Use Summary view to:",
-    "workflowContent": [
-      "<ul>",
-      "  <li>See XML and java code for server nodes configurations.</li>",
-      "  <li>See XML and java code for client nodes configurations.</li>",
-      "</ul>"
-    ],
-    "whatsNextTitle": "What's next:",
-    "whatsNextContent": [
-      "<ul>",
-      "  <li>Download XML or java code configuration.</li>",
-      "  <li>Start Ignite cluster with downloaded configuration.</li>",
-      "</ul>"
-    ]
-  },
-  "clientFields": [
-    {
-      "label": "Near cache start size",
-      "type": "number",
-      "path": "nearConfiguration",
-      "model": "nearStartSize",
-      "placeholder": 375000,
-      "tip": [
-        "Initial cache size for near cache which will be used to pre-create internal hash table after start."
-      ]
-    },
-    {
-      "label": "Near cache eviction policy",
-      "type": "dropdown-details",
-      "path": "nearConfiguration.nearEvictionPolicy",
-      "model": "kind",
-      "placeholder": "Choose eviction policy",
-      "items": "evictionPolicies",
-      "tip": [
-        "Cache expiration policy."
-      ],
-      "details": {
-        "LRU": {
-          "expanded": false,
-          "fields": [
-            {
-              "label": "Batch size",
-              "type": "number",
-              "path": "nearConfiguration.nearEvictionPolicy.LRU",
-              "model": "batchSize",
-              "placeholder": 1,
-              "tip": [
-                "Number of entries to remove on shrink."
-              ]
-            },
-            {
-              "label": "Max memory size",
-              "type": "number",
-              "path": "nearConfiguration.nearEvictionPolicy.LRU",
-              "model": "maxMemorySize",
-              "placeholder": 0,
-              "tip": [
-                "Maximum allowed cache size in bytes."
-              ]
-            },
-            {
-              "label": "Max size",
-              "type": "number",
-              "path": "nearConfiguration.nearEvictionPolicy.LRU",
-              "model": "maxSize",
-              "placeholder": 100000,
-              "tip": [
-                "Maximum allowed size of cache before entry will start getting evicted."
-              ]
-            }
-          ]
-        },
-        "RND": {
-          "expanded": false,
-          "fields": [
-            {
-              "label": "Max size",
-              "type": "number",
-              "path": "nearConfiguration.nearEvictionPolicy.RND",
-              "model": "maxSize",
-              "placeholder": 100000,
-              "tip": [
-                "Maximum allowed size of cache before entry will start getting evicted."
-              ]
-            }
-          ]
-        },
-        "FIFO": {
-          "expanded": false,
-          "fields": [
-            {
-              "label": "Batch size",
-              "type": "number",
-              "path": "nearConfiguration.nearEvictionPolicy.FIFO",
-              "model": "batchSize",
-              "placeholder": 1,
-              "tip": [
-                "Number of entries to remove on shrink."
-              ]
-            },
-            {
-              "label": "Max memory size",
-              "type": "number",
-              "path": "nearConfiguration.nearEvictionPolicy.FIFO",
-              "model": "maxMemorySize",
-              "placeholder": 0,
-              "tip": [
-                "Maximum allowed cache size in bytes."
-              ]
-            },
-            {
-              "label": "Max size",
-              "type": "number",
-              "path": "nearConfiguration.nearEvictionPolicy.FIFO",
-              "model": "maxSize",
-              "placeholder": 100000,
-              "tip": [
-                "Maximum allowed size of cache before entry will start getting evicted."
-              ]
-            }
-          ]
-        },
-        "SORTED": {
-          "expanded": false,
-          "fields": [
-            {
-              "label": "Batch size",
-              "type": "number",
-              "path": "nearConfiguration.nearEvictionPolicy.SORTED",
-              "model": "batchSize",
-              "placeholder": 1,
-              "tip": [
-                "Number of entries to remove on shrink."
-              ]
-            },
-            {
-              "label": "Max memory size",
-              "type": "number",
-              "path": "nearConfiguration.nearEvictionPolicy.SORTED",
-              "model": "maxMemorySize",
-              "placeholder": 0,
-              "tip": [
-                "Maximum allowed cache size in bytes."
-              ]
-            },
-            {
-              "label": "Max size",
-              "type": "number",
-              "path": "nearConfiguration.nearEvictionPolicy.SORTED",
-              "model": "maxSize",
-              "placeholder": 100000,
-              "tip": [
-                "Maximum allowed size of cache before entry will start getting evicted."
-              ]
-            }
-          ]
-        }
-      }
-    }
-  ]
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/controllers/profile-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/profile-controller.js b/modules/web-control-center/nodejs/controllers/profile-controller.js
deleted file mode 100644
index a67df63..0000000
--- a/modules/web-control-center/nodejs/controllers/profile-controller.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-controlCenterModule.controller('profileController', ['$scope', '$http', '$common', function ($scope, $http, $common) {
-    $scope.profileUser = angular.copy($scope.user);
-
-    $scope.saveUser = function () {
-        var profile = $scope.profileUser;
-
-        if (profile) {
-            var userName = profile.username;
-            var changeUsername = userName != $scope.user.username;
-
-            var email = profile.email;
-            var changeEmail = email != $scope.user.email;
-
-            if (changeUsername || changeEmail || profile.changePassword) {
-                $http.post('/profile/saveUser', {
-                    _id: profile._id,
-                    userName: changeUsername ? userName : undefined,
-                    email: changeEmail ? email : undefined,
-                    newPassword: profile.changePassword ? profile.newPassword : undefined
-                }).success(function (user) {
-                    $common.showInfo('Profile saved.');
-
-                    if (changeUsername)
-                        $scope.user.username = userName;
-
-                    if (changeEmail)
-                        $scope.user.email = email;
-                }).error(function (err) {
-                    $common.showError('Failed to save profile: ' + $common.errorMessage(err));
-                });
-            }
-        }
-    };
-}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/controllers/summary-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/summary-controller.js b/modules/web-control-center/nodejs/controllers/summary-controller.js
deleted file mode 100644
index 1291683..0000000
--- a/modules/web-control-center/nodejs/controllers/summary-controller.js
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-controlCenterModule.controller('summaryController', ['$scope', '$http', '$common', function ($scope, $http, $common) {
-    $scope.joinTip = $common.joinTip;
-    $scope.getModel = $common.getModel;
-
-    $scope.javaClassItems = [
-        {label: 'snippet', value: false},
-        {label: 'factory class', value: true}
-    ];
-
-    $scope.evictionPolicies = [
-        {value: 'LRU', label: 'LRU'},
-        {value: 'RND', label: 'Random'},
-        {value: 'FIFO', label: 'FIFO'},
-        {value: 'SORTED', label: 'Sorted'},
-        {value: undefined, label: 'Not set'}
-    ];
-
-    $scope.oss = ['debian:8', 'ubuntu:14.10'];
-
-    $scope.configServer = {javaClassServer: false, os: undefined};
-    $scope.backupItem = {javaClassClient: false};
-
-    $http.get('/models/summary.json')
-        .success(function (data) {
-            $scope.screenTip = data.screenTip;
-            $scope.clientFields = data.clientFields;
-        })
-        .error(function (errMsg) {
-            $common.showError(errMsg);
-        });
-
-    $scope.clusters = [];
-
-    $scope.aceInit = function (editor) {
-        editor.setReadOnly(true);
-        editor.setOption("highlightActiveLine", false);
-
-        editor.setTheme('ace/theme/chrome');
-    };
-
-    $scope.reloadServer = function () {
-        $scope.javaServer = $scope.configServer.javaClassServer ? $scope.configServer.javaClass : $scope.configServer.javaSnippet;
-
-        if ($scope.configServer.docker) {
-            var os = $scope.configServer.os ? $scope.configServer.os : $scope.oss[0];
-
-            $scope.dockerServer = $scope.configServer.docker.replace(new RegExp('\%OS\%', 'g'), os);
-        }
-    };
-
-    $scope.selectItem = function (cluster) {
-        if (!cluster)
-            return;
-
-        $scope.selectedItem = cluster;
-
-        $scope.$watch('javaClassServer', $scope.reloadServer);
-        $scope.$watch('os', $scope.reloadServer);
-
-        $scope.generateServer(cluster);
-
-        $scope.reloadServer();
-
-        $scope.$watch('configServer', function () {
-            $scope.reloadServer();
-        }, true);
-
-        $scope.$watch('backupItem', function () {
-            $scope.generateClient();
-        }, true);
-    };
-
-    $scope.generateServer = function (cluster) {
-        $http.post('summary/generator', {_id: cluster._id})
-            .success(function (data) {
-                $scope.xmlServer = data.xmlServer;
-
-                $scope.configServer.javaClass = data.javaClassServer;
-                $scope.configServer.javaSnippet = data.javaSnippetServer;
-                $scope.configServer.docker = data.docker;
-            }).error(function (errMsg) {
-                $common.showError('Failed to generate config: ' + errMsg);
-            });
-    };
-
-    $scope.generateClient = function () {
-        $http.post('summary/generator', {
-            _id: $scope.selectedItem._id, javaClass: $scope.backupItem.javaClassClient,
-            clientNearConfiguration: $scope.backupItem.nearConfiguration
-        })
-            .success(function (data) {
-                $scope.xmlClient = data.xmlClient;
-                $scope.javaClient = data.javaClient;
-            }).error(function (errMsg) {
-                $common.showError('Failed to generate config: ' + errMsg);
-            });
-    };
-
-    $scope.download = function () {
-        $http.post('summary/download', {_id: $scope.selectedItem._id, javaClass: $scope.javaClass, os: $scope.os})
-            .success(function (data) {
-                var file = document.createElement('a');
-
-                file.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + data);
-                file.setAttribute('download', $scope.selectedItem.name + '-configuration.zip');
-
-                file.style.display = 'none';
-
-                document.body.appendChild(file);
-
-                file.click();
-
-                document.body.removeChild(file);
-            })
-            .error(function (errMsg) {
-                $common.showError('Failed to generate zip: ' + errMsg);
-            });
-    };
-
-    $http.post('clusters/list').success(function (data) {
-        $scope.clusters = data.clusters;
-
-        if ($scope.clusters.length > 0) {
-            var restoredId = sessionStorage.summarySelectedId;
-
-            var selectIdx = 0;
-
-            if (restoredId) {
-                var idx = _.findIndex($scope.clusters, function (cluster) {
-                    return cluster._id == restoredId;
-                });
-
-                if (idx >= 0)
-                    selectIdx = idx;
-                else
-                    delete sessionStorage.summarySelectedId;
-            }
-
-            $scope.selectItem($scope.clusters[selectIdx]);
-
-            $scope.$watch('selectedItem', function (val) {
-                if (val)
-                    sessionStorage.summarySelectedId = val._id;
-            }, true);
-        }
-    });
-}]);



[07/50] [abbrv] incubator-ignite git commit: IGNITE-843: Fixed case when no caches.

Posted by an...@apache.org.
IGNITE-843: Fixed case when no caches.


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

Branch: refs/heads/ignite-1121
Commit: fffdbdbf7e14f783ccb2d3ee92ce41f07e832b95
Parents: 064ea50
Author: AKuznetsov <ak...@gridgain.com>
Authored: Mon Jul 20 19:17:07 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Mon Jul 20 19:17:07 2015 +0700

----------------------------------------------------------------------
 .../web-control-center/nodejs/controllers/clusters-controller.js   | 2 +-
 modules/web-control-center/nodejs/routes/generator/common.js       | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/fffdbdbf/modules/web-control-center/nodejs/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/clusters-controller.js b/modules/web-control-center/nodejs/controllers/clusters-controller.js
index 8a5dc45..36f783a 100644
--- a/modules/web-control-center/nodejs/controllers/clusters-controller.js
+++ b/modules/web-control-center/nodejs/controllers/clusters-controller.js
@@ -195,7 +195,7 @@ controlCenterModule.controller('clustersController', ['$scope', '$http', '$commo
 
         // Check cluster logical consistency.
         function validate(item) {
-            if (!item.swapSpaceSpi || !item.swapSpaceSpi.kind) {
+            if (!item.swapSpaceSpi || !item.swapSpaceSpi.kind && item.caches) {
                 for (var i = 0; i < item.caches.length; i++) {
                     var idx = $scope.indexOfCache(item.caches[i]);
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/fffdbdbf/modules/web-control-center/nodejs/routes/generator/common.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/routes/generator/common.js b/modules/web-control-center/nodejs/routes/generator/common.js
index ed65d6b..dcbf156 100644
--- a/modules/web-control-center/nodejs/routes/generator/common.js
+++ b/modules/web-control-center/nodejs/routes/generator/common.js
@@ -272,7 +272,6 @@ exports.generateProperties = function (cluster) {
     var datasources = [];
 
     if (cluster.caches && cluster.caches.length > 0) {
-
         _.forEach(cluster.caches, function (cache) {
             if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind) {
                 var storeFactory = cache.cacheStoreFactory[cache.cacheStoreFactory.kind];


[35/50] [abbrv] incubator-ignite git commit: # ignite-843 moved

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/metadata.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/metadata.js b/modules/web-control-center/src/main/js/routes/metadata.js
new file mode 100644
index 0000000..64b8763
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/metadata.js
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var router = require('express').Router();
+var db = require('../db');
+
+/* GET metadata page. */
+router.get('/', function (req, res) {
+    res.render('configuration/metadata');
+});
+
+/**
+ * Get spaces and metadata accessed for user account.
+ *
+ * @param req Request.
+ * @param res Response.
+ */
+router.post('/list', function (req, res) {
+    var user_id = req.currentUserId();
+
+    // Get owned space and all accessed space.
+    db.Space.find({$or: [{owner: user_id}, {usedBy: {$elemMatch: {account: user_id}}}]}, function (err, spaces) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        var space_ids = spaces.map(function (value) {
+            return value._id;
+        });
+
+        // Get all metadata for spaces.
+        db.CacheTypeMetadata.find({space: {$in: space_ids}}).sort('name').exec(function (err, metadatas) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            res.json({spaces: spaces, metadatas: metadatas});
+        });
+    });
+});
+
+/**
+ * Save metadata.
+ */
+router.post('/save', function (req, res) {
+    if (req.body._id)
+        db.CacheTypeMetadata.update({_id: req.body._id}, req.body, {upsert: true}, function (err) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            res.send(req.body._id);
+        });
+    else {
+        db.CacheTypeMetadata.findOne({name: req.body.name}, function (err, metadata) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            if (metadata)
+                return res.status(500).send('Cache type metadata with name: "' + metadata.name + '" already exist.');
+
+            (new db.CacheTypeMetadata(req.body)).save(function (err, metadata) {
+                if (err)
+                    return res.status(500).send(err.message);
+
+                res.send(metadata._id);
+            });
+        });
+    }
+});
+
+/**
+ * Remove metadata by ._id.
+ */
+router.post('/remove', function (req, res) {
+    db.CacheTypeMetadata.remove(req.body, function (err) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        res.sendStatus(200);
+    })
+});
+
+module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/profile.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/profile.js b/modules/web-control-center/src/main/js/routes/profile.js
new file mode 100644
index 0000000..0269e7d
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/profile.js
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var router = require('express').Router();
+var db = require('../db');
+
+router.all('/profile/*', function (req, res, next) {
+    var userId = req.body._id;
+
+    if (userId != req.currentUserId() && userId != req.user._id)
+        return res.sendStatus(403);
+    else
+        next();
+});
+
+/**
+ * Get user profile page.
+ */
+router.get('/', function (req, res) {
+    var user_id = req.currentUserId();
+
+    db.Account.findById(user_id, function (err) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        res.render('settings/profile');
+    });
+});
+
+/**
+ * Save user profile.
+ */
+router.post('/saveUser', function (req, res) {
+    var params = req.body;
+
+    if (params.newPassword) {
+        var newPassword = params.newPassword;
+
+        if (!newPassword || newPassword.length == 0)
+            return res.status(500).send('Wrong value for new password');
+
+        db.Account.findById(params._id, function (err, user) {
+            if (err)
+                return res.status(500).send(err);
+
+            user.setPassword(newPassword, function (err, updatedUser) {
+                if (err)
+                    return res.status(500).send(err.message);
+
+                if (params.userName)
+                    updatedUser.username = params.userName;
+
+                if (params.email)
+                    updatedUser.email = params.email;
+
+                updatedUser.save(function (err) {
+                    if (err)
+                        return res.status(500).send(err.message);
+
+                    res.json(user);
+                });
+            });
+        });
+    }
+    else if (params.userName || params.email) {
+        var upd = {};
+
+        if (params.userName)
+            upd.username = params.userName;
+
+        if (params.email)
+            upd.email = params.email;
+
+        db.Account.findByIdAndUpdate(params._id, upd, {new: true}, function (err, val) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            res.json(val);
+        })
+    }
+});
+
+module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/public.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/public.js b/modules/web-control-center/src/main/js/routes/public.js
new file mode 100644
index 0000000..290ba90
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/public.js
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var router = require('express').Router();
+var passport = require('passport');
+var db = require('../db');
+
+// GET dropdown-menu template.
+router.get('/select', function (req, res) {
+    res.render('templates/select', {});
+});
+
+// GET tabs template.
+router.get('/tab', function (req, res) {
+    res.render('templates/tab', {});
+});
+
+// GET confirmation dialog.
+router.get('/confirm', function (req, res) {
+    res.render('templates/confirm', {});
+});
+
+// GET save as dialog.
+router.get('/copy', function (req, res) {
+    res.render('templates/copy', {});
+});
+
+/* GET login page. */
+router.get('/login', function (req, res) {
+    res.render('login');
+});
+
+/**
+ * Register new account.
+ */
+router.post('/register', function (req, res) {
+    db.Account.count(function (err, cnt) {
+        if (err)
+            return res.status(401).send(err.message);
+
+        req.body.admin = cnt == 0;
+
+        db.Account.register(new db.Account(req.body), req.body.password, function (err, account) {
+            if (err)
+                return res.status(401).send(err.message);
+
+            if (!account)
+                return res.status(500).send('Failed to create account.');
+
+            new db.Space({name: 'Personal space', owner: account._id}).save();
+
+            req.logIn(account, {}, function (err) {
+                if (err)
+                    return res.status(401).send(err.message);
+
+                return res.redirect('/configuration/clusters');
+            });
+        });
+    });
+});
+
+/**
+ * Login in exist account.
+ */
+router.post('/login', function (req, res, next) {
+    passport.authenticate('local', function (err, user) {
+        if (err)
+            return res.status(401).send(err.message);
+
+        if (!user)
+            return res.status(401).send('Invalid email or password');
+
+        req.logIn(user, {}, function (err) {
+            if (err)
+                return res.status(401).send(err.message);
+
+            res.redirect('/configuration/clusters');
+        });
+    })(req, res, next);
+});
+
+/**
+ * Logout.
+ */
+router.get('/logout', function (req, res) {
+    req.logout();
+
+    res.redirect('/');
+});
+
+/* GET home page. */
+router.get('/', function (req, res) {
+    if (req.isAuthenticated())
+        res.redirect('/configuration/clusters');
+    else
+        res.render('index');
+});
+
+///* GET sql page. */
+//router.get('/sql', function(req, res) {
+//    res.render('sql', { user: req.user });
+//});
+//
+///* GET clients page. */
+//router.get('/clients', function(req, res) {
+//    res.render('clients', { user: req.user });
+//});
+
+module.exports = router;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/sql.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/sql.js b/modules/web-control-center/src/main/js/routes/sql.js
new file mode 100644
index 0000000..ce4565d
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/sql.js
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var router = require('express').Router();
+var db = require('../db');
+router.get('/', function(req, res) {
+    res.render('sql/sql');
+});
+
+module.exports = router;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/summary.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/summary.js b/modules/web-control-center/src/main/js/routes/summary.js
new file mode 100644
index 0000000..f766945
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/summary.js
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var db = require('../db');
+
+var router = require('express').Router();
+
+var generatorXml = require('./generator/xml');
+var generatorJava = require('./generator/java');
+var generatorDocker = require('./generator/docker');
+
+/* GET summary page. */
+router.get('/', function (req, res) {
+    res.render('configuration/summary');
+});
+
+router.post('/generator', function (req, res) {
+    // Get cluster.
+    db.Cluster.findById(req.body._id).populate('caches').exec(function (err, cluster) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        if (!cluster)
+            return res.sendStatus(404);
+
+        var clientCache = req.body.clientNearConfiguration;
+
+        if (clientCache)
+            return res.send({
+                xmlClient: generatorXml.generateClusterConfiguration(cluster, clientCache),
+                javaClient: generatorJava.generateClusterConfiguration(cluster, req.body.javaClass, clientCache)
+            });
+
+        return res.send({
+            xmlServer: generatorXml.generateClusterConfiguration(cluster),
+            javaSnippetServer: generatorJava.generateClusterConfiguration(cluster, false),
+            javaClassServer: generatorJava.generateClusterConfiguration(cluster, true),
+            docker: generatorDocker.generateClusterConfiguration(cluster, '%OS%')
+        });
+    });
+});
+
+router.post('/download', function (req, res) {
+    // Get cluster.
+    db.Cluster.findById(req.body._id).populate('caches').exec(function (err, cluster) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        if (!cluster)
+            return res.sendStatus(404);
+
+        var clientNearConfiguration = req.body.clientNearConfiguration;
+
+        var archiver = require('archiver');
+
+        // Creating archive.
+        var zip = archiver('zip');
+
+        zip.on('error', function (err) {
+            res.status(500).send({error: err.message});
+        });
+
+        // On stream closed we can end the request.
+        res.on('close', function () {
+            return res.status(200).send('OK').end();
+        });
+
+        // Set the archive name.
+        res.attachment(cluster.name + (clientNearConfiguration ? '-client' : '') + '-configuration.zip');
+
+        var generatorCommon = require('./generator/common');
+
+        // Send the file to the page output.
+        zip.pipe(res);
+
+        var javaClass = req.body.javaClass;
+
+        if (!clientNearConfiguration) {
+            zip.append(generatorDocker.generateClusterConfiguration(cluster, req.body.os), {name: "Dockerfile"});
+
+            var props = generatorCommon.generateProperties(cluster);
+
+            if (props)
+                zip.append(props, {name: "secret.properties"});
+        }
+
+        zip.append(generatorXml.generateClusterConfiguration(cluster, clientNearConfiguration), {name: cluster.name + ".xml"})
+            .append(generatorJava.generateClusterConfiguration(cluster, javaClass, clientNearConfiguration),
+                {name: javaClass ? 'ConfigurationFactory.java' : cluster.name + '.snipplet.java'})
+            .finalize();
+    });
+});
+
+module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/configuration/caches.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/configuration/caches.jade b/modules/web-control-center/src/main/js/views/configuration/caches.jade
new file mode 100644
index 0000000..3a011fc
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/configuration/caches.jade
@@ -0,0 +1,74 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+extends sidebar
+
+append scripts
+    script(src='/caches-controller.js')
+
+include ../includes/controls
+
+block content
+    .docs-header
+        h1 Create and Configure Ignite Caches
+        hr
+    .docs-body(ng-controller='cachesController')
+        +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
+        .links(ng-hide='caches.length == 0')
+            .padding-dflt
+                lable.labelHeader Caches:
+                table(st-table='caches')
+                    tbody
+                        tr(ng-repeat='row in caches track by row._id')
+                            td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
+                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}}, {{row.atomicityMode | displayValue:atomicities:'Cache atomicity not set'}}
+        .padding-top-dflt
+            button.btn.btn-primary(ng-click='createItem()') Add cache
+        hr
+        form.form-horizontal(name='inputForm' ng-if='backupItem' novalidate)
+            div(bs-collapse data-start-collapsed='false')
+                .panel.panel-default
+                    .panel-heading
+                        h3
+                            a(bs-collapse-toggle) General
+                    .panel-collapse(bs-collapse-target)
+                        .panel-body
+                            .settings-row(ng-repeat='field in general')
+                                +form-row(['col-sm-3'], ['col-sm-3'])
+            .panel-group(bs-collapse data-allow-multiple="true")
+                div(bs-collapse data-start-collapsed='true')
+                    .panel-title(ng-show='expanded')
+                        h3
+                            a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
+                    .panel-collapse(bs-collapse-target)
+                        .span(bs-collapse data-start-collapsed='true' data-allow-multiple='true')
+                            .panel.panel-default(ng-repeat='group in advanced')
+                                .panel-heading
+                                    h3
+                                        a(bs-collapse-toggle) {{group.label}}
+                                        i.tipLabel.fa.fa-question-circle(ng-if='group.tip' bs-tooltip='joinTip(group.tip)' type='button')
+                                        i.tipLabel.fa.fa-question-circle.blank(ng-if='!group.tip')
+                                .panel-collapse(bs-collapse-target)
+                                    .panel-body
+                                        .settings-row(ng-repeat='field in group.fields')
+                                            +form-row
+                    .panel-title
+                        h3
+                            a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
+            div
+                button.btn.btn-primary(ng-disabled='inputForm.$invalid' ng-click='saveItem()') Save
+                button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
+                button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/configuration/clusters.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/configuration/clusters.jade b/modules/web-control-center/src/main/js/views/configuration/clusters.jade
new file mode 100644
index 0000000..81acfed
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/configuration/clusters.jade
@@ -0,0 +1,77 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+extends sidebar
+
+append scripts
+    script(src='/clusters-controller.js')
+
+include ../includes/controls
+
+block content
+    .docs-header
+        h1 Create and Configure Ignite Clusters
+        hr
+    .docs-body(ng-controller='clustersController')
+        +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
+        .links(ng-hide='clusters.length == 0')
+            .padding-dflt
+                lable.labelHeader Clusters:
+                table(st-table='clusters')
+                    tbody
+                        tr(ng-repeat='row in clusters track by row._id')
+                            td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
+                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.discovery.kind | displayValue:discoveries:'Discovery not set'}}
+        .padding-top-dflt
+            button.btn.btn-primary(ng-click='createItem()') &nbspAdd cluster
+            label(style='margin-left: 10px; margin-right: 10px') Use template:
+            button.btn.btn-default.base-control(ng-init='create.template = templates[0].value' ng-model='create.template' data-template='/select' data-placeholder='Choose cluster template' bs-options='item.value as item.label for item in templates' bs-select)
+            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.panel-default
+                    .panel-heading
+                        h3
+                            a(bs-collapse-toggle) General
+                    .panel-collapse(bs-collapse-target)
+                        .panel-body
+                            .settings-row(ng-repeat='field in general')
+                                +form-row
+            .panel-group(bs-collapse data-allow-multiple="true")
+                div(bs-collapse data-start-collapsed='true')
+                    .panel-title(ng-show='expanded')
+                        h3
+                            a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
+                    .panel-collapse(bs-collapse-target)
+                        .span(bs-collapse data-start-collapsed='true' data-allow-multiple='true')
+                            .panel.panel-default(ng-repeat='group in advanced')
+                                .panel-heading
+                                    h3
+                                        a(bs-collapse-toggle) {{group.label}}
+                                        i.tipLabel.fa.fa-question-circle(ng-if='group.tip' bs-tooltip='joinTip(group.tip)' type='button')
+                                        i.tipLabel.fa.fa-question-circle.blank(ng-if='!group.tip')
+                                .panel-collapse(bs-collapse-target)
+                                    .panel-body
+                                        .settings-row(ng-repeat='field in group.fields')
+                                            +form-row
+                    .panel-title
+                        h3
+                            a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
+            div
+                button.btn.btn-primary(ng-disabled='inputForm.$invalid' ng-click='saveItem()') Save
+                button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
+                button.btn.btn-primary(ng-show='backupItem._id' ng-click='removeItem()') Remove
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/configuration/metadata.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/configuration/metadata.jade b/modules/web-control-center/src/main/js/views/configuration/metadata.jade
new file mode 100644
index 0000000..d5bac06
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/configuration/metadata.jade
@@ -0,0 +1,121 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+extends sidebar
+
+append scripts
+    script(src='/metadata-controller.js')
+
+include ../includes/controls
+
+block content
+    .docs-header
+        h1 Create and Configure Cache Type Metadata
+        hr
+    .docs-body(ng-controller='metadataController')
+        +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
+        .links(ng-hide='metadatas.length == 0')
+            .padding-dflt
+                lable.labelHeader Types metadata:
+                table(st-table='metadatas')
+                    tbody
+                        tr(ng-repeat='row in metadatas track by row._id')
+                            td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
+                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
+        .padding-top-dflt
+            button.btn.btn-primary(ng-click='panels.activePanel = [0]; createItem()') &nbspAdd metadata
+            label(style='margin-left: 6px; margin-right: 10px') For:
+            button.btn.btn-default(ng-model='template' data-template='/select' data-placeholder='Choose metadata type' bs-options='item.value as item.label for item in templates' bs-select)
+            i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')
+        hr
+        .panel-group(bs-collapse ng-model='panels.activePanel' data-allow-multiple="false")
+            .panel.panel-default
+                .panel-heading
+                    h3
+                        a(bs-collapse-toggle) Manual
+                .panel-collapse(role="tabpanel" bs-collapse-target)
+                    .panel-body
+                        form.form-horizontal(name='manualForm' ng-if='backupItem' novalidate)
+                            .settings-row(ng-repeat='field in metadataManual')
+                                +form-row
+                            button.btn.btn-primary(ng-disabled='manualForm.$invalid' ng-click='saveItem()') Save
+                            button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
+                            button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove
+            .panel.panel-default
+                .panel-heading
+                    h3
+                        a(bs-collapse-toggle) Load from database
+                .panel-collapse(bs-collapse-target)
+                    .panel-body
+                        form.form-horizontal(name='dbForm' novalidate)
+                            .settings-row(ng-repeat='field in metadataDb')
+                                +form-row
+                        div(ng-hide='data.tables.length == 0')
+                            table.table-bordered.table-condensed.links-edit-small-padding.col-sm-12(st-table='data.tables')
+                                thead
+                                    tr
+                                        th.col-sm-3 Schema/Table
+                                        th Key class
+                                        th Value class
+                                tbody
+                                    tr(ng-repeat='row in data.tables')
+                                        td(colspan='{{row.tableName ? 1 : 3}}')
+                                            div.checkbox(ng-if='!row.tableName')
+                                                label(ng-click='selectSchema($index)')
+                                                    input(type='checkbox' ng-checked='row.use')
+                                                    | {{row.schemaName}}
+                                            div.checkbox(ng-if='row.tableName')
+                                                label(style='padding-left: 30px' ng-click='selectTable($index)')
+                                                    input(type='checkbox' ng-checked = 'row.use')
+                                                    | {{row.tableName}}
+                                        td(ng-if='row.tableName')
+                                            a(ng-show='data.curTableIdx != $index' ng-click='selectTable($index)') {{row.keyClass}}
+                                            input.form-control(type='text' ng-show='data.curTableIdx == $index' ng-model='data.curKeyClass' placeholder='Key class full name')
+                                        td(ng-if='row.tableName')
+                                            a(ng-show='data.curTableIdx != $index' ng-click='selectTable($index)') {{row.valueClass}}
+                                            input.form-control(type='text' ng-show='data.curTableIdx == $index' ng-model='data.curValueClass' placeholder='Value class full name')
+                        //div(ng-hide='data.curTableIdx < 0')
+                        //    table.table-bordered.table-condensed.links-edit-small-padding.col-sm-12(st-table='data.tables[data.curTableIdx].fields')
+                        //        thead
+                        //            tr
+                        //                th(style='width:45px') Use
+                        //                th(style='width:45px') Key
+                        //                th(style='width:45px') Ak
+                        //                th DB Name
+                        //                th DB Type
+                        //                th Java Name
+                        //                th Java Type
+                        //        tbody
+                        //            tr(ng-repeat='row in data.tables[data.curTableIdx].fields')
+                        //                td
+                        //                    +dbcheck('row.use')
+                        //                td
+                        //                    +dbcheck('row.key')
+                        //                td
+                        //                    +dbcheck('row.ak')
+                        //                td
+                        //                    label {{row.dbName}}
+                        //                td
+                        //                    label {{row.dbType}}
+                        //                td
+                        //                    a(ng-show='data.curFieldIdx != $index' ng-click='selectField($index)') {{row.javaName}}
+                        //                    input.form-control(type='text' ng-show='data.curFieldIdx == $index' ng-model='data.curJavaName' placeholder='Field Java name')
+                        //                td
+                        //                    a(ng-show='data.curFieldIdx != $index' ng-click='selectField($index)') {{row.javaType}}
+                        //                    input.form-control(type='text' ng-show='data.curFieldIdx == $index' ng-model='data.curJavaType' placeholder='Field Java type')
+                        button.btn.btn-primary(ng-disabled='dbForm.$invalid' ng-click='saveItem()') Save
+                        button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove
+                        button.btn.btn-primary.btn-second(ng-click='reloadMetadata()') Reload
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/configuration/sidebar.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/configuration/sidebar.jade b/modules/web-control-center/src/main/js/views/configuration/sidebar.jade
new file mode 100644
index 0000000..7289f3e
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/configuration/sidebar.jade
@@ -0,0 +1,39 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+extends ../templates/layout
+
+mixin sidebar-item(ref, num, txt)
+    li
+        a(ng-class='{active: isActive("#{ref}")}' href='#{ref}')
+            span.fa-stack
+                i.fa.fa-circle-thin.fa-stack-2x
+                i.fa.fa-stack-1x #{num}
+            | #{txt}
+
+block container
+    .row
+        .col-sm-2.border-right.section-left.greedy
+            .sidebar-nav(bs-affix)
+                ul.menu(ng-controller='activeLink')
+                    +sidebar-item('/configuration/clusters', 1, 'Clusters')
+                    +sidebar-item('/configuration/metadata', 2, 'Metadata')
+                    +sidebar-item('/configuration/caches', 3, 'Caches')
+                    +sidebar-item('/configuration/summary', 4, 'Summary')
+
+        .col-sm-10.border-left.section-right
+            .docs-content
+                block content
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/configuration/summary.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/configuration/summary.jade b/modules/web-control-center/src/main/js/views/configuration/summary.jade
new file mode 100644
index 0000000..6f2f6d8
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/configuration/summary.jade
@@ -0,0 +1,117 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+extends sidebar
+
+append scripts
+    script(src='/summary-controller.js')
+
+    script(src="//cdn.jsdelivr.net/angularjs/1.3.15/angular-animate.min.js")
+    script(src="//cdn.jsdelivr.net/angularjs/1.3.15/angular-sanitize.min.js")
+
+    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/theme-chrome.js')
+    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-xml.js')
+    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-java.js')
+    script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-dockerfile.js')
+
+append css
+
+include ../includes/controls
+
+mixin hard-link(ref, txt)
+    a(style='color:#ec1c24' href=ref target="_blank") #{txt}
+
+block content
+    .docs-header
+        h1 Configurations Summary
+        hr
+    .docs-body(ng-controller='summaryController')
+        +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
+        .padding-dflt(ng-if='clusters.length == 0')
+            | No cluster configured. You can&nbsp;
+            a(href='clusters') configure
+            | &nbsp;it.
+        .padding-dflt(ng-if='clusters.length > 0')
+            lable.labelHeader Clusters:
+            .links
+                table(st-table='clusters')
+                    tbody
+                        tr(ng-repeat='row in clusters track by row._id')
+                            td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
+                                a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
+        div(ng-show='selectedItem' role="tab" method='post' action='summary/download')
+            .padding-dflt(bs-collapse data-start-collapsed='false')
+                .panel.panel-default
+                    form.panel-heading(role='tab' method='post' action='summary/download')
+                        input(type="hidden" name="_id" value="{{selectedItem._id}}")
+                        input(type="hidden" name="os" value="{{os}}")
+                        input(type="hidden" name="javaClass" value="{{javaClassServer}}")
+                        h3
+                            a(bs-collapse-toggle) Server
+                            button.btn.btn-primary.pull-right(type='submit' style='margin-top: -5px') Download
+                    .panel-collapse(role="tabpanel" bs-collapse-target)
+                        .panel-body
+                            .configBox(ng-show='selectedItem' bs-tabs)
+                                div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
+                                    .configBox(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlServer' style='margin: 0.65em 0;')
+                                div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
+                                    .settings-row
+                                        .col-sm-1
+                                            label Generate:
+                                        .col-sm-3
+                                            button.form-control(type='button' ng-model='configServer.javaClassServer'  bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
+                                    .configBox(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaServer')
+                                div(title='<img src="/images/docker.png" width="16px" height="16px"/> Dockerfile' bs-pane)
+                                    .settings-row
+                                        p
+                                            +hard-link('https://docs.docker.com/reference/builder', 'Docker')
+                                            | &nbsp;file is a text file with instructions to create Docker image.<br/>
+                                            | To build image you have to store following Docker file with your Ignite XML configuration to the same directory.<br>
+                                            | Also you could use predefined&nbsp;
+                                            +hard-link('https://ignite.incubator.apache.org/download.html#docker', 'Apache Ignite docker image')
+                                            | . For more information about using Ignite with Docker please read&nbsp;
+                                            +hard-link('http://apacheignite.readme.io/docs/docker-deployment', 'documentation')
+                                            |.
+                                        .col-sm-2
+                                            label(for='os') Operation System:
+                                        .col-sm-4
+                                            input#os.form-control(type='text', ng-model='configServer.os' placeholder='debian:8' data-min-length="0" data-html="1" data-auto-select="true" data-animation="am-flip-x" bs-typeahead bs-options='os for os in oss')
+                                    div(ui-ace='{ onLoad: aceInit, mode: "dockerfile" }' ng-model='dockerServer')
+            .padding-dflt(bs-collapse data-start-collapsed='false')
+                .panel.panel-default
+                    form.panel-heading(role='tab' method='post' action='summary/download')
+                        input(type="hidden" name="_id" value="{{selectedItem._id}}")
+                        input(type="hidden" name="javaClass" value="{{javaClassClient}}")
+                        input(type="hidden" name="clientNearConfiguration" value="{{backupItem}}")
+
+                        h3
+                            a(bs-collapse-toggle) Client
+                            button.btn.btn-primary.pull-right(type='submit' style='margin-top: -5px') Download
+                    .panel-collapse(role="tabpanel" bs-collapse-target)
+                        .panel-body
+                            div(ng-show='selectedItem')
+                                .settings-row(ng-repeat='field in clientFields')
+                                    +form-row-custom(['col-sm-3'], ['col-sm-3'])
+                                .configBox(bs-tabs)
+                                    div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
+                                        .configBox(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlClient' style='margin: 0.65em 0;')
+                                    div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
+                                        .settings-row
+                                            .col-sm-1
+                                                label Generate:
+                                            .col-sm-4
+                                                button.form-control(type='button' ng-model='backupItem.javaClassClient' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
+                                        div(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaClient')

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/error.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/error.jade b/modules/web-control-center/src/main/js/views/error.jade
new file mode 100644
index 0000000..b458fb7
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/error.jade
@@ -0,0 +1,22 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+extends templates/layout
+
+block container
+  h1= message
+  h2= error.status
+  pre #{error.stack}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/includes/controls.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/includes/controls.jade b/modules/web-control-center/src/main/js/views/includes/controls.jade
new file mode 100644
index 0000000..4a618fa
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/includes/controls.jade
@@ -0,0 +1,322 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+mixin block-callout(titleWorkflow, contentWorkflow, whatsNextWorkflow, whatsNextContent)
+    .block-callout-parent.block-callout-border.margin-bottom-dflt
+        .block-callout
+            i.fa.fa-check-square
+            label #{titleWorkflow}
+            p(ng-bind-html=contentWorkflow)
+        .block-callout
+            i.fa.fa-check-square
+            label #{whatsNextWorkflow}
+            p(ng-bind-html=whatsNextContent)
+
+
+mixin tipField(lines)
+    i.tipField.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')
+    i.tipField.fa.fa-question-circle.blank(ng-if='!#{lines}')
+
+mixin tipLabel(lines)
+    i.tipLabel.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')
+    i.tipLabel.fa.fa-question-circle.blank(ng-if='!#{lines}')
+
+mixin ico-exclamation(mdl, err, msg)
+    i.fa.fa-exclamation-triangle.form-control-feedback(ng-show='inputForm["#{mdl}"].$error.#{err}' bs-tooltip data-title='#{msg}' type='button')
+
+mixin btn-save(show, click)
+    i.tipField.fa.fa-floppy-o(ng-show=show ng-click=click)
+
+mixin btn-add(click)
+    i.tipField.fa.fa-plus(ng-click=click)
+
+mixin btn-remove(click)
+    i.tipField.fa.fa-remove(ng-click=click)
+
+mixin btn-up(show, click)
+    i.tipField.fa.fa-arrow-up(ng-show=show ng-click=click)
+
+mixin btn-down(show, click)
+    i.tipField.fa.fa-arrow-down(ng-show=show ng-click=click)
+
+mixin table-pair-edit(keyModel, valModel, keyPlaceholder, valPlaceholder)
+    .col-sm-6(style='float: right')
+        input.form-control(type='text' ng-model=valModel placeholder=valPlaceholder)
+    label.fieldSep /
+    .input-tip
+        input.form-control(type='text' ng-model=keyModel placeholder=keyPlaceholder)
+
+mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
+    .col-sm-6
+        label.table-header #{header}:
+        +tipLabel('field.tip')
+        button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
+    table.links-edit.col-sm-12(st-table=tblMdl)
+        tbody
+            tr.col-sm-12(ng-repeat='item in #{tblMdl}')
+                td.col-sm-6
+                    div(ng-show='!tableEditing(field, $index)')
+                        a.labelFormField(ng-click='curPair = tableStartEdit(backupItem, field, $index); curKey = curPair.#{keyFld}; curValue = curPair.#{valFld}') {{$index + 1}}) {{item.#{keyFld}}} / {{item.#{valFld}}}
+                        +btn-remove('tableRemove(backupItem, field, $index)')
+                    div(ng-show='tableEditing(field, $index)')
+                        label.labelField {{$index + 1}})
+                        +btn-save('tablePairSaveVisible(curKey, curValue)', 'tablePairSave(tablePairValid, backupItem, field, curKey, curValue, $index)')
+                        +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder)
+            tr.col-sm-12(ng-show='tableNewItemActive(field)')
+                td.col-sm-6
+                    +btn-save('tablePairSaveVisible(newKey, newValue)', 'tablePairSave(tablePairValid, backupItem, field, newKey, newValue, -1)')
+                    +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder)
+
+mixin details-row
+    - var lblDetailClasses = ['col-sm-4', 'details-label']
+
+    - var detailMdl = 'getModel(backupItem, detail)[detail.model]';
+    - var detailCommon = {'ng-model': detailMdl, 'ng-required': 'detail.required'};
+
+    - var customValidators = {'ng-attr-ipaddress': '{{detail.ipaddress}}'}
+
+    div(ng-switch='detail.type')
+        div(ng-switch-when='label')
+            label {{detail.label}}
+        div.checkbox(ng-switch-when='check')
+            label
+                input(type='checkbox')&attributes(detailCommon)
+                |{{detail.label}}
+                +tipLabel('detail.tip')
+        div(ng-switch-when='text')
+            label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
+            .col-sm-8
+                +tipField('detail.tip')
+                .input-tip
+                    input.form-control(type='text' placeholder='{{detail.placeholder}}')&attributes(detailCommon)
+        div(ng-switch-when='number' )
+            label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
+            .col-sm-8
+                +tipField('detail.tip')
+                .input-tip
+                    input.form-control(name='{{detail.model}}' type='number' placeholder='{{detail.placeholder}}' min='{{detail.min ? detail.min : 0}}' max='{{detail.max ? detail.max : Number.MAX_VALUE}}')&attributes(detailCommon)
+                    +ico-exclamation('{{detail.model}}', 'min', 'Value is less than allowable minimum.')
+                    +ico-exclamation('{{detail.model}}', 'max', 'Value is more than allowable maximum.')
+                    +ico-exclamation('{{detail.model}}', 'number', 'Invalid value. Only numbers allowed.')
+        div(ng-switch-when='dropdown')
+            label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
+            .col-sm-8
+                +tipField('detail.tip')
+                .input-tip
+                    button.form-control(bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in {{detail.items}}')&attributes(detailCommon)
+        div(ng-switch-when='dropdown-multiple')
+            label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
+            .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')&attributes(detailCommon)
+            div(ng-if='detail.label')
+                label.table-header {{detail.label}}:
+                +tipLabel('detail.tableTip')
+            table.col-sm-12.links-edit-details(st-table='#{detailMdl}')
+                tbody
+                    tr(ng-repeat='item in #{detailMdl} track by $index')
+                        td
+                            div(ng-show='!tableEditing(detail, $index)')
+                                a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, detail, $index)') {{$index + 1}}) {{item}}
+                                +btn-remove('tableRemove(backupItem, detail, $index)')
+                                +btn-down('detail.reordering && tableSimpleDownVisible(backupItem, detail, $index)', 'tableSimpleDown(backupItem, detail, $index)')
+                                +btn-up('detail.reordering && $index > 0', 'tableSimpleUp(backupItem, detail, $index)')
+                            div(ng-show='tableEditing(detail, $index)')
+                                label.labelField {{$index + 1}})
+                                +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, detail, curValue, $index)')
+                                .input-tip.form-group.has-feedback
+                                    input.form-control(name='{{detail.model}}.edit' type='text' ng-model='curValue' placeholder='{{detail.placeholder}}')&attributes(customValidators)
+                                    +ico-exclamation('{{detail.model}}.edit', 'ipaddress', 'Invalid address, see help for format description.')
+            button.btn.btn-primary.fieldButton(ng-disabled='!newValue' ng-click='tableSimpleSave(tableSimpleValid, backupItem, detail, newValue, -1)') Add
+            +tipField('detail.tip')
+            .input-tip.form-group.has-feedback
+                input.form-control(name='{{detail.model}}' type='text' ng-model='newValue' ng-focus='tableNewItem(detail)' placeholder='{{detail.placeholder}}')&attributes(customValidators)
+                +ico-exclamation('{{detail.model}}', 'ipaddress', 'Invalid address, see help for format description.')
+
+mixin table-db-field-edit(dbName, dbType, javaName, javaType)
+    div(style='width: 22%; float: right')
+        button.form-control(ng-model=javaType bs-select data-placeholder='Java type' bs-options='item.value as item.label for item in {{javaTypes}}')
+    label.fieldSep /
+    div(style='width: 20%; float: right')
+        input.form-control(type='text' ng-model=javaName placeholder='Java name')
+    label.fieldSep /
+    div(style='width: 22%; float: right')
+        button.form-control(ng-model=dbType bs-select data-placeholder='JDBC type' bs-options='item.value as item.label for item in {{jdbcTypes}}')
+    label.fieldSep /
+    .input-tip
+        input.form-control(type='text' ng-model=dbName placeholder='DB name')
+
+mixin table-group-item-edit(fieldName, className, direction)
+    div(style='width: 15%; float: right')
+        button.form-control(ng-model=direction bs-select data-placeholder='Sort' bs-options='item.value as item.label for item in {{sortDirections}}')
+    label.fieldSep /
+    div(style='width: 38%; float: right')
+        input.form-control(type='text' ng-model=className placeholder='Class name')
+    label.fieldSep /
+    .input-tip
+        input.form-control(type='text' ng-model=fieldName placeholder='Field name')
+
+mixin form-row
+    +form-row-custom(['col-sm-2'], ['col-sm-4'])
+
+mixin form-row-custom(lblClasses, fieldClasses)
+    - var fieldMdl = 'getModel(backupItem, field)[field.model]';
+    - var fieldCommon = {'ng-model': fieldMdl, 'ng-required': 'field.required || required(field)'};
+    - var fieldRequiredClass = '{true: "required"}[field.required || required(field)]'
+    - var fieldHide = '{{field.hide}}'
+
+    div(ng-switch='field.type')
+        div.col-sm-6(ng-switch-when='label')
+            label {{field.label}}
+        div.checkbox.col-sm-6(ng-switch-when='check' ng-hide=fieldHide)
+            label
+                input(type='checkbox')&attributes(fieldCommon)
+                | {{field.label}}
+                +tipLabel('field.tip')
+        div(ng-switch-when='text' ng-hide=fieldHide)
+            label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
+            div(class=fieldClasses)
+                +tipField('field.tip')
+                .input-tip
+                    input.form-control(type='text' placeholder='{{field.placeholder}}')&attributes(fieldCommon)
+        div(ng-switch-when='password' ng-hide=fieldHide)
+            label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
+            div(class=fieldClasses)
+                +tipField('field.tip')
+                .input-tip
+                    input.form-control(type='password' placeholder='{{field.placeholder}}')&attributes(fieldCommon)
+        div(ng-switch-when='number' ng-hide=fieldHide)
+            label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
+            div(class=fieldClasses)
+                +tipField('field.tip')
+                .input-tip
+                    input.form-control(name='{{field.model}}' type='number' placeholder='{{field.placeholder}}' min='{{field.min ? field.min : 0}}' max='{{field.max ? field.max : Number.MAX_VALUE}}')&attributes(fieldCommon)
+                    +ico-exclamation('{{field.model}}', 'min', 'Value is less than allowable minimum.')
+                    +ico-exclamation('{{field.model}}', 'max', 'Value is more than allowable maximum.')
+                    +ico-exclamation('{{field.model}}', 'number', 'Invalid value. Only numbers allowed.')
+        div(ng-switch-when='dropdown' ng-hide=fieldHide)
+            label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
+            div(class=fieldClasses)
+                +tipField('field.tip')
+                .input-tip
+                    button.form-control(bs-select data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label for item in {{field.items}}')&attributes(fieldCommon)
+        div(ng-switch-when='dropdown-multiple' ng-hide=fieldHide)
+            label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
+            div(class=fieldClasses)
+                +tipField('field.tip')
+                .input-tip
+                    button.form-control(bs-select ng-disabled='{{field.items}}.length == 0' data-multiple='1' data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label for item in {{field.items}}')&attributes(fieldCommon)
+            a.customize(ng-show='field.addLink' ng-href='{{field.addLink.ref}}') {{field.addLink.label}}
+        div(ng-switch-when='dropdown-details' ng-hide=fieldHide)
+            - var expanded = 'field.details[' + fieldMdl + '].expanded'
+
+            label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
+            div(class=fieldClasses)
+                +tipField('field.tip')
+                .input-tip
+                    button.form-control(bs-select data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label for item in {{field.items}}')&attributes(fieldCommon)
+            a.customize(ng-show='#{fieldMdl} && field.details[#{fieldMdl}].fields' ng-click='#{expanded} = !#{expanded}') {{#{expanded} ? "Hide settings" : "Show settings"}}
+            .col-sm-6.panel-details(ng-show='#{expanded} && #{fieldMdl}')
+                .details-row(ng-repeat='detail in field.details[#{fieldMdl}].fields')
+                    +details-row
+        div(ng-switch-when='table-simple' ng-hide=fieldHide)&attributes(fieldCommon)
+            .col-sm-6
+                label.table-header {{field.label}}:
+                +tipLabel('field.tableTip')
+                button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
+            table.links-edit.col-sm-12(st-table='#{fieldMdl}')
+                tbody
+                    tr.col-sm-12(ng-repeat='item in #{fieldMdl} track by $index')
+                        td.col-sm-6
+                            div(ng-show='!tableEditing(field, $index)')
+                                a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, field, $index)') {{$index + 1}}) {{item | compact}}
+                                +btn-remove('tableRemove(backupItem, field, $index)')
+                                +btn-down('field.reordering && tableSimpleDownVisible(backupItem, field, $index)', 'tableSimpleDown(backupItem, field, $index)')
+                                +btn-up('field.reordering && $index > 0', 'tableSimpleUp(backupItem, field, $index)')
+                            div(ng-show='tableEditing(field, $index)')
+                                label.labelField {{$index + 1}})
+                                +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, curValue, $index)')
+                                .input-tip
+                                    input.form-control(type='text' ng-model='curValue' placeholder='{{field.placeholder}}')
+                    tr.col-sm-12(ng-show='tableNewItemActive(field)')
+                        td.col-sm-6
+                            +btn-save('tableSimpleSaveVisible(newValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)')
+                            .input-tip
+                                input.form-control(type='text' ng-model='newValue' placeholder='{{field.placeholder}}')
+        div(ng-switch-when='indexedTypes')
+            +table-pair('Index key-value type pairs', fieldMdl, 'keyClass', 'valueClass', 'Key class full name', 'Value class full name')
+        div(ng-switch-when='queryFields' ng-hide=fieldHide)
+            +table-pair('{{field.label}}', fieldMdl, 'name', 'className', 'Field name', 'Field class full name')
+        div(ng-switch-when='dbFields' ng-hide=fieldHide)
+            .col-sm-6
+                label.table-header {{field.label}}:
+                +tipLabel('field.tip')
+                button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
+            table.links-edit.col-sm-12(st-table=fieldMdl)
+                tbody
+                    tr.col-sm-12(ng-repeat='item in #{fieldMdl}')
+                        td.col-sm-6
+                            div(ng-show='!tableEditing(field, $index)')
+                                a.labelFormField(ng-click='curField = tableStartEdit(backupItem, field, $index); curDbName = curField.dbName; curDbType = curField.dbType; curJavaName = curField.javaName; curJavaType = curField.javaType') {{$index + 1}}) {{item.dbName}} / {{item.dbType}} / {{item.javaName}} / {{item.javaType}}
+                                +btn-remove('tableRemove(backupItem, field, $index)')
+                            div(ng-if='tableEditing(field, $index)')
+                                label.labelField {{$index + 1}})
+                                +btn-save('tableDbFieldSaveVisible(curDbName, curDbType, curJavaName, curJavaType)', 'tableDbFieldSave(field, curDbName, curDbType, curJavaName, curJavaType, $index)')
+                                +table-db-field-edit('curDbName', 'curDbType', 'curJavaName', 'curJavaType')
+                    tr(ng-show='tableNewItemActive(field)')
+                        td.col-sm-6
+                            +btn-save('tableDbFieldSaveVisible(newDbName, newDbType, newJavaName, newJavaType)', 'tableDbFieldSave(field, newDbName, newDbType, newJavaName, newJavaType, -1)')
+                            +table-db-field-edit('newDbName', 'newDbType', 'newJavaName', 'newJavaType')
+        div(ng-switch-when='queryGroups' ng-hide=fieldHide)
+            .col-sm-6
+                label.table-header {{field.label}}:
+                +tipLabel('field.tip')
+                button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
+            table.links-edit.col-sm-12(st-table=fieldMdl)
+                tbody
+                    tr.col-sm-12(ng-repeat='group in #{fieldMdl}')
+                        td.col-sm-6
+                            div
+                                .col-sm-12(ng-show='!tableEditing(field, $index)')
+                                    a.labelFormField(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curGroupName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{group.name}}
+                                    +btn-remove('tableRemove(backupItem, field, $index)')
+                                    +btn-add('tableGroupNewItem($index); newDirection = "ASC"')
+                                div(ng-show='tableEditing(field, $index)')
+                                    label.labelField {{$index + 1}})
+                                    +btn-save('tableGroupSaveVisible(curGroupName)', 'tableGroupSave(curGroupName, $index)')
+                                    .input-tip
+                                        input.form-control(type='text' ng-model='curGroupName' placeholder='Index name')
+                                div
+                                    table.links-edit.col-sm-12(st-table='group.fields' ng-init='groupIndex = $index')
+                                        tr(ng-repeat='groupItem in group.fields')
+                                            td
+                                                div(ng-show='!tableGroupItemEditing(groupIndex, $index)')
+                                                    a.labelFormField(ng-click='curGroupItem = tableGroupItemStartEdit(groupIndex, $index); curFieldName = curGroupItem.name; curClassName = curGroupItem.className; curDirection = curGroupItem.direction') {{$index + 1}}) {{groupItem.name}} / {{groupItem.className}} / {{groupItem.direction}}
+                                                    +btn-remove('tableRemoveGroupItem(group, $index)')
+                                                div(ng-show='tableGroupItemEditing(groupIndex, $index)')
+                                                    label.labelField {{$index + 1}})
+                                                    +btn-save('tableGroupItemSaveVisible(curFieldName, curClassName)', 'tableGroupItemSave(curFieldName, curClassName, curDirection, groupIndex, $index)')
+                                                    +table-group-item-edit('curFieldName', 'curClassName', 'curDirection')
+                                        tr.col-sm-12(style='padding-left: 18px' ng-show='tableGroupNewItemActive(groupIndex)')
+                                            td
+                                                +btn-save('tableGroupItemSaveVisible(newFieldName, newClassName)', 'tableGroupItemSave(newFieldName, newClassName, newDirection, groupIndex, -1)')
+                                                +table-group-item-edit('newFieldName', 'newClassName', 'newDirection')
+                    tr.col-sm-12(ng-show='tableNewItemActive(field)')
+                        td.col-sm-6
+                            +btn-save('tableGroupSaveVisible(newGroupName)', 'tableGroupSave(newGroupName, -1)')
+                            .input-tip
+                                input.form-control(type='text' ng-model='newGroupName' placeholder='Group name')
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/includes/footer.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/includes/footer.jade b/modules/web-control-center/src/main/js/views/includes/footer.jade
new file mode 100644
index 0000000..d8ff5d7
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/includes/footer.jade
@@ -0,0 +1,22 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+.container.container-footer
+    footer
+        center
+            p Apache Ignite Control Center, version 1.0.0
+            p © 2015 The Apache Software Foundation.
+            p Apache, Apache Ignite, the Apache feather and the Apache Ignite logo are trademarks of The Apache Software Foundation.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/includes/header.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/includes/header.jade b/modules/web-control-center/src/main/js/views/includes/header.jade
new file mode 100644
index 0000000..ab2d31e
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/includes/header.jade
@@ -0,0 +1,39 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+mixin header-item(active, ref, txt)
+    li
+        a(ng-class='{active: isActive("#{active}")}' href='#{ref}') #{txt}
+
+header.header(id='header')
+    .viewedUser(ng-show='becomeUsed') Currently assuming "
+        strong {{user.username}}
+        | ",&nbsp;&nbsp;
+        a(href='/admin/become') revert to your identity.
+    .container
+        h1.navbar-brand
+            a(href='/') Apache Ignite Web Configurator
+        .navbar-collapse.collapse(ng-controller='auth')
+            ul.nav.navbar-nav(ng-controller='activeLink' ng-show='user')
+                +header-item('/configuration', '/configuration/clusters', 'Configuration')
+                //+header-item('/monitoring', '/monitoring', 'Monitoring')
+                //+header-item('/sql', '/sql', 'SQL')
+                //+header-item('/deploy', '/deploy', 'Deploy')
+            ul.nav.navbar-nav.pull-right
+                li(ng-if='user')
+                    a.dropdown-toggle(data-toggle='dropdown' bs-dropdown='userDropdown' data-placement='bottom-right') {{user.username}}
+                        span.caret
+                li.nav-login(ng-if='!user')
+                    a(ng-click='login()' href='#') Log In
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/index.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/index.jade b/modules/web-control-center/src/main/js/views/index.jade
new file mode 100644
index 0000000..999c4f8
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/index.jade
@@ -0,0 +1,30 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+extends templates/layout
+
+block container
+    .row
+        .docs-content
+            div
+                p
+                    | Apache Ignite<sup>tm</sup> In-Memory Data Fabric is a high-performance,
+                    | integrated and distributed in-memory platform for computing and transacting on large-scale data
+                    | sets in real-time, orders of magnitude faster than possible with traditional disk-based or flash technologies.
+        .block-image.block-display-image
+                img(ng-src='https://www.filepicker.io/api/file/lydEeGB6Rs9hwbpcQxiw' alt='Apache Ignite stack')
+        .text-center(ng-controller='auth')
+            button.btn.btn-primary(ng-click='login()' href='#') Configure Now

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/login.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/login.jade b/modules/web-control-center/src/main/js/views/login.jade
new file mode 100644
index 0000000..5bb39dd
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/login.jade
@@ -0,0 +1,55 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+mixin lbl(txt)
+    label.col-sm-3.required #{txt}
+
+.modal.center(role='dialog')
+    .modal-dialog
+        .modal-content
+            .modal-header.header
+                div(id='errors-container')
+                button.close(type='button', ng-click='$hide()', aria-hidden='true') &times;
+                h1.navbar-brand
+                    a(href='/') Apache Ignite Web Configurator
+                h4.modal-title(style='padding-right: 55px') Authentication
+                p(style='padding-right: 55px') Log in or register in order to collaborate
+            form.form-horizontal(name='loginForm')
+                .modal-body.row
+                    .col-sm-9.login.col-sm-offset-1
+                        .details-row(ng-show='action == "register"')
+                            +lbl('Full Name:')
+                            .col-sm-9
+                                input.form-control(type='text', ng-model='user_info.username', placeholder='John Smith', focus-me='action=="register"', ng-required='action=="register"')
+                        .details-row
+                            +lbl('Email:')
+                            .col-sm-9
+                                input.form-control(type='email', ng-model='user_info.email', placeholder='you@domain.com', focus-me='action=="login"', required)
+                        .details-row
+                            +lbl('Password:')
+                            .col-sm-9
+                                input.form-control(type='password', ng-model='user_info.password', placeholder='Password', required, ng-keyup='action == "login" && $event.keyCode == 13 ? auth(action, user_info) : null')
+                        .details-row(ng-show='action == "register"')
+                            +lbl('Confirm:')
+                            .col-sm-9.input-tip.has-feedback
+                                input.form-control(type='password', ng-model='user_info.confirm', match="user_info.password" placeholder='Confirm password', required, ng-keyup='$event.keyCode == 13 ? auth(action, user_info) : null')
+
+            .modal-footer
+                a.show-signup.ng-hide(ng-show='action != "login"', ng-click='action = "login";') log in
+                a.show-signup(ng-show="action != 'register'", ng-click='action = "register";') sign up
+                | &nbsp;or&nbsp;
+                button.btn.btn-primary(ng-show='action == "login"' ng-click='auth(action, user_info)') Log In
+                button.btn.btn-primary(ng-show='action == "register"' ng-disabled='loginForm.$invalid || user_info.password != user_info.confirm' ng-click='auth(action, user_info)') Sign Up

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/settings/admin.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/settings/admin.jade b/modules/web-control-center/src/main/js/views/settings/admin.jade
new file mode 100644
index 0000000..4d50631
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/settings/admin.jade
@@ -0,0 +1,58 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+         http://www.apache.org/licenses/LICENSE-2.0
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+extends ../templates/layout
+
+append scripts
+    script(src='/admin-controller.js')
+
+block container
+    .row(ng-controller='adminController')
+        .docs-content
+            .docs-header
+                h1 List of registered users
+                hr
+            .docs-body
+                table.table.table-striped.admin(st-table='displayedUsers' st-safe-src='users')
+                    thead
+                        tr
+                            th.header(colspan='5')
+                                .col-sm-2.pull-right
+                                    input.form-control(type='text' st-search='' placeholder='Filter users...')
+                        tr
+                            th(st-sort='username') User name
+                            th(st-sort='email') Email
+                            th.col-sm-2(st-sort='lastLogin') Last login
+                            th(width='1%'  st-sort='admin') Admin
+                            th(width='1%') Actions
+                    tbody
+                        tr(ng-repeat='row in displayedUsers')
+                            td {{row.username}}
+                            td
+                                a(ng-href='mailto:{{row.email}}') {{row.email}}
+                            td
+                                span {{row.lastLogin | date:'medium'}}
+                            td(style='text-align: center;')
+                                input(type='checkbox' ng-disabled='row.adminChanging || row._id == user._id'
+                                    ng-model='row.admin' ng-change='toggleAdmin(row)')
+                            td(style='text-align: center;')
+                                a(ng-click='removeUser(row)' ng-show='row._id != user._id' bs-tooltip data-title='Remove user')
+                                    i.fa.fa-remove
+                                a(style='margin-left: 5px' ng-href='admin/become?viewedUserId={{row._id}}' ng-show='row._id != user._id' bs-tooltip data-title='Become this user')
+                                    i.fa.fa-eye
+                    tfoot
+                        tr
+                            td(colspan='5' class="text-right")
+                                div(st-pagination st-items-by-page='15' st-displayed-pages='5')
+

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/settings/profile.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/settings/profile.jade b/modules/web-control-center/src/main/js/views/settings/profile.jade
new file mode 100644
index 0000000..dbc6dea
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/settings/profile.jade
@@ -0,0 +1,58 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+extends ../templates/layout
+
+mixin lbl(txt)
+    label.col-sm-2.required.labelFormField #{txt}
+
+append scripts
+    script(src='/profile-controller.js')
+
+block container
+    .row(ng-controller='profileController')
+        .docs-content
+            .docs-header
+                h1 User profile
+                hr
+            .docs-body
+                form.form-horizontal(name='profileForm' novalidate)
+                    .col-sm-10(style='padding: 0')
+                        .details-row
+                            +lbl('User name:')
+                            .col-sm-4
+                                input.form-control(type='text' ng-model='profileUser.username' placeholder='Input name' required)
+                        .details-row
+                            +lbl('Email:')
+                            .col-sm-4
+                                input.form-control(type='email' ng-model='profileUser.email' placeholder='you@domain.com' required)
+                        .details-row
+                            .checkbox
+                                label
+                                    input(type="checkbox" ng-model='profileUser.changePassword')
+                                    | Change password
+                        div(ng-show='profileUser.changePassword')
+                            .details-row
+                                +lbl('New password:')
+                                .col-sm-4
+                                    input.form-control(type='password', ng-model='profileUser.newPassword' placeholder='New password' ng-required='profileUser.changePassword')
+                            .details-row
+                                +lbl('Confirm:')
+                                .col-sm-4
+                                    input.form-control(type='password', ng-model='profileUser.confirmPassword' match='profileUser.newPassword' placeholder='Confirm new password' ng-required='profileUser.changePassword')
+                    .col-sm-12.details-row
+                        button.btn.btn-primary(ng-disabled='profileForm.$invalid' ng-click='saveUser()') Save
+

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/templates/confirm.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/templates/confirm.jade b/modules/web-control-center/src/main/js/views/templates/confirm.jade
new file mode 100644
index 0000000..bdaf9bf
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/templates/confirm.jade
@@ -0,0 +1,27 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+.modal(tabindex='-1' role='dialog')
+    .modal-dialog
+        .modal-content
+            .modal-header
+                button.close(type="button" ng-click="$hide()") &times;
+                h4.modal-title Confirmation
+            .modal-body(ng-show='content')
+                p(ng-bind-html='content' style='text-align: center;')
+            .modal-footer
+                button.btn.btn-default(type="button" ng-click="$hide()") Cancel
+                button.btn.btn-primary(type="button" ng-click="ok()") Confirm
\ No newline at end of file



[06/50] [abbrv] incubator-ignite git commit: Merge remote-tracking branch 'origin/ignite-843' into ignite-843

Posted by an...@apache.org.
Merge remote-tracking branch 'origin/ignite-843' into ignite-843


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

Branch: refs/heads/ignite-1121
Commit: 064ea503e62afcd78f6b6e15d60049b80b8c61b1
Parents: d51f412 85062e3
Author: AKuznetsov <ak...@gridgain.com>
Authored: Mon Jul 20 18:12:00 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Mon Jul 20 18:12:00 2015 +0700

----------------------------------------------------------------------
 modules/web-control-center/nodejs/app.js | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------



[12/50] [abbrv] incubator-ignite git commit: Merge branch 'ignite-843' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-1121

Posted by an...@apache.org.
Merge branch 'ignite-843' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-1121


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

Branch: refs/heads/ignite-1121
Commit: 4bc8237581c62587db5994f85fa903ccf21be8e3
Parents: 1db3736 b34fb93
Author: Andrey <an...@gridgain.com>
Authored: Tue Jul 21 09:30:01 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Tue Jul 21 09:30:01 2015 +0700

----------------------------------------------------------------------
 .../nodejs/controllers/clusters-controller.js   |  2 +-
 .../nodejs/controllers/metadata-controller.js   | 98 ++++++++++++++++----
 .../nodejs/controllers/models/metadata.json     |  2 +-
 modules/web-control-center/nodejs/db.js         |  2 +-
 .../nodejs/public/stylesheets/style.less        | 30 ++++--
 .../nodejs/routes/generator/common.js           |  1 -
 .../nodejs/views/configuration/metadata.jade    |  1 +
 .../nodejs/views/includes/controls.jade         | 40 ++++++--
 8 files changed, 135 insertions(+), 41 deletions(-)
----------------------------------------------------------------------



[44/50] [abbrv] incubator-ignite git commit: IGNITE-843 Updated DEVNOTES.txt

Posted by an...@apache.org.
IGNITE-843 Updated DEVNOTES.txt


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

Branch: refs/heads/ignite-1121
Commit: 58e0c64cff5fa2f0e4dd3f8725f5788c42d35eb5
Parents: 8a33572
Author: AKuznetsov <ak...@gridgain.com>
Authored: Wed Jul 22 21:50:44 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Wed Jul 22 21:50:44 2015 +0700

----------------------------------------------------------------------
 modules/web-control-center/src/main/js/DEVNOTES.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/58e0c64c/modules/web-control-center/src/main/js/DEVNOTES.txt
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/DEVNOTES.txt b/modules/web-control-center/src/main/js/DEVNOTES.txt
index aa56011..e8c558c 100644
--- a/modules/web-control-center/src/main/js/DEVNOTES.txt
+++ b/modules/web-control-center/src/main/js/DEVNOTES.txt
@@ -6,7 +6,7 @@ How to deploy:
 1. Install locally NodeJS using installer from site https://nodejs.org for your OS.
 2. Install locally MongoDB folow instructions from site http://docs.mongodb.org/manual/installation
 3. Checkout ignite-843 branch.
-4. Change directory '$IGNITE_HOME/modules/web-control-center/nodejs'.
+4. Change directory '$IGNITE_HOME/modules/web-control-center/src/main/js'.
 5. Run "npm install" in terminal for download all dependencies.
 
 Steps 1 - 5 should be executed once.
@@ -16,6 +16,6 @@ How to run:
 1. Run MongoDB.
  1.1 In terminal change dir to $MONGO_ISNTALL_DIR/server/3.0/bin.
  1.2 Run "mongod".
-2. In new terminal change directory '$IGNITE_HOME/modules/web-control-center/nodejs'.
+2. In new terminal change directory '$IGNITE_HOME/modules/web-control-center/src/main/js'.
 3. Start application by executing "npm start".
 4. In browser open: http://localhost:3000
\ No newline at end of file


[24/50] [abbrv] incubator-ignite git commit: # ignite-843 Fixed admin page

Posted by an...@apache.org.
# ignite-843 Fixed admin page


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

Branch: refs/heads/ignite-1121
Commit: 66e732886653bcd209282396137420d727dd4ac5
Parents: 6ed40f8
Author: Andrey <an...@gridgain.com>
Authored: Wed Jul 22 08:52:21 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Wed Jul 22 08:52:21 2015 +0700

----------------------------------------------------------------------
 .../nodejs/views/includes/controls.jade                 | 12 ++++++------
 .../web-control-center/nodejs/views/settings/admin.jade |  2 +-
 .../nodejs/views/settings/profile.jade                  |  2 +-
 modules/web-control-center/nodejs/views/sql/sql.jade    |  2 +-
 4 files changed, 9 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/66e73288/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 5aded25..0725749 100644
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ b/modules/web-control-center/nodejs/views/includes/controls.jade
@@ -54,14 +54,14 @@ mixin table-pair-edit(keyModel, valModel, keyPlaceholder, valPlaceholder)
         input.form-control(type='text' ng-model=keyModel placeholder=keyPlaceholder)
 
 mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
-    .col-sm-6
+    .col-sm-12
         label.table-header #{header}:
         +tipLabel('field.tip')
         button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
-    table.links-edit.col-sm-12(st-table=tblMdl)
+    table.panel-details.links-edit.col-sm-12(st-table=tblMdl)
         tbody
             tr.col-sm-12(ng-repeat='item in #{tblMdl}')
-                td.col-sm-6
+                td.col-sm-12
                     div(ng-show='!tableEditing(field, $index)')
                         a.labelFormField(ng-click='curPair = tableStartEdit(backupItem, field, $index); curKey = curPair.#{keyFld}; curValue = curPair.#{valFld}') {{$index + 1}}) {{item.#{keyFld}}} / {{item.#{valFld}}}
                         +btn-remove('tableRemove(backupItem, field, $index)')
@@ -70,7 +70,7 @@ mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
                         +btn-save('tablePairSaveVisible(curKey, curValue)', 'tablePairSave(tablePairValid, backupItem, field, curKey, curValue, $index)')
                         +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder)
             tr.col-sm-12(ng-show='tableNewItemActive(field)')
-                td.col-sm-6
+                td.col-sm-12
                     +btn-save('tablePairSaveVisible(newKey, newValue)', 'tablePairSave(tablePairValid, backupItem, field, newKey, newValue, -1)')
                     +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder)
 
@@ -251,9 +251,9 @@ mixin form-row-custom(lblClasses, fieldClasses)
                             +btn-save('tableSimpleSaveVisible(newValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)')
                             .input-tip
                                 input.form-control(type='text' ng-model='newValue' placeholder='{{field.placeholder}}')
-        div(ng-switch-when='indexedTypes')
+        .col-sm-6(ng-switch-when='indexedTypes')
             +table-pair('Index key-value type pairs', fieldMdl, 'keyClass', 'valueClass', 'Key class full name', 'Value class full name')
-        div(ng-switch-when='queryFields' ng-hide=fieldHide)
+        .col-sm-6(ng-switch-when='queryFields' ng-hide=fieldHide)
             +table-pair('{{field.label}}', fieldMdl, 'name', 'className', 'Field name', 'Field class full name')
         div(ng-switch-when='dbFields' ng-hide=fieldHide)
             .col-sm-6

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/66e73288/modules/web-control-center/nodejs/views/settings/admin.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/settings/admin.jade b/modules/web-control-center/nodejs/views/settings/admin.jade
index fb0c0d1..4d50631 100644
--- a/modules/web-control-center/nodejs/views/settings/admin.jade
+++ b/modules/web-control-center/nodejs/views/settings/admin.jade
@@ -18,7 +18,7 @@ append scripts
     script(src='/admin-controller.js')
 
 block container
-    .greedy.row(ng-controller='adminController')
+    .row(ng-controller='adminController')
         .docs-content
             .docs-header
                 h1 List of registered users

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/66e73288/modules/web-control-center/nodejs/views/settings/profile.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/settings/profile.jade b/modules/web-control-center/nodejs/views/settings/profile.jade
index 21820ab..dbc6dea 100644
--- a/modules/web-control-center/nodejs/views/settings/profile.jade
+++ b/modules/web-control-center/nodejs/views/settings/profile.jade
@@ -23,7 +23,7 @@ append scripts
     script(src='/profile-controller.js')
 
 block container
-    .row.greedy(ng-controller='profileController')
+    .row(ng-controller='profileController')
         .docs-content
             .docs-header
                 h1 User profile

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/66e73288/modules/web-control-center/nodejs/views/sql/sql.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/sql/sql.jade b/modules/web-control-center/nodejs/views/sql/sql.jade
index 84617b2..7c4ddaf 100644
--- a/modules/web-control-center/nodejs/views/sql/sql.jade
+++ b/modules/web-control-center/nodejs/views/sql/sql.jade
@@ -25,7 +25,7 @@ block container
     .docs-header
         h1 Connect to Ignite and execute SQL queries
         hr
-    div.greedy(ng-controller='cacheViewerController')
+    div(ng-controller='cacheViewerController')
         h4 Sql console
 
         table#queryTable(cellpadding=0, cellspacing=0, ng-init='queryType = "sql"')


[19/50] [abbrv] incubator-ignite git commit: IGNITE-843 Fixed metadata remove.

Posted by an...@apache.org.
IGNITE-843 Fixed metadata remove.


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

Branch: refs/heads/ignite-1121
Commit: 53cd4b3735d2b3ac993c543831a0984999979ed8
Parents: 2030dfb
Author: AKuznetsov <ak...@gridgain.com>
Authored: Tue Jul 21 13:53:33 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Tue Jul 21 13:53:33 2015 +0700

----------------------------------------------------------------------
 .../web-control-center/nodejs/controllers/metadata-controller.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/53cd4b37/modules/web-control-center/nodejs/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/controllers/metadata-controller.js b/modules/web-control-center/nodejs/controllers/metadata-controller.js
index bf08194..eb48494 100644
--- a/modules/web-control-center/nodejs/controllers/metadata-controller.js
+++ b/modules/web-control-center/nodejs/controllers/metadata-controller.js
@@ -254,7 +254,7 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
                 }]
         };
 
-        $scope.metadata = [];
+        $scope.metadatas = [];
 
         $http.get('/models/metadata.json')
             .success(function (data) {
@@ -392,7 +392,7 @@ controlCenterModule.controller('metadataController', ['$scope', '$http', '$commo
                             });
 
                             if (idx >= 0) {
-                                metadatas.splice(i, idx);
+                                metadatas.splice(idx, 1);
 
                                 if (metadatas.length > 0)
                                     $scope.selectItem(metadatas[0]);