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 2016/09/08 04:46:18 UTC

[01/50] [abbrv] ignite git commit: IGNITE-2278 Restored devnotes.

Repository: ignite
Updated Branches:
  refs/heads/ignite-3629 [created] 610ad247f


IGNITE-2278 Restored devnotes.


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

Branch: refs/heads/ignite-3629
Commit: ffe79eea610c202641fce66582639c4c0fd3c522
Parents: b377e83
Author: vsisko <vs...@gridgain.com>
Authored: Mon Aug 22 10:28:44 2016 +0700
Committer: vsisko <vs...@gridgain.com>
Committed: Mon Aug 22 10:28:44 2016 +0700

----------------------------------------------------------------------
 modules/web-console/DEVNOTES.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ffe79eea/modules/web-console/DEVNOTES.txt
----------------------------------------------------------------------
diff --git a/modules/web-console/DEVNOTES.txt b/modules/web-console/DEVNOTES.txt
index 3732b78..0b35ab0 100644
--- a/modules/web-console/DEVNOTES.txt
+++ b/modules/web-console/DEVNOTES.txt
@@ -25,10 +25,10 @@ How to run console in development mode:
 1. Configure MongoDB to run as service or in terminal change dir to $MONGO_INSTALL_DIR/server/3.0/bin
   and start MongoDB by executing "mongod".
 
-2. In new terminal change directory to '$IGNITE_HOME/modules/web-console/src/main/js'.
-   If needed run "npm install --no-optional" (if dependencies changed) and run "node serve" to start backend.
+2. In new terminal change directory to '$IGNITE_HOME/modules/web-console/backend'.
+   If needed run "npm install --no-optional" (if dependencies changed) and run "npm start" to start backend.
 
-3. In new terminal change directory to '$IGNITE_HOME/modules/web-console/src/main/js'
+3. In new terminal change directory to '$IGNITE_HOME/modules/web-console/frontend'
   and start webpack in development mode "npm run dev" .
 
 4. In browser open: http://localhost:9000


[18/50] [abbrv] ignite git commit: Updated development instructions.

Posted by an...@apache.org.
Updated development instructions.


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

Branch: refs/heads/ignite-3629
Commit: 916be77e62e2f585fd65593aa99be606ce28cafa
Parents: 57c78ff
Author: Alexey Kuznetsov <ak...@apache.org>
Authored: Fri Aug 26 13:40:09 2016 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Fri Aug 26 13:40:09 2016 +0700

----------------------------------------------------------------------
 modules/web-console/DEVNOTES.txt | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/916be77e/modules/web-console/DEVNOTES.txt
----------------------------------------------------------------------
diff --git a/modules/web-console/DEVNOTES.txt b/modules/web-console/DEVNOTES.txt
index 150041e..d48a042 100644
--- a/modules/web-console/DEVNOTES.txt
+++ b/modules/web-console/DEVNOTES.txt
@@ -13,12 +13,15 @@ How to deploy locally:
        npm install -g npm-windows-upgrade
        npm-windows-upgrade
        See: https://github.com/felixrieseberg/npm-windows-upgrade
-  Check npm version: "npm --version".
-5. Run "npm install --no-optional" in terminal for download dependencies.
-6. Build ignite-web-agent module follow instructions from 'modules/web-agent/README.txt'.
-7. Copy ignite-web-agent-<version>.zip from target of ignite-web-agent module to 'modules/web-console/backend/agent_dists' folder.
+  Check npm version: "npm --version", it should be 3.x.
+5. Change directory to '$IGNITE_HOME/modules/web-console/backend' and
+ run "npm install --no-optional" for download backend dependencies.
+6. Change directory to '$IGNITE_HOME/modules/web-console/frontend' and
+ run "npm install --no-optional" for download frontend dependencies.
+7. Build ignite-web-agent module follow instructions from 'modules/web-agent/README.txt'.
+8. Copy ignite-web-agent-<version>.zip from target of ignite-web-agent module to 'modules/web-console/backend/agent_dists' folder.
 
-Steps 1 - 7 should be executed once.
+Steps 1 - 8 should be executed once.
 
 How to run console in development mode:
 
@@ -28,7 +31,7 @@ How to run console in development mode:
 2. In new terminal change directory to '$IGNITE_HOME/modules/web-console/backend'.
    If needed run "npm install --no-optional" (if dependencies changed) and run "npm start" to start backend.
 
-3. In new terminal change directory to '$IGNITE_HOME/modules/web-console/frontend'
-  and start webpack in development mode "npm run dev".
+3. In new terminal change directory to '$IGNITE_HOME/modules/web-console/frontend'.
+  If needed run "npm install --no-optional" (if dependencies changed) and start webpack in development mode "npm run dev".
 
 4. In browser open: http://localhost:9000


[49/50] [abbrv] ignite git commit: Merge branches 'ignite-3629' and 'web-console-staging' of https://github.com/gridgain/apache-ignite into ignite-3629

Posted by an...@apache.org.
Merge branches 'ignite-3629' and 'web-console-staging' of https://github.com/gridgain/apache-ignite into ignite-3629


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

Branch: refs/heads/ignite-3629
Commit: af38ae6024d35711f5f3d7efb9de8cadbe34fc95
Parents: 0580bbf 2b8bdb7
Author: Andrey Novikov <an...@apache.org>
Authored: Tue Sep 6 16:01:26 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Tue Sep 6 16:01:26 2016 +0700

----------------------------------------------------------------------
 .../ui-ace-java/ui-ace-java.directive.js        |  3 ++-
 .../ui-ace-xml/ui-ace-xml.directive.js          |  3 ++-
 .../configuration/caches/concurrency.jade       |  2 +-
 .../states/configuration/caches/general.jade    |  2 +-
 .../states/configuration/caches/query.jade      |  2 +-
 .../states/configuration/caches/statistics.jade |  6 ++++--
 .../frontend/controllers/caches-controller.js   |  9 +++++++--
 .../frontend/controllers/clusters-controller.js | 12 +++++++++--
 .../frontend/controllers/domains-controller.js  |  9 +++++++--
 .../frontend/generator/generator-java.js        | 21 +++++++++++++++++---
 .../frontend/generator/generator-xml.js         |  8 +++++---
 11 files changed, 58 insertions(+), 19 deletions(-)
----------------------------------------------------------------------



[25/50] [abbrv] ignite git commit: Minor refactoring.

Posted by an...@apache.org.
Minor refactoring.


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

Branch: refs/heads/ignite-3629
Commit: 5abecfee64a7e67baf5d9b067065ffc2698bed17
Parents: 52b1803
Author: Andrey Novikov <an...@apache.org>
Authored: Mon Aug 29 13:19:06 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Mon Aug 29 13:19:06 2016 +0700

----------------------------------------------------------------------
 .../web-console/frontend/app/modules/sql/Notebook.data.js    | 8 +++-----
 .../web-console/frontend/app/modules/sql/Notebook.service.js | 8 +++-----
 .../frontend/app/modules/sql/scan-filter-input.service.js    | 3 +--
 3 files changed, 7 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/5abecfee/modules/web-console/frontend/app/modules/sql/Notebook.data.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/Notebook.data.js b/modules/web-console/frontend/app/modules/sql/Notebook.data.js
index 461ad3f2..aef72eb 100644
--- a/modules/web-console/frontend/app/modules/sql/Notebook.data.js
+++ b/modules/web-console/frontend/app/modules/sql/Notebook.data.js
@@ -70,7 +70,9 @@ const DEMO_NOTEBOOK = {
     expandedParagraphs: [0, 1, 2]
 };
 
-class NotebookData {
+export default class NotebookData {
+    static $inject = ['$rootScope', '$http', '$q'];
+
     constructor($root, $http, $q) {
         this.demo = $root.IgniteDemoMode;
 
@@ -153,7 +155,3 @@ class NotebookData {
             .catch(({data}) => Promise.reject(data));
     }
 }
-
-NotebookData.$inject = ['$rootScope', '$http', '$q'];
-
-export default NotebookData;

http://git-wip-us.apache.org/repos/asf/ignite/blob/5abecfee/modules/web-console/frontend/app/modules/sql/Notebook.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/Notebook.service.js b/modules/web-console/frontend/app/modules/sql/Notebook.service.js
index 1b0817e..12730be 100644
--- a/modules/web-console/frontend/app/modules/sql/Notebook.service.js
+++ b/modules/web-console/frontend/app/modules/sql/Notebook.service.js
@@ -15,7 +15,9 @@
  * limitations under the License.
  */
 
-class Notebook {
+export default class Notebook {
+    static $inject = ['$state', 'IgniteConfirm', 'IgniteMessages', 'IgniteNotebookData'];
+
     /**
      * @param $state
      * @param confirmModal
@@ -70,7 +72,3 @@ class Notebook {
             });
     }
 }
-
-Notebook.$inject = ['$state', 'IgniteConfirm', 'IgniteMessages', 'IgniteNotebookData'];
-
-export default Notebook;

http://git-wip-us.apache.org/repos/asf/ignite/blob/5abecfee/modules/web-console/frontend/app/modules/sql/scan-filter-input.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/scan-filter-input.service.js b/modules/web-console/frontend/app/modules/sql/scan-filter-input.service.js
index d460f04..18ba3ba 100644
--- a/modules/web-console/frontend/app/modules/sql/scan-filter-input.service.js
+++ b/modules/web-console/frontend/app/modules/sql/scan-filter-input.service.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-class ScanFilter {
+export default class ScanFilter {
     static $inject = ['$rootScope', '$q', '$modal'];
 
     constructor($root, $q, $modal) {
@@ -49,4 +49,3 @@ class ScanFilter {
         return this.deferred.promise;
     }
 }
-export default ScanFilter;


[03/50] [abbrv] ignite git commit: Merge branch 'ignite-2278-2' into web-console-staging

Posted by an...@apache.org.
Merge branch 'ignite-2278-2' into web-console-staging


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

Branch: refs/heads/ignite-3629
Commit: e6ed223e323992d1d7078353c659a4336947b49e
Parents: ffe79ee 7236570
Author: vsisko <vs...@gridgain.com>
Authored: Mon Aug 22 13:25:56 2016 +0700
Committer: vsisko <vs...@gridgain.com>
Committed: Mon Aug 22 13:25:56 2016 +0700

----------------------------------------------------------------------
 modules/web-console/backend/app/mongo.js        |  3 +-
 .../frontend/app/helpers/jade/mixins.jade       |  6 ++--
 .../configuration/caches/concurrency.jade       | 10 +++---
 .../states/configuration/caches/general.jade    |  4 +--
 .../states/configuration/caches/memory.jade     | 36 +++++++++++---------
 .../states/configuration/caches/rebalance.jade  |  2 +-
 .../configuration/caches/server-near-cache.jade |  8 ++++-
 .../states/configuration/caches/store.jade      | 14 +++++---
 .../states/configuration/clusters/binary.jade   |  4 +--
 .../configuration/clusters/communication.jade   | 11 +++---
 .../configuration/clusters/connector.jade       |  2 +-
 .../configuration/clusters/discovery.jade       | 22 +++++++-----
 .../states/configuration/clusters/general.jade  | 19 ++++++-----
 .../states/configuration/clusters/igfs.jade     |  2 +-
 .../configuration/clusters/logger/custom.jade   |  2 +-
 .../configuration/clusters/marshaller.jade      | 10 ++++--
 .../states/configuration/clusters/metrics.jade  |  3 +-
 .../states/configuration/clusters/ssl.jade      |  2 +-
 .../states/configuration/clusters/swap.jade     |  6 +++-
 .../configuration/clusters/transactions.jade    | 14 ++++++--
 .../states/configuration/igfs/general.jade      |  2 +-
 .../modules/states/configuration/igfs/ipc.jade  |  7 ++--
 .../modules/states/configuration/igfs/misc.jade |  2 +-
 .../frontend/generator/generator-common.js      |  3 +-
 24 files changed, 122 insertions(+), 72 deletions(-)
----------------------------------------------------------------------



[50/50] [abbrv] ignite git commit: IGNITE-3629 Review.

Posted by an...@apache.org.
IGNITE-3629 Review.


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

Branch: refs/heads/ignite-3629
Commit: 610ad247fdb6aa17998503fcdfe832d13cb2ceac
Parents: af38ae6
Author: Andrey Novikov <an...@apache.org>
Authored: Tue Sep 6 16:28:36 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Tue Sep 6 16:28:36 2016 +0700

----------------------------------------------------------------------
 modules/web-console/backend/app/mongoose.js     |  2 --
 modules/web-console/backend/package.json        |  3 +-
 .../web-console/backend/test/app/mockgoose.js   | 30 +++++++++++++++++
 .../backend/test/fixtures/mockgoose.js          | 34 --------------------
 modules/web-console/backend/test/injector.js    |  2 +-
 5 files changed, 33 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/610ad247/modules/web-console/backend/app/mongoose.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/app/mongoose.js b/modules/web-console/backend/app/mongoose.js
index 5dba51d..7b6e7f3 100644
--- a/modules/web-console/backend/app/mongoose.js
+++ b/modules/web-console/backend/app/mongoose.js
@@ -24,8 +24,6 @@ module.exports = {
     inject: ['require(mongoose)']
 };
 
-
 module.exports.factory = (mongoose) => {
     return mongoose;
 };
-

http://git-wip-us.apache.org/repos/asf/ignite/blob/610ad247/modules/web-console/backend/package.json
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/package.json b/modules/web-console/backend/package.json
index 598dc00..f9a8ab0 100644
--- a/modules/web-console/backend/package.json
+++ b/modules/web-console/backend/package.json
@@ -66,6 +66,7 @@
     "eslint-friendly-formatter": "^2.0.5",
     "jasmine-core": "^2.4.1",
     "mocha": "~2.5.3",
-    "mocha-teamcity-reporter": "^1.0.0"
+    "mocha-teamcity-reporter": "^1.0.0",
+    "mockgoose": "^6.0.6"
   }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/610ad247/modules/web-console/backend/test/app/mockgoose.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/test/app/mockgoose.js b/modules/web-console/backend/test/app/mockgoose.js
new file mode 100644
index 0000000..4944f90
--- /dev/null
+++ b/modules/web-console/backend/test/app/mockgoose.js
@@ -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.
+ */
+
+'use strict';
+
+// Fire me up!
+
+module.exports = {
+    implements: 'mongoose:mock',
+    inject: ['require(mongoose)', 'require(mockgoose)']
+};
+
+module.exports.factory = (mongoose, mockgoose) => {
+    return mockgoose(mongoose)
+            .then(() => mongoose);
+};

http://git-wip-us.apache.org/repos/asf/ignite/blob/610ad247/modules/web-console/backend/test/fixtures/mockgoose.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/test/fixtures/mockgoose.js b/modules/web-console/backend/test/fixtures/mockgoose.js
deleted file mode 100644
index 84eb088..0000000
--- a/modules/web-console/backend/test/fixtures/mockgoose.js
+++ /dev/null
@@ -1,34 +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.
- */
-
-'use strict';
-
-// Fire me up!
-
-module.exports = {
-    implements: 'mongoose:mock',
-    inject: ['mongoose', 'require(mockgoose)']
-};
-
-
-module.exports.factory = (mongoose, mockgoose) => {
-    return new Promise((resolve) => {
-        mockgoose(mongoose).then(() => resolve(mongoose));
-    });
-};
-
-

http://git-wip-us.apache.org/repos/asf/ignite/blob/610ad247/modules/web-console/backend/test/injector.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/test/injector.js b/modules/web-console/backend/test/injector.js
index 3cec9d6..b1dbaf4 100644
--- a/modules/web-console/backend/test/injector.js
+++ b/modules/web-console/backend/test/injector.js
@@ -27,7 +27,7 @@ module.exports = fireUp.newInjector({
         './middlewares/**/*.js',
         './routes/**/*.js',
         './services/**/*.js',
-        './test/fixtures/*.js'
+        './test/app/*.js'
     ],
     use: ['mongoose:mock']
 });


[31/50] [abbrv] ignite git commit: Cleanup unused directvie.

Posted by an...@apache.org.
Cleanup unused directvie.


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

Branch: refs/heads/ignite-3629
Commit: 4167196d0faae857ffa5730e484f7b242036b98b
Parents: ab9db26
Author: Maxim Afanasiev <ma...@gmail.com>
Authored: Tue Aug 30 17:16:13 2016 +0700
Committer: Maxim Afanasiev <ma...@gmail.com>
Committed: Tue Aug 30 17:16:13 2016 +0700

----------------------------------------------------------------------
 .../frontend/app/modules/form/form.module.js    |  2 -
 .../app/modules/form/group/group.directive.js   | 78 --------------------
 .../app/modules/form/group/table.directive.js   | 29 --------
 .../frontend/app/modules/form/group/table.jade  | 17 -----
 4 files changed, 126 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/4167196d/modules/web-console/frontend/app/modules/form/form.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/form/form.module.js b/modules/web-console/frontend/app/modules/form/form.module.js
index 6eb9bc0..c014c29 100644
--- a/modules/web-console/frontend/app/modules/form/form.module.js
+++ b/modules/web-console/frontend/app/modules/form/form.module.js
@@ -34,7 +34,6 @@ import igniteFormFieldTooltip from './field/tooltip.directive';
 import placeholder from './field/bs-select-placeholder.directive';
 
 // Group.
-import igniteFormGroup from './group/group.directive';
 import igniteFormGroupAdd from './group/add.directive';
 import igniteFormGroupTooltip from './group/tooltip.directive';
 
@@ -70,7 +69,6 @@ angular
 .directive(...igniteFormFieldTooltip)
 .directive(...placeholder)
 // Group.
-.directive(...igniteFormGroup)
 .directive(...igniteFormGroupAdd)
 .directive(...igniteFormGroupTooltip)
 // Validators.

http://git-wip-us.apache.org/repos/asf/ignite/blob/4167196d/modules/web-console/frontend/app/modules/form/group/group.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/form/group/group.directive.js b/modules/web-console/frontend/app/modules/form/group/group.directive.js
deleted file mode 100644
index d72b053..0000000
--- a/modules/web-console/frontend/app/modules/form/group/group.directive.js
+++ /dev/null
@@ -1,78 +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.
- */
-
-export default ['igniteFormGroup', [() => {
-    const controller = [function() { }];
-
-    const link = (scope, el, attrs, [ngModelCtrl, ownFormCtrl, parentFormCtrl]) => {
-        if (!ownFormCtrl)
-            return;
-
-        const name = attrs.ngForm;
-        ngModelCtrl.$name = name;
-
-        parentFormCtrl.$addControl(ngModelCtrl);
-        parentFormCtrl.$removeControl(ownFormCtrl);
-
-        scope.group = {};
-
-        scope.ngModel = scope.ngModel || [];
-        parentFormCtrl.$defaults = parentFormCtrl.$defaults || {};
-
-        if (parentFormCtrl.$pristine) {
-            if (!(_.isNull(parentFormCtrl.$defaults[name]) || _.isUndefined(parentFormCtrl.$defaults[name])))
-                scope.ngModel = parentFormCtrl.$defaults[name];
-            else
-                parentFormCtrl.$defaults[name] = _.cloneDeep(scope.ngModel);
-        }
-
-        const setAsDefault = () => {
-            if (!parentFormCtrl.$pristine)
-                return;
-
-            scope.ngModel = scope.ngModel || [];
-            parentFormCtrl.$defaults = parentFormCtrl.$defaults || {};
-            parentFormCtrl.$defaults[name] = _.cloneDeep(scope.ngModel);
-        };
-
-        const setAsDirty = () => {
-            if (_.isEqual(scope.ngModel, parentFormCtrl.$defaults[name]))
-                ngModelCtrl.$setPristine();
-            else
-                ngModelCtrl.$setDirty();
-        };
-
-        scope.$watch(() => parentFormCtrl.$pristine, setAsDefault);
-
-        scope.$watch('ngModel', setAsDefault);
-        scope.$watch('ngModel', setAsDirty, true);
-    };
-
-    return {
-        restrict: 'A',
-        scope: {
-            ngModel: '=ngModel'
-        },
-        bindToController: {
-            label: '@'
-        },
-        link,
-        controller,
-        controllerAs: 'group',
-        require: ['?ngModel', '?form', '^^form']
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/4167196d/modules/web-console/frontend/app/modules/form/group/table.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/form/group/table.directive.js b/modules/web-console/frontend/app/modules/form/group/table.directive.js
deleted file mode 100644
index 8c4d0ed..0000000
--- a/modules/web-console/frontend/app/modules/form/group/table.directive.js
+++ /dev/null
@@ -1,29 +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.
- */
-
-import templateUrl from './table.jade';
-
-export default ['igniteFormGroupTable', [() => {
-    return {
-        restrict: 'E',
-        scope: {},
-        templateUrl,
-        replace: true,
-        transclude: true,
-        require: ['^form', '^igniteFormGroup']
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/4167196d/modules/web-console/frontend/app/modules/form/group/table.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/form/group/table.jade b/modules/web-console/frontend/app/modules/form/group/table.jade
deleted file mode 100644
index 6f9486d..0000000
--- a/modules/web-console/frontend/app/modules/form/group/table.jade
+++ /dev/null
@@ -1,17 +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.
-
-div
\ No newline at end of file


[45/50] [abbrv] ignite git commit: IGNITE-2047 Fixed add of table values for new object.

Posted by an...@apache.org.
IGNITE-2047 Fixed add of table values for new object.


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

Branch: refs/heads/ignite-3629
Commit: 05c35bb1cf00e777f2ec826c0cf29508f748143b
Parents: ef5f47c
Author: vsisko <vs...@gridgain.com>
Authored: Tue Sep 6 12:59:21 2016 +0700
Committer: vsisko <vs...@gridgain.com>
Committed: Tue Sep 6 12:59:21 2016 +0700

----------------------------------------------------------------------
 .../web-console/frontend/controllers/caches-controller.js   | 9 +++++++--
 .../web-console/frontend/controllers/clusters-controller.js | 7 ++++++-
 2 files changed, 13 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/05c35bb1/modules/web-console/frontend/controllers/caches-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/caches-controller.js b/modules/web-console/frontend/controllers/caches-controller.js
index f08940c..db0636c 100644
--- a/modules/web-console/frontend/controllers/caches-controller.js
+++ b/modules/web-console/frontend/controllers/caches-controller.js
@@ -27,8 +27,13 @@ export default ['cachesController', [
 
         const blank = {
             evictionPolicy: {},
-            cacheStoreFactory: {},
-            nearConfiguration: {}
+            cacheStoreFactory: {
+                CacheHibernateBlobStoreFactory: {
+                    hibernateProperties: []
+                }
+            },
+            nearConfiguration: {},
+            sqlFunctionClasses: []
         };
 
         // We need to initialize backupItem with empty object in order to properly used from angular directives.

http://git-wip-us.apache.org/repos/asf/ignite/blob/05c35bb1/modules/web-console/frontend/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/clusters-controller.js b/modules/web-console/frontend/controllers/clusters-controller.js
index 17a4e51..c03aa19 100644
--- a/modules/web-console/frontend/controllers/clusters-controller.js
+++ b/modules/web-console/frontend/controllers/clusters-controller.js
@@ -31,7 +31,12 @@ export default ['clustersController', [
             cacheKeyConfiguration: [],
             communication: {},
             connector: {},
-            discovery: {},
+            discovery: {
+                Cloud: {
+                    regions: [],
+                    zones: []
+                }
+            },
             marshaller: {},
             sslContextFactory: {
                 trustManagers: []


[02/50] [abbrv] ignite git commit: IGNITE-2278 Fixed tips

Posted by an...@apache.org.
IGNITE-2278 Fixed tips


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

Branch: refs/heads/ignite-3629
Commit: 72365708ee0dadd1c0da7a2fd2968270cb877b62
Parents: ca908b3
Author: vsisko <vs...@gridgain.com>
Authored: Mon Aug 22 13:25:34 2016 +0700
Committer: vsisko <vs...@gridgain.com>
Committed: Mon Aug 22 13:25:34 2016 +0700

----------------------------------------------------------------------
 .../frontend/app/modules/states/configuration/caches/memory.jade   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/72365708/modules/web-console/frontend/app/modules/states/configuration/caches/memory.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/memory.jade b/modules/web-console/frontend/app/modules/states/configuration/caches/memory.jade
index 24ce0f6..debbe0d 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/memory.jade
+++ b/modules/web-console/frontend/app/modules/states/configuration/caches/memory.jade
@@ -69,7 +69,7 @@ include ../../../../../app/helpers/jade/mixins.jade
                             {value: 1, label: "Limited"},\
                             {value: 0, label: "Unlimited"}\
                         ]',
-                        'Off-heap storage mode:\
+                        'Off-heap storage mode\
                         <ul>\
                             <li>Disabled - Off-heap storage is disabled</li>\
                             <li>Limited - Off-heap storage has limited size</li>\


[36/50] [abbrv] ignite git commit: Fixed notebook save.

Posted by an...@apache.org.
Fixed notebook save.


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

Branch: refs/heads/ignite-3629
Commit: 957d47236e51d3a6e2e81018bc54a2aaa4706ceb
Parents: 31f8d1c
Author: Andrey Novikov <an...@apache.org>
Authored: Fri Sep 2 17:11:24 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Fri Sep 2 17:11:24 2016 +0700

----------------------------------------------------------------------
 .../web-console/backend/services/notebooks.js   |  4 +--
 .../frontend/app/modules/sql/sql.controller.js  | 33 ++++++++++++++------
 modules/web-console/frontend/views/sql/sql.jade | 16 +++++-----
 3 files changed, 34 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/957d4723/modules/web-console/backend/services/notebooks.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/services/notebooks.js b/modules/web-console/backend/services/notebooks.js
index 915279c..609d732 100644
--- a/modules/web-console/backend/services/notebooks.js
+++ b/modules/web-console/backend/services/notebooks.js
@@ -44,8 +44,8 @@ module.exports.factory = (_, mongo, spacesService, errors) => {
      * @returns {Promise.<mongo.ObjectId>} that resolves cache id
      */
     const update = (notebook) => {
-        return mongo.Notebook.update({_id: notebook._id}, notebook, {upsert: true}).exec()
-            .then(() => notebook)
+        return mongo.Notebook.findOneAndUpdate({_id: notebook._id}, notebook, {upsert: true}).exec()
+            .then((doc) => doc)
             .catch((err) => {
                 if (err.code === mongo.errCodes.DUPLICATE_KEY_UPDATE_ERROR || err.code === mongo.errCodes.DUPLICATE_KEY_ERROR)
                     throw new errors.DuplicateKeyException('Notebook with name: "' + notebook.name + '" already exist.');

http://git-wip-us.apache.org/repos/asf/ignite/blob/957d4723/modules/web-console/frontend/app/modules/sql/sql.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/sql.controller.js b/modules/web-console/frontend/app/modules/sql/sql.controller.js
index 235592b..8b5a1dd 100644
--- a/modules/web-console/frontend/app/modules/sql/sql.controller.js
+++ b/modules/web-console/frontend/app/modules/sql/sql.controller.js
@@ -133,7 +133,11 @@ class Paragraph {
     }
 
     queryExecuted() {
-        return this.queryArgs && this.queryArgs.query && !this.queryArgs.query.startsWith('EXPLAIN ');
+        return !_.isEmpty(this.meta);
+    }
+
+    scanExplain() {
+        return this.queryExecuted() && this.queryArgs.type !== 'QUERY';
     }
 
     timeLineSupported() {
@@ -1191,7 +1195,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
 
             _showLoading(paragraph, false);
 
-            if (paragraph.result === 'none' || !paragraph.queryExecuted())
+            if (_.isNil(paragraph.result) || paragraph.scanExplain())
                 paragraph.result = 'table';
             else if (paragraph.chart()) {
                 let resetCharts = queryChanged;
@@ -1246,6 +1250,9 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
         };
 
         $scope.execute = (paragraph) => {
+            if (!$scope.actionAvailable(paragraph, true))
+                return;
+
             Notebook.save($scope.notebook)
                 .catch(Messages.showError);
 
@@ -1258,7 +1265,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                     const args = paragraph.queryArgs = {
                         cacheName: paragraph.cacheName,
                         pageSize: paragraph.pageSize,
-                        query: paragraph.query
+                        query: paragraph.query,
+                        type: 'QUERY'
                     };
 
                     return agentMonitor.query(cacheNode(paragraph.cacheName), args.cacheName, args.query, false, args.pageSize);
@@ -1278,10 +1286,6 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                 .then(() => paragraph.ace.focus());
         };
 
-        $scope.queryExecuted = function(paragraph) {
-            return LegacyUtils.isDefined(paragraph.queryArgs);
-        };
-
         const _cancelRefresh = (paragraph) => {
             if (paragraph.rate && paragraph.rate.stopTime) {
                 delete paragraph.queryArgs;
@@ -1295,6 +1299,9 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
         };
 
         $scope.explain = (paragraph) => {
+            if (!$scope.actionAvailable(paragraph, true))
+                return;
+
             Notebook.save($scope.notebook)
                 .catch(Messages.showError);
 
@@ -1307,7 +1314,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                     const args = paragraph.queryArgs = {
                         cacheName: paragraph.cacheName,
                         pageSize: paragraph.pageSize,
-                        query: 'EXPLAIN ' + paragraph.query
+                        query: 'EXPLAIN ' + paragraph.query,
+                        type: 'EXPLAIN'
                     };
 
                     return agentMonitor.query(cacheNode(paragraph.cacheName), args.cacheName, args.query, false, args.pageSize);
@@ -1322,6 +1330,9 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
         };
 
         $scope.scan = (paragraph, query = null) => {
+            if (!$scope.actionAvailable(paragraph, false))
+                return;
+
             Notebook.save($scope.notebook)
                 .catch(Messages.showError);
 
@@ -1334,7 +1345,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                     const args = paragraph.queryArgs = {
                         cacheName: paragraph.cacheName,
                         pageSize: paragraph.pageSize,
-                        query
+                        query,
+                        type: 'SCAN'
                     };
 
                     return agentMonitor.query(cacheNode(paragraph.cacheName), args.cacheName, query, false, args.pageSize);
@@ -1349,6 +1361,9 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
         };
 
         $scope.scanWithFilter = (paragraph) => {
+            if (!$scope.actionAvailable(paragraph, false))
+                return;
+
             ScanFilterInput.open()
                 .then(({filter, caseSensitive}) => {
                     const prefix = caseSensitive ? SCAN_CACHE_WITH_FILTER_CASE_SENSITIVE : SCAN_CACHE_WITH_FILTER;

http://git-wip-us.apache.org/repos/asf/ignite/blob/957d4723/modules/web-console/frontend/views/sql/sql.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/sql/sql.jade b/modules/web-console/frontend/views/sql/sql.jade
index 570517d..81acdfd 100644
--- a/modules/web-console/frontend/views/sql/sql.jade
+++ b/modules/web-console/frontend/views/sql/sql.jade
@@ -84,11 +84,11 @@ mixin paragraph-rename
 
 mixin query-controls
     .sql-controls
-        a.btn.btn-primary(ng-disabled='!actionAvailable(paragraph, true)' ng-click='actionAvailable(paragraph, true) && execute(paragraph)' data-placement='bottom' bs-tooltip data-title='{{actionTooltip(paragraph, "execute", true)}}') Execute
-        a.btn.btn-primary(ng-disabled='!actionAvailable(paragraph, true)' ng-click='actionAvailable(paragraph, true) && explain(paragraph)' data-placement='bottom' bs-tooltip data-title='{{actionTooltip(paragraph, "explain", true)}}') Explain
-        .btn-group(ng-disabled='!actionAvailable(paragraph, false)')
-            a.btn.btn-primary.fieldButton(ng-click='actionAvailable(paragraph, false) && scan(paragraph)' data-placement='bottom' bs-tooltip data-title='{{actionTooltip(paragraph, "execute scan", false)}}') Scan
-            a.btn.btn-primary(data-toggle='dropdown' data-container='body' bs-dropdown='[{ text: "Scan with filter", click: "actionAvailable(paragraph, false) && scanWithFilter(paragraph)" }]' data-placement='bottom-right')
+        a.btn.btn-primary(ng-disabled='!actionAvailable(paragraph, true)' ng-click='execute(paragraph)' data-placement='bottom' bs-tooltip='' data-title='{{actionTooltip(paragraph, "execute", true)}}') Execute
+        a.btn.btn-primary(ng-disabled='!actionAvailable(paragraph, true)' ng-click='explain(paragraph)' data-placement='bottom' bs-tooltip='' data-title='{{actionTooltip(paragraph, "explain", true)}}') Explain
+        .btn-group(bs-tooltip='' data-title='{{actionTooltip(paragraph, "execute scan", false)}}' data-placement='bottom')
+            a.btn.btn-primary.fieldButton(ng-disabled='!actionAvailable(paragraph, false)' ng-click='scan(paragraph)') Scan
+            a.btn.btn-primary(ng-disabled='!actionAvailable(paragraph, false)' data-toggle='dropdown' data-container='body' bs-dropdown='[{ text: "Scan with filter", click: "actionAvailable(paragraph, false) && scanWithFilter(paragraph)" }]')
                 span.caret
 
         .pull-right
@@ -115,7 +115,7 @@ mixin table-result
     .grid(ui-grid='paragraph.gridOptions' ui-grid-resize-columns ui-grid-exporter)
 
 mixin chart-result
-    div(ng-show='paragraph.queryExecuted()')
+    div(ng-hide='paragraph.scanExplain()')
         +chart-settings
         .empty(ng-show='paragraph.chartColumns.length > 0 && !paragraph.chartColumnsConfigured()') Cannot display chart. Please configure axis using #[b Chart settings]
         .empty(ng-show='paragraph.chartColumns.length == 0') Cannot display chart. Result set must contain Java build-in type columns. Please change query and execute it again.
@@ -124,7 +124,7 @@ mixin chart-result
                 div(ng-repeat='chart in paragraph.charts')
                     nvd3(options='chart.options' data='chart.data' api='chart.api')
             .empty(ng-show='!paragraph.timeLineSupported() && paragraph.chartTimeLineEnabled()') Pie chart does not support 'TIME_LINE' column for X-axis. Please use another column for X-axis or switch to another chart.
-    .empty(ng-hide='paragraph.queryExecuted()')
+    .empty(ng-show='paragraph.scanExplain()')
         .row
             .col-xs-4.col-xs-offset-4
                 +result-toolbar
@@ -176,7 +176,7 @@ mixin chart-result
                                         label No caches
                             .col-sm-12
                                 +query-controls
-                            .col-sm-12.sql-result(ng-switch='paragraph.resultType()')
+                            .col-sm-12.sql-result(ng-if='paragraph.queryExecuted()' ng-switch='paragraph.resultType()')
                                 .error(ng-switch-when='error') Error: {{paragraph.errMsg}}
                                 .empty(ng-switch-when='empty') Result set is empty
                                 .table(ng-switch-when='table')


[32/50] [abbrv] ignite git commit: IGNITE-3803 Fixed blinking signin page for authorized user.

Posted by an...@apache.org.
IGNITE-3803 Fixed blinking signin page for authorized user.


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

Branch: refs/heads/ignite-3629
Commit: 76f7eabca16e345792b344cec6ed251c2ad6caa9
Parents: 4167196
Author: Maxim Afanasiev <ma...@gmail.com>
Authored: Wed Aug 31 15:32:54 2016 +0700
Committer: Maxim Afanasiev <ma...@gmail.com>
Committed: Wed Aug 31 15:32:54 2016 +0700

----------------------------------------------------------------------
 .../frontend/app/modules/states/signin.state.js          | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/76f7eabc/modules/web-console/frontend/app/modules/states/signin.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/signin.state.js b/modules/web-console/frontend/app/modules/states/signin.state.js
index ec62af5..14ebc1b 100644
--- a/modules/web-console/frontend/app/modules/states/signin.state.js
+++ b/modules/web-console/frontend/app/modules/states/signin.state.js
@@ -30,10 +30,13 @@ angular
     .state('signin', {
         url: '/',
         templateUrl,
-        onEnter: ['$state', 'User', ($state, User) => {
-            User.read()
-                .then(() => $state.go('base.configuration.clusters', {}, {reload: true}));
-        }],
+        resolve: {
+            user: ['$state', 'User', ($state, User) => {
+                return User.read()
+                    .then(() => $state.go('base.configuration.clusters'))
+                    .catch(() => {});
+            }]
+        },
         metaTags: {
         }
     });


[22/50] [abbrv] ignite git commit: Fixed wrong merge.

Posted by an...@apache.org.
Fixed wrong merge.


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

Branch: refs/heads/ignite-3629
Commit: 1bb10f90595ae01f95e34f4f5e86718ff12907cf
Parents: 38f0e0a
Author: Maxim Afanasiev <ma...@gmail.com>
Authored: Fri Aug 26 16:41:32 2016 +0700
Committer: Maxim Afanasiev <ma...@gmail.com>
Committed: Fri Aug 26 16:42:01 2016 +0700

----------------------------------------------------------------------
 .../web-console/src/main/js/app/app.config.js   |  86 --------
 .../main/js/app/controllers/auth.controller.js  |  30 ---
 .../js/app/controllers/notebooks.controller.js  |  69 -------
 .../controllers/reset-password.controller.js    |  51 -----
 .../js/app/directives/auto-focus.directive.js   |  26 ---
 .../directives/copy-to-clipboard.directive.js   |  29 ---
 .../main/js/app/directives/match.directive.js   |  27 ---
 .../app/directives/on-click-focus.directive.js  |  26 ---
 .../directives/on-enter-focus-move.directive.js |  29 ---
 .../js/app/directives/on-escape.directive.js    |  32 ---
 .../js/app/filters/domainsValidation.filter.js  |  33 ---
 .../src/main/js/app/services/Clone.service.js   |  64 ------
 .../js/app/services/ConfirmBatch.service.js     |  92 ---------
 .../js/app/services/CopyToClipboard.service.js  |  50 -----
 .../src/main/js/app/services/Focus.service.js   |  33 ---
 .../main/js/app/services/LegacyTable.service.js | 205 -------------------
 .../main/js/app/services/Messages.service.js    |  63 ------
 .../app/services/UnsavedChangesGuard.service.js |  38 ----
 .../src/main/js/app/services/confirm.service.js |   0
 modules/web-console/src/main/js/app/vendor.js   |  54 -----
 .../main/js/gulpfile.babel.js/webpack/common.js | 192 -----------------
 .../webpack/environments/production.js          |  45 ----
 .../main/js/gulpfile.babel.js/webpack/index.js  |  32 ---
 .../webpack/plugins/progress.js                 |  82 --------
 24 files changed, 1388 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/app.config.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/app.config.js b/modules/web-console/src/main/js/app/app.config.js
deleted file mode 100644
index 25c24b0..0000000
--- a/modules/web-console/src/main/js/app/app.config.js
+++ /dev/null
@@ -1,86 +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.
- */
-
-import alertTemplateUrl from '../views/templates/alert.jade';
-
-const igniteConsoleCfg = angular.module('ignite-console.config', ['ngAnimate', 'mgcrea.ngStrap']);
-
-// Configure AngularJS animation: do not animate fa-spin.
-igniteConsoleCfg.config(['$animateProvider', ($animateProvider) => {
-    $animateProvider.classNameFilter(/^((?!(fa-spin)).)*$/);
-}]);
-
-// AngularStrap modal popup configuration.
-igniteConsoleCfg.config(['$modalProvider', ($modalProvider) => {
-    angular.extend($modalProvider.defaults, {
-        animation: 'am-fade-and-scale',
-        html: true
-    });
-}]);
-
-// AngularStrap popover configuration.
-igniteConsoleCfg.config(['$popoverProvider', ($popoverProvider) => {
-    angular.extend($popoverProvider.defaults, {
-        trigger: 'manual',
-        placement: 'right',
-        container: 'body',
-        templateUrl: '/templates/validation-error.html'
-    });
-}]);
-
-// AngularStrap tooltips configuration.
-igniteConsoleCfg.config(['$tooltipProvider', ($tooltipProvider) => {
-    angular.extend($tooltipProvider.defaults, {
-        container: 'body',
-        delay: 150,
-        placement: 'right',
-        html: 'true',
-        trigger: 'click hover'
-    });
-}]);
-
-// AngularStrap select (combobox) configuration.
-igniteConsoleCfg.config(['$selectProvider', ($selectProvider) => {
-    angular.extend($selectProvider.defaults, {
-        container: 'body',
-        maxLength: '5',
-        allText: 'Select All',
-        noneText: 'Clear All',
-        templateUrl: '/templates/select.html',
-        iconCheckmark: 'fa fa-check',
-        caretHtml: ''
-    });
-}]);
-
-// AngularStrap alerts configuration.
-igniteConsoleCfg.config(['$alertProvider', ($alertProvider) => {
-    angular.extend($alertProvider.defaults, {
-        container: 'body',
-        placement: 'top-right',
-        duration: '5',
-        templateUrl: alertTemplateUrl,
-        type: 'danger'
-    });
-}]);
-
-
-// AngularStrap dropdowns () configuration.
-igniteConsoleCfg.config(['$dropdownProvider', ($dropdownProvider) => {
-    angular.extend($dropdownProvider.defaults, {
-        templateUrl: 'templates/dropdown.html'
-    });
-}]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/controllers/auth.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/controllers/auth.controller.js b/modules/web-console/src/main/js/app/controllers/auth.controller.js
deleted file mode 100644
index 21ffeb8..0000000
--- a/modules/web-console/src/main/js/app/controllers/auth.controller.js
+++ /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.
- */
-
-// Sign in controller.
-// TODO IGNITE-1936 Refactor this controller.
-export default ['auth', [
-    '$scope', 'IgniteFocus', 'IgniteCountries', 'Auth',
-    ($scope, Focus, Countries, Auth) => {
-        $scope.auth = Auth.auth;
-        $scope.forgotPassword = Auth.forgotPassword;
-        $scope.action = 'signin';
-        $scope.countries = Countries.getAll();
-
-        Focus.move('user_email');
-    }
-]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/controllers/notebooks.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/controllers/notebooks.controller.js b/modules/web-console/src/main/js/app/controllers/notebooks.controller.js
deleted file mode 100644
index 0440c46..0000000
--- a/modules/web-console/src/main/js/app/controllers/notebooks.controller.js
+++ /dev/null
@@ -1,69 +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.
- */
-
-// Controller that load notebooks in navigation bar .
-export default ['notebooks', [
-    '$rootScope', '$scope', '$modal', '$state', '$http', 'IgniteMessages',
-    ($root, $scope, $modal, $state, $http, Messages) => {
-        $root.notebooks = [];
-
-        // Pre-fetch modal dialogs.
-        const _notebookNewModal = $modal({scope: $scope, templateUrl: '/sql/notebook-new.html', show: false});
-
-        $root.rebuildDropdown = function() {
-            $scope.notebookDropdown = [
-                {text: 'Create new notebook', click: 'inputNotebookName()'},
-                {divider: true}
-            ];
-
-            _.forEach($root.notebooks, (notebook) => $scope.notebookDropdown.push({
-                text: notebook.name,
-                sref: 'base.sql.notebook({noteId:"' + notebook._id + '"})'
-            }));
-        };
-
-        $root.reloadNotebooks = function() {
-            // When landing on the page, get clusters and show them.
-            $http.post('/api/v1/notebooks/list')
-                .success((data) => {
-                    $root.notebooks = data;
-
-                    $root.rebuildDropdown();
-                })
-                .error(Messages.showError);
-        };
-
-        $root.inputNotebookName = () => {
-            _notebookNewModal.$promise.then(_notebookNewModal.show);
-        };
-
-        $root.createNewNotebook = (name) => {
-            $http.post('/api/v1/notebooks/new', {name})
-                .success((noteId) => {
-                    _notebookNewModal.hide();
-
-                    $root.reloadNotebooks();
-
-                    $state.go('base.sql.notebook', {noteId});
-                })
-                .error(Messages.showError);
-        };
-
-        $root.reloadNotebooks();
-
-    }
-]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/controllers/reset-password.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/controllers/reset-password.controller.js b/modules/web-console/src/main/js/app/controllers/reset-password.controller.js
deleted file mode 100644
index f3cee81..0000000
--- a/modules/web-console/src/main/js/app/controllers/reset-password.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.
- */
-
-// Controller for password reset.
-export default ['resetPassword', [
-    '$scope', '$modal', '$http', '$state', 'IgniteMessages', 'IgniteFocus',
-    ($scope, $modal, $http, $state, Messages, Focus) => {
-        if ($state.params.token) {
-            $http.post('/api/v1/password/validate/token', {token: $state.params.token})
-                .success((res) => {
-                    $scope.email = res.email;
-                    $scope.token = res.token;
-                    $scope.error = res.error;
-
-                    if ($scope.token && !$scope.error)
-                        Focus.move('user_password');
-                });
-        }
-
-        // Try to reset user password for provided token.
-        $scope.resetPassword = (reset_info) => {
-            $http.post('/api/v1/password/reset', reset_info)
-                .success(() => {
-                    Messages.showInfo('Password successfully changed');
-
-                    $state.go('base.configuration.clusters');
-                })
-                .error((err, state) => {
-                    Messages.showError(err);
-
-                    if (state === 503)
-                        $state.go('base.configuration.clusters');
-                });
-        };
-
-    }
-]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/directives/auto-focus.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/auto-focus.directive.js b/modules/web-console/src/main/js/app/directives/auto-focus.directive.js
deleted file mode 100644
index 326fe1f..0000000
--- a/modules/web-console/src/main/js/app/directives/auto-focus.directive.js
+++ /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.
- */
-
-// Directive to auto-focus specified element.
-export default ['igniteAutoFocus', ['$timeout', ($timeout) => {
-    return {
-        restrict: 'AC',
-        link(scope, element) {
-            $timeout(() => element[0].focus());
-        }
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/directives/copy-to-clipboard.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/copy-to-clipboard.directive.js b/modules/web-console/src/main/js/app/directives/copy-to-clipboard.directive.js
deleted file mode 100644
index ee2110e..0000000
--- a/modules/web-console/src/main/js/app/directives/copy-to-clipboard.directive.js
+++ /dev/null
@@ -1,29 +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.
- */
-
-// Directive for copy to clipboard.
-export default ['igniteCopyToClipboard', ['IgniteCopyToClipboard', (CopyToClipboard) => {
-    return {
-        restrict: 'A',
-        link(scope, element, attrs) {
-            element.bind('click', () => CopyToClipboard.copy(attrs.igniteCopyToClipboard));
-
-            if (!document.queryCommandSupported('copy'))
-                element.hide();
-        }
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/directives/match.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/match.directive.js b/modules/web-console/src/main/js/app/directives/match.directive.js
deleted file mode 100644
index 3a45f6d..0000000
--- a/modules/web-console/src/main/js/app/directives/match.directive.js
+++ /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.
- */
-
-// Directive to enable validation to match specified value.
-export default ['igniteMatch', ['$parse', ($parse) => {
-    return {
-        require: 'ngModel',
-        link(scope, elem, attrs, ctrl) {
-            scope.$watch(() => $parse(attrs.igniteMatch)(scope) === ctrl.$modelValue,
-                (currentValue) => ctrl.$setValidity('mismatch', currentValue));
-        }
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/directives/on-click-focus.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/on-click-focus.directive.js b/modules/web-console/src/main/js/app/directives/on-click-focus.directive.js
deleted file mode 100644
index 5c9ee88..0000000
--- a/modules/web-console/src/main/js/app/directives/on-click-focus.directive.js
+++ /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.
- */
-
-// Directive to describe element that should be focused on click.
-export default ['igniteOnClickFocus', ['IgniteFocus', (Focus) => {
-    return function(scope, elem, attrs) {
-        elem.on('click', () => Focus.move(attrs.igniteOnClickFocus));
-
-        // Removes bound events in the element itself when the scope is destroyed
-        scope.$on('$destroy', () => elem.off('click'));
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/directives/on-enter-focus-move.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/on-enter-focus-move.directive.js b/modules/web-console/src/main/js/app/directives/on-enter-focus-move.directive.js
deleted file mode 100644
index 2dd2884..0000000
--- a/modules/web-console/src/main/js/app/directives/on-enter-focus-move.directive.js
+++ /dev/null
@@ -1,29 +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.
- */
-
-// Directive to move focus to specified element on ENTER key.
-export default ['igniteOnEnterFocusMove', ['IgniteFocus', (Focus) => {
-    return function(scope, elem, attrs) {
-        elem.on('keydown keypress', (event) => {
-            if (event.which === 13) {
-                event.preventDefault();
-
-                Focus.move(attrs.igniteOnEnterFocusMove);
-            }
-        });
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/directives/on-escape.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/on-escape.directive.js b/modules/web-console/src/main/js/app/directives/on-escape.directive.js
deleted file mode 100644
index aa1accd..0000000
--- a/modules/web-console/src/main/js/app/directives/on-escape.directive.js
+++ /dev/null
@@ -1,32 +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.
- */
-
-// Directive to bind ESC key press with some user action.
-export default ['igniteOnEscape', ['$timeout', ($timeout) => {
-    return function(scope, elem, attrs) {
-        elem.on('keydown keypress', (event) => {
-            if (event.which === 27) {
-                scope.$apply(() => $timeout(() => scope.$eval(attrs.igniteOnEscape)));
-
-                event.preventDefault();
-            }
-        });
-
-        // Removes bound events in the element itself when the scope is destroyed.
-        scope.$on('$destroy', () => elem.off('keydown keypress'));
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/filters/domainsValidation.filter.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/filters/domainsValidation.filter.js b/modules/web-console/src/main/js/app/filters/domainsValidation.filter.js
deleted file mode 100644
index 1a38392..0000000
--- a/modules/web-console/src/main/js/app/filters/domainsValidation.filter.js
+++ /dev/null
@@ -1,33 +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.
- */
-
-// Filter domain models with key fields configuration.
-export default ['domainsValidation', ['IgniteLegacyUtils', (LegacyUtils) => (domains, valid, invalid) => {
-    if (valid && invalid)
-        return domains;
-
-    const out = [];
-
-    _.forEach(domains, function(domain) {
-        const _valid = !LegacyUtils.domainForStoreConfigured(domain) || LegacyUtils.isJavaBuiltInClass(domain.keyType) || !_.isEmpty(domain.keyFields);
-
-        if (valid && _valid || invalid && !_valid)
-            out.push(domain);
-    });
-
-    return out;
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/services/Clone.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/Clone.service.js b/modules/web-console/src/main/js/app/services/Clone.service.js
deleted file mode 100644
index 52a4e4e..0000000
--- a/modules/web-console/src/main/js/app/services/Clone.service.js
+++ /dev/null
@@ -1,64 +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.
- */
-
-// Service for clone objects.
-export default ['IgniteClone', ['$rootScope', '$q', '$modal', ($root, $q, $modal) => {
-    const scope = $root.$new();
-
-    let _names = [];
-    let deferred;
-    let _validator;
-
-    function _nextAvailableName(name) {
-        let num = 1;
-        let tmpName = name;
-
-        while (_.includes(_names, tmpName)) {
-            tmpName = name + '_' + num.toString();
-
-            num++;
-        }
-
-        return tmpName;
-    }
-
-    const cloneModal = $modal({templateUrl: '/templates/clone.html', scope, placement: 'center', show: false});
-
-    scope.ok = function(newName) {
-        if (!_validator || _validator(newName)) {
-            deferred.resolve(_nextAvailableName(newName));
-
-            cloneModal.hide();
-        }
-    };
-
-    cloneModal.confirm = function(oldName, names, validator) {
-        _names = names;
-
-        scope.newName = _nextAvailableName(oldName);
-
-        _validator = validator;
-
-        deferred = $q.defer();
-
-        cloneModal.$promise.then(cloneModal.show);
-
-        return deferred.promise;
-    };
-
-    return cloneModal;
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/services/ConfirmBatch.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/ConfirmBatch.service.js b/modules/web-console/src/main/js/app/services/ConfirmBatch.service.js
deleted file mode 100644
index ef66335..0000000
--- a/modules/web-console/src/main/js/app/services/ConfirmBatch.service.js
+++ /dev/null
@@ -1,92 +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.
- */
-
-// Service for confirm or skip several steps.
-export default ['IgniteConfirmBatch', ['$rootScope', '$q', '$modal', ($root, $q, $modal) => {
-    const scope = $root.$new();
-
-    scope.confirmModal = $modal({
-        templateUrl: '/templates/batch-confirm.html',
-        scope,
-        placement: 'center',
-        show: false,
-        backdrop: 'static',
-        keyboard: false
-    });
-
-    const _done = (cancel) => {
-        scope.confirmModal.hide();
-
-        if (cancel)
-            scope.deferred.reject('cancelled');
-        else
-            scope.deferred.resolve();
-    };
-
-    const _nextElement = (skip) => {
-        scope.items[scope.curIx++].skip = skip;
-
-        if (scope.curIx < scope.items.length)
-            scope.content = scope.contentGenerator(scope.items[scope.curIx]);
-        else
-            _done();
-    };
-
-    scope.cancel = () => {
-        _done(true);
-    };
-
-    scope.skip = (applyToAll) => {
-        if (applyToAll) {
-            for (let i = scope.curIx; i < scope.items.length; i++)
-                scope.items[i].skip = true;
-
-            _done();
-        }
-        else
-            _nextElement(true);
-    };
-
-    scope.overwrite = (applyToAll) => {
-        if (applyToAll)
-            _done();
-        else
-            _nextElement(false);
-    };
-
-    return {
-        /**
-         * Show confirm all dialog.
-         *
-         * @param confirmMessageFn Function to generate a confirm message.
-         * @param itemsToConfirm Array of element to process by confirm.
-         */
-        confirm(confirmMessageFn, itemsToConfirm) {
-            scope.deferred = $q.defer();
-
-            scope.contentGenerator = confirmMessageFn;
-
-            scope.items = itemsToConfirm;
-            scope.curIx = 0;
-            scope.content = (scope.items && scope.items.length > 0) ? scope.contentGenerator(scope.items[0]) : null;
-
-            scope.confirmModal.$promise.then(scope.confirmModal.show);
-
-            return scope.deferred.promise;
-        }
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/services/CopyToClipboard.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/CopyToClipboard.service.js b/modules/web-console/src/main/js/app/services/CopyToClipboard.service.js
deleted file mode 100644
index 74c4764..0000000
--- a/modules/web-console/src/main/js/app/services/CopyToClipboard.service.js
+++ /dev/null
@@ -1,50 +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.
- */
-
-// Service to copy some value to OS clipboard.
-export default ['IgniteCopyToClipboard', ['$window', 'IgniteMessages', ($window, Messages) => {
-    const body = angular.element($window.document.body);
-
-    const textArea = angular.element('<textarea/>');
-
-    textArea.css({
-        position: 'fixed',
-        opacity: '0'
-    });
-
-    return {
-        copy(toCopy) {
-            textArea.val(toCopy);
-
-            body.append(textArea);
-
-            textArea[0].select();
-
-            try {
-                if (document.execCommand('copy'))
-                    Messages.showInfo('Value copied to clipboard');
-                else
-                    window.prompt('Copy to clipboard: Ctrl+C, Enter', toCopy);  // eslint-disable-line no-alert
-            }
-            catch (err) {
-                window.prompt('Copy to clipboard: Ctrl+C, Enter', toCopy);  // eslint-disable-line no-alert
-            }
-
-            textArea.remove();
-        }
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/services/Focus.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/Focus.service.js b/modules/web-console/src/main/js/app/services/Focus.service.js
deleted file mode 100644
index a07e181..0000000
--- a/modules/web-console/src/main/js/app/services/Focus.service.js
+++ /dev/null
@@ -1,33 +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.
- */
-
-// Service to transfer focus for specified element.
-export default ['IgniteFocus', ['$timeout', ($timeout) => {
-    return {
-        move(id) {
-            // Timeout makes sure that is invoked after any other event has been triggered.
-            // E.g. click events that need to run before the focus or inputs elements that are
-            // in a disabled state but are enabled when those events are triggered.
-            $timeout(() => {
-                const elem = $('#' + id);
-
-                if (elem.length > 0)
-                    elem[0].focus();
-            }, 100);
-        }
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/services/LegacyTable.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/LegacyTable.service.js b/modules/web-console/src/main/js/app/services/LegacyTable.service.js
deleted file mode 100644
index 8f3b791..0000000
--- a/modules/web-console/src/main/js/app/services/LegacyTable.service.js
+++ /dev/null
@@ -1,205 +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.
- */
-
-// TODO: Refactor this service for legacy tables with more than one input field.
-export default ['IgniteLegacyTable', ['IgniteLegacyUtils', 'IgniteFocus', (LegacyUtils, Focus) => {
-    function _model(item, field) {
-        return LegacyUtils.getModel(item, field);
-    }
-
-    const table = {name: 'none', editIndex: -1};
-
-    function _tableReset() {
-        delete table.field;
-        table.name = 'none';
-        table.editIndex = -1;
-
-        LegacyUtils.hidePopover();
-    }
-
-    function _tableSaveAndReset() {
-        const field = table.field;
-
-        const save = LegacyUtils.isDefined(field) && LegacyUtils.isDefined(field.save);
-
-        if (!save || !LegacyUtils.isDefined(field) || field.save(field, table.editIndex, true)) {
-            _tableReset();
-
-            return true;
-        }
-
-        return false;
-    }
-
-    function _tableState(field, editIndex, specName) {
-        table.field = field;
-        table.name = specName || field.model;
-        table.editIndex = editIndex;
-    }
-
-    function _tableUI(field) {
-        const ui = field.ui;
-
-        return ui ? ui : field.type;
-    }
-
-    function _tableFocus(focusId, index) {
-        Focus.move((index < 0 ? 'new' : 'cur') + focusId + (index >= 0 ? index : ''));
-    }
-
-    function _tablePairValue(filed, index) {
-        return index < 0 ? {key: filed.newKey, value: filed.newValue} : {key: filed.curKey, value: filed.curValue};
-    }
-
-    function _tableStartEdit(item, tbl, index, save) {
-        _tableState(tbl, index);
-
-        const val = _.get(_model(item, tbl), tbl.model)[index];
-
-        const ui = _tableUI(tbl);
-
-        tbl.save = save;
-
-        if (ui === 'table-pair') {
-            tbl.curKey = val[tbl.keyName];
-            tbl.curValue = val[tbl.valueName];
-
-            _tableFocus('Key' + tbl.focusId, index);
-        }
-        else if (ui === 'table-db-fields') {
-            tbl.curDatabaseFieldName = val.databaseFieldName;
-            tbl.curDatabaseFieldType = val.databaseFieldType;
-            tbl.curJavaFieldName = val.javaFieldName;
-            tbl.curJavaFieldType = val.javaFieldType;
-
-            _tableFocus('DatabaseFieldName' + tbl.focusId, index);
-        }
-        else if (ui === 'table-indexes') {
-            tbl.curIndexName = val.name;
-            tbl.curIndexType = val.indexType;
-            tbl.curIndexFields = val.fields;
-
-            _tableFocus(tbl.focusId, index);
-        }
-    }
-
-    function _tableNewItem(tbl) {
-        _tableState(tbl, -1);
-
-        const ui = _tableUI(tbl);
-
-        if (ui === 'table-pair') {
-            tbl.newKey = null;
-            tbl.newValue = null;
-
-            _tableFocus('Key' + tbl.focusId, -1);
-        }
-        else if (ui === 'table-db-fields') {
-            tbl.newDatabaseFieldName = null;
-            tbl.newDatabaseFieldType = null;
-            tbl.newJavaFieldName = null;
-            tbl.newJavaFieldType = null;
-
-            _tableFocus('DatabaseFieldName' + tbl.focusId, -1);
-        }
-        else if (ui === 'table-indexes') {
-            tbl.newIndexName = null;
-            tbl.newIndexType = 'SORTED';
-            tbl.newIndexFields = null;
-
-            _tableFocus(tbl.focusId, -1);
-        }
-    }
-
-    return {
-        tableState: _tableState,
-        tableReset: _tableReset,
-        tableSaveAndReset: _tableSaveAndReset,
-        tableNewItem: _tableNewItem,
-        tableNewItemActive(tbl) {
-            return table.name === tbl.model && table.editIndex < 0;
-        },
-        tableEditing(tbl, index) {
-            return table.name === tbl.model && table.editIndex === index;
-        },
-        tableEditedRowIndex() {
-            return table.editIndex;
-        },
-        tableField() {
-            return table.field;
-        },
-        tableStartEdit: _tableStartEdit,
-        tableRemove(item, field, index) {
-            _tableReset();
-
-            _.get(_model(item, field), field.model).splice(index, 1);
-        },
-        tablePairValue: _tablePairValue,
-        tablePairSave(pairValid, item, field, index, stopEdit) {
-            const valid = pairValid(item, field, index);
-
-            if (valid) {
-                const pairValue = _tablePairValue(field, index);
-
-                let pairModel = {};
-
-                const container = _.get(item, field.model);
-
-                if (index < 0) {
-                    pairModel[field.keyName] = pairValue.key;
-                    pairModel[field.valueName] = pairValue.value;
-
-                    if (container)
-                        container.push(pairModel);
-                    else
-                        _.set(item, field.model, [pairModel]);
-
-                    if (!stopEdit)
-                        _tableNewItem(field);
-                }
-                else {
-                    pairModel = container[index];
-
-                    pairModel[field.keyName] = pairValue.key;
-                    pairModel[field.valueName] = pairValue.value;
-
-                    if (!stopEdit) {
-                        if (index < container.length - 1)
-                            _tableStartEdit(item, field, index + 1);
-                        else
-                            _tableNewItem(field);
-                    }
-                }
-            }
-
-            return valid;
-        },
-        tablePairSaveVisible(field, index) {
-            const pairValue = _tablePairValue(field, index);
-
-            return !LegacyUtils.isEmptyString(pairValue.key) && !LegacyUtils.isEmptyString(pairValue.value);
-        },
-        tableFocusInvalidField(index, id) {
-            _tableFocus(id, index);
-
-            return false;
-        },
-        tableFieldId(index, id) {
-            return (index < 0 ? 'new' : 'cur') + id + (index >= 0 ? index : '');
-        }
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/services/Messages.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/Messages.service.js b/modules/web-console/src/main/js/app/services/Messages.service.js
deleted file mode 100644
index e679488..0000000
--- a/modules/web-console/src/main/js/app/services/Messages.service.js
+++ /dev/null
@@ -1,63 +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.
- */
-
-// Service to show various information and error messages.
-export default ['IgniteMessages', ['$alert', ($alert) => {
-    // Common instance of alert modal.
-    let msgModal;
-
-    const errorMessage = (prefix, err) => {
-        prefix = prefix || '';
-
-        if (err) {
-            if (err.hasOwnProperty('message'))
-                return prefix + err.message;
-
-            return prefix + err;
-        }
-
-        return prefix + 'Internal error.';
-    };
-
-    const hideAlert = () => {
-        if (msgModal)
-            msgModal.hide();
-    };
-
-    const _showMessage = (err, type, duration, icon) => {
-        hideAlert();
-
-        const title = errorMessage(null, err);
-
-        msgModal = $alert({type, title, duration});
-
-        msgModal.$scope.icon = icon;
-    };
-
-    return {
-        errorMessage,
-        hideAlert,
-        showError(err) {
-            _showMessage(err, 'danger', 10, 'fa-exclamation-triangle');
-
-            return false;
-        },
-        showInfo(err) {
-            _showMessage(err, 'success', 3, 'fa-check-circle-o');
-        }
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/services/UnsavedChangesGuard.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/UnsavedChangesGuard.service.js b/modules/web-console/src/main/js/app/services/UnsavedChangesGuard.service.js
deleted file mode 100644
index 91244b0..0000000
--- a/modules/web-console/src/main/js/app/services/UnsavedChangesGuard.service.js
+++ /dev/null
@@ -1,38 +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.
- */
-
-const MSG = 'You have unsaved changes.\n\nAre you sure you want to discard them?';
-
-// Service that show confirmation about unsaved changes on user change location.
-export default ['IgniteUnsavedChangesGuard', ['$rootScope', ($root) => {
-    return {
-        install(scope, customDirtyCheck = () => scope.ui.inputForm.$dirty) {
-            scope.$on('$destroy', () => window.onbeforeunload = null);
-
-            const unbind = $root.$on('$stateChangeStart', (event) => {
-                if (_.get(scope, 'ui.inputForm', false) && customDirtyCheck()) {
-                    if (!confirm(MSG)) // eslint-disable-line no-alert
-                        event.preventDefault();
-                    else
-                        unbind();
-                }
-            });
-
-            window.onbeforeunload = () => _.get(scope, 'ui.inputForm.$dirty', false) ? MSG : null;
-        }
-    };
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/services/confirm.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/confirm.service.js b/modules/web-console/src/main/js/app/services/confirm.service.js
deleted file mode 100644
index e69de29..0000000

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/app/vendor.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/vendor.js b/modules/web-console/src/main/js/app/vendor.js
deleted file mode 100644
index a8eeea7..0000000
--- a/modules/web-console/src/main/js/app/vendor.js
+++ /dev/null
@@ -1,54 +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.
- */
-
-import 'jquery';
-import 'angular';
-import 'angular-animate';
-import 'angular-sanitize';
-import 'angular-strap';
-import 'angular-strap/dist/angular-strap.tpl';
-import 'angular-socket-io';
-import 'angular-retina';
-import 'angular-ui-router';
-import 'ui-router-metatags/dist/ui-router-metatags';
-import 'angular-smart-table';
-import 'angular-ui-grid/ui-grid';
-import 'angular-drag-and-drop-lists';
-import 'angular-nvd3';
-import 'angular-tree-control';
-import 'angular-gridster';
-import 'bootstrap-sass/assets/javascripts/bootstrap/transition';
-import 'bootstrap-sass/assets/javascripts/bootstrap/carousel';
-import 'brace';
-import 'brace/mode/xml';
-import 'brace/mode/sql';
-import 'brace/mode/java';
-import 'brace/mode/dockerfile';
-import 'brace/mode/snippets';
-import 'brace/theme/chrome';
-import 'brace/ext/language_tools';
-import 'brace/ext/searchbox';
-import 'file-saver';
-import 'jszip';
-import 'nvd3';
-import 'query-command-supported';
-import 'angular-gridster/dist/angular-gridster.min.css';
-import 'angular-tree-control/css/tree-control-attribute.css';
-import 'angular-tree-control/css/tree-control.css';
-import 'angular-ui-grid/ui-grid.css';
-import 'angular-motion/dist/angular-motion.css';
-import 'nvd3/build/nv.d3.css';

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/gulpfile.babel.js/webpack/common.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/webpack/common.js b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/common.js
deleted file mode 100644
index 237f2e7..0000000
--- a/modules/web-console/src/main/js/gulpfile.babel.js/webpack/common.js
+++ /dev/null
@@ -1,192 +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.
- */
-
-import path from 'path';
-import fs from 'fs';
-import webpack from 'webpack';
-import autoprefixer from 'autoprefixer-core';
-import jade from 'jade';
-import progressPlugin from './plugins/progress';
-import eslintFormatter from 'eslint-friendly-formatter';
-
-import ExtractTextPlugin from 'extract-text-webpack-plugin';
-import HtmlWebpackPlugin from 'html-webpack-plugin';
-
-import {srcDir, destDir, rootDir} from '../paths';
-
-const NODE_ENV = process.env.NODE_ENV || 'production';
-const development = NODE_ENV === 'development';
-const node_modules_path = path.resolve('node_modules');
-const cssLoader = 'css-loader?sourceMap!postcss-loader';
-const stylesLoader = cssLoader + '!sass-loader?outputStyle=expanded&sourceMap=true&sourceMapContents=true';
-
-let favicon;
-
-try {
-    fs.accessSync('build/ignite_modules/favicon.ico', fs.F_OK);
-
-    favicon = 'build/ignite_modules/favicon.ico';
-} catch (ignore) {
-    favicon = 'build/favicon.ico';
-}
-
-export default () => {
-    return {
-        node: {
-            fs: 'empty'
-        },
-
-        // Entry points.
-        entry: {
-            polyfill: 'babel-polyfill',
-            app: path.join(srcDir, 'app.js'),
-            vendor: path.join(srcDir, 'vendor.js')
-        },
-
-        // Output system.
-        output: {
-            path: destDir,
-            publicPath: './',
-            filename: '[name].js'
-        },
-
-        // Resolves modules.
-        resolve: {
-            extensions: [
-                '',
-                '.js'
-            ],
-            root: [rootDir],
-            modulesDirectories: [
-                node_modules_path,
-                './'
-            ]
-        },
-
-        // Modules resolvers.
-        /* global require */
-        module: {
-            noParse: [],
-            preLoaders: [
-                {
-                    test: /\.js$/,
-                    exclude: [node_modules_path],
-                    loader: 'eslint-loader'
-                }
-            ],
-            loaders: [
-                {
-                    test: /\.json$/,
-                    loader: 'json-loader'
-                },
-                {
-                    test: /\.jade$/,
-                    loaders: [
-                        `ngtemplate-loader?relativeTo=${rootDir}`,
-                        'html-loader?attrs[]=img:src&attrs[]=img:data-src',
-                        'jade-html-loader'
-                    ]
-                },
-                {
-                    test: /\.js$/,
-                    exclude: [node_modules_path],
-                    loaders: ['ng-annotate-loader']
-                },
-                {
-                    test: /\.js$/,
-                    exclude: [node_modules_path],
-                    loader: 'babel-loader',
-                    query: {
-                        cacheDirectory: true,
-                        plugins: ['transform-runtime',
-                            'add-module-exports'],
-                        presets: ['angular']
-
-                    }
-                },
-                {
-                    test: /\.css$/,
-                    loader: development ? `style-loader!${cssLoader}` : ExtractTextPlugin.extract('style-loader', cssLoader)
-                },
-                {
-                    test: /\.(scss|sass)$/,
-                    loader: development ? `style-loader!${stylesLoader}` : ExtractTextPlugin.extract('style-loader', stylesLoader)
-                },
-                {
-                    test: /\.(woff2|woff|ttf|eot|svg)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
-                    loaders: [
-                        'file-loader?name=assets/fonts/[name].[ext]'
-                    ]
-                },
-                {
-                    test: /\.(jpe?g|png|gif)$/i,
-                    loaders: ['file-loader?name=assets/images/[name]_[hash].[ext]']
-                },
-                {
-                    test: require.resolve('jquery'),
-                    loaders: [
-                        'expose-loader?$',
-                        'expose-loader?jQuery'
-                    ]
-                },
-                {
-                    test: require.resolve('nvd3'),
-                    loaders: [
-                        'expose-loader?nv'
-                    ]
-                }
-            ]
-        },
-
-        // Postcss configuration.
-        postcss: [autoprefixer({browsers: ['last 2 versions']})],
-
-        // ESLint loader configuration.
-        eslint: {
-            failOnWarning: false,
-            failOnError: false,
-            formatter: eslintFormatter
-        },
-
-        // Load plugins.
-        plugins: [
-            new webpack.ProvidePlugin({
-                $: 'jquery',
-                jQuery: 'jquery',
-                _: 'lodash',
-                nv: 'nvd3'
-            }),
-            new webpack.DefinePlugin({NODE_ENV: JSON.stringify(NODE_ENV)}),
-            // new webpack.NoErrorsPlugin(),
-            new webpack.optimize.DedupePlugin(),
-            new webpack.optimize.CommonsChunkPlugin({
-                name: 'common',
-                chunks: ['vendor', 'app']
-            }),
-            new webpack.optimize.AggressiveMergingPlugin({moveToParents: true}),
-            new ExtractTextPlugin('assets/css/[name]' + (development ? '' : '.[chunkhash]') + '.css', {allChunks: true}),
-            new HtmlWebpackPlugin({
-                filename: 'index.html',
-                templateContent: () => {
-                    return jade.renderFile(path.join(rootDir, 'views', 'index.jade'));
-                },
-                favicon
-            }),
-            progressPlugin
-        ]
-    };
-};

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/gulpfile.babel.js/webpack/environments/production.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/webpack/environments/production.js b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/environments/production.js
deleted file mode 100644
index db66720..0000000
--- a/modules/web-console/src/main/js/gulpfile.babel.js/webpack/environments/production.js
+++ /dev/null
@@ -1,45 +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.
- */
-
-import webpack from 'webpack';
-
-import {destDir, rootDir} from '../../paths';
-
-export default () => {
-    const plugins = [
-        new webpack.optimize.UglifyJsPlugin({
-            path: destDir,
-            minimize: true,
-            warnings: false,
-            sourceMap: false,
-            mangle: true
-        })
-    ];
-
-    return {
-        context: rootDir,
-        bail: true, // Cancel build on error.
-        debug: false,
-        devtool: 'cheap-source-map',
-        output: {
-            publicPath: '/',
-            filename: '[name].[chunkhash].js',
-            path: destDir
-        },
-        plugins
-    };
-};

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/gulpfile.babel.js/webpack/index.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/webpack/index.js b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/index.js
deleted file mode 100644
index 6682f9c..0000000
--- a/modules/web-console/src/main/js/gulpfile.babel.js/webpack/index.js
+++ /dev/null
@@ -1,32 +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.
- */
-
-import _ from 'lodash';
-import commonConfig from './common';
-import devConfig from './environments/development';
-import prodConfig from './environments/production';
-
-const env = process.env.NODE_ENV || 'production';
-
-// Config by environments.
-const configs = {
-    production: prodConfig,
-    development: devConfig
-};
-
-// Load config file by environment
-export default _.merge(commonConfig(), configs[env]());

http://git-wip-us.apache.org/repos/asf/ignite/blob/1bb10f90/modules/web-console/src/main/js/gulpfile.babel.js/webpack/plugins/progress.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/webpack/plugins/progress.js b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/plugins/progress.js
deleted file mode 100644
index 5f753c7..0000000
--- a/modules/web-console/src/main/js/gulpfile.babel.js/webpack/plugins/progress.js
+++ /dev/null
@@ -1,82 +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.
- */
-
-import ProgressPlugin from 'webpack/lib/ProgressPlugin';
-
-let chars = 0;
-let lastState = 0;
-let lastStateTime = 0;
-
-const outputStream = process.stdout;
-
-const _goToLineStart = (nextMessage) => {
-    let str = '';
-
-    for (; chars > nextMessage.length; chars--)
-        str += '\b \b';
-
-    chars = nextMessage.length;
-
-    for (let i = 0; i < chars; i++)
-        str += '\b';
-
-    if (str)
-        outputStream.write(str);
-};
-
-export default new ProgressPlugin((percentage, msg) => {
-    let state = msg;
-
-    if (percentage < 1) {
-        percentage = Math.floor(percentage * 100);
-
-        msg = percentage + '% ' + msg;
-
-        if (percentage < 100)
-            msg = ' ' + msg;
-
-        if (percentage < 10)
-            msg = ' ' + msg;
-    }
-
-    state = state.replace(/^\d+\/\d+\s+/, '');
-
-    if (percentage === 0) {
-        lastState = null;
-        lastStateTime = (new Date()).getTime();
-    }
-    else if (state !== lastState || percentage === 1) {
-        const now = (new Date()).getTime();
-
-        if (lastState) {
-            const stateMsg = (now - lastStateTime) + 'ms ' + lastState;
-
-            _goToLineStart(stateMsg);
-
-            outputStream.write(stateMsg + '\n');
-
-            chars = 0;
-        }
-
-        lastState = state;
-        lastStateTime = now;
-    }
-
-    _goToLineStart(msg);
-
-    outputStream.write(msg);
-});


[24/50] [abbrv] ignite git commit: IGNITE-3706 Fixed new query creation.

Posted by an...@apache.org.
IGNITE-3706 Fixed new query creation.


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

Branch: refs/heads/ignite-3629
Commit: 52b18034176f0c458a1f5dcd2e463e3f252ce753
Parents: ce5ea58
Author: Andrey Novikov <an...@apache.org>
Authored: Mon Aug 29 10:25:46 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Mon Aug 29 10:25:46 2016 +0700

----------------------------------------------------------------------
 .../frontend/app/modules/sql/sql.controller.js  | 142 +++++++++----------
 1 file changed, 71 insertions(+), 71 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/52b18034/modules/web-console/frontend/app/modules/sql/sql.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/sql.controller.js b/modules/web-console/frontend/app/modules/sql/sql.controller.js
index d3449ed..1c68a64 100644
--- a/modules/web-console/frontend/app/modules/sql/sql.controller.js
+++ b/modules/web-console/frontend/app/modules/sql/sql.controller.js
@@ -41,9 +41,66 @@ const _fullColName = (col) => {
     return res.join('.');
 };
 
+let paragraphId = 0;
+
 class Paragraph {
-    constructor(paragraph) {
+    constructor($animate, $timeout, paragraph) {
+        const self = this;
+
+        self.id = 'paragraph-' + paragraphId++;
+
         _.assign(this, paragraph);
+
+        Object.defineProperty(this, 'gridOptions', {value: {
+            enableGridMenu: false,
+            enableColumnMenus: false,
+            flatEntityAccess: true,
+            fastWatch: true,
+            rebuildColumns() {
+                if (_.isNil(this.api))
+                    return;
+
+                this.columnDefs = _.reduce(self.meta, (cols, col, idx) => {
+                    if (self.columnFilter(col)) {
+                        cols.push({
+                            displayName: col.fieldName,
+                            headerTooltip: _fullColName(col),
+                            field: idx.toString(),
+                            minWidth: 50,
+                            cellClass: 'cell-left'
+                        });
+                    }
+
+                    return cols;
+                }, []);
+
+                $timeout(() => this.api.core.notifyDataChange('column'));
+            },
+            adjustHeight() {
+                if (_.isNil(this.api))
+                    return;
+
+                this.data = self.rows;
+
+                const height = Math.min(self.rows.length, 15) * 30 + 47;
+
+                // Remove header height.
+                this.api.grid.element.css('height', height + 'px');
+
+                $timeout(() => this.api.core.handleWindowResize());
+            },
+            onRegisterApi(api) {
+                $animate.enabled(api.grid.element, false);
+
+                this.api = api;
+
+                this.rebuildColumns();
+
+                this.adjustHeight();
+            }
+        }});
+
+        Object.defineProperty(this, 'chartHistory', {value: []});
     }
 
     resultType() {
@@ -93,8 +150,8 @@ class Paragraph {
 }
 
 // Controller for SQL notebook screen.
-export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', '$animate', '$location', '$anchorScroll', '$state', '$modal', '$popover', 'IgniteLoading', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteAgentMonitor', 'IgniteChartColors', 'IgniteNotebook', 'IgniteScanFilterInput', 'uiGridConstants', 'uiGridExporterConstants',
-    function($root, $scope, $http, $q, $timeout, $interval, $animate, $location, $anchorScroll, $state, $modal, $popover, Loading, LegacyUtils, Messages, Confirm, agentMonitor, IgniteChartColors, Notebook, ScanFilterInput, uiGridConstants, uiGridExporterConstants) {
+export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', '$animate', '$location', '$anchorScroll', '$state', '$modal', '$popover', 'IgniteLoading', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteAgentMonitor', 'IgniteChartColors', 'IgniteNotebook', 'IgniteScanFilterInput', 'uiGridExporterConstants',
+    function($root, $scope, $http, $q, $timeout, $interval, $animate, $location, $anchorScroll, $state, $modal, $popover, Loading, LegacyUtils, Messages, Confirm, agentMonitor, IgniteChartColors, Notebook, ScanFilterInput, uiGridExporterConstants) {
         let stopTopology = null;
 
         const _tryStopRefresh = function(paragraph) {
@@ -674,8 +731,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             });
         };
 
-        $scope.scrollToParagraph = function(paragraphId) {
-            const idx = _.findIndex($scope.notebook.paragraphs, {id: paragraphId});
+        $scope.scrollToParagraph = (id) => {
+            const idx = _.findIndex($scope.notebook.paragraphs, {id});
 
             if (idx >= 0) {
                 if (!_.includes($scope.notebook.expandedParagraphs, idx))
@@ -686,7 +743,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                 });
             }
 
-            $location.hash(paragraphId);
+            $location.hash(id);
 
             $anchorScroll();
         };
@@ -695,8 +752,6 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
 
         const _allColumn = () => true;
 
-        let paragraphId = 0;
-
         $scope.aceInit = function(paragraph) {
             return function(editor) {
                 editor.setAutoScrollEditorIntoView(true);
@@ -788,64 +843,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                 if (!$scope.notebook.paragraphs)
                     $scope.notebook.paragraphs = [];
 
-                $scope.notebook.paragraphs = _.map($scope.notebook.paragraphs, (paragraph) => {
-                    paragraph.id = 'paragraph-' + paragraphId++;
-
-                    const par = new Paragraph(paragraph);
-
-                    Object.defineProperty(par, 'gridOptions', {value: {
-                        enableGridMenu: false,
-                        enableColumnMenus: false,
-                        flatEntityAccess: true,
-                        fastWatch: true,
-                        rebuildColumns() {
-                            if (_.isNil(this.api))
-                                return;
-
-                            this.columnDefs = _.reduce(par.meta, (cols, col, idx) => {
-                                if (par.columnFilter(col)) {
-                                    cols.push({
-                                        displayName: col.fieldName,
-                                        headerTooltip: _fullColName(col),
-                                        field: idx.toString(),
-                                        minWidth: 50,
-                                        cellClass: 'cell-left'
-                                    });
-                                }
-
-                                return cols;
-                            }, []);
-
-                            $timeout(() => this.api.core.notifyDataChange(uiGridConstants.dataChange.COLUMN));
-                        },
-                        adjustHeight() {
-                            if (_.isNil(this.api))
-                                return;
-
-                            this.data = par.rows;
-
-                            const height = Math.min(this.data.length, 15) * 30 + 47;
-
-                            // Remove header height.
-                            this.api.grid.element.css('height', height + 'px');
-
-                            $timeout(() => this.api.core.handleWindowResize());
-                        },
-                        onRegisterApi(api) {
-                            $animate.enabled(api.grid.element, false);
-
-                            this.api = api;
-
-                            this.rebuildColumns();
-
-                            this.adjustHeight();
-                        }
-                    }});
-
-                    Object.defineProperty(par, 'chartHistory', {value: []});
-
-                    return par;
-                });
+                $scope.notebook.paragraphs = _.map($scope.notebook.paragraphs,
+                    (paragraph) => new Paragraph($animate, $timeout, paragraph));
 
                 if (_.isEmpty($scope.notebook.paragraphs))
                     $scope.addParagraph();
@@ -902,8 +901,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
         $scope.addParagraph = function() {
             const sz = $scope.notebook.paragraphs.length;
 
-            const paragraph = {
-                id: 'paragraph-' + paragraphId++,
+            const paragraph = new Paragraph($animate, $timeout, {
                 name: 'Query' + (sz === 0 ? '' : sz),
                 query: '',
                 pageSize: $scope.pageSizes[0],
@@ -914,7 +912,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                     unit: 60000,
                     installed: false
                 }
-            };
+            });
 
             if ($scope.caches && $scope.caches.length > 0)
                 paragraph.cacheName = $scope.caches[0].name;
@@ -927,9 +925,11 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
 
             $location.hash(paragraph.id);
 
-            $anchorScroll();
+            $timeout(() => {
+                $anchorScroll();
 
-            setTimeout(paragraph.ace.focus);
+                paragraph.ace.focus();
+            });
         };
 
         function _saveChartSettings(paragraph) {


[38/50] [abbrv] ignite git commit: GG-11489 Minor fix.

Posted by an...@apache.org.
GG-11489 Minor fix.


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

Branch: refs/heads/ignite-3629
Commit: 5330ed886d618c3f6e0b3cb1c94ab322b8710856
Parents: a0d985d
Author: Andrey Novikov <an...@apache.org>
Authored: Mon Sep 5 17:48:25 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Mon Sep 5 17:48:25 2016 +0700

----------------------------------------------------------------------
 .../frontend/app/controllers/reset-password.controller.js | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/5330ed88/modules/web-console/frontend/app/controllers/reset-password.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/controllers/reset-password.controller.js b/modules/web-console/frontend/app/controllers/reset-password.controller.js
index 846cd42..da0c37b 100644
--- a/modules/web-console/frontend/app/controllers/reset-password.controller.js
+++ b/modules/web-console/frontend/app/controllers/reset-password.controller.js
@@ -35,15 +35,15 @@ export default ['resetPassword', [
         $scope.resetPassword = (reset_info) => {
             $http.post('/api/v1/password/reset', reset_info)
                 .success(() => {
-                    Messages.showInfo('Password successfully changed');
+                    $state.go('signin');
 
-                    $state.go('base.configuration.clusters');
+                    Messages.showInfo('Password successfully changed');
                 })
                 .error((err, state) => {
-                    Messages.showError(err);
-
                     if (state === 503)
-                        $state.go('base.configuration.clusters');
+                        $state.go('signin');
+
+                    Messages.showError(err);
                 });
         };
     }


[43/50] [abbrv] ignite git commit: IGNITE-2047 Fixed inform message

Posted by an...@apache.org.
IGNITE-2047 Fixed inform message


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

Branch: refs/heads/ignite-3629
Commit: 5daf03046ba06d2c5032cced5c8a24145735224c
Parents: 79175ab
Author: vsisko <vs...@gridgain.com>
Authored: Tue Sep 6 11:02:12 2016 +0700
Committer: vsisko <vs...@gridgain.com>
Committed: Tue Sep 6 11:02:12 2016 +0700

----------------------------------------------------------------------
 .../frontend/app/modules/states/configuration/caches/general.jade  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/5daf0304/modules/web-console/frontend/app/modules/states/configuration/caches/general.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/general.jade b/modules/web-console/frontend/app/modules/states/configuration/caches/general.jade
index 114085e..e3147b1 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/general.jade
+++ b/modules/web-console/frontend/app/modules/states/configuration/caches/general.jade
@@ -33,7 +33,7 @@ include ../../../../../app/helpers/jade/mixins.jade
                     +clusters(model, 'Associate clusters with the current cache')
                 .settings-row
                     +dropdown-multiple('<span>Domain models:</span><a ui-sref="base.configuration.domains({linkId: linkId()})"> (add)</a>',
-                        model + '.domains', '"domains"', true, 'Choose domain models', 'No domain models configured', 'domains',
+                        model + '.domains', '"domains"', true, 'Choose domain models', 'No valid domain models configured', 'domains',
                         'Select domain models to describe types in cache')
                 .settings-row
                     +cacheMode('Mode:', model + '.cacheMode', '"cacheMode"', 'PARTITIONED')


[41/50] [abbrv] ignite git commit: IGNITE-2047 Fixed add of ssl thrust manager for new cluster.

Posted by an...@apache.org.
IGNITE-2047 Fixed add of ssl thrust manager for new cluster.


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

Branch: refs/heads/ignite-3629
Commit: 33581ba565e6ed8061447d051144a63abecb40dc
Parents: 40a7990
Author: vsisko <vs...@gridgain.com>
Authored: Tue Sep 6 10:40:55 2016 +0700
Committer: vsisko <vs...@gridgain.com>
Committed: Tue Sep 6 10:40:55 2016 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/controllers/clusters-controller.js | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/33581ba5/modules/web-console/frontend/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/clusters-controller.js b/modules/web-console/frontend/controllers/clusters-controller.js
index 5f6f19b..17a4e51 100644
--- a/modules/web-console/frontend/controllers/clusters-controller.js
+++ b/modules/web-console/frontend/controllers/clusters-controller.js
@@ -33,7 +33,9 @@ export default ['clustersController', [
             connector: {},
             discovery: {},
             marshaller: {},
-            sslContextFactory: {},
+            sslContextFactory: {
+                trustManagers: []
+            },
             swapSpaceSpi: {},
             transactionConfiguration: {},
             collision: {}


[39/50] [abbrv] ignite git commit: ignite-3629 Integrated mockgoose for mocking mongo db layer.

Posted by an...@apache.org.
ignite-3629 Integrated mockgoose for mocking mongo db layer.


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

Branch: refs/heads/ignite-3629
Commit: 0580bbf45e3248fc7a74d2b09727975b44d9de54
Parents: 5330ed8
Author: Maxim Afanasiev <ma...@gmail.com>
Authored: Mon Sep 5 23:05:53 2016 +0700
Committer: Maxim Afanasiev <ma...@gmail.com>
Committed: Mon Sep 5 23:05:53 2016 +0700

----------------------------------------------------------------------
 modules/web-console/backend/app/mongo.js        |  2 +-
 modules/web-console/backend/app/mongoose.js     | 31 ++++++++++++++++++
 .../backend/test/fixtures/mockgoose.js          | 34 ++++++++++++++++++++
 modules/web-console/backend/test/injector.js    |  6 ++--
 4 files changed, 70 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/0580bbf4/modules/web-console/backend/app/mongo.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/app/mongo.js b/modules/web-console/backend/app/mongo.js
index 7fe39f0..640cece 100644
--- a/modules/web-console/backend/app/mongo.js
+++ b/modules/web-console/backend/app/mongo.js
@@ -24,7 +24,7 @@
  */
 module.exports = {
     implements: 'mongo',
-    inject: ['require(passport-local-mongoose)', 'settings', 'ignite_modules/mongo:*', 'require(mongoose)']
+    inject: ['require(passport-local-mongoose)', 'settings', 'ignite_modules/mongo:*', 'mongoose']
 };
 
 module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/0580bbf4/modules/web-console/backend/app/mongoose.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/app/mongoose.js b/modules/web-console/backend/app/mongoose.js
new file mode 100644
index 0000000..5dba51d
--- /dev/null
+++ b/modules/web-console/backend/app/mongoose.js
@@ -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.
+ */
+
+'use strict';
+
+// Fire me up!
+
+module.exports = {
+    implements: 'mongoose',
+    inject: ['require(mongoose)']
+};
+
+
+module.exports.factory = (mongoose) => {
+    return mongoose;
+};
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/0580bbf4/modules/web-console/backend/test/fixtures/mockgoose.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/test/fixtures/mockgoose.js b/modules/web-console/backend/test/fixtures/mockgoose.js
new file mode 100644
index 0000000..84eb088
--- /dev/null
+++ b/modules/web-console/backend/test/fixtures/mockgoose.js
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+// Fire me up!
+
+module.exports = {
+    implements: 'mongoose:mock',
+    inject: ['mongoose', 'require(mockgoose)']
+};
+
+
+module.exports.factory = (mongoose, mockgoose) => {
+    return new Promise((resolve) => {
+        mockgoose(mongoose).then(() => resolve(mongoose));
+    });
+};
+
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/0580bbf4/modules/web-console/backend/test/injector.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/test/injector.js b/modules/web-console/backend/test/injector.js
index 8d44d31..3cec9d6 100644
--- a/modules/web-console/backend/test/injector.js
+++ b/modules/web-console/backend/test/injector.js
@@ -26,6 +26,8 @@ module.exports = fireUp.newInjector({
         './errors/**/*.js',
         './middlewares/**/*.js',
         './routes/**/*.js',
-        './services/**/*.js'
-    ]
+        './services/**/*.js',
+        './test/fixtures/*.js'
+    ],
+    use: ['mongoose:mock']
 });


[23/50] [abbrv] ignite git commit: IGNITE-2388 Reworked authorization check.

Posted by an...@apache.org.
IGNITE-2388 Reworked authorization check.


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

Branch: refs/heads/ignite-3629
Commit: ce5ea58d99516fd0c694fc0307d4694da127cdd0
Parents: 1bb10f9
Author: Andrey Novikov <an...@apache.org>
Authored: Mon Aug 29 09:36:26 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Mon Aug 29 09:36:26 2016 +0700

----------------------------------------------------------------------
 modules/web-console/backend/app/routes.js       | 14 +++++-
 modules/web-console/backend/middlewares/user.js |  3 --
 modules/web-console/frontend/app/app.js         | 14 ++----
 .../app/modules/states/password.state.js        |  4 +-
 .../frontend/app/modules/states/signin.state.js |  8 ++--
 .../app/modules/user/AclRoute.provider.js       | 17 +++++--
 .../frontend/app/modules/user/Auth.service.js   | 42 ++++------------
 .../frontend/app/modules/user/User.service.js   | 50 +++++---------------
 .../frontend/app/modules/user/user.module.js    | 18 +++++++
 .../frontend/controllers/admin-controller.js    |  2 +-
 10 files changed, 74 insertions(+), 98 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ce5ea58d/modules/web-console/backend/app/routes.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/app/routes.js b/modules/web-console/backend/app/routes.js
index 86a31f0..6961173 100644
--- a/modules/web-console/backend/app/routes.js
+++ b/modules/web-console/backend/app/routes.js
@@ -29,9 +29,19 @@ module.exports.factory = function(publicRoute, adminRoute, profilesRoute, demoRo
     clustersRoute, domainsRoute, cachesRoute, igfssRoute, notebooksRoute, agentsRoute, configurationsRoute) {
     return {
         register: (app) => {
-            const _mustAuthenticated = (req, res, next) => req.isAuthenticated() ? next() : res.redirect('/');
+            const _mustAuthenticated = (req, res, next) => {
+                if (req.isAuthenticated())
+                    return next();
 
-            const _adminOnly = (req, res, next) => req.isAuthenticated() && req.user.admin ? next() : res.sendStatus(403);
+                res.status(401).send('Access denied. You are not authorized to access this page.');
+            };
+
+            const _adminOnly = (req, res, next) => {
+                if (req.isAuthenticated() && req.user.admin)
+                    return next();
+
+                res.status(401).send('Access denied. You are not authorized to access this page.');
+            };
 
             // Registering the standard routes
             app.use('/', publicRoute);

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce5ea58d/modules/web-console/backend/middlewares/user.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/middlewares/user.js b/modules/web-console/backend/middlewares/user.js
index 25e639b..8923211 100644
--- a/modules/web-console/backend/middlewares/user.js
+++ b/modules/web-console/backend/middlewares/user.js
@@ -24,9 +24,6 @@ module.exports = {
     factory: () => {
         return (req, res, next) => {
             req.currentUserId = function() {
-                if (!req.user)
-                    return null;
-
                 if (req.session.viewedUser && req.user.admin)
                     return req.session.viewedUser._id;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce5ea58d/modules/web-console/frontend/app/app.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/app.js b/modules/web-console/frontend/app/app.js
index 7ac1802..98a2fac 100644
--- a/modules/web-console/frontend/app/app.js
+++ b/modules/web-console/frontend/app/app.js
@@ -242,12 +242,9 @@ angular
     $root.$meta = $meta;
     $root.gettingStarted = gettingStarted;
 }])
-.run(['$rootScope', 'Auth', 'User', 'IgniteAgentMonitor', ($root, Auth, User, agentMonitor) => {
-    if (Auth.authorized) {
-        User.read()
-            .then((user) => $root.$broadcast('user', user))
-            .then(() => Auth.authorized && agentMonitor.init());
-    }
+.run(['$rootScope', 'User', 'IgniteAgentMonitor', ($root, User, agentMonitor) => {
+    User.read()
+        .then(() => agentMonitor.init());
 }])
 .run(['$rootScope', ($root) => {
     $root.$on('$stateChangeStart', () => {
@@ -257,9 +254,8 @@ angular
 .run(['$rootScope', '$http', '$state', 'IgniteMessages', 'User',
     ($root, $http, $state, Messages, User) => { // eslint-disable-line no-shadow
         $root.revertIdentity = () => {
-            $http
-                .get('/api/v1/admin/revert/identity')
-                .then(User.read)
+            $http.get('/api/v1/admin/revert/identity')
+                .then(User.load)
                 .then((user) => {
                     $root.$broadcast('user', user);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce5ea58d/modules/web-console/frontend/app/modules/states/password.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/password.state.js b/modules/web-console/frontend/app/modules/states/password.state.js
index 2eb030c..48d01df 100644
--- a/modules/web-console/frontend/app/modules/states/password.state.js
+++ b/modules/web-console/frontend/app/modules/states/password.state.js
@@ -21,7 +21,7 @@ angular
 .module('ignite-console.states.password', [
     'ui.router'
 ])
-.config(['$stateProvider', 'AclRouteProvider', function($stateProvider, AclRoute) {
+.config(['$stateProvider', function($stateProvider) {
     // set up the states
     $stateProvider
     .state('password', {
@@ -32,7 +32,6 @@ angular
     .state('password.reset', {
         url: '/reset?{token}',
         templateUrl: '/reset.html',
-        onEnter: AclRoute.checkAccess('login'),
         metaTags: {
             title: 'Reset password'
         }
@@ -40,7 +39,6 @@ angular
     .state('password.send', {
         url: '/send',
         templateUrl: '/reset.html',
-        onEnter: AclRoute.checkAccess('login'),
         metaTags: {
             title: 'Password Send'
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce5ea58d/modules/web-console/frontend/app/modules/states/signin.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/signin.state.js b/modules/web-console/frontend/app/modules/states/signin.state.js
index aaae286..ec62af5 100644
--- a/modules/web-console/frontend/app/modules/states/signin.state.js
+++ b/modules/web-console/frontend/app/modules/states/signin.state.js
@@ -30,11 +30,9 @@ angular
     .state('signin', {
         url: '/',
         templateUrl,
-        onEnter: ['$state', 'Auth', 'AclService', ($state, Auth, AclService) => {
-            if (Auth.authorized)
-                $state.go('base.configuration.clusters', {}, {reload: true});
-            else if (!AclService.can('login'))
-                $state.go('403');
+        onEnter: ['$state', 'User', ($state, User) => {
+            User.read()
+                .then(() => $state.go('base.configuration.clusters', {}, {reload: true}));
         }],
         metaTags: {
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce5ea58d/modules/web-console/frontend/app/modules/user/AclRoute.provider.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/AclRoute.provider.js b/modules/web-console/frontend/app/modules/user/AclRoute.provider.js
index cfd9da1..40abea5 100644
--- a/modules/web-console/frontend/app/modules/user/AclRoute.provider.js
+++ b/modules/web-console/frontend/app/modules/user/AclRoute.provider.js
@@ -20,11 +20,20 @@ export default [() => {
         static checkAccess = (permissions, failState) => {
             failState = failState || '403';
 
-            return ['$state', 'AclService', 'Auth', ($state, AclService) => {
-                if (AclService.can(permissions))
-                    return;
+            return ['$state', 'AclService', 'User', ($state, AclService, User) => {
+                User.read()
+                    .then(() => {
+                        if (AclService.can(permissions))
+                            return;
 
-                return $state.go(failState);
+                        return $state.go(failState);
+                    })
+                    .catch(() => {
+                        User.clean();
+
+                        if ($state.current.name !== 'signin')
+                            $state.go('signin');
+                    });
             }];
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce5ea58d/modules/web-console/frontend/app/modules/user/Auth.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/Auth.service.js b/modules/web-console/frontend/app/modules/user/Auth.service.js
index 15b90f0..ddf58d0 100644
--- a/modules/web-console/frontend/app/modules/user/Auth.service.js
+++ b/modules/web-console/frontend/app/modules/user/Auth.service.js
@@ -17,30 +17,7 @@
 
 export default ['Auth', ['$http', '$rootScope', '$state', '$window', 'IgniteLegacyUtils', 'IgniteMessages', 'gettingStarted', 'User', 'IgniteAgentMonitor',
     ($http, $root, $state, $window, LegacyUtils, Messages, gettingStarted, User, agentMonitor) => {
-        let _auth = false;
-
-        try {
-            _auth = localStorage.authorized === 'true';
-        }
-        catch (ignore) {
-            // No-op.
-        }
-
-        function _authorized(value) {
-            try {
-                return _auth = localStorage.authorized = !!value;
-            } catch (ignore) {
-                return _auth = !!value;
-            }
-        }
-
         return {
-            get authorized() {
-                return _auth;
-            },
-            set authorized(auth) {
-                _authorized(auth);
-            },
             forgotPassword(userInfo) {
                 $http.post('/api/v1/password/forgot', userInfo)
                     .success(() => $state.go('password.send'))
@@ -49,17 +26,20 @@ export default ['Auth', ['$http', '$rootScope', '$state', '$window', 'IgniteLega
             auth(action, userInfo) {
                 $http.post('/api/v1/' + action, userInfo)
                     .catch(({data}) => Promise.reject(data))
-                    .then(User.read)
-                    .then((user) => {
-                        _authorized(true);
+                    .then(() => {
+                        if (action === 'password/forgot')
+                            return;
 
-                        $root.$broadcast('user', user);
+                        User.read()
+                            .then((user) => {
+                                $root.$broadcast('user', user);
 
-                        $state.go('base.configuration.clusters');
+                                $state.go('base.configuration.clusters');
 
-                        $root.gettingStarted.tryShow();
+                                agentMonitor.init();
 
-                        agentMonitor.init();
+                                $root.gettingStarted.tryShow();
+                            });
                     })
                     .catch((err) => LegacyUtils.showPopoverMessage(null, null, action + '_email', Messages.errorMessage(null, err)));
             },
@@ -68,8 +48,6 @@ export default ['Auth', ['$http', '$rootScope', '$state', '$window', 'IgniteLega
                     .success(() => {
                         User.clean();
 
-                        _authorized(false);
-
                         $window.open($state.href('signin'), '_self');
                     })
                     .error(Messages.showError);

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce5ea58d/modules/web-console/frontend/app/modules/user/User.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/User.service.js b/modules/web-console/frontend/app/modules/user/User.service.js
index 4812b54..f95590a 100644
--- a/modules/web-console/frontend/app/modules/user/User.service.js
+++ b/modules/web-console/frontend/app/modules/user/User.service.js
@@ -16,57 +16,29 @@
  */
 
 export default ['User', ['$q', '$injector', '$rootScope', '$state', '$http', function($q, $injector, $root, $state, $http) {
-    let _user;
-
-    try {
-        _user = JSON.parse(localStorage.user);
-
-        if (_user)
-            $root.user = _user;
-    }
-    catch (ignore) {
-        // No-op.
-    }
+    let user = null;
 
     return {
-        read() {
-            const dropSessionAndSignin = () => {
-                const Auth = $injector.get('Auth');
-
-                Auth.authorized = false;
-
-                this.clean();
-
-                if ($state.current.name !== 'signin')
-                    $state.go('signin');
-            };
-
+        load() {
             return $http.post('/api/v1/user')
                 .then(({data}) => {
-                    if (_.isEmpty(data))
-                        return dropSessionAndSignin();
+                    user = $root.user = data;
 
-                    try {
-                        localStorage.user = JSON.stringify(data);
-                    }
-                    catch (ignore) {
-                        // No-op.
-                    }
+                    $root.$broadcast('user', user);
 
-                    return _user = $root.user = data;
+                    return user;
                 })
-                .catch(({data, status}) => {
-                    if (status === 401)
-                        dropSessionAndSignin();
+                .catch(({data}) => $q.reject(data));
+        },
+        read() {
+            if (user)
+                return $q.resolve(user);
 
-                    return Promise.reject(data);
-                });
+            return this.load();
         },
         clean() {
             delete $root.user;
 
-            delete localStorage.user;
-
             delete $root.IgniteDemoMode;
 
             sessionStorage.removeItem('IgniteDemoMode');

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce5ea58d/modules/web-console/frontend/app/modules/user/user.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/user.module.js b/modules/web-console/frontend/app/modules/user/user.module.js
index a480f97..e721789 100644
--- a/modules/web-console/frontend/app/modules/user/user.module.js
+++ b/modules/web-console/frontend/app/modules/user/user.module.js
@@ -27,6 +27,24 @@ angular
     'mm.acl',
     'ignite-console.config'
 ])
+.factory('sessionRecoverer', ['$injector', '$q', ($injector, $q) => {
+    return {
+        responseError: (response) => {
+            const $state = $injector.get('$state');
+
+            // Session has expired
+            if (response.status === 401 && $state.current.name !== 'signin')
+                $state.go('signin');
+
+            $injector.get('User').clean();
+
+            return $q.reject(response);
+        }
+    };
+}])
+.config(['$httpProvider', ($httpProvider) => {
+    $httpProvider.interceptors.push('sessionRecoverer');
+}])
 .service(...Auth)
 .service(...User)
 .provider('AclRoute', AclRouteProvider)

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce5ea58d/modules/web-console/frontend/controllers/admin-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/admin-controller.js b/modules/web-console/frontend/controllers/admin-controller.js
index 73eb61a..57a39b2 100644
--- a/modules/web-console/frontend/controllers/admin-controller.js
+++ b/modules/web-console/frontend/controllers/admin-controller.js
@@ -41,7 +41,7 @@ export default ['adminController', [
         $scope.becomeUser = function(user) {
             $http.get('/api/v1/admin/become', { params: {viewedUserId: user._id}})
                 .catch(({data}) => Promise.reject(data))
-                .then(User.read)
+                .then(User.load)
                 .then((becomeUser) => {
                     $rootScope.$broadcast('user', becomeUser);
 


[17/50] [abbrv] ignite git commit: GG-11178 Minor fix.

Posted by an...@apache.org.
GG-11178 Minor fix.


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

Branch: refs/heads/ignite-3629
Commit: 57c78ff11643e52f24b989ee9ee13844229f6e14
Parents: c716d59
Author: Andrey Novikov <an...@apache.org>
Authored: Fri Aug 26 11:10:06 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Fri Aug 26 11:10:06 2016 +0700

----------------------------------------------------------------------
 .../java/org/apache/ignite/console/demo/AgentClusterDemo.java     | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/57c78ff1/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/demo/AgentClusterDemo.java
----------------------------------------------------------------------
diff --git a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/demo/AgentClusterDemo.java b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/demo/AgentClusterDemo.java
index bf0903a..09189b5 100644
--- a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/demo/AgentClusterDemo.java
+++ b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/demo/AgentClusterDemo.java
@@ -54,6 +54,7 @@ import org.apache.ignite.logger.log4j.Log4JLogger;
 import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.spi.swapspace.file.FileSwapSpaceSpi;
 import org.apache.ignite.transactions.Transaction;
 import org.apache.log4j.Logger;
 
@@ -363,6 +364,8 @@ public class AgentClusterDemo {
 
         cfg.setCacheConfiguration(cacheCountry(), cacheDepartment(), cacheEmployee(), cacheParking(), cacheCar());
 
+        cfg.setSwapSpaceSpi(new FileSwapSpaceSpi());
+
         return cfg;
     }
 


[05/50] [abbrv] ignite git commit: Merge branch 'web-console-staging' of https://github.com/gridgain/apache-ignite into web-console-staging

Posted by an...@apache.org.
Merge branch 'web-console-staging' of https://github.com/gridgain/apache-ignite into web-console-staging


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

Branch: refs/heads/ignite-3629
Commit: 9e45deed0b0ade456594539428b0c468e7a336d7
Parents: e8a32f1 e6ed223
Author: Dmitriyff Smile <dm...@gmail.com>
Authored: Mon Aug 22 14:00:10 2016 +0700
Committer: Dmitriyff Smile <dm...@gmail.com>
Committed: Mon Aug 22 14:00:10 2016 +0700

----------------------------------------------------------------------
 modules/web-console/backend/app/mongo.js        |  3 +-
 .../frontend/app/helpers/jade/mixins.jade       |  6 ++--
 .../configuration/caches/concurrency.jade       | 10 +++---
 .../states/configuration/caches/general.jade    |  4 +--
 .../states/configuration/caches/memory.jade     | 36 +++++++++++---------
 .../states/configuration/caches/rebalance.jade  |  2 +-
 .../configuration/caches/server-near-cache.jade |  8 ++++-
 .../states/configuration/caches/store.jade      | 14 +++++---
 .../states/configuration/clusters/binary.jade   |  4 +--
 .../configuration/clusters/communication.jade   | 11 +++---
 .../configuration/clusters/connector.jade       |  2 +-
 .../configuration/clusters/discovery.jade       | 22 +++++++-----
 .../states/configuration/clusters/general.jade  | 19 ++++++-----
 .../states/configuration/clusters/igfs.jade     |  2 +-
 .../configuration/clusters/logger/custom.jade   |  2 +-
 .../configuration/clusters/marshaller.jade      | 10 ++++--
 .../states/configuration/clusters/metrics.jade  |  3 +-
 .../states/configuration/clusters/ssl.jade      |  2 +-
 .../states/configuration/clusters/swap.jade     |  6 +++-
 .../configuration/clusters/transactions.jade    | 14 ++++++--
 .../states/configuration/igfs/general.jade      |  2 +-
 .../modules/states/configuration/igfs/ipc.jade  |  7 ++--
 .../modules/states/configuration/igfs/misc.jade |  2 +-
 .../frontend/generator/generator-common.js      |  3 +-
 24 files changed, 122 insertions(+), 72 deletions(-)
----------------------------------------------------------------------



[33/50] [abbrv] ignite git commit: IGNITE-2047 Fixed id generation for checkboxes. Fixed popover message for checkbox field.

Posted by an...@apache.org.
IGNITE-2047 Fixed id generation for checkboxes. Fixed popover message for checkbox field.


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

Branch: refs/heads/ignite-3629
Commit: 1fe790a94357013d6660472093f1650e9894b890
Parents: 76f7eab
Author: vsisko <vs...@gridgain.com>
Authored: Thu Sep 1 14:45:56 2016 +0700
Committer: vsisko <vs...@gridgain.com>
Committed: Thu Sep 1 14:45:56 2016 +0700

----------------------------------------------------------------------
 .../frontend/app/helpers/jade/form/form-field-checkbox.jade      | 4 ++--
 modules/web-console/frontend/controllers/caches-controller.js    | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/1fe790a9/modules/web-console/frontend/app/helpers/jade/form/form-field-checkbox.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/helpers/jade/form/form-field-checkbox.jade b/modules/web-console/frontend/app/helpers/jade/form/form-field-checkbox.jade
index ece189d..ef5cb37 100644
--- a/modules/web-console/frontend/app/helpers/jade/form/form-field-checkbox.jade
+++ b/modules/web-console/frontend/app/helpers/jade/form/form-field-checkbox.jade
@@ -15,8 +15,8 @@
     limitations under the License.
 
 mixin form-field-checkbox(label, model, name, disabled, required, tip)
-    div.checkbox
-        label.col-xs-12.col-sm-12.col-md-12(id='#{name}Label')
+    div.checkbox.col-xs-12.col-sm-12.col-md-12
+        label(id='{{ #{name} }}Label')
             .input-tip
                 if block
                     block

http://git-wip-us.apache.org/repos/asf/ignite/blob/1fe790a9/modules/web-console/frontend/controllers/caches-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/caches-controller.js b/modules/web-console/frontend/controllers/caches-controller.js
index 3a8a849..f08940c 100644
--- a/modules/web-console/frontend/controllers/caches-controller.js
+++ b/modules/web-console/frontend/controllers/caches-controller.js
@@ -331,7 +331,7 @@ export default ['cachesController', [
                 return ErrorPopover.show('cacheStoreFactory', 'Write behind enabled but store is not configured!', $scope.ui, 'store');
 
             if (cacheStoreFactorySelected && !item.readThrough && !item.writeThrough)
-                return ErrorPopover.show('readThroughTooltip', 'Store is configured but read/write through are not enabled!', $scope.ui, 'store');
+                return ErrorPopover.show('readThroughLabel', 'Store is configured but read/write through are not enabled!', $scope.ui, 'store');
 
             return true;
         }


[27/50] [abbrv] ignite git commit: IGNITE-3620 Moved popover functions and form function in separated services.

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/27176d59/modules/web-console/frontend/controllers/domains-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/domains-controller.js b/modules/web-console/frontend/controllers/domains-controller.js
index cf4e3c8..ea53777 100644
--- a/modules/web-console/frontend/controllers/domains-controller.js
+++ b/modules/web-console/frontend/controllers/domains-controller.js
@@ -17,8 +17,8 @@
 
 // Controller for Domain model screen.
 export default ['domainsController', [
-    '$rootScope', '$scope', '$http', '$state', '$filter', '$timeout', '$modal', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteFocus', 'IgniteConfirm', 'IgniteConfirmBatch', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteAgentMonitor', 'IgniteLegacyTable', 'igniteConfigurationResource',
-    function($root, $scope, $http, $state, $filter, $timeout, $modal, LegacyUtils, Messages, Focus, Confirm, ConfirmBatch, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, IgniteAgentMonitor, LegacyTable, Resource) {
+    '$rootScope', '$scope', '$http', '$state', '$filter', '$timeout', '$modal', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteFocus', 'IgniteConfirm', 'IgniteConfirmBatch', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteAgentMonitor', 'IgniteLegacyTable', 'igniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils',
+    function($root, $scope, $http, $state, $filter, $timeout, $modal, LegacyUtils, Messages, Focus, Confirm, ConfirmBatch, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, IgniteAgentMonitor, LegacyTable, Resource, ErrorPopover, FormUtils) {
         UnsavedChangesGuard.install($scope);
 
         const emptyDomain = {empty: true};
@@ -30,7 +30,7 @@ export default ['domainsController', [
         // We need to initialize backupItem with empty object in order to properly used from angular directives.
         $scope.backupItem = emptyDomain;
 
-        $scope.ui = LegacyUtils.formUI();
+        $scope.ui = FormUtils.formUI();
         $scope.ui.activePanels = [0, 1];
         $scope.ui.topPanels = [0, 1, 2];
 
@@ -68,9 +68,9 @@ export default ['domainsController', [
 
         $scope.getModel = LegacyUtils.getModel;
         $scope.javaBuiltInClasses = LegacyUtils.javaBuiltInClasses;
-        $scope.compactJavaName = LegacyUtils.compactJavaName;
-        $scope.widthIsSufficient = LegacyUtils.widthIsSufficient;
-        $scope.saveBtnTipText = LegacyUtils.saveBtnTipText;
+        $scope.compactJavaName = FormUtils.compactJavaName;
+        $scope.widthIsSufficient = FormUtils.widthIsSufficient;
+        $scope.saveBtnTipText = FormUtils.saveBtnTipText;
 
         $scope.tableSave = function(field, index, stopEdit) {
             if (LegacyTable.tableEditing({model: 'table-index-fields'}, LegacyTable.tableEditedRowIndex())) {
@@ -173,10 +173,6 @@ export default ['domainsController', [
             'It may be a result of import tables from database without primary keys<br/>' +
             'Key field for such key types should be configured manually';
 
-        $scope.hidePopover = LegacyUtils.hidePopover;
-
-        const showPopoverMessage = LegacyUtils.showPopoverMessage;
-
         $scope.indexType = LegacyUtils.mkOptions(['SORTED', 'FULLTEXT', 'GEOSPATIAL']);
 
         const _dbPresets = [
@@ -380,7 +376,7 @@ export default ['domainsController', [
         $scope.showImportDomainModal = function() {
             LegacyTable.tableReset();
 
-            LegacyUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, function() {
+            FormUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, function() {
                 if ($scope.ui.inputForm.$dirty)
                     $scope.backupItem = $scope.selectedItem ? angular.copy($scope.selectedItem) : prepareNewItem();
 
@@ -436,7 +432,7 @@ export default ['domainsController', [
 
                                     $scope.ui.selectedJdbcDriverJar = $scope.jdbcDriverJars[0].value;
 
-                                    LegacyUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, function() {
+                                    FormUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, function() {
                                         importDomainModal.$promise.then(() => {
                                             $scope.importDomain.action = 'connect';
                                             $scope.importDomain.tables = [];
@@ -728,7 +724,7 @@ export default ['domainsController', [
 
         function _saveDomainModel() {
             if (LegacyUtils.isEmptyString($scope.ui.packageName))
-                return LegacyUtils.showPopoverMessage(null, null, 'domainPackageName', 'Package could not be empty');
+                return ErrorPopover.show('domainPackageName', 'Package could not be empty');
 
             if (!LegacyUtils.isValidJavaClass('Package', $scope.ui.packageName, false, 'domainPackageName', true))
                 return false;
@@ -1132,6 +1128,10 @@ export default ['domainsController', [
                     else
                         form.$setDirty();
                 }, true);
+
+                $scope.$watch('ui.activePanels.length', () => {
+                    ErrorPopover.hide();
+                });
             })
             .catch(Messages.showError)
             .then(() => {
@@ -1191,15 +1191,15 @@ export default ['domainsController', [
                     $state.go('base.configuration.domains');
             }
 
-            LegacyUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, selectItem);
+            FormUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, selectItem);
         };
 
         // Add new domain model.
         $scope.createItem = function(cacheId) {
             if ($scope.tableReset(true)) {
                 $timeout(() => {
-                    LegacyUtils.ensureActivePanel($scope.ui, 'query');
-                    LegacyUtils.ensureActivePanel($scope.ui, 'general', 'keyType');
+                    FormUtils.ensureActivePanel($scope.ui, 'query');
+                    FormUtils.ensureActivePanel($scope.ui, 'general', 'keyType');
                 });
 
                 $scope.selectItem(null, prepareNewItem(cacheId));
@@ -1209,14 +1209,14 @@ export default ['domainsController', [
         function checkQueryConfiguration(item) {
             if (item.queryMetadata === 'Configuration' && LegacyUtils.domainForQueryConfigured(item)) {
                 if (_.isEmpty(item.fields))
-                    return showPopoverMessage($scope.ui, 'query', 'queryFields', 'Query fields should not be empty');
+                    return ErrorPopover.show('queryFields', 'Query fields should not be empty', $scope.ui, 'query');
 
                 const indexes = item.indexes;
 
                 if (indexes && indexes.length > 0) {
                     if (_.find(indexes, function(index, i) {
                         if (_.isEmpty(index.fields))
-                            return !showPopoverMessage($scope.ui, 'query', 'indexes' + i, 'Index fields are not specified');
+                            return !ErrorPopover.show('indexes' + i, 'Index fields are not specified', $scope.ui, 'query');
                     }))
                         return false;
                 }
@@ -1228,19 +1228,19 @@ export default ['domainsController', [
         function checkStoreConfiguration(item) {
             if (LegacyUtils.domainForStoreConfigured(item)) {
                 if (LegacyUtils.isEmptyString(item.databaseSchema))
-                    return showPopoverMessage($scope.ui, 'store', 'databaseSchema', 'Database schema should not be empty');
+                    return ErrorPopover.show('databaseSchema', 'Database schema should not be empty', $scope.ui, 'store');
 
                 if (LegacyUtils.isEmptyString(item.databaseTable))
-                    return showPopoverMessage($scope.ui, 'store', 'databaseTable', 'Database table should not be empty');
+                    return ErrorPopover.show('databaseTable', 'Database table should not be empty', $scope.ui, 'store');
 
                 if (_.isEmpty(item.keyFields))
-                    return showPopoverMessage($scope.ui, 'store', 'keyFields', 'Key fields are not specified');
+                    return ErrorPopover.show('keyFields', 'Key fields are not specified', $scope.ui, 'store');
 
                 if (LegacyUtils.isJavaBuiltInClass(item.keyType) && item.keyFields.length !== 1)
-                    return showPopoverMessage($scope.ui, 'store', 'keyFields', 'Only one field should be specified in case when key type is a Java built-in type');
+                    return ErrorPopover.show('keyFields', 'Only one field should be specified in case when key type is a Java built-in type', $scope.ui, 'store');
 
                 if (_.isEmpty(item.valueFields))
-                    return showPopoverMessage($scope.ui, 'store', 'valueFields', 'Value fields are not specified');
+                    return ErrorPopover.show('valueFields', 'Value fields are not specified', $scope.ui, 'store');
             }
 
             return true;
@@ -1258,7 +1258,7 @@ export default ['domainsController', [
                 return false;
 
             if (!LegacyUtils.domainForStoreConfigured(item) && !LegacyUtils.domainForQueryConfigured(item) && item.queryMetadata === 'Configuration')
-                return showPopoverMessage($scope.ui, 'query', 'query-title', 'SQL query domain model should be configured');
+                return ErrorPopover.show('query-title', 'SQL query domain model should be configured', $scope.ui, 'query');
 
             return true;
         }
@@ -1466,7 +1466,7 @@ export default ['domainsController', [
 
                     // Found duplicate by key.
                     if (idx >= 0 && idx !== index)
-                        return showPopoverMessage($scope.ui, 'query', LegacyTable.tableFieldId(index, pairField.idPrefix + pairField.id), 'Field with such ' + pairField.dupObjName + ' already exists!');
+                        return ErrorPopover.show(LegacyTable.tableFieldId(index, pairField.idPrefix + pairField.id), 'Field with such ' + pairField.dupObjName + ' already exists!', $scope.ui, 'query');
                 }
 
                 if (pairField.classValidation && !LegacyUtils.isValidJavaClass(pairField.msg, pairValue.value, true, LegacyTable.tableFieldId(index, 'Value' + pairField.id), false, $scope.ui, 'query'))
@@ -1524,7 +1524,7 @@ export default ['domainsController', [
 
                     // Found duplicate.
                     if (idx >= 0 && index !== idx)
-                        return showPopoverMessage($scope.ui, 'store', LegacyTable.tableFieldId(index, 'DatabaseFieldName' + dbFieldTable.id), 'Field with such database name already exists!');
+                        return ErrorPopover.show(LegacyTable.tableFieldId(index, 'DatabaseFieldName' + dbFieldTable.id), 'Field with such database name already exists!', $scope.ui, 'store');
 
                     idx = _.findIndex(model, function(dbMeta) {
                         return dbMeta.javaFieldName === dbFieldValue.javaFieldName;
@@ -1532,7 +1532,7 @@ export default ['domainsController', [
 
                     // Found duplicate.
                     if (idx >= 0 && index !== idx)
-                        return showPopoverMessage($scope.ui, 'store', LegacyTable.tableFieldId(index, 'JavaFieldName' + dbFieldTable.id), 'Field with such java name already exists!');
+                        return ErrorPopover.show(LegacyTable.tableFieldId(index, 'JavaFieldName' + dbFieldTable.id), 'Field with such java name already exists!', $scope.ui, 'store');
 
                     if (index < 0)
                         model.push(dbFieldValue);
@@ -1593,7 +1593,7 @@ export default ['domainsController', [
 
                 // Found duplicate.
                 if (idx >= 0 && idx !== curIdx)
-                    return showPopoverMessage($scope.ui, 'query', LegacyTable.tableFieldId(curIdx, 'IndexName'), 'Index with such name already exists!');
+                    return ErrorPopover.show(LegacyTable.tableFieldId(curIdx, 'IndexName'), 'Index with such name already exists!', $scope.ui, 'query');
             }
 
             LegacyTable.tableReset();
@@ -1708,7 +1708,7 @@ export default ['domainsController', [
 
                 // Found duplicate.
                 if (idx >= 0 && idx !== curIdx)
-                    return showPopoverMessage($scope.ui, 'query', LegacyTable.tableFieldId(curIdx, 'FieldName' + (index.indexType === 'SORTED' ? 'S' : '') + indexIdx + (curIdx >= 0 ? '-' : '')), 'Field with such name already exists in index!');
+                    return ErrorPopover.show(LegacyTable.tableFieldId(curIdx, 'FieldName' + (index.indexType === 'SORTED' ? 'S' : '') + indexIdx + (curIdx >= 0 ? '-' : '')), 'Field with such name already exists in index!', $scope.ui, 'query');
             }
 
             LegacyTable.tableReset();

http://git-wip-us.apache.org/repos/asf/ignite/blob/27176d59/modules/web-console/frontend/controllers/igfs-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/igfs-controller.js b/modules/web-console/frontend/controllers/igfs-controller.js
index 2508e6b..10e22c4 100644
--- a/modules/web-console/frontend/controllers/igfs-controller.js
+++ b/modules/web-console/frontend/controllers/igfs-controller.js
@@ -17,8 +17,8 @@
 
 // Controller for IGFS screen.
 export default ['igfsController', [
-    '$scope', '$http', '$state', '$filter', '$timeout', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteLegacyTable', 'igniteConfigurationResource',
-    function($scope, $http, $state, $filter, $timeout, LegacyUtils, Messages, Confirm, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, LegacyTable, Resource) {
+    '$scope', '$http', '$state', '$filter', '$timeout', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteLegacyTable', 'igniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils',
+    function($scope, $http, $state, $filter, $timeout, LegacyUtils, Messages, Confirm, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, LegacyTable, Resource, ErrorPopover, FormUtils) {
         UnsavedChangesGuard.install($scope);
 
         const emptyIgfs = {empty: true};
@@ -33,15 +33,13 @@ export default ['igfsController', [
         // We need to initialize backupItem with empty object in order to properly used from angular directives.
         $scope.backupItem = emptyIgfs;
 
-        $scope.ui = LegacyUtils.formUI();
+        $scope.ui = FormUtils.formUI();
         $scope.ui.activePanels = [0];
         $scope.ui.topPanels = [0];
 
-        $scope.compactJavaName = LegacyUtils.compactJavaName;
-        $scope.widthIsSufficient = LegacyUtils.widthIsSufficient;
-        $scope.saveBtnTipText = LegacyUtils.saveBtnTipText;
-
-        const showPopoverMessage = LegacyUtils.showPopoverMessage;
+        $scope.compactJavaName = FormUtils.compactJavaName;
+        $scope.widthIsSufficient = FormUtils.widthIsSufficient;
+        $scope.saveBtnTipText = FormUtils.saveBtnTipText;
 
         $scope.tableSave = function(field, index, stopEdit) {
             if (field.type === 'pathModes' && LegacyTable.tablePairSaveVisible(field, index))
@@ -94,7 +92,7 @@ export default ['igfsController', [
 
                 // Found duplicate.
                 if (idx >= 0 && idx !== index)
-                    return showPopoverMessage($scope.ui, 'misc', LegacyTable.tableFieldId(index, 'KeyPathMode'), 'Such path already exists!');
+                    return ErrorPopover.show(LegacyTable.tableFieldId(index, 'KeyPathMode'), 'Such path already exists!', $scope.ui, 'misc');
             }
 
             return true;
@@ -121,7 +119,7 @@ export default ['igfsController', [
         $scope.toggleExpanded = function() {
             $scope.ui.expanded = !$scope.ui.expanded;
 
-            LegacyUtils.hidePopover();
+            ErrorPopover.hide();
         };
 
         $scope.igfss = [];
@@ -190,6 +188,10 @@ export default ['igfsController', [
                     else
                         form.$setDirty();
                 }, true);
+
+                $scope.$watch('ui.activePanels.length', () => {
+                    ErrorPopover.hide();
+                });
             })
             .catch(Messages.showError)
             .then(() => {
@@ -231,7 +233,7 @@ export default ['igfsController', [
                     $state.go('base.configuration.igfs');
             }
 
-            LegacyUtils.confirmUnsavedChanges($scope.backupItem && $scope.ui.inputForm.$dirty, selectItem);
+            FormUtils.confirmUnsavedChanges($scope.backupItem && $scope.ui.inputForm.$dirty, selectItem);
         };
 
         $scope.linkId = () => $scope.backupItem._id ? $scope.backupItem._id : 'create';
@@ -251,7 +253,7 @@ export default ['igfsController', [
         // Add new IGFS.
         $scope.createItem = function(linkId) {
             if ($scope.tableReset(true)) {
-                $timeout(() => LegacyUtils.ensureActivePanel($scope.ui, 'general', 'igfsName'));
+                $timeout(() => FormUtils.ensureActivePanel($scope.ui, 'general', 'igfsName'));
 
                 $scope.selectItem(null, prepareNewItem(linkId));
             }
@@ -259,21 +261,21 @@ export default ['igfsController', [
 
         // Check IGFS logical consistency.
         function validate(item) {
-            LegacyUtils.hidePopover();
+            ErrorPopover.hide();
 
             if (LegacyUtils.isEmptyString(item.name))
-                return showPopoverMessage($scope.ui, 'general', 'igfsName', 'IGFS name should not be empty!');
+                return ErrorPopover.show('igfsName', 'IGFS name should not be empty!', $scope.ui, 'general');
 
             if (!LegacyUtils.checkFieldValidators($scope.ui))
                 return false;
 
             if (!item.secondaryFileSystemEnabled && (item.defaultMode === 'PROXY'))
-                return showPopoverMessage($scope.ui, 'secondaryFileSystem', 'secondaryFileSystem-title', 'Secondary file system should be configured for "PROXY" IGFS mode!');
+                return ErrorPopover.show('secondaryFileSystem-title', 'Secondary file system should be configured for "PROXY" IGFS mode!', $scope.ui, 'secondaryFileSystem');
 
             if (item.pathModes) {
                 for (let pathIx = 0; pathIx < item.pathModes.length; pathIx++) {
                     if (!item.secondaryFileSystemEnabled && item.pathModes[pathIx].mode === 'PROXY')
-                        return showPopoverMessage($scope.ui, 'secondaryFileSystem', 'secondaryFileSystem-title', 'Secondary file system should be configured for "PROXY" path mode!');
+                        return ErrorPopover.show('secondaryFileSystem-title', 'Secondary file system should be configured for "PROXY" path mode!', $scope.ui, 'secondaryFileSystem');
                 }
             }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/27176d59/modules/web-console/frontend/generator/generator-xml.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/generator/generator-xml.js b/modules/web-console/frontend/generator/generator-xml.js
index 9f7ebe4..acdbca0 100644
--- a/modules/web-console/frontend/generator/generator-xml.js
+++ b/modules/web-console/frontend/generator/generator-xml.js
@@ -1293,7 +1293,7 @@ $generatorXml.cacheNodeFilter = function(cache, igfss, res) {
 
     const kind = _.get(cache, 'nodeFilter.kind');
 
-    if (_.isNil(cache.nodeFilter[kind]))
+    if (_.isNil(kind) || _.isNil(cache.nodeFilter[kind]))
         return res;
 
     switch (kind) {


[40/50] [abbrv] ignite git commit: IGNITE-2047 Fixed add of cache key configuration for new cluster.

Posted by an...@apache.org.
IGNITE-2047 Fixed add of cache key configuration for new cluster.


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

Branch: refs/heads/ignite-3629
Commit: 40a79908f13673999f87813530c07e44975288b1
Parents: 5330ed8
Author: vsisko <vs...@gridgain.com>
Authored: Tue Sep 6 10:32:29 2016 +0700
Committer: vsisko <vs...@gridgain.com>
Committed: Tue Sep 6 10:32:29 2016 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/controllers/clusters-controller.js | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/40a79908/modules/web-console/frontend/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/clusters-controller.js b/modules/web-console/frontend/controllers/clusters-controller.js
index 7389578..5f6f19b 100644
--- a/modules/web-console/frontend/controllers/clusters-controller.js
+++ b/modules/web-console/frontend/controllers/clusters-controller.js
@@ -28,6 +28,7 @@ export default ['clustersController', [
         const blank = {
             atomicConfiguration: {},
             binaryConfiguration: {},
+            cacheKeyConfiguration: [],
             communication: {},
             connector: {},
             discovery: {},


[07/50] [abbrv] ignite git commit: IGNITE-3706 Added query duration, scan with filter on SQL screen.

Posted by an...@apache.org.
IGNITE-3706  Added query duration, scan with filter on SQL screen.


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

Branch: refs/heads/ignite-3629
Commit: d8fa49eac8ade248d1e850ecf371d4001e07f1a5
Parents: 0a1fa24
Author: Andrey Novikov <an...@apache.org>
Authored: Wed Aug 24 15:04:58 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Wed Aug 24 15:04:58 2016 +0700

----------------------------------------------------------------------
 .../frontend/app/helpers/jade/form/form-field-checkbox.jade        | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d8fa49ea/modules/web-console/frontend/app/helpers/jade/form/form-field-checkbox.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/helpers/jade/form/form-field-checkbox.jade b/modules/web-console/frontend/app/helpers/jade/form/form-field-checkbox.jade
index 76d8728..ece189d 100644
--- a/modules/web-console/frontend/app/helpers/jade/form/form-field-checkbox.jade
+++ b/modules/web-console/frontend/app/helpers/jade/form/form-field-checkbox.jade
@@ -35,4 +35,4 @@ mixin form-field-checkbox(label, model, name, disabled, required, tip)
                         data-ignite-form-panel-field=''
                     )
             span #{label}
-            i.tipLabel.fa.fa-question-circle(bs-tooltip data-title=tip)
+            i.tipLabel.fa.fa-question-circle(bs-tooltip='' data-title=tip)


[46/50] [abbrv] ignite git commit: Restore cache query indexed types.

Posted by an...@apache.org.
Restore cache query indexed types.


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

Branch: refs/heads/ignite-3629
Commit: 4fe6862df4c0f4076c486d8321f0315e658e0d5f
Parents: 05c35bb
Author: Andrey Novikov <an...@apache.org>
Authored: Tue Sep 6 14:50:51 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Tue Sep 6 14:50:51 2016 +0700

----------------------------------------------------------------------
 .../ui-ace-java/ui-ace-java.directive.js          |  3 ++-
 .../directives/ui-ace-xml/ui-ace-xml.directive.js |  3 ++-
 .../states/configuration/caches/query.jade        |  2 +-
 .../frontend/generator/generator-java.js          | 18 ++++++++++++++++--
 .../frontend/generator/generator-xml.js           |  6 +++---
 5 files changed, 24 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/4fe6862d/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.directive.js b/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.directive.js
index 3216d41..fbb1431 100644
--- a/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.directive.js
+++ b/modules/web-console/frontend/app/directives/ui-ace-java/ui-ace-java.directive.js
@@ -77,6 +77,7 @@ export default ['igniteUiAceJava', ['GeneratorJava', (generator) => {
                     break;
 
                 case 'cacheStore':
+                case 'cacheQuery':
                     ctrl.generator = (cache) => {
                         const domains = _.reduce(scope.detail, (acc, domain) => {
                             if (_.includes(cache.domains, domain.value))
@@ -85,7 +86,7 @@ export default ['igniteUiAceJava', ['GeneratorJava', (generator) => {
                             return acc;
                         }, []);
 
-                        return generator.cacheStore(cache, domains).asString();
+                        return generator[method](cache, domains).asString();
                     };
 
                     break;

http://git-wip-us.apache.org/repos/asf/ignite/blob/4fe6862d/modules/web-console/frontend/app/directives/ui-ace-xml/ui-ace-xml.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/directives/ui-ace-xml/ui-ace-xml.directive.js b/modules/web-console/frontend/app/directives/ui-ace-xml/ui-ace-xml.directive.js
index 4b27e60..3bd834f 100644
--- a/modules/web-console/frontend/app/directives/ui-ace-xml/ui-ace-xml.directive.js
+++ b/modules/web-console/frontend/app/directives/ui-ace-xml/ui-ace-xml.directive.js
@@ -77,6 +77,7 @@ export default ['igniteUiAceXml', ['GeneratorXml', (generator) => {
                     break;
 
                 case 'cacheStore':
+                case 'cacheQuery':
                     ctrl.generator = (cache) => {
                         const domains = _.reduce(scope.detail, (acc, domain) => {
                             if (_.includes(cache.domains, domain.value))
@@ -85,7 +86,7 @@ export default ['igniteUiAceXml', ['GeneratorXml', (generator) => {
                             return acc;
                         }, []);
 
-                        return generator.cacheStore(cache, domains).asString();
+                        return generator[method](cache, domains).asString();
                     };
 
                     break;

http://git-wip-us.apache.org/repos/asf/ignite/blob/4fe6862d/modules/web-console/frontend/app/modules/states/configuration/caches/query.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/query.jade b/modules/web-console/frontend/app/modules/states/configuration/caches/query.jade
index b924720..c83114b 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/query.jade
+++ b/modules/web-console/frontend/app/modules/states/configuration/caches/query.jade
@@ -92,4 +92,4 @@ include ../../../../../app/helpers/jade/mixins.jade
                         'If set then all the SQL table and field names will be escaped with double quotes<br/>\
                         This enforces case sensitivity for field names and also allows having special characters in table and field names')
             .col-sm-6
-                +preview-xml-java(model, 'cacheQuery')
+                +preview-xml-java(model, 'cacheQuery', 'domains')

http://git-wip-us.apache.org/repos/asf/ignite/blob/4fe6862d/modules/web-console/frontend/generator/generator-java.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/generator/generator-java.js b/modules/web-console/frontend/generator/generator-java.js
index 250ab41..43002d3 100644
--- a/modules/web-console/frontend/generator/generator-java.js
+++ b/modules/web-console/frontend/generator/generator-java.js
@@ -1401,7 +1401,7 @@ $generatorJava.cacheMemory = function(cache, varName, res) {
 };
 
 // Generate cache query & indexing group.
-$generatorJava.cacheQuery = function(cache, varName, res) {
+$generatorJava.cacheQuery = function(cache, domains, varName, res) {
     if (!res)
         res = $generatorCommon.builder();
 
@@ -1414,6 +1414,20 @@ $generatorJava.cacheQuery = function(cache, varName, res) {
 
     res.softEmptyLine();
 
+    const indexedTypes = _.reduce(domains, (acc, domain) => {
+        if (domain.queryMetadata === 'Annotations') {
+            acc.push(domain.keyType);
+            acc.push(domain.valueType);
+        }
+
+        return acc;
+    }, []);
+
+    if (indexedTypes.length > 0)
+        $generatorJava.multiparamProperty(res, varName, {indexedTypes}, 'indexedTypes', 'class');
+
+    res.softEmptyLine();
+
     $generatorJava.multiparamProperty(res, varName, cache, 'sqlFunctionClasses', 'class');
 
     res.softEmptyLine();
@@ -2089,7 +2103,7 @@ $generatorJava.cache = function(cache, varName, res) {
 
     $generatorJava.cacheGeneral(cache, varName, res);
     $generatorJava.cacheMemory(cache, varName, res);
-    $generatorJava.cacheQuery(cache, varName, res);
+    $generatorJava.cacheQuery(cache, cache.domains, varName, res);
     $generatorJava.cacheStore(cache, cache.domains, varName, res);
 
     const igfs = _.get(cache, 'nodeFilter.IGFS.instance');

http://git-wip-us.apache.org/repos/asf/ignite/blob/4fe6862d/modules/web-console/frontend/generator/generator-xml.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/generator/generator-xml.js b/modules/web-console/frontend/generator/generator-xml.js
index acdbca0..870d13f 100644
--- a/modules/web-console/frontend/generator/generator-xml.js
+++ b/modules/web-console/frontend/generator/generator-xml.js
@@ -1142,7 +1142,7 @@ $generatorXml.cacheMemory = function(cache, res) {
 };
 
 // Generate cache query & indexing group.
-$generatorXml.cacheQuery = function(cache, res) {
+$generatorXml.cacheQuery = function(cache, domains, res) {
     if (!res)
         res = $generatorCommon.builder();
 
@@ -1150,7 +1150,7 @@ $generatorXml.cacheQuery = function(cache, res) {
     $generatorXml.property(res, cache, 'sqlOnheapRowCacheSize', null, 10240);
     $generatorXml.property(res, cache, 'longQueryWarningTimeout', null, 3000);
 
-    const indexedTypes = _.filter(cache.domains, (domain) => domain.queryMetadata === 'Annotations');
+    const indexedTypes = _.filter(domains, (domain) => domain.queryMetadata === 'Annotations');
 
     if (indexedTypes.length > 0) {
         res.startBlock('<property name="indexedTypes">');
@@ -1689,7 +1689,7 @@ $generatorXml.cacheConfiguration = function(cache, res) {
 
     $generatorXml.cacheGeneral(cache, res);
     $generatorXml.cacheMemory(cache, res);
-    $generatorXml.cacheQuery(cache, res);
+    $generatorXml.cacheQuery(cache, cache.domains, res);
     $generatorXml.cacheStore(cache, cache.domains, res);
 
     const igfs = _.get(cache, 'nodeFilter.IGFS.instance');


[44/50] [abbrv] ignite git commit: IGNITE-2047 Fixed generation of default value.

Posted by an...@apache.org.
IGNITE-2047 Fixed generation of default value.


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

Branch: refs/heads/ignite-3629
Commit: ef5f47cdae2807f09c79cd782aa6194d387ad53f
Parents: 5daf030
Author: vsisko <vs...@gridgain.com>
Authored: Tue Sep 6 11:02:35 2016 +0700
Committer: vsisko <vs...@gridgain.com>
Committed: Tue Sep 6 11:02:35 2016 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/generator/generator-java.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ef5f47cd/modules/web-console/frontend/generator/generator-java.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/generator/generator-java.js b/modules/web-console/frontend/generator/generator-java.js
index de61e04..250ab41 100644
--- a/modules/web-console/frontend/generator/generator-java.js
+++ b/modules/web-console/frontend/generator/generator-java.js
@@ -1757,7 +1757,7 @@ $generatorJava.cacheConcurrency = function(cache, varName, res) {
     $generatorJava.property(res, varName, cache, 'maxConcurrentAsyncOperations', null, null, 500);
     $generatorJava.property(res, varName, cache, 'defaultLockTimeout', null, null, 0);
     $generatorJava.enumProperty(res, varName, cache, 'atomicWriteOrderMode', 'org.apache.ignite.cache.CacheAtomicWriteOrderMode');
-    $generatorJava.enumProperty(res, varName, cache, 'writeSynchronizationMode', 'org.apache.ignite.cache.CacheWriteSynchronizationMode', null, null, 'PRIMARY_SYNC');
+    $generatorJava.enumProperty(res, varName, cache, 'writeSynchronizationMode', 'org.apache.ignite.cache.CacheWriteSynchronizationMode', null, 'PRIMARY_SYNC');
 
     res.needEmptyLine = true;
 


[29/50] [abbrv] ignite git commit: IGNITE-3620 Moved popover functions and form function in separated services.

Posted by an...@apache.org.
IGNITE-3620 Moved popover functions and form function in separated services.


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

Branch: refs/heads/ignite-3629
Commit: 27176d5901dbec5d1cef8504c07c02e2f0adbf19
Parents: f8095d7
Author: Vasiliy Sisko <vs...@gridgain.com>
Authored: Tue Aug 30 10:40:17 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Tue Aug 30 10:40:17 2016 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/app/app.js         |    4 +
 .../app/modules/form/field/label.directive.js   |    2 +-
 .../configuration/summary/summary.controller.js |    6 +-
 .../frontend/app/modules/user/Auth.service.js   |    8 +-
 .../app/services/ErrorPopover.service.js        |  126 ++
 .../frontend/app/services/FormUtils.service.js  |  435 ++++++
 .../app/services/LegacyTable.service.js         |  302 ++--
 .../app/services/LegacyUtils.service.js         | 1333 ++++++------------
 .../frontend/controllers/caches-controller.js   |   58 +-
 .../frontend/controllers/clusters-controller.js |   74 +-
 .../frontend/controllers/domains-controller.js  |   58 +-
 .../frontend/controllers/igfs-controller.js     |   34 +-
 .../frontend/generator/generator-xml.js         |    2 +-
 13 files changed, 1312 insertions(+), 1130 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/27176d59/modules/web-console/frontend/app/app.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/app.js b/modules/web-console/frontend/app/app.js
index 98a2fac..e5ea8ca 100644
--- a/modules/web-console/frontend/app/app.js
+++ b/modules/web-console/frontend/app/app.js
@@ -81,6 +81,8 @@ import JavaTypes from './services/JavaTypes.service';
 import Messages from './services/Messages.service';
 import ModelNormalizer from './services/ModelNormalizer.service.js';
 import LegacyTable from './services/LegacyTable.service';
+import ErrorPopover from './services/ErrorPopover.service';
+import FormUtils from './services/FormUtils.service';
 import LegacyUtils from './services/LegacyUtils.service';
 import UnsavedChangesGuard from './services/UnsavedChangesGuard.service';
 
@@ -203,6 +205,8 @@ angular
 .service(...Messages)
 .service(...ModelNormalizer)
 .service(...LegacyTable)
+.service('IgniteErrorPopover', ErrorPopover)
+.service(...FormUtils)
 .service(...LegacyUtils)
 .service(...UnsavedChangesGuard)
 // Controllers.

http://git-wip-us.apache.org/repos/asf/ignite/blob/27176d59/modules/web-console/frontend/app/modules/form/field/label.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/form/field/label.directive.js b/modules/web-console/frontend/app/modules/form/field/label.directive.js
index c4b11d6..97ba598 100644
--- a/modules/web-console/frontend/app/modules/form/field/label.directive.js
+++ b/modules/web-console/frontend/app/modules/form/field/label.directive.js
@@ -29,7 +29,7 @@ export default ['igniteFormFieldLabel', [() => {
 
                         const $label = $element.parent().parent().find('.group-legend > label, .ignite-field > label');
 
-                        if ($element[0].id) {
+                        if ($label[0] && $element[0].id) {
                             const id = $element[0].id;
 
                             $label[0].id = id.indexOf('+') >= 0 ? $scope.$eval(id) : id;

http://git-wip-us.apache.org/repos/asf/ignite/blob/27176d59/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js b/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js
index ac81feb..f0cb842 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js
+++ b/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js
@@ -20,8 +20,8 @@ import JSZip from 'jszip';
 import saver from 'file-saver';
 
 export default [
-    '$rootScope', '$scope', '$http', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteLoading', '$filter', 'igniteConfigurationResource', 'JavaTypes', 'IgniteVersion', 'GeneratorDocker', 'GeneratorPom',
-    function($root, $scope, $http, LegacyUtils, Messages, Loading, $filter, Resource, JavaTypes, IgniteVersion, docker, pom) {
+    '$rootScope', '$scope', '$http', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteLoading', '$filter', 'igniteConfigurationResource', 'JavaTypes', 'IgniteVersion', 'GeneratorDocker', 'GeneratorPom', 'IgniteFormUtils',
+    function($root, $scope, $http, LegacyUtils, Messages, Loading, $filter, Resource, JavaTypes, IgniteVersion, docker, pom, FormUtils) {
         const ctrl = this;
 
         $scope.ui = { ready: false };
@@ -57,7 +57,7 @@ export default [
             return !row || !row._id || _.findIndex(rows, (item) => item._id === row._id) >= 0;
         };
 
-        $scope.widthIsSufficient = LegacyUtils.widthIsSufficient;
+        $scope.widthIsSufficient = FormUtils.widthIsSufficient;
         $scope.dialects = {};
 
         $scope.projectStructureOptions = {

http://git-wip-us.apache.org/repos/asf/ignite/blob/27176d59/modules/web-console/frontend/app/modules/user/Auth.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/Auth.service.js b/modules/web-console/frontend/app/modules/user/Auth.service.js
index ddf58d0..43e2f92 100644
--- a/modules/web-console/frontend/app/modules/user/Auth.service.js
+++ b/modules/web-console/frontend/app/modules/user/Auth.service.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-export default ['Auth', ['$http', '$rootScope', '$state', '$window', 'IgniteLegacyUtils', 'IgniteMessages', 'gettingStarted', 'User', 'IgniteAgentMonitor',
-    ($http, $root, $state, $window, LegacyUtils, Messages, gettingStarted, User, agentMonitor) => {
+export default ['Auth', ['$http', '$rootScope', '$state', '$window', 'IgniteErrorPopover', 'IgniteMessages', 'gettingStarted', 'User', 'IgniteAgentMonitor',
+    ($http, $root, $state, $window, ErrorPopover, Messages, gettingStarted, User, agentMonitor) => {
         return {
             forgotPassword(userInfo) {
                 $http.post('/api/v1/password/forgot', userInfo)
                     .success(() => $state.go('password.send'))
-                    .error((err) => LegacyUtils.showPopoverMessage(null, null, 'forgot_email', Messages.errorMessage(null, err)));
+                    .error((err) => ErrorPopover.show('forgot_email', Messages.errorMessage(null, err)));
             },
             auth(action, userInfo) {
                 $http.post('/api/v1/' + action, userInfo)
@@ -41,7 +41,7 @@ export default ['Auth', ['$http', '$rootScope', '$state', '$window', 'IgniteLega
                                 $root.gettingStarted.tryShow();
                             });
                     })
-                    .catch((err) => LegacyUtils.showPopoverMessage(null, null, action + '_email', Messages.errorMessage(null, err)));
+                    .catch((err) => ErrorPopover.show(action + '_email', Messages.errorMessage(null, err)));
             },
             logout() {
                 $http.post('/api/v1/logout')

http://git-wip-us.apache.org/repos/asf/ignite/blob/27176d59/modules/web-console/frontend/app/services/ErrorPopover.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/services/ErrorPopover.service.js b/modules/web-console/frontend/app/services/ErrorPopover.service.js
new file mode 100644
index 0000000..bb2cb48
--- /dev/null
+++ b/modules/web-console/frontend/app/services/ErrorPopover.service.js
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+export default class ErrorPopover {
+    static $inject = ['$popover', '$anchorScroll', '$location', '$timeout', 'IgniteFormUtils'];
+
+    /**
+     * @param $popover
+     * @param $anchorScroll
+     * @param $location
+     * @param $timeout
+     * @param FormUtils
+     */
+    constructor($popover, $anchorScroll, $location, $timeout, FormUtils) {
+        this.$popover = $popover;
+        this.$anchorScroll = $anchorScroll;
+        this.$location = $location;
+        this.$timeout = $timeout;
+        this.FormUtils = FormUtils;
+
+        this.$anchorScroll.yOffset = 55;
+
+        this._popover = null;
+    }
+
+    /**
+     * Check that element is document area.
+     *
+     * @param el Element to check.
+     * @returns {boolean} True when element in document area.
+     */
+    static _isElementInViewport(el) {
+        const rect = el.getBoundingClientRect();
+
+        return (
+            rect.top >= 0 &&
+            rect.left >= 0 &&
+            rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
+            rect.right <= (window.innerWidth || document.documentElement.clientWidth)
+        );
+    }
+
+    /**
+     * Internal show popover message with detected properties.
+     *
+     * @param id Id element to show popover message.
+     * @param message Message to show.
+     * @param showTime Time before popover will be hidden.
+     */
+    _show(id, message, showTime = 5000) {
+        const body = $('body');
+
+        let el = body.find('#' + id);
+
+        if (!el || el.length === 0)
+            el = body.find('[name="' + id + '"]');
+
+        if (el && el.length > 0) {
+            if (!ErrorPopover._isElementInViewport(el[0])) {
+                this.$location.hash(el[0].id);
+
+                this.$anchorScroll();
+            }
+
+            const newPopover = this.$popover(el, {content: message});
+
+            this._popover = newPopover;
+
+            this.$timeout(() => newPopover.$promise.then(() => {
+                newPopover.show();
+
+                // Workaround to fix popover location when content is longer than content template.
+                // https://github.com/mgcrea/angular-strap/issues/1497
+                this.$timeout(newPopover.$applyPlacement);
+            }), 400);
+            this.$timeout(() => newPopover.hide(), showTime);
+        }
+    }
+
+    /**
+     * Show popover message.
+     *
+     * @param {String} id ID of element to show popover.
+     * @param {String} message Message to show.
+     * @param {Object} [ui] Form UI object. When specified extend section with that name.
+     * @param {String} [panelId] ID of element owner panel. When specified focus element with that ID.
+     * @param {Number} [showTime] Time before popover will be hidden. 5 sec when not specified.
+     * @returns {boolean} False always.
+     */
+    show(id, message, ui, panelId, showTime) {
+        if (this._popover)
+            this._popover.hide();
+
+        if (ui) {
+            this.FormUtils.ensureActivePanel(ui, panelId);
+
+            this.$timeout(() => this._show(id, message, showTime), ui.isPanelLoaded(panelId) ? 200 : 500);
+        }
+        else
+            this._show(id, message);
+
+        return false;
+    }
+
+    /**
+     * Hide popover message.
+     */
+    hide() {
+        if (this._popover)
+            this._popover.hide();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/27176d59/modules/web-console/frontend/app/services/FormUtils.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/services/FormUtils.service.js b/modules/web-console/frontend/app/services/FormUtils.service.js
new file mode 100644
index 0000000..5e7943a
--- /dev/null
+++ b/modules/web-console/frontend/app/services/FormUtils.service.js
@@ -0,0 +1,435 @@
+/*
+ * 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.
+ */
+
+export default ['IgniteFormUtils', ['$window', 'IgniteFocus', ($window, Focus) => {
+    function ensureActivePanel(ui, pnl, focusId) {
+        if (ui) {
+            const collapses = $('div.panel-collapse');
+
+            ui.loadPanel(pnl);
+
+            const idx = _.findIndex(collapses, function(collapse) {
+                return collapse.id === pnl;
+            });
+
+            if (idx >= 0) {
+                const activePanels = ui.activePanels;
+
+                if (!_.includes(ui.topPanels, idx)) {
+                    ui.expanded = true;
+
+                    const customExpanded = ui[pnl];
+
+                    if (customExpanded)
+                        ui[customExpanded] = true;
+                }
+
+                if (!activePanels || activePanels.length < 1)
+                    ui.activePanels = [idx];
+                else if (!_.includes(activePanels, idx)) {
+                    const newActivePanels = angular.copy(activePanels);
+
+                    newActivePanels.push(idx);
+
+                    ui.activePanels = newActivePanels;
+                }
+            }
+
+            if (!_.isNil(focusId))
+                Focus.move(focusId);
+        }
+    }
+
+    let context = null;
+
+    /**
+     * Calculate width of specified text in body's font.
+     *
+     * @param text Text to calculate width.
+     * @returns {Number} Width of text in pixels.
+     */
+    function measureText(text) {
+        if (!context) {
+            const canvas = document.createElement('canvas');
+
+            context = canvas.getContext('2d');
+
+            const style = window.getComputedStyle(document.getElementsByTagName('body')[0]);
+
+            context.font = style.fontSize + ' ' + style.fontFamily;
+        }
+
+        return context.measureText(text).width;
+    }
+
+    /**
+     * Compact java full class name by max number of characters.
+     *
+     * @param names Array of class names to compact.
+     * @param nameLength Max available width in characters for simple name.
+     * @returns {*} Array of compacted class names.
+     */
+    function compactByMaxCharts(names, nameLength) {
+        for (let nameIx = 0; nameIx < names.length; nameIx++) {
+            const s = names[nameIx];
+
+            if (s.length > nameLength) {
+                let totalLength = s.length;
+
+                const packages = s.split('.');
+
+                const packageCnt = packages.length - 1;
+
+                for (let i = 0; i < packageCnt && totalLength > nameLength; i++) {
+                    if (packages[i].length > 0) {
+                        totalLength -= packages[i].length - 1;
+
+                        packages[i] = packages[i][0];
+                    }
+                }
+
+                if (totalLength > nameLength) {
+                    const className = packages[packageCnt];
+
+                    const classNameLen = className.length;
+
+                    let remains = Math.min(nameLength - totalLength + classNameLen, classNameLen);
+
+                    if (remains < 3)
+                        remains = Math.min(3, classNameLen);
+
+                    packages[packageCnt] = className.substring(0, remains) + '...';
+                }
+
+                let result = packages[0];
+
+                for (let i = 1; i < packages.length; i++)
+                    result += '.' + packages[i];
+
+                names[nameIx] = result;
+            }
+        }
+
+        return names;
+    }
+
+    /**
+     * Compact java full class name by max number of pixels.
+     *
+     * @param names Array of class names to compact.
+     * @param nameLength Max available width in characters for simple name. Used for calculation optimization.
+     * @param nameWidth Maximum available width in pixels for simple name.
+     * @returns {*} Array of compacted class names.
+     */
+    function compactByMaxPixels(names, nameLength, nameWidth) {
+        if (nameWidth <= 0)
+            return names;
+
+        const fitted = [];
+
+        const widthByName = [];
+
+        const len = names.length;
+
+        let divideTo = len;
+
+        for (let nameIx = 0; nameIx < len; nameIx++) {
+            fitted[nameIx] = false;
+
+            widthByName[nameIx] = nameWidth;
+        }
+
+        // Try to distribute space from short class names to long class names.
+        let remains = 0;
+
+        do {
+            for (let nameIx = 0; nameIx < len; nameIx++) {
+                if (!fitted[nameIx]) {
+                    const curNameWidth = measureText(names[nameIx]);
+
+                    if (widthByName[nameIx] > curNameWidth) {
+                        fitted[nameIx] = true;
+
+                        remains += widthByName[nameIx] - curNameWidth;
+
+                        divideTo -= 1;
+
+                        widthByName[nameIx] = curNameWidth;
+                    }
+                }
+            }
+
+            const remainsByName = remains / divideTo;
+
+            for (let nameIx = 0; nameIx < len; nameIx++) {
+                if (!fitted[nameIx])
+                    widthByName[nameIx] += remainsByName;
+            }
+        }
+        while (remains > 0);
+
+        // Compact class names to available for each space.
+        for (let nameIx = 0; nameIx < len; nameIx++) {
+            const s = names[nameIx];
+
+            if (s.length > (nameLength / 2 | 0)) {
+                let totalWidth = measureText(s);
+
+                if (totalWidth > widthByName[nameIx]) {
+                    const packages = s.split('.');
+
+                    const packageCnt = packages.length - 1;
+
+                    for (let i = 0; i < packageCnt && totalWidth > widthByName[nameIx]; i++) {
+                        if (packages[i].length > 1) {
+                            totalWidth -= measureText(packages[i].substring(1, packages[i].length));
+
+                            packages[i] = packages[i][0];
+                        }
+                    }
+
+                    let shortPackage = '';
+
+                    for (let i = 0; i < packageCnt; i++)
+                        shortPackage += packages[i] + '.';
+
+                    const className = packages[packageCnt];
+
+                    const classLen = className.length;
+
+                    let minLen = Math.min(classLen, 3);
+
+                    totalWidth = measureText(shortPackage + className);
+
+                    // Compact class name if shorten package path is very long.
+                    if (totalWidth > widthByName[nameIx]) {
+                        let maxLen = classLen;
+                        let middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
+
+                        while (middleLen !== minLen && middleLen !== maxLen) {
+                            const middleLenPx = measureText(shortPackage + className.substr(0, middleLen) + '...');
+
+                            if (middleLenPx > widthByName[nameIx])
+                                maxLen = middleLen;
+                            else
+                                minLen = middleLen;
+
+                            middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
+                        }
+
+                        names[nameIx] = shortPackage + className.substring(0, middleLen) + '...';
+                    }
+                    else
+                        names[nameIx] = shortPackage + className;
+                }
+            }
+        }
+
+        return names;
+    }
+
+    /**
+     * Compact any string by max number of pixels.
+     *
+     * @param label String to compact.
+     * @param nameWidth Maximum available width in pixels for simple name.
+     * @returns {*} Compacted string.
+     */
+    function compactLabelByPixels(label, nameWidth) {
+        if (nameWidth <= 0)
+            return label;
+
+        const totalWidth = measureText(label);
+
+        if (totalWidth > nameWidth) {
+            let maxLen = label.length;
+            let minLen = Math.min(maxLen, 3);
+            let middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
+
+            while (middleLen !== minLen && middleLen !== maxLen) {
+                const middleLenPx = measureText(label.substr(0, middleLen) + '...');
+
+                if (middleLenPx > nameWidth)
+                    maxLen = middleLen;
+                else
+                    minLen = middleLen;
+
+                middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
+            }
+
+            return label.substring(0, middleLen) + '...';
+        }
+
+        return label;
+    }
+
+    /**
+     * Calculate available width for text in link to edit element.
+     *
+     * @param index Showed index of element for calculation of maximum width in pixels.
+     * @param id Id of contains link table.
+     * @returns {*[]} First element is length of class for single value, second element is length for pair vlaue.
+     */
+    function availableWidth(index, id) {
+        const idElem = $('#' + id);
+
+        let width = 0;
+
+        switch (idElem.prop('tagName')) {
+            // Detection of available width in presentation table row.
+            case 'TABLE':
+                const cont = $(idElem.find('tr')[index - 1]).find('td')[0];
+
+                width = cont.clientWidth;
+
+                if (width > 0) {
+                    const children = $(cont).children(':not("a")');
+
+                    _.forEach(children, function(child) {
+                        if ('offsetWidth' in child)
+                            width -= $(child).outerWidth(true);
+                    });
+                }
+
+                break;
+
+            // Detection of available width in dropdown row.
+            case 'A':
+                width = idElem.width();
+
+                $(idElem).children(':not("span")').each(function(ix, child) {
+                    if ('offsetWidth' in child)
+                        width -= child.offsetWidth;
+                });
+
+                break;
+
+            default:
+        }
+
+        return width | 0;
+    }
+
+    return {
+        /**
+         * Cut class name by width in pixel or width in symbol count.
+         *
+         * @param id Id of parent table.
+         * @param index Row number in table.
+         * @param maxLength Maximum length in symbols for all names.
+         * @param names Array of class names to compact.
+         * @param divider String to visualy divide items.
+         * @returns {*} Array of compacted class names.
+         */
+        compactJavaName(id, index, maxLength, names, divider) {
+            divider = ' ' + divider + ' ';
+
+            const prefix = index + ') ';
+
+            const nameCnt = names.length;
+
+            const nameLength = ((maxLength - 3 * (nameCnt - 1)) / nameCnt) | 0;
+
+            try {
+                const nameWidth = (availableWidth(index, id) - measureText(prefix) - (nameCnt - 1) * measureText(divider)) /
+                    nameCnt | 0;
+
+                // HTML5 calculation of showed message width.
+                names = compactByMaxPixels(names, nameLength, nameWidth);
+            }
+            catch (err) {
+                names = compactByMaxCharts(names, nameLength);
+            }
+
+            let result = prefix + names[0];
+
+            for (let nameIx = 1; nameIx < names.length; nameIx++)
+                result += divider + names[nameIx];
+
+            return result;
+        },
+        /**
+         * Compact text by width in pixels or symbols count.
+         *
+         * @param id Id of parent table.
+         * @param index Row number in table.
+         * @param maxLength Maximum length in symbols for all names.
+         * @param label Text to compact.
+         * @returns Compacted label text.
+         */
+        compactTableLabel(id, index, maxLength, label) {
+            label = index + ') ' + label;
+
+            try {
+                const nameWidth = availableWidth(index, id) | 0;
+
+                // HTML5 calculation of showed message width.
+                label = compactLabelByPixels(label, nameWidth);
+            }
+            catch (err) {
+                const nameLength = maxLength - 3 | 0;
+
+                label = label.length > maxLength ? label.substr(0, nameLength) + '...' : label;
+            }
+
+            return label;
+        },
+        widthIsSufficient(id, index, text) {
+            try {
+                const available = availableWidth(index, id);
+
+                const required = measureText(text);
+
+                return !available || available >= Math.floor(required);
+            }
+            catch (err) {
+                return true;
+            }
+        },
+        ensureActivePanel(panels, id, focusId) {
+            ensureActivePanel(panels, id, focusId);
+        },
+        confirmUnsavedChanges(dirty, selectFunc) {
+            if (dirty) {
+                if ($window.confirm('You have unsaved changes.\n\nAre you sure you want to discard them?'))
+                    selectFunc();
+            }
+            else
+                selectFunc();
+        },
+        saveBtnTipText(dirty, objectName) {
+            if (dirty)
+                return 'Save ' + objectName;
+
+            return 'Nothing to save';
+        },
+        formUI() {
+            return {
+                ready: false,
+                expanded: false,
+                loadedPanels: [],
+                loadPanel(pnl) {
+                    if (!_.includes(this.loadedPanels, pnl))
+                        this.loadedPanels.push(pnl);
+                },
+                isPanelLoaded(pnl) {
+                    return _.includes(this.loadedPanels, pnl);
+                }
+            };
+        }
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/27176d59/modules/web-console/frontend/app/services/LegacyTable.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/services/LegacyTable.service.js b/modules/web-console/frontend/app/services/LegacyTable.service.js
index 8f3b791..89f4345 100644
--- a/modules/web-console/frontend/app/services/LegacyTable.service.js
+++ b/modules/web-console/frontend/app/services/LegacyTable.service.js
@@ -16,190 +16,194 @@
  */
 
 // TODO: Refactor this service for legacy tables with more than one input field.
-export default ['IgniteLegacyTable', ['IgniteLegacyUtils', 'IgniteFocus', (LegacyUtils, Focus) => {
-    function _model(item, field) {
-        return LegacyUtils.getModel(item, field);
-    }
-
-    const table = {name: 'none', editIndex: -1};
-
-    function _tableReset() {
-        delete table.field;
-        table.name = 'none';
-        table.editIndex = -1;
-
-        LegacyUtils.hidePopover();
-    }
-
-    function _tableSaveAndReset() {
-        const field = table.field;
-
-        const save = LegacyUtils.isDefined(field) && LegacyUtils.isDefined(field.save);
-
-        if (!save || !LegacyUtils.isDefined(field) || field.save(field, table.editIndex, true)) {
-            _tableReset();
-
-            return true;
+export default ['IgniteLegacyTable',
+    ['IgniteLegacyUtils', 'IgniteFocus', 'IgniteErrorPopover', (LegacyUtils, Focus, ErrorPopover) => {
+        function _model(item, field) {
+            return LegacyUtils.getModel(item, field);
         }
 
-        return false;
-    }
+        const table = {name: 'none', editIndex: -1};
 
-    function _tableState(field, editIndex, specName) {
-        table.field = field;
-        table.name = specName || field.model;
-        table.editIndex = editIndex;
-    }
+        function _tableReset() {
+            delete table.field;
+            table.name = 'none';
+            table.editIndex = -1;
 
-    function _tableUI(field) {
-        const ui = field.ui;
-
-        return ui ? ui : field.type;
-    }
+            ErrorPopover.hide();
+        }
 
-    function _tableFocus(focusId, index) {
-        Focus.move((index < 0 ? 'new' : 'cur') + focusId + (index >= 0 ? index : ''));
-    }
+        function _tableSaveAndReset() {
+            const field = table.field;
 
-    function _tablePairValue(filed, index) {
-        return index < 0 ? {key: filed.newKey, value: filed.newValue} : {key: filed.curKey, value: filed.curValue};
-    }
+            const save = LegacyUtils.isDefined(field) && LegacyUtils.isDefined(field.save);
 
-    function _tableStartEdit(item, tbl, index, save) {
-        _tableState(tbl, index);
+            if (!save || !LegacyUtils.isDefined(field) || field.save(field, table.editIndex, true)) {
+                _tableReset();
 
-        const val = _.get(_model(item, tbl), tbl.model)[index];
+                return true;
+            }
 
-        const ui = _tableUI(tbl);
+            return false;
+        }
 
-        tbl.save = save;
+        function _tableState(field, editIndex, specName) {
+            table.field = field;
+            table.name = specName || field.model;
+            table.editIndex = editIndex;
+        }
 
-        if (ui === 'table-pair') {
-            tbl.curKey = val[tbl.keyName];
-            tbl.curValue = val[tbl.valueName];
+        function _tableUI(field) {
+            const ui = field.ui;
 
-            _tableFocus('Key' + tbl.focusId, index);
+            return ui ? ui : field.type;
         }
-        else if (ui === 'table-db-fields') {
-            tbl.curDatabaseFieldName = val.databaseFieldName;
-            tbl.curDatabaseFieldType = val.databaseFieldType;
-            tbl.curJavaFieldName = val.javaFieldName;
-            tbl.curJavaFieldType = val.javaFieldType;
 
-            _tableFocus('DatabaseFieldName' + tbl.focusId, index);
+        function _tableFocus(focusId, index) {
+            Focus.move((index < 0 ? 'new' : 'cur') + focusId + (index >= 0 ? index : ''));
         }
-        else if (ui === 'table-indexes') {
-            tbl.curIndexName = val.name;
-            tbl.curIndexType = val.indexType;
-            tbl.curIndexFields = val.fields;
 
-            _tableFocus(tbl.focusId, index);
+        function _tablePairValue(filed, index) {
+            return index < 0 ? {key: filed.newKey, value: filed.newValue} : {
+                key: filed.curKey,
+                value: filed.curValue
+            };
         }
-    }
 
-    function _tableNewItem(tbl) {
-        _tableState(tbl, -1);
+        function _tableStartEdit(item, tbl, index, save) {
+            _tableState(tbl, index);
 
-        const ui = _tableUI(tbl);
+            const val = _.get(_model(item, tbl), tbl.model)[index];
 
-        if (ui === 'table-pair') {
-            tbl.newKey = null;
-            tbl.newValue = null;
+            const ui = _tableUI(tbl);
 
-            _tableFocus('Key' + tbl.focusId, -1);
-        }
-        else if (ui === 'table-db-fields') {
-            tbl.newDatabaseFieldName = null;
-            tbl.newDatabaseFieldType = null;
-            tbl.newJavaFieldName = null;
-            tbl.newJavaFieldType = null;
+            tbl.save = save;
 
-            _tableFocus('DatabaseFieldName' + tbl.focusId, -1);
-        }
-        else if (ui === 'table-indexes') {
-            tbl.newIndexName = null;
-            tbl.newIndexType = 'SORTED';
-            tbl.newIndexFields = null;
+            if (ui === 'table-pair') {
+                tbl.curKey = val[tbl.keyName];
+                tbl.curValue = val[tbl.valueName];
+
+                _tableFocus('Key' + tbl.focusId, index);
+            }
+            else if (ui === 'table-db-fields') {
+                tbl.curDatabaseFieldName = val.databaseFieldName;
+                tbl.curDatabaseFieldType = val.databaseFieldType;
+                tbl.curJavaFieldName = val.javaFieldName;
+                tbl.curJavaFieldType = val.javaFieldType;
 
-            _tableFocus(tbl.focusId, -1);
+                _tableFocus('DatabaseFieldName' + tbl.focusId, index);
+            }
+            else if (ui === 'table-indexes') {
+                tbl.curIndexName = val.name;
+                tbl.curIndexType = val.indexType;
+                tbl.curIndexFields = val.fields;
+
+                _tableFocus(tbl.focusId, index);
+            }
         }
-    }
-
-    return {
-        tableState: _tableState,
-        tableReset: _tableReset,
-        tableSaveAndReset: _tableSaveAndReset,
-        tableNewItem: _tableNewItem,
-        tableNewItemActive(tbl) {
-            return table.name === tbl.model && table.editIndex < 0;
-        },
-        tableEditing(tbl, index) {
-            return table.name === tbl.model && table.editIndex === index;
-        },
-        tableEditedRowIndex() {
-            return table.editIndex;
-        },
-        tableField() {
-            return table.field;
-        },
-        tableStartEdit: _tableStartEdit,
-        tableRemove(item, field, index) {
-            _tableReset();
-
-            _.get(_model(item, field), field.model).splice(index, 1);
-        },
-        tablePairValue: _tablePairValue,
-        tablePairSave(pairValid, item, field, index, stopEdit) {
-            const valid = pairValid(item, field, index);
-
-            if (valid) {
-                const pairValue = _tablePairValue(field, index);
 
-                let pairModel = {};
+        function _tableNewItem(tbl) {
+            _tableState(tbl, -1);
 
-                const container = _.get(item, field.model);
+            const ui = _tableUI(tbl);
 
-                if (index < 0) {
-                    pairModel[field.keyName] = pairValue.key;
-                    pairModel[field.valueName] = pairValue.value;
+            if (ui === 'table-pair') {
+                tbl.newKey = null;
+                tbl.newValue = null;
 
-                    if (container)
-                        container.push(pairModel);
-                    else
-                        _.set(item, field.model, [pairModel]);
+                _tableFocus('Key' + tbl.focusId, -1);
+            }
+            else if (ui === 'table-db-fields') {
+                tbl.newDatabaseFieldName = null;
+                tbl.newDatabaseFieldType = null;
+                tbl.newJavaFieldName = null;
+                tbl.newJavaFieldType = null;
 
-                    if (!stopEdit)
-                        _tableNewItem(field);
-                }
-                else {
-                    pairModel = container[index];
+                _tableFocus('DatabaseFieldName' + tbl.focusId, -1);
+            }
+            else if (ui === 'table-indexes') {
+                tbl.newIndexName = null;
+                tbl.newIndexType = 'SORTED';
+                tbl.newIndexFields = null;
 
-                    pairModel[field.keyName] = pairValue.key;
-                    pairModel[field.valueName] = pairValue.value;
+                _tableFocus(tbl.focusId, -1);
+            }
+        }
 
-                    if (!stopEdit) {
-                        if (index < container.length - 1)
-                            _tableStartEdit(item, field, index + 1);
+        return {
+            tableState: _tableState,
+            tableReset: _tableReset,
+            tableSaveAndReset: _tableSaveAndReset,
+            tableNewItem: _tableNewItem,
+            tableNewItemActive(tbl) {
+                return table.name === tbl.model && table.editIndex < 0;
+            },
+            tableEditing(tbl, index) {
+                return table.name === tbl.model && table.editIndex === index;
+            },
+            tableEditedRowIndex() {
+                return table.editIndex;
+            },
+            tableField() {
+                return table.field;
+            },
+            tableStartEdit: _tableStartEdit,
+            tableRemove(item, field, index) {
+                _tableReset();
+
+                _.get(_model(item, field), field.model).splice(index, 1);
+            },
+            tablePairValue: _tablePairValue,
+            tablePairSave(pairValid, item, field, index, stopEdit) {
+                const valid = pairValid(item, field, index);
+
+                if (valid) {
+                    const pairValue = _tablePairValue(field, index);
+
+                    let pairModel = {};
+
+                    const container = _.get(item, field.model);
+
+                    if (index < 0) {
+                        pairModel[field.keyName] = pairValue.key;
+                        pairModel[field.valueName] = pairValue.value;
+
+                        if (container)
+                            container.push(pairModel);
                         else
+                            _.set(item, field.model, [pairModel]);
+
+                        if (!stopEdit)
                             _tableNewItem(field);
                     }
+                    else {
+                        pairModel = container[index];
+
+                        pairModel[field.keyName] = pairValue.key;
+                        pairModel[field.valueName] = pairValue.value;
+
+                        if (!stopEdit) {
+                            if (index < container.length - 1)
+                                _tableStartEdit(item, field, index + 1);
+                            else
+                                _tableNewItem(field);
+                        }
+                    }
                 }
-            }
 
-            return valid;
-        },
-        tablePairSaveVisible(field, index) {
-            const pairValue = _tablePairValue(field, index);
+                return valid;
+            },
+            tablePairSaveVisible(field, index) {
+                const pairValue = _tablePairValue(field, index);
 
-            return !LegacyUtils.isEmptyString(pairValue.key) && !LegacyUtils.isEmptyString(pairValue.value);
-        },
-        tableFocusInvalidField(index, id) {
-            _tableFocus(id, index);
+                return !LegacyUtils.isEmptyString(pairValue.key) && !LegacyUtils.isEmptyString(pairValue.value);
+            },
+            tableFocusInvalidField(index, id) {
+                _tableFocus(id, index);
 
-            return false;
-        },
-        tableFieldId(index, id) {
-            return (index < 0 ? 'new' : 'cur') + id + (index >= 0 ? index : '');
-        }
-    };
-}]];
+                return false;
+            },
+            tableFieldId(index, id) {
+                return (index < 0 ? 'new' : 'cur') + id + (index >= 0 ? index : '');
+            }
+        };
+    }]];


[09/50] [abbrv] ignite git commit: IGNITE-3725 Fixed deselect all schema in import model dialog.

Posted by an...@apache.org.
IGNITE-3725 Fixed deselect all schema in import model dialog.


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

Branch: refs/heads/ignite-3629
Commit: 5b69ace924a1b726a2730a906b963a2334d5ecad
Parents: 41f1ae9
Author: Andrey Novikov <an...@apache.org>
Authored: Wed Aug 24 16:02:59 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Wed Aug 24 16:02:59 2016 +0700

----------------------------------------------------------------------
 .../web-console/src/main/js/controllers/domains-controller.js    | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/5b69ace9/modules/web-console/src/main/js/controllers/domains-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/controllers/domains-controller.js b/modules/web-console/src/main/js/controllers/domains-controller.js
index cfb539d..214d1885 100644
--- a/modules/web-console/src/main/js/controllers/domains-controller.js
+++ b/modules/web-console/src/main/js/controllers/domains-controller.js
@@ -325,7 +325,9 @@ export default ['domainsController', [
         $scope.selectAllSchemas = function() {
             const allSelected = $scope.importDomain.allSchemasSelected;
 
-            _.forEach($scope.importDomain.displayedSchemas, (schema) => schema.use = allSelected);
+            _.forEach($scope.importDomain.displayedSchemas, (schema) => {
+                schema.use = allSelected;
+            });
         };
 
         $scope.selectSchema = function() {


[48/50] [abbrv] ignite git commit: Fixed package name after refresh.

Posted by an...@apache.org.
Fixed package name after refresh.


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

Branch: refs/heads/ignite-3629
Commit: 2b8bdb78ca8e2dbdba3c154895057e1fb3b22496
Parents: 594f064
Author: Andrey Novikov <an...@apache.org>
Authored: Tue Sep 6 15:12:53 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Tue Sep 6 15:12:53 2016 +0700

----------------------------------------------------------------------
 .../web-console/frontend/controllers/domains-controller.js  | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/2b8bdb78/modules/web-console/frontend/controllers/domains-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/domains-controller.js b/modules/web-console/frontend/controllers/domains-controller.js
index c1f6c91..143b57b 100644
--- a/modules/web-console/frontend/controllers/domains-controller.js
+++ b/modules/web-console/frontend/controllers/domains-controller.js
@@ -47,8 +47,13 @@ export default ['domainsController', [
             return name ? name.replace(/[^A-Za-z_0-9/.]+/g, '_') : 'org';
         };
 
-        $scope.ui.packageNameUserInput = $scope.ui.packageName =
-            _toJavaPackage($root.user.email.replace('@', '.').split('.').reverse().join('.') + '.model');
+        $root.$on('user', (event, user) => {
+            if ($scope.ui.packageName)
+                $scope.ui.packageNameUserInput = $scope.ui.packageName;
+
+            $scope.ui.packageName = _toJavaPackage(user.email.replace('@', '.').split('.').reverse().join('.') + '.model');
+        });
+
         $scope.ui.builtinKeys = true;
         $scope.ui.usePrimitives = true;
         $scope.ui.generateAliases = true;


[16/50] [abbrv] ignite git commit: IGNITE-2388 Fixed state transition problems. Minior UI fixes.

Posted by an...@apache.org.
IGNITE-2388 Fixed state transition problems. Minior UI fixes.


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

Branch: refs/heads/ignite-3629
Commit: c716d598343700dbcabdfb752ad223a1a9e08799
Parents: 1640e66
Author: Maxim Afanasiev <ma...@gridgain.com>
Authored: Fri Aug 26 10:07:37 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Fri Aug 26 10:07:37 2016 +0700

----------------------------------------------------------------------
 .../backend/errors/AuthFailedException.js       | 30 ++++++++++++++++++++
 .../backend/errors/MissingResourceException.js  | 30 ++++++++++++++++++++
 .../backend/errors/NotFoundException.js         | 29 -------------------
 modules/web-console/backend/errors/index.js     | 18 ++++++++----
 modules/web-console/backend/routes/demo.js      |  2 +-
 modules/web-console/backend/services/agents.js  |  2 +-
 modules/web-console/backend/services/spaces.js  |  2 +-
 modules/web-console/backend/services/users.js   |  2 +-
 modules/web-console/frontend/app/app.js         |  1 -
 .../app/modules/branding/header-logo.jade       |  2 +-
 .../frontend/app/modules/states/errors.state.js | 10 +++++--
 .../frontend/app/modules/states/signin.state.js |  5 ++--
 .../frontend/app/modules/user/User.service.js   | 28 +++++++++++-------
 .../frontend/app/modules/user/permissions.js    |  4 +--
 .../public/stylesheets/blocks/error.scss        |  2 +-
 modules/web-console/frontend/views/403.jade     | 12 ++------
 modules/web-console/frontend/views/404.jade     | 10 +------
 17 files changed, 112 insertions(+), 77 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/backend/errors/AuthFailedException.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/errors/AuthFailedException.js b/modules/web-console/backend/errors/AuthFailedException.js
new file mode 100644
index 0000000..3208e1d
--- /dev/null
+++ b/modules/web-console/backend/errors/AuthFailedException.js
@@ -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.
+ */
+
+'use strict';
+
+import AppErrorException from './AppErrorException';
+
+class AuthFailedException extends AppErrorException {
+    constructor(message) {
+        super(message);
+
+        this.httpCode = 401;
+    }
+}
+
+module.exports = AuthFailedException;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/backend/errors/MissingResourceException.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/errors/MissingResourceException.js b/modules/web-console/backend/errors/MissingResourceException.js
new file mode 100644
index 0000000..799775b
--- /dev/null
+++ b/modules/web-console/backend/errors/MissingResourceException.js
@@ -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.
+ */
+
+'use strict';
+
+import AppErrorException from './AppErrorException';
+
+class MissingResourceException extends AppErrorException {
+    constructor(message) {
+        super(message);
+
+        this.httpCode = 404;
+    }
+}
+
+module.exports = MissingResourceException;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/backend/errors/NotFoundException.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/errors/NotFoundException.js b/modules/web-console/backend/errors/NotFoundException.js
deleted file mode 100644
index 2e0fdd6..0000000
--- a/modules/web-console/backend/errors/NotFoundException.js
+++ /dev/null
@@ -1,29 +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.
- */
-
-'use strict';
-
-import AppErrorException from './AppErrorException';
-
-class NotFoundException extends AppErrorException {
-    constructor(message) {
-        super(message);
-        this.httpCode = 404;
-    }
-}
-
-module.exports = NotFoundException;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/backend/errors/index.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/errors/index.js b/modules/web-console/backend/errors/index.js
index 011883a..0af5cd5 100644
--- a/modules/web-console/backend/errors/index.js
+++ b/modules/web-console/backend/errors/index.js
@@ -19,13 +19,21 @@
 
 // Fire me up!
 
+import AppErrorException from './AppErrorException';
+import IllegalArgumentException from './IllegalArgumentException';
+import DuplicateKeyException from './DuplicateKeyException';
+import ServerErrorException from './ServerErrorException';
+import MissingResourceException from './MissingResourceException';
+import AuthFailedException from './AuthFailedException';
+
 module.exports = {
     implements: 'errors',
     factory: () => ({
-        AppErrorException: require('./AppErrorException'),
-        IllegalArgumentException: require('./IllegalArgumentException'),
-        DuplicateKeyException: require('./DuplicateKeyException'),
-        ServerErrorException: require('./ServerErrorException'),
-        NotFoundException: require('./NotFoundException')
+        AppErrorException,
+        IllegalArgumentException,
+        DuplicateKeyException,
+        ServerErrorException,
+        MissingResourceException,
+        AuthFailedException
     })
 };

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/backend/routes/demo.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/routes/demo.js b/modules/web-console/backend/routes/demo.js
index 0b611f8..724b5c1 100644
--- a/modules/web-console/backend/routes/demo.js
+++ b/modules/web-console/backend/routes/demo.js
@@ -51,7 +51,7 @@ module.exports.factory = (_, express, settings, mongo, spacesService, errors) =>
                     }
                 })
                 .catch((err) => {
-                    if (err instanceof errors.NotFoundException)
+                    if (err instanceof errors.MissingResourceException)
                         return spacesService.createDemoSpace(req.user._id);
                 })
                 .then((space) => {

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/backend/services/agents.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/services/agents.js b/modules/web-console/backend/services/agents.js
index b4d160b..8a65739 100644
--- a/modules/web-console/backend/services/agents.js
+++ b/modules/web-console/backend/services/agents.js
@@ -44,7 +44,7 @@ module.exports.factory = (_, fs, path, JSZip, settings, agentMgr, errors) => {
             const latest = agentMgr.supportedAgents.latest;
 
             if (_.isEmpty(latest))
-                throw new errors.NotFoundException('Missing agent zip on server. Please ask webmaster to upload agent zip!');
+                throw new errors.MissingResourceException('Missing agent zip on server. Please ask webmaster to upload agent zip!');
 
             const filePath = latest.filePath;
             const fileName = latest.fileName;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/backend/services/spaces.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/services/spaces.js b/modules/web-console/backend/services/spaces.js
index 2b469e0..863d57c 100644
--- a/modules/web-console/backend/services/spaces.js
+++ b/modules/web-console/backend/services/spaces.js
@@ -42,7 +42,7 @@ module.exports.factory = (mongo, errors) => {
             return mongo.Space.find({owner: userId, demo: !!demo}).lean().exec()
                 .then((spaces) => {
                     if (!spaces.length)
-                        throw new errors.NotFoundException('Failed to find space');
+                        throw new errors.MissingResourceException('Failed to find space');
 
                     return spaces;
                 });

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/backend/services/users.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/services/users.js b/modules/web-console/backend/services/users.js
index 76dbe62..8058b25 100644
--- a/modules/web-console/backend/services/users.js
+++ b/modules/web-console/backend/services/users.js
@@ -203,7 +203,7 @@ module.exports.factory = (_, mongo, settings, spacesService, mailsService, agent
          */
         static get(user, viewedUser) {
             if (_.isNil(user))
-                return Promise.reject('The user profile service failed the sign in. User profile cannot be loaded.');
+                return Promise.reject(new errors.AuthFailedException('The user profile service failed the sign in. User profile cannot be loaded.'));
 
             const becomeUsed = viewedUser && user.admin;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/frontend/app/app.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/app.js b/modules/web-console/frontend/app/app.js
index 549081f..7ac1802 100644
--- a/modules/web-console/frontend/app/app.js
+++ b/modules/web-console/frontend/app/app.js
@@ -269,4 +269,3 @@ angular
         };
     }
 ]);
-

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/frontend/app/modules/branding/header-logo.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/branding/header-logo.jade b/modules/web-console/frontend/app/modules/branding/header-logo.jade
index b807921..b58f670 100644
--- a/modules/web-console/frontend/app/modules/branding/header-logo.jade
+++ b/modules/web-console/frontend/app/modules/branding/header-logo.jade
@@ -14,5 +14,5 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 
-a(href='/')
+a(ui-sref='signin')
     img.navbar-brand(ng-src='{{logo.url}}' height='40')

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/frontend/app/modules/states/errors.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/errors.state.js b/modules/web-console/frontend/app/modules/states/errors.state.js
index df31f57..2bdb80a 100644
--- a/modules/web-console/frontend/app/modules/states/errors.state.js
+++ b/modules/web-console/frontend/app/modules/states/errors.state.js
@@ -28,10 +28,16 @@ angular
         $stateProvider
             .state('404', {
                 url: '/404',
-                templateUrl: templateNotFoundPage
+                templateUrl: templateNotFoundPage,
+                metaTags: {
+                    title: 'Page not found'
+                }
             })
             .state('403', {
                 url: '/403',
-                templateUrl: templateNotAuthorizedPage
+                templateUrl: templateNotAuthorizedPage,
+                metaTags: {
+                    title: 'Not authorized'
+                }
             });
     }]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/frontend/app/modules/states/signin.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/signin.state.js b/modules/web-console/frontend/app/modules/states/signin.state.js
index 42175cf..aaae286 100644
--- a/modules/web-console/frontend/app/modules/states/signin.state.js
+++ b/modules/web-console/frontend/app/modules/states/signin.state.js
@@ -32,9 +32,8 @@ angular
         templateUrl,
         onEnter: ['$state', 'Auth', 'AclService', ($state, Auth, AclService) => {
             if (Auth.authorized)
-                $state.go('base.configuration.clusters');
-
-            if (!AclService.can('login'))
+                $state.go('base.configuration.clusters', {}, {reload: true});
+            else if (!AclService.can('login'))
                 $state.go('403');
         }],
         metaTags: {

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/frontend/app/modules/user/User.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/User.service.js b/modules/web-console/frontend/app/modules/user/User.service.js
index faf9282..4812b54 100644
--- a/modules/web-console/frontend/app/modules/user/User.service.js
+++ b/modules/web-console/frontend/app/modules/user/User.service.js
@@ -30,18 +30,21 @@ export default ['User', ['$q', '$injector', '$rootScope', '$state', '$http', fun
 
     return {
         read() {
-            return $http.post('/api/v1/user')
-                .then(({data}) => {
-                    if (_.isEmpty(data)) {
-                        const Auth = $injector.get('Auth');
+            const dropSessionAndSignin = () => {
+                const Auth = $injector.get('Auth');
 
-                        Auth.authorized = false;
+                Auth.authorized = false;
 
-                        this.clean();
+                this.clean();
 
-                        if ($state.current.name !== 'signin')
-                            $state.go('signin');
-                    }
+                if ($state.current.name !== 'signin')
+                    $state.go('signin');
+            };
+
+            return $http.post('/api/v1/user')
+                .then(({data}) => {
+                    if (_.isEmpty(data))
+                        return dropSessionAndSignin();
 
                     try {
                         localStorage.user = JSON.stringify(data);
@@ -52,7 +55,12 @@ export default ['User', ['$q', '$injector', '$rootScope', '$state', '$http', fun
 
                     return _user = $root.user = data;
                 })
-                .catch(({data}) => Promise.reject(data));
+                .catch(({data, status}) => {
+                    if (status === 401)
+                        dropSessionAndSignin();
+
+                    return Promise.reject(data);
+                });
         },
         clean() {
             delete $root.user;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/frontend/app/modules/user/permissions.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/permissions.js b/modules/web-console/frontend/app/modules/user/permissions.js
index ef10884..e13509c 100644
--- a/modules/web-console/frontend/app/modules/user/permissions.js
+++ b/modules/web-console/frontend/app/modules/user/permissions.js
@@ -15,8 +15,8 @@
  * limitations under the License.
  */
 
-const guest = ['login', 'terms'];
-const becomed = ['profile', 'configuration', 'query', 'terms'];
+const guest = ['login'];
+const becomed = ['profile', 'configuration', 'query'];
 const user = becomed.concat(['logout']);
 const admin = user.concat(['admin_page']);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/frontend/public/stylesheets/blocks/error.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/stylesheets/blocks/error.scss b/modules/web-console/frontend/public/stylesheets/blocks/error.scss
index 20f83a8..4e16989 100644
--- a/modules/web-console/frontend/public/stylesheets/blocks/error.scss
+++ b/modules/web-console/frontend/public/stylesheets/blocks/error.scss
@@ -20,7 +20,7 @@
     min-height: 300px;
 
     &__title {
-        margin-top: 100px;
+        margin-top: 150px;
         font-weight: 200;
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/frontend/views/403.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/403.jade b/modules/web-console/frontend/views/403.jade
index 1a1cc04..38d8bb5 100644
--- a/modules/web-console/frontend/views/403.jade
+++ b/modules/web-console/frontend/views/403.jade
@@ -14,17 +14,9 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 
-header#header.header
-    table.container
-        tr
-            td.col-xs-3.col-sm-3.col-md-2
-                ignite-header-logo
-            td
-                ignite-header-title
+include includes/header
 
 .error-page
     .container
         h1.error-page__title 403
-        h2.error-page__description You not authorized
-
-include includes/footer
+        h2.error-page__description You are not authorized

http://git-wip-us.apache.org/repos/asf/ignite/blob/c716d598/modules/web-console/frontend/views/404.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/404.jade b/modules/web-console/frontend/views/404.jade
index 3533905..7d2fc55 100644
--- a/modules/web-console/frontend/views/404.jade
+++ b/modules/web-console/frontend/views/404.jade
@@ -14,17 +14,9 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 
-header#header.header
-    table.container
-        tr
-            td.col-xs-3.col-sm-3.col-md-2
-                ignite-header-logo
-            td
-                ignite-header-title
+include includes/header
 
 .error-page
     .container
         h1.error-page__title 404
         h2.error-page__description Page not found
-
-include includes/footer


[08/50] [abbrv] ignite git commit: IGNITE-3723 Fixed import model dialog.

Posted by an...@apache.org.
IGNITE-3723 Fixed import model dialog.


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

Branch: refs/heads/ignite-3629
Commit: 677b8c7448580ad44145ec524eb0a9fed03b628d
Parents: d8fa49e
Author: Maxim Afanasiev <ma...@gridgain.com>
Authored: Wed Aug 24 15:57:26 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Wed Aug 24 15:57:26 2016 +0700

----------------------------------------------------------------------
 .../views/configuration/domains-import.jade     | 53 ++++++++------------
 1 file changed, 21 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/677b8c74/modules/web-console/frontend/views/configuration/domains-import.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/configuration/domains-import.jade b/modules/web-console/frontend/views/configuration/domains-import.jade
index d167465..8d958d6 100644
--- a/modules/web-console/frontend/views/configuration/domains-import.jade
+++ b/modules/web-console/frontend/views/configuration/domains-import.jade
@@ -38,7 +38,7 @@ mixin td-ellipses-lbl(w, lbl)
                         li Agent failed to find JDBC drivers
                         li Copy required JDBC drivers into agent 'jdbc-drivers' folder and try again
                         li Refer to agent README.txt for more information
-                .import-domain-model-wizard-page(ng-show='importDomain.action == "connect" && importDomain.demo')
+                .import-domain-model-wizard-page(ng-if='importDomain.action == "connect" && importDomain.demo')
                     div(ng-if='demoConnection.db == "H2"')
                         label Demo description:
                         ul
@@ -52,8 +52,10 @@ mixin td-ellipses-lbl(w, lbl)
                                 li Agent failed to resolve H2 database jar
                                 li Copy h2-x.x.x.jar into agent 'jdbc-drivers' folder and try again
                                 li Refer to agent README.txt for more information
-                .import-domain-model-wizard-page(ng-show='importDomain.action == "connect" && !importDomain.demo')
-                    form.form-horizontal(name='connectForm' novalidate)
+                .import-domain-model-wizard-page(ng-if='importDomain.action == "connect" && !importDomain.demo')
+                    - var form = 'connectForm'
+
+                    form.form-horizontal(name=form novalidate)
                         .settings-row
                             label.col-xs-4.col-sm-2.col-md-2.required Driver JAR:
                             .col-xs-8.col-sm-10.col-md-10
@@ -63,38 +65,27 @@ mixin td-ellipses-lbl(w, lbl)
                         .settings-row
                             label.col-xs-4.col-sm-2.col-md-2.required JDBC driver:
                             .col-xs-8.col-sm-10.col-md-10
+                                - var name = '"jdbcDriverClass"'
                                 i.tipField.fa.fa-question-circle(bs-tooltip='' data-title='Fully qualified class name of JDBC driver that will be used to connect to database')
-                                .input-tip
-                                    ignite-form-field-input-text(
-                                        data-id='jdbcDriverClass'
-                                        data-name='jdbcDriverClass'
-                                        data-ng-model='selectedPreset.jdbcDriverClass'
-                                        data-ignite-label-name='JDBC driver'
-                                        data-ng-required='true'
-                                        data-placeholder='Enter fully qualified class name'
 
+                                +form-field-feedback(name, 'javaBuiltInClass', 'JDBC Driver should not be the Java built-in class!')
+                                +form-field-feedback(name, 'javaKeywords', 'JDBC Driver could not contains reserved Java keyword!')
+                                +form-field-feedback(name, 'javaPackageSpecified', 'JDBC Driver does not have package specified!')
+                                +form-field-feedback(name, 'javaIdentifier', 'JDBC Driver is invalid Java identifier!')
+
+                                .input-tip
+                                    +ignite-form-field-input(name, 'selectedPreset.jdbcDriverClass', false, true, 'Enter fully qualified class name')(
                                         data-java-identifier='true'
                                         data-java-package-specified='true'
                                         data-java-keywords='true'
                                         data-java-built-in-class='true'
                                     )
-                                        +error-feedback('connectForm.$error.javaBuiltInClass', 'javaBuiltInClass', 'JDBC Driver should not be the Java built-in class!')
-                                        +error-feedback('connectForm.$error.javaKeywords', 'javaKeywords', 'JDBC Driver could not contains reserved Java keyword!')
-                                        +error-feedback('connectForm.$error.javaPackageSpecified', 'javaPackageSpecified', 'JDBC Driver does not have package specified!')
-                                        +error-feedback('connectForm.$error.javaIdentifier', 'javaIdentifier', 'JDBC Driver is invalid Java identifier!')
                         .settings-row
                             label.col-xs-4.col-sm-2.col-md-2.required JDBC URL:
                             .col-xs-8.col-sm-10.col-md-10
                                 i.tipField.fa.fa-question-circle(bs-tooltip='' data-title='JDBC URL for connecting to database<br>Refer to your database documentation for details')
                                 .input-tip
-                                    ignite-form-field-input-text(
-                                        data-id='jdbcUrl'
-                                        data-name='jdbcUrl'
-                                        data-ng-model='selectedPreset.jdbcUrl'
-                                        data-ignite-label-name='JDBC URL'
-                                        data-ng-required='true'
-                                        data-placeholder='JDBC URL'
-                                    )
+                                    +ignite-form-field-input('jdbcUrl', 'selectedPreset.jdbcUrl', false, true, 'JDBC URL')
                         .settings-row
                             label.col-xs-4.col-sm-2.col-md-2 User:
                             .col-xs-8.col-sm-10.col-md-10
@@ -183,26 +174,24 @@ mixin td-ellipses-lbl(w, lbl)
                         .col-sm-1(style='padding-left: 5px')
                             button.btn.btn-primary(ng-click='applyDefaults()') Apply
                 .import-domain-model-wizard-page(ng-show='importDomain.action == "options"')
+                    - var form = 'optionsForm'
                     form.form-horizontal(name='optionsForm' novalidate)
                         .settings-row
                             .col-xs-3.col-sm-2.col-md-2.required
                                 label.required Package:
                             .col-xs-9.col-sm-10.col-md-10
+                                - var name = '"domainPackageName"'
                                 i.tipField.fa.fa-question-circle(bs-tooltip='' data-title='Package that will be used for POJOs generation')
+
+                                +form-field-feedback(name, 'javaPackageName', 'Package name is invalid')
+                                +form-field-feedback(name, 'javaKeywords', 'Package name could not contains reserved java keyword')
+
                                 .input-tip
-                                    ignite-form-field-input-text(
-                                        data-id='domainPackageName'
-                                        data-name='domainPackageName'
-                                        data-ng-model='ui.packageName'
-                                        data-ignite-label-name='Package'
-                                        data-ng-required='true'
-                                        data-placeholder='Enter package name'
+                                    +ignite-form-field-input(name, 'ui.packageName', false, true, 'Enter package name')(
                                         data-java-keywords='true'
                                         data-java-package-name='package-only'
                                         ng-model-options='{allowInvalid: true}'
                                     )
-                                        +error-feedback('optionsForm.$error.javaPackageName', 'javaPackageName', 'Package name is invalid')
-                                        +error-feedback('optionsForm.$error.javaKeywords', 'javaKeywords', 'Package name could not contains reserved java keyword')
                         .settings-row
                             .checkbox
                                 label


[14/50] [abbrv] ignite git commit: GG-11175 Removed duplicated discovery events.

Posted by an...@apache.org.
GG-11175 Removed duplicated discovery events.


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

Branch: refs/heads/ignite-3629
Commit: 63cfc55031e58bb8a4d6fdb324167eeda567235f
Parents: d2da35b
Author: Andrey Novikov <an...@apache.org>
Authored: Thu Aug 25 13:40:05 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Thu Aug 25 13:40:05 2016 +0700

----------------------------------------------------------------------
 .../visor/event/VisorGridDiscoveryEventV2.java  | 80 ++++++++++++++++
 .../visor/node/VisorNodeDataCollectorJob.java   | 10 +-
 .../internal/visor/util/VisorEventMapper.java   | 96 +++++++++++++++-----
 .../internal/visor/util/VisorTaskUtils.java     | 22 ++++-
 4 files changed, 180 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/63cfc550/modules/core/src/main/java/org/apache/ignite/internal/visor/event/VisorGridDiscoveryEventV2.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/event/VisorGridDiscoveryEventV2.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/event/VisorGridDiscoveryEventV2.java
new file mode 100644
index 0000000..b66aacf
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/event/VisorGridDiscoveryEventV2.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.visor.event;
+
+import java.util.UUID;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.lang.IgniteUuid;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Lightweight counterpart for {@link org.apache.ignite.events.DiscoveryEvent}.
+ */
+public class VisorGridDiscoveryEventV2 extends VisorGridDiscoveryEvent {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Topology version. */
+    private final long topVer;
+
+    /**
+     * Create event with given parameters.
+     *
+     * @param typeId Event type.
+     * @param id Event id.
+     * @param name Event name.
+     * @param nid Event node ID.
+     * @param ts Event timestamp.
+     * @param msg Event message.
+     * @param shortDisplay Shortened version of {@code toString()} result.
+     * @param evtNodeId Event node id.
+     * @param addr Event node address.
+     * @param isDaemon If event node is daemon on not.
+     * @param topVer Topology version.
+     */
+    public VisorGridDiscoveryEventV2(
+        int typeId,
+        IgniteUuid id,
+        String name,
+        UUID nid,
+        long ts,
+        @Nullable String msg,
+        String shortDisplay,
+        UUID evtNodeId,
+        String addr,
+        boolean isDaemon,
+        long topVer
+    ) {
+        super(typeId, id, name, nid, ts, msg, shortDisplay, evtNodeId, addr, isDaemon);
+
+        this.topVer = topVer;
+    }
+
+    /**
+     * @return Topology version or {@code 0} if configured discovery SPI implementation
+     *      does not support versioning.
+     **/
+    public long topologyVersion() {
+        return topVer;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(VisorGridDiscoveryEventV2.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/63cfc550/modules/core/src/main/java/org/apache/ignite/internal/visor/node/VisorNodeDataCollectorJob.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/node/VisorNodeDataCollectorJob.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/node/VisorNodeDataCollectorJob.java
index 611dcde..abe1364 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/visor/node/VisorNodeDataCollectorJob.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/node/VisorNodeDataCollectorJob.java
@@ -41,6 +41,8 @@ import org.apache.ignite.lang.IgniteProductVersion;
 import static org.apache.ignite.internal.processors.cache.GridCacheUtils.isIgfsCache;
 import static org.apache.ignite.internal.processors.cache.GridCacheUtils.isSystemCache;
 import static org.apache.ignite.internal.visor.compute.VisorComputeMonitoringHolder.COMPUTE_MONITORING_HOLDER_KEY;
+import static org.apache.ignite.internal.visor.util.VisorTaskUtils.EVT_MAPPER;
+import static org.apache.ignite.internal.visor.util.VisorTaskUtils.EVT_MAPPER_V2;
 import static org.apache.ignite.internal.visor.util.VisorTaskUtils.VISOR_TASK_EVTS;
 import static org.apache.ignite.internal.visor.util.VisorTaskUtils.checkExplicitTaskMonitoring;
 import static org.apache.ignite.internal.visor.util.VisorTaskUtils.collectEvents;
@@ -62,6 +64,9 @@ public class VisorNodeDataCollectorJob extends VisorJob<VisorNodeDataCollectorTa
     /** */
     private static final IgniteProductVersion VER_1_5_26 = IgniteProductVersion.fromString("1.5.26");
 
+    /** */
+    protected static final IgniteProductVersion VER_1_7_2 = IgniteProductVersion.fromString("1.7.2");
+
     /**
      * Create job with given argument.
      *
@@ -82,7 +87,8 @@ public class VisorNodeDataCollectorJob extends VisorJob<VisorNodeDataCollectorTa
      */
     protected void events0(VisorNodeDataCollectorJobResult res, String evtOrderKey, String evtThrottleCntrKey,
         final boolean all) {
-        res.events().addAll(collectEvents(ignite, evtOrderKey, evtThrottleCntrKey, all));
+        res.events().addAll(collectEvents(ignite, evtOrderKey, evtThrottleCntrKey, all,
+            compatibleWith(VER_1_7_2) ? EVT_MAPPER_V2 : EVT_MAPPER));
     }
 
     /**
@@ -132,7 +138,7 @@ public class VisorNodeDataCollectorJob extends VisorJob<VisorNodeDataCollectorTa
      * @param ver Version to check.
      * @return {@code true} if found at least one compatible node with specified version.
      */
-    private boolean compatibleWith(IgniteProductVersion ver) {
+    protected boolean compatibleWith(IgniteProductVersion ver) {
         for (ClusterNode node : ignite.cluster().nodes())
             if (node.version().compareToIgnoreTimestamp(ver) <= 0)
                 return true;

http://git-wip-us.apache.org/repos/asf/ignite/blob/63cfc550/modules/core/src/main/java/org/apache/ignite/internal/visor/util/VisorEventMapper.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/util/VisorEventMapper.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/util/VisorEventMapper.java
index 7e3ae96..829adb3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/visor/util/VisorEventMapper.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/util/VisorEventMapper.java
@@ -55,38 +55,88 @@ public class VisorEventMapper implements IgniteClosure<Event, VisorGridEvent> {
      */
     protected VisorGridEvent map(Event evt, int type, IgniteUuid id, String name, UUID nid, long ts, String msg,
         String shortDisplay) {
-        if (evt instanceof TaskEvent) {
-            TaskEvent te = (TaskEvent)evt;
+        if (evt instanceof TaskEvent)
+            return taskEvent((TaskEvent)evt, type, id, name, nid, ts, msg, shortDisplay);
 
-            return new VisorGridTaskEvent(type, id, name, nid, ts, msg, shortDisplay,
-                te.taskName(), te.taskClassName(), te.taskSessionId(), te.internal());
-        }
+        if (evt instanceof JobEvent)
+            return jobEvent((JobEvent)evt, type, id, name, nid, ts, msg, shortDisplay);
 
-        if (evt instanceof JobEvent) {
-            JobEvent je = (JobEvent)evt;
+        if (evt instanceof DeploymentEvent)
+            return deploymentEvent((DeploymentEvent)evt, type, id, name, nid, ts, msg, shortDisplay);
 
-            return new VisorGridJobEvent(type, id, name, nid, ts, msg, shortDisplay,
-                je.taskName(), je.taskClassName(), je.taskSessionId(), je.jobId());
-        }
+        if (evt instanceof DiscoveryEvent)
+            return discoveryEvent((DiscoveryEvent)evt, type, id, name, nid, ts, msg, shortDisplay);
 
-        if (evt instanceof DeploymentEvent) {
-            DeploymentEvent de = (DeploymentEvent)evt;
-
-            return new VisorGridDeploymentEvent(type, id, name, nid, ts, msg, shortDisplay, de.alias());
-        }
+        return null;
+    }
 
-        if (evt instanceof DiscoveryEvent) {
-            DiscoveryEvent de = (DiscoveryEvent)evt;
+    /**
+     * @param te Task event.
+     * @param type Event's type.
+     * @param id Event id.
+     * @param name Event name.
+     * @param nid Event node ID.
+     * @param ts Event timestamp.
+     * @param msg Event message.
+     * @param shortDisplay Shortened version of {@code toString()} result.
+     * @return Visor data transfer object for event.
+     */
+    protected VisorGridEvent taskEvent(TaskEvent te, int type, IgniteUuid id, String name, UUID nid, long ts,
+        String msg, String shortDisplay) {
+        return new VisorGridTaskEvent(type, id, name, nid, ts, msg, shortDisplay,
+            te.taskName(), te.taskClassName(), te.taskSessionId(), te.internal());
+    }
 
-            ClusterNode node = de.eventNode();
+    /**
+     * @param je Job event.
+     * @param type Event's type.
+     * @param id Event id.
+     * @param name Event name.
+     * @param nid Event node ID.
+     * @param ts Event timestamp.
+     * @param msg Event message.
+     * @param shortDisplay Shortened version of {@code toString()} result.
+     * @return Visor data transfer object for event.
+     */
+    protected VisorGridEvent jobEvent(JobEvent je, int type, IgniteUuid id, String name, UUID nid, long ts,
+        String msg, String shortDisplay) {
+        return new VisorGridJobEvent(type, id, name, nid, ts, msg, shortDisplay, je.taskName(), je.taskClassName(),
+            je.taskSessionId(), je.jobId());
+    }
 
-            String addr = F.first(node.addresses());
+    /**
+     * @param de Deployment event.
+     * @param type Event's type.
+     * @param id Event id.
+     * @param name Event name.
+     * @param nid Event node ID.
+     * @param ts Event timestamp.
+     * @param msg Event message.
+     * @param shortDisplay Shortened version of {@code toString()} result.
+     * @return Visor data transfer object for event.
+     */
+    protected VisorGridEvent deploymentEvent(DeploymentEvent de, int type, IgniteUuid id, String name, UUID nid,
+        long ts, String msg, String shortDisplay) {
+        return new VisorGridDeploymentEvent(type, id, name, nid, ts, msg, shortDisplay, de.alias());
+    }
 
-            return new VisorGridDiscoveryEvent(type, id, name, nid, ts, msg, shortDisplay,
-                node.id(), addr, node.isDaemon());
-        }
+    /**
+     * @param de Discovery event.
+     * @param type Event's type.
+     * @param id Event id.
+     * @param name Event name.
+     * @param nid Event node ID.
+     * @param ts Event timestamp.
+     * @param msg Event message.
+     * @param shortDisplay Shortened version of {@code toString()} result.
+     * @return Visor data transfer object for event.
+     */
+    protected VisorGridEvent discoveryEvent(DiscoveryEvent de, int type, IgniteUuid id, String name, UUID nid,
+        long ts, String msg, String shortDisplay) {
+        ClusterNode node = de.eventNode();
 
-        return null;
+        return new VisorGridDiscoveryEvent(type, id, name, nid, ts, msg, shortDisplay, node.id(),
+            F.first(node.addresses()), node.isDaemon());
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/63cfc550/modules/core/src/main/java/org/apache/ignite/internal/visor/util/VisorTaskUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/util/VisorTaskUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/util/VisorTaskUtils.java
index 7eebbf1..9e7ba29 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/visor/util/VisorTaskUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/util/VisorTaskUtils.java
@@ -41,6 +41,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.SortedMap;
+import java.util.UUID;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.zip.ZipEntry;
@@ -54,18 +55,21 @@ import org.apache.ignite.cache.eviction.fifo.FifoEvictionPolicyMBean;
 import org.apache.ignite.cache.eviction.lru.LruEvictionPolicyMBean;
 import org.apache.ignite.cache.eviction.random.RandomEvictionPolicyMBean;
 import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.events.DiscoveryEvent;
 import org.apache.ignite.events.Event;
 import org.apache.ignite.internal.processors.igfs.IgfsEx;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.SB;
 import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.internal.visor.event.VisorGridDiscoveryEventV2;
 import org.apache.ignite.internal.visor.event.VisorGridEvent;
 import org.apache.ignite.internal.visor.event.VisorGridEventsLost;
 import org.apache.ignite.internal.visor.file.VisorFileBlock;
 import org.apache.ignite.internal.visor.log.VisorLogFile;
 import org.apache.ignite.lang.IgniteClosure;
 import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.lang.IgniteUuid;
 import org.jetbrains.annotations.Nullable;
 
 import static java.lang.System.getProperty;
@@ -382,6 +386,17 @@ public class VisorTaskUtils {
     /** Mapper from grid event to Visor data transfer object. */
     public static final VisorEventMapper EVT_MAPPER = new VisorEventMapper();
 
+    /** Mapper from grid event to Visor data transfer object. */
+    public static final VisorEventMapper EVT_MAPPER_V2 = new VisorEventMapper() {
+        @Override protected VisorGridEvent discoveryEvent(DiscoveryEvent de, int type, IgniteUuid id, String name,
+            UUID nid, long ts, String msg, String shortDisplay) {
+            ClusterNode node = de.eventNode();
+
+            return new VisorGridDiscoveryEventV2(type, id, name, nid, ts, msg, shortDisplay, node.id(),
+                F.first(node.addresses()), node.isDaemon(), de.topologyVersion());
+        }
+    };
+
     /**
      * Grabs local events and detects if events was lost since last poll.
      *
@@ -389,17 +404,18 @@ public class VisorTaskUtils {
      * @param evtOrderKey Unique key to take last order key from node local map.
      * @param evtThrottleCntrKey Unique key to take throttle count from node local map.
      * @param all If {@code true} then collect all events otherwise collect only non task events.
+     * @param evtMapper Closure to map grid events to Visor data transfer objects.
      * @return Collections of node events
      */
     public static Collection<VisorGridEvent> collectEvents(Ignite ignite, String evtOrderKey, String evtThrottleCntrKey,
-        final boolean all) {
+        boolean all, IgniteClosure<Event, VisorGridEvent> evtMapper) {
         int[] evtTypes = all ? VISOR_ALL_EVTS : VISOR_NON_TASK_EVTS;
 
         // Collect discovery events for Web Console.
         if (evtOrderKey.startsWith("CONSOLE_"))
             evtTypes = concat(evtTypes, EVTS_DISCOVERY);
 
-        return collectEvents(ignite, evtOrderKey, evtThrottleCntrKey, evtTypes, EVT_MAPPER);
+        return collectEvents(ignite, evtOrderKey, evtThrottleCntrKey, evtTypes, evtMapper);
     }
 
     /**
@@ -413,7 +429,7 @@ public class VisorTaskUtils {
      * @return Collections of node events
      */
     public static Collection<VisorGridEvent> collectEvents(Ignite ignite, String evtOrderKey, String evtThrottleCntrKey,
-        final int[] evtTypes, IgniteClosure<Event, VisorGridEvent> evtMapper) {
+        int[] evtTypes, IgniteClosure<Event, VisorGridEvent> evtMapper) {
         assert ignite != null;
         assert evtTypes != null && evtTypes.length > 0;
 


[30/50] [abbrv] ignite git commit: Minor fix.

Posted by an...@apache.org.
Minor fix.


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

Branch: refs/heads/ignite-3629
Commit: ab9db26b5c23abe706dc372d3fe98da926c92881
Parents: 27176d5
Author: Andrey Novikov <an...@apache.org>
Authored: Tue Aug 30 14:37:20 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Tue Aug 30 14:37:20 2016 +0700

----------------------------------------------------------------------
 .../frontend/app/modules/user/User.service.js     | 18 +++++++++++-------
 .../frontend/app/services/LegacyUtils.service.js  | 16 ++++++----------
 .../frontend/controllers/domains-controller.js    | 18 ++++++++----------
 3 files changed, 25 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ab9db26b/modules/web-console/frontend/app/modules/user/User.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/User.service.js b/modules/web-console/frontend/app/modules/user/User.service.js
index f95590a..8b9a1e7 100644
--- a/modules/web-console/frontend/app/modules/user/User.service.js
+++ b/modules/web-console/frontend/app/modules/user/User.service.js
@@ -16,23 +16,27 @@
  */
 
 export default ['User', ['$q', '$injector', '$rootScope', '$state', '$http', function($q, $injector, $root, $state, $http) {
-    let user = null;
+    let user;
 
     return {
         load() {
-            return $http.post('/api/v1/user')
+            return user = $http.post('/api/v1/user')
                 .then(({data}) => {
-                    user = $root.user = data;
+                    $root.user = data;
 
-                    $root.$broadcast('user', user);
+                    $root.$broadcast('user', $root.user);
 
-                    return user;
+                    return $root.user;
                 })
-                .catch(({data}) => $q.reject(data));
+                .catch(({data}) => {
+                    user = null;
+
+                    return $q.reject(data);
+                });
         },
         read() {
             if (user)
-                return $q.resolve(user);
+                return user;
 
             return this.load();
         },

http://git-wip-us.apache.org/repos/asf/ignite/blob/ab9db26b/modules/web-console/frontend/app/services/LegacyUtils.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/services/LegacyUtils.service.js b/modules/web-console/frontend/app/services/LegacyUtils.service.js
index 6328895..ed555a1 100644
--- a/modules/web-console/frontend/app/services/LegacyUtils.service.js
+++ b/modules/web-console/frontend/app/services/LegacyUtils.service.js
@@ -362,9 +362,7 @@ export default ['IgniteLegacyUtils', ['IgniteErrorPopover', (ErrorPopover) => {
         isEmptyString,
         SUPPORTED_JDBC_TYPES,
         findJdbcType(jdbcType) {
-            const res = _.find(ALL_JDBC_TYPES, function (item) {
-                return item.dbType === jdbcType;
-            });
+            const res = _.find(ALL_JDBC_TYPES, (item) => item.dbType === jdbcType);
 
             return res ? res : {dbName: 'Unknown', javaType: 'Unknown'};
         },
@@ -432,16 +430,14 @@ export default ['IgniteLegacyUtils', ['IgniteErrorPopover', (ErrorPopover) => {
         },
         cacheStoreJdbcDialects,
         cacheStoreJdbcDialectsLabel(dialect) {
-            const found = _.find(cacheStoreJdbcDialects, function (dialectVal) {
-                return dialectVal.value === dialect;
-            });
+            const found = _.find(cacheStoreJdbcDialects, (dialectVal) => dialectVal.value === dialect);
 
             return found ? found.label : null;
         },
         checkDataSources(cluster, caches, checkCacheExt) {
             let res = DS_CHECK_SUCCESS;
 
-            _.find(caches, function (curCache, curIx) {
+            _.find(caches, (curCache, curIx) => {
                 res = compareDataSources(curCache, cluster);
 
                 if (!res.checked)
@@ -457,7 +453,7 @@ export default ['IgniteLegacyUtils', ['IgniteErrorPopover', (ErrorPopover) => {
                     return false;
                 }
 
-                return _.find(caches, function (checkCache, checkIx) {
+                return _.find(caches, (checkCache, checkIx) => {
                     if (checkIx < curIx) {
                         res = compareDataSources(checkCache, curCache);
 
@@ -484,7 +480,7 @@ export default ['IgniteLegacyUtils', ['IgniteErrorPopover', (ErrorPopover) => {
                     return false;
                 }
 
-                return _.find(caches, function (checkCache, checkIx) {
+                return _.find(caches, (checkCache, checkIx) => {
                     if (checkIx < curIx) {
                         res = compareSQLSchemaNames(checkCache, curCache);
 
@@ -551,7 +547,7 @@ export default ['IgniteLegacyUtils', ['IgniteErrorPopover', (ErrorPopover) => {
                 const errNameFull = actualError.$name;
                 const errNameShort = errNameFull.endsWith('TextInput') ? errNameFull.substring(0, errNameFull.length - 9) : errNameFull;
 
-                const extractErrorMessage = function (errName) {
+                const extractErrorMessage = (errName) => {
                     try {
                         return errors[firstErrorKey][0].$errorMessages[errName][firstErrorKey];
                     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ab9db26b/modules/web-console/frontend/controllers/domains-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/domains-controller.js b/modules/web-console/frontend/controllers/domains-controller.js
index ea53777..c1f6c91 100644
--- a/modules/web-console/frontend/controllers/domains-controller.js
+++ b/modules/web-console/frontend/controllers/domains-controller.js
@@ -397,9 +397,9 @@ export default ['domainsController', [
                 $scope.importDomain.loadingOptions = LOADING_JDBC_DRIVERS;
 
                 IgniteAgentMonitor.startWatch({text: 'Back to Domain models', goal: 'import domain model from database'})
-                    .then(function() {
-                        importDomainModal.$promise.then(importDomainModal.show);
-
+                    .then(importDomainModal.$promise)
+                    .then(importDomainModal.show)
+                    .then(() => {
                         if (demo) {
                             $scope.ui.packageNameUserInput = $scope.ui.packageName;
                             $scope.ui.packageName = 'model';
@@ -420,7 +420,7 @@ export default ['domainsController', [
                                 if (drivers && drivers.length > 0) {
                                     drivers = _.sortBy(drivers, 'jdbcDriverJar');
 
-                                    _.forEach(drivers, function(drv) {
+                                    _.forEach(drivers, (drv) => {
                                         $scope.jdbcDriverJars.push({
                                             label: drv.jdbcDriverJar,
                                             value: {
@@ -432,13 +432,11 @@ export default ['domainsController', [
 
                                     $scope.ui.selectedJdbcDriverJar = $scope.jdbcDriverJars[0].value;
 
-                                    FormUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, function() {
-                                        importDomainModal.$promise.then(() => {
-                                            $scope.importDomain.action = 'connect';
-                                            $scope.importDomain.tables = [];
+                                    FormUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, () => {
+                                        $scope.importDomain.action = 'connect';
+                                        $scope.importDomain.tables = [];
 
-                                            Focus.move('jdbcUrl');
-                                        });
+                                        Focus.move('jdbcUrl');
                                     });
                                 }
                                 else {


[34/50] [abbrv] ignite git commit: IGNITE-3683 Fixed dropdown postion on show.

Posted by an...@apache.org.
IGNITE-3683 Fixed dropdown postion on show.


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

Branch: refs/heads/ignite-3629
Commit: 05bf80231b97d3ac73b09aa60372c4f7ff679c0c
Parents: 1fe790a
Author: Maxim Afanasiev <ma...@gridgain.com>
Authored: Thu Sep 1 17:02:25 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Thu Sep 1 17:02:25 2016 +0700

----------------------------------------------------------------------
 .../helpers/jade/form/form-field-dropdown.jade  |  1 +
 .../app/modules/form/field/input/select.scss    | 21 ++++++++++++++++++++
 .../frontend/app/modules/form/form.module.js    |  1 +
 3 files changed, 23 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/05bf8023/modules/web-console/frontend/app/helpers/jade/form/form-field-dropdown.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/helpers/jade/form/form-field-dropdown.jade b/modules/web-console/frontend/app/helpers/jade/form/form-field-dropdown.jade
index 807982a..a8496bc 100644
--- a/modules/web-console/frontend/app/helpers/jade/form/form-field-dropdown.jade
+++ b/modules/web-console/frontend/app/helpers/jade/form/form-field-dropdown.jade
@@ -31,6 +31,7 @@ mixin ignite-form-field-dropdown(label, model, name, disabled, required, multipl
             bs-options='item.value as item.label for item in #{options}' 
 
             data-multiple=multiple ? '1' : false
+            data-container='body > .wrapper'
 
             tabindex='0'
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/05bf8023/modules/web-console/frontend/app/modules/form/field/input/select.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/form/field/input/select.scss b/modules/web-console/frontend/app/modules/form/field/input/select.scss
new file mode 100644
index 0000000..55bbd58
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/form/field/input/select.scss
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+.select.dropdown-menu.ng-leave {
+    transition: none !important; /* disable transitions */
+    animation: none 0s !important; /* disable keyframe animations */
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/05bf8023/modules/web-console/frontend/app/modules/form/form.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/form/form.module.js b/modules/web-console/frontend/app/modules/form/form.module.js
index c014c29..23eafcd 100644
--- a/modules/web-console/frontend/app/modules/form/form.module.js
+++ b/modules/web-console/frontend/app/modules/form/form.module.js
@@ -21,6 +21,7 @@ import angular from 'angular';
 import './field/field.scss';
 import './field/feedback.scss';
 import './field/input/text.scss';
+import './field/input/select.scss';
 
 // Panel.
 import igniteFormPanel from './panel/panel.directive';


[13/50] [abbrv] ignite git commit: IGNITE-3706 Minor fix.

Posted by an...@apache.org.
IGNITE-3706 Minor fix.


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

Branch: refs/heads/ignite-3629
Commit: d2da35b9bbcc2473878b40e127663bf1591fe795
Parents: 671c1d9
Author: Andrey Novikov <an...@apache.org>
Authored: Thu Aug 25 13:34:07 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Thu Aug 25 13:34:07 2016 +0700

----------------------------------------------------------------------
 .../frontend/app/modules/sql/sql.controller.js            | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d2da35b9/modules/web-console/frontend/app/modules/sql/sql.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/sql.controller.js b/modules/web-console/frontend/app/modules/sql/sql.controller.js
index 3162224..d3449ed 100644
--- a/modules/web-console/frontend/app/modules/sql/sql.controller.js
+++ b/modules/web-console/frontend/app/modules/sql/sql.controller.js
@@ -22,9 +22,6 @@ const TIME_LINE = {value: -1, type: 'java.sql.Date', label: 'TIME_LINE'};
 const ROW_IDX = {value: -2, type: 'java.lang.Integer', label: 'ROW_IDX'};
 
 /** Prefix for node local key for SCAN near queries. */
-const SCAN_NEAR_CACHE = 'VISOR_SCAN_NEAR_CACHE';
-
-/** Prefix for node local key for SCAN near queries. */
 const SCAN_CACHE_WITH_FILTER = 'VISOR_SCAN_CACHE_WITH_FILTER';
 
 /** Prefix for node local key for SCAN near queries. */
@@ -45,10 +42,7 @@ const _fullColName = (col) => {
 };
 
 class Paragraph {
-    constructor($timeout, Notebook, paragraph) {
-        this.$timeout = $timeout;
-        this.Notebook = Notebook;
-
+    constructor(paragraph) {
         _.assign(this, paragraph);
     }
 
@@ -797,7 +791,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                 $scope.notebook.paragraphs = _.map($scope.notebook.paragraphs, (paragraph) => {
                     paragraph.id = 'paragraph-' + paragraphId++;
 
-                    const par = new Paragraph($timeout, Notebook, paragraph);
+                    const par = new Paragraph(paragraph);
 
                     Object.defineProperty(par, 'gridOptions', {value: {
                         enableGridMenu: false,


[35/50] [abbrv] ignite git commit: Fixed typo

Posted by an...@apache.org.
Fixed typo


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

Branch: refs/heads/ignite-3629
Commit: 31f8d1ca1a0be5eaf806590f42de6e6a7b49c7b0
Parents: 05bf802
Author: Andrey Novikov <an...@apache.org>
Authored: Fri Sep 2 13:14:22 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Fri Sep 2 13:14:22 2016 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/app/modules/sql/sql.controller.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/31f8d1ca/modules/web-console/frontend/app/modules/sql/sql.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/sql.controller.js b/modules/web-console/frontend/app/modules/sql/sql.controller.js
index 1c68a64..235592b 100644
--- a/modules/web-console/frontend/app/modules/sql/sql.controller.js
+++ b/modules/web-console/frontend/app/modules/sql/sql.controller.js
@@ -1581,14 +1581,14 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
         };
 
         $scope.showResultQuery = function(paragraph) {
-            if (LegacyUtils.isDefined(paragraph)) {
+            if (!_.isNil(paragraph)) {
                 const scope = $scope.$new();
 
                 if (_.isNil(paragraph.queryArgs.query)) {
                     scope.title = 'SCAN query';
                     scope.content = [`SCAN query for cache: <b>${$scope.maskCacheName(paragraph.queryArgs.cacheName)}</b>`];
                 }
-                if (paragraph.queryArgs.query.startsWith(SCAN_CACHE_WITH_FILTER)) {
+                else if (paragraph.queryArgs.query.startsWith(SCAN_CACHE_WITH_FILTER)) {
                     scope.title = 'SCAN query';
 
                     let filter = '';


[15/50] [abbrv] ignite git commit: Merge branches 'ignite-1.7.2' and 'web-console-staging'.

Posted by an...@apache.org.
Merge branches 'ignite-1.7.2' and 'web-console-staging'.


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

Branch: refs/heads/ignite-3629
Commit: 1640e66bd56bfdefe112243bb4153324c37c91ef
Parents: 63cfc55 4343c73
Author: Alexey Kuznetsov <ak...@apache.org>
Authored: Thu Aug 25 14:49:33 2016 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Thu Aug 25 14:49:33 2016 +0700

----------------------------------------------------------------------
 .gitignore                                      |    1 +
 RELEASE_NOTES.txt                               |   19 +
 assembly/libs/README.txt                        |   39 +-
 .../hibernate/HibernateL2CacheExample.java      |    2 +-
 .../examples/datagrid/CacheQueryExample.java    |   78 +-
 .../jdbc2/JdbcDistributedJoinsQueryTest.java    |  319 ++++
 .../JettyRestProcessorAbstractSelfTest.java     |  178 +-
 .../jdbc/suite/IgniteJdbcDriverTestSuite.java   |    2 +
 .../ignite/codegen/MessageCodeGenerator.java    |    6 +
 modules/core/pom.xml                            |    6 +
 .../src/main/java/org/apache/ignite/Ignite.java |    4 +-
 .../org/apache/ignite/IgniteJdbcDriver.java     |   14 +-
 .../org/apache/ignite/cache/QueryEntity.java    |   18 +
 .../ignite/cache/query/SqlFieldsQuery.java      |   53 +
 .../org/apache/ignite/cache/query/SqlQuery.java |   28 +
 .../store/jdbc/CacheAbstractJdbcStore.java      |  144 +-
 .../cache/store/jdbc/CacheJdbcPojoStore.java    |    7 +-
 .../store/jdbc/CacheJdbcPojoStoreFactory.java   |   26 +
 .../store/jdbc/JdbcTypesDefaultTransformer.java |  117 ++
 .../cache/store/jdbc/JdbcTypesTransformer.java  |   39 +
 .../store/jdbc/dialect/BasicJdbcDialect.java    |    7 +-
 .../cache/store/jdbc/dialect/JdbcDialect.java   |   11 +-
 .../cache/store/jdbc/dialect/MySQLDialect.java  |   18 +-
 .../configuration/IgniteConfiguration.java      |   42 +-
 .../ignite/internal/MarshallerContextImpl.java  |    9 +-
 .../internal/cluster/ClusterGroupAdapter.java   |   18 +-
 .../ignite/internal/jdbc2/JdbcConnection.java   |   12 +
 .../ignite/internal/jdbc2/JdbcQueryTask.java    |    9 +-
 .../ignite/internal/jdbc2/JdbcResultSet.java    |    4 +-
 .../ignite/internal/jdbc2/JdbcStatement.java    |    2 +-
 .../managers/communication/GridIoManager.java   |   34 +-
 .../communication/GridIoMessageFactory.java     |    2 +-
 .../managers/communication/GridIoPolicy.java    |    5 +-
 .../discovery/GridDiscoveryManager.java         |    3 +-
 .../GridAffinityFunctionContextImpl.java        |    2 +-
 .../cache/GridCacheAffinityManager.java         |    2 +-
 .../processors/cache/GridCacheContext.java      |   19 +
 .../GridCacheDefaultAffinityKeyMapper.java      |   19 +
 .../processors/cache/GridCacheIoManager.java    |   21 +-
 .../processors/cache/IgniteCacheProxy.java      |    8 +
 .../binary/CacheObjectBinaryProcessorImpl.java  |    8 +
 .../distributed/GridCacheTxRecoveryFuture.java  |    7 +
 .../distributed/GridCacheTxRecoveryRequest.java |    1 -
 .../GridCacheTxRecoveryResponse.java            |   23 +-
 .../GridDistributedTxFinishRequest.java         |   19 +-
 .../GridDistributedTxFinishResponse.java        |    1 -
 .../GridDistributedTxPrepareRequest.java        |   26 +-
 .../GridDistributedTxPrepareResponse.java       |   20 +-
 .../dht/GridCachePartitionedConcurrentMap.java  |  142 +-
 .../dht/GridDhtPartitionTopology.java           |    2 +-
 .../dht/GridDhtPartitionTopologyImpl.java       |  176 +-
 .../dht/GridDhtPartitionsReservation.java       |    3 +-
 .../cache/distributed/dht/GridReservable.java   |    5 +-
 .../near/GridNearTxPrepareFutureAdapter.java    |    7 +
 .../cache/query/GridCacheQueryManager.java      |  110 +-
 .../cache/query/GridCacheQueryMarshallable.java |   37 +
 .../cache/query/GridCacheSqlQuery.java          |   33 +-
 .../cache/query/GridCacheTwoStepQuery.java      |  123 +-
 .../continuous/CacheContinuousQueryManager.java |    2 +-
 .../cache/transactions/IgniteTxHandler.java     |   55 +-
 .../IgniteTxImplicitSingleStateImpl.java        |   13 +
 .../IgniteTxRemoteSingleStateImpl.java          |   13 +
 .../transactions/IgniteTxRemoteStateImpl.java   |   38 +-
 .../cache/transactions/IgniteTxState.java       |    6 +
 .../cache/transactions/IgniteTxStateAware.java  |   34 +
 .../cache/transactions/IgniteTxStateImpl.java   |   12 +
 .../cacheobject/IgniteCacheObjectProcessor.java |    6 +
 .../IgniteCacheObjectProcessorImpl.java         |    5 +
 .../processors/closure/GridClosurePolicy.java   |   51 -
 .../closure/GridClosureProcessor.java           |   52 +-
 .../datastructures/GridCacheSemaphoreImpl.java  |  108 +-
 .../internal/processors/igfs/IgfsImpl.java      |    6 +-
 .../processors/job/GridJobProcessor.java        |    4 +-
 .../processors/odbc/OdbcHandshakeRequest.java   |   42 +-
 .../processors/odbc/OdbcHandshakeResult.java    |   17 +-
 .../processors/odbc/OdbcMessageParser.java      |   34 +-
 .../processors/odbc/OdbcProtocolVersion.java    |  125 ++
 .../processors/odbc/OdbcRequestHandler.java     |   26 +-
 .../platform/PlatformAbstractBootstrap.java     |    5 +
 .../processors/platform/PlatformBootstrap.java  |    6 +
 .../processors/platform/PlatformIgnition.java   |    7 +-
 .../platform/PlatformProcessorImpl.java         |   35 +-
 .../platform/cache/PlatformCache.java           |   12 +-
 .../affinity/PlatformAffinityFunction.java      |   27 +
 .../cache/affinity/PlatformAffinityUtils.java   |    2 +
 .../callback/PlatformCallbackGateway.java       |   13 +-
 .../callback/PlatformCallbackUtils.java         |    8 +
 .../platform/cluster/PlatformClusterGroup.java  |    7 +
 .../platform/compute/PlatformAbstractTask.java  |    1 +
 .../dotnet/PlatformDotNetBootstrap.java         |   12 +
 .../dotnet/PlatformDotNetCacheStore.java        |   27 +-
 .../PlatformDotNetConfigurationClosure.java     |   58 +-
 .../dotnet/PlatformDotNetConsoleStream.java     |   54 +
 .../services/PlatformAbstractService.java       |    3 +-
 .../utils/PlatformConfigurationUtils.java       |  106 +-
 .../platform/utils/PlatformFutureUtils.java     |    2 +
 .../platform/utils/PlatformUtils.java           |   12 +
 .../processors/query/GridQueryIndexing.java     |   51 +-
 .../processors/query/GridQueryProcessor.java    |  194 +--
 .../query/GridQueryTypeDescriptor.java          |    7 +
 .../messages/GridQueryCancelRequest.java        |    2 +-
 .../twostep/messages/GridQueryFailResponse.java |    2 +-
 .../messages/GridQueryNextPageRequest.java      |    2 +-
 .../messages/GridQueryNextPageResponse.java     |   12 +-
 .../h2/twostep/messages/GridQueryRequest.java   |   28 +-
 .../handlers/cache/GridCacheCommandHandler.java |  100 +-
 .../handlers/query/QueryCommandHandler.java     |    4 +
 .../rest/request/RestQueryRequest.java          |   17 +
 .../ignite/internal/util/IgniteUtils.java       |   47 +-
 .../internal/util/PartitionedReadOnlySet.java   |   71 -
 .../ignite/internal/util/lang/GridFunc.java     |   20 +
 .../offheap/unsafe/GridOffHeapSnapTreeMap.java  |   91 +-
 .../internal/visor/query/VisorQueryArgV2.java   |   49 +
 .../internal/visor/query/VisorQueryJob.java     |    1 +
 .../internal/visor/util/VisorTaskUtils.java     |    8 +
 .../dotnet/PlatformDotNetAffinityFunction.java  |   15 +
 .../SpringApplicationContextResource.java       |    4 +-
 .../apache/ignite/resources/SpringResource.java |   15 +-
 .../ignite/scheduler/SchedulerFuture.java       |    5 +-
 .../communication/tcp/TcpCommunicationSpi.java  |    6 +-
 .../ignite/spi/discovery/tcp/ClientImpl.java    |    8 +-
 .../java/org/jetbrains/annotations/NotNull.java |   38 -
 .../org/jetbrains/annotations/Nullable.java     |   33 -
 .../org/jetbrains/annotations/package-info.java |   27 -
 .../resources/META-INF/classnames.properties    |   20 +-
 .../ignite/internal/ClusterGroupSelfTest.java   |   30 +-
 .../MarshallerContextLockingSelfTest.java       |  139 ++
 .../cache/GridCacheAbstractFullApiSelfTest.java |  127 +-
 ...eDynamicCacheStartNoExchangeTimeoutTest.java |    2 +
 .../IgniteTxExceptionAbstractSelfTest.java      |   45 +-
 .../IgniteSemaphoreAbstractSelfTest.java        |   25 +-
 .../CacheLateAffinityAssignmentTest.java        |    4 -
 .../dht/IgniteCacheConcurrentPutGetRemove.java  |  201 +++
 .../IgniteCacheSyncRebalanceModeSelfTest.java   |    2 +
 .../processors/igfs/IgfsAbstractSelfTest.java   |    4 +-
 ...niteMessagingConfigVariationFullApiTest.java |  484 ++++++
 .../GridCacheAtomicCommandHandlerSelfTest.java  |   39 +
 .../cache/GridCacheCommandHandlerSelfTest.java  |   20 +-
 .../ignite/platform/PlatformStringTestTask.java |   67 +
 .../jdbc/TcpDiscoveryJdbcIpFinderSelfTest.java  |    2 +-
 .../junits/common/GridCommonAbstractTest.java   |   39 +-
 .../ignite/testsuites/IgniteBasicTestSuite.java |    3 +
 ...essagingConfigVariationFullApiTestSuite.java |   72 +
 .../testsuites/IgniteRestHandlerTestSuite.java  |    2 +
 modules/docker/1.6.0/Dockerfile                 |   44 +
 modules/docker/1.6.0/run.sh                     |   51 +
 modules/docker/Dockerfile                       |   24 +-
 .../query/h2/opt/GridH2SpatialIndex.java        |   74 +-
 .../processors/query/h2/IgniteH2Indexing.java   |  726 ++++++--
 .../query/h2/opt/GridH2AbstractKeyValueRow.java |   72 +-
 .../query/h2/opt/GridH2CollocationModel.java    |  783 +++++++++
 .../processors/query/h2/opt/GridH2Cursor.java   |   36 +-
 .../query/h2/opt/GridH2DefaultTableEngine.java  |   38 +
 .../query/h2/opt/GridH2IndexBase.java           | 1392 ++++++++++++++-
 .../query/h2/opt/GridH2MetaTable.java           |  383 ++++
 .../query/h2/opt/GridH2QueryContext.java        |  612 +++++++
 .../query/h2/opt/GridH2QueryType.java           |   49 +
 .../query/h2/opt/GridH2RetryException.java      |   32 +
 .../processors/query/h2/opt/GridH2Row.java      |   86 +-
 .../query/h2/opt/GridH2RowDescriptor.java       |   28 +-
 .../query/h2/opt/GridH2RowFactory.java          |  179 ++
 .../processors/query/h2/opt/GridH2Table.java    |  372 ++--
 .../query/h2/opt/GridH2TreeIndex.java           |  142 +-
 .../processors/query/h2/opt/GridH2Utils.java    |  133 --
 .../query/h2/opt/GridH2ValueCacheObject.java    |    3 +-
 .../query/h2/opt/GridLuceneIndex.java           |    7 +-
 .../processors/query/h2/sql/GridSqlAlias.java   |   12 +
 .../processors/query/h2/sql/GridSqlColumn.java  |   22 +-
 .../processors/query/h2/sql/GridSqlElement.java |   11 +
 .../query/h2/sql/GridSqlOperation.java          |    2 +-
 .../query/h2/sql/GridSqlOperationType.java      |    8 +-
 .../query/h2/sql/GridSqlQueryParser.java        |   97 +-
 .../query/h2/sql/GridSqlQuerySplitter.java      |  293 +++-
 .../processors/query/h2/sql/GridSqlSelect.java  |    9 +-
 .../processors/query/h2/sql/GridSqlTable.java   |   70 +
 .../query/h2/twostep/GridMapQueryExecutor.java  |  415 +++--
 .../query/h2/twostep/GridMergeIndex.java        |   75 +-
 .../h2/twostep/GridMergeIndexUnsorted.java      |    6 +-
 .../query/h2/twostep/GridMergeTable.java        |    4 +-
 .../h2/twostep/GridReduceQueryExecutor.java     |  338 ++--
 .../query/h2/twostep/GridThreadLocalTable.java  |   68 +-
 .../query/h2/twostep/msg/GridH2Array.java       |    9 +-
 .../query/h2/twostep/msg/GridH2Boolean.java     |   10 +-
 .../query/h2/twostep/msg/GridH2Byte.java        |    9 +-
 .../query/h2/twostep/msg/GridH2Bytes.java       |   11 +-
 .../query/h2/twostep/msg/GridH2CacheObject.java |    9 +-
 .../query/h2/twostep/msg/GridH2Date.java        |    9 +-
 .../query/h2/twostep/msg/GridH2Decimal.java     |   11 +-
 .../query/h2/twostep/msg/GridH2Double.java      |    9 +-
 .../query/h2/twostep/msg/GridH2Float.java       |    9 +-
 .../query/h2/twostep/msg/GridH2Geometry.java    |   11 +-
 .../h2/twostep/msg/GridH2IndexRangeRequest.java |  208 +++
 .../twostep/msg/GridH2IndexRangeResponse.java   |  279 +++
 .../query/h2/twostep/msg/GridH2Integer.java     |   20 +-
 .../query/h2/twostep/msg/GridH2JavaObject.java  |   11 +-
 .../query/h2/twostep/msg/GridH2Long.java        |    9 +-
 .../query/h2/twostep/msg/GridH2Null.java        |   15 +-
 .../h2/twostep/msg/GridH2QueryRequest.java      |  401 +++++
 .../query/h2/twostep/msg/GridH2RowMessage.java  |  116 ++
 .../query/h2/twostep/msg/GridH2RowRange.java    |  181 ++
 .../h2/twostep/msg/GridH2RowRangeBounds.java    |  188 ++
 .../query/h2/twostep/msg/GridH2Short.java       |    9 +-
 .../query/h2/twostep/msg/GridH2String.java      |    9 +-
 .../query/h2/twostep/msg/GridH2Time.java        |    9 +-
 .../query/h2/twostep/msg/GridH2Timestamp.java   |   11 +-
 .../query/h2/twostep/msg/GridH2Uuid.java        |    9 +-
 .../h2/twostep/msg/GridH2ValueMessage.java      |    2 +-
 .../twostep/msg/GridH2ValueMessageFactory.java  |   22 +-
 .../cache/CacheIndexingOffheapCleanupTest.java  |  178 ++
 ...idCacheReduceQueryMultithreadedSelfTest.java |  168 --
 .../cache/IgniteCacheAbstractQuerySelfTest.java |   30 +-
 .../IgniteCacheCrossCacheJoinRandomTest.java    |  442 +++++
 ...acheDistributedJoinCollocatedAndNotTest.java |  365 ++++
 ...acheDistributedJoinCustomAffinityMapper.java |  262 +++
 .../IgniteCacheDistributedJoinNoIndexTest.java  |  299 ++++
 ...ributedJoinPartitionedAndReplicatedTest.java |  487 ++++++
 ...CacheDistributedJoinQueryConditionsTest.java |  624 +++++++
 .../cache/IgniteCacheDistributedJoinTest.java   |  316 ++++
 ...PartitionedAndReplicatedCollocationTest.java |  399 +++++
 ...teCacheJoinPartitionedAndReplicatedTest.java |  316 ++++
 ...IgniteCacheJoinQueryWithAffinityKeyTest.java |  646 +++++++
 ...eLockPartitionOnAffinityRunAbstractTest.java |    2 +-
 ...IgniteCachePrimitiveFieldsQuerySelfTest.java |  134 ++
 .../cache/IgniteCacheQueryLoadSelfTest.java     |   12 +-
 .../cache/IgniteCacheUnionDuplicatesTest.java   |  151 ++
 .../cache/IgniteCrossCachesJoinsQueryTest.java  | 1641 ++++++++++++++++++
 ...QueryNodeRestartDistributedJoinSelfTest.java |  476 +++++
 ...dCacheAbstractReduceFieldsQuerySelfTest.java |  420 -----
 ...ridCacheReduceFieldsQueryAtomicSelfTest.java |   38 -
 ...GridCacheReduceFieldsQueryLocalSelfTest.java |   37 -
 ...cheReduceFieldsQueryPartitionedSelfTest.java |   59 -
 ...acheReduceFieldsQueryReplicatedSelfTest.java |   37 -
 .../query/IgniteSqlSchemaIndexingTest.java      |    5 +-
 .../query/IgniteSqlSplitterSelfTest.java        |  833 ++++++++-
 .../h2/GridIndexingSpiAbstractSelfTest.java     |  145 +-
 .../query/h2/opt/GridH2TableSelfTest.java       |   10 +-
 .../h2/sql/AbstractH2CompareQueryTest.java      |  165 +-
 .../query/h2/sql/GridQueryParsingTest.java      |   28 +-
 .../H2CompareBigQueryDistributedJoinsTest.java  |   28 +
 .../query/h2/sql/H2CompareBigQueryTest.java     |  119 +-
 .../IgniteCacheQuerySelfTestSuite.java          |   27 +-
 .../IgniteCacheQuerySelfTestSuite2.java         |   10 -
 .../IgniteCacheWithIndexingTestSuite.java       |    2 +
 .../ignite/stream/kafka/KafkaStreamer.java      |    4 +-
 .../connect/IgniteSourceConnectorTest.java      |   58 +-
 .../cpp/common/include/ignite/common/utils.h    |   18 +
 modules/platforms/cpp/core-test/Makefile.am     |    1 +
 .../cpp/core-test/config/cache-query.xml        |   42 +-
 .../cpp/core-test/project/vs/core-test.vcxproj  |    3 +-
 .../project/vs/core-test.vcxproj.filters        |    5 +-
 .../cpp/core-test/src/cache_query_test.cpp      |  443 ++++-
 .../cpp/core-test/src/interop_test.cpp          |  148 ++
 .../core/include/ignite/cache/query/query_sql.h |   61 +-
 .../ignite/cache/query/query_sql_fields.h       |  111 +-
 modules/platforms/cpp/examples/README.txt       |    1 +
 .../cpp/jni/include/ignite/jni/exports.h        |    4 +
 .../platforms/cpp/jni/include/ignite/jni/java.h |   17 +-
 modules/platforms/cpp/jni/project/vs/module.def |    4 +
 modules/platforms/cpp/jni/src/exports.cpp       |   12 +
 modules/platforms/cpp/jni/src/java.cpp          |  120 +-
 modules/platforms/cpp/odbc-test/Makefile.am     |    1 +
 .../odbc-test/config/queries-test-noodbc.xml    |  103 ++
 .../cpp/odbc-test/config/queries-test.xml       |   54 +-
 .../cpp/odbc-test/project/vs/odbc-test.vcxproj  |    1 +
 .../project/vs/odbc-test.vcxproj.filters        |    3 +
 .../cpp/odbc-test/src/configuration_test.cpp    |  244 ++-
 .../cpp/odbc-test/src/queries_test.cpp          |  285 ++-
 modules/platforms/cpp/odbc/Makefile.am          |    1 +
 modules/platforms/cpp/odbc/include/Makefile.am  |    1 +
 .../cpp/odbc/include/ignite/odbc/common_types.h |    3 +
 .../include/ignite/odbc/config/configuration.h  |  182 +-
 .../cpp/odbc/include/ignite/odbc/connection.h   |   54 +-
 .../cpp/odbc/include/ignite/odbc/message.h      |   35 +-
 .../cpp/odbc/include/ignite/odbc/parser.h       |    3 -
 .../odbc/include/ignite/odbc/protocol_version.h |  172 ++
 .../platforms/cpp/odbc/project/vs/odbc.vcxproj  |    2 +
 .../cpp/odbc/project/vs/odbc.vcxproj.filters    |    6 +
 .../cpp/odbc/src/config/configuration.cpp       |  273 +--
 modules/platforms/cpp/odbc/src/connection.cpp   |   70 +-
 .../odbc/src/diagnostic/diagnostic_record.cpp   |    6 +
 modules/platforms/cpp/odbc/src/odbc.cpp         |   27 +-
 .../platforms/cpp/odbc/src/protocol_version.cpp |  134 ++
 .../Apache.Ignite.AspNet.csproj                 |   73 +
 .../Apache.Ignite.AspNet.nuspec                 |   57 +
 .../Apache.Ignite.AspNet.ruleset                |    9 +
 .../Apache.Ignite.AspNet.snk                    |  Bin 0 -> 596 bytes
 .../IgniteOutputCacheProvider.cs                |  220 +++
 .../Apache.Ignite.AspNet/IgniteWebUtils.cs      |   44 +
 .../dotnet/Apache.Ignite.AspNet/Package-Info.cs |   26 +
 .../Properties/AssemblyInfo.cs                  |   39 +
 .../Properties/AssemblyInfo.cs                  |    2 +-
 .../Apache.Ignite.Core.Tests.NuGet.csproj       |   14 +
 .../AspNetTest.cs                               |   73 +
 .../Properties/AssemblyInfo.cs                  |    2 +-
 .../SchemaTest.cs                               |   62 +
 .../install-package.ps1                         |   21 +-
 .../packages.config                             |    2 +
 .../Properties/AssemblyInfo.cs                  |    2 +-
 .../Apache.Ignite.Core.Tests.csproj             |   19 +-
 .../AspNet/IgniteOutputCacheProviderTest.cs     |  172 ++
 .../Binary/BinarySelfTest.cs                    |  164 +-
 .../Binary/BinaryStringTest.cs                  |  120 ++
 .../Cache/Affinity/AffinityFieldTest.cs         |  199 +++
 .../Affinity/AffinityFunctionSpringTest.cs      |    2 +-
 .../Cache/Affinity/AffinityFunctionTest.cs      |  485 ++++++
 .../Cache/Affinity/AffinityTest.cs              |  138 ++
 .../Cache/CacheAffinityFieldTest.cs             |  199 ---
 .../Cache/CacheAffinityTest.cs                  |  139 --
 .../Cache/CacheConfigurationTest.cs             |  134 +-
 .../Cache/Query/CacheLinqTest.cs                |  280 ++-
 .../Cache/Query/CacheQueriesTest.cs             |  257 +--
 .../Continuous/ContinuousQueryAbstractTest.cs   |   18 +-
 .../Cache/Store/CacheStoreTest.cs               |   11 +-
 .../Compute/AbstractTaskTest.cs                 |    9 +
 .../Compute/BinarizableTaskTest.cs              |   13 +-
 .../Compute/ComputeApiTest.cs                   |  110 +-
 .../Compute/FailoverTaskSelfTest.cs             |    2 +-
 .../Compute/IgniteExceptionTaskSelfTest.cs      |   18 +-
 .../Compute/ResourceTaskTest.cs                 |    8 +-
 .../Compute/TaskAdapterTest.cs                  |   16 +-
 .../Compute/TaskResultTest.cs                   |   10 +-
 .../Config/Cache/Affinity/affinity-function.xml |    4 +-
 .../Config/cache-query-continuous.xml           |    1 +
 .../native-client-test-cache-affinity.xml       |    2 +-
 .../ConsoleRedirectTest.cs                      |  177 ++
 .../Apache.Ignite.Core.Tests/EventsTest.cs      |    4 +-
 .../Examples/Example.cs                         |    8 +-
 .../Examples/ExamplesTest.cs                    |   46 +-
 .../Examples/PathUtil.cs                        |   10 +-
 .../Examples/ProjectFilesTest.cs                |    2 +-
 .../Apache.Ignite.Core.Tests/ExceptionsTest.cs  |   81 +-
 .../IgniteConfigurationSectionTest.cs           |   32 +
 .../IgniteConfigurationSerializerTest.cs        |   21 +
 .../IgniteConfigurationTest.cs                  |   12 +-
 .../IgniteStartStopTest.cs                      |    3 +-
 .../Apache.Ignite.Core.Tests/LifecycleTest.cs   |    9 +
 .../Apache.Ignite.Core.Tests/MessagingTest.cs   |   16 +-
 .../Properties/AssemblyInfo.cs                  |    2 +-
 .../Apache.Ignite.Core.Tests/ReconnectTest.cs   |   13 +
 .../Services/ServiceProxyTest.cs                |    6 +-
 .../Services/ServicesTest.cs                    |   26 +-
 .../Apache.Ignite.Core.Tests/TestAppConfig.cs   |  100 ++
 .../Apache.Ignite.Core.Tests/TestRunner.cs      |   46 +-
 .../Apache.Ignite.Core.Tests/TestUtils.cs       |   15 +-
 .../dotnet/Apache.Ignite.Core.Tests/app.config  |    2 +-
 .../Apache.Ignite.Core.Tests/custom_app.config  |   34 +
 .../Apache.Ignite.Core.Schema.nuspec            |   53 +
 .../Apache.Ignite.Core.csproj                   |   19 +-
 .../Apache.Ignite.Core.nuspec                   |    2 +-
 .../Binary/BinaryReflectiveSerializer.cs        |  193 +-
 .../Cache/Configuration/CacheConfiguration.cs   |   18 +-
 .../Cache/Query/SqlFieldsQuery.cs               |   27 +-
 .../Apache.Ignite.Core/Cache/Query/SqlQuery.cs  |   13 +
 .../Apache.Ignite.Core/Cluster/IClusterGroup.cs |    6 +
 .../Apache.Ignite.Core/Common/JavaException.cs  |   65 +
 .../Configuration/AtomicConfiguration.cs        |    9 +
 .../Configuration/Package-Info.cs               |   26 +
 .../Discovery/Package-Info.cs                   |   26 +
 .../Discovery/Tcp/Multicast/Package-Info.cs     |   26 +
 .../Multicast/TcpDiscoveryMulticastIpFinder.cs  |    7 +
 .../Discovery/Tcp/Package-Info.cs               |   26 +
 .../Discovery/Tcp/Static/Package-Info.cs        |   26 +
 .../Apache.Ignite.Core/Events/EventBase.cs      |    2 +-
 .../dotnet/Apache.Ignite.Core/IIgnite.cs        |   25 +
 .../Apache.Ignite.Core/IgniteConfiguration.cs   |    2 +
 .../IgniteConfigurationSection.xsd              |    9 +-
 .../dotnet/Apache.Ignite.Core/Ignition.cs       |   91 +-
 .../Impl/Binary/BinarizableSerializer.cs        |   22 +-
 .../Impl/Binary/BinaryFullTypeDescriptor.cs     |    8 +-
 .../Impl/Binary/BinaryReader.cs                 |   38 +-
 .../Impl/Binary/BinaryReaderExtensions.cs       |    2 +-
 .../Impl/Binary/BinaryReflectiveActions.cs      |   10 +-
 .../BinaryReflectiveSerializerInternal.cs       |  169 ++
 .../Binary/BinarySurrogateTypeDescriptor.cs     |    4 +-
 .../Impl/Binary/BinarySystemTypeSerializer.cs   |   20 +-
 .../Impl/Binary/BinaryUtils.cs                  |  180 +-
 .../Impl/Binary/BinaryWriter.cs                 |    2 +-
 .../Impl/Binary/DateTimeSerializer.cs           |   48 +
 .../Impl/Binary/IBinarySerializerInternal.cs    |   42 +
 .../Impl/Binary/IBinarySystemTypeSerializer.cs  |   34 -
 .../Impl/Binary/IBinaryTypeDescriptor.cs        |    2 +-
 .../Impl/Binary/Io/BinaryHeapStream.cs          |    2 +-
 .../Impl/Binary/Io/BinaryStreamBase.cs          |   14 -
 .../Impl/Binary/Marshaller.cs                   |   77 +-
 .../Impl/Binary/SerializableSerializer.cs       |   48 +
 .../Impl/Binary/UserSerializerProxy.cs          |   68 +
 .../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs  |    6 +-
 .../Impl/Cache/Store/CacheStore.cs              |    4 +-
 .../Impl/Cluster/ClusterGroupImpl.cs            |    6 +
 .../Impl/Common/DelegateConverter.cs            |   44 +
 .../Impl/Compute/ComputeTaskHolder.cs           |    3 +-
 .../Apache.Ignite.Core/Impl/ExceptionUtils.cs   |   31 +-
 .../dotnet/Apache.Ignite.Core/Impl/Ignite.cs    |   48 +-
 .../Apache.Ignite.Core/Impl/IgniteProxy.cs      |   43 +-
 .../Apache.Ignite.Core/Impl/IgniteUtils.cs      |   47 +-
 .../Impl/LifecycleBeanHolder.cs                 |    2 +-
 .../Impl/Memory/PlatformMemoryStream.cs         |    3 +-
 .../Apache.Ignite.Core/Impl/NativeMethods.cs    |    6 +
 .../Impl/Services/ServiceProxyInvoker.cs        |   14 +-
 .../Impl/Services/Services.cs                   |   17 +-
 .../Impl/Unmanaged/IgniteJniNativeMethods.cs    |    9 +
 .../Impl/Unmanaged/UnmanagedCallbacks.cs        |   94 +-
 .../Impl/Unmanaged/UnmanagedUtils.cs            |   23 +
 .../Apache.Ignite.Core/Interop/Package-Info.cs  |   26 +
 .../Lifecycle/ClientReconnectEventArgs.cs       |   47 +
 .../Properties/AssemblyInfo.cs                  |    4 +-
 .../Transactions/TransactionConfiguration.cs    |   12 +
 .../Apache.Ignite.Linq.csproj                   |    4 +-
 .../Apache.Ignite.Linq.nuspec                   |    6 +-
 .../Apache.Ignite.Linq/CacheExtensions.cs       |   24 +-
 .../dotnet/Apache.Ignite.Linq/CompiledQuery.cs  |    1 +
 .../dotnet/Apache.Ignite.Linq/CompiledQuery2.cs |  257 +++
 .../Apache.Ignite.Linq/Impl/AliasDictionary.cs  |   74 +-
 .../Impl/CacheFieldsQueryExecutor.cs            |  163 +-
 .../Impl/CacheQueryExpressionVisitor.cs         |   19 +-
 .../Impl/CacheQueryModelVisitor.cs              |   21 +-
 .../Apache.Ignite.Linq/Impl/CacheQueryable.cs   |   10 +-
 .../Impl/CacheQueryableBase.cs                  |   29 +-
 .../Apache.Ignite.Linq/Impl/ExpressionWalker.cs |   44 +-
 .../Apache.Ignite.Linq/Impl/ICacheQueryProxy.cs |   40 -
 .../Impl/ICacheQueryableInternal.cs             |   14 +-
 .../dotnet/Apache.Ignite.Linq/Package-Info.cs   |   26 +
 .../Properties/AssemblyInfo.cs                  |    2 +-
 .../dotnet/Apache.Ignite.Linq/QueryOptions.cs   |   91 +
 modules/platforms/dotnet/Apache.Ignite.dxg      |    4 +-
 modules/platforms/dotnet/Apache.Ignite.sln      |   15 +-
 .../dotnet/Apache.Ignite.sln.DotSettings        |    7 +-
 .../dotnet/Apache.Ignite/Config/Configurator.cs |   11 +-
 .../Apache.Ignite/Properties/AssemblyInfo.cs    |    2 +-
 .../dotnet/examples/Apache.Ignite.Examples.sln  |    8 -
 .../examples/Apache.Ignite.Examples/App.config  |   33 +-
 .../Compute/ClosureExample.cs                   |    4 +-
 .../Compute/TaskExample.cs                      |    4 +-
 .../Datagrid/ContinuousQueryExample.cs          |    4 +-
 .../Datagrid/DataStreamerExample.cs             |    4 +-
 .../Datagrid/LinqExample.cs                     |    4 +-
 .../Datagrid/PutGetExample.cs                   |    4 +-
 .../Datagrid/QueryExample.cs                    |    4 +-
 .../Datagrid/StoreExample.cs                    |    4 +-
 .../Datagrid/TransactionExample.cs              |    4 +-
 .../Events/EventsExample.cs                     |    6 +-
 .../Messaging/MessagingExample.cs               |    4 +-
 .../Misc/LifecycleExample.cs                    |   13 +-
 .../Properties/AssemblyInfo.cs                  |    2 +-
 .../Services/ServicesExample.cs                 |    4 +-
 .../Properties/AssemblyInfo.cs                  |    2 +-
 .../dotnet/examples/Config/examples-config.xml  |   98 --
 .../http/jetty/GridJettyRestHandler.java        |    5 +
 .../processors/schedule/ScheduleFutureImpl.java |    7 +-
 .../schedule/GridScheduleSelfTest.java          |   33 +-
 .../parser/dialect/DatabaseMetadataDialect.java |   18 +
 .../parser/dialect/JdbcMetadataDialect.java     |    5 +-
 .../parser/dialect/OracleMetadataDialect.java   |    5 +-
 .../ignite/schema/generator/CodeGenerator.java  |   23 +-
 .../schema/parser/DatabaseMetadataParser.java   |    4 +-
 .../ignite/schema/ui/SchemaImportApp.java       |    3 +-
 .../schema/test/AbstractSchemaImportTest.java   |   27 +-
 .../test/generator/CodeGeneratorTest.java       |   28 +-
 .../schema/test/generator/XmlGeneratorTest.java |   22 +-
 .../ignite/schema/test/model/CacheConfig.txt    |  409 +++++
 .../schema/test/model/ignite-type-metadata.xml  |   50 +-
 .../test/parser/DbMetadataParserTest.java       |    6 +-
 .../apache/ignite/logger/slf4j/Slf4jLogger.java |    2 +-
 .../org/apache/ignite/spark/IgniteContext.scala |    8 +-
 .../org/apache/ignite/spark/IgniteRDD.scala     |   10 +-
 .../apache/ignite/spark/JavaIgniteContext.scala |    2 +-
 .../org/apache/ignite/spark/JavaIgniteRDD.scala |   12 +-
 .../ignite/spark/impl/IgniteAbstractRDD.scala   |    2 +-
 .../apache/ignite/spark/impl/IgniteSqlRDD.scala |    2 +-
 .../spark/JavaEmbeddedIgniteRDDSelfTest.java    |   19 +-
 .../org/apache/ignite/spark/IgniteRDDSpec.scala |   38 +-
 modules/spring/pom.xml                          |    7 -
 .../org/apache/ignite/IgniteSpringBean.java     |  143 +-
 .../GridResourceSpringBeanInjector.java         |   39 +-
 .../jdbc/CacheJdbcPojoStoreFactorySelfTest.java |   11 +-
 .../ignite/internal/IgniteSpringBeanTest.java   |   55 +
 .../GridSpringResourceInjectionSelfTest.java    |  311 +++-
 .../spring-resource-with-duplicate-beans.xml    |   30 +
 .../processors/resource/spring-resource.xml     |    2 +-
 .../org/apache/ignite/spring-injection-test.xml |    2 +-
 .../testsuites/IgniteSpringTestSuite.java       |    2 +
 .../commands/alert/VisorAlertCommand.scala      |   43 +-
 .../commands/cache/VisorCacheCommand.scala      |   16 +-
 .../cache/websession/WebSessionFilter.java      |   11 +-
 .../ignite/cache/websession/WebSessionV2.java   |   10 +-
 .../internal/websession/WebSessionSelfTest.java |    8 +-
 modules/yardstick/config/queries.sql            |    1 +
 .../ignite/yardstick/IgniteBenchmarkUtils.java  |   71 +-
 .../IgniteSqlQueryDistributedJoinBenchmark.java |  166 ++
 ...lQueryDistributedJoinBroadcastBenchmark.java |   28 +
 .../IgniteCacheRandomOperationBenchmark.java    |   71 +-
 parent/pom.xml                                  |   25 +-
 492 files changed, 28413 insertions(+), 5475 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/1640e66b/modules/core/src/main/java/org/apache/ignite/internal/visor/util/VisorTaskUtils.java
----------------------------------------------------------------------


[06/50] [abbrv] ignite git commit: IGNITE-3706 Added query duration, scan with filter on SQL screen.

Posted by an...@apache.org.
IGNITE-3706  Added query duration, scan with filter on SQL screen.


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

Branch: refs/heads/ignite-3629
Commit: 0a1fa244e2f3a17b2962b1e6e8a7e6a01c0a090e
Parents: 9e45dee
Author: Andrey Novikov <an...@apache.org>
Authored: Wed Aug 24 14:54:23 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Wed Aug 24 14:54:23 2016 +0700

----------------------------------------------------------------------
 modules/web-console/DEVNOTES.txt                |   4 +-
 modules/web-console/backend/app/agent.js        |  61 +--
 modules/web-console/backend/app/browser.js      |  36 +-
 modules/web-console/frontend/app/app.js         |   2 +
 .../frontend/app/filters/duration.filter.js     |  38 ++
 .../frontend/app/modules/agent/agent.module.js  |  43 +-
 .../app/modules/sql/scan-filter-input.jade      |  39 ++
 .../modules/sql/scan-filter-input.service.js    |  52 ++
 .../frontend/app/modules/sql/sql.controller.js  | 482 +++++++++++--------
 .../frontend/app/modules/sql/sql.module.js      |   2 +
 .../frontend/gulpfile.babel.js/paths.js         |   3 +-
 .../frontend/public/stylesheets/style.scss      |  74 ++-
 modules/web-console/frontend/views/sql/sql.jade |  64 ++-
 13 files changed, 546 insertions(+), 354 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/0a1fa244/modules/web-console/DEVNOTES.txt
----------------------------------------------------------------------
diff --git a/modules/web-console/DEVNOTES.txt b/modules/web-console/DEVNOTES.txt
index 0b35ab0..150041e 100644
--- a/modules/web-console/DEVNOTES.txt
+++ b/modules/web-console/DEVNOTES.txt
@@ -16,7 +16,7 @@ How to deploy locally:
   Check npm version: "npm --version".
 5. Run "npm install --no-optional" in terminal for download dependencies.
 6. Build ignite-web-agent module follow instructions from 'modules/web-agent/README.txt'.
-7. Copy ignite-web-agent-<version>.zip from target of ignite-web-agent module to 'modules/web-console/src/main/js/serve/agent_dists' folder.
+7. Copy ignite-web-agent-<version>.zip from target of ignite-web-agent module to 'modules/web-console/backend/agent_dists' folder.
 
 Steps 1 - 7 should be executed once.
 
@@ -29,6 +29,6 @@ How to run console in development mode:
    If needed run "npm install --no-optional" (if dependencies changed) and run "npm start" to start backend.
 
 3. In new terminal change directory to '$IGNITE_HOME/modules/web-console/frontend'
-  and start webpack in development mode "npm run dev" .
+  and start webpack in development mode "npm run dev".
 
 4. In browser open: http://localhost:9000

http://git-wip-us.apache.org/repos/asf/ignite/blob/0a1fa244/modules/web-console/backend/app/agent.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/app/agent.js b/modules/web-console/backend/app/agent.js
index 0f4eb9f..a1858fd 100644
--- a/modules/web-console/backend/app/agent.js
+++ b/modules/web-console/backend/app/agent.js
@@ -222,59 +222,64 @@ module.exports.factory = function(_, ws, fs, path, JSZip, socketio, settings, mo
         }
 
         /**
-         *
          * @param {Boolean} demo Is need run command on demo node.
+         * @param {String} nid Node id.
          * @param {String} cacheName Cache name.
          * @param {String} query Query.
+         * @param {Boolean} local Flag whether to execute query locally.
          * @param {int} pageSize Page size.
          * @returns {Promise}
          */
-        fieldsQuery(demo, cacheName, query, pageSize) {
-            const cmd = new Command(demo, 'qryfldexe')
-                .addParam('cacheName', cacheName)
-                .addParam('qry', query)
-                .addParam('pageSize', pageSize);
-
-            return this.executeRest(cmd);
-        }
-
-        /**
-         *
-         * @param {Boolean} demo Is need run command on demo node.
-         * @param {String} cacheName Cache name.
-         * @param {int} pageSize Page size.
-         * @returns {Promise}
-         */
-        scan(demo, cacheName, pageSize) {
-            const cmd = new Command(demo, 'qryscanexe')
-                .addParam('cacheName', cacheName)
-                .addParam('pageSize', pageSize);
+        fieldsQuery(demo, nid, cacheName, query, local, pageSize) {
+            const cmd = new Command(demo, 'exe')
+                .addParam('name', 'org.apache.ignite.internal.visor.compute.VisorGatewayTask')
+                .addParam('p1', nid)
+                .addParam('p2', 'org.apache.ignite.internal.visor.query.VisorQueryTask')
+                .addParam('p3', 'org.apache.ignite.internal.visor.query.VisorQueryArg')
+                .addParam('p4', cacheName)
+                .addParam('p5', query)
+                .addParam('p6', local)
+                .addParam('p7', pageSize);
 
             return this.executeRest(cmd);
         }
 
         /**
          * @param {Boolean} demo Is need run command on demo node.
+         * @param {String} nid Node id.
          * @param {int} queryId Query Id.
          * @param {int} pageSize Page size.
          * @returns {Promise}
          */
-        queryFetch(demo, queryId, pageSize) {
-            const cmd = new Command(demo, 'qryfetch')
-                .addParam('qryId', queryId)
-                .addParam('pageSize', pageSize);
+        queryFetch(demo, nid, queryId, pageSize) {
+            const cmd = new Command(demo, 'exe')
+                .addParam('name', 'org.apache.ignite.internal.visor.compute.VisorGatewayTask')
+                .addParam('p1', nid)
+                .addParam('p2', 'org.apache.ignite.internal.visor.query.VisorQueryNextPageTask')
+                .addParam('p3', 'org.apache.ignite.lang.IgniteBiTuple')
+                .addParam('p4', 'java.lang.String')
+                .addParam('p5', 'java.lang.Integer')
+                .addParam('p6', queryId)
+                .addParam('p7', pageSize);
 
             return this.executeRest(cmd);
         }
 
         /**
          * @param {Boolean} demo Is need run command on demo node.
+         * @param {String} nid Node id.
          * @param {int} queryId Query Id.
          * @returns {Promise}
          */
-        queryClose(demo, queryId) {
-            const cmd = new Command(demo, 'qrycls')
-                .addParam('qryId', queryId);
+        queryClose(demo, nid, queryId) {
+            const cmd = new Command(demo, 'exe')
+                .addParam('name', 'org.apache.ignite.internal.visor.compute.VisorGatewayTask')
+                .addParam('p1', '')
+                .addParam('p2', 'org.apache.ignite.internal.visor.query.VisorQueryCleanupTask')
+                .addParam('p3', 'java.util.Map')
+                .addParam('p4', 'java.util.UUID')
+                .addParam('p5', 'java.util.Set')
+                .addParam('p6', `${nid}=${queryId}`);
 
             return this.executeRest(cmd);
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0a1fa244/modules/web-console/backend/app/browser.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/app/browser.js b/modules/web-console/backend/app/browser.js
index 1c5058d..3256b6a 100644
--- a/modules/web-console/backend/app/browser.js
+++ b/modules/web-console/backend/app/browser.js
@@ -90,53 +90,53 @@ module.exports.factory = (_, socketio, agentMgr, configure) => {
                 });
 
                 // Close query on node.
-                socket.on('node:query:close', (queryId, cb) => {
+                socket.on('node:query:close', (nid, queryId, cb) => {
                     agentMgr.findAgent(accountId())
-                        .then((agent) => agent.queryClose(demo, queryId))
+                        .then((agent) => agent.queryClose(demo, nid, queryId))
                         .then(() => cb())
                         .catch((err) => cb(_errorToJson(err)));
                 });
 
                 // Execute query on node and return first page to browser.
-                socket.on('node:query', (cacheName, pageSize, query, cb) => {
+                socket.on('node:query', (nid, cacheName, query, local, pageSize, cb) => {
                     agentMgr.findAgent(accountId())
-                        .then((agent) => {
-                            if (query === null)
-                                return agent.scan(demo, cacheName, pageSize);
-
-                            return agent.fieldsQuery(demo, cacheName, query, pageSize);
-                        })
+                        .then((agent) => agent.fieldsQuery(demo, nid, cacheName, query, local, pageSize))
                         .then((res) => cb(null, res))
                         .catch((err) => cb(_errorToJson(err)));
                 });
 
                 // Fetch next page for query and return result to browser.
-                socket.on('node:query:fetch', (queryId, pageSize, cb) => {
+                socket.on('node:query:fetch', (nid, queryId, pageSize, cb) => {
                     agentMgr.findAgent(accountId())
-                        .then((agent) => agent.queryFetch(demo, queryId, pageSize))
+                        .then((agent) => agent.queryFetch(demo, nid, queryId, pageSize))
                         .then((res) => cb(null, res))
                         .catch((err) => cb(_errorToJson(err)));
                 });
 
                 // Execute query on node and return full result to browser.
-                socket.on('node:query:getAll', (cacheName, query, cb) => {
+                socket.on('node:query:getAll', (nid, cacheName, query, local, cb) => {
                     // Set page size for query.
                     const pageSize = 1024;
 
                     agentMgr.findAgent(accountId())
                         .then((agent) => {
-                            const firstPage = query === null ? agent.scan(demo, cacheName, pageSize)
-                                : agent.fieldsQuery(demo, cacheName, query, pageSize);
+                            const firstPage = agent.fieldsQuery(demo, nid, cacheName, query, local, pageSize)
+                                .then(({result}) => {
+                                    if (result.key)
+                                        return Promise.reject(result.key);
+
+                                    return result.value;
+                                });
 
                             const fetchResult = (acc) => {
-                                if (acc.last)
+                                if (!acc.hasMore)
                                     return acc;
 
-                                return agent.queryFetch(demo, acc.queryId, pageSize)
+                                return agent.queryFetch(demo, acc.responseNodeId, acc.queryId, pageSize)
                                     .then((res) => {
-                                        acc.items = acc.items.concat(res.items);
+                                        acc.rows = acc.rows.concat(res.rows);
 
-                                        acc.last = res.last;
+                                        acc.hasMore = res.hasMore;
 
                                         return fetchResult(acc);
                                     });

http://git-wip-us.apache.org/repos/asf/ignite/blob/0a1fa244/modules/web-console/frontend/app/app.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/app.js b/modules/web-console/frontend/app/app.js
index 89381aa..7340d7b 100644
--- a/modules/web-console/frontend/app/app.js
+++ b/modules/web-console/frontend/app/app.js
@@ -89,6 +89,7 @@ import UnsavedChangesGuard from './services/UnsavedChangesGuard.service';
 import byName from './filters/byName.filter';
 import domainsValidation from './filters/domainsValidation.filter';
 import hasPojo from './filters/hasPojo.filter';
+import duration from './filters/duration.filter';
 
 // Generators
 import $generatorCommon from 'generator/generator-common';
@@ -215,6 +216,7 @@ angular
 .filter(...hasPojo)
 .filter(...domainsValidation)
 .filter(...byName)
+.filter(...duration)
 .config(['$stateProvider', '$locationProvider', '$urlRouterProvider', ($stateProvider, $locationProvider, $urlRouterProvider) => {
     // Set up the states.
     $stateProvider

http://git-wip-us.apache.org/repos/asf/ignite/blob/0a1fa244/modules/web-console/frontend/app/filters/duration.filter.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/filters/duration.filter.js b/modules/web-console/frontend/app/filters/duration.filter.js
new file mode 100644
index 0000000..deeedd7
--- /dev/null
+++ b/modules/web-console/frontend/app/filters/duration.filter.js
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+export default ['duration', [() => {
+    /**
+     * @param {Number} t Time in ms.
+     */
+    return (t) => {
+        const a = (i, suffix) => i && i !== '00' ? i + suffix + ' ' : '';
+
+        const cd = 24 * 60 * 60 * 1000;
+        const ch = 60 * 60 * 1000;
+        const cm = 60 * 1000;
+        const cs = 1000;
+
+        const d = Math.floor(t / cd);
+        const h = Math.floor((t - d * cd) / ch);
+        const m = Math.floor((t - d * cd - h * ch) / cm);
+        const s = Math.floor((t - d * cd - h * ch - m * cm) / cs);
+        const ms = t % 1000;
+
+        return a(d, 'd') + a(h, 'h') + a(m, 'm') + a(s, 's') + (t < cm ? ms + 'ms' : '');
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/0a1fa244/modules/web-console/frontend/app/modules/agent/agent.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/agent/agent.module.js b/modules/web-console/frontend/app/modules/agent/agent.module.js
index ca95166..f65781e 100644
--- a/modules/web-console/frontend/app/modules/agent/agent.module.js
+++ b/modules/web-console/frontend/app/modules/agent/agent.module.js
@@ -18,6 +18,8 @@
 import angular from 'angular';
 import io from 'socket.io-client'; // eslint-disable-line no-unused-vars
 
+const maskNull = (val) => _.isEmpty(val) ? 'null' : val;
+
 class IgniteAgentMonitor {
     constructor(socketFactory, $root, $q, $state, $modal, Messages) {
         this._scope = $root.$new();
@@ -260,47 +262,60 @@ class IgniteAgentMonitor {
     }
 
     /**
+     * @param {String} nid Node id.
      * @param {int} [queryId]
      * @returns {Promise}
      */
-    queryClose(queryId) {
-        return this._rest('node:query:close', queryId);
+    queryClose(nid, queryId) {
+        return this._rest('node:query:close', nid, queryId);
     }
 
     /**
+     * @param {String} nid Node id.
      * @param {String} cacheName Cache name.
-     * @param {int} pageSize
      * @param {String} [query] Query if null then scan query.
+     * @param {Boolean} local Flag whether to execute query locally.
+     * @param {int} pageSize
      * @returns {Promise}
      */
-    query(cacheName, pageSize, query) {
-        return this._rest('node:query', _.isEmpty(cacheName) ? null : cacheName, pageSize, query);
+    query(nid, cacheName, query, local, pageSize) {
+        return this._rest('node:query', nid, maskNull(cacheName), maskNull(query), local, pageSize)
+            .then(({result}) => {
+                if (_.isEmpty(result.key))
+                    return result.value;
+
+                return Promise.reject(result.key);
+            });
     }
 
     /**
+     * @param {String} nid Node id.
      * @param {String} cacheName Cache name.
      * @param {String} [query] Query if null then scan query.
+     * @param {Boolean} local Flag whether to execute query locally.
      * @returns {Promise}
      */
-    queryGetAll(cacheName, query) {
-        return this._rest('node:query:getAll', _.isEmpty(cacheName) ? null : cacheName, query);
+    queryGetAll(nid, cacheName, query, local) {
+        return this._rest('node:query:getAll', nid, maskNull(cacheName), maskNull(query), local);
     }
 
     /**
-     * @param {String} [cacheName] Cache name.
+     * @param {String} nid Node id.
+     * @param {int} queryId
+     * @param {int} pageSize
      * @returns {Promise}
      */
-    metadata(cacheName) {
-        return this._rest('node:cache:metadata', _.isEmpty(cacheName) ? null : cacheName);
+    next(nid, queryId, pageSize) {
+        return this._rest('node:query:fetch', nid, queryId, pageSize)
+            .then(({result}) => result);
     }
 
     /**
-     * @param {int} queryId
-     * @param {int} pageSize
+     * @param {String} [cacheName] Cache name.
      * @returns {Promise}
      */
-    next(queryId, pageSize) {
-        return this._rest('node:query:fetch', queryId, pageSize);
+    metadata(cacheName) {
+        return this._rest('node:cache:metadata', maskNull(cacheName));
     }
 
     stopWatch() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/0a1fa244/modules/web-console/frontend/app/modules/sql/scan-filter-input.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/scan-filter-input.jade b/modules/web-console/frontend/app/modules/sql/scan-filter-input.jade
new file mode 100644
index 0000000..addc5f3
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/sql/scan-filter-input.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.
+
+include ../../helpers/jade/mixins.jade
+
+.modal(tabindex='-1' role='dialog')
+    .modal-dialog
+        .modal-content
+            .modal-header
+                button.close(ng-click='$hide()') &times;
+                h4.modal-title Scan filter
+            form.form-horizontal.modal-body.row(name='ui.inputForm' novalidate)
+                .settings-row
+                    .col-sm-2
+                        label.required.labelFormField Filter:&nbsp;
+                    .col-sm-10
+                        .input-tip
+                            +ignite-form-field-input('"filter"', 'ui.filter', false, 'true', 'Enter filter')(
+                                data-ignite-form-field-input-autofocus='true'
+                                ignite-on-enter='form.$valid && ok()'
+                            )
+                .settings-row
+                    +checkbox('Case sensitive search', 'ui.caseSensitive', '"caseSensitive"', 'Select this checkbox for case sensitive search')
+            .modal-footer
+                button.btn.btn-default(id='btn-cancel' ng-click='$hide()') Cancel
+                button.btn.btn-primary(id='btn-scan' ng-disabled='ui.inputForm.$invalid' ng-click='ok()') Scan

http://git-wip-us.apache.org/repos/asf/ignite/blob/0a1fa244/modules/web-console/frontend/app/modules/sql/scan-filter-input.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/scan-filter-input.service.js b/modules/web-console/frontend/app/modules/sql/scan-filter-input.service.js
new file mode 100644
index 0000000..d460f04
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/sql/scan-filter-input.service.js
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+class ScanFilter {
+    static $inject = ['$rootScope', '$q', '$modal'];
+
+    constructor($root, $q, $modal) {
+        this.deferred = null;
+        this.$q = $q;
+
+        const scope = $root.$new();
+
+        scope.ui = {};
+
+        scope.ok = () => {
+            this.deferred.resolve({filter: scope.ui.filter, caseSensitive: !!scope.ui.caseSensitive});
+
+            this.modal.hide();
+        };
+
+        scope.$hide = () => {
+            this.modal.hide();
+
+            this.deferred.reject();
+        };
+
+        this.modal = $modal({templateUrl: '/scan-filter-input.html', scope, placement: 'center', show: false});
+    }
+
+    open() {
+        this.deferred = this.$q.defer();
+
+        this.modal.$promise.then(this.modal.show);
+
+        return this.deferred.promise;
+    }
+}
+export default ScanFilter;

http://git-wip-us.apache.org/repos/asf/ignite/blob/0a1fa244/modules/web-console/frontend/app/modules/sql/sql.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/sql.controller.js b/modules/web-console/frontend/app/modules/sql/sql.controller.js
index 76db15f..3162224 100644
--- a/modules/web-console/frontend/app/modules/sql/sql.controller.js
+++ b/modules/web-console/frontend/app/modules/sql/sql.controller.js
@@ -15,9 +15,92 @@
  * limitations under the License.
  */
 
+// Time line X axis descriptor.
+const TIME_LINE = {value: -1, type: 'java.sql.Date', label: 'TIME_LINE'};
+
+// Row index X axis descriptor.
+const ROW_IDX = {value: -2, type: 'java.lang.Integer', label: 'ROW_IDX'};
+
+/** Prefix for node local key for SCAN near queries. */
+const SCAN_NEAR_CACHE = 'VISOR_SCAN_NEAR_CACHE';
+
+/** Prefix for node local key for SCAN near queries. */
+const SCAN_CACHE_WITH_FILTER = 'VISOR_SCAN_CACHE_WITH_FILTER';
+
+/** Prefix for node local key for SCAN near queries. */
+const SCAN_CACHE_WITH_FILTER_CASE_SENSITIVE = 'VISOR_SCAN_CACHE_WITH_FILTER_CASE_SENSITIVE';
+
+const _fullColName = (col) => {
+    const res = [];
+
+    if (col.schemaName)
+        res.push(col.schemaName);
+
+    if (col.typeName)
+        res.push(col.typeName);
+
+    res.push(col.fieldName);
+
+    return res.join('.');
+};
+
+class Paragraph {
+    constructor($timeout, Notebook, paragraph) {
+        this.$timeout = $timeout;
+        this.Notebook = Notebook;
+
+        _.assign(this, paragraph);
+    }
+
+    resultType() {
+        if (_.isNil(this.queryArgs))
+            return null;
+
+        if (!_.isEmpty(this.errMsg))
+            return 'error';
+
+        if (_.isEmpty(this.rows))
+            return 'empty';
+
+        return this.result === 'table' ? 'table' : 'chart';
+    }
+
+    nonRefresh() {
+        return _.isNil(this.rate) || _.isNil(this.rate.stopTime);
+    }
+
+    table() {
+        return this.result === 'table';
+    }
+
+    chart() {
+        return this.result !== 'table' && this.result !== 'none';
+    }
+
+    nonEmpty() {
+        return this.rows && this.rows.length > 0;
+    }
+
+    queryExecuted() {
+        return this.queryArgs && this.queryArgs.query && !this.queryArgs.query.startsWith('EXPLAIN ');
+    }
+
+    timeLineSupported() {
+        return this.result !== 'pie';
+    }
+
+    chartColumnsConfigured() {
+        return !_.isEmpty(this.chartKeyCols) && !_.isEmpty(this.chartValCols);
+    }
+
+    chartTimeLineEnabled() {
+        return !_.isEmpty(this.chartKeyCols) && _.eq(this.chartKeyCols[0], TIME_LINE);
+    }
+}
+
 // Controller for SQL notebook screen.
-export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', '$animate', '$location', '$anchorScroll', '$state', '$modal', '$popover', 'IgniteLoading', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteAgentMonitor', 'IgniteChartColors', 'IgniteNotebook', 'uiGridConstants', 'uiGridExporterConstants',
-    function($root, $scope, $http, $q, $timeout, $interval, $animate, $location, $anchorScroll, $state, $modal, $popover, Loading, LegacyUtils, Messages, Confirm, agentMonitor, IgniteChartColors, Notebook, uiGridConstants, uiGridExporterConstants) {
+export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', '$animate', '$location', '$anchorScroll', '$state', '$modal', '$popover', 'IgniteLoading', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteAgentMonitor', 'IgniteChartColors', 'IgniteNotebook', 'IgniteScanFilterInput', 'uiGridConstants', 'uiGridExporterConstants',
+    function($root, $scope, $http, $q, $timeout, $interval, $animate, $location, $anchorScroll, $state, $modal, $popover, Loading, LegacyUtils, Messages, Confirm, agentMonitor, IgniteChartColors, Notebook, ScanFilterInput, uiGridConstants, uiGridExporterConstants) {
         let stopTopology = null;
 
         const _tryStopRefresh = function(paragraph) {
@@ -76,39 +159,6 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
 
         $scope.maskCacheName = (cacheName) => _.isEmpty(cacheName) ? '<default>' : cacheName;
 
-        // Time line X axis descriptor.
-        const TIME_LINE = {value: -1, type: 'java.sql.Date', label: 'TIME_LINE'};
-
-        // Row index X axis descriptor.
-        const ROW_IDX = {value: -2, type: 'java.lang.Integer', label: 'ROW_IDX'};
-
-        const EXTENDED_PARAGRAPH = {
-            table() {
-                return this.result === 'table';
-            },
-            chart() {
-                return this.result !== 'table' && this.result !== 'none';
-            },
-            nonEmpty() {
-                return this.rows && this.rows.length > 0;
-            },
-            queryExecuted() {
-                return this.queryArgs && this.queryArgs.query && !this.queryArgs.query.startsWith('EXPLAIN ');
-            },
-            refreshExecuting() {
-                return this.rate && this.rate.stopTime;
-            },
-            timeLineSupported() {
-                return this.result !== 'pie';
-            },
-            chartColumnsConfigured() {
-                return !_.isEmpty(this.chartKeyCols) && !_.isEmpty(this.chartValCols);
-            },
-            chartTimeLineEnabled() {
-                return !_.isEmpty(this.chartKeyCols) && _.eq(this.chartKeyCols[0], TIME_LINE);
-            }
-        };
-
         // We need max 1800 items to hold history for 30 mins in case of refresh every second.
         const HISTORY_LENGTH = 1800;
 
@@ -653,65 +703,6 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
 
         let paragraphId = 0;
 
-        const _fullColName = function(col) {
-            const res = [];
-
-            if (col.schemaName)
-                res.push(col.schemaName);
-
-            if (col.typeName)
-                res.push(col.typeName);
-
-            res.push(col.fieldName);
-
-            return res.join('.');
-        };
-
-        function enhanceParagraph(paragraph) {
-            Object.assign(paragraph, EXTENDED_PARAGRAPH);
-
-            Object.defineProperty(paragraph, 'gridOptions', { value: {
-                enableGridMenu: false,
-                enableColumnMenus: false,
-                flatEntityAccess: true,
-                fastWatch: true,
-                updateColumns(cols) {
-                    this.columnDefs = _.map(cols, (col) => {
-                        return {
-                            displayName: col.fieldName,
-                            headerTooltip: _fullColName(col),
-                            field: col.field,
-                            minWidth: 50,
-                            cellClass: 'cell-left'
-                        };
-                    });
-
-                    $timeout(() => this.api.core.notifyDataChange(uiGridConstants.dataChange.COLUMN));
-                },
-                updateRows(rows) {
-                    const sizeChanged = this.data.length !== rows.length;
-
-                    this.data = rows;
-
-                    if (sizeChanged) {
-                        const height = Math.min(rows.length, 15) * 30 + 47;
-
-                        // Remove header height.
-                        this.api.grid.element.css('height', height + 'px');
-
-                        $timeout(() => this.api.core.handleWindowResize());
-                    }
-                },
-                onRegisterApi(api) {
-                    $animate.enabled(api.grid.element, false);
-
-                    this.api = api;
-                }
-            }});
-
-            Object.defineProperty(paragraph, 'chartHistory', {value: []});
-        }
-
         $scope.aceInit = function(paragraph) {
             return function(editor) {
                 editor.setAutoScrollEditorIntoView(true);
@@ -732,89 +723,142 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             };
         };
 
-        const _setActiveCache = function() {
-            if ($scope.caches.length > 0) {
-                _.forEach($scope.notebook.paragraphs, (paragraph) => {
-                    if (!_.find($scope.caches, {name: paragraph.cacheName}))
-                        paragraph.cacheName = $scope.caches[0].name;
-                });
-            }
-        };
-
-        const _updateTopology = () =>
+        /**
+         * Update caches list.
+         * @private
+         */
+        const _refreshFn = () =>
             agentMonitor.topology()
                 .then((clusters) => {
-                    agentMonitor.checkModal();
+                    $scope.caches = _.sortBy(_.reduce(clusters, (items, cluster) => {
+                        _.forEach(cluster.caches, (cache) => {
+                            let item = _.find(items, {name: cache.name});
 
-                    const caches = _.flattenDeep(clusters.map((cluster) => cluster.caches));
+                            if (_.isNil(item)) {
+                                cache.label = $scope.maskCacheName(cache.name);
 
-                    $scope.caches = _.sortBy(_.map(_.uniqBy(_.reject(caches, {mode: 'LOCAL'}), 'name'), (cache) => {
-                        cache.label = $scope.maskCacheName(cache.name);
+                                cache.nodeIds = [];
 
-                        return cache;
-                    }), 'label');
+                                items.push(item = cache);
+                            }
+
+                            item.nodeIds.push(cluster.nodeId);
+                        });
+
+                        return items;
+                    }, []), 'label');
+
+                    if (_.isEmpty($scope.caches))
+                        return;
+
+                    // Reset to first cache in case of stopped selected.
+                    const cacheNames = _.map($scope.caches, (cache) => cache.name);
 
-                    _setActiveCache();
+                    _.forEach($scope.notebook.paragraphs, (paragraph) => {
+                        if (!_.includes(cacheNames, paragraph.cacheName))
+                            paragraph.cacheName = _.head(cacheNames);
+                    });
                 })
-                .catch((err) => {
-                    if (err.code === 2)
-                        return agentMonitor.showNodeError('Agent is failed to authenticate in grid. Please check agent\'s login and password.');
+                .then(() => agentMonitor.checkModal())
+                .catch((err) => agentMonitor.showNodeError(err));
+
+        const _startWatch = () =>
+            agentMonitor.startWatch({
+                state: 'base.configuration.clusters',
+                text: 'Back to Configuration',
+                goal: 'execute sql statements',
+                onDisconnect: () => {
+                    _stopTopologyRefresh();
 
-                    agentMonitor.showNodeError(err);
+                    _startWatch();
+                }
+            })
+                .then(() => Loading.start('sqlLoading'))
+                .then(_refreshFn)
+                .then(() => Loading.finish('sqlLoading'))
+                .then(() => {
+                    $root.IgniteDemoMode && _.forEach($scope.notebook.paragraphs, $scope.execute);
+
+                    stopTopology = $interval(_refreshFn, 5000, 0, false);
                 });
 
-        const _startTopologyRefresh = () => {
-            Loading.start('sqlLoading');
+        Notebook.find($state.params.noteId)
+            .then((notebook) => {
+                $scope.notebook = _.cloneDeep(notebook);
+
+                $scope.notebook_name = $scope.notebook.name;
+
+                if (!$scope.notebook.expandedParagraphs)
+                    $scope.notebook.expandedParagraphs = [];
+
+                if (!$scope.notebook.paragraphs)
+                    $scope.notebook.paragraphs = [];
+
+                $scope.notebook.paragraphs = _.map($scope.notebook.paragraphs, (paragraph) => {
+                    paragraph.id = 'paragraph-' + paragraphId++;
+
+                    const par = new Paragraph($timeout, Notebook, paragraph);
+
+                    Object.defineProperty(par, 'gridOptions', {value: {
+                        enableGridMenu: false,
+                        enableColumnMenus: false,
+                        flatEntityAccess: true,
+                        fastWatch: true,
+                        rebuildColumns() {
+                            if (_.isNil(this.api))
+                                return;
+
+                            this.columnDefs = _.reduce(par.meta, (cols, col, idx) => {
+                                if (par.columnFilter(col)) {
+                                    cols.push({
+                                        displayName: col.fieldName,
+                                        headerTooltip: _fullColName(col),
+                                        field: idx.toString(),
+                                        minWidth: 50,
+                                        cellClass: 'cell-left'
+                                    });
+                                }
 
-            agentMonitor.awaitAgent()
-                .then(_updateTopology)
-                .then(() => {
-                    if ($root.IgniteDemoMode)
-                        _.forEach($scope.notebook.paragraphs, $scope.execute);
+                                return cols;
+                            }, []);
 
-                    Loading.finish('sqlLoading');
+                            $timeout(() => this.api.core.notifyDataChange(uiGridConstants.dataChange.COLUMN));
+                        },
+                        adjustHeight() {
+                            if (_.isNil(this.api))
+                                return;
 
-                    stopTopology = $interval(_updateTopology, 5000, 0, false);
-                });
-        };
+                            this.data = par.rows;
 
-        const loadNotebook = function(notebook) {
-            $scope.notebook = _.cloneDeep(notebook);
+                            const height = Math.min(this.data.length, 15) * 30 + 47;
 
-            $scope.notebook_name = $scope.notebook.name;
+                            // Remove header height.
+                            this.api.grid.element.css('height', height + 'px');
 
-            if (!$scope.notebook.expandedParagraphs)
-                $scope.notebook.expandedParagraphs = [];
+                            $timeout(() => this.api.core.handleWindowResize());
+                        },
+                        onRegisterApi(api) {
+                            $animate.enabled(api.grid.element, false);
 
-            if (!$scope.notebook.paragraphs)
-                $scope.notebook.paragraphs = [];
+                            this.api = api;
 
-            _.forEach($scope.notebook.paragraphs, (paragraph) => {
-                paragraph.id = 'paragraph-' + paragraphId++;
+                            this.rebuildColumns();
 
-                enhanceParagraph(paragraph);
-            });
+                            this.adjustHeight();
+                        }
+                    }});
 
-            if (_.isEmpty($scope.notebook.paragraphs))
-                $scope.addParagraph();
-            else
-                $scope.rebuildScrollParagraphs();
+                    Object.defineProperty(par, 'chartHistory', {value: []});
 
-            agentMonitor.startWatch({
-                state: 'base.configuration.clusters',
-                text: 'Back to Configuration',
-                goal: 'execute sql statements',
-                onDisconnect: () => {
-                    _stopTopologyRefresh();
+                    return par;
+                });
 
-                    _startTopologyRefresh();
-                }
+                if (_.isEmpty($scope.notebook.paragraphs))
+                    $scope.addParagraph();
+                else
+                    $scope.rebuildScrollParagraphs();
             })
-            .then(_startTopologyRefresh);
-        };
-
-        Notebook.find($state.params.noteId)
-            .then(loadNotebook)
+            .then(_startWatch)
             .catch(() => {
                 $scope.notebookLoadFailed = true;
 
@@ -878,8 +922,6 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                 }
             };
 
-            enhanceParagraph(paragraph);
-
             if ($scope.caches && $scope.caches.length > 0)
                 paragraph.cacheName = $scope.caches[0].name;
 
@@ -893,9 +935,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
 
             $anchorScroll();
 
-            setTimeout(function() {
-                paragraph.ace.focus();
-            });
+            setTimeout(paragraph.ace.focus);
         };
 
         function _saveChartSettings(paragraph) {
@@ -931,8 +971,6 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
 
             if (paragraph.chart())
                 _chartApplySettings(paragraph, true);
-            else
-                $timeout(() => paragraph.gridOptions.api.core.handleWindowResize());
         };
 
         $scope.resultEq = function(paragraph, result) {
@@ -1033,25 +1071,15 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                 });
             });
 
-            const cols = [];
-
-            _.forEach(paragraph.meta, (col, idx) => {
-                if (paragraph.columnFilter(col)) {
-                    col.field = paragraph.queryArgs.query ? idx.toString() : col.fieldName;
-
-                    cols.push(col);
-                }
-            });
-
-            paragraph.gridOptions.updateColumns(cols);
+            paragraph.gridOptions.rebuildColumns();
 
-            paragraph.chartColumns = _.reduce(cols, (acc, col) => {
-                if (_notObjectType(col.fieldTypeName)) {
+            paragraph.chartColumns = _.reduce(paragraph.meta, (acc, col, idx) => {
+                if (paragraph.columnFilter(col) && _notObjectType(col.fieldTypeName)) {
                     acc.push({
                         label: col.fieldName,
                         type: col.fieldTypeName,
                         aggFx: $scope.aggregateFxs[0],
-                        value: col.field
+                        value: idx.toString()
                     });
                 }
 
@@ -1087,14 +1115,14 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
 
         /**
          * @param {Object} paragraph Query
-         * @param {{fieldsMetadata: Array, items: Array, queryId: int, last: Boolean}} res Query results.
+         * @param {{columns: Array, rows: Array, responseNodeId: String, queryId: int, hasMore: Boolean}} res Query results.
          * @private
          */
-        const _processQueryResult = function(paragraph, res) {
+        const _processQueryResult = (paragraph, res) => {
             const prevKeyCols = paragraph.chartKeyCols;
             const prevValCols = paragraph.chartValCols;
 
-            if (!_.eq(paragraph.meta, res.fieldsMetadata)) {
+            if (!_.eq(paragraph.meta, res.columns)) {
                 paragraph.meta = [];
 
                 paragraph.chartColumns = [];
@@ -1105,17 +1133,17 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                 if (!LegacyUtils.isDefined(paragraph.chartValCols))
                     paragraph.chartValCols = [];
 
-                if (res.fieldsMetadata.length <= 2) {
-                    const _key = _.find(res.fieldsMetadata, {fieldName: '_KEY'});
-                    const _val = _.find(res.fieldsMetadata, {fieldName: '_VAL'});
+                if (res.columns.length <= 2) {
+                    const _key = _.find(res.columns, {fieldName: '_KEY'});
+                    const _val = _.find(res.columns, {fieldName: '_VAL'});
 
-                    paragraph.disabledSystemColumns = (res.fieldsMetadata.length === 2 && _key && _val) ||
-                        (res.fieldsMetadata.length === 1 && (_key || _val));
+                    paragraph.disabledSystemColumns = (res.columns.length === 2 && _key && _val) ||
+                        (res.columns.length === 1 && (_key || _val));
                 }
 
                 paragraph.columnFilter = _columnFilter(paragraph);
 
-                paragraph.meta = res.fieldsMetadata;
+                paragraph.meta = res.columns;
 
                 _rebuildColumns(paragraph);
             }
@@ -1124,24 +1152,28 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
 
             paragraph.total = 0;
 
-            paragraph.queryId = res.last ? null : res.queryId;
+            paragraph.duration = res.duration;
+
+            paragraph.queryId = res.hasMore ? res.queryId : null;
+
+            paragraph.resNodeId = res.responseNodeId;
 
             delete paragraph.errMsg;
 
             // Prepare explain results for display in table.
-            if (paragraph.queryArgs.query && paragraph.queryArgs.query.startsWith('EXPLAIN') && res.items) {
+            if (paragraph.queryArgs.query && paragraph.queryArgs.query.startsWith('EXPLAIN') && res.rows) {
                 paragraph.rows = [];
 
-                res.items.forEach(function(row, i) {
-                    const line = res.items.length - 1 === i ? row[0] : row[0] + '\n';
+                res.rows.forEach((row, i) => {
+                    const line = res.rows.length - 1 === i ? row[0] : row[0] + '\n';
 
                     line.replace(/\"/g, '').split('\n').forEach((ln) => paragraph.rows.push([ln]));
                 });
             }
             else
-                paragraph.rows = res.items;
+                paragraph.rows = res.rows;
 
-            paragraph.gridOptions.updateRows(paragraph.rows);
+            paragraph.gridOptions.adjustHeight(paragraph.rows.length);
 
             const chartHistory = paragraph.chartHistory;
 
@@ -1189,12 +1221,18 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             return queryId ? agentMonitor.queryClose(queryId) : $q.when();
         };
 
+        const cacheNode = (name) => {
+            const cache = _.find($scope.caches, {name});
+
+            return cache.nodeIds[_.random(0, cache.nodeIds.length - 1)];
+        };
+
         const _executeRefresh = (paragraph) => {
             const args = paragraph.queryArgs;
 
             agentMonitor.awaitAgent()
                 .then(() => _closeOldQuery(paragraph))
-                .then(() => agentMonitor.query(args.cacheName, args.pageSize, args.query))
+                .then(() => agentMonitor.query(cacheNode(args.cacheName), args.cacheName, args.query, false, args.pageSize))
                 .then(_processQueryResult.bind(this, paragraph))
                 .catch((err) => paragraph.errMsg = err.message);
         };
@@ -1213,7 +1251,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             }
         };
 
-        $scope.execute = function(paragraph) {
+        $scope.execute = (paragraph) => {
             Notebook.save($scope.notebook)
                 .catch(Messages.showError);
 
@@ -1222,16 +1260,16 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             _showLoading(paragraph, true);
 
             _closeOldQuery(paragraph)
-                .then(function() {
+                .then(() => {
                     const args = paragraph.queryArgs = {
                         cacheName: paragraph.cacheName,
                         pageSize: paragraph.pageSize,
                         query: paragraph.query
                     };
 
-                    return agentMonitor.query(args.cacheName, args.pageSize, args.query);
+                    return agentMonitor.query(cacheNode(paragraph.cacheName), args.cacheName, args.query, false, args.pageSize);
                 })
-                .then(function(res) {
+                .then((res) => {
                     _processQueryResult(paragraph, res);
 
                     _tryStartRefresh(paragraph);
@@ -1250,7 +1288,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             return LegacyUtils.isDefined(paragraph.queryArgs);
         };
 
-        const _cancelRefresh = function(paragraph) {
+        const _cancelRefresh = (paragraph) => {
             if (paragraph.rate && paragraph.rate.stopTime) {
                 delete paragraph.queryArgs;
 
@@ -1262,7 +1300,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             }
         };
 
-        $scope.explain = function(paragraph) {
+        $scope.explain = (paragraph) => {
             Notebook.save($scope.notebook)
                 .catch(Messages.showError);
 
@@ -1271,14 +1309,14 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             _showLoading(paragraph, true);
 
             _closeOldQuery(paragraph)
-                .then(function() {
+                .then(() => {
                     const args = paragraph.queryArgs = {
                         cacheName: paragraph.cacheName,
                         pageSize: paragraph.pageSize,
                         query: 'EXPLAIN ' + paragraph.query
                     };
 
-                    return agentMonitor.query(args.cacheName, args.pageSize, args.query);
+                    return agentMonitor.query(cacheNode(paragraph.cacheName), args.cacheName, args.query, false, args.pageSize);
                 })
                 .then(_processQueryResult.bind(this, paragraph))
                 .catch((err) => {
@@ -1289,7 +1327,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                 .then(() => paragraph.ace.focus());
         };
 
-        $scope.scan = function(paragraph) {
+        $scope.scan = (paragraph, query = null) => {
             Notebook.save($scope.notebook)
                 .catch(Messages.showError);
 
@@ -1301,10 +1339,11 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                 .then(() => {
                     const args = paragraph.queryArgs = {
                         cacheName: paragraph.cacheName,
-                        pageSize: paragraph.pageSize
+                        pageSize: paragraph.pageSize,
+                        query
                     };
 
-                    return agentMonitor.query(args.cacheName, args.pageSize);
+                    return agentMonitor.query(cacheNode(paragraph.cacheName), args.cacheName, query, false, args.pageSize);
                 })
                 .then(_processQueryResult.bind(this, paragraph))
                 .catch((err) => {
@@ -1315,6 +1354,15 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                 .then(() => paragraph.ace.focus());
         };
 
+        $scope.scanWithFilter = (paragraph) => {
+            ScanFilterInput.open()
+                .then(({filter, caseSensitive}) => {
+                    const prefix = caseSensitive ? SCAN_CACHE_WITH_FILTER_CASE_SENSITIVE : SCAN_CACHE_WITH_FILTER;
+
+                    $scope.scan(paragraph, `${prefix}${filter}`);
+                });
+        };
+
         function _updatePieChartsWithData(paragraph, newDatum) {
             $timeout(() => {
                 _.forEach(paragraph.charts, function(chart) {
@@ -1332,18 +1380,20 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             });
         }
 
-        $scope.nextPage = function(paragraph) {
+        $scope.nextPage = (paragraph) => {
             _showLoading(paragraph, true);
 
             paragraph.queryArgs.pageSize = paragraph.pageSize;
 
-            agentMonitor.next(paragraph.queryId, paragraph.pageSize)
-                .then(function(res) {
+            agentMonitor.next(paragraph.resNodeId, paragraph.queryId, paragraph.pageSize)
+                .then((res) => {
                     paragraph.page++;
 
                     paragraph.total += paragraph.rows.length;
 
-                    paragraph.rows = res.items;
+                    paragraph.duration = res.duration;
+
+                    paragraph.rows = res.rows;
 
                     if (paragraph.chart()) {
                         if (paragraph.result === 'pie')
@@ -1352,11 +1402,11 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                             _updateChartsWithData(paragraph, _chartDatum(paragraph));
                     }
 
-                    paragraph.gridOptions.updateRows(paragraph.rows);
+                    paragraph.gridOptions.adjustHeight(paragraph.rows.length);
 
                     _showLoading(paragraph, false);
 
-                    if (res.last)
+                    if (!res.hasMore)
                         delete paragraph.queryId;
                 })
                 .catch((err) => {
@@ -1424,8 +1474,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
         $scope.exportCsvAll = function(paragraph) {
             const args = paragraph.queryArgs;
 
-            agentMonitor.queryGetAll(args.cacheName, args.query)
-                .then((res) => _export(paragraph.name + '-all.csv', paragraph.columnFilter, res.fieldsMetadata, res.items))
+            agentMonitor.queryGetAll(cacheNode(args.cacheName), args.cacheName, args.query, false)
+                .then((res) => _export(paragraph.name + '-all.csv', paragraph.columnFilter, res.columns, res.rows))
                 .catch(Messages.showError)
                 .then(() => paragraph.ace.focus());
         };
@@ -1544,6 +1594,18 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                     scope.title = 'SCAN query';
                     scope.content = [`SCAN query for cache: <b>${$scope.maskCacheName(paragraph.queryArgs.cacheName)}</b>`];
                 }
+                if (paragraph.queryArgs.query.startsWith(SCAN_CACHE_WITH_FILTER)) {
+                    scope.title = 'SCAN query';
+
+                    let filter = '';
+
+                    if (paragraph.queryArgs.query.startsWith(SCAN_CACHE_WITH_FILTER_CASE_SENSITIVE))
+                        filter = paragraph.queryArgs.query.substr(SCAN_CACHE_WITH_FILTER_CASE_SENSITIVE.length);
+                    else
+                        filter = paragraph.queryArgs.query.substr(SCAN_CACHE_WITH_FILTER.length);
+
+                    scope.content = [`SCAN query for cache: <b>${$scope.maskCacheName(paragraph.queryArgs.cacheName)}</b> with filter: <b>${filter}</b>`];
+                }
                 else if (paragraph.queryArgs.query .startsWith('EXPLAIN ')) {
                     scope.title = 'Explain query';
                     scope.content = [paragraph.queryArgs.query];

http://git-wip-us.apache.org/repos/asf/ignite/blob/0a1fa244/modules/web-console/frontend/app/modules/sql/sql.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/sql.module.js b/modules/web-console/frontend/app/modules/sql/sql.module.js
index 703ecc8..daf5cce 100644
--- a/modules/web-console/frontend/app/modules/sql/sql.module.js
+++ b/modules/web-console/frontend/app/modules/sql/sql.module.js
@@ -19,6 +19,7 @@ import angular from 'angular';
 
 import NotebookData from './Notebook.data';
 import Notebook from './Notebook.service';
+import ScanFilterInput from './scan-filter-input.service';
 import notebook from './notebook.controller';
 import sql from './sql.controller';
 
@@ -52,5 +53,6 @@ angular.module('ignite-console.sql', [
     )
     .service('IgniteNotebookData', NotebookData)
     .service('IgniteNotebook', Notebook)
+    .service('IgniteScanFilterInput', ScanFilterInput)
     .controller('notebookController', notebook)
     .controller('sqlController', sql);

http://git-wip-us.apache.org/repos/asf/ignite/blob/0a1fa244/modules/web-console/frontend/gulpfile.babel.js/paths.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/gulpfile.babel.js/paths.js b/modules/web-console/frontend/gulpfile.babel.js/paths.js
index 4441cfa..9134e44 100644
--- a/modules/web-console/frontend/gulpfile.babel.js/paths.js
+++ b/modules/web-console/frontend/gulpfile.babel.js/paths.js
@@ -28,7 +28,8 @@ const jadePaths = [
     './views/*.jade',
     './views/**/*.jade',
     './app/helpers/**/*.jade',
-    './app/modules/states/configuration/**/*.jade'
+    './app/modules/states/configuration/**/*.jade',
+    './app/modules/sql/*.jade'
 ];
 
 const resourcePaths = [

http://git-wip-us.apache.org/repos/asf/ignite/blob/0a1fa244/modules/web-console/frontend/public/stylesheets/style.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/stylesheets/style.scss b/modules/web-console/frontend/public/stylesheets/style.scss
index 3704643..994595a 100644
--- a/modules/web-console/frontend/public/stylesheets/style.scss
+++ b/modules/web-console/frontend/public/stylesheets/style.scss
@@ -641,29 +641,6 @@ button.form-control {
         }
     }
 
-    .sql-controls {
-        margin: 10px 0;
-        padding: 0 10px;
-    }
-
-    .sql-table-total {
-        padding: 0 10px;
-
-        label, b {
-            display: inline-block;
-
-            padding-top: 5px;
-
-            height: 27px;
-        }
-
-        margin-bottom: 10px;
-    }
-
-    .sql-table {
-        height: 400px;
-    }
-
     table thead {
         background-color: white;
     }
@@ -682,38 +659,45 @@ button.form-control {
         line-height: 55px;
     }
 
-    .sql-error-result {
-        padding: 10px 0;
+    .sql-controls {
+        border-top: 1px solid $ignite-border-color;
 
-        text-align: center;
-        color: $brand-primary;
+        padding: 10px 10px;
+    }
 
+    .sql-result {
         border-top: 1px solid $ignite-border-color;
-    }
 
-    .sql-empty-result {
-        margin-top: 10px;
-        margin-bottom: 10px;
-        text-align: center;
-        color: $ignite-placeholder-color;
-    }
+        .error {
+            padding: 10px 10px;
 
-    .sql-next {
-        float: right;
+            text-align: center;
+            color: $brand-primary;
+        }
 
-        .disabled {
-            cursor: default;
-            text-decoration: none;
+        .empty {
+            padding: 10px 10px;
+
+            text-align: center;
+            color: $ignite-placeholder-color;
         }
 
-        a {
-            margin-right: 5px;
-            margin-bottom: 5px;
+        .total {
+            padding: 10px 10px;
         }
 
-        i {
-            margin-top: 3px;
-            margin-right: 10px;
+        .table {
+            margin: 0
+        }
+
+        .chart {
+            margin: 0
+        }
+
+        .footer {
+            border-top: 1px solid $ignite-border-color;
+
+            padding: 5px 10px;
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0a1fa244/modules/web-console/frontend/views/sql/sql.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/sql/sql.jade b/modules/web-console/frontend/views/sql/sql.jade
index 582c8ca..570517d 100644
--- a/modules/web-console/frontend/views/sql/sql.jade
+++ b/modules/web-console/frontend/views/sql/sql.jade
@@ -28,8 +28,8 @@ mixin result-toolbar
         +btn-toolbar-data('fa-line-chart', 'line', 'Show line chart<br/>By default first column - X values, second column - Y values<br/>In case of one column it will be treated as Y values')
         +btn-toolbar-data('fa-area-chart', 'area', 'Show area chart<br/>By default first column - X values, second column - Y values<br/>In case of one column it will be treated as Y values')
 
-mixin chart-settings(mdl)
-    .row
+mixin chart-settings
+    .total.row
         .col-xs-4
             .chart-settings-link(ng-show='paragraph.chart && paragraph.chartColumns.length > 0')
                 a(title='Click to show chart settings dialog' ng-click='$event.stopPropagation()' bs-popover data-template-url='/sql/chart-settings.html' data-placement='bottom' data-auto-close='1' data-trigger='click')
@@ -86,9 +86,13 @@ mixin query-controls
     .sql-controls
         a.btn.btn-primary(ng-disabled='!actionAvailable(paragraph, true)' ng-click='actionAvailable(paragraph, true) && execute(paragraph)' data-placement='bottom' bs-tooltip data-title='{{actionTooltip(paragraph, "execute", true)}}') Execute
         a.btn.btn-primary(ng-disabled='!actionAvailable(paragraph, true)' ng-click='actionAvailable(paragraph, true) && explain(paragraph)' data-placement='bottom' bs-tooltip data-title='{{actionTooltip(paragraph, "explain", true)}}') Explain
-        a.btn.btn-primary(ng-disabled='!actionAvailable(paragraph, false)' ng-click='actionAvailable(paragraph, false) && scan(paragraph)' data-placement='bottom' bs-tooltip data-title='{{actionTooltip(paragraph, "execute scan", false)}}') Scan
+        .btn-group(ng-disabled='!actionAvailable(paragraph, false)')
+            a.btn.btn-primary.fieldButton(ng-click='actionAvailable(paragraph, false) && scan(paragraph)' data-placement='bottom' bs-tooltip data-title='{{actionTooltip(paragraph, "execute scan", false)}}') Scan
+            a.btn.btn-primary(data-toggle='dropdown' data-container='body' bs-dropdown='[{ text: "Scan with filter", click: "actionAvailable(paragraph, false) && scanWithFilter(paragraph)" }]' data-placement='bottom-right')
+                span.caret
+
         .pull-right
-            labelHide System columns:
+            label.tipLabel System columns:
             a.btn.btn-default.fa.fa-bars.tipLabel(ng-class='{"btn-info": paragraph.systemColumns}' ng-click='toggleSystemColumns(paragraph)' ng-disabled='paragraph.disabledSystemColumns' bs-tooltip data-title='Show "_KEY", "_VAL" columns')
             label.tipLabel Refresh rate:
             button.btn.btn-default.fa.fa-clock-o.tipLabel(title='Click to show refresh rate dialog' ng-class='{"btn-info": paragraph.rate && paragraph.rate.installed}' bs-popover data-template-url='/sql/paragraph-rate.html' data-placement='left' data-auto-close='1' data-trigger='click') {{rateAsString(paragraph)}}
@@ -96,10 +100,11 @@ mixin query-controls
             button.select-toggle.fieldButton.btn.btn-default(ng-model='paragraph.pageSize' bs-options='item for item in pageSizes' bs-select bs-tooltip data-placement='bottom-right' data-title='Max number of rows to show in query result as one page')
 
 mixin table-result
-    .sql-table-total.row
+    .total.row
         .col-xs-4
-            label(style='margin-right: 10px;') Page: #[b {{paragraph.page}}]
-            label Results so far: #[b {{paragraph.rows.length + paragraph.total}}]
+            label Page: #[b {{paragraph.page}}]
+            label.margin-left-dflt Results so far: #[b {{paragraph.rows.length + paragraph.total}}]
+            label.margin-left-dflt Duration: #[b {{paragraph.duration | duration}}]
         .col-xs-4
             +result-toolbar
         .col-xs-4
@@ -112,31 +117,19 @@ mixin table-result
 mixin chart-result
     div(ng-show='paragraph.queryExecuted()')
         +chart-settings
-        div(ng-show='paragraph.chartColumns.length > 0 && !paragraph.chartColumnsConfigured()')
-            .sql-empty-result Cannot display chart. Please configure axis using #[b Chart settings]
-        div(ng-show='paragraph.chartColumns.length == 0')
-            .sql-empty-result Cannot display chart. Result set must contain Java build-in type columns. Please change query and execute it again.
+        .empty(ng-show='paragraph.chartColumns.length > 0 && !paragraph.chartColumnsConfigured()') Cannot display chart. Please configure axis using #[b Chart settings]
+        .empty(ng-show='paragraph.chartColumns.length == 0') Cannot display chart. Result set must contain Java build-in type columns. Please change query and execute it again.
         div(ng-show='paragraph.chartColumnsConfigured()')
             div(ng-show='paragraph.timeLineSupported() || !paragraph.chartTimeLineEnabled()')
                 div(ng-repeat='chart in paragraph.charts')
                     nvd3(options='chart.options' data='chart.data' api='chart.api')
-            .sql-empty-result(ng-show='!paragraph.timeLineSupported() && paragraph.chartTimeLineEnabled()') Pie chart does not support 'TIME_LINE' column for X-axis. Please use another column for X-axis or switch to another chart.
-    .sql-empty-result(ng-hide='paragraph.queryExecuted()')
+            .empty(ng-show='!paragraph.timeLineSupported() && paragraph.chartTimeLineEnabled()') Pie chart does not support 'TIME_LINE' column for X-axis. Please use another column for X-axis or switch to another chart.
+    .empty(ng-hide='paragraph.queryExecuted()')
         .row
             .col-xs-4.col-xs-offset-4
                 +result-toolbar
         label.margin-top-dflt Charts do not support #[b Explain] and #[b Scan] query
 
-mixin footer-controls
-    hr(style='margin-top: 0; margin-bottom: 5px')
-    a(style='float: left; margin-left: 10px; margin-bottom: 5px' ng-click='showResultQuery(paragraph)') Show query
-
-    -var nextVisibleCondition = 'paragraph.queryId && (paragraph.table() || paragraph.chart() && (paragraph.timeLineSupported() || !paragraph.chartTimeLineEnabled()))'
-
-    .sql-next(ng-show=nextVisibleCondition)
-        i.fa.fa-chevron-circle-right(ng-class='{disabled: paragraph.loading}' ng-click='!paragraph.loading && nextPage(paragraph)')
-        a(ng-class='{disabled: paragraph.loading}' ng-click='!paragraph.loading && nextPage(paragraph)') Next
-
 .row(ng-controller='sqlController')
     .docs-content
         .row(ng-if='notebook' bs-affix style='margin-bottom: 20px;')
@@ -182,20 +175,19 @@ mixin footer-controls
                                     .empty-caches(ng-show='caches.length == 0')
                                         label No caches
                             .col-sm-12
-                                hr(style='margin: 0')
-                            .col-sm-12
                                 +query-controls
-                            .col-sm-12.sql-error-result(ng-show='paragraph.errMsg') Error: {{paragraph.errMsg}}
-                            .col-sm-12(ng-show='!paragraph.errMsg && paragraph.queryArgs')
-                                hr(style='margin-top: 0; margin-bottom: 10px')
-
-                                .sql-empty-result(ng-show='!paragraph.nonEmpty()') Result set is empty
-
-                                div(ng-show='paragraph.table() && paragraph.nonEmpty()')
+                            .col-sm-12.sql-result(ng-switch='paragraph.resultType()')
+                                .error(ng-switch-when='error') Error: {{paragraph.errMsg}}
+                                .empty(ng-switch-when='empty') Result set is empty
+                                .table(ng-switch-when='table')
                                     +table-result
-
-                                div(ng-show='paragraph.chart() && paragraph.nonEmpty()')
+                                .chart(ng-switch-when='chart')
                                     +chart-result
+                                .footer.clearfix(ng-show='paragraph.nonRefresh()')
+                                    a.pull-left(ng-click='showResultQuery(paragraph)') Show query
+
+                                    -var nextVisibleCondition = 'paragraph.queryId && (paragraph.table() || paragraph.chart() && (paragraph.timeLineSupported() || !paragraph.chartTimeLineEnabled()))'
 
-                                div(ng-show='!paragraph.refreshExecuting()')
-                                    +footer-controls
+                                    .pull-right(ng-show=nextVisibleCondition ng-class='{disabled: paragraph.loading}' ng-click='!paragraph.loading && nextPage(paragraph)')
+                                        i.fa.fa-chevron-circle-right
+                                        a Next


[20/50] [abbrv] ignite git commit: Minor code cleanup.

Posted by an...@apache.org.
Minor code cleanup.


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

Branch: refs/heads/ignite-3629
Commit: a4f7df48379e7d056bb068ec6090af6dba84f635
Parents: 2fb16dd
Author: Alexey Kuznetsov <ak...@apache.org>
Authored: Fri Aug 26 15:15:28 2016 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Fri Aug 26 15:15:28 2016 +0700

----------------------------------------------------------------------
 modules/web-console/backend/services/auth.js                     | 2 +-
 .../gulpfile.babel.js/webpack/environments/development.js        | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/a4f7df48/modules/web-console/backend/services/auth.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/services/auth.js b/modules/web-console/backend/services/auth.js
index 8a4f1ab..9f7d77d 100644
--- a/modules/web-console/backend/services/auth.js
+++ b/modules/web-console/backend/services/auth.js
@@ -33,7 +33,7 @@ module.exports = {
  */
 module.exports.factory = (_, mongo, spacesService, errors) => {
     class AuthService {
-        // TODO move implementation from public router.
+        // TODO IGNITE-3774: move implementation from public router.
         static resetPassword() {
 
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/a4f7df48/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js b/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js
index 9758221..229760e 100644
--- a/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js
+++ b/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js
@@ -51,8 +51,8 @@ export default () => {
                 '/api/v1/*': {
                     target: 'http://localhost:3000',
                     changeOrigin: true,
-                    pathRewrite:{
-                        '^/api/v1' : ''
+                    pathRewrite: {
+                        '^/api/v1': ''
                     }
                 }
             },


[37/50] [abbrv] ignite git commit: GG-11489 Fixed terms page permission.

Posted by an...@apache.org.
GG-11489 Fixed terms page permission.


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

Branch: refs/heads/ignite-3629
Commit: a0d985d5adedb4df182d7c911a8143fed89d92a6
Parents: 957d472
Author: Andrey Novikov <an...@apache.org>
Authored: Mon Sep 5 17:24:45 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Mon Sep 5 17:24:45 2016 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/app/app.js                        | 5 ++---
 modules/web-console/frontend/app/modules/agent/agent.module.js | 3 +++
 2 files changed, 5 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/a0d985d5/modules/web-console/frontend/app/app.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/app.js b/modules/web-console/frontend/app/app.js
index e5ea8ca..45851a2 100644
--- a/modules/web-console/frontend/app/app.js
+++ b/modules/web-console/frontend/app/app.js
@@ -246,9 +246,8 @@ angular
     $root.$meta = $meta;
     $root.gettingStarted = gettingStarted;
 }])
-.run(['$rootScope', 'User', 'IgniteAgentMonitor', ($root, User, agentMonitor) => {
-    User.read()
-        .then(() => agentMonitor.init());
+.run(['$rootScope', 'IgniteAgentMonitor', ($root, agentMonitor) => {
+    $root.$on('user', () => agentMonitor.init());
 }])
 .run(['$rootScope', ($root) => {
     $root.$on('$stateChangeStart', () => {

http://git-wip-us.apache.org/repos/asf/ignite/blob/a0d985d5/modules/web-console/frontend/app/modules/agent/agent.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/agent/agent.module.js b/modules/web-console/frontend/app/modules/agent/agent.module.js
index f65781e..22ced13 100644
--- a/modules/web-console/frontend/app/modules/agent/agent.module.js
+++ b/modules/web-console/frontend/app/modules/agent/agent.module.js
@@ -126,6 +126,9 @@ class IgniteAgentMonitor {
     }
 
     init() {
+        if (this._socket)
+            return;
+
         this._socket = this._socketFactory();
 
         const disconnectFn = () => {


[12/50] [abbrv] ignite git commit: Fixed html output in info window.

Posted by an...@apache.org.
Fixed html output in info window.


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

Branch: refs/heads/ignite-3629
Commit: 671c1d9779c50e18db1ef9c3ecc147f659a90312
Parents: f1cdb87
Author: Maxim Afanasiev <ma...@gridgain.com>
Authored: Wed Aug 24 16:41:48 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Wed Aug 24 16:41:48 2016 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/views/templates/alert.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/671c1d97/modules/web-console/frontend/views/templates/alert.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/templates/alert.jade b/modules/web-console/frontend/views/templates/alert.jade
index 0ab3dd9..182ba99 100644
--- a/modules/web-console/frontend/views/templates/alert.jade
+++ b/modules/web-console/frontend/views/templates/alert.jade
@@ -17,5 +17,5 @@
 .alert(ng-show='type' ng-class='[type ? "alert-" + type : null]')
     button.close(type='button', ng-if='dismissable', ng-click='$hide()') &times;
     i.alert-icon.fa(ng-if='icon' ng-class='[icon]')
-    span.alert-title(ng-bind='title')
+    span.alert-title(ng-bind-html='title')
     span.alert-content(ng-bind-html='content')


[21/50] [abbrv] ignite git commit: Updated development instructions.

Posted by an...@apache.org.
Updated development instructions.


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

Branch: refs/heads/ignite-3629
Commit: 38f0e0a03ce20a9ca66f6a18a2ca2d2ad3025e19
Parents: a4f7df4
Author: Alexey Kuznetsov <ak...@apache.org>
Authored: Fri Aug 26 15:29:56 2016 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Fri Aug 26 15:29:56 2016 +0700

----------------------------------------------------------------------
 modules/web-console/DEVNOTES.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/38f0e0a0/modules/web-console/DEVNOTES.txt
----------------------------------------------------------------------
diff --git a/modules/web-console/DEVNOTES.txt b/modules/web-console/DEVNOTES.txt
index d48a042..27211aa 100644
--- a/modules/web-console/DEVNOTES.txt
+++ b/modules/web-console/DEVNOTES.txt
@@ -19,7 +19,8 @@ How to deploy locally:
 6. Change directory to '$IGNITE_HOME/modules/web-console/frontend' and
  run "npm install --no-optional" for download frontend dependencies.
 7. Build ignite-web-agent module follow instructions from 'modules/web-agent/README.txt'.
-8. Copy ignite-web-agent-<version>.zip from target of ignite-web-agent module to 'modules/web-console/backend/agent_dists' folder.
+8. Copy ignite-web-agent-<version>.zip from '$IGNITE_HOME/modules/web-console/web-agent/target'
+ to '$IGNITE_HOME/modules/web-console/backend/agent_dists' folder.
 
 Steps 1 - 8 should be executed once.
 


[42/50] [abbrv] ignite git commit: IGNITE-2047 Fixed tooltips

Posted by an...@apache.org.
IGNITE-2047 Fixed tooltips


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

Branch: refs/heads/ignite-3629
Commit: 79175ab26a369cc1440d05a57178ec39bd70f911
Parents: 33581ba
Author: vsisko <vs...@gridgain.com>
Authored: Tue Sep 6 10:56:38 2016 +0700
Committer: vsisko <vs...@gridgain.com>
Committed: Tue Sep 6 10:56:38 2016 +0700

----------------------------------------------------------------------
 .../app/modules/states/configuration/caches/concurrency.jade   | 2 +-
 .../app/modules/states/configuration/caches/statistics.jade    | 6 ++++--
 2 files changed, 5 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/79175ab2/modules/web-console/frontend/app/modules/states/configuration/caches/concurrency.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/concurrency.jade b/modules/web-console/frontend/app/modules/states/configuration/caches/concurrency.jade
index 3918b91..37bd88d 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/concurrency.jade
+++ b/modules/web-console/frontend/app/modules/states/configuration/caches/concurrency.jade
@@ -35,7 +35,7 @@ include ../../../../../app/helpers/jade/mixins.jade
                         If <b>0</b> then number of concurrent asynchronous operations is unlimited')
                 .settings-row
                     +number('Default lock timeout:', model + '.defaultLockTimeout', '"defaultLockTimeout"', 'true', '0', '0',
-                        'Default lock acquisition timeout<br/>\
+                        'Default lock acquisition timeout in milliseconds<br/>\
                         If <b>0</b> then lock acquisition will never timeout')
                 .settings-row(ng-hide='#{model}.atomicityMode === "TRANSACTIONAL"')
                     +dropdown('Entry versioning:', model + '.atomicWriteOrderMode', '"atomicWriteOrderMode"', 'true', 'Choose versioning',

http://git-wip-us.apache.org/repos/asf/ignite/blob/79175ab2/modules/web-console/frontend/app/modules/states/configuration/caches/statistics.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/statistics.jade b/modules/web-console/frontend/app/modules/states/configuration/caches/statistics.jade
index afb440d..027a2bd 100644
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/statistics.jade
+++ b/modules/web-console/frontend/app/modules/states/configuration/caches/statistics.jade
@@ -30,8 +30,10 @@ include ../../../../../app/helpers/jade/mixins.jade
         .panel-body(ng-if='ui.isPanelLoaded("#{form}")')
             .col-sm-6
                 .settings-row
-                    +checkbox('Statistics enabled', model + '.statisticsEnabled', '"statisticsEnabled"', 'Flag indicating whether statistics gathering is enabled on a cache')
+                    +checkbox('Statistics enabled', model + '.statisticsEnabled', '"statisticsEnabled"', 'Flag indicating whether statistics gathering is enabled on this cache')
                 .settings-row
-                    +checkbox('Management enabled', model + '.managementEnabled', '"managementEnabled"', 'Flag indicating whether management is enabled on this cache')
+                    +checkbox('Management enabled', model + '.managementEnabled', '"managementEnabled"',
+                    'Flag indicating whether management is enabled on this cache<br/>\
+                    If enabled the CacheMXBean for each cache is registered in the platform MBean server')
             .col-sm-6
                 +preview-xml-java(model, 'cacheStatistics')


[47/50] [abbrv] ignite git commit: Restore cache query indexed types.

Posted by an...@apache.org.
Restore cache query indexed types.


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

Branch: refs/heads/ignite-3629
Commit: 594f064f20be103ee74a4ba27362ff2ee89aca91
Parents: 4fe6862
Author: Andrey Novikov <an...@apache.org>
Authored: Tue Sep 6 15:01:17 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Tue Sep 6 15:01:17 2016 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/generator/generator-java.js | 7 ++++---
 modules/web-console/frontend/generator/generator-xml.js  | 2 ++
 2 files changed, 6 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/594f064f/modules/web-console/frontend/generator/generator-java.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/generator/generator-java.js b/modules/web-console/frontend/generator/generator-java.js
index 43002d3..6cc3323 100644
--- a/modules/web-console/frontend/generator/generator-java.js
+++ b/modules/web-console/frontend/generator/generator-java.js
@@ -1412,8 +1412,6 @@ $generatorJava.cacheQuery = function(cache, domains, varName, res) {
     $generatorJava.property(res, varName, cache, 'sqlOnheapRowCacheSize', null, null, 10240);
     $generatorJava.property(res, varName, cache, 'longQueryWarningTimeout', null, null, 3000);
 
-    res.softEmptyLine();
-
     const indexedTypes = _.reduce(domains, (acc, domain) => {
         if (domain.queryMetadata === 'Annotations') {
             acc.push(domain.keyType);
@@ -1423,8 +1421,11 @@ $generatorJava.cacheQuery = function(cache, domains, varName, res) {
         return acc;
     }, []);
 
-    if (indexedTypes.length > 0)
+    if (indexedTypes.length > 0) {
+        res.softEmptyLine();
+
         $generatorJava.multiparamProperty(res, varName, {indexedTypes}, 'indexedTypes', 'class');
+    }
 
     res.softEmptyLine();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/594f064f/modules/web-console/frontend/generator/generator-xml.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/generator/generator-xml.js b/modules/web-console/frontend/generator/generator-xml.js
index 870d13f..b49b052 100644
--- a/modules/web-console/frontend/generator/generator-xml.js
+++ b/modules/web-console/frontend/generator/generator-xml.js
@@ -1153,6 +1153,8 @@ $generatorXml.cacheQuery = function(cache, domains, res) {
     const indexedTypes = _.filter(domains, (domain) => domain.queryMetadata === 'Annotations');
 
     if (indexedTypes.length > 0) {
+        res.softEmptyLine();
+
         res.startBlock('<property name="indexedTypes">');
         res.startBlock('<list>');
 


[11/50] [abbrv] ignite git commit: IGNITE-2388 Implemented ACL services and userbar modification on ACL.

Posted by an...@apache.org.
IGNITE-2388 Implemented ACL services and userbar modification on ACL.


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

Branch: refs/heads/ignite-3629
Commit: f1cdb871884c69c4d1c3a1073e694dccc3fcb634
Parents: 8e844d2
Author: Maxim Afanasiev <ma...@gridgain.com>
Authored: Wed Aug 24 16:36:27 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Wed Aug 24 16:36:27 2016 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/app/app.js         |  5 +--
 .../app/modules/navbar/userbar.directive.js     |  8 ++---
 .../frontend/app/modules/states/admin.state.js  |  3 +-
 .../app/modules/states/configuration.state.js   | 10 ++++--
 .../frontend/app/modules/states/errors.state.js | 37 +++++++++++++++++++
 .../frontend/app/modules/states/logout.state.js |  7 ++--
 .../app/modules/states/password.state.js        |  4 ++-
 .../app/modules/states/profile.state.js         |  3 +-
 .../frontend/app/modules/states/signin.state.js | 26 +++++---------
 .../app/modules/user/AclRoute.provider.js       | 38 ++++++++++++++++++++
 .../frontend/app/modules/user/permissions.js    | 28 +++++++++++++++
 .../frontend/app/modules/user/user.module.js    | 29 +++++++++++++--
 modules/web-console/frontend/app/vendor.js      |  1 +
 modules/web-console/frontend/package.json       |  1 +
 .../public/stylesheets/blocks/error.scss        | 31 ++++++++++++++++
 .../frontend/public/stylesheets/style.scss      |  1 +
 modules/web-console/frontend/views/403.jade     | 30 ++++++++++++++++
 modules/web-console/frontend/views/404.jade     | 30 ++++++++++++++++
 18 files changed, 257 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/app.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/app.js b/modules/web-console/frontend/app/app.js
index 7340d7b..549081f 100644
--- a/modules/web-console/frontend/app/app.js
+++ b/modules/web-console/frontend/app/app.js
@@ -34,6 +34,7 @@ import './modules/states/password.state';
 import './modules/states/configuration.state';
 import './modules/states/profile.state';
 import './modules/states/admin.state';
+import './modules/states/errors.state';
 
 // ignite:modules
 import './modules/user/user.module';
@@ -158,6 +159,7 @@ angular
     'ignite-console.states.configuration',
     'ignite-console.states.profile',
     'ignite-console.states.admin',
+    'ignite-console.states.errors',
     // Common modules.
     'ignite-console.dialog',
     'ignite-console.navbar',
@@ -231,8 +233,7 @@ angular
             templateUrl: baseTemplate
         });
 
-    $urlRouterProvider.otherwise('/');
-
+    $urlRouterProvider.otherwise('/404');
     $locationProvider.html5Mode(true);
 }])
 .run(['$rootScope', '$state', 'MetaTags', 'gettingStarted', ($root, $state, $meta, gettingStarted) => {

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/navbar/userbar.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/navbar/userbar.directive.js b/modules/web-console/frontend/app/modules/navbar/userbar.directive.js
index b10d5ef..af70eb1 100644
--- a/modules/web-console/frontend/app/modules/navbar/userbar.directive.js
+++ b/modules/web-console/frontend/app/modules/navbar/userbar.directive.js
@@ -18,7 +18,7 @@
 export default ['igniteUserbar', [function() {
     return {
         restrict: 'A',
-        controller: ['$rootScope', 'IgniteUserbar', function($root, IgniteUserbar) {
+        controller: ['$rootScope', 'IgniteUserbar', 'AclService', function($root, IgniteUserbar, AclService) {
             const ctrl = this;
 
             ctrl.items = [
@@ -26,15 +26,15 @@ export default ['igniteUserbar', [function() {
                 {text: 'Getting started', click: 'gettingStarted.tryShow(true)'}
             ];
 
-            const _rebuildSettings = (event, user) => {
+            const _rebuildSettings = () => {
                 ctrl.items.splice(2);
 
-                if (!user.becomeUsed && user.admin)
+                if (AclService.can('admin_page'))
                     ctrl.items.push({text: 'Admin panel', sref: 'settings.admin'});
 
                 ctrl.items.push(...IgniteUserbar);
 
-                if (!user.becomeUsed)
+                if (AclService.can('logout'))
                     ctrl.items.push({text: 'Log out', sref: 'logout'});
             };
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/admin.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/admin.state.js b/modules/web-console/frontend/app/modules/states/admin.state.js
index af1fbde..c3151e1 100644
--- a/modules/web-console/frontend/app/modules/states/admin.state.js
+++ b/modules/web-console/frontend/app/modules/states/admin.state.js
@@ -21,12 +21,13 @@ angular
 .module('ignite-console.states.admin', [
     'ui.router'
 ])
-.config(['$stateProvider', function($stateProvider) {
+.config(['$stateProvider', 'AclRouteProvider', function($stateProvider, AclRoute) {
     // set up the states
     $stateProvider
     .state('settings.admin', {
         url: '/admin',
         templateUrl: '/settings/admin.html',
+        onEnter: AclRoute.checkAccess('admin_page'),
         metaTags: {
             title: 'List of registered users'
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/configuration.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration.state.js b/modules/web-console/frontend/app/modules/states/configuration.state.js
index fd9bd1c..7fd7541 100644
--- a/modules/web-console/frontend/app/modules/states/configuration.state.js
+++ b/modules/web-console/frontend/app/modules/states/configuration.state.js
@@ -32,16 +32,18 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
     // Services.
     .service('igniteConfigurationResource', ConfigurationResource)
     // Configure state provider.
-    .config(['$stateProvider', ($stateProvider) => {
+    .config(['$stateProvider', 'AclRouteProvider', ($stateProvider, AclRoute) => {
         // Setup the states.
         $stateProvider
             .state('base.configuration', {
                 url: '/configuration',
-                templateUrl: '/configuration/sidebar.html'
+                templateUrl: '/configuration/sidebar.html',
+                abstract: true
             })
             .state('base.configuration.clusters', {
                 url: '/clusters',
                 templateUrl: '/configuration/clusters.html',
+                onEnter: AclRoute.checkAccess('configuration'),
                 params: {
                     linkId: null
                 },
@@ -52,6 +54,7 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
             .state('base.configuration.caches', {
                 url: '/caches',
                 templateUrl: '/configuration/caches.html',
+                onEnter: AclRoute.checkAccess('configuration'),
                 params: {
                     linkId: null
                 },
@@ -62,6 +65,7 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
             .state('base.configuration.domains', {
                 url: '/domains',
                 templateUrl: '/configuration/domains.html',
+                onEnter: AclRoute.checkAccess('configuration'),
                 params: {
                     linkId: null
                 },
@@ -72,6 +76,7 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
             .state('base.configuration.igfs', {
                 url: '/igfs',
                 templateUrl: '/configuration/igfs.html',
+                onEnter: AclRoute.checkAccess('configuration'),
                 params: {
                     linkId: null
                 },
@@ -82,6 +87,7 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
             .state('base.configuration.summary', {
                 url: '/summary',
                 templateUrl: '/configuration/summary.html',
+                onEnter: AclRoute.checkAccess('configuration'),
                 controller: ConfigurationSummaryCtrl,
                 controllerAs: 'ctrl',
                 metaTags: {

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/errors.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/errors.state.js b/modules/web-console/frontend/app/modules/states/errors.state.js
new file mode 100644
index 0000000..df31f57
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/states/errors.state.js
@@ -0,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.
+ */
+
+import angular from 'angular';
+import templateNotFoundPage from '../../../views/404.jade';
+import templateNotAuthorizedPage from '../../../views/403.jade';
+
+angular
+    .module('ignite-console.states.errors', [
+        'ui.router'
+    ])
+    .config(['$stateProvider', 'AclRouteProvider', function($stateProvider) {
+        // set up the states
+        $stateProvider
+            .state('404', {
+                url: '/404',
+                templateUrl: templateNotFoundPage
+            })
+            .state('403', {
+                url: '/403',
+                templateUrl: templateNotAuthorizedPage
+            });
+    }]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/logout.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/logout.state.js b/modules/web-console/frontend/app/modules/states/logout.state.js
index 7f24a45..42795ea 100644
--- a/modules/web-console/frontend/app/modules/states/logout.state.js
+++ b/modules/web-console/frontend/app/modules/states/logout.state.js
@@ -21,14 +21,13 @@ angular
 .module('ignite-console.states.logout', [
     'ui.router'
 ])
-.config(['$stateProvider', function($stateProvider) {
+.config(['$stateProvider', 'AclRouteProvider', function($stateProvider, AclRoute) {
     // set up the states
     $stateProvider
     .state('logout', {
         url: '/logout',
-        controller: ['Auth', function(Auth) {
-            Auth.logout();
-        }],
+        onEnter: AclRoute.checkAccess('logout'),
+        controller: ['Auth', (Auth) => Auth.logout()],
         metaTags: {
             title: 'Logout'
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/password.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/password.state.js b/modules/web-console/frontend/app/modules/states/password.state.js
index 48d01df..2eb030c 100644
--- a/modules/web-console/frontend/app/modules/states/password.state.js
+++ b/modules/web-console/frontend/app/modules/states/password.state.js
@@ -21,7 +21,7 @@ angular
 .module('ignite-console.states.password', [
     'ui.router'
 ])
-.config(['$stateProvider', function($stateProvider) {
+.config(['$stateProvider', 'AclRouteProvider', function($stateProvider, AclRoute) {
     // set up the states
     $stateProvider
     .state('password', {
@@ -32,6 +32,7 @@ angular
     .state('password.reset', {
         url: '/reset?{token}',
         templateUrl: '/reset.html',
+        onEnter: AclRoute.checkAccess('login'),
         metaTags: {
             title: 'Reset password'
         }
@@ -39,6 +40,7 @@ angular
     .state('password.send', {
         url: '/send',
         templateUrl: '/reset.html',
+        onEnter: AclRoute.checkAccess('login'),
         metaTags: {
             title: 'Password Send'
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/profile.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/profile.state.js b/modules/web-console/frontend/app/modules/states/profile.state.js
index 8b6cdfe..9c31340 100644
--- a/modules/web-console/frontend/app/modules/states/profile.state.js
+++ b/modules/web-console/frontend/app/modules/states/profile.state.js
@@ -21,12 +21,13 @@ angular
 .module('ignite-console.states.profile', [
     'ui.router'
 ])
-.config(['$stateProvider', function($stateProvider) {
+.config(['$stateProvider', 'AclRouteProvider', function($stateProvider, AclRoute) {
     // set up the states
     $stateProvider
     .state('settings.profile', {
         url: '/profile',
         templateUrl: '/settings/profile.html',
+        onEnter: AclRoute.checkAccess('profile'),
         metaTags: {
             title: 'User profile'
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/states/signin.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/signin.state.js b/modules/web-console/frontend/app/modules/states/signin.state.js
index a23a496..42175cf 100644
--- a/modules/web-console/frontend/app/modules/states/signin.state.js
+++ b/modules/web-console/frontend/app/modules/states/signin.state.js
@@ -24,30 +24,20 @@ angular
     // services
     'ignite-console.user'
 ])
-.config(['$stateProvider', function($stateProvider) {
+.config(['$stateProvider', 'AclRouteProvider', function($stateProvider) {
     // set up the states
     $stateProvider
     .state('signin', {
         url: '/',
         templateUrl,
-        metaTags: {
-        }
-    });
-}])
-.run(['$rootScope', '$state', 'Auth', 'IgniteBranding', function($root, $state, Auth, branding) {
-    $root.$on('$stateChangeStart', function(event, toState) {
-        if (toState.name === branding.termsState)
-            return;
-
-        if (!Auth.authorized && (toState.name !== 'signin' && !_.startsWith(toState.name, 'password.'))) {
-            event.preventDefault();
+        onEnter: ['$state', 'Auth', 'AclService', ($state, Auth, AclService) => {
+            if (Auth.authorized)
+                $state.go('base.configuration.clusters');
 
-            $state.go('signin');
-        }
-        else if (Auth.authorized && toState.name === 'signin') {
-            event.preventDefault();
-
-            $state.go('base.configuration.clusters');
+            if (!AclService.can('login'))
+                $state.go('403');
+        }],
+        metaTags: {
         }
     });
 }]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/user/AclRoute.provider.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/AclRoute.provider.js b/modules/web-console/frontend/app/modules/user/AclRoute.provider.js
new file mode 100644
index 0000000..cfd9da1
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/user/AclRoute.provider.js
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+export default [() => {
+    class AclRoute {
+        static checkAccess = (permissions, failState) => {
+            failState = failState || '403';
+
+            return ['$state', 'AclService', 'Auth', ($state, AclService) => {
+                if (AclService.can(permissions))
+                    return;
+
+                return $state.go(failState);
+            }];
+        }
+    }
+
+    return {
+        checkAccess: AclRoute.checkAccess,
+        $get: () => {
+            return AclRoute;
+        }
+    };
+}];

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/user/permissions.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/permissions.js b/modules/web-console/frontend/app/modules/user/permissions.js
new file mode 100644
index 0000000..ef10884
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/user/permissions.js
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+const guest = ['login', 'terms'];
+const becomed = ['profile', 'configuration', 'query', 'terms'];
+const user = becomed.concat(['logout']);
+const admin = user.concat(['admin_page']);
+
+export default {
+    guest,
+    user,
+    admin,
+    becomed
+};

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/modules/user/user.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/user/user.module.js b/modules/web-console/frontend/app/modules/user/user.module.js
index 2387f20..a480f97 100644
--- a/modules/web-console/frontend/app/modules/user/user.module.js
+++ b/modules/web-console/frontend/app/modules/user/user.module.js
@@ -16,13 +16,38 @@
  */
 
 import angular from 'angular';
+import aclData from './permissions';
 
 import Auth from './Auth.service';
 import User from './User.service';
+import AclRouteProvider from './AclRoute.provider';
 
 angular
 .module('ignite-console.user', [
-
+    'mm.acl',
+    'ignite-console.config'
 ])
 .service(...Auth)
-.service(...User);
+.service(...User)
+.provider('AclRoute', AclRouteProvider)
+.run(['$rootScope', 'AclService', ($root, AclService) => {
+    AclService.setAbilities(aclData);
+    AclService.attachRole('guest');
+
+    $root.$on('user', (event, user) => {
+        if (!user)
+            return;
+
+        AclService.flushRoles();
+
+        let role = 'user';
+
+        if (user.admin)
+            role = 'admin';
+
+        if (user.becomeUsed)
+            role = 'becomed';
+
+        AclService.attachRole(role);
+    });
+}]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/app/vendor.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/vendor.js b/modules/web-console/frontend/app/vendor.js
index a8eeea7..0322887 100644
--- a/modules/web-console/frontend/app/vendor.js
+++ b/modules/web-console/frontend/app/vendor.js
@@ -17,6 +17,7 @@
 
 import 'jquery';
 import 'angular';
+import 'angular-acl';
 import 'angular-animate';
 import 'angular-sanitize';
 import 'angular-strap';

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/package.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/package.json b/modules/web-console/frontend/package.json
index 9bc6987..5814522 100644
--- a/modules/web-console/frontend/package.json
+++ b/modules/web-console/frontend/package.json
@@ -30,6 +30,7 @@
   ],
   "dependencies": {
     "angular": "^1.5.5",
+    "angular-acl": "^0.1.7",
     "angular-animate": "^1.5.5",
     "angular-aria": "^1.5.5",
     "angular-cookies": "^1.5.5",

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/public/stylesheets/blocks/error.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/stylesheets/blocks/error.scss b/modules/web-console/frontend/public/stylesheets/blocks/error.scss
new file mode 100644
index 0000000..20f83a8
--- /dev/null
+++ b/modules/web-console/frontend/public/stylesheets/blocks/error.scss
@@ -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.
+ */
+
+.error-page {
+    text-align: center;
+    min-height: 300px;
+
+    &__title {
+        margin-top: 100px;
+        font-weight: 200;
+    }
+
+    &__description {
+        margin-top: 30px;
+        font-weight: 500;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/public/stylesheets/style.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/stylesheets/style.scss b/modules/web-console/frontend/public/stylesheets/style.scss
index 994595a..4db7127 100644
--- a/modules/web-console/frontend/public/stylesheets/style.scss
+++ b/modules/web-console/frontend/public/stylesheets/style.scss
@@ -20,6 +20,7 @@
 @import "./variables";
 @import "~roboto-font/css/fonts.css";
 @import "./../../app/directives/information/information.scss";
+@import "./blocks/error";
 
 hr {
     margin: 20px 0;

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/views/403.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/403.jade b/modules/web-console/frontend/views/403.jade
new file mode 100644
index 0000000..1a1cc04
--- /dev/null
+++ b/modules/web-console/frontend/views/403.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.
+
+header#header.header
+    table.container
+        tr
+            td.col-xs-3.col-sm-3.col-md-2
+                ignite-header-logo
+            td
+                ignite-header-title
+
+.error-page
+    .container
+        h1.error-page__title 403
+        h2.error-page__description You not authorized
+
+include includes/footer

http://git-wip-us.apache.org/repos/asf/ignite/blob/f1cdb871/modules/web-console/frontend/views/404.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/404.jade b/modules/web-console/frontend/views/404.jade
new file mode 100644
index 0000000..3533905
--- /dev/null
+++ b/modules/web-console/frontend/views/404.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.
+
+header#header.header
+    table.container
+        tr
+            td.col-xs-3.col-sm-3.col-md-2
+                ignite-header-logo
+            td
+                ignite-header-title
+
+.error-page
+    .container
+        h1.error-page__title 404
+        h2.error-page__description Page not found
+
+include includes/footer


[04/50] [abbrv] ignite git commit: IGNITE-2047 added fix to popover

Posted by an...@apache.org.
IGNITE-2047 added fix to popover


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

Branch: refs/heads/ignite-3629
Commit: e8a32f127c0e9c9a09a2d5de4d459ffc9ab9edfe
Parents: ffe79ee
Author: Dmitriyff Smile <dm...@gmail.com>
Authored: Mon Aug 22 13:59:53 2016 +0700
Committer: Dmitriyff Smile <dm...@gmail.com>
Committed: Mon Aug 22 13:59:53 2016 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/public/stylesheets/style.scss | 1 +
 modules/web-console/frontend/views/sql/sql.jade            | 6 +++---
 2 files changed, 4 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e8a32f12/modules/web-console/frontend/public/stylesheets/style.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/stylesheets/style.scss b/modules/web-console/frontend/public/stylesheets/style.scss
index 969d621..3704643 100644
--- a/modules/web-console/frontend/public/stylesheets/style.scss
+++ b/modules/web-console/frontend/public/stylesheets/style.scss
@@ -1172,6 +1172,7 @@ button.form-control {
 .theme-line .popover.cache-metadata {
     @extend .popover.settings;
 
+    position: absolute;
     z-index: 1030;
     min-width: 305px;
     max-width: 450px;

http://git-wip-us.apache.org/repos/asf/ignite/blob/e8a32f12/modules/web-console/frontend/views/sql/sql.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/sql/sql.jade b/modules/web-console/frontend/views/sql/sql.jade
index 0047adf..582c8ca 100644
--- a/modules/web-console/frontend/views/sql/sql.jade
+++ b/modules/web-console/frontend/views/sql/sql.jade
@@ -155,8 +155,8 @@ mixin footer-controls
         div(ng-if='notebook' ignite-loading='sqlLoading' ignite-loading-text='{{ loadingText }}' ignite-loading-position='top')
             .docs-body.paragraphs
                 .panel-group(bs-collapse ng-model='notebook.expandedParagraphs' data-allow-multiple='true' data-start-collapsed='false')
-                    .panel.panel-default(ng-repeat='paragraph in notebook.paragraphs')
-                        .panel-heading(id='{{paragraph.id}}' bs-collapse-toggle)
+                    .panel.panel-default(ng-repeat='paragraph in notebook.paragraphs' id='{{paragraph.id}}')
+                        .panel-heading(bs-collapse-toggle)
                             .row
                                 +paragraph-rename
                         .panel-collapse(role='tabpanel' bs-collapse-target)
@@ -168,7 +168,7 @@ mixin footer-controls
                                 .col-xs-4.col-sm-3
                                     div(ng-show='caches.length > 0' style='padding: 5px 10px' st-table='displayedCaches' st-safe-src='caches')
                                         lable.labelField.labelFormField Caches:
-                                        i.fa.fa-database.tipField(title='Click to show cache types metadata dialog' bs-popover data-template-url='/sql/cache-metadata.html', data-placement='bottom', data-trigger='click')
+                                        i.fa.fa-database.tipField(title='Click to show cache types metadata dialog' bs-popover data-template-url='/sql/cache-metadata.html' data-placement='bottom' data-trigger='click' data-container='#{{ paragraph.id}}')
                                         .input-tip
                                             input.form-control(type='text' st-search='label' placeholder='Filter caches...')
                                         table.links


[28/50] [abbrv] ignite git commit: IGNITE-3620 Moved popover functions and form function in separated services.

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/27176d59/modules/web-console/frontend/app/services/LegacyUtils.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/services/LegacyUtils.service.js b/modules/web-console/frontend/app/services/LegacyUtils.service.js
index 21fab0c..6328895 100644
--- a/modules/web-console/frontend/app/services/LegacyUtils.service.js
+++ b/modules/web-console/frontend/app/services/LegacyUtils.service.js
@@ -16,958 +16,561 @@
  */
 
 // TODO: Refactor this service for legacy tables with more than one input field.
-export default ['IgniteLegacyUtils', [
-    '$alert', '$popover', '$anchorScroll', '$location', '$timeout', '$window', 'IgniteFocus',
-    ($alert, $popover, $anchorScroll, $location, $timeout, $window, Focus) => {
-        $anchorScroll.yOffset = 55;
-
-        function isDefined(v) {
-            return !_.isNil(v);
-        }
-
-        function isEmptyString(s) {
-            if (isDefined(s))
-                return s.trim().length === 0;
-
-            return true;
-        }
-
-        const javaBuiltInClasses = [
-            'BigDecimal', 'Boolean', 'Byte', 'Date', 'Double', 'Float', 'Integer', 'Long', 'Object', 'Short', 'String', 'Time', 'Timestamp', 'UUID'
-        ];
-
-        const javaBuiltInTypes = [
-            'BigDecimal', 'boolean', 'Boolean', 'byte', 'Byte', 'Date', 'double', 'Double', 'float', 'Float',
-            'int', 'Integer', 'long', 'Long', 'Object', 'short', 'Short', 'String', 'Time', 'Timestamp', 'UUID'
-        ];
-
-        const javaBuiltInFullNameClasses = [
-            'java.math.BigDecimal', 'java.lang.Boolean', 'java.lang.Byte', 'java.sql.Date', 'java.lang.Double',
-            'java.lang.Float', 'java.lang.Integer', 'java.lang.Long', 'java.lang.Object', 'java.lang.Short',
-            'java.lang.String', 'java.sql.Time', 'java.sql.Timestamp', 'java.util.UUID'
-        ];
-
-        /**
-         * @param clsName Class name to check.
-         * @returns {Boolean} 'true' if given class name is a java build-in type.
-         */
-        function isJavaBuiltInClass(clsName) {
-            if (isEmptyString(clsName))
-                return false;
-
-            return _.includes(javaBuiltInClasses, clsName) || _.includes(javaBuiltInFullNameClasses, clsName);
-        }
-
-        const SUPPORTED_JDBC_TYPES = [
-            'BIGINT',
-            'BIT',
-            'BOOLEAN',
-            'BLOB',
-            'CHAR',
-            'CLOB',
-            'DATE',
-            'DECIMAL',
-            'DOUBLE',
-            'FLOAT',
-            'INTEGER',
-            'LONGNVARCHAR',
-            'LONGVARCHAR',
-            'NCHAR',
-            'NUMERIC',
-            'NVARCHAR',
-            'REAL',
-            'SMALLINT',
-            'TIME',
-            'TIMESTAMP',
-            'TINYINT',
-            'VARCHAR'
-        ];
-
-        const ALL_JDBC_TYPES = [
-            {dbName: 'BIT', dbType: -7, javaType: 'Boolean', primitiveType: 'boolean'},
-            {dbName: 'TINYINT', dbType: -6, javaType: 'Byte', primitiveType: 'byte'},
-            {dbName: 'SMALLINT', dbType: 5, javaType: 'Short', primitiveType: 'short'},
-            {dbName: 'INTEGER', dbType: 4, javaType: 'Integer', primitiveType: 'int'},
-            {dbName: 'BIGINT', dbType: -5, javaType: 'Long', primitiveType: 'long'},
-            {dbName: 'FLOAT', dbType: 6, javaType: 'Float', primitiveType: 'float'},
-            {dbName: 'REAL', dbType: 7, javaType: 'Double', primitiveType: 'double'},
-            {dbName: 'DOUBLE', dbType: 8, javaType: 'Double', primitiveType: 'double'},
-            {dbName: 'NUMERIC', dbType: 2, javaType: 'BigDecimal'},
-            {dbName: 'DECIMAL', dbType: 3, javaType: 'BigDecimal'},
-            {dbName: 'CHAR', dbType: 1, javaType: 'String'},
-            {dbName: 'VARCHAR', dbType: 12, javaType: 'String'},
-            {dbName: 'LONGVARCHAR', dbType: -1, javaType: 'String'},
-            {dbName: 'DATE', dbType: 91, javaType: 'Date'},
-            {dbName: 'TIME', dbType: 92, javaType: 'Time'},
-            {dbName: 'TIMESTAMP', dbType: 93, javaType: 'Timestamp'},
-            {dbName: 'BINARY', dbType: -2, javaType: 'Object'},
-            {dbName: 'VARBINARY', dbType: -3, javaType: 'Object'},
-            {dbName: 'LONGVARBINARY', dbType: -4, javaType: 'Object'},
-            {dbName: 'NULL', dbType: 0, javaType: 'Object'},
-            {dbName: 'OTHER', dbType: 1111, javaType: 'Object'},
-            {dbName: 'JAVA_OBJECT', dbType: 2000, javaType: 'Object'},
-            {dbName: 'DISTINCT', dbType: 2001, javaType: 'Object'},
-            {dbName: 'STRUCT', dbType: 2002, javaType: 'Object'},
-            {dbName: 'ARRAY', dbType: 2003, javaType: 'Object'},
-            {dbName: 'BLOB', dbType: 2004, javaType: 'Object'},
-            {dbName: 'CLOB', dbType: 2005, javaType: 'String'},
-            {dbName: 'REF', dbType: 2006, javaType: 'Object'},
-            {dbName: 'DATALINK', dbType: 70, javaType: 'Object'},
-            {dbName: 'BOOLEAN', dbType: 16, javaType: 'Boolean', primitiveType: 'boolean'},
-            {dbName: 'ROWID', dbType: -8, javaType: 'Object'},
-            {dbName: 'NCHAR', dbType: -15, javaType: 'String'},
-            {dbName: 'NVARCHAR', dbType: -9, javaType: 'String'},
-            {dbName: 'LONGNVARCHAR', dbType: -16, javaType: 'String'},
-            {dbName: 'NCLOB', dbType: 2011, javaType: 'String'},
-            {dbName: 'SQLXML', dbType: 2009, javaType: 'Object'}
-        ];
-
-        /*eslint-disable */
-        const JAVA_KEYWORDS = [
-            'abstract',     'assert',        'boolean',      'break',           'byte',
-            'case',         'catch',         'char',         'class',           'const',
-            'continue',     'default',       'do',           'double',          'else',
-            'enum',         'extends',       'false',        'final',           'finally',
-            'float',        'for',           'goto',         'if',              'implements',
-            'import',       'instanceof',    'int',          'interface',       'long',
-            'native',       'new',           'null',         'package',         'private',
-            'protected',    'public',        'return',       'short',           'static',
-            'strictfp',     'super',         'switch',       'synchronized',    'this',
-            'throw',        'throws',        'transient',    'true',            'try',
-            'void',         'volatile',      'while'
-        ];
-        /*eslint-enable */
-
-        const VALID_JAVA_IDENTIFIER = new RegExp('^[a-zA-Z_$][a-zA-Z\\d_$]*$');
-
-        let popover = null;
-
-        function isElementInViewport(el) {
-            const rect = el.getBoundingClientRect();
-
-            return (
-                rect.top >= 0 &&
-                rect.left >= 0 &&
-                rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
-                rect.right <= (window.innerWidth || document.documentElement.clientWidth)
-            );
-        }
-
-        const _showPopoverMessage = (id, message, showTime) => {
-            const body = $('body');
-
-            let el = body.find('#' + id);
-
-            if (!el || el.length === 0)
-                el = body.find('[name="' + id + '"]');
-
-            if (el && el.length > 0) {
-                if (!isElementInViewport(el[0])) {
-                    $location.hash(el[0].id);
-
-                    $anchorScroll();
-                }
-
-                const newPopover = $popover(el, {content: message});
-
-                popover = newPopover;
-
-                $timeout(() => newPopover.$promise.then(() => {
-                    newPopover.show();
-
-                    // Workaround to fix popover location when content is longer than content template.
-                    // https://github.com/mgcrea/angular-strap/issues/1497
-                    $timeout(newPopover.$applyPlacement);
-                }), 400);
-                $timeout(() => newPopover.hide(), showTime || 5000);
-            }
-        };
-
-        function ensureActivePanel(ui, pnl, focusId) {
-            if (ui) {
-                const collapses = $('div.panel-collapse');
-
-                ui.loadPanel(pnl);
-
-                const idx = _.findIndex(collapses, function(collapse) {
-                    return collapse.id === pnl;
-                });
+export default ['IgniteLegacyUtils', ['IgniteErrorPopover', (ErrorPopover) => {
+    function isDefined(v) {
+        return !_.isNil(v);
+    }
 
-                if (idx >= 0) {
-                    const activePanels = ui.activePanels;
+    function isEmptyString(s) {
+        if (isDefined(s))
+            return s.trim().length === 0;
 
-                    if (!_.includes(ui.topPanels, idx)) {
-                        ui.expanded = true;
+        return true;
+    }
 
-                        const customExpanded = ui[pnl];
+    const javaBuiltInClasses = [
+        'BigDecimal',
+        'Boolean',
+        'Byte',
+        'Date',
+        'Double',
+        'Float',
+        'Integer',
+        'Long',
+        'Object',
+        'Short',
+        'String',
+        'Time',
+        'Timestamp',
+        'UUID'
+    ];
+
+    const javaBuiltInTypes = [
+        'BigDecimal',
+        'boolean',
+        'Boolean',
+        'byte',
+        'Byte',
+        'Date',
+        'double',
+        'Double',
+        'float',
+        'Float',
+        'int',
+        'Integer',
+        'long',
+        'Long',
+        'Object',
+        'short',
+        'Short',
+        'String',
+        'Time',
+        'Timestamp',
+        'UUID'
+    ];
+
+    const javaBuiltInFullNameClasses = [
+        'java.math.BigDecimal',
+        'java.lang.Boolean',
+        'java.lang.Byte',
+        'java.sql.Date',
+        'java.lang.Double',
+        'java.lang.Float',
+        'java.lang.Integer',
+        'java.lang.Long',
+        'java.lang.Object',
+        'java.lang.Short',
+        'java.lang.String',
+        'java.sql.Time',
+        'java.sql.Timestamp',
+        'java.util.UUID'
+    ];
+
+    /**
+     * @param clsName Class name to check.
+     * @returns {Boolean} 'true' if given class name is a java build-in type.
+     */
+    function isJavaBuiltInClass(clsName) {
+        if (isEmptyString(clsName))
+            return false;
 
-                        if (customExpanded)
-                            ui[customExpanded] = true;
-                    }
+        return _.includes(javaBuiltInClasses, clsName) || _.includes(javaBuiltInFullNameClasses, clsName);
+    }
 
-                    if (!activePanels || activePanels.length < 1)
-                        ui.activePanels = [idx];
-                    else if (!_.includes(activePanels, idx)) {
-                        const newActivePanels = angular.copy(activePanels);
+    const SUPPORTED_JDBC_TYPES = [
+        'BIGINT',
+        'BIT',
+        'BOOLEAN',
+        'BLOB',
+        'CHAR',
+        'CLOB',
+        'DATE',
+        'DECIMAL',
+        'DOUBLE',
+        'FLOAT',
+        'INTEGER',
+        'LONGNVARCHAR',
+        'LONGVARCHAR',
+        'NCHAR',
+        'NUMERIC',
+        'NVARCHAR',
+        'REAL',
+        'SMALLINT',
+        'TIME',
+        'TIMESTAMP',
+        'TINYINT',
+        'VARCHAR'
+    ];
+
+    const ALL_JDBC_TYPES = [
+        {dbName: 'BIT', dbType: -7, javaType: 'Boolean', primitiveType: 'boolean'},
+        {dbName: 'TINYINT', dbType: -6, javaType: 'Byte', primitiveType: 'byte'},
+        {dbName: 'SMALLINT', dbType: 5, javaType: 'Short', primitiveType: 'short'},
+        {dbName: 'INTEGER', dbType: 4, javaType: 'Integer', primitiveType: 'int'},
+        {dbName: 'BIGINT', dbType: -5, javaType: 'Long', primitiveType: 'long'},
+        {dbName: 'FLOAT', dbType: 6, javaType: 'Float', primitiveType: 'float'},
+        {dbName: 'REAL', dbType: 7, javaType: 'Double', primitiveType: 'double'},
+        {dbName: 'DOUBLE', dbType: 8, javaType: 'Double', primitiveType: 'double'},
+        {dbName: 'NUMERIC', dbType: 2, javaType: 'BigDecimal'},
+        {dbName: 'DECIMAL', dbType: 3, javaType: 'BigDecimal'},
+        {dbName: 'CHAR', dbType: 1, javaType: 'String'},
+        {dbName: 'VARCHAR', dbType: 12, javaType: 'String'},
+        {dbName: 'LONGVARCHAR', dbType: -1, javaType: 'String'},
+        {dbName: 'DATE', dbType: 91, javaType: 'Date'},
+        {dbName: 'TIME', dbType: 92, javaType: 'Time'},
+        {dbName: 'TIMESTAMP', dbType: 93, javaType: 'Timestamp'},
+        {dbName: 'BINARY', dbType: -2, javaType: 'Object'},
+        {dbName: 'VARBINARY', dbType: -3, javaType: 'Object'},
+        {dbName: 'LONGVARBINARY', dbType: -4, javaType: 'Object'},
+        {dbName: 'NULL', dbType: 0, javaType: 'Object'},
+        {dbName: 'OTHER', dbType: 1111, javaType: 'Object'},
+        {dbName: 'JAVA_OBJECT', dbType: 2000, javaType: 'Object'},
+        {dbName: 'DISTINCT', dbType: 2001, javaType: 'Object'},
+        {dbName: 'STRUCT', dbType: 2002, javaType: 'Object'},
+        {dbName: 'ARRAY', dbType: 2003, javaType: 'Object'},
+        {dbName: 'BLOB', dbType: 2004, javaType: 'Object'},
+        {dbName: 'CLOB', dbType: 2005, javaType: 'String'},
+        {dbName: 'REF', dbType: 2006, javaType: 'Object'},
+        {dbName: 'DATALINK', dbType: 70, javaType: 'Object'},
+        {dbName: 'BOOLEAN', dbType: 16, javaType: 'Boolean', primitiveType: 'boolean'},
+        {dbName: 'ROWID', dbType: -8, javaType: 'Object'},
+        {dbName: 'NCHAR', dbType: -15, javaType: 'String'},
+        {dbName: 'NVARCHAR', dbType: -9, javaType: 'String'},
+        {dbName: 'LONGNVARCHAR', dbType: -16, javaType: 'String'},
+        {dbName: 'NCLOB', dbType: 2011, javaType: 'String'},
+        {dbName: 'SQLXML', dbType: 2009, javaType: 'Object'}
+    ];
+
+    /*eslint-disable */
+    const JAVA_KEYWORDS = [
+        'abstract',
+        'assert',
+        'boolean',
+        'break',
+        'byte',
+        'case',
+        'catch',
+        'char',
+        'class',
+        'const',
+        'continue',
+        'default',
+        'do',
+        'double',
+        'else',
+        'enum',
+        'extends',
+        'false',
+        'final',
+        'finally',
+        'float',
+        'for',
+        'goto',
+        'if',
+        'implements',
+        'import',
+        'instanceof',
+        'int',
+        'interface',
+        'long',
+        'native',
+        'new',
+        'null',
+        'package',
+        'private',
+        'protected',
+        'public',
+        'return',
+        'short',
+        'static',
+        'strictfp',
+        'super',
+        'switch',
+        'synchronized',
+        'this',
+        'throw',
+        'throws',
+        'transient',
+        'true',
+        'try',
+        'void',
+        'volatile',
+        'while'
+    ];
+    /*eslint-enable */
+
+    const VALID_JAVA_IDENTIFIER = new RegExp('^[a-zA-Z_$][a-zA-Z\\d_$]*$');
+
+    function isValidJavaIdentifier(msg, ident, elemId, panels, panelId) {
+        if (isEmptyString(ident))
+            return ErrorPopover.show(elemId, msg + ' is invalid!', panels, panelId);
+
+        if (_.includes(JAVA_KEYWORDS, ident))
+            return ErrorPopover.show(elemId, msg + ' could not contains reserved java keyword: "' + ident + '"!', panels, panelId);
+
+        if (!VALID_JAVA_IDENTIFIER.test(ident))
+            return ErrorPopover.show(elemId, msg + ' contains invalid identifier: "' + ident + '"!', panels, panelId);
+
+        return true;
+    }
 
-                        newActivePanels.push(idx);
+    function getModel(obj, field) {
+        let path = field.path;
 
-                        ui.activePanels = newActivePanels;
-                    }
-                }
+        if (!isDefined(path) || !isDefined(obj))
+            return obj;
 
-                if (isDefined(focusId))
-                    Focus.move(focusId);
-            }
-        }
+        path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
+        path = path.replace(/^\./, '');           // strip a leading dot
 
-        function showPopoverMessage(ui, panelId, id, message, showTime) {
-            if (popover)
-                popover.hide();
+        const segs = path.split('.');
+        let root = obj;
 
-            if (ui) {
-                ensureActivePanel(ui, panelId);
+        while (segs.length > 0) {
+            const pathStep = segs.shift();
 
-                $timeout(() => _showPopoverMessage(id, message, showTime), ui.isPanelLoaded(panelId) ? 200 : 500);
-            }
-            else
-                _showPopoverMessage(id, message, showTime);
+            if (typeof root[pathStep] === 'undefined')
+                root[pathStep] = {};
 
-            return false;
+            root = root[pathStep];
         }
 
-        function isValidJavaIdentifier(msg, ident, elemId, panels, panelId) {
-            if (isEmptyString(ident))
-                return showPopoverMessage(panels, panelId, elemId, msg + ' is invalid!');
-
-            if (_.includes(JAVA_KEYWORDS, ident))
-                return showPopoverMessage(panels, panelId, elemId, msg + ' could not contains reserved java keyword: "' + ident + '"!');
-
-            if (!VALID_JAVA_IDENTIFIER.test(ident))
-                return showPopoverMessage(panels, panelId, elemId, msg + ' contains invalid identifier: "' + ident + '"!');
+        return root;
+    }
 
-            return true;
+    /**
+     * Extract datasource from cache or cluster.
+     *
+     * @param object Cache or cluster to extract datasource.
+     * @returns {*} Datasource object or null if not set.
+     */
+    function extractDataSource(object) {
+        // Extract from cluster object
+        if (_.get(object, 'discovery.kind') === 'Jdbc') {
+            const datasource = object.discovery.Jdbc;
+
+            if (datasource.dataSourceBean && datasource.dialect)
+                return datasource;
+        } // Extract from cache object
+        else if (_.get(object, 'cacheStoreFactory.kind')) {
+            const storeFactory = object.cacheStoreFactory[object.cacheStoreFactory.kind];
+
+            if (storeFactory.dialect || (storeFactory.connectVia === 'DataSource'))
+                return storeFactory;
         }
 
-        let context = null;
-
-        /**
-         * Calculate width of specified text in body's font.
-         *
-         * @param text Text to calculate width.
-         * @returns {Number} Width of text in pixels.
-         */
-        function measureText(text) {
-            if (!context) {
-                const canvas = document.createElement('canvas');
-
-                context = canvas.getContext('2d');
-
-                const style = window.getComputedStyle(document.getElementsByTagName('body')[0]);
+        return null;
+    }
 
-                context.font = style.fontSize + ' ' + style.fontFamily;
-            }
+    const cacheStoreJdbcDialects = [
+        {value: 'Generic', label: 'Generic JDBC'},
+        {value: 'Oracle', label: 'Oracle'},
+        {value: 'DB2', label: 'IBM DB2'},
+        {value: 'SQLServer', label: 'Microsoft SQL Server'},
+        {value: 'MySQL', label: 'MySQL'},
+        {value: 'PostgreSQL', label: 'PostgreSQL'},
+        {value: 'H2', label: 'H2 database'}
+    ];
+
+    function domainForStoreConfigured(domain) {
+        const isEmpty = !isDefined(domain) || (isEmptyString(domain.databaseSchema) &&
+            isEmptyString(domain.databaseTable) &&
+            _.isEmpty(domain.keyFields) &&
+            _.isEmpty(domain.valueFields));
+
+        return !isEmpty;
+    }
 
-            return context.measureText(text).width;
+    const DS_CHECK_SUCCESS = {checked: true};
+
+    /**
+     * Compare datasources of caches or clusters.
+     *
+     * @param firstObj First cache or cluster.
+     * @param secondObj Second cache or cluster.
+     * @returns {*} Check result object.
+     */
+    function compareDataSources(firstObj, secondObj) {
+        const firstDs = extractDataSource(firstObj);
+        const secondDs = extractDataSource(secondObj);
+
+        if (firstDs && secondDs) {
+            const firstDB = firstDs.dialect;
+            const secondDB = secondDs.dialect;
+
+            if (firstDs.dataSourceBean === secondDs.dataSourceBean && firstDB !== secondDB)
+                return {checked: false, firstObj, firstDB, secondObj, secondDB};
         }
 
-        /**
-         * Compact java full class name by max number of characters.
-         *
-         * @param names Array of class names to compact.
-         * @param nameLength Max available width in characters for simple name.
-         * @returns {*} Array of compacted class names.
-         */
-        function compactByMaxCharts(names, nameLength) {
-            for (let nameIx = 0; nameIx < names.length; nameIx++) {
-                const s = names[nameIx];
-
-                if (s.length > nameLength) {
-                    let totalLength = s.length;
-
-                    const packages = s.split('.');
-
-                    const packageCnt = packages.length - 1;
-
-                    for (let i = 0; i < packageCnt && totalLength > nameLength; i++) {
-                        if (packages[i].length > 0) {
-                            totalLength -= packages[i].length - 1;
-
-                            packages[i] = packages[i][0];
-                        }
-                    }
-
-                    if (totalLength > nameLength) {
-                        const className = packages[packageCnt];
-
-                        const classNameLen = className.length;
+        return DS_CHECK_SUCCESS;
+    }
 
-                        let remains = Math.min(nameLength - totalLength + classNameLen, classNameLen);
+    function compareSQLSchemaNames(firstCache, secondCache) {
+        const firstName = firstCache.sqlSchema;
+        const secondName = secondCache.sqlSchema;
 
-                        if (remains < 3)
-                            remains = Math.min(3, classNameLen);
+        if (firstName && secondName && (firstName === secondName))
+            return {checked: false, firstCache, secondCache};
 
-                        packages[packageCnt] = className.substring(0, remains) + '...';
-                    }
+        return DS_CHECK_SUCCESS;
+    }
 
-                    let result = packages[0];
+    function toJavaName(prefix, name) {
+        const javaName = name ? name.replace(/[^A-Za-z_0-9]+/g, '_') : 'dflt';
 
-                    for (let i = 1; i < packages.length; i++)
-                        result += '.' + packages[i];
+        return prefix + javaName.charAt(0).toLocaleUpperCase() + javaName.slice(1);
+    }
 
-                    names[nameIx] = result;
+    return {
+        getModel,
+        mkOptions(options) {
+            return _.map(options, (option) => {
+                return {value: option, label: isDefined(option) ? option : 'Not set'};
+            });
+        },
+        isDefined,
+        hasProperty(obj, props) {
+            for (const propName in props) {
+                if (props.hasOwnProperty(propName)) {
+                    if (obj[propName])
+                        return true;
                 }
             }
 
-            return names;
-        }
-
-        /**
-         * Compact java full class name by max number of pixels.
-         *
-         * @param names Array of class names to compact.
-         * @param nameLength Max available width in characters for simple name. Used for calculation optimization.
-         * @param nameWidth Maximum available width in pixels for simple name.
-         * @returns {*} Array of compacted class names.
-         */
-        function compactByMaxPixels(names, nameLength, nameWidth) {
-            if (nameWidth <= 0)
-                return names;
-
-            const fitted = [];
-
-            const widthByName = [];
-
-            const len = names.length;
-
-            let divideTo = len;
-
-            for (let nameIx = 0; nameIx < len; nameIx++) {
-                fitted[nameIx] = false;
-
-                widthByName[nameIx] = nameWidth;
-            }
-
-            // Try to distribute space from short class names to long class names.
-            let remains = 0;
-
-            do {
-                for (let nameIx = 0; nameIx < len; nameIx++) {
-                    if (!fitted[nameIx]) {
-                        const curNameWidth = measureText(names[nameIx]);
+            return false;
+        },
+        isEmptyString,
+        SUPPORTED_JDBC_TYPES,
+        findJdbcType(jdbcType) {
+            const res = _.find(ALL_JDBC_TYPES, function (item) {
+                return item.dbType === jdbcType;
+            });
+
+            return res ? res : {dbName: 'Unknown', javaType: 'Unknown'};
+        },
+        javaBuiltInClasses,
+        javaBuiltInTypes,
+        isJavaBuiltInClass,
+        isValidJavaIdentifier,
+        isValidJavaClass(msg, ident, allowBuiltInClass, elemId, packageOnly, panels, panelId) {
+            if (isEmptyString(ident))
+                return ErrorPopover.show(elemId, msg + ' could not be empty!', panels, panelId);
 
-                        if (widthByName[nameIx] > curNameWidth) {
-                            fitted[nameIx] = true;
+            const parts = ident.split('.');
 
-                            remains += widthByName[nameIx] - curNameWidth;
+            const len = parts.length;
 
-                            divideTo -= 1;
+            if (!allowBuiltInClass && isJavaBuiltInClass(ident))
+                return ErrorPopover.show(elemId, msg + ' should not be the Java build-in class!', panels, panelId);
 
-                            widthByName[nameIx] = curNameWidth;
-                        }
-                    }
-                }
+            if (len < 2 && !isJavaBuiltInClass(ident) && !packageOnly)
+                return ErrorPopover.show(elemId, msg + ' does not have package specified!', panels, panelId);
 
-                const remainsByName = remains / divideTo;
+            for (let i = 0; i < parts.length; i++) {
+                const part = parts[i];
 
-                for (let nameIx = 0; nameIx < len; nameIx++) {
-                    if (!fitted[nameIx])
-                        widthByName[nameIx] += remainsByName;
-                }
+                if (!isValidJavaIdentifier(msg, part, elemId, panels, panelId))
+                    return false;
             }
-            while (remains > 0);
 
-            // Compact class names to available for each space.
-            for (let nameIx = 0; nameIx < len; nameIx++) {
-                const s = names[nameIx];
-
-                if (s.length > (nameLength / 2 | 0)) {
-                    let totalWidth = measureText(s);
+            return true;
+        },
+        domainForQueryConfigured(domain) {
+            const isEmpty = !isDefined(domain) || (_.isEmpty(domain.fields) &&
+                _.isEmpty(domain.aliases) &&
+                _.isEmpty(domain.indexes));
 
-                    if (totalWidth > widthByName[nameIx]) {
-                        const packages = s.split('.');
+            return !isEmpty;
+        },
+        domainForStoreConfigured,
+        download(type, name, data) {
+            const file = document.createElement('a');
 
-                        const packageCnt = packages.length - 1;
+            file.setAttribute('href', 'data:' + type + ';charset=utf-8,' + data);
+            file.setAttribute('download', name);
+            file.setAttribute('target', '_self');
 
-                        for (let i = 0; i < packageCnt && totalWidth > widthByName[nameIx]; i++) {
-                            if (packages[i].length > 1) {
-                                totalWidth -= measureText(packages[i].substring(1, packages[i].length));
+            file.style.display = 'none';
 
-                                packages[i] = packages[i][0];
-                            }
-                        }
+            document.body.appendChild(file);
 
-                        let shortPackage = '';
+            file.click();
 
-                        for (let i = 0; i < packageCnt; i++)
-                            shortPackage += packages[i] + '.';
+            document.body.removeChild(file);
+        },
+        getQueryVariable(name) {
+            const attrs = window.location.search.substring(1).split('&');
+            const attr = _.find(attrs, (a) => a === name || (a.indexOf('=') >= 0 && a.substr(0, a.indexOf('=')) === name));
 
-                        const className = packages[packageCnt];
-
-                        const classLen = className.length;
+            if (!isDefined(attr))
+                return null;
 
-                        let minLen = Math.min(classLen, 3);
+            if (attr === name)
+                return true;
 
-                        totalWidth = measureText(shortPackage + className);
+            return attr.substr(attr.indexOf('=') + 1);
+        },
+        cacheStoreJdbcDialects,
+        cacheStoreJdbcDialectsLabel(dialect) {
+            const found = _.find(cacheStoreJdbcDialects, function (dialectVal) {
+                return dialectVal.value === dialect;
+            });
 
-                        // Compact class name if shorten package path is very long.
-                        if (totalWidth > widthByName[nameIx]) {
-                            let maxLen = classLen;
-                            let middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
+            return found ? found.label : null;
+        },
+        checkDataSources(cluster, caches, checkCacheExt) {
+            let res = DS_CHECK_SUCCESS;
 
-                            while (middleLen !== minLen && middleLen !== maxLen) {
-                                const middleLenPx = measureText(shortPackage + className.substr(0, middleLen) + '...');
+            _.find(caches, function (curCache, curIx) {
+                res = compareDataSources(curCache, cluster);
 
-                                if (middleLenPx > widthByName[nameIx])
-                                    maxLen = middleLen;
-                                else
-                                    minLen = middleLen;
+                if (!res.checked)
+                    return true;
 
-                                middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
-                            }
+                if (isDefined(checkCacheExt)) {
+                    if (checkCacheExt._id !== curCache._id) {
+                        res = compareDataSources(checkCacheExt, curCache);
 
-                            names[nameIx] = shortPackage + className.substring(0, middleLen) + '...';
-                        }
-                        else
-                            names[nameIx] = shortPackage + className;
+                        return !res.checked;
                     }
-                }
-            }
-
-            return names;
-        }
 
-        /**
-         * Compact any string by max number of pixels.
-         *
-         * @param label String to compact.
-         * @param nameWidth Maximum available width in pixels for simple name.
-         * @returns {*} Compacted string.
-         */
-        function compactLabelByPixels(label, nameWidth) {
-            if (nameWidth <= 0)
-                return label;
-
-            const totalWidth = measureText(label);
-
-            if (totalWidth > nameWidth) {
-                let maxLen = label.length;
-                let minLen = Math.min(maxLen, 3);
-                let middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
-
-                while (middleLen !== minLen && middleLen !== maxLen) {
-                    const middleLenPx = measureText(label.substr(0, middleLen) + '...');
-
-                    if (middleLenPx > nameWidth)
-                        maxLen = middleLen;
-                    else
-                        minLen = middleLen;
-
-                    middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
+                    return false;
                 }
 
-                return label.substring(0, middleLen) + '...';
-            }
-
-            return label;
-        }
-
-        /**
-         * Calculate available width for text in link to edit element.
-         *
-         * @param index Showed index of element for calculation of maximum width in pixels.
-         * @param id Id of contains link table.
-         * @returns {*[]} First element is length of class for single value, second element is length for pair vlaue.
-         */
-        function availableWidth(index, id) {
-            const idElem = $('#' + id);
-
-            let width = 0;
-
-            switch (idElem.prop('tagName')) {
-                // Detection of available width in presentation table row.
-                case 'TABLE':
-                    const cont = $(idElem.find('tr')[index - 1]).find('td')[0];
-
-                    width = cont.clientWidth;
+                return _.find(caches, function (checkCache, checkIx) {
+                    if (checkIx < curIx) {
+                        res = compareDataSources(checkCache, curCache);
 
-                    if (width > 0) {
-                        const children = $(cont).children(':not("a")');
-
-                        _.forEach(children, function(child) {
-                            if ('offsetWidth' in child)
-                                width -= $(child).outerWidth(true);
-                        });
+                        return !res.checked;
                     }
 
-                    break;
-
-                // Detection of available width in dropdown row.
-                case 'A':
-                    width = idElem.width();
-
-                    $(idElem).children(':not("span")').each(function(ix, child) {
-                        if ('offsetWidth' in child)
-                            width -= child.offsetWidth;
-                    });
-
-                    break;
-
-                default:
-            }
-
-            return width | 0;
-        }
-
-        function getModel(obj, field) {
-            let path = field.path;
-
-            if (!isDefined(path) || !isDefined(obj))
-                return obj;
-
-            path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
-            path = path.replace(/^\./, '');           // strip a leading dot
-
-            const segs = path.split('.');
-            let root = obj;
-
-            while (segs.length > 0) {
-                const pathStep = segs.shift();
-
-                if (typeof root[pathStep] === 'undefined')
-                    root[pathStep] = {};
-
-                root = root[pathStep];
-            }
-
-            return root;
-        }
-
-        /**
-         * Extract datasource from cache or cluster.
-         *
-         * @param object Cache or cluster to extract datasource.
-         * @returns {*} Datasource object or null if not set.
-         */
-        function extractDataSource(object) {
-            // Extract from cluster object
-            if (_.get(object, 'discovery.kind') === 'Jdbc') {
-                const datasource = object.discovery.Jdbc;
-
-                if (datasource.dataSourceBean && datasource.dialect)
-                    return datasource;
-            } // Extract from cache object
-            else if (_.get(object, 'cacheStoreFactory.kind')) {
-                const storeFactory = object.cacheStoreFactory[object.cacheStoreFactory.kind];
-
-                if (storeFactory.dialect || (storeFactory.connectVia === 'DataSource'))
-                    return storeFactory;
-            }
-
-            return null;
-        }
-
-        const cacheStoreJdbcDialects = [
-            {value: 'Generic', label: 'Generic JDBC'},
-            {value: 'Oracle', label: 'Oracle'},
-            {value: 'DB2', label: 'IBM DB2'},
-            {value: 'SQLServer', label: 'Microsoft SQL Server'},
-            {value: 'MySQL', label: 'MySQL'},
-            {value: 'PostgreSQL', label: 'PostgreSQL'},
-            {value: 'H2', label: 'H2 database'}
-        ];
-
-        function domainForStoreConfigured(domain) {
-            const isEmpty = !isDefined(domain) || (isEmptyString(domain.databaseSchema) &&
-                isEmptyString(domain.databaseTable) &&
-                _.isEmpty(domain.keyFields) &&
-                _.isEmpty(domain.valueFields));
-
-            return !isEmpty;
-        }
-
-        const DS_CHECK_SUCCESS = { checked: true };
-
-        /**
-         * Compare datasources of caches or clusters.
-         *
-         * @param firstObj First cache or cluster.
-         * @param secondObj Second cache or cluster.
-         * @returns {*} Check result object.
-         */
-        function compareDataSources(firstObj, secondObj) {
-            const firstDs = extractDataSource(firstObj);
-            const secondDs = extractDataSource(secondObj);
-
-            if (firstDs && secondDs) {
-                const firstDB = firstDs.dialect;
-                const secondDB = secondDs.dialect;
-
-                if (firstDs.dataSourceBean === secondDs.dataSourceBean && firstDB !== secondDB)
-                    return {checked: false, firstObj, firstDB, secondObj, secondDB};
-            }
-
-            return DS_CHECK_SUCCESS;
-        }
-
-        function compareSQLSchemaNames(firstCache, secondCache) {
-            const firstName = firstCache.sqlSchema;
-            const secondName = secondCache.sqlSchema;
-
-            if (firstName && secondName && (firstName === secondName))
-                return {checked: false, firstCache, secondCache};
-
-            return DS_CHECK_SUCCESS;
-        }
-
-        function toJavaName(prefix, name) {
-            const javaName = name ? name.replace(/[^A-Za-z_0-9]+/g, '_') : 'dflt';
-
-            return prefix + javaName.charAt(0).toLocaleUpperCase() + javaName.slice(1);
-        }
-
-        return {
-            getModel,
-            mkOptions(options) {
-                return _.map(options, (option) => {
-                    return {value: option, label: isDefined(option) ? option : 'Not set'};
+                    return false;
                 });
-            },
-            isDefined,
-            hasProperty(obj, props) {
-                for (const propName in props) {
-                    if (props.hasOwnProperty(propName)) {
-                        if (obj[propName])
-                            return true;
-                    }
-                }
-
-                return false;
-            },
-            isEmptyString,
-            SUPPORTED_JDBC_TYPES,
-            findJdbcType(jdbcType) {
-                const res = _.find(ALL_JDBC_TYPES, function(item) {
-                    return item.dbType === jdbcType;
-                });
-
-                return res ? res : {dbName: 'Unknown', javaType: 'Unknown'};
-            },
-            javaBuiltInClasses,
-            javaBuiltInTypes,
-            isJavaBuiltInClass,
-            isValidJavaIdentifier,
-            isValidJavaClass(msg, ident, allowBuiltInClass, elemId, packageOnly, panels, panelId) {
-                if (isEmptyString(ident))
-                    return showPopoverMessage(panels, panelId, elemId, msg + ' could not be empty!');
-
-                const parts = ident.split('.');
+            });
 
-                const len = parts.length;
-
-                if (!allowBuiltInClass && isJavaBuiltInClass(ident))
-                    return showPopoverMessage(panels, panelId, elemId, msg + ' should not be the Java build-in class!');
-
-                if (len < 2 && !isJavaBuiltInClass(ident) && !packageOnly)
-                    return showPopoverMessage(panels, panelId, elemId, msg + ' does not have package specified!');
-
-                for (let i = 0; i < parts.length; i++) {
-                    const part = parts[i];
-
-                    if (!isValidJavaIdentifier(msg, part, elemId, panels, panelId))
-                        return false;
-                }
-
-                return true;
-            },
-            domainForQueryConfigured(domain) {
-                const isEmpty = !isDefined(domain) || (_.isEmpty(domain.fields) &&
-                    _.isEmpty(domain.aliases) &&
-                    _.isEmpty(domain.indexes));
-
-                return !isEmpty;
-            },
-            domainForStoreConfigured,
-            /**
-             * Cut class name by width in pixel or width in symbol count.
-             *
-             * @param id Id of parent table.
-             * @param index Row number in table.
-             * @param maxLength Maximum length in symbols for all names.
-             * @param names Array of class names to compact.
-             * @param divider String to visualy divide items.
-             * @returns {*} Array of compacted class names.
-             */
-            compactJavaName(id, index, maxLength, names, divider) {
-                divider = ' ' + divider + ' ';
-
-                const prefix = index + ') ';
-
-                const nameCnt = names.length;
-
-                const nameLength = ((maxLength - 3 * (nameCnt - 1)) / nameCnt) | 0;
-
-                try {
-                    const nameWidth = (availableWidth(index, id) - measureText(prefix) - (nameCnt - 1) * measureText(divider)) /
-                        nameCnt | 0;
-
-                    // HTML5 calculation of showed message width.
-                    names = compactByMaxPixels(names, nameLength, nameWidth);
-                }
-                catch (err) {
-                    names = compactByMaxCharts(names, nameLength);
-                }
-
-                let result = prefix + names[0];
-
-                for (let nameIx = 1; nameIx < names.length; nameIx++)
-                    result += divider + names[nameIx];
-
-                return result;
-            },
-            /**
-             * Compact text by width in pixels or symbols count.
-             *
-             * @param id Id of parent table.
-             * @param index Row number in table.
-             * @param maxLength Maximum length in symbols for all names.
-             * @param label Text to compact.
-             * @returns Compacted label text.
-             */
-            compactTableLabel(id, index, maxLength, label) {
-                label = index + ') ' + label;
-
-                try {
-                    const nameWidth = availableWidth(index, id) | 0;
-
-                    // HTML5 calculation of showed message width.
-                    label = compactLabelByPixels(label, nameWidth);
-                }
-                catch (err) {
-                    const nameLength = maxLength - 3 | 0;
-
-                    label = label.length > maxLength ? label.substr(0, nameLength) + '...' : label;
-                }
+            return res;
+        },
+        checkCacheSQLSchemas(caches, checkCacheExt) {
+            let res = DS_CHECK_SUCCESS;
 
-                return label;
-            },
-            widthIsSufficient(id, index, text) {
-                try {
-                    const available = availableWidth(index, id);
+            _.find(caches, (curCache, curIx) => {
+                if (isDefined(checkCacheExt)) {
+                    if (checkCacheExt._id !== curCache._id) {
+                        res = compareSQLSchemaNames(checkCacheExt, curCache);
 
-                    const required = measureText(text);
+                        return !res.checked;
+                    }
 
-                    return !available || available >= Math.floor(required);
-                }
-                catch (err) {
-                    return true;
-                }
-            },
-            ensureActivePanel(panels, id, focusId) {
-                ensureActivePanel(panels, id, focusId);
-            },
-            showPopoverMessage,
-            hidePopover() {
-                if (popover)
-                    popover.hide();
-            },
-            confirmUnsavedChanges(dirty, selectFunc) {
-                if (dirty) {
-                    if ($window.confirm('You have unsaved changes.\n\nAre you sure you want to discard them?'))
-                        selectFunc();
+                    return false;
                 }
-                else
-                    selectFunc();
-            },
-            saveBtnTipText(dirty, objectName) {
-                if (dirty)
-                    return 'Save ' + objectName;
 
-                return 'Nothing to save';
-            },
-            download(type, name, data) {
-                const file = document.createElement('a');
+                return _.find(caches, function (checkCache, checkIx) {
+                    if (checkIx < curIx) {
+                        res = compareSQLSchemaNames(checkCache, curCache);
 
-                file.setAttribute('href', 'data:' + type + ';charset=utf-8,' + data);
-                file.setAttribute('download', name);
-                file.setAttribute('target', '_self');
+                        return !res.checked;
+                    }
 
-                file.style.display = 'none';
+                    return false;
+                });
+            });
 
-                document.body.appendChild(file);
+            return res;
+        },
+        autoCacheStoreConfiguration(cache, domains) {
+            const cacheStoreFactory = isDefined(cache.cacheStoreFactory) &&
+                isDefined(cache.cacheStoreFactory.kind);
 
-                file.click();
+            if (!cacheStoreFactory && _.findIndex(domains, domainForStoreConfigured) >= 0) {
+                const dflt = !cache.readThrough && !cache.writeThrough;
 
-                document.body.removeChild(file);
-            },
-            formUI() {
                 return {
-                    ready: false,
-                    expanded: false,
-                    loadedPanels: [],
-                    loadPanel(pnl) {
-                        if (!_.includes(this.loadedPanels, pnl))
-                            this.loadedPanels.push(pnl);
+                    cacheStoreFactory: {
+                        kind: 'CacheJdbcPojoStoreFactory',
+                        CacheJdbcPojoStoreFactory: {
+                            dataSourceBean: toJavaName('ds', cache.name),
+                            dialect: 'Generic'
+                        },
+                        CacheJdbcBlobStoreFactory: {connectVia: 'DataSource'}
                     },
-                    isPanelLoaded(pnl) {
-                        return _.includes(this.loadedPanels, pnl);
-                    }
+                    readThrough: dflt || cache.readThrough,
+                    writeThrough: dflt || cache.writeThrough
                 };
-            },
-            getQueryVariable(name) {
-                const attrs = window.location.search.substring(1).split('&');
-                const attr = _.find(attrs, (a) => a === name || (a.indexOf('=') >= 0 && a.substr(0, a.indexOf('=')) === name));
-
-                if (!isDefined(attr))
-                    return null;
-
-                if (attr === name)
-                    return true;
-
-                return attr.substr(attr.indexOf('=') + 1);
-            },
-            cacheStoreJdbcDialects,
-            cacheStoreJdbcDialectsLabel(dialect) {
-                const found = _.find(cacheStoreJdbcDialects, function(dialectVal) {
-                    return dialectVal.value === dialect;
-                });
-
-                return found ? found.label : null;
-            },
-            checkDataSources(cluster, caches, checkCacheExt) {
-                let res = DS_CHECK_SUCCESS;
-
-                _.find(caches, function(curCache, curIx) {
-                    res = compareDataSources(curCache, cluster);
-
-                    if (!res.checked)
-                        return true;
-
-                    if (isDefined(checkCacheExt)) {
-                        if (checkCacheExt._id !== curCache._id) {
-                            res = compareDataSources(checkCacheExt, curCache);
+            }
+        },
+        autoClusterSwapSpiConfiguration(cluster, caches) {
+            const swapConfigured = cluster.swapSpaceSpi && cluster.swapSpaceSpi.kind;
 
-                            return !res.checked;
-                        }
+            if (!swapConfigured && _.find(caches, (cache) => cache.swapEnabled))
+                return {swapSpaceSpi: {kind: 'FileSwapSpaceSpi'}};
 
-                        return false;
-                    }
+            return null;
+        },
+        randomString(len) {
+            const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+            const possibleLen = possible.length;
 
-                    return _.find(caches, function(checkCache, checkIx) {
-                        if (checkIx < curIx) {
-                            res = compareDataSources(checkCache, curCache);
+            let res = '';
 
-                            return !res.checked;
-                        }
+            for (let i = 0; i < len; i++)
+                res += possible.charAt(Math.floor(Math.random() * possibleLen));
 
-                        return false;
-                    });
-                });
+            return res;
+        },
+        checkFieldValidators(ui) {
+            const form = ui.inputForm;
+            const errors = form.$error;
+            const errKeys = Object.keys(errors);
 
-                return res;
-            },
-            checkCacheSQLSchemas(caches, checkCacheExt) {
-                let res = DS_CHECK_SUCCESS;
+            if (errKeys && errKeys.length > 0) {
+                const firstErrorKey = errKeys[0];
 
-                _.find(caches, (curCache, curIx) => {
-                    if (isDefined(checkCacheExt)) {
-                        if (checkCacheExt._id !== curCache._id) {
-                            res = compareSQLSchemaNames(checkCacheExt, curCache);
+                const firstError = errors[firstErrorKey][0];
+                const actualError = firstError.$error[firstErrorKey][0];
 
-                            return !res.checked;
-                        }
+                const errNameFull = actualError.$name;
+                const errNameShort = errNameFull.endsWith('TextInput') ? errNameFull.substring(0, errNameFull.length - 9) : errNameFull;
 
-                        return false;
+                const extractErrorMessage = function (errName) {
+                    try {
+                        return errors[firstErrorKey][0].$errorMessages[errName][firstErrorKey];
                     }
-
-                    return _.find(caches, function(checkCache, checkIx) {
-                        if (checkIx < curIx) {
-                            res = compareSQLSchemaNames(checkCache, curCache);
-
-                            return !res.checked;
-                        }
-
-                        return false;
-                    });
-                });
-
-                return res;
-            },
-            autoCacheStoreConfiguration(cache, domains) {
-                const cacheStoreFactory = isDefined(cache.cacheStoreFactory) &&
-                    isDefined(cache.cacheStoreFactory.kind);
-
-                if (!cacheStoreFactory && _.findIndex(domains, domainForStoreConfigured) >= 0) {
-                    const dflt = !cache.readThrough && !cache.writeThrough;
-
-                    return {
-                        cacheStoreFactory: {
-                            kind: 'CacheJdbcPojoStoreFactory',
-                            CacheJdbcPojoStoreFactory: {
-                                dataSourceBean: toJavaName('ds', cache.name),
-                                dialect: 'Generic'
-                            },
-                            CacheJdbcBlobStoreFactory: { connectVia: 'DataSource' }
-                        },
-                        readThrough: dflt || cache.readThrough,
-                        writeThrough: dflt || cache.writeThrough
-                    };
-                }
-            },
-            autoClusterSwapSpiConfiguration(cluster, caches) {
-                const swapConfigured = cluster.swapSpaceSpi && cluster.swapSpaceSpi.kind;
-
-                if (!swapConfigured && _.find(caches, (cache) => cache.swapEnabled))
-                    return {swapSpaceSpi: {kind: 'FileSwapSpaceSpi'}};
-
-                return null;
-            },
-            randomString(len) {
-                const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
-                const possibleLen = possible.length;
-
-                let res = '';
-
-                for (let i = 0; i < len; i++)
-                    res += possible.charAt(Math.floor(Math.random() * possibleLen));
-
-                return res;
-            },
-            checkFieldValidators(ui) {
-                const form = ui.inputForm;
-                const errors = form.$error;
-                const errKeys = Object.keys(errors);
-
-                if (errKeys && errKeys.length > 0) {
-                    const firstErrorKey = errKeys[0];
-
-                    const firstError = errors[firstErrorKey][0];
-                    const actualError = firstError.$error[firstErrorKey][0];
-
-                    const errNameFull = actualError.$name;
-                    const errNameShort = errNameFull.endsWith('TextInput') ? errNameFull.substring(0, errNameFull.length - 9) : errNameFull;
-
-                    const extractErrorMessage = function(errName) {
+                    catch (ignored) {
                         try {
-                            return errors[firstErrorKey][0].$errorMessages[errName][firstErrorKey];
+                            return form[firstError.$name].$errorMessages[errName][firstErrorKey];
                         }
-                        catch (ignored) {
-                            try {
-                                return form[firstError.$name].$errorMessages[errName][firstErrorKey];
-                            }
-                            catch (ignited) {
-                                return false;
-                            }
+                        catch (ignited) {
+                            return false;
                         }
-                    };
+                    }
+                };
 
-                    const msg = extractErrorMessage(errNameFull) || extractErrorMessage(errNameShort) || 'Invalid value!';
+                const msg = extractErrorMessage(errNameFull) || extractErrorMessage(errNameShort) || 'Invalid value!';
 
-                    return showPopoverMessage(ui, firstError.$name, errNameFull, msg);
-                }
-
-                return true;
+                return ErrorPopover.show(errNameFull, msg, ui, firstError.$name);
             }
-        };
-    }
-]];
+
+            return true;
+        }
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/27176d59/modules/web-console/frontend/controllers/caches-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/caches-controller.js b/modules/web-console/frontend/controllers/caches-controller.js
index 90c82b4..3a8a849 100644
--- a/modules/web-console/frontend/controllers/caches-controller.js
+++ b/modules/web-console/frontend/controllers/caches-controller.js
@@ -17,8 +17,8 @@
 
 // Controller for Caches screen.
 export default ['cachesController', [
-    '$scope', '$http', '$state', '$filter', '$timeout', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'igniteConfigurationResource',
-    function($scope, $http, $state, $filter, $timeout, LegacyUtils, Messages, Confirm, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, Resource) {
+    '$scope', '$http', '$state', '$filter', '$timeout', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'igniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils',
+    function($scope, $http, $state, $filter, $timeout, LegacyUtils, Messages, Confirm, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, Resource, ErrorPopover, FormUtils) {
         UnsavedChangesGuard.install($scope);
 
         const emptyCache = {empty: true};
@@ -34,17 +34,14 @@ export default ['cachesController', [
         // We need to initialize backupItem with empty object in order to properly used from angular directives.
         $scope.backupItem = emptyCache;
 
-        $scope.ui = LegacyUtils.formUI();
+        $scope.ui = FormUtils.formUI();
         $scope.ui.activePanels = [0];
         $scope.ui.topPanels = [0, 1, 2, 3];
 
-        $scope.hidePopover = LegacyUtils.hidePopover;
-        $scope.saveBtnTipText = LegacyUtils.saveBtnTipText;
-        $scope.widthIsSufficient = LegacyUtils.widthIsSufficient;
+        $scope.saveBtnTipText = FormUtils.saveBtnTipText;
+        $scope.widthIsSufficient = FormUtils.widthIsSufficient;
         $scope.offHeapMode = 'DISABLED';
 
-        const showPopoverMessage = LegacyUtils.showPopoverMessage;
-
         $scope.contentVisible = function() {
             const item = $scope.backupItem;
 
@@ -54,7 +51,7 @@ export default ['cachesController', [
         $scope.toggleExpanded = function() {
             $scope.ui.expanded = !$scope.ui.expanded;
 
-            LegacyUtils.hidePopover();
+            ErrorPopover.hide();
         };
 
         $scope.caches = [];
@@ -162,6 +159,10 @@ export default ['cachesController', [
                 }, true);
 
                 $scope.$watch('backupItem.offHeapMode', setOffHeapMaxMemory);
+
+                $scope.$watch('ui.activePanels.length', () => {
+                    ErrorPopover.hide();
+                });
             })
             .catch(Messages.showError)
             .then(() => {
@@ -206,7 +207,7 @@ export default ['cachesController', [
                     $state.go('base.configuration.caches');
             }
 
-            LegacyUtils.confirmUnsavedChanges($scope.backupItem && $scope.ui.inputForm.$dirty, selectItem);
+            FormUtils.confirmUnsavedChanges($scope.backupItem && $scope.ui.inputForm.$dirty, selectItem);
         };
 
         $scope.linkId = () => $scope.backupItem._id ? $scope.backupItem._id : 'create';
@@ -227,7 +228,7 @@ export default ['cachesController', [
 
         // Add new cache.
         $scope.createItem = function(linkId) {
-            $timeout(() => LegacyUtils.ensureActivePanel($scope.ui, 'general', 'cacheName'));
+            $timeout(() => FormUtils.ensureActivePanel($scope.ui, 'general', 'cacheName'));
 
             $scope.selectItem(null, prepareNewItem(linkId));
         };
@@ -260,18 +261,20 @@ export default ['cachesController', [
 
             if (!checkRes.checked) {
                 if (_.get(checkRes.secondObj, 'discovery.kind') === 'Jdbc') {
-                    return showPopoverMessage($scope.ui, 'store', checkRes.firstObj.cacheStoreFactory.kind === 'CacheJdbcPojoStoreFactory' ? 'pojoDialect' : 'blobDialect',
+                    return ErrorPopover.show(checkRes.firstObj.cacheStoreFactory.kind === 'CacheJdbcPojoStoreFactory' ? 'pojoDialect' : 'blobDialect',
                         'Found cluster "' + failCluster.label + '" with the same data source bean name "' +
                         checkRes.secondObj.discovery.Jdbc.dataSourceBean + '" and different database: "' +
                         LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.firstDB) + '" in current cache and "' +
-                        LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.secondDB) + '" in"' + checkRes.secondObj.label + '" cluster', 10000);
+                        LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.secondDB) + '" in"' + checkRes.secondObj.label + '" cluster',
+                        $scope.ui, 'store', 10000);
                 }
 
-                return showPopoverMessage($scope.ui, 'store', checkRes.firstObj.cacheStoreFactory.kind === 'CacheJdbcPojoStoreFactory' ? 'pojoDialect' : 'blobDialect',
+                return ErrorPopover.show(checkRes.firstObj.cacheStoreFactory.kind === 'CacheJdbcPojoStoreFactory' ? 'pojoDialect' : 'blobDialect',
                     'Found cache "' + checkRes.secondObj.name + '" in cluster "' + failCluster.label + '" ' +
                     'with the same data source bean name "' + checkRes.firstObj.cacheStoreFactory[checkRes.firstObj.cacheStoreFactory.kind].dataSourceBean +
                     '" and different database: "' + LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.firstDB) + '" in current cache and "' +
-                    LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.secondDB) + '" in "' + checkRes.secondObj.name + '" cache', 10000);
+                    LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.secondDB) + '" in "' + checkRes.secondObj.name + '" cache',
+                    $scope.ui, 'store', 10000);
             }
 
             return true;
@@ -291,9 +294,10 @@ export default ['cachesController', [
             });
 
             if (!checkRes.checked) {
-                return showPopoverMessage($scope.ui, 'query', 'sqlSchema',
+                return ErrorPopover.show('sqlSchema',
                     'Found cache "' + checkRes.secondCache.name + '" in cluster "' + failCluster.label + '" ' +
-                    'with the same SQL schema name "' + checkRes.firstCache.sqlSchema + '"', 10000);
+                    'with the same SQL schema name "' + checkRes.firstCache.sqlSchema + '"',
+                    $scope.ui, 'query', 10000);
             }
 
             return true;
@@ -321,35 +325,35 @@ export default ['cachesController', [
             }
 
             if ((item.readThrough || item.writeThrough) && !cacheStoreFactorySelected)
-                return showPopoverMessage($scope.ui, 'store', 'cacheStoreFactory', (item.readThrough ? 'Read' : 'Write') + ' through are enabled but store is not configured!');
+                return ErrorPopover.show('cacheStoreFactory', (item.readThrough ? 'Read' : 'Write') + ' through are enabled but store is not configured!', $scope.ui, 'store');
 
             if (item.writeBehindEnabled && !cacheStoreFactorySelected)
-                return showPopoverMessage($scope.ui, 'store', 'cacheStoreFactory', 'Write behind enabled but store is not configured!');
+                return ErrorPopover.show('cacheStoreFactory', 'Write behind enabled but store is not configured!', $scope.ui, 'store');
 
             if (cacheStoreFactorySelected && !item.readThrough && !item.writeThrough)
-                return showPopoverMessage($scope.ui, 'store', 'readThroughTooltip', 'Store is configured but read/write through are not enabled!');
+                return ErrorPopover.show('readThroughTooltip', 'Store is configured but read/write through are not enabled!', $scope.ui, 'store');
 
             return true;
         }
 
         // Check cache logical consistency.
         function validate(item) {
-            LegacyUtils.hidePopover();
+            ErrorPopover.hide();
 
             if (LegacyUtils.isEmptyString(item.name))
-                return showPopoverMessage($scope.ui, 'general', 'cacheName', 'Cache name should not be empty!');
+                return ErrorPopover.show('cacheName', 'Cache name should not be empty!', $scope.ui, 'general');
 
             if (item.memoryMode === 'ONHEAP_TIERED' && item.offHeapMaxMemory > 0 && !LegacyUtils.isDefined(item.evictionPolicy.kind))
-                return showPopoverMessage($scope.ui, 'memory', 'evictionPolicyKind', 'Eviction policy should not be configured!');
+                return ErrorPopover.show('evictionPolicyKind', 'Eviction policy should not be configured!', $scope.ui, 'memory');
 
             if (!LegacyUtils.checkFieldValidators($scope.ui))
                 return false;
 
             if (item.memoryMode === 'OFFHEAP_VALUES' && !_.isEmpty(item.domains))
-                return showPopoverMessage($scope.ui, 'memory', 'memoryMode', 'Query indexing could not be enabled while values are stored off-heap!');
+                return ErrorPopover.show('memoryMode', 'Query indexing could not be enabled while values are stored off-heap!', $scope.ui, 'memory');
 
             if (item.memoryMode === 'OFFHEAP_TIERED' && item.offHeapMaxMemory === -1)
-                return showPopoverMessage($scope.ui, 'memory', 'offHeapMode', 'Invalid value!');
+                return ErrorPopover.show('offHeapMode', 'Invalid value!', $scope.ui, 'memory');
 
             if (!checkSQLSchemas())
                 return false;
@@ -358,10 +362,10 @@ export default ['cachesController', [
                 return false;
 
             if (item.writeBehindFlushSize === 0 && item.writeBehindFlushFrequency === 0)
-                return showPopoverMessage($scope.ui, 'store', 'writeBehindFlushSize', 'Both "Flush frequency" and "Flush size" are not allowed as 0!');
+                return ErrorPopover.show('writeBehindFlushSize', 'Both "Flush frequency" and "Flush size" are not allowed as 0!', $scope.ui, 'store');
 
             if (item.nodeFilter && item.nodeFilter.kind === 'OnNodes' && _.isEmpty(item.nodeFilter.OnNodes.nodeIds))
-                return showPopoverMessage($scope.ui, 'nodeFilter', 'nodeFilter-title', 'At least one node ID should be specified!');
+                return ErrorPopover.show('nodeFilter-title', 'At least one node ID should be specified!', $scope.ui, 'nodeFilter');
 
             return true;
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/27176d59/modules/web-console/frontend/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/controllers/clusters-controller.js b/modules/web-console/frontend/controllers/clusters-controller.js
index 3a6d93c..7389578 100644
--- a/modules/web-console/frontend/controllers/clusters-controller.js
+++ b/modules/web-console/frontend/controllers/clusters-controller.js
@@ -17,8 +17,8 @@
 
 // Controller for Clusters screen.
 export default ['clustersController', [
-    '$rootScope', '$scope', '$http', '$state', '$timeout', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'igniteEventGroups', 'DemoInfo', 'IgniteLegacyTable', 'igniteConfigurationResource',
-    function($root, $scope, $http, $state, $timeout, LegacyUtils, Messages, Confirm, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, igniteEventGroups, DemoInfo, LegacyTable, Resource) {
+    '$rootScope', '$scope', '$http', '$state', '$timeout', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'igniteEventGroups', 'DemoInfo', 'IgniteLegacyTable', 'igniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils',
+    function($root, $scope, $http, $state, $timeout, LegacyUtils, Messages, Confirm, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, igniteEventGroups, DemoInfo, LegacyTable, Resource, ErrorPopover, FormUtils) {
         UnsavedChangesGuard.install($scope);
 
         const emptyCluster = {empty: true};
@@ -43,8 +43,6 @@ export default ['clustersController', [
             'collision.JobStealing.stealingAttributes': {id: 'CAttribute', idPrefix: 'Key', searchCol: 'name', valueCol: 'key', dupObjName: 'name', group: 'collision'}
         };
 
-        const showPopoverMessage = LegacyUtils.showPopoverMessage;
-
         $scope.tablePairValid = function(item, field, index) {
             const pairField = pairFields[field.model];
 
@@ -60,7 +58,7 @@ export default ['clustersController', [
 
                     // Found duplicate by key.
                     if (idx >= 0 && idx !== index)
-                        return showPopoverMessage($scope.ui, pairField.group, LegacyTable.tableFieldId(index, pairField.idPrefix + pairField.id), 'Attribute with such ' + pairField.dupObjName + ' already exists!');
+                        return ErrorPopover.show(LegacyTable.tableFieldId(index, pairField.idPrefix + pairField.id), 'Attribute with such ' + pairField.dupObjName + ' already exists!', $scope.ui, pairField.group);
                 }
             }
 
@@ -142,13 +140,12 @@ export default ['clustersController', [
         // We need to initialize backupItem with empty object in order to properly used from angular directives.
         $scope.backupItem = emptyCluster;
 
-        $scope.ui = LegacyUtils.formUI();
+        $scope.ui = FormUtils.formUI();
         $scope.ui.activePanels = [0];
         $scope.ui.topPanels = [0];
 
-        $scope.hidePopover = LegacyUtils.hidePopover;
-        $scope.saveBtnTipText = LegacyUtils.saveBtnTipText;
-        $scope.widthIsSufficient = LegacyUtils.widthIsSufficient;
+        $scope.saveBtnTipText = FormUtils.saveBtnTipText;
+        $scope.widthIsSufficient = FormUtils.widthIsSufficient;
 
         $scope.contentVisible = function() {
             const item = $scope.backupItem;
@@ -159,7 +156,7 @@ export default ['clustersController', [
         $scope.toggleExpanded = function() {
             $scope.ui.expanded = !$scope.ui.expanded;
 
-            LegacyUtils.hidePopover();
+            ErrorPopover.hide();
         };
 
         $scope.discoveries = [
@@ -249,6 +246,10 @@ export default ['clustersController', [
                         form.$setDirty();
                 }, true);
 
+                $scope.$watch('ui.activePanels.length', () => {
+                    ErrorPopover.hide();
+                });
+
                 if ($root.IgniteDemoMode && sessionStorage.showDemoInfo !== 'true') {
                     sessionStorage.showDemoInfo = 'true';
 
@@ -294,7 +295,7 @@ export default ['clustersController', [
                     $state.go('base.configuration.clusters');
             }
 
-            LegacyUtils.confirmUnsavedChanges($scope.backupItem && $scope.ui.inputForm.$dirty, selectItem);
+            FormUtils.confirmUnsavedChanges($scope.backupItem && $scope.ui.inputForm.$dirty, selectItem);
         };
 
         $scope.linkId = () => $scope.backupItem._id ? $scope.backupItem._id : 'create';
@@ -321,7 +322,7 @@ export default ['clustersController', [
 
         // Add new cluster.
         $scope.createItem = function(linkId) {
-            $timeout(() => LegacyUtils.ensureActivePanel($scope.ui, 'general', 'clusterName'));
+            $timeout(() => FormUtils.ensureActivePanel($scope.ui, 'general', 'clusterName'));
 
             $scope.selectItem(null, prepareNewItem(linkId));
         };
@@ -342,18 +343,20 @@ export default ['clustersController', [
 
             if (!checkRes.checked) {
                 if (_.get(checkRes.secondObj, 'discovery.kind') === 'Jdbc') {
-                    return showPopoverMessage($scope.ui, 'general', 'dialect',
+                    return ErrorPopover.show('dialect',
                         'Found cache "' + checkRes.firstObj.name + '" with the same data source bean name "' +
                         item.discovery.Jdbc.dataSourceBean + '" and different database: "' +
                         LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.secondDB) + '" in current cluster and "' +
-                        LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.firstDB) + '" in "' + checkRes.firstObj.name + '" cache', 10000);
+                        LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.firstDB) + '" in "' + checkRes.firstObj.name + '" cache',
+                        $scope.ui, 'general', 10000);
                 }
 
-                return showPopoverMessage($scope.ui, 'general', 'caches',
+                return ErrorPopover.show('caches',
                     'Found caches "' + checkRes.firstObj.name + '" and "' + checkRes.secondObj.name + '" ' +
                     'with the same data source bean name "' + checkRes.firstObj.cacheStoreFactory[checkRes.firstObj.cacheStoreFactory.kind].dataSourceBean +
                     '" and different databases: "' + LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.firstDB) + '" in "' + checkRes.firstObj.name + '" and "' +
-                    LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.secondDB) + '" in "' + checkRes.secondObj.name + '" cache', 10000);
+                    LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.secondDB) + '" in "' + checkRes.secondObj.name + '" cache',
+                    $scope.ui, 'general', 10000);
             }
 
             return true;
@@ -365,9 +368,10 @@ export default ['clustersController', [
             const checkRes = LegacyUtils.checkCacheSQLSchemas(caches);
 
             if (!checkRes.checked) {
-                return showPopoverMessage($scope.ui, 'general', 'caches',
+                return ErrorPopover.show('caches',
                     'Found caches "' + checkRes.firstCache.name + '" and "' + checkRes.secondCache.name + '" ' +
-                    'with the same SQL schema name "' + checkRes.firstCache.sqlSchema + '"', 10000);
+                    'with the same SQL schema name "' + checkRes.firstCache.sqlSchema + '"',
+                    $scope.ui, 'general', 10000);
             }
 
             return true;
@@ -382,10 +386,10 @@ export default ['clustersController', [
                         const type = b.typeConfigurations[typeIx];
 
                         if (LegacyUtils.isEmptyString(type.typeName))
-                            return showPopoverMessage($scope.ui, 'binary', 'typeName' + typeIx, 'Type name should be specified!');
+                            return ErrorPopover.show('typeName' + typeIx, 'Type name should be specified!', $scope.ui, 'binary');
 
                         if (_.find(b.typeConfigurations, (t, ix) => ix < typeIx && t.typeName === type.typeName))
-                            return showPopoverMessage($scope.ui, 'binary', 'typeName' + typeIx, 'Type with such name is already specified!');
+                            return ErrorPopover.show('typeName' + typeIx, 'Type with such name is already specified!', $scope.ui, 'binary');
                     }
                 }
             }
@@ -403,10 +407,10 @@ export default ['clustersController', [
                 const type = cfgs[typeIx];
 
                 if (LegacyUtils.isEmptyString(type.typeName))
-                    return showPopoverMessage($scope.ui, 'cacheKeyCfg', 'cacheKeyTypeName' + typeIx, 'Cache type configuration name should be specified!');
+                    return ErrorPopover.show('cacheKeyTypeName' + typeIx, 'Cache type configuration name should be specified!', $scope.ui, 'cacheKeyCfg');
 
                 if (_.find(cfgs, (t, ix) => ix < typeIx && t.typeName === type.typeName))
-                    return showPopoverMessage($scope.ui, 'cacheKeyCfg', 'cacheKeyTypeName' + typeIx, 'Cache type configuration with such name is already specified!');
+                    return ErrorPopover.show('cacheKeyTypeName' + typeIx, 'Cache type configuration with such name is already specified!', $scope.ui, 'cacheKeyCfg');
             }
 
             return true;
@@ -418,14 +422,14 @@ export default ['clustersController', [
             if (LegacyUtils.isDefined(c)) {
                 if (LegacyUtils.isDefined(c.unacknowledgedMessagesBufferSize)) {
                     if (LegacyUtils.isDefined(c.messageQueueLimit) && c.unacknowledgedMessagesBufferSize < 5 * c.messageQueueLimit)
-                        return showPopoverMessage($scope.ui, 'communication', 'unacknowledgedMessagesBufferSize', 'Maximum number of stored unacknowledged messages should be at least 5 * message queue limit!');
+                        return ErrorPopover.show('unacknowledgedMessagesBufferSize', 'Maximum number of stored unacknowledged messages should be at least 5 * message queue limit!', $scope.ui, 'communication');
 
                     if (LegacyUtils.isDefined(c.ackSendThreshold) && c.unacknowledgedMessagesBufferSize < 5 * c.ackSendThreshold)
-                        return showPopoverMessage($scope.ui, 'communication', 'unacknowledgedMessagesBufferSize', 'Maximum number of stored unacknowledged messages should be at least 5 * ack send threshold!');
+                        return ErrorPopover.show('unacknowledgedMessagesBufferSize', 'Maximum number of stored unacknowledged messages should be at least 5 * ack send threshold!', $scope.ui, 'communication');
                 }
 
                 if (c.sharedMemoryPort === 0)
-                    return showPopoverMessage($scope.ui, 'communication', 'sharedMemoryPort', 'Shared memory port should be more than "0" or equals to "-1"!');
+                    return ErrorPopover.show('sharedMemoryPort', 'Shared memory port should be more than "0" or equals to "-1"!', $scope.ui, 'communication');
             }
 
             return true;
@@ -436,10 +440,10 @@ export default ['clustersController', [
 
             if (d) {
                 if ((_.isNil(d.maxAckTimeout) ? 600000 : d.maxAckTimeout) < (d.ackTimeout || 5000))
-                    return showPopoverMessage($scope.ui, 'discovery', 'ackTimeout', 'Acknowledgement timeout should be less than max acknowledgement timeout!');
+                    return ErrorPopover.show('ackTimeout', 'Acknowledgement timeout should be less than max acknowledgement timeout!', $scope.ui, 'discovery');
 
                 if (d.kind === 'Vm' && d.Vm && d.Vm.addresses.length === 0)
-                    return showPopoverMessage($scope.ui, 'general', 'addresses', 'Addresses are not specified!');
+                    return ErrorPopover.show('addresses', 'Addresses are not specified!', $scope.ui, 'general');
             }
 
             return true;
@@ -454,12 +458,12 @@ export default ['clustersController', [
                 const sparsity = swap.maximumSparsity;
 
                 if (LegacyUtils.isDefined(sparsity) && (sparsity < 0 || sparsity >= 1))
-                    return showPopoverMessage($scope.ui, 'swap', 'maximumSparsity', 'Maximum sparsity should be more or equal 0 and less than 1!');
+                    return ErrorPopover.show('maximumSparsity', 'Maximum sparsity should be more or equal 0 and less than 1!', $scope.ui, 'swap');
 
                 const readStripesNumber = swap.readStripesNumber;
 
                 if (readStripesNumber && !(readStripesNumber === -1 || (readStripesNumber & (readStripesNumber - 1)) === 0))
-                    return showPopoverMessage($scope.ui, 'swap', 'readStripesNumber', 'Read stripe size must be positive and power of two!');
+                    return ErrorPopover.show('readStripesNumber', 'Read stripe size must be positive and power of two!', $scope.ui, 'swap');
             }
 
             return true;
@@ -470,15 +474,15 @@ export default ['clustersController', [
 
             if (LegacyUtils.isDefined(r)) {
                 if (r.sslEnabled && LegacyUtils.isEmptyString(r.sslFactory))
-                    return showPopoverMessage($scope.ui, 'connector', 'connectorSslFactory', 'SSL factory should not be empty!');
+                    return ErrorPopover.show('connectorSslFactory', 'SSL factory should not be empty!', $scope.ui, 'connector');
             }
 
             if (item.sslEnabled) {
                 if (!LegacyUtils.isDefined(item.sslContextFactory) || LegacyUtils.isEmptyString(item.sslContextFactory.keyStoreFilePath))
-                    return showPopoverMessage($scope.ui, 'sslConfiguration', 'keyStoreFilePath', 'Key store file should not be empty!');
+                    return ErrorPopover.show('keyStoreFilePath', 'Key store file should not be empty!', $scope.ui, 'sslConfiguration');
 
                 if (LegacyUtils.isEmptyString(item.sslContextFactory.trustStoreFilePath) && _.isEmpty(item.sslContextFactory.trustManagers))
-                    return showPopoverMessage($scope.ui, 'sslConfiguration', 'sslConfiguration-title', 'Trust storage file or managers should be configured!');
+                    return ErrorPopover.show('sslConfiguration-title', 'Trust storage file or managers should be configured!', $scope.ui, 'sslConfiguration');
             }
 
             return true;
@@ -486,17 +490,17 @@ export default ['clustersController', [
 
         function checkPoolSizes(item) {
             if (item.rebalanceThreadPoolSize && item.systemThreadPoolSize && item.systemThreadPoolSize <= item.rebalanceThreadPoolSize)
-                return showPopoverMessage($scope.ui, 'pools', 'rebalanceThreadPoolSize', 'Rebalance thread pool size exceed or equals System thread pool size!');
+                return ErrorPopover.show('rebalanceThreadPoolSize', 'Rebalance thread pool size exceed or equals System thread pool size!', $scope.ui, 'pools');
 
             return true;
         }
 
         // Check cluster logical consistency.
         function validate(item) {
-            LegacyUtils.hidePopover();
+            ErrorPopover.hide();
 
             if (LegacyUtils.isEmptyString(item.name))
-                return showPopoverMessage($scope.ui, 'general', 'clusterName', 'Cluster name should not be empty!');
+                return ErrorPopover.show('clusterName', 'Cluster name should not be empty!', $scope.ui, 'general');
 
             if (!LegacyUtils.checkFieldValidators($scope.ui))
                 return false;


[19/50] [abbrv] ignite git commit: Fixed url rewriting in webpack dev server configuration.

Posted by an...@apache.org.
Fixed url rewriting in webpack dev server configuration.


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

Branch: refs/heads/ignite-3629
Commit: 2fb16dd9a6e68a26edab912c43aed48835e806e1
Parents: 916be77
Author: Maxim Afanasiev <ma...@gmail.com>
Authored: Fri Aug 26 13:53:33 2016 +0700
Committer: Maxim Afanasiev <ma...@gmail.com>
Committed: Fri Aug 26 13:55:44 2016 +0700

----------------------------------------------------------------------
 .../gulpfile.babel.js/webpack/environments/development.js      | 6 ++----
 modules/web-console/frontend/package.json                      | 2 +-
 2 files changed, 3 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/2fb16dd9/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js b/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js
index 45773cf..9758221 100644
--- a/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js
+++ b/modules/web-console/frontend/gulpfile.babel.js/webpack/environments/development.js
@@ -51,10 +51,8 @@ export default () => {
                 '/api/v1/*': {
                     target: 'http://localhost:3000',
                     changeOrigin: true,
-                    rewrite: (req) => {
-                        req.url = req.url.replace(/^\/api\/v1/, '');
-
-                        return req;
+                    pathRewrite:{
+                        '^/api/v1' : ''
                     }
                 }
             },

http://git-wip-us.apache.org/repos/asf/ignite/blob/2fb16dd9/modules/web-console/frontend/package.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/package.json b/modules/web-console/frontend/package.json
index 5814522..7ea2893 100644
--- a/modules/web-console/frontend/package.json
+++ b/modules/web-console/frontend/package.json
@@ -120,6 +120,6 @@
     "url": "^0.11.0",
     "url-loader": "^0.5.6",
     "webpack": "^1.13.1",
-    "webpack-dev-server": "^1.14.1"
+    "webpack-dev-server": "^1.15.0"
   }
 }


[26/50] [abbrv] ignite git commit: IGNITE-3384 Added docker build for ignite.

Posted by an...@apache.org.
IGNITE-3384 Added docker build for ignite.


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

Branch: refs/heads/ignite-3629
Commit: f8095d7616ae9d629146f4e1de44fddf77451649
Parents: 5abecfe
Author: Maxim Afanasiev <ma...@gridgain.com>
Authored: Mon Aug 29 18:14:42 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Mon Aug 29 18:14:42 2016 +0700

----------------------------------------------------------------------
 modules/web-console/.dockerignore               |  4 --
 modules/web-console/.gitignore                  |  6 +++
 .../docker/compose/backend/.dockerignore        |  1 +
 .../docker/compose/backend/Dockerfile           |  6 +--
 .../web-console/docker/compose/backend/build.sh | 40 +++++++++++++++++-
 .../docker/compose/docker-compose.yml           | 31 +++++++++++---
 .../docker/compose/frontend/.dockerignore       |  3 ++
 .../docker/compose/frontend/DockerfileBuild     |  4 +-
 .../docker/compose/frontend/build.sh            | 44 ++++++++++++++------
 .../docker/compose/frontend/nginx/nginx.conf    |  9 +++-
 .../web-console/docker/standalone/.dockerignore |  2 +
 .../web-console/docker/standalone/Dockerfile    | 26 +++++++-----
 modules/web-console/docker/standalone/build.sh  | 42 +++++++++++++++++--
 .../docker/standalone/docker-compose.yml        | 19 ++++++++-
 .../web-console/docker/standalone/entrypoint.sh |  2 +-
 .../docker/standalone/nginx/web-console.conf    |  7 +---
 16 files changed, 192 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/.dockerignore
----------------------------------------------------------------------
diff --git a/modules/web-console/.dockerignore b/modules/web-console/.dockerignore
deleted file mode 100644
index ed365b8..0000000
--- a/modules/web-console/.dockerignore
+++ /dev/null
@@ -1,4 +0,0 @@
-node_modules
-backend/node_modules
-frontend/node_modules
-.idea

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/.gitignore
----------------------------------------------------------------------
diff --git a/modules/web-console/.gitignore b/modules/web-console/.gitignore
new file mode 100644
index 0000000..9ddddc4
--- /dev/null
+++ b/modules/web-console/.gitignore
@@ -0,0 +1,6 @@
+docker/standalone/backend/build
+docker/standalone/frontend/build
+docker/standalone/data
+docker/compose/backend/build
+docker/compose/frontend/build
+docker/dev/data

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/compose/backend/.dockerignore
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/compose/backend/.dockerignore b/modules/web-console/docker/compose/backend/.dockerignore
new file mode 100644
index 0000000..6fadfa5
--- /dev/null
+++ b/modules/web-console/docker/compose/backend/.dockerignore
@@ -0,0 +1 @@
+build/node_modules

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/compose/backend/Dockerfile
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/compose/backend/Dockerfile b/modules/web-console/docker/compose/backend/Dockerfile
index 7d157e1..b4f7c9d 100644
--- a/modules/web-console/docker/compose/backend/Dockerfile
+++ b/modules/web-console/docker/compose/backend/Dockerfile
@@ -21,12 +21,10 @@ RUN mkdir -p /opt/web-console-backend
 
 WORKDIR /opt/web-console-backend
 
-COPY backend .
+COPY build .
 
-RUN npm -g update npm && npm install
+RUN npm -g update npm && npm install --no-optional
 
 EXPOSE 3000 3001
 
-VOLUME ["/opt/web-console-backend/serve/agent_dists"]
-
 CMD ["npm", "start"]

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/compose/backend/build.sh
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/compose/backend/build.sh b/modules/web-console/docker/compose/backend/build.sh
index 0927746..f925bd7 100755
--- a/modules/web-console/docker/compose/backend/build.sh
+++ b/modules/web-console/docker/compose/backend/build.sh
@@ -16,6 +16,42 @@
 # limitations under the License.
 #
 
-cd "$(dirname "$0")"
+if [ -z "$IGNITE_HOME" ]; then
+    echo "Ignite source folder is not found or IGNITE_HOME environment variable is not valid."
 
-sudo docker build -f=./Dockerfile -t ignite/web-console-backend:latest ../../..
+    exit 1
+fi
+
+WORK_DIR=`cd "$(dirname "$0")"; pwd`
+
+BUILD_DIR="$WORK_DIR/build"
+
+IGNITE_WEB_CONSOLE_BACKEND_DIR="$IGNITE_HOME/modules/web-console/backend"
+DOCKER_IMAGE_NAME="ignite/web-console-backend"
+
+echo "Receiving version..."
+VERSION=`cd $IGNITE_HOME && mvn org.apache.maven.plugins:maven-help-plugin:evaluate -Dexpression=project.version| grep -Ev '(^\[|Download\w+:)'`
+RELEASE_VERSION=${VERSION%-SNAPSHOT}
+
+echo "Building $DOCKER_IMAGE_NAME:$RELEASE_VERSION"
+echo "Step 1. Prepare build temp paths."
+cd $WORK_DIR
+rm -Rf $BUILD_DIR
+docker rmi -f $DOCKER_IMAGE_NAME:$RELEASE_VERSION
+
+echo "Step 2. Build ignite web agent."
+cd $IGNITE_HOME
+mvn versions:set -DnewVersion=$RELEASE_VERSION -DgenerateBackupPoms=false -Pweb-console -DartifactId='*'
+mvn clean package -pl :ignite-web-agent -am -P web-console -DskipTests=true
+mvn versions:set -DnewVersion=$VERSION -DgenerateBackupPoms=false -Pweb-console -DartifactId='*'
+
+echo "Step 3. Copy sources."
+cd $WORK_DIR
+cp -r $IGNITE_WEB_CONSOLE_BACKEND_DIR/. $BUILD_DIR
+cp $IGNITE_HOME/modules/web-console/web-agent/target/ignite-web-agent*.zip $BUILD_DIR/agent_dists/.
+
+echo "Step 4. Build docker image."
+docker build -f=./Dockerfile -t $DOCKER_IMAGE_NAME:$RELEASE_VERSION .
+
+echo "Step 5. Cleanup."
+rm -Rf $BUILD_DIR

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/compose/docker-compose.yml
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/compose/docker-compose.yml b/modules/web-console/docker/compose/docker-compose.yml
index cca5eac..bacd769 100644
--- a/modules/web-console/docker/compose/docker-compose.yml
+++ b/modules/web-console/docker/compose/docker-compose.yml
@@ -18,21 +18,42 @@
 mongodb:
   image: mongo:latest
   volumes:
-    - /docker/web-console/mongo:/data/db
+    # External volume for persisting data. (HOST_PATH:CONTAINER_PATH).
+    - ./data/mongo:/data/db
 
 backend:
-  image: ignite/web-console-backend:latest
+  image: ignite/web-console-backend:1.7.0
   links:
+    # Link mongodb container as with mongodb hostname.
     - mongodb:mongodb
   ports:
+    # Proxy 3001 port from docker container to 3001 port host machine. (HOST_PORT:DOCKER_PORT)
     - 3001:3001
-  restart: always
+  # Restart on crash.
+  restart: always  
   environment:
-    - mongoDB__url=mongodb://mongodb/console
+    # Port for serving frontend API
+    - server_port=3000
+    # Cookie session secret
+    - server_sessionSecret="CHANGE ME"
+    # URL for mongodb connection
+    - mongodb_url=mongodb://mongodb/console
+    # Port for web-agent.
+    - agentServer_port=3001
+    # Mail connection settings. Leave empty if no needed. See also settings, https://github.com/nodemailer/nodemailer
+    - mail_service=""
+    - mail_sign=""
+    - mail_greeting=""
+    - mail_from=""
+    - mail_auth_user=""
+    - mail_auth_pass=""
 
 frontend:
-  image: ignite/web-console-frontend:latest
+  image: ignite/web-console-frontend:1.7.0
   links:
+    # Link backend container to proxy backend requests throught nginx container.
     - backend:backend
+
   ports:
+    # Proxy HTTP nginx port (HOST_PORT:DOCKER_PORT)
     - 80:80

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/compose/frontend/.dockerignore
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/compose/frontend/.dockerignore b/modules/web-console/docker/compose/frontend/.dockerignore
new file mode 100644
index 0000000..caf0e8e
--- /dev/null
+++ b/modules/web-console/docker/compose/frontend/.dockerignore
@@ -0,0 +1,3 @@
+src/build
+src/ignite_modules_temp
+src/node_modules

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/compose/frontend/DockerfileBuild
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/compose/frontend/DockerfileBuild b/modules/web-console/docker/compose/frontend/DockerfileBuild
index 617edc6..277991f 100644
--- a/modules/web-console/docker/compose/frontend/DockerfileBuild
+++ b/modules/web-console/docker/compose/frontend/DockerfileBuild
@@ -21,9 +21,9 @@ RUN mkdir -p /opt/web-console-frontend
 
 WORKDIR /opt/web-console-frontend
 
-ADD frontend /opt/web-console-frontend
+COPY src .
 
-RUN npm update -g npm && npm install
+RUN npm update -g npm && npm install --no-optional
 
 VOLUME /opt/web-console-frontend/build
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/compose/frontend/build.sh
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/compose/frontend/build.sh b/modules/web-console/docker/compose/frontend/build.sh
index d5a0bb2..4dfa57a 100755
--- a/modules/web-console/docker/compose/frontend/build.sh
+++ b/modules/web-console/docker/compose/frontend/build.sh
@@ -16,24 +16,44 @@
 # limitations under the License.
 #
 
-cd "$(dirname "$0")"
+if [ -z "$IGNITE_HOME" ]; then
+    echo "Ignite source folder is not found or IGNITE_HOME environment variable is not valid."
 
-BUILD_DIR=$PWD/build
-IMAGE_BUILD_CONTAINER=web-console-frontend-builder
-IMAGE_BUILD_NAME=ignite/$IMAGE_BUILD_CONTAINER
-IMAGE_NAME=ignite/web-console-frontend
-CURRENT_USER=$(whoami)
+    exit 1
+fi
 
+WORK_DIR=`cd "$(dirname "$0")"; pwd`
+
+SOURCE_DIR=$WORK_DIR/src
+BUILD_DIR=$WORK_DIR/build
+
+DOCKER_BUILD_CONTAINER=web-console-frontend-builder
+DOCKER_BUILD_IMAGE_NAME=ignite/$DOCKER_BUILD_CONTAINER
+DOCKER_IMAGE_NAME=ignite/web-console-frontend
+
+echo "Receiving version..."
+VERSION=`cd $IGNITE_HOME && mvn org.apache.maven.plugins:maven-help-plugin:evaluate -Dexpression=project.version| grep -Ev '(^\[|Download\w+:)'`
+RELEASE_VERSION=${VERSION%-SNAPSHOT}
+
+echo "Building $DOCKER_IMAGE_NAME:$RELEASE_VERSION"
 echo "Step 1. Build frontend SPA"
+cd $WORK_DIR
+
+rm -Rf $SOURCE_DIR
+rm -Rf $BUILD_DIR
+mkdir -p $SOURCE_DIR
 mkdir -p $BUILD_DIR
-sudo docker build -f=./DockerfileBuild -t $IMAGE_BUILD_NAME:latest ../../..
-sudo docker run -it -v $BUILD_DIR:/opt/web-console-frontend/build --name $IMAGE_BUILD_CONTAINER $IMAGE_BUILD_NAME
-sudo chown -R $CURRENT_USER $BUILD_DIR
+
+cp -r $IGNITE_HOME/modules/web-console/frontend/. $SOURCE_DIR
+
+docker build -f=./DockerfileBuild -t $DOCKER_BUILD_IMAGE_NAME:latest .
+docker run -it -v $BUILD_DIR:/opt/web-console-frontend/build --name $DOCKER_BUILD_CONTAINER $DOCKER_BUILD_IMAGE_NAME
 
 echo "Step 2. Build NGINX container with SPA and proxy configuration"
-sudo docker build -f=./Dockerfile -t $IMAGE_NAME:latest .
+docker build -f=./Dockerfile -t $DOCKER_IMAGE_NAME:$RELEASE_VERSION .
 
 echo "Step 3. Cleanup"
-sudo docker rm $IMAGE_BUILD_CONTAINER
-sudo docker rmi $IMAGE_BUILD_NAME
+docker rm -f $DOCKER_BUILD_CONTAINER
+docker rmi -f $DOCKER_BUILD_IMAGE_NAME
+rm -r $SOURCE_DIR
 rm -r $BUILD_DIR

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/compose/frontend/nginx/nginx.conf
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/compose/frontend/nginx/nginx.conf b/modules/web-console/docker/compose/frontend/nginx/nginx.conf
index 220d69c..dc208f5 100644
--- a/modules/web-console/docker/compose/frontend/nginx/nginx.conf
+++ b/modules/web-console/docker/compose/frontend/nginx/nginx.conf
@@ -44,9 +44,14 @@ http {
 
   include /etc/nginx/mime.types;
   default_type  application/octet-stream;
-  gzip on;
+
+  gzip              on;
+  gzip_disable      "msie6";
+  gzip_types        text/plain text/css text/xml text/javascript application/json application/x-javascript application/xml application/xml+rss application/javascript;
+  gzip_vary         on;
+  gzip_comp_level   5;
 
   access_log  /var/log/nginx/access.log  main;
   #conf.d
-  include web-console.conf ;
+  include web-console.conf;
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/standalone/.dockerignore
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/standalone/.dockerignore b/modules/web-console/docker/standalone/.dockerignore
new file mode 100644
index 0000000..35b7244
--- /dev/null
+++ b/modules/web-console/docker/standalone/.dockerignore
@@ -0,0 +1,2 @@
+build/frontend/node_modules
+build/backend/node_modules

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/standalone/Dockerfile
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/standalone/Dockerfile b/modules/web-console/docker/standalone/Dockerfile
index 9d3284a..785f109 100644
--- a/modules/web-console/docker/standalone/Dockerfile
+++ b/modules/web-console/docker/standalone/Dockerfile
@@ -20,7 +20,7 @@ FROM ubuntu:14.04
 ENV NPM_CONFIG_LOGLEVEL info
 ENV NODE_VERSION 4.4.7
 
-# Before package list update
+# Before package list update.
 RUN set -ex  && \
       for key in \
         9554F04D7259F04124DE6B476D5A82AC7E37093B \
@@ -38,7 +38,7 @@ RUN set -ex  && \
 RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927 && \
    echo "deb http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.2.list
 
-# Update package list & install
+# Update package list & install.
 RUN apt-get update && \
     apt-get install -y nginx-light mongodb-org-server curl xz-utils
 
@@ -50,25 +50,29 @@ RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-
   tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 && \
   rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt
 
+# Install global node packages.
+RUN npm upgrade -g npm && npm install -g pm2
+
 # Install frontend & backend apps.
 RUN mkdir -p /opt/web-console
 
+# Copy source.
 WORKDIR /opt/web-console
+COPY build .
 
-# Copy source.
-ADD . /opt/web-console
+# Install node modules.
+RUN cd /opt/web-console/frontend && npm install --no-optional && npm run build
+RUN cd /opt/web-console/backend && npm install --no-optional
 
-RUN npm upgrade -g npm && \
-    npm install && \
-    npm run build && \
-    npm install -g pm2
+# Returns to base path.
+WORKDIR /opt/web-console
 
 # Copy nginx config.
-COPY docker/web-console/nginx/nginx.conf /etc/nginx/nginx.conf
-COPY docker/web-console/nginx/web-console.conf /etc/nginx/web-console.conf
+COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
+COPY ./nginx/web-console.conf /etc/nginx/web-console.conf
 
 # Setup entrypoint.
-COPY docker/web-console/entrypoint.sh .
+COPY ./entrypoint.sh .
 RUN chmod 755 /opt/web-console/entrypoint.sh
 
 # Clean up.

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/standalone/build.sh
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/standalone/build.sh b/modules/web-console/docker/standalone/build.sh
index 538cb89..4365dec 100755
--- a/modules/web-console/docker/standalone/build.sh
+++ b/modules/web-console/docker/standalone/build.sh
@@ -16,8 +16,44 @@
 # limitations under the License.
 #
 
-cd "$(dirname "$0")"
+if [ -z "$IGNITE_HOME" ]; then
+    echo "Ignite source folder is not found or IGNITE_HOME environment variable is not valid."
 
-IMAGE_NAME=ignite/web-console-standalone
+    exit 1
+fi
 
-sudo docker build -f=./Dockerfile -t $IMAGE_NAME:latest ../..
+WORK_DIR=`cd "$(dirname "$0")"; pwd`
+
+BUILD_DIR="$WORK_DIR/build"
+
+IGNITE_WEB_CONSOLE_DIR="$IGNITE_HOME/modules/web-console"
+DOCKER_IMAGE_NAME="ignite/web-console-standalone"
+
+echo "Receiving version..."
+VERSION=`cd $IGNITE_HOME && mvn org.apache.maven.plugins:maven-help-plugin:evaluate -Dexpression=project.version| grep -Ev '(^\[|Download\w+:)'`
+RELEASE_VERSION=${VERSION%-SNAPSHOT}
+
+echo "Building $DOCKER_IMAGE_NAME:$RELEASE_VERSION"
+echo "Step 1. Prepare build temp paths."
+cd $WORK_DIR
+rm -Rf $BUILD_DIR
+docker rmi -f $DOCKER_IMAGE_NAME:$RELEASE_VERSION
+mkdir -p $BUILD_DIR/frontend $BUILD_DIR/backend
+
+echo "Step 2. Build ignite web agent."
+cd $IGNITE_HOME
+mvn versions:set -DnewVersion=$RELEASE_VERSION -DgenerateBackupPoms=false -Pweb-console -DartifactId='*'
+mvn clean package -pl :ignite-web-agent -am -P web-console -DskipTests=true
+mvn versions:set -DnewVersion=$VERSION -DgenerateBackupPoms=false -Pweb-console -DartifactId='*'
+
+echo "Step 3. Copy sources."
+cd $WORK_DIR
+cp -r $IGNITE_WEB_CONSOLE_DIR/frontend/. $BUILD_DIR/frontend
+cp -r $IGNITE_WEB_CONSOLE_DIR/backend/. $BUILD_DIR/backend
+cp $IGNITE_HOME/modules/web-console/web-agent/target/ignite-web-agent*.zip $BUILD_DIR/backend/agent_dists/.
+
+echo "Step 4. Build docker image."
+docker build -f=./Dockerfile -t $DOCKER_IMAGE_NAME:$RELEASE_VERSION .
+
+echo "Step 5. Cleanup."
+rm -Rf $BUILD_DIR

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/standalone/docker-compose.yml
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/standalone/docker-compose.yml b/modules/web-console/docker/standalone/docker-compose.yml
index cd68ca3..561c88d 100644
--- a/modules/web-console/docker/standalone/docker-compose.yml
+++ b/modules/web-console/docker/standalone/docker-compose.yml
@@ -16,11 +16,26 @@
 #
 
 webconsole:
-  image: ignite/web-console-standalone:latest
+  image: ignite/web-console-standalone
   ports:
     - 3080:80
+    - 3000:3000
     - 3001:3001
     - 27017:27017
   restart: always
   environment:
-    - mongoDB__url=mongodb://localhost/console
+    # Port for serving frontend API
+    - server_port=3000
+    # Cookie session secret
+    - server_sessionSecret="CHANGE ME"
+    # URL for mongodb connection
+    - mongodb_url=mongodb://127.0.0.1/console
+    # Port for web-agent.
+    - agentServer_port=3001
+    # Mail connection settings. Leave empty if no needed. See also settings, https://github.com/nodemailer/nodemailer
+    - mail_service=""
+    - mail_sign=""
+    - mail_greeting=""
+    - mail_from=""
+    - mail_auth_user=""
+    - mail_auth_pass=""

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/standalone/entrypoint.sh
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/standalone/entrypoint.sh b/modules/web-console/docker/standalone/entrypoint.sh
index d9bcd8b..3882f06 100755
--- a/modules/web-console/docker/standalone/entrypoint.sh
+++ b/modules/web-console/docker/standalone/entrypoint.sh
@@ -20,4 +20,4 @@
 
 service nginx start
 
-pm2 start index.js --no-daemon
+cd backend && pm2 start ./index.js --no-daemon

http://git-wip-us.apache.org/repos/asf/ignite/blob/f8095d76/modules/web-console/docker/standalone/nginx/web-console.conf
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/standalone/nginx/web-console.conf b/modules/web-console/docker/standalone/nginx/web-console.conf
index 65b8d4a..3de544f 100644
--- a/modules/web-console/docker/standalone/nginx/web-console.conf
+++ b/modules/web-console/docker/standalone/nginx/web-console.conf
@@ -23,18 +23,13 @@ server {
   listen 80;
   server_name _;
 
-  set $ignite_console_dir /opt/web-console/build;
-  set $maintenance $ignite_console_dir/maintenance.file;
+  set $ignite_console_dir /opt/web-console/frontend/build;
 
   root $ignite_console_dir;
 
   error_page 500 502 503 504 /50x.html;
 
   location / {
-    if (-f $maintenance) {
-      return 503;
-    }
-
     try_files $uri /index.html = 404;
   }
 


[10/50] [abbrv] ignite git commit: Merge branches 'web-console-production' and 'web-console-staging' of https://github.com/gridgain/apache-ignite into web-console-staging

Posted by an...@apache.org.
Merge branches 'web-console-production' and 'web-console-staging' of https://github.com/gridgain/apache-ignite into web-console-staging


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

Branch: refs/heads/ignite-3629
Commit: 8e844d22656de03080778c38a4dce6c1926d5a8d
Parents: 677b8c7 5b69ace
Author: Andrey Novikov <an...@apache.org>
Authored: Wed Aug 24 16:03:32 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Wed Aug 24 16:03:32 2016 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/controllers/domains-controller.js | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/8e844d22/modules/web-console/frontend/controllers/domains-controller.js
----------------------------------------------------------------------
diff --cc modules/web-console/frontend/controllers/domains-controller.js
index ef9d580,0000000..cf4e3c8
mode 100644,000000..100644
--- a/modules/web-console/frontend/controllers/domains-controller.js
+++ b/modules/web-console/frontend/controllers/domains-controller.js
@@@ -1,1756 -1,0 +1,1758 @@@
 +/*
 + * 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.
 + */
 +
 +// Controller for Domain model screen.
 +export default ['domainsController', [
 +    '$rootScope', '$scope', '$http', '$state', '$filter', '$timeout', '$modal', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteFocus', 'IgniteConfirm', 'IgniteConfirmBatch', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteAgentMonitor', 'IgniteLegacyTable', 'igniteConfigurationResource',
 +    function($root, $scope, $http, $state, $filter, $timeout, $modal, LegacyUtils, Messages, Focus, Confirm, ConfirmBatch, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, IgniteAgentMonitor, LegacyTable, Resource) {
 +        UnsavedChangesGuard.install($scope);
 +
 +        const emptyDomain = {empty: true};
 +
 +        let __original_value;
 +
 +        const blank = {};
 +
 +        // We need to initialize backupItem with empty object in order to properly used from angular directives.
 +        $scope.backupItem = emptyDomain;
 +
 +        $scope.ui = LegacyUtils.formUI();
 +        $scope.ui.activePanels = [0, 1];
 +        $scope.ui.topPanels = [0, 1, 2];
 +
 +        const IMPORT_DM_NEW_CACHE = 1;
 +        const IMPORT_DM_ASSOCIATE_CACHE = 2;
 +
 +        /**
 +         * Convert some name to valid java package name.
 +         *
 +         * @param name to convert.
 +         * @returns {string} Valid java package name.
 +         */
 +        const _toJavaPackage = (name) => {
 +            return name ? name.replace(/[^A-Za-z_0-9/.]+/g, '_') : 'org';
 +        };
 +
 +        $scope.ui.packageNameUserInput = $scope.ui.packageName =
 +            _toJavaPackage($root.user.email.replace('@', '.').split('.').reverse().join('.') + '.model');
 +        $scope.ui.builtinKeys = true;
 +        $scope.ui.usePrimitives = true;
 +        $scope.ui.generateAliases = true;
 +        $scope.ui.generatedCachesClusters = [];
 +
 +        function _mapCaches(caches) {
 +            return _.map(caches, (cache) => {
 +                return {label: cache.name, value: cache._id, cache};
 +            });
 +        }
 +
 +        $scope.contentVisible = function() {
 +            const item = $scope.backupItem;
 +
 +            return !item.empty && (!item._id || _.find($scope.displayedRows, {_id: item._id}));
 +        };
 +
 +        $scope.getModel = LegacyUtils.getModel;
 +        $scope.javaBuiltInClasses = LegacyUtils.javaBuiltInClasses;
 +        $scope.compactJavaName = LegacyUtils.compactJavaName;
 +        $scope.widthIsSufficient = LegacyUtils.widthIsSufficient;
 +        $scope.saveBtnTipText = LegacyUtils.saveBtnTipText;
 +
 +        $scope.tableSave = function(field, index, stopEdit) {
 +            if (LegacyTable.tableEditing({model: 'table-index-fields'}, LegacyTable.tableEditedRowIndex())) {
 +                if ($scope.tableIndexItemSaveVisible(field, index))
 +                    return $scope.tableIndexItemSave(field, field.indexIdx, index, stopEdit);
 +            }
 +            else {
 +                switch (field.type) {
 +                    case 'fields':
 +                    case 'aliases':
 +                        if (LegacyTable.tablePairSaveVisible(field, index))
 +                            return LegacyTable.tablePairSave($scope.tablePairValid, $scope.backupItem, field, index, stopEdit);
 +
 +                        break;
 +
 +                    case 'indexes':
 +                        if ($scope.tableIndexSaveVisible(field, index))
 +                            return $scope.tableIndexSave(field, index, stopEdit);
 +
 +                        break;
 +
 +                    case 'table-db-fields':
 +                        if ($scope.tableDbFieldSaveVisible(field, index))
 +                            return $scope.tableDbFieldSave(field, index, stopEdit);
 +
 +                        break;
 +
 +                    default:
 +                }
 +            }
 +
 +            return true;
 +        };
 +
 +        $scope.tableReset = (trySave) => {
 +            const field = LegacyTable.tableField();
 +
 +            if (trySave && LegacyUtils.isDefined(field) && !$scope.tableSave(field, LegacyTable.tableEditedRowIndex(), true))
 +                return false;
 +
 +            LegacyTable.tableReset();
 +
 +            return true;
 +        };
 +
 +        $scope.tableNewItem = function(field) {
 +            if ($scope.tableReset(true))
 +                LegacyTable.tableNewItem(field);
 +        };
 +
 +        $scope.tableNewItemActive = LegacyTable.tableNewItemActive;
 +
 +        $scope.tableStartEdit = function(item, field, index) {
 +            if ($scope.tableReset(true))
 +                LegacyTable.tableStartEdit(item, field, index, $scope.tableSave);
 +        };
 +
 +        $scope.tableEditing = LegacyTable.tableEditing;
 +
 +        $scope.tableRemove = function(item, field, index) {
 +            if ($scope.tableReset(true))
 +                LegacyTable.tableRemove(item, field, index);
 +        };
 +
 +        $scope.tablePairSave = LegacyTable.tablePairSave;
 +        $scope.tablePairSaveVisible = LegacyTable.tablePairSaveVisible;
 +
 +        $scope.queryFieldsTbl = {
 +            type: 'fields',
 +            model: 'fields',
 +            focusId: 'QryField',
 +            ui: 'table-pair',
 +            keyName: 'name',
 +            valueName: 'className',
 +            save: $scope.tableSave
 +        };
 +
 +        $scope.aliasesTbl = {
 +            type: 'aliases',
 +            model: 'aliases',
 +            focusId: 'Alias',
 +            ui: 'table-pair',
 +            keyName: 'field',
 +            valueName: 'alias',
 +            save: $scope.tableSave
 +        };
 +
 +        $scope.queryMetadataVariants = LegacyUtils.mkOptions(['Annotations', 'Configuration']);
 +
 +        const INFO_CONNECT_TO_DB = 'Configure connection to database';
 +        const INFO_SELECT_SCHEMAS = 'Select schemas to load tables from';
 +        const INFO_SELECT_TABLES = 'Select tables to import as domain model';
 +        const INFO_SELECT_OPTIONS = 'Select import domain model options';
 +        const LOADING_JDBC_DRIVERS = {text: 'Loading JDBC drivers...'};
 +        const LOADING_SCHEMAS = {text: 'Loading schemas...'};
 +        const LOADING_TABLES = {text: 'Loading tables...'};
 +        const SAVING_DOMAINS = {text: 'Saving domain model...'};
 +
 +        $scope.ui.invalidKeyFieldsTooltip = 'Found key types without configured key fields<br/>' +
 +            'It may be a result of import tables from database without primary keys<br/>' +
 +            'Key field for such key types should be configured manually';
 +
 +        $scope.hidePopover = LegacyUtils.hidePopover;
 +
 +        const showPopoverMessage = LegacyUtils.showPopoverMessage;
 +
 +        $scope.indexType = LegacyUtils.mkOptions(['SORTED', 'FULLTEXT', 'GEOSPATIAL']);
 +
 +        const _dbPresets = [
 +            {
 +                db: 'Oracle',
 +                jdbcDriverClass: 'oracle.jdbc.OracleDriver',
 +                jdbcUrl: 'jdbc:oracle:thin:@[host]:[port]:[database]',
 +                user: 'system'
 +            },
 +            {
 +                db: 'DB2',
 +                jdbcDriverClass: 'com.ibm.db2.jcc.DB2Driver',
 +                jdbcUrl: 'jdbc:db2://[host]:[port]/[database]',
 +                user: 'db2admin'
 +            },
 +            {
 +                db: 'SQLServer',
 +                jdbcDriverClass: 'com.microsoft.sqlserver.jdbc.SQLServerDriver',
 +                jdbcUrl: 'jdbc:sqlserver://[host]:[port][;databaseName=database]'
 +            },
 +            {
 +                db: 'PostgreSQL',
 +                jdbcDriverClass: 'org.postgresql.Driver',
 +                jdbcUrl: 'jdbc:postgresql://[host]:[port]/[database]',
 +                user: 'sa'
 +            },
 +            {
 +                db: 'MySQL',
 +                jdbcDriverClass: 'com.mysql.jdbc.Driver',
 +                jdbcUrl: 'jdbc:mysql://[host]:[port]/[database]',
 +                user: 'root'
 +            },
 +            {
 +                db: 'H2',
 +                jdbcDriverClass: 'org.h2.Driver',
 +                jdbcUrl: 'jdbc:h2:tcp://[host]/[database]',
 +                user: 'sa'
 +            }
 +        ];
 +
 +        $scope.selectedPreset = {
 +            db: 'General',
 +            jdbcDriverJar: '',
 +            jdbcDriverClass: '',
 +            jdbcUrl: 'jdbc:[database]',
 +            user: 'sa',
 +            password: '',
 +            tablesOnly: true
 +        };
 +
 +        $scope.demoConnection = {
 +            db: 'H2',
 +            jdbcDriverClass: 'org.h2.Driver',
 +            jdbcUrl: 'jdbc:h2:mem:demo-db',
 +            user: 'sa',
 +            password: '',
 +            tablesOnly: true
 +        };
 +
 +        function _loadPresets() {
 +            try {
 +                const restoredPresets = JSON.parse(localStorage.dbPresets);
 +
 +                _.forEach(restoredPresets, (restoredPreset) => {
 +                    const preset = _.find(_dbPresets, {jdbcDriverClass: restoredPreset.jdbcDriverClass});
 +
 +                    if (preset) {
 +                        preset.jdbcUrl = restoredPreset.jdbcUrl;
 +                        preset.user = restoredPreset.user;
 +                    }
 +                });
 +            }
 +            catch (ignore) {
 +                // No-op.
 +            }
 +        }
 +
 +        _loadPresets();
 +
 +        function _savePreset(preset) {
 +            try {
 +                const oldPreset = _.find(_dbPresets, {jdbcDriverClass: preset.jdbcDriverClass});
 +
 +                if (oldPreset)
 +                    angular.extend(oldPreset, preset);
 +                else
 +                    _dbPresets.push(preset);
 +
 +                localStorage.dbPresets = JSON.stringify(_dbPresets);
 +            }
 +            catch (err) {
 +                Messages.showError(err);
 +            }
 +        }
 +
 +        function _findPreset(selectedJdbcJar) {
 +            let result = _.find(_dbPresets, function(preset) {
 +                return preset.jdbcDriverClass === selectedJdbcJar.jdbcDriverClass;
 +            });
 +
 +            if (!result)
 +                result = {db: 'General', jdbcUrl: 'jdbc:[database]', user: 'admin'};
 +
 +            result.jdbcDriverJar = selectedJdbcJar.jdbcDriverJar;
 +            result.jdbcDriverClass = selectedJdbcJar.jdbcDriverClass;
 +
 +            return result;
 +        }
 +
 +        $scope.$watch('ui.selectedJdbcDriverJar', function(val) {
 +            if (val && !$scope.importDomain.demo) {
 +                const foundPreset = _findPreset(val);
 +
 +                const selectedPreset = $scope.selectedPreset;
 +
 +                selectedPreset.db = foundPreset.db;
 +                selectedPreset.jdbcDriverJar = foundPreset.jdbcDriverJar;
 +                selectedPreset.jdbcDriverClass = foundPreset.jdbcDriverClass;
 +                selectedPreset.jdbcUrl = foundPreset.jdbcUrl;
 +                selectedPreset.user = foundPreset.user;
 +            }
 +        }, true);
 +
 +        $scope.ui.showValid = true;
 +
 +        $scope.supportedJdbcTypes = LegacyUtils.mkOptions(LegacyUtils.SUPPORTED_JDBC_TYPES);
 +
 +        $scope.supportedJavaTypes = LegacyUtils.mkOptions(LegacyUtils.javaBuiltInTypes);
 +
 +        $scope.sortDirections = [
 +            {value: true, label: 'ASC'},
 +            {value: false, label: 'DESC'}
 +        ];
 +
 +        $scope.domains = [];
 +
 +        $scope.isJavaBuiltInClass = function() {
 +            const item = $scope.backupItem;
 +
 +            if (item && item.keyType)
 +                return LegacyUtils.isJavaBuiltInClass(item.keyType);
 +
 +            return false;
 +        };
 +
 +        $scope.selectAllSchemas = function() {
 +            const allSelected = $scope.importDomain.allSchemasSelected;
 +
-             _.forEach($scope.importDomain.displayedSchemas, (schema) => schema.use = allSelected);
++            _.forEach($scope.importDomain.displayedSchemas, (schema) => {
++                schema.use = allSelected;
++            });
 +        };
 +
 +        $scope.selectSchema = function() {
 +            if (LegacyUtils.isDefined($scope.importDomain) && LegacyUtils.isDefined($scope.importDomain.displayedSchemas))
 +                $scope.importDomain.allSchemasSelected = $scope.importDomain.displayedSchemas.length > 0 && _.every($scope.importDomain.displayedSchemas, 'use', true);
 +        };
 +
 +        $scope.selectAllTables = function() {
 +            const allSelected = $scope.importDomain.allTablesSelected;
 +
 +            _.forEach($scope.importDomain.displayedTables, function(table) {
 +                table.use = allSelected;
 +            });
 +        };
 +
 +        $scope.selectTable = function() {
 +            if (LegacyUtils.isDefined($scope.importDomain) && LegacyUtils.isDefined($scope.importDomain.displayedTables))
 +                $scope.importDomain.allTablesSelected = $scope.importDomain.displayedTables.length > 0 && _.every($scope.importDomain.displayedTables, 'use', true);
 +        };
 +
 +        $scope.$watch('importDomain.displayedSchemas', $scope.selectSchema);
 +
 +        $scope.$watch('importDomain.displayedTables', $scope.selectTable);
 +
 +        // Pre-fetch modal dialogs.
 +        const importDomainModal = $modal({scope: $scope, templateUrl: '/configuration/domains-import.html', show: false});
 +
 +        const hideImportDomain = importDomainModal.hide;
 +
 +        importDomainModal.hide = function() {
 +            IgniteAgentMonitor.stopWatch();
 +
 +            hideImportDomain();
 +        };
 +
 +        $scope.linkId = () => $scope.backupItem._id ? $scope.backupItem._id : 'create';
 +
 +        function prepareNewItem(cacheId) {
 +            return {
 +                space: $scope.spaces[0]._id,
 +                caches: cacheId && _.find($scope.caches, {value: cacheId}) ? [cacheId] : // eslint-disable-line no-nested-ternary
 +                    (_.isEmpty($scope.caches) ? [] : [$scope.caches[0].value]),
 +                queryMetadata: 'Configuration'
 +            };
 +        }
 +
 +        /**
 +         * Show import domain models modal.
 +         */
 +        $scope.showImportDomainModal = function() {
 +            LegacyTable.tableReset();
 +
 +            LegacyUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, function() {
 +                if ($scope.ui.inputForm.$dirty)
 +                    $scope.backupItem = $scope.selectedItem ? angular.copy($scope.selectedItem) : prepareNewItem();
 +
 +                const demo = $root.IgniteDemoMode;
 +
 +                $scope.importDomain = {
 +                    demo,
 +                    action: demo ? 'connect' : 'drivers',
 +                    jdbcDriversNotFound: demo,
 +                    schemas: [],
 +                    allSchemasSelected: false,
 +                    tables: [],
 +                    allTablesSelected: false,
 +                    button: 'Next',
 +                    info: ''
 +                };
 +
 +                $scope.importDomain.loadingOptions = LOADING_JDBC_DRIVERS;
 +
 +                IgniteAgentMonitor.startWatch({text: 'Back to Domain models', goal: 'import domain model from database'})
 +                    .then(function() {
 +                        importDomainModal.$promise.then(importDomainModal.show);
 +
 +                        if (demo) {
 +                            $scope.ui.packageNameUserInput = $scope.ui.packageName;
 +                            $scope.ui.packageName = 'model';
 +
 +                            return;
 +                        }
 +
 +                        // Get available JDBC drivers via agent.
 +                        Loading.start('importDomainFromDb');
 +
 +                        $scope.jdbcDriverJars = [];
 +                        $scope.ui.selectedJdbcDriverJar = {};
 +
 +                        return IgniteAgentMonitor.drivers()
 +                            .then(function(drivers) {
 +                                $scope.ui.packageName = $scope.ui.packageNameUserInput;
 +
 +                                if (drivers && drivers.length > 0) {
 +                                    drivers = _.sortBy(drivers, 'jdbcDriverJar');
 +
 +                                    _.forEach(drivers, function(drv) {
 +                                        $scope.jdbcDriverJars.push({
 +                                            label: drv.jdbcDriverJar,
 +                                            value: {
 +                                                jdbcDriverJar: drv.jdbcDriverJar,
 +                                                jdbcDriverClass: drv.jdbcDriverCls
 +                                            }
 +                                        });
 +                                    });
 +
 +                                    $scope.ui.selectedJdbcDriverJar = $scope.jdbcDriverJars[0].value;
 +
 +                                    LegacyUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, function() {
 +                                        importDomainModal.$promise.then(() => {
 +                                            $scope.importDomain.action = 'connect';
 +                                            $scope.importDomain.tables = [];
 +
 +                                            Focus.move('jdbcUrl');
 +                                        });
 +                                    });
 +                                }
 +                                else {
 +                                    $scope.importDomain.jdbcDriversNotFound = true;
 +                                    $scope.importDomain.button = 'Cancel';
 +                                }
 +                            })
 +                            .then(() => {
 +                                $scope.importDomain.info = INFO_CONNECT_TO_DB;
 +
 +                                Loading.finish('importDomainFromDb');
 +                            });
 +                    });
 +            });
 +        };
 +
 +        /**
 +         * Load list of database schemas.
 +         */
 +        function _loadSchemas() {
 +            IgniteAgentMonitor.awaitAgent()
 +                .then(function() {
 +                    $scope.importDomain.loadingOptions = LOADING_SCHEMAS;
 +                    Loading.start('importDomainFromDb');
 +
 +                    if ($root.IgniteDemoMode)
 +                        return IgniteAgentMonitor.schemas($scope.demoConnection);
 +
 +                    const preset = $scope.selectedPreset;
 +
 +                    _savePreset(preset);
 +
 +                    return IgniteAgentMonitor.schemas(preset);
 +                })
 +                .then(function(schemas) {
 +                    $scope.importDomain.schemas = _.map(schemas, function(schema) {
 +                        return {use: true, name: schema};
 +                    });
 +
 +                    $scope.importDomain.action = 'schemas';
 +
 +                    if ($scope.importDomain.schemas.length === 0)
 +                        $scope.importDomainNext();
 +
 +                    $scope.importDomain.info = INFO_SELECT_SCHEMAS;
 +                })
 +                .catch(Messages.showError)
 +                .then(() => Loading.finish('importDomainFromDb'));
 +        }
 +
 +        const DFLT_PARTITIONED_CACHE = {
 +            label: 'PARTITIONED',
 +            value: -1,
 +            cache: {
 +                name: 'PARTITIONED',
 +                cacheMode: 'PARTITIONED',
 +                atomicityMode: 'ATOMIC',
 +                readThrough: true,
 +                writeThrough: true
 +            }
 +        };
 +
 +        const DFLT_REPLICATED_CACHE = {
 +            label: 'REPLICATED',
 +            value: -2,
 +            cache: {
 +                name: 'REPLICATED',
 +                cacheMode: 'REPLICATED',
 +                atomicityMode: 'ATOMIC',
 +                readThrough: true,
 +                writeThrough: true
 +            }
 +        };
 +
 +        let _importCachesOrTemplates = [];
 +
 +        $scope.tableActionView = function(tbl) {
 +            const cacheName = _.find(_importCachesOrTemplates, {value: tbl.cacheOrTemplate}).label;
 +
 +            if (tbl.action === IMPORT_DM_NEW_CACHE)
 +                return 'Create ' + tbl.generatedCacheName + ' (' + cacheName + ')';
 +
 +            return 'Associate with ' + cacheName;
 +        };
 +
 +        function toJavaClassName(name) {
 +            const len = name.length;
 +
 +            let buf = '';
 +
 +            let capitalizeNext = true;
 +
 +            for (let i = 0; i < len; i++) {
 +                const ch = name.charAt(i);
 +
 +                if (ch === ' ' || ch === '_')
 +                    capitalizeNext = true;
 +                else if (capitalizeNext) {
 +                    buf += ch.toLocaleUpperCase();
 +
 +                    capitalizeNext = false;
 +                }
 +                else
 +                    buf += ch.toLocaleLowerCase();
 +            }
 +
 +            return buf;
 +        }
 +
 +        function toJavaName(dbName) {
 +            const javaName = toJavaClassName(dbName);
 +
 +            return javaName.charAt(0).toLocaleLowerCase() + javaName.slice(1);
 +        }
 +
 +        function _fillCommonCachesOrTemplates(item) {
 +            return function(action) {
 +                if (item.cachesOrTemplates)
 +                    item.cachesOrTemplates.length = 0;
 +                else
 +                    item.cachesOrTemplates = [];
 +
 +                if (action === IMPORT_DM_NEW_CACHE) {
 +                    item.cachesOrTemplates.push(DFLT_PARTITIONED_CACHE);
 +                    item.cachesOrTemplates.push(DFLT_REPLICATED_CACHE);
 +                }
 +
 +                if (!_.isEmpty($scope.caches)) {
 +                    if (item.cachesOrTemplates.length > 0)
 +                        item.cachesOrTemplates.push(null);
 +
 +                    _.forEach($scope.caches, function(cache) {
 +                        item.cachesOrTemplates.push(cache);
 +                    });
 +                }
 +
 +                if (!_.find(item.cachesOrTemplates, {value: item.cacheOrTemplate}))
 +                    item.cacheOrTemplate = item.cachesOrTemplates[0].value;
 +            };
 +        }
 +        /**
 +         * Load list of database tables.
 +         */
 +        function _loadTables() {
 +            IgniteAgentMonitor.awaitAgent()
 +                .then(function() {
 +                    $scope.importDomain.loadingOptions = LOADING_TABLES;
 +                    Loading.start('importDomainFromDb');
 +
 +                    $scope.importDomain.allTablesSelected = false;
 +
 +                    const preset = $scope.importDomain.demo ? $scope.demoConnection : $scope.selectedPreset;
 +
 +                    preset.schemas = [];
 +
 +                    _.forEach($scope.importDomain.schemas, function(schema) {
 +                        if (schema.use)
 +                            preset.schemas.push(schema.name);
 +                    });
 +
 +                    return IgniteAgentMonitor.tables(preset);
 +                })
 +                .then(function(tables) {
 +                    _importCachesOrTemplates = [DFLT_PARTITIONED_CACHE, DFLT_REPLICATED_CACHE].concat($scope.caches);
 +
 +                    _fillCommonCachesOrTemplates($scope.importCommon)($scope.importCommon.action);
 +
 +                    _.forEach(tables, function(tbl, idx) {
 +                        tbl.id = idx;
 +                        tbl.action = IMPORT_DM_NEW_CACHE;
 +                        tbl.generatedCacheName = toJavaClassName(tbl.tbl) + 'Cache';
 +                        tbl.cacheOrTemplate = DFLT_PARTITIONED_CACHE.value;
 +                        tbl.label = tbl.schema + '.' + tbl.tbl;
 +                        tbl.edit = false;
 +                        tbl.use = LegacyUtils.isDefined(_.find(tbl.cols, function(col) {
 +                            return col.key;
 +                        }));
 +                    });
 +
 +                    $scope.importDomain.action = 'tables';
 +                    $scope.importDomain.tables = tables;
 +                    $scope.importDomain.info = INFO_SELECT_TABLES;
 +                })
 +                .catch(Messages.showError)
 +                .then(() => Loading.finish('importDomainFromDb'));
 +        }
 +
 +        $scope.applyDefaults = function() {
 +            _.forEach($scope.importDomain.displayedTables, function(table) {
 +                table.edit = false;
 +                table.action = $scope.importCommon.action;
 +                table.cacheOrTemplate = $scope.importCommon.cacheOrTemplate;
 +            });
 +        };
 +
 +        $scope._curDbTable = null;
 +
 +        $scope.startEditDbTableCache = function(tbl) {
 +            if ($scope._curDbTable) {
 +                $scope._curDbTable.edit = false;
 +
 +                if ($scope._curDbTable.actionWatch) {
 +                    $scope._curDbTable.actionWatch();
 +
 +                    $scope._curDbTable.actionWatch = null;
 +                }
 +            }
 +
 +            $scope._curDbTable = tbl;
 +
 +            const _fillFn = _fillCommonCachesOrTemplates($scope._curDbTable);
 +
 +            _fillFn($scope._curDbTable.action);
 +
 +            $scope._curDbTable.actionWatch = $scope.$watch('_curDbTable.action', _fillFn, true);
 +
 +            $scope._curDbTable.edit = true;
 +        };
 +
 +        /**
 +         * Show page with import domain models options.
 +         */
 +        function _selectOptions() {
 +            $scope.importDomain.action = 'options';
 +            $scope.importDomain.button = 'Save';
 +            $scope.importDomain.info = INFO_SELECT_OPTIONS;
 +
 +            Focus.move('domainPackageName');
 +        }
 +
 +        function _saveBatch(batch) {
 +            if (batch && batch.length > 0) {
 +                $scope.importDomain.loadingOptions = SAVING_DOMAINS;
 +                Loading.start('importDomainFromDb');
 +
 +                $http.post('/api/v1/configuration/domains/save/batch', batch)
 +                    .success(function(savedBatch) {
 +                        let lastItem;
 +                        const newItems = [];
 +
 +                        _.forEach(_mapCaches(savedBatch.generatedCaches), function(cache) {
 +                            $scope.caches.push(cache);
 +                        });
 +
 +                        _.forEach(savedBatch.savedDomains, function(savedItem) {
 +                            const idx = _.findIndex($scope.domains, function(domain) {
 +                                return domain._id === savedItem._id;
 +                            });
 +
 +                            if (idx >= 0)
 +                                $scope.domains[idx] = savedItem;
 +                            else
 +                                newItems.push(savedItem);
 +
 +                            lastItem = savedItem;
 +                        });
 +
 +                        _.forEach(newItems, function(item) {
 +                            $scope.domains.push(item);
 +                        });
 +
 +                        if (!lastItem && $scope.domains.length > 0)
 +                            lastItem = $scope.domains[0];
 +
 +                        $scope.selectItem(lastItem);
 +
 +                        Messages.showInfo('Domain models imported from database.');
 +
 +                        $scope.ui.activePanels = [0, 1, 2];
 +
 +                        $scope.ui.showValid = true;
 +                    })
 +                    .error(Messages.showError)
 +                    .finally(() => {
 +                        Loading.finish('importDomainFromDb');
 +
 +                        importDomainModal.hide();
 +                    });
 +            }
 +            else
 +                importDomainModal.hide();
 +        }
 +
 +        function _saveDomainModel() {
 +            if (LegacyUtils.isEmptyString($scope.ui.packageName))
 +                return LegacyUtils.showPopoverMessage(null, null, 'domainPackageName', 'Package could not be empty');
 +
 +            if (!LegacyUtils.isValidJavaClass('Package', $scope.ui.packageName, false, 'domainPackageName', true))
 +                return false;
 +
 +            const batch = [];
 +            const checkedCaches = [];
 +
 +            let containKey = true;
 +            let containDup = false;
 +
 +            function queryField(name, jdbcType) {
 +                return {name: toJavaName(name), className: jdbcType.javaType};
 +            }
 +
 +            function dbField(name, jdbcType, nullable) {
 +                return {
 +                    jdbcType,
 +                    databaseFieldName: name,
 +                    databaseFieldType: jdbcType.dbName,
 +                    javaFieldName: toJavaName(name),
 +                    javaFieldType: nullable ? jdbcType.javaType :
 +                        ($scope.ui.usePrimitives && jdbcType.primitiveType ? jdbcType.primitiveType : jdbcType.javaType)
 +                };
 +            }
 +
 +            _.forEach($scope.importDomain.tables, function(table, curIx) {
 +                if (table.use) {
 +                    const qryFields = [];
 +                    const indexes = [];
 +                    const keyFields = [];
 +                    const valFields = [];
 +                    const aliases = [];
 +
 +                    const tableName = table.tbl;
 +                    let typeName = toJavaClassName(tableName);
 +
 +                    if (_.find($scope.importDomain.tables,
 +                            (tbl, ix) => tbl.use && ix !== curIx && tableName === tbl.tbl)) {
 +                        typeName = typeName + '_' + toJavaClassName(table.schema);
 +
 +                        containDup = true;
 +                    }
 +
 +                    const valType = _toJavaPackage($scope.ui.packageName) + '.' + typeName;
 +
 +                    let _containKey = false;
 +
 +                    _.forEach(table.cols, function(col) {
 +                        const colName = col.name;
 +                        const jdbcType = LegacyUtils.findJdbcType(col.type);
 +                        const nullable = col.nullable;
 +
 +                        qryFields.push(queryField(colName, jdbcType));
 +
 +                        const fld = dbField(colName, jdbcType, nullable);
 +
 +                        if ($scope.ui.generateAliases && !_.find(aliases, {field: fld.javaFieldName}) &&
 +                            fld.javaFieldName.toUpperCase() !== fld.databaseFieldName.toUpperCase())
 +                            aliases.push({field: fld.javaFieldName, alias: fld.databaseFieldName});
 +
 +                        if (col.key) {
 +                            keyFields.push(fld);
 +
 +                            _containKey = true;
 +                        }
 +                        else
 +                            valFields.push(fld);
 +                    });
 +
 +                    containKey &= _containKey;
 +
 +                    if (table.idxs) {
 +                        _.forEach(table.idxs, function(idx) {
 +                            const fields = Object.keys(idx.fields);
 +
 +                            indexes.push({
 +                                name: idx.name, indexType: 'SORTED', fields: _.map(fields, function(fieldName) {
 +                                    return {
 +                                        name: toJavaName(fieldName),
 +                                        direction: idx.fields[fieldName]
 +                                    };
 +                                })
 +                            });
 +                        });
 +                    }
 +
 +                    const domainFound = _.find($scope.domains, function(domain) {
 +                        return domain.valueType === valType;
 +                    });
 +
 +                    const newDomain = {
 +                        confirm: false,
 +                        skip: false,
 +                        space: $scope.spaces[0],
 +                        caches: []
 +                    };
 +
 +                    if (LegacyUtils.isDefined(domainFound)) {
 +                        newDomain._id = domainFound._id;
 +                        newDomain.caches = domainFound.caches;
 +                        newDomain.confirm = true;
 +                    }
 +
 +                    newDomain.keyType = valType + 'Key';
 +                    newDomain.valueType = valType;
 +                    newDomain.queryMetadata = 'Configuration';
 +                    newDomain.databaseSchema = table.schema;
 +                    newDomain.databaseTable = tableName;
 +                    newDomain.fields = qryFields;
 +                    newDomain.indexes = indexes;
 +                    newDomain.keyFields = keyFields;
 +                    newDomain.aliases = aliases;
 +                    newDomain.valueFields = valFields;
 +
 +                    // If value fields not found - copy key fields.
 +                    if (_.isEmpty(valFields))
 +                        newDomain.valueFields = keyFields.slice();
 +
 +                    // Use Java built-in type for key.
 +                    if ($scope.ui.builtinKeys && newDomain.keyFields.length === 1) {
 +                        const keyField = newDomain.keyFields[0];
 +
 +                        newDomain.keyType = keyField.jdbcType.javaType;
 +
 +                        // Exclude key column from query fields and indexes.
 +                        newDomain.fields = _.filter(newDomain.fields, function(field) {
 +                            return field.name !== keyField.javaFieldName;
 +                        });
 +
 +                        _.forEach(newDomain.indexes, function(index) {
 +                            index.fields = _.filter(index.fields, function(field) {
 +                                return field.name !== keyField.javaFieldName;
 +                            });
 +                        });
 +
 +                        newDomain.indexes = _.filter(newDomain.indexes, (index) => !_.isEmpty(index.fields));
 +                    }
 +
 +                    // Prepare caches for generation.
 +                    if (table.action === IMPORT_DM_NEW_CACHE) {
 +                        const template = _.find(_importCachesOrTemplates, {value: table.cacheOrTemplate});
 +
 +                        const newCache = angular.copy(template.cache);
 +
 +                        newDomain.newCache = newCache;
 +
 +                        delete newCache._id;
 +                        newCache.name = typeName + 'Cache';
 +                        newCache.clusters = $scope.ui.generatedCachesClusters;
 +
 +                        // POJO store factory is not defined in template.
 +                        if (!newCache.cacheStoreFactory || newCache.cacheStoreFactory.kind !== 'CacheJdbcPojoStoreFactory') {
 +                            const dialect = $scope.importDomain.demo ? 'H2' : $scope.selectedPreset.db;
 +
 +                            newCache.cacheStoreFactory = {
 +                                kind: 'CacheJdbcPojoStoreFactory',
 +                                CacheJdbcPojoStoreFactory: {dataSourceBean: 'ds' + dialect, dialect},
 +                                CacheJdbcBlobStoreFactory: { connectVia: 'DataSource' }
 +                            };
 +                        }
 +
 +                        if (!newCache.readThrough && !newCache.writeThrough) {
 +                            newCache.readThrough = true;
 +                            newCache.writeThrough = true;
 +                        }
 +                    }
 +                    else {
 +                        const cacheId = table.cacheOrTemplate;
 +
 +                        newDomain.caches = [cacheId];
 +
 +                        if (!_.includes(checkedCaches, cacheId)) {
 +                            const cache = _.find($scope.caches, {value: cacheId}).cache;
 +
 +                            const change = LegacyUtils.autoCacheStoreConfiguration(cache, [newDomain]);
 +
 +                            if (change)
 +                                newDomain.cacheStoreChanges = [{cacheId, change}];
 +
 +                            checkedCaches.push(cacheId);
 +                        }
 +                    }
 +
 +                    batch.push(newDomain);
 +                }
 +            });
 +
 +            /**
 +             * Generate message to show on confirm dialog.
 +             *
 +             * @param meta Object to confirm.
 +             * @returns {string} Generated message.
 +             */
 +            function overwriteMessage(meta) {
 +                return '<span>' +
 +                    'Domain model with name &quot;' + meta.databaseTable + '&quot; already exist.<br/><br/>' +
 +                    'Are you sure you want to overwrite it?' +
 +                    '</span>';
 +            }
 +
 +            const itemsToConfirm = _.filter(batch, (item) => item.confirm);
 +
 +            function checkOverwrite() {
 +                if (itemsToConfirm.length > 0) {
 +                    ConfirmBatch.confirm(overwriteMessage, itemsToConfirm)
 +                        .then(() => _saveBatch(_.filter(batch, (item) => !item.skip)))
 +                        .catch(() => Messages.showError('Importing of domain models interrupted by user.'));
 +                }
 +                else
 +                    _saveBatch(batch);
 +            }
 +
 +            function checkDuplicate() {
 +                if (containDup) {
 +                    Confirm.confirm('Some tables have the same name.<br/>' +
 +                            'Name of types for that tables will contain schema name too.')
 +                        .then(() => checkOverwrite());
 +                }
 +                else
 +                    checkOverwrite();
 +            }
 +
 +            if (containKey)
 +                checkDuplicate();
 +            else {
 +                Confirm.confirm('Some tables have no primary key.<br/>' +
 +                        'You will need to configure key type and key fields for such tables after import complete.')
 +                    .then(() => checkDuplicate());
 +            }
 +        }
 +
 +        $scope.importDomainNext = function() {
 +            if (!$scope.importDomainNextAvailable())
 +                return;
 +
 +            const act = $scope.importDomain.action;
 +
 +            if (act === 'drivers' && $scope.importDomain.jdbcDriversNotFound)
 +                importDomainModal.hide();
 +            else if (act === 'connect')
 +                _loadSchemas();
 +            else if (act === 'schemas')
 +                _loadTables();
 +            else if (act === 'tables')
 +                _selectOptions();
 +            else if (act === 'options')
 +                _saveDomainModel();
 +        };
 +
 +        $scope.nextTooltipText = function() {
 +            const importDomainNextAvailable = $scope.importDomainNextAvailable();
 +
 +            const act = $scope.importDomain.action;
 +
 +            if (act === 'drivers' && $scope.importDomain.jdbcDriversNotFound)
 +                return 'Resolve issue with JDBC drivers<br>Close this dialog and try again';
 +
 +            if (act === 'connect' && _.isNil($scope.selectedPreset.jdbcDriverClass))
 +                return 'Input valid JDBC driver class name';
 +
 +            if (act === 'connect' && _.isNil($scope.selectedPreset.jdbcUrl))
 +                return 'Input valid JDBC URL';
 +
 +            if (act === 'connect' || act === 'drivers')
 +                return 'Click to load list of schemas from database';
 +
 +            if (act === 'schemas')
 +                return importDomainNextAvailable ? 'Click to load list of tables from database' : 'Select schemas to continue';
 +
 +            if (act === 'tables')
 +                return importDomainNextAvailable ? 'Click to show import options' : 'Select tables to continue';
 +
 +            if (act === 'options')
 +                return 'Click to import domain model for selected tables';
 +
 +            return 'Click to continue';
 +        };
 +
 +        $scope.prevTooltipText = function() {
 +            const act = $scope.importDomain.action;
 +
 +            if (act === 'schemas')
 +                return $scope.importDomain.demo ? 'Click to return on demo description step' : 'Click to return on connection configuration step';
 +
 +            if (act === 'tables')
 +                return 'Click to return on schemas selection step';
 +
 +            if (act === 'options')
 +                return 'Click to return on tables selection step';
 +        };
 +
 +        $scope.importDomainNextAvailable = function() {
 +            switch ($scope.importDomain.action) {
 +                case 'connect':
 +                    return !_.isNil($scope.selectedPreset.jdbcDriverClass) && !_.isNil($scope.selectedPreset.jdbcUrl);
 +
 +                case 'schemas':
 +                    return _.isEmpty($scope.importDomain.schemas) || _.find($scope.importDomain.schemas, {use: true});
 +
 +                case 'tables':
 +                    return _.find($scope.importDomain.tables, {use: true});
 +
 +                default:
 +                    return true;
 +            }
 +        };
 +
 +        $scope.importDomainPrev = function() {
 +            $scope.importDomain.button = 'Next';
 +
 +            if ($scope.importDomain.action === 'options') {
 +                $scope.importDomain.action = 'tables';
 +                $scope.importDomain.info = INFO_SELECT_TABLES;
 +            }
 +            else if ($scope.importDomain.action === 'tables' && $scope.importDomain.schemas.length > 0) {
 +                $scope.importDomain.action = 'schemas';
 +                $scope.importDomain.info = INFO_SELECT_SCHEMAS;
 +            }
 +            else {
 +                $scope.importDomain.action = 'connect';
 +                $scope.importDomain.info = INFO_CONNECT_TO_DB;
 +            }
 +        };
 +
 +        $scope.domainModelTitle = function() {
 +            return $scope.ui.showValid ? 'Domain model types:' : 'Domain model types without key fields:';
 +        };
 +
 +        function selectFirstItem() {
 +            if ($scope.domains.length > 0)
 +                $scope.selectItem($scope.domains[0]);
 +        }
 +
 +        $scope.importActions = [{
 +            label: 'Create new cache by template',
 +            shortLabel: 'Create',
 +            value: IMPORT_DM_NEW_CACHE
 +        }];
 +
 +        $scope.importCommon = {};
 +
 +        // When landing on the page, get domain models and show them.
 +        Loading.start('loadingDomainModelsScreen');
 +
 +        Resource.read()
 +            .then(({spaces, clusters, caches, domains}) => {
 +                $scope.spaces = spaces;
 +                $scope.clusters = _.map(clusters, (cluster) => ({
 +                    label: cluster.name,
 +                    value: cluster._id
 +                }));
 +                $scope.caches = _mapCaches(caches);
 +                $scope.domains = _.sortBy(domains, 'valueType');
 +
 +                _.forEach($scope.clusters, (cluster) => $scope.ui.generatedCachesClusters.push(cluster.value));
 +
 +                if (!_.isEmpty($scope.caches)) {
 +                    $scope.importActions.push({
 +                        label: 'Associate with existing cache',
 +                        shortLabel: 'Associate',
 +                        value: IMPORT_DM_ASSOCIATE_CACHE
 +                    });
 +                }
 +
 +                $scope.$watch('importCommon.action', _fillCommonCachesOrTemplates($scope.importCommon), true);
 +
 +                $scope.importCommon.action = IMPORT_DM_NEW_CACHE;
 +
 +                if ($state.params.linkId)
 +                    $scope.createItem($state.params.linkId);
 +                else {
 +                    const lastSelectedDomain = angular.fromJson(sessionStorage.lastSelectedDomain);
 +
 +                    if (lastSelectedDomain) {
 +                        const idx = _.findIndex($scope.domains, function(domain) {
 +                            return domain._id === lastSelectedDomain;
 +                        });
 +
 +                        if (idx >= 0)
 +                            $scope.selectItem($scope.domains[idx]);
 +                        else {
 +                            sessionStorage.removeItem('lastSelectedDomain');
 +
 +                            selectFirstItem();
 +                        }
 +                    }
 +                    else
 +                        selectFirstItem();
 +                }
 +
 +                $scope.$watch('ui.inputForm.$valid', function(valid) {
 +                    if (valid && ModelNormalizer.isEqual(__original_value, $scope.backupItem))
 +                        $scope.ui.inputForm.$dirty = false;
 +                });
 +
 +                $scope.$watch('backupItem', function(val) {
 +                    const form = $scope.ui.inputForm;
 +
 +                    if (form.$pristine || (form.$valid && ModelNormalizer.isEqual(__original_value, val)))
 +                        form.$setPristine();
 +                    else
 +                        form.$setDirty();
 +                }, true);
 +            })
 +            .catch(Messages.showError)
 +            .then(() => {
 +                $scope.ui.ready = true;
 +                $scope.ui.inputForm.$setPristine();
 +
 +                Loading.finish('loadingDomainModelsScreen');
 +            });
 +
 +        const clearFormDefaults = (ngFormCtrl) => {
 +            ngFormCtrl.$defaults = {};
 +
 +            _.forOwn(ngFormCtrl, (value, key) => {
 +                if (value && key !== '$$parentForm' && value.constructor.name === 'FormController')
 +                    clearFormDefaults(value);
 +            });
 +        };
 +
 +        $scope.selectItem = function(item, backup) {
 +            function selectItem() {
 +                clearFormDefaults($scope.ui.inputForm);
 +
 +                LegacyTable.tableReset();
 +
 +                $scope.selectedItem = item;
 +
 +                try {
 +                    if (item && item._id)
 +                        sessionStorage.lastSelectedDomain = angular.toJson(item._id);
 +                    else
 +                        sessionStorage.removeItem('lastSelectedDomain');
 +                }
 +                catch (ignored) {
 +                    // Ignore possible errors when read from storage.
 +                }
 +
 +                if (backup)
 +                    $scope.backupItem = backup;
 +                else if (item)
 +                    $scope.backupItem = angular.copy(item);
 +                else
 +                    $scope.backupItem = emptyDomain;
 +
 +                $scope.backupItem = angular.merge({}, blank, $scope.backupItem);
 +                $scope.ui.inputForm.$error = {};
 +                $scope.ui.inputForm.$setPristine();
 +
 +                __original_value = ModelNormalizer.normalize($scope.backupItem);
 +
 +                if (LegacyUtils.isDefined($scope.backupItem) && !LegacyUtils.isDefined($scope.backupItem.queryMetadata))
 +                    $scope.backupItem.queryMetadata = 'Configuration';
 +
 +                if (LegacyUtils.isDefined($scope.selectedItem) && !LegacyUtils.isDefined($scope.selectedItem.queryMetadata))
 +                    $scope.selectedItem.queryMetadata = 'Configuration';
 +
 +                if (LegacyUtils.getQueryVariable('new'))
 +                    $state.go('base.configuration.domains');
 +            }
 +
 +            LegacyUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, selectItem);
 +        };
 +
 +        // Add new domain model.
 +        $scope.createItem = function(cacheId) {
 +            if ($scope.tableReset(true)) {
 +                $timeout(() => {
 +                    LegacyUtils.ensureActivePanel($scope.ui, 'query');
 +                    LegacyUtils.ensureActivePanel($scope.ui, 'general', 'keyType');
 +                });
 +
 +                $scope.selectItem(null, prepareNewItem(cacheId));
 +            }
 +        };
 +
 +        function checkQueryConfiguration(item) {
 +            if (item.queryMetadata === 'Configuration' && LegacyUtils.domainForQueryConfigured(item)) {
 +                if (_.isEmpty(item.fields))
 +                    return showPopoverMessage($scope.ui, 'query', 'queryFields', 'Query fields should not be empty');
 +
 +                const indexes = item.indexes;
 +
 +                if (indexes && indexes.length > 0) {
 +                    if (_.find(indexes, function(index, i) {
 +                        if (_.isEmpty(index.fields))
 +                            return !showPopoverMessage($scope.ui, 'query', 'indexes' + i, 'Index fields are not specified');
 +                    }))
 +                        return false;
 +                }
 +            }
 +
 +            return true;
 +        }
 +
 +        function checkStoreConfiguration(item) {
 +            if (LegacyUtils.domainForStoreConfigured(item)) {
 +                if (LegacyUtils.isEmptyString(item.databaseSchema))
 +                    return showPopoverMessage($scope.ui, 'store', 'databaseSchema', 'Database schema should not be empty');
 +
 +                if (LegacyUtils.isEmptyString(item.databaseTable))
 +                    return showPopoverMessage($scope.ui, 'store', 'databaseTable', 'Database table should not be empty');
 +
 +                if (_.isEmpty(item.keyFields))
 +                    return showPopoverMessage($scope.ui, 'store', 'keyFields', 'Key fields are not specified');
 +
 +                if (LegacyUtils.isJavaBuiltInClass(item.keyType) && item.keyFields.length !== 1)
 +                    return showPopoverMessage($scope.ui, 'store', 'keyFields', 'Only one field should be specified in case when key type is a Java built-in type');
 +
 +                if (_.isEmpty(item.valueFields))
 +                    return showPopoverMessage($scope.ui, 'store', 'valueFields', 'Value fields are not specified');
 +            }
 +
 +            return true;
 +        }
 +
 +        // Check domain model logical consistency.
 +        function validate(item) {
 +            if (!LegacyUtils.checkFieldValidators($scope.ui))
 +                return false;
 +
 +            if (!checkQueryConfiguration(item))
 +                return false;
 +
 +            if (!checkStoreConfiguration(item))
 +                return false;
 +
 +            if (!LegacyUtils.domainForStoreConfigured(item) && !LegacyUtils.domainForQueryConfigured(item) && item.queryMetadata === 'Configuration')
 +                return showPopoverMessage($scope.ui, 'query', 'query-title', 'SQL query domain model should be configured');
 +
 +            return true;
 +        }
 +
 +        function _checkShowValidPresentation() {
 +            if (!$scope.ui.showValid) {
 +                const validFilter = $filter('domainsValidation');
 +
 +                $scope.ui.showValid = validFilter($scope.domains, false, true).length === 0;
 +            }
 +        }
 +
 +        // Save domain models into database.
 +        function save(item) {
 +            const qry = LegacyUtils.domainForQueryConfigured(item);
 +            const str = LegacyUtils.domainForStoreConfigured(item);
 +
 +            item.kind = 'query';
 +
 +            if (qry && str)
 +                item.kind = 'both';
 +            else if (str)
 +                item.kind = 'store';
 +
 +            $http.post('/api/v1/configuration/domains/save', item)
 +                .success(function(res) {
 +                    $scope.ui.inputForm.$setPristine();
 +
 +                    const savedMeta = res.savedDomains[0];
 +
 +                    const idx = _.findIndex($scope.domains, function(domain) {
 +                        return domain._id === savedMeta._id;
 +                    });
 +
 +                    if (idx >= 0)
 +                        angular.extend($scope.domains[idx], savedMeta);
 +                    else
 +                        $scope.domains.push(savedMeta);
 +
 +                    _.forEach($scope.caches, (cache) => {
 +                        if (_.includes(item.caches, cache.value))
 +                            cache.cache.domains = _.union(cache.cache.domains, [savedMeta._id]);
 +                        else
 +                            _.remove(cache.cache.domains, (id) => id === savedMeta._id);
 +                    });
 +
 +                    $scope.selectItem(savedMeta);
 +
 +                    Messages.showInfo('Domain model "' + item.valueType + '" saved.');
 +
 +                    _checkShowValidPresentation();
 +                })
 +                .error(Messages.showError);
 +        }
 +
 +        // Save domain model.
 +        $scope.saveItem = function() {
 +            if ($scope.tableReset(true)) {
 +                const item = $scope.backupItem;
 +
 +                item.cacheStoreChanges = [];
 +
 +                _.forEach(item.caches, function(cacheId) {
 +                    const cache = _.find($scope.caches, {value: cacheId}).cache;
 +
 +                    const change = LegacyUtils.autoCacheStoreConfiguration(cache, [item]);
 +
 +                    if (change)
 +                        item.cacheStoreChanges.push({cacheId, change});
 +                });
 +
 +                if (validate(item))
 +                    save(item);
 +            }
 +        };
 +
 +        function _domainNames() {
 +            return _.map($scope.domains, function(domain) {
 +                return domain.valueType;
 +            });
 +        }
 +
 +        function _newNameIsValidJavaClass(newName) {
 +            return LegacyUtils.isValidJavaClass('New name for value type', newName, false, 'copy-new-name');
 +        }
 +
 +        // Save domain model with new name.
 +        $scope.cloneItem = function() {
 +            if ($scope.tableReset(true) && validate($scope.backupItem)) {
 +                Clone.confirm($scope.backupItem.valueType, _domainNames(), _newNameIsValidJavaClass).then(function(newName) {
 +                    const item = angular.copy($scope.backupItem);
 +
 +                    delete item._id;
 +                    item.valueType = newName;
 +
 +                    save(item);
 +                });
 +            }
 +        };
 +
 +        // Remove domain model from db.
 +        $scope.removeItem = function() {
 +            LegacyTable.tableReset();
 +
 +            const selectedItem = $scope.selectedItem;
 +
 +            Confirm.confirm('Are you sure you want to remove domain model: "' + selectedItem.valueType + '"?')
 +                .then(function() {
 +                    const _id = selectedItem._id;
 +
 +                    $http.post('/api/v1/configuration/domains/remove', {_id})
 +                        .success(function() {
 +                            Messages.showInfo('Domain model has been removed: ' + selectedItem.valueType);
 +
 +                            const domains = $scope.domains;
 +
 +                            const idx = _.findIndex(domains, function(domain) {
 +                                return domain._id === _id;
 +                            });
 +
 +                            if (idx >= 0) {
 +                                domains.splice(idx, 1);
 +
 +                                $scope.ui.inputForm.$setPristine();
 +
 +                                if (domains.length > 0)
 +                                    $scope.selectItem(domains[0]);
 +                                else
 +                                    $scope.backupItem = emptyDomain;
 +
 +                                _.forEach($scope.caches, (cache) => _.remove(cache.cache.domains, (id) => id === _id));
 +                            }
 +
 +                            _checkShowValidPresentation();
 +                        })
 +                        .error(Messages.showError);
 +                });
 +        };
 +
 +        // Remove all domain models from db.
 +        $scope.removeAllItems = function() {
 +            LegacyTable.tableReset();
 +
 +            Confirm.confirm('Are you sure you want to remove all domain models?')
 +                .then(function() {
 +                    $http.post('/api/v1/configuration/domains/remove/all')
 +                        .success(function() {
 +                            Messages.showInfo('All domain models have been removed');
 +
 +                            $scope.domains = [];
 +
 +                            _.forEach($scope.caches, (cache) => cache.cache.domains = []);
 +
 +                            $scope.backupItem = emptyDomain;
 +                            $scope.ui.showValid = true;
 +                            $scope.ui.inputForm.$error = {};
 +                            $scope.ui.inputForm.$setPristine();
 +                        })
 +                        .error(Messages.showError);
 +                });
 +        };
 +
 +        $scope.toggleValid = function() {
 +            $scope.ui.showValid = !$scope.ui.showValid;
 +
 +            const validFilter = $filter('domainsValidation');
 +
 +            let idx = -1;
 +
 +            if (LegacyUtils.isDefined($scope.selectedItem)) {
 +                idx = _.findIndex(validFilter($scope.domains, $scope.ui.showValid, true), function(domain) {
 +                    return domain._id === $scope.selectedItem._id;
 +                });
 +            }
 +
 +            if (idx === -1)
 +                $scope.backupItem = emptyDomain;
 +        };
 +
 +        const pairFields = {
 +            fields: {
 +                msg: 'Query field class',
 +                id: 'QryField',
 +                idPrefix: 'Key',
 +                searchCol: 'name',
 +                valueCol: 'key',
 +                classValidation: true,
 +                dupObjName: 'name'
 +            },
 +            aliases: {id: 'Alias', idPrefix: 'Value', searchCol: 'alias', valueCol: 'value', dupObjName: 'alias'}
 +        };
 +
 +        $scope.tablePairValid = function(item, field, index) {
 +            const pairField = pairFields[field.model];
 +
 +            const pairValue = LegacyTable.tablePairValue(field, index);
 +
 +            if (pairField) {
 +                const model = item[field.model];
 +
 +                if (LegacyUtils.isDefined(model)) {
 +                    const idx = _.findIndex(model, function(pair) {
 +                        return pair[pairField.searchCol] === pairValue[pairField.valueCol];
 +                    });
 +
 +                    // Found duplicate by key.
 +                    if (idx >= 0 && idx !== index)
 +                        return showPopoverMessage($scope.ui, 'query', LegacyTable.tableFieldId(index, pairField.idPrefix + pairField.id), 'Field with such ' + pairField.dupObjName + ' already exists!');
 +                }
 +
 +                if (pairField.classValidation && !LegacyUtils.isValidJavaClass(pairField.msg, pairValue.value, true, LegacyTable.tableFieldId(index, 'Value' + pairField.id), false, $scope.ui, 'query'))
 +                    return LegacyTable.tableFocusInvalidField(index, 'Value' + pairField.id);
 +            }
 +
 +            return true;
 +        };
 +
 +        function tableDbFieldValue(field, index) {
 +            return (index < 0) ? {
 +                databaseFieldName: field.newDatabaseFieldName,
 +                databaseFieldType: field.newDatabaseFieldType,
 +                javaFieldName: field.newJavaFieldName,
 +                javaFieldType: field.newJavaFieldType
 +            } : {
 +                databaseFieldName: field.curDatabaseFieldName,
 +                databaseFieldType: field.curDatabaseFieldType,
 +                javaFieldName: field.curJavaFieldName,
 +                javaFieldType: field.curJavaFieldType
 +            };
 +        }
 +
 +        $scope.tableDbFieldSaveVisible = function(field, index) {
 +            const dbFieldValue = tableDbFieldValue(field, index);
 +
 +            return LegacyUtils.isDefined(dbFieldValue.databaseFieldType) &&
 +                LegacyUtils.isDefined(dbFieldValue.javaFieldType) &&
 +                !LegacyUtils.isEmptyString(dbFieldValue.databaseFieldName) &&
 +                !LegacyUtils.isEmptyString(dbFieldValue.javaFieldName);
 +        };
 +
 +        const dbFieldTables = {
 +            keyFields: {msg: 'Key field', id: 'KeyField'},
 +            valueFields: {msg: 'Value field', id: 'ValueField'}
 +        };
 +
 +        $scope.tableDbFieldSave = function(field, index, stopEdit) {
 +            const dbFieldTable = dbFieldTables[field.model];
 +
 +            if (dbFieldTable) {
 +                const dbFieldValue = tableDbFieldValue(field, index);
 +
 +                const item = $scope.backupItem;
 +
 +                let model = item[field.model];
 +
 +                if (!LegacyUtils.isValidJavaIdentifier(dbFieldTable.msg + ' java name', dbFieldValue.javaFieldName, LegacyTable.tableFieldId(index, 'JavaFieldName' + dbFieldTable.id)))
 +                    return false;
 +
 +                if (LegacyUtils.isDefined(model)) {
 +                    let idx = _.findIndex(model, function(dbMeta) {
 +                        return dbMeta.databaseFieldName === dbFieldValue.databaseFieldName;
 +                    });
 +
 +                    // Found duplicate.
 +                    if (idx >= 0 && index !== idx)
 +                        return showPopoverMessage($scope.ui, 'store', LegacyTable.tableFieldId(index, 'DatabaseFieldName' + dbFieldTable.id), 'Field with such database name already exists!');
 +
 +                    idx = _.findIndex(model, function(dbMeta) {
 +                        return dbMeta.javaFieldName === dbFieldValue.javaFieldName;
 +                    });
 +
 +                    // Found duplicate.
 +                    if (idx >= 0 && index !== idx)
 +                        return showPopoverMessage($scope.ui, 'store', LegacyTable.tableFieldId(index, 'JavaFieldName' + dbFieldTable.id), 'Field with such java name already exists!');
 +
 +                    if (index < 0)
 +                        model.push(dbFieldValue);
 +                    else {
 +                        const dbField = model[index];
 +
 +                        dbField.databaseFieldName = dbFieldValue.databaseFieldName;
 +                        dbField.databaseFieldType = dbFieldValue.databaseFieldType;
 +                        dbField.javaFieldName = dbFieldValue.javaFieldName;
 +                        dbField.javaFieldType = dbFieldValue.javaFieldType;
 +                    }
 +                }
 +                else {
 +                    model = [dbFieldValue];
 +
 +                    item[field.model] = model;
 +                }
 +
 +                if (!stopEdit) {
 +                    if (index < 0)
 +                        LegacyTable.tableNewItem(field);
 +                    else if (index < model.length - 1)
 +                        LegacyTable.tableStartEdit(item, field, index + 1);
 +                    else
 +                        LegacyTable.tableNewItem(field);
 +                }
 +
 +                return true;
 +            }
 +
 +            return false;
 +        };
 +
 +        function tableIndexName(field, index) {
 +            return index < 0 ? field.newIndexName : field.curIndexName;
 +        }
 +
 +        function tableIndexType(field, index) {
 +            return index < 0 ? field.newIndexType : field.curIndexType;
 +        }
 +
 +        $scope.tableIndexSaveVisible = function(field, index) {
 +            return !LegacyUtils.isEmptyString(tableIndexName(field, index)) && LegacyUtils.isDefined(tableIndexType(field, index));
 +        };
 +
 +        $scope.tableIndexSave = function(field, curIdx, stopEdit) {
 +            const indexName = tableIndexName(field, curIdx);
 +            const indexType = tableIndexType(field, curIdx);
 +
 +            const item = $scope.backupItem;
 +
 +            const indexes = item.indexes;
 +
 +            if (LegacyUtils.isDefined(indexes)) {
 +                const idx = _.findIndex(indexes, function(index) {
 +                    return index.name === indexName;
 +                });
 +
 +                // Found duplicate.
 +                if (idx >= 0 && idx !== curIdx)
 +                    return showPopoverMessage($scope.ui, 'query', LegacyTable.tableFieldId(curIdx, 'IndexName'), 'Index with such name already exists!');
 +            }
 +
 +            LegacyTable.tableReset();
 +
 +            if (curIdx < 0) {
 +                const newIndex = {name: indexName, indexType};
 +
 +                if (item.indexes)
 +                    item.indexes.push(newIndex);
 +                else
 +                    item.indexes = [newIndex];
 +            }
 +            else {
 +                item.indexes[curIdx].name = indexName;
 +                item.indexes[curIdx].indexType = indexType;
 +            }
 +
 +            if (!stopEdit) {
 +                if (curIdx < 0)
 +                    $scope.tableIndexNewItem(field, item.indexes.length - 1);
 +                else {
 +                    const index = item.indexes[curIdx];
 +
 +                    if (index.fields && index.fields.length > 0)
 +                        $scope.tableIndexItemStartEdit(field, curIdx, 0);
 +                    else
 +                        $scope.tableIndexNewItem(field, curIdx);
 +                }
 +            }
 +
 +            return true;
 +        };
 +
 +        $scope.tableIndexNewItem = function(field, indexIdx) {
 +            if ($scope.tableReset(true)) {
 +                const index = $scope.backupItem.indexes[indexIdx];
 +
 +                LegacyTable.tableState(field, -1, 'table-index-fields');
 +                LegacyTable.tableFocusInvalidField(-1, 'FieldName' + (index.indexType === 'SORTED' ? 'S' : '') + indexIdx);
 +
 +                field.newFieldName = null;
 +                field.newDirection = true;
 +                field.indexIdx = indexIdx;
 +            }
 +        };
 +
 +        $scope.tableIndexNewItemActive = function(field, itemIndex) {
 +            const indexes = $scope.backupItem.indexes;
 +
 +            if (indexes) {
 +                const index = indexes[itemIndex];
 +
 +                if (index)
 +                    return LegacyTable.tableNewItemActive({model: 'table-index-fields'}) && field.indexIdx === itemIndex;
 +            }
 +
 +            return false;
 +        };
 +
 +        $scope.tableIndexItemEditing = function(field, itemIndex, curIdx) {
 +            const indexes = $scope.backupItem.indexes;
 +
 +            if (indexes) {
 +                const index = indexes[itemIndex];
 +
 +                if (index)
 +                    return LegacyTable.tableEditing({model: 'table-index-fields'}, curIdx) && field.indexIdx === itemIndex;
 +            }
 +
 +            return false;
 +        };
 +
 +        function tableIndexItemValue(field, index) {
 +            return index < 0 ? {
 +                name: field.newFieldName,
 +                direction: field.newDirection
 +            } : {
 +                name: field.curFieldName,
 +                direction: field.curDirection
 +            };
 +        }
 +
 +        $scope.tableIndexItemStartEdit = function(field, indexIdx, curIdx) {
 +            if ($scope.tableReset(true)) {
 +                const index = $scope.backupItem.indexes[indexIdx];
 +
 +                LegacyTable.tableState(field, curIdx, 'table-index-fields');
 +
 +                const indexItem = index.fields[curIdx];
 +
 +                field.curFieldName = indexItem.name;
 +                field.curDirection = indexItem.direction;
 +                field.indexIdx = indexIdx;
 +
 +                Focus.move('curFieldName' + (index.indexType === 'SORTED' ? 'S' : '') + field.indexIdx + '-' + curIdx);
 +            }
 +        };
 +
 +        $scope.tableIndexItemSaveVisible = function(field, index) {
 +            return !LegacyUtils.isEmptyString(tableIndexItemValue(field, index).name);
 +        };
 +
 +        $scope.tableIndexItemSave = function(field, indexIdx, curIdx, stopEdit) {
 +            const indexItemValue = tableIndexItemValue(field, curIdx);
 +
 +            const index = $scope.backupItem.indexes[indexIdx];
 +
 +            const fields = index.fields;
 +
 +            if (LegacyUtils.isDefined(fields)) {
 +                const idx = _.findIndex(fields, (fld) => fld.name === indexItemValue.name);
 +
 +                // Found duplicate.
 +                if (idx >= 0 && idx !== curIdx)
 +                    return showPopoverMessage($scope.ui, 'query', LegacyTable.tableFieldId(curIdx, 'FieldName' + (index.indexType === 'SORTED' ? 'S' : '') + indexIdx + (curIdx >= 0 ? '-' : '')), 'Field with such name already exists in index!');
 +            }
 +
 +            LegacyTable.tableReset();
 +
 +            field.indexIdx = -1;
 +
 +            if (curIdx < 0) {
 +                if (index.fields)
 +                    index.fields.push(indexItemValue);
 +                else
 +                    index.fields = [indexItemValue];
 +
 +                if (!stopEdit)
 +                    $scope.tableIndexNewItem(field, indexIdx);
 +            }
 +            else {
 +                index.fields[curIdx] = indexItemValue;
 +
 +                if (!stopEdit) {
 +                    if (curIdx < index.fields.length - 1)
 +                        $scope.tableIndexItemStartEdit(field, indexIdx, curIdx + 1);
 +                    else
 +                        $scope.tableIndexNewItem(field, indexIdx);
 +                }
 +            }
 +
 +            return true;
 +        };
 +
 +        $scope.tableRemoveIndexItem = function(index, curIdx) {
 +            LegacyTable.tableReset();
 +
 +            index.fields.splice(curIdx, 1);
 +        };
 +
 +        $scope.resetAll = function() {
 +            LegacyTable.tableReset();
 +
 +            Confirm.confirm('Are you sure you want to undo all changes for current domain model?')
 +                .then(function() {
 +                    $scope.backupItem = $scope.selectedItem ? angular.copy($scope.selectedItem) : prepareNewItem();
 +                    $scope.ui.inputForm.$error = {};
 +                    $scope.ui.inputForm.$setPristine();
 +                });
 +        };
 +    }
 +]];