You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by an...@apache.org on 2015/07/23 10:41:06 UTC
[35/50] [abbrv] incubator-ignite git commit: # ignite-843 moved
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/metadata.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/metadata.js b/modules/web-control-center/src/main/js/routes/metadata.js
new file mode 100644
index 0000000..64b8763
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/metadata.js
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var router = require('express').Router();
+var db = require('../db');
+
+/* GET metadata page. */
+router.get('/', function (req, res) {
+ res.render('configuration/metadata');
+});
+
+/**
+ * Get spaces and metadata accessed for user account.
+ *
+ * @param req Request.
+ * @param res Response.
+ */
+router.post('/list', function (req, res) {
+ var user_id = req.currentUserId();
+
+ // Get owned space and all accessed space.
+ db.Space.find({$or: [{owner: user_id}, {usedBy: {$elemMatch: {account: user_id}}}]}, function (err, spaces) {
+ if (err)
+ return res.status(500).send(err.message);
+
+ var space_ids = spaces.map(function (value) {
+ return value._id;
+ });
+
+ // Get all metadata for spaces.
+ db.CacheTypeMetadata.find({space: {$in: space_ids}}).sort('name').exec(function (err, metadatas) {
+ if (err)
+ return res.status(500).send(err.message);
+
+ res.json({spaces: spaces, metadatas: metadatas});
+ });
+ });
+});
+
+/**
+ * Save metadata.
+ */
+router.post('/save', function (req, res) {
+ if (req.body._id)
+ db.CacheTypeMetadata.update({_id: req.body._id}, req.body, {upsert: true}, function (err) {
+ if (err)
+ return res.status(500).send(err.message);
+
+ res.send(req.body._id);
+ });
+ else {
+ db.CacheTypeMetadata.findOne({name: req.body.name}, function (err, metadata) {
+ if (err)
+ return res.status(500).send(err.message);
+
+ if (metadata)
+ return res.status(500).send('Cache type metadata with name: "' + metadata.name + '" already exist.');
+
+ (new db.CacheTypeMetadata(req.body)).save(function (err, metadata) {
+ if (err)
+ return res.status(500).send(err.message);
+
+ res.send(metadata._id);
+ });
+ });
+ }
+});
+
+/**
+ * Remove metadata by ._id.
+ */
+router.post('/remove', function (req, res) {
+ db.CacheTypeMetadata.remove(req.body, function (err) {
+ if (err)
+ return res.status(500).send(err.message);
+
+ res.sendStatus(200);
+ })
+});
+
+module.exports = router;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/profile.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/profile.js b/modules/web-control-center/src/main/js/routes/profile.js
new file mode 100644
index 0000000..0269e7d
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/profile.js
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var router = require('express').Router();
+var db = require('../db');
+
+router.all('/profile/*', function (req, res, next) {
+ var userId = req.body._id;
+
+ if (userId != req.currentUserId() && userId != req.user._id)
+ return res.sendStatus(403);
+ else
+ next();
+});
+
+/**
+ * Get user profile page.
+ */
+router.get('/', function (req, res) {
+ var user_id = req.currentUserId();
+
+ db.Account.findById(user_id, function (err) {
+ if (err)
+ return res.status(500).send(err.message);
+
+ res.render('settings/profile');
+ });
+});
+
+/**
+ * Save user profile.
+ */
+router.post('/saveUser', function (req, res) {
+ var params = req.body;
+
+ if (params.newPassword) {
+ var newPassword = params.newPassword;
+
+ if (!newPassword || newPassword.length == 0)
+ return res.status(500).send('Wrong value for new password');
+
+ db.Account.findById(params._id, function (err, user) {
+ if (err)
+ return res.status(500).send(err);
+
+ user.setPassword(newPassword, function (err, updatedUser) {
+ if (err)
+ return res.status(500).send(err.message);
+
+ if (params.userName)
+ updatedUser.username = params.userName;
+
+ if (params.email)
+ updatedUser.email = params.email;
+
+ updatedUser.save(function (err) {
+ if (err)
+ return res.status(500).send(err.message);
+
+ res.json(user);
+ });
+ });
+ });
+ }
+ else if (params.userName || params.email) {
+ var upd = {};
+
+ if (params.userName)
+ upd.username = params.userName;
+
+ if (params.email)
+ upd.email = params.email;
+
+ db.Account.findByIdAndUpdate(params._id, upd, {new: true}, function (err, val) {
+ if (err)
+ return res.status(500).send(err.message);
+
+ res.json(val);
+ })
+ }
+});
+
+module.exports = router;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/public.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/public.js b/modules/web-control-center/src/main/js/routes/public.js
new file mode 100644
index 0000000..290ba90
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/public.js
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var router = require('express').Router();
+var passport = require('passport');
+var db = require('../db');
+
+// GET dropdown-menu template.
+router.get('/select', function (req, res) {
+ res.render('templates/select', {});
+});
+
+// GET tabs template.
+router.get('/tab', function (req, res) {
+ res.render('templates/tab', {});
+});
+
+// GET confirmation dialog.
+router.get('/confirm', function (req, res) {
+ res.render('templates/confirm', {});
+});
+
+// GET save as dialog.
+router.get('/copy', function (req, res) {
+ res.render('templates/copy', {});
+});
+
+/* GET login page. */
+router.get('/login', function (req, res) {
+ res.render('login');
+});
+
+/**
+ * Register new account.
+ */
+router.post('/register', function (req, res) {
+ db.Account.count(function (err, cnt) {
+ if (err)
+ return res.status(401).send(err.message);
+
+ req.body.admin = cnt == 0;
+
+ db.Account.register(new db.Account(req.body), req.body.password, function (err, account) {
+ if (err)
+ return res.status(401).send(err.message);
+
+ if (!account)
+ return res.status(500).send('Failed to create account.');
+
+ new db.Space({name: 'Personal space', owner: account._id}).save();
+
+ req.logIn(account, {}, function (err) {
+ if (err)
+ return res.status(401).send(err.message);
+
+ return res.redirect('/configuration/clusters');
+ });
+ });
+ });
+});
+
+/**
+ * Login in exist account.
+ */
+router.post('/login', function (req, res, next) {
+ passport.authenticate('local', function (err, user) {
+ if (err)
+ return res.status(401).send(err.message);
+
+ if (!user)
+ return res.status(401).send('Invalid email or password');
+
+ req.logIn(user, {}, function (err) {
+ if (err)
+ return res.status(401).send(err.message);
+
+ res.redirect('/configuration/clusters');
+ });
+ })(req, res, next);
+});
+
+/**
+ * Logout.
+ */
+router.get('/logout', function (req, res) {
+ req.logout();
+
+ res.redirect('/');
+});
+
+/* GET home page. */
+router.get('/', function (req, res) {
+ if (req.isAuthenticated())
+ res.redirect('/configuration/clusters');
+ else
+ res.render('index');
+});
+
+///* GET sql page. */
+//router.get('/sql', function(req, res) {
+// res.render('sql', { user: req.user });
+//});
+//
+///* GET clients page. */
+//router.get('/clients', function(req, res) {
+// res.render('clients', { user: req.user });
+//});
+
+module.exports = router;
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/sql.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/sql.js b/modules/web-control-center/src/main/js/routes/sql.js
new file mode 100644
index 0000000..ce4565d
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/sql.js
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var router = require('express').Router();
+var db = require('../db');
+router.get('/', function(req, res) {
+ res.render('sql/sql');
+});
+
+module.exports = router;
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/summary.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/summary.js b/modules/web-control-center/src/main/js/routes/summary.js
new file mode 100644
index 0000000..f766945
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/summary.js
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var db = require('../db');
+
+var router = require('express').Router();
+
+var generatorXml = require('./generator/xml');
+var generatorJava = require('./generator/java');
+var generatorDocker = require('./generator/docker');
+
+/* GET summary page. */
+router.get('/', function (req, res) {
+ res.render('configuration/summary');
+});
+
+router.post('/generator', function (req, res) {
+ // Get cluster.
+ db.Cluster.findById(req.body._id).populate('caches').exec(function (err, cluster) {
+ if (err)
+ return res.status(500).send(err.message);
+
+ if (!cluster)
+ return res.sendStatus(404);
+
+ var clientCache = req.body.clientNearConfiguration;
+
+ if (clientCache)
+ return res.send({
+ xmlClient: generatorXml.generateClusterConfiguration(cluster, clientCache),
+ javaClient: generatorJava.generateClusterConfiguration(cluster, req.body.javaClass, clientCache)
+ });
+
+ return res.send({
+ xmlServer: generatorXml.generateClusterConfiguration(cluster),
+ javaSnippetServer: generatorJava.generateClusterConfiguration(cluster, false),
+ javaClassServer: generatorJava.generateClusterConfiguration(cluster, true),
+ docker: generatorDocker.generateClusterConfiguration(cluster, '%OS%')
+ });
+ });
+});
+
+router.post('/download', function (req, res) {
+ // Get cluster.
+ db.Cluster.findById(req.body._id).populate('caches').exec(function (err, cluster) {
+ if (err)
+ return res.status(500).send(err.message);
+
+ if (!cluster)
+ return res.sendStatus(404);
+
+ var clientNearConfiguration = req.body.clientNearConfiguration;
+
+ var archiver = require('archiver');
+
+ // Creating archive.
+ var zip = archiver('zip');
+
+ zip.on('error', function (err) {
+ res.status(500).send({error: err.message});
+ });
+
+ // On stream closed we can end the request.
+ res.on('close', function () {
+ return res.status(200).send('OK').end();
+ });
+
+ // Set the archive name.
+ res.attachment(cluster.name + (clientNearConfiguration ? '-client' : '') + '-configuration.zip');
+
+ var generatorCommon = require('./generator/common');
+
+ // Send the file to the page output.
+ zip.pipe(res);
+
+ var javaClass = req.body.javaClass;
+
+ if (!clientNearConfiguration) {
+ zip.append(generatorDocker.generateClusterConfiguration(cluster, req.body.os), {name: "Dockerfile"});
+
+ var props = generatorCommon.generateProperties(cluster);
+
+ if (props)
+ zip.append(props, {name: "secret.properties"});
+ }
+
+ zip.append(generatorXml.generateClusterConfiguration(cluster, clientNearConfiguration), {name: cluster.name + ".xml"})
+ .append(generatorJava.generateClusterConfiguration(cluster, javaClass, clientNearConfiguration),
+ {name: javaClass ? 'ConfigurationFactory.java' : cluster.name + '.snipplet.java'})
+ .finalize();
+ });
+});
+
+module.exports = router;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/configuration/caches.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/configuration/caches.jade b/modules/web-control-center/src/main/js/views/configuration/caches.jade
new file mode 100644
index 0000000..3a011fc
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/configuration/caches.jade
@@ -0,0 +1,74 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+extends sidebar
+
+append scripts
+ script(src='/caches-controller.js')
+
+include ../includes/controls
+
+block content
+ .docs-header
+ h1 Create and Configure Ignite Caches
+ hr
+ .docs-body(ng-controller='cachesController')
+ +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
+ .links(ng-hide='caches.length == 0')
+ .padding-dflt
+ lable.labelHeader Caches:
+ table(st-table='caches')
+ tbody
+ tr(ng-repeat='row in caches track by row._id')
+ td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
+ a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}}, {{row.atomicityMode | displayValue:atomicities:'Cache atomicity not set'}}
+ .padding-top-dflt
+ button.btn.btn-primary(ng-click='createItem()') Add cache
+ hr
+ form.form-horizontal(name='inputForm' ng-if='backupItem' novalidate)
+ div(bs-collapse data-start-collapsed='false')
+ .panel.panel-default
+ .panel-heading
+ h3
+ a(bs-collapse-toggle) General
+ .panel-collapse(bs-collapse-target)
+ .panel-body
+ .settings-row(ng-repeat='field in general')
+ +form-row(['col-sm-3'], ['col-sm-3'])
+ .panel-group(bs-collapse data-allow-multiple="true")
+ div(bs-collapse data-start-collapsed='true')
+ .panel-title(ng-show='expanded')
+ h3
+ a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
+ .panel-collapse(bs-collapse-target)
+ .span(bs-collapse data-start-collapsed='true' data-allow-multiple='true')
+ .panel.panel-default(ng-repeat='group in advanced')
+ .panel-heading
+ h3
+ a(bs-collapse-toggle) {{group.label}}
+ i.tipLabel.fa.fa-question-circle(ng-if='group.tip' bs-tooltip='joinTip(group.tip)' type='button')
+ i.tipLabel.fa.fa-question-circle.blank(ng-if='!group.tip')
+ .panel-collapse(bs-collapse-target)
+ .panel-body
+ .settings-row(ng-repeat='field in group.fields')
+ +form-row
+ .panel-title
+ h3
+ a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
+ div
+ button.btn.btn-primary(ng-disabled='inputForm.$invalid' ng-click='saveItem()') Save
+ button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
+ button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/configuration/clusters.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/configuration/clusters.jade b/modules/web-control-center/src/main/js/views/configuration/clusters.jade
new file mode 100644
index 0000000..81acfed
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/configuration/clusters.jade
@@ -0,0 +1,77 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+extends sidebar
+
+append scripts
+ script(src='/clusters-controller.js')
+
+include ../includes/controls
+
+block content
+ .docs-header
+ h1 Create and Configure Ignite Clusters
+ hr
+ .docs-body(ng-controller='clustersController')
+ +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
+ .links(ng-hide='clusters.length == 0')
+ .padding-dflt
+ lable.labelHeader Clusters:
+ table(st-table='clusters')
+ tbody
+ tr(ng-repeat='row in clusters track by row._id')
+ td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
+ a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.discovery.kind | displayValue:discoveries:'Discovery not set'}}
+ .padding-top-dflt
+ button.btn.btn-primary(ng-click='createItem()')  Add cluster
+ label(style='margin-left: 10px; margin-right: 10px') Use template:
+ button.btn.btn-default.base-control(ng-init='create.template = templates[0].value' ng-model='create.template' data-template='/select' data-placeholder='Choose cluster template' bs-options='item.value as item.label for item in templates' bs-select)
+ i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')
+ hr
+ form.form-horizontal(name='inputForm' ng-if='backupItem' novalidate)
+ div(bs-collapse data-start-collapsed='false')
+ .panel.panel-default
+ .panel-heading
+ h3
+ a(bs-collapse-toggle) General
+ .panel-collapse(bs-collapse-target)
+ .panel-body
+ .settings-row(ng-repeat='field in general')
+ +form-row
+ .panel-group(bs-collapse data-allow-multiple="true")
+ div(bs-collapse data-start-collapsed='true')
+ .panel-title(ng-show='expanded')
+ h3
+ a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
+ .panel-collapse(bs-collapse-target)
+ .span(bs-collapse data-start-collapsed='true' data-allow-multiple='true')
+ .panel.panel-default(ng-repeat='group in advanced')
+ .panel-heading
+ h3
+ a(bs-collapse-toggle) {{group.label}}
+ i.tipLabel.fa.fa-question-circle(ng-if='group.tip' bs-tooltip='joinTip(group.tip)' type='button')
+ i.tipLabel.fa.fa-question-circle.blank(ng-if='!group.tip')
+ .panel-collapse(bs-collapse-target)
+ .panel-body
+ .settings-row(ng-repeat='field in group.fields')
+ +form-row
+ .panel-title
+ h3
+ a(bs-collapse-toggle='0' ng-click='expanded = !expanded;') {{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}
+ div
+ button.btn.btn-primary(ng-disabled='inputForm.$invalid' ng-click='saveItem()') Save
+ button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
+ button.btn.btn-primary(ng-show='backupItem._id' ng-click='removeItem()') Remove
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/configuration/metadata.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/configuration/metadata.jade b/modules/web-control-center/src/main/js/views/configuration/metadata.jade
new file mode 100644
index 0000000..d5bac06
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/configuration/metadata.jade
@@ -0,0 +1,121 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+extends sidebar
+
+append scripts
+ script(src='/metadata-controller.js')
+
+include ../includes/controls
+
+block content
+ .docs-header
+ h1 Create and Configure Cache Type Metadata
+ hr
+ .docs-body(ng-controller='metadataController')
+ +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
+ .links(ng-hide='metadatas.length == 0')
+ .padding-dflt
+ lable.labelHeader Types metadata:
+ table(st-table='metadatas')
+ tbody
+ tr(ng-repeat='row in metadatas track by row._id')
+ td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
+ a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
+ .padding-top-dflt
+ button.btn.btn-primary(ng-click='panels.activePanel = [0]; createItem()')  Add metadata
+ label(style='margin-left: 6px; margin-right: 10px') For:
+ button.btn.btn-default(ng-model='template' data-template='/select' data-placeholder='Choose metadata type' bs-options='item.value as item.label for item in templates' bs-select)
+ i.tiplabel.fa.fa-question-circle(bs-tooltip data-title='{{joinTip(templateTip)}}' type='button')
+ hr
+ .panel-group(bs-collapse ng-model='panels.activePanel' data-allow-multiple="false")
+ .panel.panel-default
+ .panel-heading
+ h3
+ a(bs-collapse-toggle) Manual
+ .panel-collapse(role="tabpanel" bs-collapse-target)
+ .panel-body
+ form.form-horizontal(name='manualForm' ng-if='backupItem' novalidate)
+ .settings-row(ng-repeat='field in metadataManual')
+ +form-row
+ button.btn.btn-primary(ng-disabled='manualForm.$invalid' ng-click='saveItem()') Save
+ button.btn.btn-primary(ng-show='backupItem._id' ng-disabled='inputForm.$invalid' ng-click='saveItemAs()') Copy
+ button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove
+ .panel.panel-default
+ .panel-heading
+ h3
+ a(bs-collapse-toggle) Load from database
+ .panel-collapse(bs-collapse-target)
+ .panel-body
+ form.form-horizontal(name='dbForm' novalidate)
+ .settings-row(ng-repeat='field in metadataDb')
+ +form-row
+ div(ng-hide='data.tables.length == 0')
+ table.table-bordered.table-condensed.links-edit-small-padding.col-sm-12(st-table='data.tables')
+ thead
+ tr
+ th.col-sm-3 Schema/Table
+ th Key class
+ th Value class
+ tbody
+ tr(ng-repeat='row in data.tables')
+ td(colspan='{{row.tableName ? 1 : 3}}')
+ div.checkbox(ng-if='!row.tableName')
+ label(ng-click='selectSchema($index)')
+ input(type='checkbox' ng-checked='row.use')
+ | {{row.schemaName}}
+ div.checkbox(ng-if='row.tableName')
+ label(style='padding-left: 30px' ng-click='selectTable($index)')
+ input(type='checkbox' ng-checked = 'row.use')
+ | {{row.tableName}}
+ td(ng-if='row.tableName')
+ a(ng-show='data.curTableIdx != $index' ng-click='selectTable($index)') {{row.keyClass}}
+ input.form-control(type='text' ng-show='data.curTableIdx == $index' ng-model='data.curKeyClass' placeholder='Key class full name')
+ td(ng-if='row.tableName')
+ a(ng-show='data.curTableIdx != $index' ng-click='selectTable($index)') {{row.valueClass}}
+ input.form-control(type='text' ng-show='data.curTableIdx == $index' ng-model='data.curValueClass' placeholder='Value class full name')
+ //div(ng-hide='data.curTableIdx < 0')
+ // table.table-bordered.table-condensed.links-edit-small-padding.col-sm-12(st-table='data.tables[data.curTableIdx].fields')
+ // thead
+ // tr
+ // th(style='width:45px') Use
+ // th(style='width:45px') Key
+ // th(style='width:45px') Ak
+ // th DB Name
+ // th DB Type
+ // th Java Name
+ // th Java Type
+ // tbody
+ // tr(ng-repeat='row in data.tables[data.curTableIdx].fields')
+ // td
+ // +dbcheck('row.use')
+ // td
+ // +dbcheck('row.key')
+ // td
+ // +dbcheck('row.ak')
+ // td
+ // label {{row.dbName}}
+ // td
+ // label {{row.dbType}}
+ // td
+ // a(ng-show='data.curFieldIdx != $index' ng-click='selectField($index)') {{row.javaName}}
+ // input.form-control(type='text' ng-show='data.curFieldIdx == $index' ng-model='data.curJavaName' placeholder='Field Java name')
+ // td
+ // a(ng-show='data.curFieldIdx != $index' ng-click='selectField($index)') {{row.javaType}}
+ // input.form-control(type='text' ng-show='data.curFieldIdx == $index' ng-model='data.curJavaType' placeholder='Field Java type')
+ button.btn.btn-primary(ng-disabled='dbForm.$invalid' ng-click='saveItem()') Save
+ button.btn.btn-primary.btn-second(ng-show='backupItem._id' ng-click='removeItem()') Remove
+ button.btn.btn-primary.btn-second(ng-click='reloadMetadata()') Reload
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/configuration/sidebar.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/configuration/sidebar.jade b/modules/web-control-center/src/main/js/views/configuration/sidebar.jade
new file mode 100644
index 0000000..7289f3e
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/configuration/sidebar.jade
@@ -0,0 +1,39 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+extends ../templates/layout
+
+mixin sidebar-item(ref, num, txt)
+ li
+ a(ng-class='{active: isActive("#{ref}")}' href='#{ref}')
+ span.fa-stack
+ i.fa.fa-circle-thin.fa-stack-2x
+ i.fa.fa-stack-1x #{num}
+ | #{txt}
+
+block container
+ .row
+ .col-sm-2.border-right.section-left.greedy
+ .sidebar-nav(bs-affix)
+ ul.menu(ng-controller='activeLink')
+ +sidebar-item('/configuration/clusters', 1, 'Clusters')
+ +sidebar-item('/configuration/metadata', 2, 'Metadata')
+ +sidebar-item('/configuration/caches', 3, 'Caches')
+ +sidebar-item('/configuration/summary', 4, 'Summary')
+
+ .col-sm-10.border-left.section-right
+ .docs-content
+ block content
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/configuration/summary.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/configuration/summary.jade b/modules/web-control-center/src/main/js/views/configuration/summary.jade
new file mode 100644
index 0000000..6f2f6d8
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/configuration/summary.jade
@@ -0,0 +1,117 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+extends sidebar
+
+append scripts
+ script(src='/summary-controller.js')
+
+ script(src="//cdn.jsdelivr.net/angularjs/1.3.15/angular-animate.min.js")
+ script(src="//cdn.jsdelivr.net/angularjs/1.3.15/angular-sanitize.min.js")
+
+ script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/theme-chrome.js')
+ script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-xml.js')
+ script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-java.js')
+ script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-dockerfile.js')
+
+append css
+
+include ../includes/controls
+
+mixin hard-link(ref, txt)
+ a(style='color:#ec1c24' href=ref target="_blank") #{txt}
+
+block content
+ .docs-header
+ h1 Configurations Summary
+ hr
+ .docs-body(ng-controller='summaryController')
+ +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)')
+ .padding-dflt(ng-if='clusters.length == 0')
+ | No cluster configured. You can
+ a(href='clusters') configure
+ | it.
+ .padding-dflt(ng-if='clusters.length > 0')
+ lable.labelHeader Clusters:
+ .links
+ table(st-table='clusters')
+ tbody
+ tr(ng-repeat='row in clusters track by row._id')
+ td.col-sm-6(ng-class='{active: row._id == selectedItem._id}')
+ a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}
+ div(ng-show='selectedItem' role="tab" method='post' action='summary/download')
+ .padding-dflt(bs-collapse data-start-collapsed='false')
+ .panel.panel-default
+ form.panel-heading(role='tab' method='post' action='summary/download')
+ input(type="hidden" name="_id" value="{{selectedItem._id}}")
+ input(type="hidden" name="os" value="{{os}}")
+ input(type="hidden" name="javaClass" value="{{javaClassServer}}")
+ h3
+ a(bs-collapse-toggle) Server
+ button.btn.btn-primary.pull-right(type='submit' style='margin-top: -5px') Download
+ .panel-collapse(role="tabpanel" bs-collapse-target)
+ .panel-body
+ .configBox(ng-show='selectedItem' bs-tabs)
+ div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
+ .configBox(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlServer' style='margin: 0.65em 0;')
+ div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
+ .settings-row
+ .col-sm-1
+ label Generate:
+ .col-sm-3
+ button.form-control(type='button' ng-model='configServer.javaClassServer' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
+ .configBox(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaServer')
+ div(title='<img src="/images/docker.png" width="16px" height="16px"/> Dockerfile' bs-pane)
+ .settings-row
+ p
+ +hard-link('https://docs.docker.com/reference/builder', 'Docker')
+ | file is a text file with instructions to create Docker image.<br/>
+ | To build image you have to store following Docker file with your Ignite XML configuration to the same directory.<br>
+ | Also you could use predefined
+ +hard-link('https://ignite.incubator.apache.org/download.html#docker', 'Apache Ignite docker image')
+ | . For more information about using Ignite with Docker please read
+ +hard-link('http://apacheignite.readme.io/docs/docker-deployment', 'documentation')
+ |.
+ .col-sm-2
+ label(for='os') Operation System:
+ .col-sm-4
+ input#os.form-control(type='text', ng-model='configServer.os' placeholder='debian:8' data-min-length="0" data-html="1" data-auto-select="true" data-animation="am-flip-x" bs-typeahead bs-options='os for os in oss')
+ div(ui-ace='{ onLoad: aceInit, mode: "dockerfile" }' ng-model='dockerServer')
+ .padding-dflt(bs-collapse data-start-collapsed='false')
+ .panel.panel-default
+ form.panel-heading(role='tab' method='post' action='summary/download')
+ input(type="hidden" name="_id" value="{{selectedItem._id}}")
+ input(type="hidden" name="javaClass" value="{{javaClassClient}}")
+ input(type="hidden" name="clientNearConfiguration" value="{{backupItem}}")
+
+ h3
+ a(bs-collapse-toggle) Client
+ button.btn.btn-primary.pull-right(type='submit' style='margin-top: -5px') Download
+ .panel-collapse(role="tabpanel" bs-collapse-target)
+ .panel-body
+ div(ng-show='selectedItem')
+ .settings-row(ng-repeat='field in clientFields')
+ +form-row-custom(['col-sm-3'], ['col-sm-3'])
+ .configBox(bs-tabs)
+ div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane)
+ .configBox(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlClient' style='margin: 0.65em 0;')
+ div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane)
+ .settings-row
+ .col-sm-1
+ label Generate:
+ .col-sm-4
+ button.form-control(type='button' ng-model='backupItem.javaClassClient' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
+ div(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaClient')
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/error.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/error.jade b/modules/web-control-center/src/main/js/views/error.jade
new file mode 100644
index 0000000..b458fb7
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/error.jade
@@ -0,0 +1,22 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+extends templates/layout
+
+block container
+ h1= message
+ h2= error.status
+ pre #{error.stack}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/includes/controls.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/includes/controls.jade b/modules/web-control-center/src/main/js/views/includes/controls.jade
new file mode 100644
index 0000000..4a618fa
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/includes/controls.jade
@@ -0,0 +1,322 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+mixin block-callout(titleWorkflow, contentWorkflow, whatsNextWorkflow, whatsNextContent)
+ .block-callout-parent.block-callout-border.margin-bottom-dflt
+ .block-callout
+ i.fa.fa-check-square
+ label #{titleWorkflow}
+ p(ng-bind-html=contentWorkflow)
+ .block-callout
+ i.fa.fa-check-square
+ label #{whatsNextWorkflow}
+ p(ng-bind-html=whatsNextContent)
+
+
+mixin tipField(lines)
+ i.tipField.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')
+ i.tipField.fa.fa-question-circle.blank(ng-if='!#{lines}')
+
+mixin tipLabel(lines)
+ i.tipLabel.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')
+ i.tipLabel.fa.fa-question-circle.blank(ng-if='!#{lines}')
+
+mixin ico-exclamation(mdl, err, msg)
+ i.fa.fa-exclamation-triangle.form-control-feedback(ng-show='inputForm["#{mdl}"].$error.#{err}' bs-tooltip data-title='#{msg}' type='button')
+
+mixin btn-save(show, click)
+ i.tipField.fa.fa-floppy-o(ng-show=show ng-click=click)
+
+mixin btn-add(click)
+ i.tipField.fa.fa-plus(ng-click=click)
+
+mixin btn-remove(click)
+ i.tipField.fa.fa-remove(ng-click=click)
+
+mixin btn-up(show, click)
+ i.tipField.fa.fa-arrow-up(ng-show=show ng-click=click)
+
+mixin btn-down(show, click)
+ i.tipField.fa.fa-arrow-down(ng-show=show ng-click=click)
+
+mixin table-pair-edit(keyModel, valModel, keyPlaceholder, valPlaceholder)
+ .col-sm-6(style='float: right')
+ input.form-control(type='text' ng-model=valModel placeholder=valPlaceholder)
+ label.fieldSep /
+ .input-tip
+ input.form-control(type='text' ng-model=keyModel placeholder=keyPlaceholder)
+
+mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
+ .col-sm-6
+ label.table-header #{header}:
+ +tipLabel('field.tip')
+ button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
+ table.links-edit.col-sm-12(st-table=tblMdl)
+ tbody
+ tr.col-sm-12(ng-repeat='item in #{tblMdl}')
+ td.col-sm-6
+ div(ng-show='!tableEditing(field, $index)')
+ a.labelFormField(ng-click='curPair = tableStartEdit(backupItem, field, $index); curKey = curPair.#{keyFld}; curValue = curPair.#{valFld}') {{$index + 1}}) {{item.#{keyFld}}} / {{item.#{valFld}}}
+ +btn-remove('tableRemove(backupItem, field, $index)')
+ div(ng-show='tableEditing(field, $index)')
+ label.labelField {{$index + 1}})
+ +btn-save('tablePairSaveVisible(curKey, curValue)', 'tablePairSave(tablePairValid, backupItem, field, curKey, curValue, $index)')
+ +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder)
+ tr.col-sm-12(ng-show='tableNewItemActive(field)')
+ td.col-sm-6
+ +btn-save('tablePairSaveVisible(newKey, newValue)', 'tablePairSave(tablePairValid, backupItem, field, newKey, newValue, -1)')
+ +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder)
+
+mixin details-row
+ - var lblDetailClasses = ['col-sm-4', 'details-label']
+
+ - var detailMdl = 'getModel(backupItem, detail)[detail.model]';
+ - var detailCommon = {'ng-model': detailMdl, 'ng-required': 'detail.required'};
+
+ - var customValidators = {'ng-attr-ipaddress': '{{detail.ipaddress}}'}
+
+ div(ng-switch='detail.type')
+ div(ng-switch-when='label')
+ label {{detail.label}}
+ div.checkbox(ng-switch-when='check')
+ label
+ input(type='checkbox')&attributes(detailCommon)
+ |{{detail.label}}
+ +tipLabel('detail.tip')
+ div(ng-switch-when='text')
+ label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
+ .col-sm-8
+ +tipField('detail.tip')
+ .input-tip
+ input.form-control(type='text' placeholder='{{detail.placeholder}}')&attributes(detailCommon)
+ div(ng-switch-when='number' )
+ label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
+ .col-sm-8
+ +tipField('detail.tip')
+ .input-tip
+ input.form-control(name='{{detail.model}}' type='number' placeholder='{{detail.placeholder}}' min='{{detail.min ? detail.min : 0}}' max='{{detail.max ? detail.max : Number.MAX_VALUE}}')&attributes(detailCommon)
+ +ico-exclamation('{{detail.model}}', 'min', 'Value is less than allowable minimum.')
+ +ico-exclamation('{{detail.model}}', 'max', 'Value is more than allowable maximum.')
+ +ico-exclamation('{{detail.model}}', 'number', 'Invalid value. Only numbers allowed.')
+ div(ng-switch-when='dropdown')
+ label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
+ .col-sm-8
+ +tipField('detail.tip')
+ .input-tip
+ button.form-control(bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in {{detail.items}}')&attributes(detailCommon)
+ div(ng-switch-when='dropdown-multiple')
+ label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
+ .col-sm-8
+ button.form-control(bs-select data-multiple='1' data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in {{detail.items}}')&attributes(detailCommon)
+ +tipField('detail.tip')
+ div(ng-switch-when='table-simple')&attributes(detailCommon)
+ div(ng-if='detail.label')
+ label.table-header {{detail.label}}:
+ +tipLabel('detail.tableTip')
+ table.col-sm-12.links-edit-details(st-table='#{detailMdl}')
+ tbody
+ tr(ng-repeat='item in #{detailMdl} track by $index')
+ td
+ div(ng-show='!tableEditing(detail, $index)')
+ a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, detail, $index)') {{$index + 1}}) {{item}}
+ +btn-remove('tableRemove(backupItem, detail, $index)')
+ +btn-down('detail.reordering && tableSimpleDownVisible(backupItem, detail, $index)', 'tableSimpleDown(backupItem, detail, $index)')
+ +btn-up('detail.reordering && $index > 0', 'tableSimpleUp(backupItem, detail, $index)')
+ div(ng-show='tableEditing(detail, $index)')
+ label.labelField {{$index + 1}})
+ +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, detail, curValue, $index)')
+ .input-tip.form-group.has-feedback
+ input.form-control(name='{{detail.model}}.edit' type='text' ng-model='curValue' placeholder='{{detail.placeholder}}')&attributes(customValidators)
+ +ico-exclamation('{{detail.model}}.edit', 'ipaddress', 'Invalid address, see help for format description.')
+ button.btn.btn-primary.fieldButton(ng-disabled='!newValue' ng-click='tableSimpleSave(tableSimpleValid, backupItem, detail, newValue, -1)') Add
+ +tipField('detail.tip')
+ .input-tip.form-group.has-feedback
+ input.form-control(name='{{detail.model}}' type='text' ng-model='newValue' ng-focus='tableNewItem(detail)' placeholder='{{detail.placeholder}}')&attributes(customValidators)
+ +ico-exclamation('{{detail.model}}', 'ipaddress', 'Invalid address, see help for format description.')
+
+mixin table-db-field-edit(dbName, dbType, javaName, javaType)
+ div(style='width: 22%; float: right')
+ button.form-control(ng-model=javaType bs-select data-placeholder='Java type' bs-options='item.value as item.label for item in {{javaTypes}}')
+ label.fieldSep /
+ div(style='width: 20%; float: right')
+ input.form-control(type='text' ng-model=javaName placeholder='Java name')
+ label.fieldSep /
+ div(style='width: 22%; float: right')
+ button.form-control(ng-model=dbType bs-select data-placeholder='JDBC type' bs-options='item.value as item.label for item in {{jdbcTypes}}')
+ label.fieldSep /
+ .input-tip
+ input.form-control(type='text' ng-model=dbName placeholder='DB name')
+
+mixin table-group-item-edit(fieldName, className, direction)
+ div(style='width: 15%; float: right')
+ button.form-control(ng-model=direction bs-select data-placeholder='Sort' bs-options='item.value as item.label for item in {{sortDirections}}')
+ label.fieldSep /
+ div(style='width: 38%; float: right')
+ input.form-control(type='text' ng-model=className placeholder='Class name')
+ label.fieldSep /
+ .input-tip
+ input.form-control(type='text' ng-model=fieldName placeholder='Field name')
+
+mixin form-row
+ +form-row-custom(['col-sm-2'], ['col-sm-4'])
+
+mixin form-row-custom(lblClasses, fieldClasses)
+ - var fieldMdl = 'getModel(backupItem, field)[field.model]';
+ - var fieldCommon = {'ng-model': fieldMdl, 'ng-required': 'field.required || required(field)'};
+ - var fieldRequiredClass = '{true: "required"}[field.required || required(field)]'
+ - var fieldHide = '{{field.hide}}'
+
+ div(ng-switch='field.type')
+ div.col-sm-6(ng-switch-when='label')
+ label {{field.label}}
+ div.checkbox.col-sm-6(ng-switch-when='check' ng-hide=fieldHide)
+ label
+ input(type='checkbox')&attributes(fieldCommon)
+ | {{field.label}}
+ +tipLabel('field.tip')
+ div(ng-switch-when='text' ng-hide=fieldHide)
+ label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
+ div(class=fieldClasses)
+ +tipField('field.tip')
+ .input-tip
+ input.form-control(type='text' placeholder='{{field.placeholder}}')&attributes(fieldCommon)
+ div(ng-switch-when='password' ng-hide=fieldHide)
+ label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
+ div(class=fieldClasses)
+ +tipField('field.tip')
+ .input-tip
+ input.form-control(type='password' placeholder='{{field.placeholder}}')&attributes(fieldCommon)
+ div(ng-switch-when='number' ng-hide=fieldHide)
+ label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
+ div(class=fieldClasses)
+ +tipField('field.tip')
+ .input-tip
+ input.form-control(name='{{field.model}}' type='number' placeholder='{{field.placeholder}}' min='{{field.min ? field.min : 0}}' max='{{field.max ? field.max : Number.MAX_VALUE}}')&attributes(fieldCommon)
+ +ico-exclamation('{{field.model}}', 'min', 'Value is less than allowable minimum.')
+ +ico-exclamation('{{field.model}}', 'max', 'Value is more than allowable maximum.')
+ +ico-exclamation('{{field.model}}', 'number', 'Invalid value. Only numbers allowed.')
+ div(ng-switch-when='dropdown' ng-hide=fieldHide)
+ label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
+ div(class=fieldClasses)
+ +tipField('field.tip')
+ .input-tip
+ button.form-control(bs-select data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label for item in {{field.items}}')&attributes(fieldCommon)
+ div(ng-switch-when='dropdown-multiple' ng-hide=fieldHide)
+ label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
+ div(class=fieldClasses)
+ +tipField('field.tip')
+ .input-tip
+ button.form-control(bs-select ng-disabled='{{field.items}}.length == 0' data-multiple='1' data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label for item in {{field.items}}')&attributes(fieldCommon)
+ a.customize(ng-show='field.addLink' ng-href='{{field.addLink.ref}}') {{field.addLink.label}}
+ div(ng-switch-when='dropdown-details' ng-hide=fieldHide)
+ - var expanded = 'field.details[' + fieldMdl + '].expanded'
+
+ label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
+ div(class=fieldClasses)
+ +tipField('field.tip')
+ .input-tip
+ button.form-control(bs-select data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label for item in {{field.items}}')&attributes(fieldCommon)
+ a.customize(ng-show='#{fieldMdl} && field.details[#{fieldMdl}].fields' ng-click='#{expanded} = !#{expanded}') {{#{expanded} ? "Hide settings" : "Show settings"}}
+ .col-sm-6.panel-details(ng-show='#{expanded} && #{fieldMdl}')
+ .details-row(ng-repeat='detail in field.details[#{fieldMdl}].fields')
+ +details-row
+ div(ng-switch-when='table-simple' ng-hide=fieldHide)&attributes(fieldCommon)
+ .col-sm-6
+ label.table-header {{field.label}}:
+ +tipLabel('field.tableTip')
+ button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
+ table.links-edit.col-sm-12(st-table='#{fieldMdl}')
+ tbody
+ tr.col-sm-12(ng-repeat='item in #{fieldMdl} track by $index')
+ td.col-sm-6
+ div(ng-show='!tableEditing(field, $index)')
+ a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, field, $index)') {{$index + 1}}) {{item | compact}}
+ +btn-remove('tableRemove(backupItem, field, $index)')
+ +btn-down('field.reordering && tableSimpleDownVisible(backupItem, field, $index)', 'tableSimpleDown(backupItem, field, $index)')
+ +btn-up('field.reordering && $index > 0', 'tableSimpleUp(backupItem, field, $index)')
+ div(ng-show='tableEditing(field, $index)')
+ label.labelField {{$index + 1}})
+ +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, curValue, $index)')
+ .input-tip
+ input.form-control(type='text' ng-model='curValue' placeholder='{{field.placeholder}}')
+ tr.col-sm-12(ng-show='tableNewItemActive(field)')
+ td.col-sm-6
+ +btn-save('tableSimpleSaveVisible(newValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)')
+ .input-tip
+ input.form-control(type='text' ng-model='newValue' placeholder='{{field.placeholder}}')
+ div(ng-switch-when='indexedTypes')
+ +table-pair('Index key-value type pairs', fieldMdl, 'keyClass', 'valueClass', 'Key class full name', 'Value class full name')
+ div(ng-switch-when='queryFields' ng-hide=fieldHide)
+ +table-pair('{{field.label}}', fieldMdl, 'name', 'className', 'Field name', 'Field class full name')
+ div(ng-switch-when='dbFields' ng-hide=fieldHide)
+ .col-sm-6
+ label.table-header {{field.label}}:
+ +tipLabel('field.tip')
+ button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
+ table.links-edit.col-sm-12(st-table=fieldMdl)
+ tbody
+ tr.col-sm-12(ng-repeat='item in #{fieldMdl}')
+ td.col-sm-6
+ div(ng-show='!tableEditing(field, $index)')
+ a.labelFormField(ng-click='curField = tableStartEdit(backupItem, field, $index); curDbName = curField.dbName; curDbType = curField.dbType; curJavaName = curField.javaName; curJavaType = curField.javaType') {{$index + 1}}) {{item.dbName}} / {{item.dbType}} / {{item.javaName}} / {{item.javaType}}
+ +btn-remove('tableRemove(backupItem, field, $index)')
+ div(ng-if='tableEditing(field, $index)')
+ label.labelField {{$index + 1}})
+ +btn-save('tableDbFieldSaveVisible(curDbName, curDbType, curJavaName, curJavaType)', 'tableDbFieldSave(field, curDbName, curDbType, curJavaName, curJavaType, $index)')
+ +table-db-field-edit('curDbName', 'curDbType', 'curJavaName', 'curJavaType')
+ tr(ng-show='tableNewItemActive(field)')
+ td.col-sm-6
+ +btn-save('tableDbFieldSaveVisible(newDbName, newDbType, newJavaName, newJavaType)', 'tableDbFieldSave(field, newDbName, newDbType, newJavaName, newJavaType, -1)')
+ +table-db-field-edit('newDbName', 'newDbType', 'newJavaName', 'newJavaType')
+ div(ng-switch-when='queryGroups' ng-hide=fieldHide)
+ .col-sm-6
+ label.table-header {{field.label}}:
+ +tipLabel('field.tip')
+ button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
+ table.links-edit.col-sm-12(st-table=fieldMdl)
+ tbody
+ tr.col-sm-12(ng-repeat='group in #{fieldMdl}')
+ td.col-sm-6
+ div
+ .col-sm-12(ng-show='!tableEditing(field, $index)')
+ a.labelFormField(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curGroupName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{group.name}}
+ +btn-remove('tableRemove(backupItem, field, $index)')
+ +btn-add('tableGroupNewItem($index); newDirection = "ASC"')
+ div(ng-show='tableEditing(field, $index)')
+ label.labelField {{$index + 1}})
+ +btn-save('tableGroupSaveVisible(curGroupName)', 'tableGroupSave(curGroupName, $index)')
+ .input-tip
+ input.form-control(type='text' ng-model='curGroupName' placeholder='Index name')
+ div
+ table.links-edit.col-sm-12(st-table='group.fields' ng-init='groupIndex = $index')
+ tr(ng-repeat='groupItem in group.fields')
+ td
+ div(ng-show='!tableGroupItemEditing(groupIndex, $index)')
+ a.labelFormField(ng-click='curGroupItem = tableGroupItemStartEdit(groupIndex, $index); curFieldName = curGroupItem.name; curClassName = curGroupItem.className; curDirection = curGroupItem.direction') {{$index + 1}}) {{groupItem.name}} / {{groupItem.className}} / {{groupItem.direction}}
+ +btn-remove('tableRemoveGroupItem(group, $index)')
+ div(ng-show='tableGroupItemEditing(groupIndex, $index)')
+ label.labelField {{$index + 1}})
+ +btn-save('tableGroupItemSaveVisible(curFieldName, curClassName)', 'tableGroupItemSave(curFieldName, curClassName, curDirection, groupIndex, $index)')
+ +table-group-item-edit('curFieldName', 'curClassName', 'curDirection')
+ tr.col-sm-12(style='padding-left: 18px' ng-show='tableGroupNewItemActive(groupIndex)')
+ td
+ +btn-save('tableGroupItemSaveVisible(newFieldName, newClassName)', 'tableGroupItemSave(newFieldName, newClassName, newDirection, groupIndex, -1)')
+ +table-group-item-edit('newFieldName', 'newClassName', 'newDirection')
+ tr.col-sm-12(ng-show='tableNewItemActive(field)')
+ td.col-sm-6
+ +btn-save('tableGroupSaveVisible(newGroupName)', 'tableGroupSave(newGroupName, -1)')
+ .input-tip
+ input.form-control(type='text' ng-model='newGroupName' placeholder='Group name')
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/includes/footer.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/includes/footer.jade b/modules/web-control-center/src/main/js/views/includes/footer.jade
new file mode 100644
index 0000000..d8ff5d7
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/includes/footer.jade
@@ -0,0 +1,22 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+.container.container-footer
+ footer
+ center
+ p Apache Ignite Control Center, version 1.0.0
+ p © 2015 The Apache Software Foundation.
+ p Apache, Apache Ignite, the Apache feather and the Apache Ignite logo are trademarks of The Apache Software Foundation.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/includes/header.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/includes/header.jade b/modules/web-control-center/src/main/js/views/includes/header.jade
new file mode 100644
index 0000000..ab2d31e
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/includes/header.jade
@@ -0,0 +1,39 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+mixin header-item(active, ref, txt)
+ li
+ a(ng-class='{active: isActive("#{active}")}' href='#{ref}') #{txt}
+
+header.header(id='header')
+ .viewedUser(ng-show='becomeUsed') Currently assuming "
+ strong {{user.username}}
+ | ",
+ a(href='/admin/become') revert to your identity.
+ .container
+ h1.navbar-brand
+ a(href='/') Apache Ignite Web Configurator
+ .navbar-collapse.collapse(ng-controller='auth')
+ ul.nav.navbar-nav(ng-controller='activeLink' ng-show='user')
+ +header-item('/configuration', '/configuration/clusters', 'Configuration')
+ //+header-item('/monitoring', '/monitoring', 'Monitoring')
+ //+header-item('/sql', '/sql', 'SQL')
+ //+header-item('/deploy', '/deploy', 'Deploy')
+ ul.nav.navbar-nav.pull-right
+ li(ng-if='user')
+ a.dropdown-toggle(data-toggle='dropdown' bs-dropdown='userDropdown' data-placement='bottom-right') {{user.username}}
+ span.caret
+ li.nav-login(ng-if='!user')
+ a(ng-click='login()' href='#') Log In
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/index.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/index.jade b/modules/web-control-center/src/main/js/views/index.jade
new file mode 100644
index 0000000..999c4f8
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/index.jade
@@ -0,0 +1,30 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+extends templates/layout
+
+block container
+ .row
+ .docs-content
+ div
+ p
+ | Apache Ignite<sup>tm</sup> In-Memory Data Fabric is a high-performance,
+ | integrated and distributed in-memory platform for computing and transacting on large-scale data
+ | sets in real-time, orders of magnitude faster than possible with traditional disk-based or flash technologies.
+ .block-image.block-display-image
+ img(ng-src='https://www.filepicker.io/api/file/lydEeGB6Rs9hwbpcQxiw' alt='Apache Ignite stack')
+ .text-center(ng-controller='auth')
+ button.btn.btn-primary(ng-click='login()' href='#') Configure Now
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/login.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/login.jade b/modules/web-control-center/src/main/js/views/login.jade
new file mode 100644
index 0000000..5bb39dd
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/login.jade
@@ -0,0 +1,55 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+mixin lbl(txt)
+ label.col-sm-3.required #{txt}
+
+.modal.center(role='dialog')
+ .modal-dialog
+ .modal-content
+ .modal-header.header
+ div(id='errors-container')
+ button.close(type='button', ng-click='$hide()', aria-hidden='true') ×
+ h1.navbar-brand
+ a(href='/') Apache Ignite Web Configurator
+ h4.modal-title(style='padding-right: 55px') Authentication
+ p(style='padding-right: 55px') Log in or register in order to collaborate
+ form.form-horizontal(name='loginForm')
+ .modal-body.row
+ .col-sm-9.login.col-sm-offset-1
+ .details-row(ng-show='action == "register"')
+ +lbl('Full Name:')
+ .col-sm-9
+ input.form-control(type='text', ng-model='user_info.username', placeholder='John Smith', focus-me='action=="register"', ng-required='action=="register"')
+ .details-row
+ +lbl('Email:')
+ .col-sm-9
+ input.form-control(type='email', ng-model='user_info.email', placeholder='you@domain.com', focus-me='action=="login"', required)
+ .details-row
+ +lbl('Password:')
+ .col-sm-9
+ input.form-control(type='password', ng-model='user_info.password', placeholder='Password', required, ng-keyup='action == "login" && $event.keyCode == 13 ? auth(action, user_info) : null')
+ .details-row(ng-show='action == "register"')
+ +lbl('Confirm:')
+ .col-sm-9.input-tip.has-feedback
+ input.form-control(type='password', ng-model='user_info.confirm', match="user_info.password" placeholder='Confirm password', required, ng-keyup='$event.keyCode == 13 ? auth(action, user_info) : null')
+
+ .modal-footer
+ a.show-signup.ng-hide(ng-show='action != "login"', ng-click='action = "login";') log in
+ a.show-signup(ng-show="action != 'register'", ng-click='action = "register";') sign up
+ | or
+ button.btn.btn-primary(ng-show='action == "login"' ng-click='auth(action, user_info)') Log In
+ button.btn.btn-primary(ng-show='action == "register"' ng-disabled='loginForm.$invalid || user_info.password != user_info.confirm' ng-click='auth(action, user_info)') Sign Up
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/settings/admin.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/settings/admin.jade b/modules/web-control-center/src/main/js/views/settings/admin.jade
new file mode 100644
index 0000000..4d50631
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/settings/admin.jade
@@ -0,0 +1,58 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+extends ../templates/layout
+
+append scripts
+ script(src='/admin-controller.js')
+
+block container
+ .row(ng-controller='adminController')
+ .docs-content
+ .docs-header
+ h1 List of registered users
+ hr
+ .docs-body
+ table.table.table-striped.admin(st-table='displayedUsers' st-safe-src='users')
+ thead
+ tr
+ th.header(colspan='5')
+ .col-sm-2.pull-right
+ input.form-control(type='text' st-search='' placeholder='Filter users...')
+ tr
+ th(st-sort='username') User name
+ th(st-sort='email') Email
+ th.col-sm-2(st-sort='lastLogin') Last login
+ th(width='1%' st-sort='admin') Admin
+ th(width='1%') Actions
+ tbody
+ tr(ng-repeat='row in displayedUsers')
+ td {{row.username}}
+ td
+ a(ng-href='mailto:{{row.email}}') {{row.email}}
+ td
+ span {{row.lastLogin | date:'medium'}}
+ td(style='text-align: center;')
+ input(type='checkbox' ng-disabled='row.adminChanging || row._id == user._id'
+ ng-model='row.admin' ng-change='toggleAdmin(row)')
+ td(style='text-align: center;')
+ a(ng-click='removeUser(row)' ng-show='row._id != user._id' bs-tooltip data-title='Remove user')
+ i.fa.fa-remove
+ a(style='margin-left: 5px' ng-href='admin/become?viewedUserId={{row._id}}' ng-show='row._id != user._id' bs-tooltip data-title='Become this user')
+ i.fa.fa-eye
+ tfoot
+ tr
+ td(colspan='5' class="text-right")
+ div(st-pagination st-items-by-page='15' st-displayed-pages='5')
+
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/settings/profile.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/settings/profile.jade b/modules/web-control-center/src/main/js/views/settings/profile.jade
new file mode 100644
index 0000000..dbc6dea
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/settings/profile.jade
@@ -0,0 +1,58 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+extends ../templates/layout
+
+mixin lbl(txt)
+ label.col-sm-2.required.labelFormField #{txt}
+
+append scripts
+ script(src='/profile-controller.js')
+
+block container
+ .row(ng-controller='profileController')
+ .docs-content
+ .docs-header
+ h1 User profile
+ hr
+ .docs-body
+ form.form-horizontal(name='profileForm' novalidate)
+ .col-sm-10(style='padding: 0')
+ .details-row
+ +lbl('User name:')
+ .col-sm-4
+ input.form-control(type='text' ng-model='profileUser.username' placeholder='Input name' required)
+ .details-row
+ +lbl('Email:')
+ .col-sm-4
+ input.form-control(type='email' ng-model='profileUser.email' placeholder='you@domain.com' required)
+ .details-row
+ .checkbox
+ label
+ input(type="checkbox" ng-model='profileUser.changePassword')
+ | Change password
+ div(ng-show='profileUser.changePassword')
+ .details-row
+ +lbl('New password:')
+ .col-sm-4
+ input.form-control(type='password', ng-model='profileUser.newPassword' placeholder='New password' ng-required='profileUser.changePassword')
+ .details-row
+ +lbl('Confirm:')
+ .col-sm-4
+ input.form-control(type='password', ng-model='profileUser.confirmPassword' match='profileUser.newPassword' placeholder='Confirm new password' ng-required='profileUser.changePassword')
+ .col-sm-12.details-row
+ button.btn.btn-primary(ng-disabled='profileForm.$invalid' ng-click='saveUser()') Save
+
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/views/templates/confirm.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/views/templates/confirm.jade b/modules/web-control-center/src/main/js/views/templates/confirm.jade
new file mode 100644
index 0000000..bdaf9bf
--- /dev/null
+++ b/modules/web-control-center/src/main/js/views/templates/confirm.jade
@@ -0,0 +1,27 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+.modal(tabindex='-1' role='dialog')
+ .modal-dialog
+ .modal-content
+ .modal-header
+ button.close(type="button" ng-click="$hide()") ×
+ h4.modal-title Confirmation
+ .modal-body(ng-show='content')
+ p(ng-bind-html='content' style='text-align: center;')
+ .modal-footer
+ button.btn.btn-default(type="button" ng-click="$hide()") Cancel
+ button.btn.btn-primary(type="button" ng-click="ok()") Confirm
\ No newline at end of file