http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/backend/test/unit/IgfsService.test.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/test/unit/IgfsService.test.js 
b/modules/web-console/backend/test/unit/IgfsService.test.js
new file mode 100644
index 0000000..3d78148
--- /dev/null
+++ b/modules/web-console/backend/test/unit/IgfsService.test.js
@@ -0,0 +1,190 @@
+/*
+ * 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 {assert} from 'chai';
+import injector from '../injector';
+import testIgfss from '../data/igfss.json';
+import testAccounts from '../data/accounts.json';
+
+let igfsService;
+let mongo;
+let errors;
+
+suite('IgfsServiceTestsSuite', () => {
+    const prepareUserSpaces = () => {
+        return mongo.Account.create(testAccounts)
+            .then((accounts) => {
+                return Promise.all(accounts.map((account) => 
mongo.Space.create(
+                    [
+                        {name: 'Personal space', owner: account._id, demo: 
false},
+                        {name: 'Demo space', owner: account._id, demo: true}
+                    ]
+                )))
+                    .then((spaces) => [accounts, spaces]);
+            });
+    };
+
+    suiteSetup(() => {
+        return Promise.all([injector('services/igfss'),
+            injector('mongo'),
+            injector('errors')])
+            .then(([_igfsService, _mongo, _errors]) => {
+                mongo = _mongo;
+                igfsService = _igfsService;
+                errors = _errors;
+            });
+    });
+
+    setup(() => {
+        return Promise.all([
+            mongo.Igfs.remove().exec(),
+            mongo.Account.remove().exec(),
+            mongo.Space.remove().exec()
+        ]);
+    });
+
+    test('Create new igfs', (done) => {
+        igfsService.merge(testIgfss[0])
+            .then((igfs) => {
+                assert.isNotNull(igfs._id);
+
+                return igfs._id;
+            })
+            .then((igfsId) => mongo.Igfs.findById(igfsId))
+            .then((igfs) => {
+                assert.isNotNull(igfs);
+            })
+            .then(done)
+            .catch(done);
+    });
+
+    test('Update existed igfs', (done) => {
+        const newName = 'NewUniqueName';
+
+        igfsService.merge(testIgfss[0])
+            .then((existIgfs) => {
+                const igfsBeforeMerge = {...testIgfss[0], _id: existIgfs._id, 
name: newName};
+
+                return igfsService.merge(igfsBeforeMerge);
+            })
+            .then((igfs) => mongo.Igfs.findById(igfs._id))
+            .then((igfsAfterMerge) => {
+                assert.equal(igfsAfterMerge.name, newName);
+            })
+            .then(done)
+            .catch(done);
+    });
+
+    test('Create duplicated igfs', (done) => {
+        igfsService.merge(testIgfss[0])
+            .then(() => igfsService.merge(testIgfss[0]))
+            .catch((err) => {
+                assert.instanceOf(err, errors.DuplicateKeyException);
+
+                done();
+            });
+    });
+
+    test('Remove existed igfs', (done) => {
+        igfsService.merge(testIgfss[0])
+            .then((existIgfs) => {
+                return mongo.Igfs.findById(existIgfs._id)
+                    .then((foundIgfs) => igfsService.remove(foundIgfs._id))
+                    .then(({rowsAffected}) => {
+                        assert.equal(rowsAffected, 1);
+                    })
+                    .then(() => mongo.Igfs.findById(existIgfs._id))
+                    .then((notFoundIgfs) => {
+                        assert.isNull(notFoundIgfs);
+                    });
+            })
+            .then(done)
+            .catch(done);
+    });
+
+    test('Remove igfs without identifier', (done) => {
+        igfsService.merge(testIgfss[0])
+            .then(() => igfsService.remove())
+            .catch((err) => {
+                assert.instanceOf(err, errors.IllegalArgumentException);
+
+                done();
+            });
+    });
+
+    test('Remove missed igfs', (done) => {
+        const validNoExistingId = 'FFFFFFFFFFFFFFFFFFFFFFFF';
+
+        igfsService.merge(testIgfss[0])
+            .then(() => igfsService.remove(validNoExistingId))
+            .then(({rowsAffected}) => {
+                assert.equal(rowsAffected, 0);
+            })
+            .then(done)
+            .catch(done);
+    });
+
+    test('Remove all igfss in space', (done) => {
+        prepareUserSpaces()
+            .then(([accounts, spaces]) => {
+                const currentUser = accounts[0];
+                const userIgfs = {...testIgfss[0], space: spaces[0][0]._id};
+
+                return igfsService.merge(userIgfs)
+                    .then(() => igfsService.removeAll(currentUser._id, false));
+            })
+            .then(({rowsAffected}) => {
+                assert.equal(rowsAffected, 1);
+            })
+            .then(done)
+            .catch(done);
+    });
+
+    test('Get all igfss by space', (done) => {
+        prepareUserSpaces()
+            .then(([accounts, spaces]) => {
+                const userIgfs = {...testIgfss[0], space: spaces[0][0]._id};
+
+                return igfsService.merge(userIgfs)
+                    .then((existIgfs) => {
+                        return igfsService.listBySpaces(spaces[0][0]._id)
+                            .then((igfss) => {
+                                assert.equal(igfss.length, 1);
+                                assert.equal(igfss[0]._id.toString(), 
existIgfs._id.toString());
+                            });
+                    });
+            })
+            .then(done)
+            .catch(done);
+    });
+
+    test('Update linked entities on update igfs', (done) => {
+        // TODO IGNITE-3262 Add test.
+        done();
+    });
+
+    test('Update linked entities on remove igfs', (done) => {
+        // TODO IGNITE-3262 Add test.
+        done();
+    });
+
+    test('Update linked entities on remove all igfss in space', (done) => {
+        // TODO IGNITE-3262 Add test.
+        done();
+    });
+});

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/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/6af6560a/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
new file mode 100644
index 0000000..b4f7c9d
--- /dev/null
+++ b/modules/web-console/docker/compose/backend/Dockerfile
@@ -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.
+#
+
+FROM node:4
+
+RUN mkdir -p /opt/web-console-backend
+
+WORKDIR /opt/web-console-backend
+
+COPY build .
+
+RUN npm -g update npm && npm install --no-optional
+
+EXPOSE 3000 3001
+
+CMD ["npm", "start"]

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/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
new file mode 100644
index 0000000..f925bd7
--- /dev/null
+++ b/modules/web-console/docker/compose/backend/build.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+#
+# 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.
+#
+
+if [ -z "$IGNITE_HOME" ]; then
+    echo "Ignite source folder is not found or IGNITE_HOME environment 
variable is not valid."
+
+    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/6af6560a/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
new file mode 100644
index 0000000..bacd769
--- /dev/null
+++ b/modules/web-console/docker/compose/docker-compose.yml
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+
+mongodb:
+  image: mongo:latest
+  volumes:
+    # External volume for persisting data. (HOST_PATH:CONTAINER_PATH).
+    - ./data/mongo:/data/db
+
+backend:
+  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 on crash.
+  restart: always  
+  environment:
+    # 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: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/6af6560a/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/6af6560a/modules/web-console/docker/compose/frontend/Dockerfile
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/compose/frontend/Dockerfile 
b/modules/web-console/docker/compose/frontend/Dockerfile
new file mode 100644
index 0000000..1b578d1
--- /dev/null
+++ b/modules/web-console/docker/compose/frontend/Dockerfile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+
+FROM nginx
+
+RUN mkdir -p /data/www
+
+WORKDIR /data/www
+
+COPY ./build .
+
+COPY nginx/nginx.conf /etc/nginx/nginx.conf
+COPY nginx/web-console.conf /etc/nginx/web-console.conf
+
+VOLUME /etc/nginx
+VOLUME /data/www
+
+EXPOSE 80

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/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
new file mode 100644
index 0000000..277991f
--- /dev/null
+++ b/modules/web-console/docker/compose/frontend/DockerfileBuild
@@ -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.
+#
+
+FROM node:4
+
+RUN mkdir -p /opt/web-console-frontend
+
+WORKDIR /opt/web-console-frontend
+
+COPY src .
+
+RUN npm update -g npm && npm install --no-optional
+
+VOLUME /opt/web-console-frontend/build
+
+CMD ["npm", "run", "build"]

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/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
new file mode 100644
index 0000000..4dfa57a
--- /dev/null
+++ b/modules/web-console/docker/compose/frontend/build.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+#
+# 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.
+#
+
+if [ -z "$IGNITE_HOME" ]; then
+    echo "Ignite source folder is not found or IGNITE_HOME environment 
variable is not valid."
+
+    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
+
+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"
+docker build -f=./Dockerfile -t $DOCKER_IMAGE_NAME:$RELEASE_VERSION .
+
+echo "Step 3. Cleanup"
+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/6af6560a/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
new file mode 100644
index 0000000..dc208f5
--- /dev/null
+++ b/modules/web-console/docker/compose/frontend/nginx/nginx.conf
@@ -0,0 +1,57 @@
+#
+# 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.
+#
+
+user  nginx;
+worker_processes  1;
+
+error_log  /var/log/nginx/error.log  warn;
+pid        /var/run/nginx.pid;
+
+events {
+  worker_connections  128;
+}
+
+http {
+  server_tokens off;
+  sendfile            on;
+  aio                 on;
+  tcp_nopush          on;
+
+  keepalive_timeout   60;
+  tcp_nodelay         on;
+
+  client_max_body_size 100m;
+
+  #access log
+  log_format main '$http_host $remote_addr - $remote_user [$time_local] '
+  '"$request" $status $bytes_sent '
+  '"$http_referer" "$http_user_agent" '
+  '"$gzip_ratio"';
+
+  include /etc/nginx/mime.types;
+  default_type  application/octet-stream;
+
+  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;
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/docker/compose/frontend/nginx/web-console.conf
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/compose/frontend/nginx/web-console.conf 
b/modules/web-console/docker/compose/frontend/nginx/web-console.conf
new file mode 100644
index 0000000..d80a7f9
--- /dev/null
+++ b/modules/web-console/docker/compose/frontend/nginx/web-console.conf
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+
+upstream backend-api {
+  server backend:3000;
+}
+
+server {
+  listen 80;
+  server_name _;
+
+  set $ignite_console_dir /data/www;
+  set $maintenance $ignite_console_dir/maintenance.file;
+
+  root $ignite_console_dir;
+
+  error_page 500 502 503 504 /50x.html;
+
+  location / {
+    if (-f $maintenance) {
+      return 503;
+    }
+
+    try_files $uri /index.html = 404;
+  }
+
+  location /api/v1 {
+    rewrite /api/v1/(.*) /$1 break;
+    proxy_set_header Host $http_host;
+    proxy_pass http://backend-api;
+  }
+
+  location /socket.io {
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection "upgrade";
+    proxy_http_version 1.1;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    proxy_set_header Host $host;
+    proxy_pass http://backend-api;
+  }
+
+  location = /50x.html {
+    root $ignite_console_dir/error_page;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/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/6af6560a/modules/web-console/docker/standalone/Dockerfile
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/standalone/Dockerfile 
b/modules/web-console/docker/standalone/Dockerfile
new file mode 100644
index 0000000..785f109
--- /dev/null
+++ b/modules/web-console/docker/standalone/Dockerfile
@@ -0,0 +1,87 @@
+#
+# 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.
+#
+
+FROM ubuntu:14.04
+
+ENV NPM_CONFIG_LOGLEVEL info
+ENV NODE_VERSION 4.4.7
+
+# Before package list update.
+RUN set -ex  && \
+      for key in \
+        9554F04D7259F04124DE6B476D5A82AC7E37093B \
+        94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
+        0034A06D9D9B0064CE8ADF6BF1747F4AD2306D93 \
+        FD3A5288F042B6850C66B31F09FE44734EB7990E \
+        71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
+        DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
+        B9AE9905FFD7803F25714661B63B535A4C206CA9 \
+        C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
+      ; do \
+        gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
+      done
+
+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.
+RUN apt-get update && \
+    apt-get install -y nginx-light mongodb-org-server curl xz-utils
+
+# Install Node JS.
+RUN curl -SLO 
"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz";  
&& \
+  curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"; && \
+  gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc && \
+  grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c 
- && \
+  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 .
+
+# 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
+
+# Returns to base path.
+WORKDIR /opt/web-console
+
+# Copy nginx config.
+COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
+COPY ./nginx/web-console.conf /etc/nginx/web-console.conf
+
+# Setup entrypoint.
+COPY ./entrypoint.sh .
+RUN chmod 755 /opt/web-console/entrypoint.sh
+
+# Clean up.
+RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
+
+VOLUME ["/etc/nginx"]
+VOLUME ["/var/lib/mongodb"]
+VOLUME ["/opt/web-console/serve/agent_dists"]
+
+EXPOSE 80 3001
+
+ENTRYPOINT ["/opt/web-console/entrypoint.sh"]

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/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
new file mode 100644
index 0000000..4365dec
--- /dev/null
+++ b/modules/web-console/docker/standalone/build.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+#
+# 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.
+#
+
+if [ -z "$IGNITE_HOME" ]; then
+    echo "Ignite source folder is not found or IGNITE_HOME environment 
variable is not valid."
+
+    exit 1
+fi
+
+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/6af6560a/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
new file mode 100644
index 0000000..561c88d
--- /dev/null
+++ b/modules/web-console/docker/standalone/docker-compose.yml
@@ -0,0 +1,41 @@
+#
+# 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.
+#
+
+webconsole:
+  image: ignite/web-console-standalone
+  ports:
+    - 3080:80
+    - 3000:3000
+    - 3001:3001
+    - 27017:27017
+  restart: always
+  environment:
+    # 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/6af6560a/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
new file mode 100644
index 0000000..3882f06
--- /dev/null
+++ b/modules/web-console/docker/standalone/entrypoint.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+#
+# 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.
+#
+
+/usr/bin/mongod --fork --config=/etc/mongod.conf
+
+service nginx start
+
+cd backend && pm2 start ./index.js --no-daemon

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/docker/standalone/nginx/nginx.conf
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/standalone/nginx/nginx.conf 
b/modules/web-console/docker/standalone/nginx/nginx.conf
new file mode 100644
index 0000000..dbc79d7
--- /dev/null
+++ b/modules/web-console/docker/standalone/nginx/nginx.conf
@@ -0,0 +1,55 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+user  www-data;
+worker_processes  1;
+
+error_log  /var/log/nginx/error.log  warn;
+pid        /var/run/nginx.pid;
+
+events {
+    worker_connections  128;
+}
+
+http {
+    server_tokens off;
+    sendfile            on;
+    tcp_nopush          on;
+
+    keepalive_timeout   60;
+    tcp_nodelay         on;
+
+    client_max_body_size 100m;
+
+    #access log
+    log_format main '$http_host $remote_addr - $remote_user [$time_local] '
+    '"$request" $status $bytes_sent '
+    '"$http_referer" "$http_user_agent" '
+    '"$gzip_ratio"';
+
+    include /etc/nginx/mime.types;
+    default_type  application/octet-stream;
+    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 ;
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/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
new file mode 100644
index 0000000..3de544f
--- /dev/null
+++ b/modules/web-console/docker/standalone/nginx/web-console.conf
@@ -0,0 +1,54 @@
+#
+# 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.
+#
+
+upstream backend-api {
+  server localhost:3000;
+}
+
+server {
+  listen 80;
+  server_name _;
+
+  set $ignite_console_dir /opt/web-console/frontend/build;
+
+  root $ignite_console_dir;
+
+  error_page 500 502 503 504 /50x.html;
+
+  location / {
+    try_files $uri /index.html = 404;
+  }
+
+  location /api/v1 {
+    rewrite /api/v1/(.*) /$1 break;
+    proxy_set_header Host $http_host;
+    proxy_pass http://backend-api;
+  }
+
+  location /socket.io {
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection "upgrade";
+    proxy_http_version 1.1;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    proxy_set_header Host $host;
+    proxy_pass http://backend-api;
+  }
+
+  location = /50x.html {
+    root $ignite_console_dir/error_page;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/.babelrc
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/.babelrc 
b/modules/web-console/frontend/.babelrc
new file mode 100644
index 0000000..a1d48c1
--- /dev/null
+++ b/modules/web-console/frontend/.babelrc
@@ -0,0 +1,9 @@
+{
+  "presets": ["angular"],
+  "plugins": [[
+    "transform-builtin-extend", {
+      "globals": ["Error", "Array"],
+      "approximate": true
+    }
+  ]]
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/.eslintrc
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/.eslintrc 
b/modules/web-console/frontend/.eslintrc
new file mode 100644
index 0000000..a8a3bb8
--- /dev/null
+++ b/modules/web-console/frontend/.eslintrc
@@ -0,0 +1,202 @@
+parser: "babel-eslint"
+
+env:
+    es6: true
+    browser: true
+
+ecmaFeatures:
+    arrowFunctions: true
+    blockBindings: true
+    classes: true
+    defaultParams: true
+    destructuring: true
+    module: true
+    objectLiteralComputedProperties: true
+    objectLiteralShorthandMethods: true
+    objectLiteralShorthandProperties: true
+    spread: true
+    templateStrings: true
+    experimentalObjectRestSpread: true
+
+globals:
+    _: true
+    $: true
+    d3: true
+    io: true
+    window: true
+    global: true
+    angular: true
+    $generatorCommon: true
+    $generatorProperties: true
+    $generatorXml: true
+    $generatorJava: true
+    $generatorPom: true
+    $generatorReadme: true
+    $generatorDocker: true
+    $generatorOptional: true
+    saveAs: true
+    process: true
+
+rules:
+    arrow-parens: [1, "always"]
+    arrow-spacing: [1, { "before": true, "after": true }]
+    accessor-pairs: 2
+    block-scoped-var: 2
+    brace-style: [0, "1tbs"]
+    comma-dangle: [2, "never"]
+    comma-spacing: [2, {"before": false, "after": true}]
+    comma-style: [2, "last"]
+    complexity: [1, 40]
+    computed-property-spacing: [2, "never"]
+    consistent-return: 0
+    consistent-this: [0, "that"]
+    constructor-super: 2
+    curly: [2, "multi-or-nest"]
+    default-case: 2
+    dot-location: 0
+    dot-notation: [2, { "allowKeywords": true }]
+    eol-last: 2
+    eqeqeq: 2
+    func-names: 0
+    func-style: [0, "declaration"]
+    generator-star-spacing: 0
+    guard-for-in: 1
+    handle-callback-err: 0
+    id-length: [2, {"min": 1, "max": 60}]
+    indent: [2, 4, {"SwitchCase": 1}]
+    key-spacing: [2, { "beforeColon": false, "afterColon": true }]
+    lines-around-comment: 0
+    linebreak-style: [0, "unix"]
+    max-depth: [0, 4]
+    max-len: [0, 120, 4]
+    max-nested-callbacks: [1, 4]
+    max-params: [0, 3]
+    max-statements: [0, 10]
+    new-cap: 2
+    new-parens: 2
+    no-alert: 2
+    no-array-constructor: 2
+    no-bitwise: 0
+    no-caller: 2
+    no-catch-shadow: 2
+    no-cond-assign: 2
+    no-console: 0
+    no-constant-condition: 2
+    no-continue: 0
+    no-class-assign: 2
+    no-const-assign: 2
+    no-control-regex: 2
+    no-debugger: 2
+    no-delete-var: 2
+    no-div-regex: 0
+    no-dupe-keys: 2
+    no-dupe-args: 2
+    no-duplicate-case: 2
+    no-else-return: 2
+    no-empty: 2
+    no-empty-character-class: 2
+    no-eq-null: 2
+    no-eval: 2
+    no-ex-assign: 2
+    no-extend-native: 2
+    no-extra-bind: 2
+    no-extra-boolean-cast: 2
+    no-extra-parens: 0
+    no-extra-semi: 2
+    no-fallthrough: 2
+    no-floating-decimal: 1
+    no-func-assign: 2
+    no-implied-eval: 2
+    no-inline-comments: 0
+    no-inner-declarations: [2, "functions"]
+    no-invalid-regexp: 2
+    no-irregular-whitespace: 2
+    no-iterator: 2
+    no-label-var: 2
+    no-labels: 2
+    no-lone-blocks: 2
+    no-lonely-if: 2
+    no-implicit-coercion: [2, {"boolean": false, "number": true, "string": 
true}]
+    no-loop-func: 2
+    no-mixed-requires: [0, false]
+    no-mixed-spaces-and-tabs: [2, true]
+    no-multi-spaces: 2
+    no-multi-str: 2
+    no-multiple-empty-lines: [0, {"max": 2}]
+    no-native-reassign: 2
+    no-negated-in-lhs: 2
+    no-nested-ternary: 0
+    no-new: 2
+    no-new-func: 2
+    no-new-object: 2
+    no-new-require: 0
+    no-new-wrappers: 2
+    no-obj-calls: 2
+    no-octal: 2
+    no-octal-escape: 2
+    no-param-reassign: 0
+    no-path-concat: 0
+    no-plusplus: 0
+    no-process-env: 0
+    no-process-exit: 1
+    no-proto: 2
+    no-redeclare: 2
+    no-regex-spaces: 1
+    no-restricted-modules: 0
+    no-script-url: 0
+    no-self-compare: 2
+    no-sequences: 2
+    no-shadow: 2
+    no-shadow-restricted-names: 2
+    no-spaced-func: 2
+    no-sparse-arrays: 1
+    no-sync: 0
+    no-ternary: 0
+    no-trailing-spaces: 2
+    no-throw-literal: 0
+    no-this-before-super: 2
+    no-unexpected-multiline: 2
+    no-undef: 2
+    no-undef-init: 2
+    no-undefined: 2
+    no-unneeded-ternary: 2
+    no-unreachable: 2
+    no-unused-expressions: [2, { allowShortCircuit: true }]
+    no-unused-vars: [2, {"vars": "all", "args": "after-used"}]
+    no-use-before-define: 2
+    no-useless-call: 2
+    no-void: 0
+    no-var: 2
+    no-warning-comments: 0
+    no-with: 2
+    newline-after-var: 0
+    object-shorthand: [2, "always"]
+    one-var: [2, "never"]
+    operator-assignment: [2, "always"]
+    operator-linebreak: 0
+    padded-blocks: 0
+    prefer-const: 1
+    prefer-spread: 2
+    quote-props: [2, "as-needed"]
+    quotes: [2, "single"]
+    radix: 1
+    semi: [2, "always"]
+    semi-spacing: [2, {"before": false, "after": true}]
+    sort-vars: 0
+    keyword-spacing: 2
+    space-before-blocks: [2, "always"]
+    space-before-function-paren: [2, "never"]
+    space-in-parens: 0
+    space-infix-ops: 2
+    space-unary-ops: [2, { "words": true, "nonwords": false }]
+    spaced-comment: [1, "always"]
+    use-isnan: 2
+    valid-jsdoc: 0
+    valid-typeof: 2
+    vars-on-top: 2
+    wrap-iife: 0
+    wrap-regex: 0
+    yoda: [2, "never"]
+
+parserOptions:
+    sourceType: module

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/.gitignore
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/.gitignore 
b/modules/web-console/frontend/.gitignore
new file mode 100644
index 0000000..46bca13
--- /dev/null
+++ b/modules/web-console/frontend/.gitignore
@@ -0,0 +1,7 @@
+*.idea
+*.log
+.npmrc
+build/*
+node_modules
+ignite_modules_temp/*
+public/stylesheets/*.css

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/app.config.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/app.config.js 
b/modules/web-console/frontend/app/app.config.js
new file mode 100644
index 0000000..25c24b0
--- /dev/null
+++ b/modules/web-console/frontend/app/app.config.js
@@ -0,0 +1,86 @@
+/*
+ * 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/6af6560a/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
new file mode 100644
index 0000000..45851a2
--- /dev/null
+++ b/modules/web-console/frontend/app/app.js
@@ -0,0 +1,270 @@
+/*
+ * 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 '../public/stylesheets/style.scss';
+import './helpers/jade/mixins.jade';
+
+import './app.config';
+
+import './decorator/select';
+import './decorator/tooltip';
+
+import './modules/form/form.module';
+import './modules/agent/agent.module.js';
+import './modules/sql/sql.module';
+import './modules/Demo/Demo.module.js';
+
+import './modules/states/signin.state';
+import './modules/states/logout.state';
+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';
+import './modules/branding/branding.module';
+import './modules/navbar/navbar.module';
+import './modules/configuration/configuration.module';
+import './modules/getting-started/GettingStarted.provider';
+import './modules/dialog/dialog.module';
+import './modules/version/Version.provider';
+import './modules/ace.module';
+import './modules/socket.module';
+import './modules/loading/loading.module';
+// endignite
+
+// Directives.
+import igniteAutoFocus from './directives/auto-focus.directive.js';
+import igniteBsAffixUpdate from './directives/bs-affix-update.directive';
+import igniteCentered from './directives/centered/centered.directive.js';
+import igniteCopyToClipboard from 
'./directives/copy-to-clipboard.directive.js';
+import igniteHideOnStateChange from 
'./directives/hide-on-state-change/hide-on-state-change.directive';
+import igniteInformation from './directives/information/information.directive';
+import igniteMatch from './directives/match.directive.js';
+import igniteOnClickFocus from './directives/on-click-focus.directive.js';
+import igniteOnEnter from './directives/on-enter.directive.js';
+import igniteOnEnterFocusMove from 
'./directives/on-enter-focus-move.directive.js';
+import igniteOnEscape from './directives/on-escape.directive.js';
+import igniteUiAceDocker from 
'./directives/ui-ace-docker/ui-ace-docker.directive';
+import igniteUiAceJava from './directives/ui-ace-java/ui-ace-java.directive';
+import igniteUiAcePojos from 
'./directives/ui-ace-pojos/ui-ace-pojos.directive';
+import igniteUiAcePom from './directives/ui-ace-pom/ui-ace-pom.directive';
+import igniteUiAceTabs from './directives/ui-ace-tabs.directive';
+import igniteUiAceXml from './directives/ui-ace-xml/ui-ace-xml.directive';
+
+// Services.
+import ChartColors from './services/ChartColors.service';
+import Clone from './services/Clone.service.js';
+import Confirm from './services/Confirm.service.js';
+import ConfirmBatch from './services/ConfirmBatch.service.js';
+import CopyToClipboard from './services/CopyToClipboard.service';
+import Countries from './services/Countries.service';
+import Focus from './services/Focus.service';
+import InetAddress from './services/InetAddress.service';
+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';
+
+// Providers.
+
+// Filters.
+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';
+import $generatorJava from 'generator/generator-java';
+import $generatorOptional from 'generator/generator-optional';
+import $generatorProperties from 'generator/generator-properties';
+import $generatorReadme from 'generator/generator-readme';
+import $generatorXml from 'generator/generator-xml';
+
+window.$generatorCommon = $generatorCommon;
+window.$generatorJava = $generatorJava;
+window.$generatorOptional = $generatorOptional;
+window.$generatorProperties = $generatorProperties;
+window.$generatorReadme = $generatorReadme;
+window.$generatorXml = $generatorXml;
+
+// Controllers
+import admin from 'controllers/admin-controller';
+import caches from 'controllers/caches-controller';
+import clusters from 'controllers/clusters-controller';
+import domains from 'controllers/domains-controller';
+import igfs from 'controllers/igfs-controller';
+import profile from 'controllers/profile-controller';
+import auth from './controllers/auth.controller';
+import resetPassword from './controllers/reset-password.controller';
+
+// Inject external modules.
+import 'ignite_modules_temp/index';
+
+import baseTemplate from '../views/base.jade';
+
+angular
+.module('ignite-console', [
+    // Optional AngularJS modules.
+    'ngAnimate',
+    'ngSanitize',
+    // Third party libs.
+    'ngRetina',
+    'btford.socket-io',
+    'mgcrea.ngStrap',
+    'ui.router',
+    'gridster',
+    'dndLists',
+    'nvd3',
+    'smart-table',
+    'treeControl',
+    'ui.grid',
+    'ui.grid.saveState',
+    'ui.grid.selection',
+    'ui.grid.resizeColumns',
+    'ui.grid.autoResize',
+    'ui.grid.exporter',
+    // Base modules.
+    'ignite-console.ace',
+    'ignite-console.Form',
+    'ignite-console.user',
+    'ignite-console.branding',
+    'ignite-console.socket',
+    'ignite-console.agent',
+    'ignite-console.sql',
+    'ignite-console.demo',
+    // States.
+    'ignite-console.states.login',
+    'ignite-console.states.logout',
+    'ignite-console.states.password',
+    'ignite-console.states.configuration',
+    'ignite-console.states.profile',
+    'ignite-console.states.admin',
+    'ignite-console.states.errors',
+    // Common modules.
+    'ignite-console.dialog',
+    'ignite-console.navbar',
+    'ignite-console.configuration',
+    'ignite-console.getting-started',
+    'ignite-console.version',
+    'ignite-console.loading',
+    // Ignite configuration module.
+    'ignite-console.config',
+    // Ignite modules.
+    'ignite-console.modules'
+])
+// Directives.
+.directive(...igniteAutoFocus)
+.directive(...igniteBsAffixUpdate)
+.directive(...igniteCentered)
+.directive(...igniteCopyToClipboard)
+.directive(...igniteHideOnStateChange)
+.directive(...igniteInformation)
+.directive(...igniteMatch)
+.directive(...igniteOnClickFocus)
+.directive(...igniteOnEnter)
+.directive(...igniteOnEnterFocusMove)
+.directive(...igniteOnEscape)
+.directive(...igniteUiAceDocker)
+.directive(...igniteUiAceJava)
+.directive(...igniteUiAcePojos)
+.directive(...igniteUiAcePom)
+.directive(...igniteUiAceTabs)
+.directive(...igniteUiAceXml)
+// Services.
+.service(...ChartColors)
+.service(...Clone)
+.service(...Confirm)
+.service(...ConfirmBatch)
+.service(...CopyToClipboard)
+.service(...Countries)
+.service(...Focus)
+.service(...InetAddress)
+.service(...JavaTypes)
+.service(...Messages)
+.service(...ModelNormalizer)
+.service(...LegacyTable)
+.service('IgniteErrorPopover', ErrorPopover)
+.service(...FormUtils)
+.service(...LegacyUtils)
+.service(...UnsavedChangesGuard)
+// Controllers.
+.controller(...admin)
+.controller(...auth)
+.controller(...resetPassword)
+.controller(...caches)
+.controller(...clusters)
+.controller(...domains)
+.controller(...igfs)
+.controller(...profile)
+// Filters.
+.filter(...hasPojo)
+.filter(...domainsValidation)
+.filter(...byName)
+.filter(...duration)
+.config(['$stateProvider', '$locationProvider', '$urlRouterProvider', 
($stateProvider, $locationProvider, $urlRouterProvider) => {
+    // Set up the states.
+    $stateProvider
+        .state('base', {
+            url: '',
+            abstract: true,
+            templateUrl: baseTemplate
+        })
+        .state('settings', {
+            url: '/settings',
+            abstract: true,
+            templateUrl: baseTemplate
+        });
+
+    $urlRouterProvider.otherwise('/404');
+    $locationProvider.html5Mode(true);
+}])
+.run(['$rootScope', '$state', 'MetaTags', 'gettingStarted', ($root, $state, 
$meta, gettingStarted) => {
+    $root._ = _;
+    $root.$state = $state;
+    $root.$meta = $meta;
+    $root.gettingStarted = gettingStarted;
+}])
+.run(['$rootScope', 'IgniteAgentMonitor', ($root, agentMonitor) => {
+    $root.$on('user', () => agentMonitor.init());
+}])
+.run(['$rootScope', ($root) => {
+    $root.$on('$stateChangeStart', () => {
+        _.forEach(angular.element('.modal'), (m) => 
angular.element(m).scope().$hide());
+    });
+}])
+.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.load)
+                .then((user) => {
+                    $root.$broadcast('user', user);
+
+                    $state.go('settings.admin');
+                })
+                .catch(Messages.showError);
+        };
+    }
+]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/controllers/auth.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/controllers/auth.controller.js 
b/modules/web-console/frontend/app/controllers/auth.controller.js
new file mode 100644
index 0000000..21ffeb8
--- /dev/null
+++ b/modules/web-console/frontend/app/controllers/auth.controller.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.
+ */
+
+// 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/6af6560a/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
new file mode 100644
index 0000000..da0c37b
--- /dev/null
+++ b/modules/web-console/frontend/app/controllers/reset-password.controller.js
@@ -0,0 +1,50 @@
+/*
+ * 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(() => {
+                    $state.go('signin');
+
+                    Messages.showInfo('Password successfully changed');
+                })
+                .error((err, state) => {
+                    if (state === 503)
+                        $state.go('signin');
+
+                    Messages.showError(err);
+                });
+        };
+    }
+]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/data/colors.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/data/colors.json 
b/modules/web-console/frontend/app/data/colors.json
new file mode 100644
index 0000000..188e485
--- /dev/null
+++ b/modules/web-console/frontend/app/data/colors.json
@@ -0,0 +1,22 @@
+[
+  "#1f77b4",
+  "#ff7f0e",
+  "#2ca02c",
+  "#d62728",
+  "#9467bd",
+  "#8c564b",
+  "#e377c2",
+  "#7f7f7f",
+  "#bcbd22",
+  "#17becf",
+  "#ffbb78",
+  "#98df8a",
+  "#ff9896",
+  "#c5b0d5",
+  "#aec7e8",
+  "#c49c94",
+  "#f7b6d2",
+  "#c7c7c7",
+  "#dbdb8d",
+  "#9edae5"
+]

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/data/countries.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/data/countries.json 
b/modules/web-console/frontend/app/data/countries.json
new file mode 100644
index 0000000..f420f48
--- /dev/null
+++ b/modules/web-console/frontend/app/data/countries.json
@@ -0,0 +1,94 @@
+[
+  {
+    "name": "United States",
+    "code": "USA"
+  },
+  {
+    "name": "Canada",
+    "code": "CAN"
+  },
+  {
+    "name": "United Kingdom",
+    "code": "GBR"
+  },
+  {
+    "name": "Germany",
+    "code": "DEU"
+  },
+  {
+    "name": "France",
+    "code": "FRA"
+  },
+  {
+    "name": "Switzerland",
+    "code": "CHE"
+  },
+  {
+    "name": "Netherlands",
+    "code": "NLD"
+  },
+  {
+    "name": "Israel",
+    "code": "ISR"
+  },
+  {
+    "name": "Sweden",
+    "code": "SWE"
+  },
+  {
+    "name": "Russia",
+    "code": "RUS"
+  },
+  {
+    "name": "Other Europe",
+    "code": "Other Europe"
+  },
+  {
+    "name": "China",
+    "code": "CHN"
+  },
+  {
+    "name": "India",
+    "code": "IND"
+  },
+  {
+    "name": "Japan",
+    "code": "JPN"
+  },
+  {
+    "name": "Other Asia",
+    "code": "Other Asia"
+  },
+  {
+    "name": "Australia",
+    "code": "AUS"
+  },
+  {
+    "name": "Brazil",
+    "code": "BRA"
+  },
+  {
+    "name": "Argentina",
+    "code": "ARG"
+  },
+  {
+    "name": "Other South America",
+    "code": "Other South America"
+  },
+  {
+    "name": "South Africa",
+    "code": "ZAF"
+  },
+  {
+    "name": "Nigeria",
+    "code": "NGA"
+  },
+  {
+    "name": "Other Africa",
+    "code": "Other Africa"
+  },
+  {
+    "name": "Rest of the World",
+    "code": "Rest of the World"
+  }
+]

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/data/demo-info.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/data/demo-info.json 
b/modules/web-console/frontend/app/data/demo-info.json
new file mode 100644
index 0000000..0d2ad22
--- /dev/null
+++ b/modules/web-console/frontend/app/data/demo-info.json
@@ -0,0 +1,14 @@
+[
+    {
+        "title": "Apache Ignite Web Console Demo",
+        "message": [
+            "<div>",
+            " <h4><i class='fa fa-cogs fa-cursor-default'></i>&nbsp;What Can 
You Do</h4>",
+            " <ul>",
+            "  <li><b>Configuration</b> to checkout predefined clusters, 
caches, domain models and IGFS</li>",
+            "  <li><b>SQL</b> to run various SQL queries on the demo 
database</li>",
+            " </ul>",
+            "</div>"
+        ]
+    }
+]

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/data/event-types.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/data/event-types.json 
b/modules/web-console/frontend/app/data/event-types.json
new file mode 100644
index 0000000..8d0c878
--- /dev/null
+++ b/modules/web-console/frontend/app/data/event-types.json
@@ -0,0 +1,169 @@
+[
+  {
+    "label": "EVTS_CHECKPOINT",
+    "value": "EVTS_CHECKPOINT",
+    "class": "org.apache.ignite.events.EventType",
+    "events": [
+      "EVT_CHECKPOINT_SAVED",
+      "EVT_CHECKPOINT_LOADED",
+      "EVT_CHECKPOINT_REMOVED"
+    ]
+  },
+  {
+    "label": "EVTS_DEPLOYMENT",
+    "value": "EVTS_DEPLOYMENT",
+    "class": "org.apache.ignite.events.EventType",
+    "events": [
+      "EVT_CLASS_DEPLOYED",
+      "EVT_CLASS_UNDEPLOYED",
+      "EVT_CLASS_DEPLOY_FAILED",
+      "EVT_TASK_DEPLOYED",
+      "EVT_TASK_UNDEPLOYED",
+      "EVT_TASK_DEPLOY_FAILED"
+    ]
+  },
+  {
+    "label": "EVTS_ERROR",
+    "value": "EVTS_ERROR",
+    "class": "org.apache.ignite.events.EventType",
+    "events": [
+      "EVT_JOB_TIMEDOUT",
+      "EVT_JOB_FAILED",
+      "EVT_JOB_FAILED_OVER",
+      "EVT_JOB_REJECTED",
+      "EVT_JOB_CANCELLED",
+      "EVT_TASK_TIMEDOUT",
+      "EVT_TASK_FAILED",
+      "EVT_CLASS_DEPLOY_FAILED",
+      "EVT_TASK_DEPLOY_FAILED",
+      "EVT_TASK_DEPLOYED",
+      "EVT_TASK_UNDEPLOYED",
+      "EVT_CACHE_REBALANCE_STARTED",
+      "EVT_CACHE_REBALANCE_STOPPED"
+    ]
+  },
+  {
+    "label": "EVTS_DISCOVERY",
+    "value": "EVTS_DISCOVERY",
+    "class": "org.apache.ignite.events.EventType",
+    "events": [
+      "EVT_NODE_JOINED",
+      "EVT_NODE_LEFT",
+      "EVT_NODE_FAILED",
+      "EVT_NODE_SEGMENTED",
+      "EVT_CLIENT_NODE_DISCONNECTED",
+      "EVT_CLIENT_NODE_RECONNECTED"
+    ]
+  },
+  {
+    "label": "EVTS_JOB_EXECUTION",
+    "value": "EVTS_JOB_EXECUTION",
+    "class": "org.apache.ignite.events.EventType",
+    "events": [
+      "EVT_JOB_MAPPED",
+      "EVT_JOB_RESULTED",
+      "EVT_JOB_FAILED_OVER",
+      "EVT_JOB_STARTED",
+      "EVT_JOB_FINISHED",
+      "EVT_JOB_TIMEDOUT",
+      "EVT_JOB_REJECTED",
+      "EVT_JOB_FAILED",
+      "EVT_JOB_QUEUED",
+      "EVT_JOB_CANCELLED"
+    ]
+  },
+  {
+    "label": "EVTS_TASK_EXECUTION",
+    "value": "EVTS_TASK_EXECUTION",
+    "class": "org.apache.ignite.events.EventType",
+    "events": [
+      "EVT_TASK_STARTED",
+      "EVT_TASK_FINISHED",
+      "EVT_TASK_FAILED",
+      "EVT_TASK_TIMEDOUT",
+      "EVT_TASK_SESSION_ATTR_SET",
+      "EVT_TASK_REDUCED"
+    ]
+  },
+  {
+    "label": "EVTS_CACHE",
+    "value": "EVTS_CACHE",
+    "class": "org.apache.ignite.events.EventType",
+    "events": [
+      "EVT_CACHE_ENTRY_CREATED",
+      "EVT_CACHE_ENTRY_DESTROYED",
+      "EVT_CACHE_OBJECT_PUT",
+      "EVT_CACHE_OBJECT_READ",
+      "EVT_CACHE_OBJECT_REMOVED",
+      "EVT_CACHE_OBJECT_LOCKED",
+      "EVT_CACHE_OBJECT_UNLOCKED",
+      "EVT_CACHE_OBJECT_SWAPPED",
+      "EVT_CACHE_OBJECT_UNSWAPPED",
+      "EVT_CACHE_OBJECT_EXPIRED"
+    ]
+  },
+  {
+    "label": "EVTS_CACHE_REBALANCE",
+    "value": "EVTS_CACHE_REBALANCE",
+    "class": "org.apache.ignite.events.EventType",
+    "events": [
+      "EVT_CACHE_REBALANCE_STARTED",
+      "EVT_CACHE_REBALANCE_STOPPED",
+      "EVT_CACHE_REBALANCE_PART_LOADED",
+      "EVT_CACHE_REBALANCE_PART_UNLOADED",
+      "EVT_CACHE_REBALANCE_OBJECT_LOADED",
+      "EVT_CACHE_REBALANCE_OBJECT_UNLOADED",
+      "EVT_CACHE_REBALANCE_PART_DATA_LOST"
+    ]
+  },
+  {
+    "label": "EVTS_CACHE_LIFECYCLE",
+    "value": "EVTS_CACHE_LIFECYCLE",
+    "class": "org.apache.ignite.events.EventType",
+    "events": [
+      "EVT_CACHE_STARTED",
+      "EVT_CACHE_STOPPED",
+      "EVT_CACHE_NODES_LEFT"
+    ]
+  },
+  {
+    "label": "EVTS_CACHE_QUERY",
+    "value": "EVTS_CACHE_QUERY",
+    "class": "org.apache.ignite.events.EventType",
+    "events": [
+      "EVT_CACHE_QUERY_EXECUTED",
+      "EVT_CACHE_QUERY_OBJECT_READ"
+    ]
+  },
+  {
+    "label": "EVTS_SWAPSPACE",
+    "value": "EVTS_SWAPSPACE",
+    "class": "org.apache.ignite.events.EventType",
+    "events": [
+      "EVT_SWAP_SPACE_CLEARED",
+      "EVT_SWAP_SPACE_DATA_REMOVED",
+      "EVT_SWAP_SPACE_DATA_READ",
+      "EVT_SWAP_SPACE_DATA_STORED",
+      "EVT_SWAP_SPACE_DATA_EVICTED"
+    ]
+  },
+  {
+    "label": "EVTS_IGFS",
+    "value": "EVTS_IGFS",
+    "class": "org.apache.ignite.events.EventType",
+    "events": [
+      "EVT_IGFS_FILE_CREATED",
+      "EVT_IGFS_FILE_RENAMED",
+      "EVT_IGFS_FILE_DELETED",
+      "EVT_IGFS_FILE_OPENED_READ",
+      "EVT_IGFS_FILE_OPENED_WRITE",
+      "EVT_IGFS_FILE_CLOSED_WRITE",
+      "EVT_IGFS_FILE_CLOSED_READ",
+      "EVT_IGFS_FILE_PURGED",
+      "EVT_IGFS_META_UPDATED",
+      "EVT_IGFS_DIR_CREATED",
+      "EVT_IGFS_DIR_RENAMED",
+      "EVT_IGFS_DIR_DELETED"
+    ]
+  }
+]

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/data/getting-started.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/data/getting-started.json 
b/modules/web-console/frontend/app/data/getting-started.json
new file mode 100644
index 0000000..1b435ab
--- /dev/null
+++ b/modules/web-console/frontend/app/data/getting-started.json
@@ -0,0 +1,109 @@
+[
+    {
+        "title": "With Apache Ignite Web Console You Can",
+        "message": [
+            "<div class='col-xs-4'>",
+            " <img src='/images/ignite-puzzle.png' width='80%' 
class='getting-started-puzzle' />",
+            "</div>",
+            "<div class='col-xs-8'>",
+            " <ul>",
+            "  <li>Generate cluster configuration</li>",
+            "  <li>Import domain model from database</li>",
+            "  <li>Configure all needed caches</li>",
+            "  <li>Preview generated XML and Java code in browser</li>",
+            "  <li>Download ready-to-use Maven project</li>",
+            "  <li>Execute SQL queries on real clusters</li>",
+            " </ul>",
+            "</div>"
+        ]
+    },
+    {
+        "title": "Clusters",
+        "message": [
+            "<div class='col-xs-7'>",
+            " <img src='/images/cluster.png' width='100%' />",
+            "</div>",
+            "<div class='col-xs-5'>",
+            " <ul>",
+            "  <li>Configure cluster properties</li>",
+            "  <li>Associate cluster with caches</li>",
+            " </ul>",
+            "</div>"
+        ]
+    },
+    {
+        "title": "Domain Model",
+        "message": [
+            "<div class='col-xs-7'>",
+            " <img src='/images/domains.png' width='100%' />",
+            "</div>",
+            "<div class='col-xs-5'>",
+            " <ul>",
+            "  <li>Import database schemas</li>",
+            "  <li>Try in <span class='getting-started-demo'>Demo</span> 
mode</li>",
+            " </ul>",
+            "</div>"
+        ]
+    },
+    {
+        "title": "Caches",
+        "message": [
+            "<div class='col-xs-7'>",
+            " <img src='/images/cache.png' width='100%' />",
+            "</div>",
+            "<div class='col-xs-5'>",
+            " <ul>",
+            "  <li>Configure memory settings</li>",
+            "  <li>Configure persistence</li>",
+            " </ul>",
+            "</div>"
+        ]
+    },
+    {
+        "title": "In-memory File System",
+        "message": [
+            "<div class='col-xs-7'>",
+            " <img src='/images/igfs.png' width='100%' />",
+            "</div>",
+            "<div class='col-xs-5'>",
+            " <ul>",
+            "  <li>Configure IGFS properties</li>",
+            "  <li>Associate IGFS with clusters</li>",
+            " </ul>",
+            "</div>"
+        ]
+    },
+    {
+      "title": "Summary",
+      "message": [
+          "<div class='col-xs-7'>",
+          " <img src='/images/summary.png' width='100%' />",
+          "</div>",
+          "<div class='col-xs-5'>",
+          " <ul>",
+          "  <li>Preview XML configuration</li>",
+          "  <li>Preview code configuration</li>",
+          "  <li>Preview Docker file</li>",
+          "  <li>Preview POM dependencies</li>",
+          "  <li>Download ready-to-use project</li>",
+          " </ul>",
+          "</div>"
+      ]
+    },
+    {
+        "title": "SQL Queries",
+        "message": [
+            "<div class='col-xs-7'>",
+            " <img src='/images/query-table.png' width='100%' />",
+            "</div>",
+            "<div class='col-xs-5'>",
+            " <ul>",
+            "  <li>Execute SQL Queries</li>",
+            "  <li>View Execution Paln</li>",
+            "  <li>View In-Memory Schema</li>",
+            "  <li>View Streaming Charts</li>",
+            " </ul>",
+            "</div>"
+        ]
+    }
+]

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/data/java-classes.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/data/java-classes.json 
b/modules/web-console/frontend/app/data/java-classes.json
new file mode 100644
index 0000000..b0ec9fb
--- /dev/null
+++ b/modules/web-console/frontend/app/data/java-classes.json
@@ -0,0 +1,19 @@
+[
+  {"short": "BigDecimal", "full": "java.math.BigDecimal"},
+  {"short": "Boolean", "full": "java.lang.Boolean"},
+  {"short": "Byte", "full": "java.lang.Byte"},
+  {"short": "Character", "full": "java.lang.Character"},
+  {"short": "Date", "full": "java.sql.Date"},
+  {"short": "java.util.Date", "full": "java.util.Date"},
+  {"short": "Double", "full": "java.lang.Double"},
+  {"short": "Float", "full": "java.lang.Float"},
+  {"short": "Integer", "full": "java.lang.Integer"},
+  {"short": "Long", "full": "java.lang.Long"},
+  {"short": "Number", "full": "java.lang.Number"},
+  {"short": "Object", "full": "java.lang.Object"},
+  {"short": "Short", "full": "java.lang.Short"},
+  {"short": "String", "full": "java.lang.String"},
+  {"short": "Time", "full": "java.sql.Time"},
+  {"short": "Timestamp", "full": "java.sql.Timestamp"},
+  {"short": "UUID", "full": "java.util.UUID"}
+]

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/data/java-keywords.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/data/java-keywords.json 
b/modules/web-console/frontend/app/data/java-keywords.json
new file mode 100644
index 0000000..a2d5ec2
--- /dev/null
+++ b/modules/web-console/frontend/app/data/java-keywords.json
@@ -0,0 +1,55 @@
+[
+  "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"
+]

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/data/java-primitives.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/data/java-primitives.json 
b/modules/web-console/frontend/app/data/java-primitives.json
new file mode 100644
index 0000000..eab6b69
--- /dev/null
+++ b/modules/web-console/frontend/app/data/java-primitives.json
@@ -0,0 +1,9 @@
+[
+  "boolean",
+  "byte",
+  "double",
+  "float",
+  "int",
+  "long",
+  "short"
+]

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/data/pom-dependencies.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/data/pom-dependencies.json 
b/modules/web-console/frontend/app/data/pom-dependencies.json
new file mode 100644
index 0000000..7ab6c1b
--- /dev/null
+++ b/modules/web-console/frontend/app/data/pom-dependencies.json
@@ -0,0 +1,20 @@
+{
+    "Cloud": {"artifactId": "ignite-cloud"},
+    "S3": {"artifactId": "ignite-aws"},
+    "GoogleStorage": {"artifactId": "ignite-gce"},
+    "ZooKeeper": {"artifactId": "ignite-zookeeper"},
+
+    "Log4j": {"artifactId": "ignite-log4j"},
+    "Log4j2": {"artifactId": "ignite-log4j2"},
+    "JCL": {"artifactId": "ignite-jcl"},
+    "HadoopIgfsJcl": {"artifactId": "ignite-hadoop"},
+    "SLF4J": {"artifactId": "ignite-slf4j"},
+
+    "Generic": {"groupId": "com.mchange", "artifactId": "c3p0", "version": 
"0.9.5.1"},
+    "MySQL": {"groupId": "mysql", "artifactId": "mysql-connector-java", 
"version": "5.1.37"},
+    "PostgreSQL": {"groupId": "org.postgresql", "artifactId": "postgresql", 
"version": "9.4-1204-jdbc42"},
+    "H2": {"groupId": "com.h2database", "artifactId": "h2", "version": 
"1.3.175"},
+    "Oracle": {"groupId": "oracle", "artifactId": "jdbc", "version": "11.2", 
"jar": "ojdbc6.jar"},
+    "DB2": {"groupId": "ibm", "artifactId": "jdbc", "version": "4.19.26", 
"jar": "db2jcc4.jar"},
+    "SQLServer": {"groupId": "microsoft", "artifactId": "jdbc", "version": 
"4.1", "jar": "sqljdbc41.jar"}
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/decorator/select.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/decorator/select.js 
b/modules/web-console/frontend/app/decorator/select.js
new file mode 100644
index 0000000..2d22707
--- /dev/null
+++ b/modules/web-console/frontend/app/decorator/select.js
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import angular from 'angular';
+
+/**
+ * Special decorator that fix problem in AngularStrap selectAll / deselectAll 
methods.
+ * If this problem will be fixed in AngularStrap we can remove this delegate.
+ */
+angular.module('mgcrea.ngStrap.select')
+    .decorator('$select', ['$delegate', ($delegate) => {
+        function SelectFactoryDecorated(element, controller, config) {
+            const delegate = $delegate(element, controller, config);
+
+            // Common vars.
+            const options = angular.extend({}, $delegate.defaults, config);
+
+            const scope = delegate.$scope;
+
+            const valueByIndex = (index) => {
+                if (angular.isUndefined(scope.$matches[index]))
+                    return null;
+
+                return scope.$matches[index].value;
+            };
+
+            const selectAll = (active) => {
+                const selected = [];
+
+                scope.$apply(() => {
+                    for (let i = 0; i < scope.$matches.length; i++) {
+                        if (scope.$isActive(i) === active) {
+                            selected[i] = scope.$matches[i].value;
+
+                            delegate.activate(i);
+
+                            
controller.$setViewValue(scope.$activeIndex.map(valueByIndex));
+                        }
+                    }
+                });
+
+                // Emit events.
+                for (let i = 0; i < selected.length; i++) {
+                    if (selected[i])
+                        scope.$emit(options.prefixEvent + '.select', 
selected[i], i, delegate);
+                }
+            };
+
+            scope.$selectAll = () => {
+                scope.$$postDigest(selectAll.bind(this, false));
+            };
+
+            scope.$selectNone = () => {
+                scope.$$postDigest(selectAll.bind(this, true));
+            };
+
+            return delegate;
+        }
+
+        SelectFactoryDecorated.defaults = $delegate.defaults;
+
+        return SelectFactoryDecorated;
+    }]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/decorator/tooltip.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/decorator/tooltip.js 
b/modules/web-console/frontend/app/decorator/tooltip.js
new file mode 100644
index 0000000..a47337a
--- /dev/null
+++ b/modules/web-console/frontend/app/decorator/tooltip.js
@@ -0,0 +1,56 @@
+/*
+ * 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';
+
+/**
+ * Special decorator that fix problem in AngularStrap $tooltip in special case.
+ * Case: when tooltip is shown on table row remove button and user click this 
button.
+ * If this problem will be fixed in AngularStrap we can remove this delegate.
+ */
+angular.module('mgcrea.ngStrap.tooltip')
+    .decorator('$tooltip', ['$delegate', ($delegate) => {
+        function TooltipFactoryDecorated(element, config) {
+            const delegate = $delegate(element, config);
+
+            const scope = delegate.$scope;
+
+            const options = delegate.$options;
+
+            const hideWraped = delegate.hide;
+
+            delegate.hide = (blur) => {
+                if (!delegate.$isShown)
+                    return;
+
+                if (delegate.$element !== null)
+                    return hideWraped(blur);
+
+                scope.$emit(options.prefixEvent + '.hide.before', delegate);
+
+                if (angular.isDefined(options.onBeforeHide) && 
angular.isFunction(options.onBeforeHide))
+                    options.onBeforeHide(delegate);
+
+                delegate.$isShown = scope.$isShown = false;
+                scope.$$phase || (scope.$root && scope.$root.$$phase) || 
scope.$digest();
+            };
+
+            return delegate;
+        }
+
+        return TooltipFactoryDecorated;
+    }]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/6af6560a/modules/web-console/frontend/app/directives/auto-focus.directive.js
----------------------------------------------------------------------
diff --git 
a/modules/web-console/frontend/app/directives/auto-focus.directive.js 
b/modules/web-console/frontend/app/directives/auto-focus.directive.js
new file mode 100644
index 0000000..326fe1f
--- /dev/null
+++ b/modules/web-console/frontend/app/directives/auto-focus.directive.js
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Directive to auto-focus specified element.
+export default ['igniteAutoFocus', ['$timeout', ($timeout) => {
+    return {
+        restrict: 'AC',
+        link(scope, element) {
+            $timeout(() => element[0].focus());
+        }
+    };
+}]];

Reply via email to