You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by av...@apache.org on 2016/05/18 09:21:05 UTC
[02/28] ignite git commit: IGNITE-843 Implemented Web Console.
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/serve/routes/public.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/serve/routes/public.js b/modules/web-console/src/main/js/serve/routes/public.js
new file mode 100644
index 0000000..0009e6a
--- /dev/null
+++ b/modules/web-console/src/main/js/serve/routes/public.js
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+// Fire me up!
+
+module.exports = {
+ implements: 'public-routes',
+ inject: ['require(express)', 'require(passport)', 'require(nodemailer)', 'settings', 'mail', 'mongo']
+};
+
+module.exports.factory = function(express, passport, nodemailer, settings, mail, mongo) {
+ return new Promise((factoryResolve) => {
+ const router = new express.Router();
+
+ const _randomString = () => {
+ const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ const possibleLen = possible.length;
+
+ let res = '';
+
+ for (let i = 0; i < settings.tokenLength; i++)
+ res += possible.charAt(Math.floor(Math.random() * possibleLen));
+
+ return res;
+ };
+
+ // GET user.
+ router.post('/user', (req, res) => {
+ const becomeUsed = req.session.viewedUser && req.user.admin;
+
+ let user = req.user;
+
+ if (becomeUsed) {
+ user = req.session.viewedUser;
+
+ user.becomeUsed = true;
+ }
+ else if (user)
+ user = user.toJSON();
+ else
+ return res.json(user);
+
+ mongo.Space.findOne({owner: user._id, demo: true}).exec()
+ .then((demoSpace) => {
+ if (user && demoSpace)
+ user.demoCreated = true;
+
+ res.json(user);
+ })
+ .catch((err) => {
+ res.status(401).send(err.message);
+ });
+ });
+
+ /**
+ * Register new account.
+ */
+ router.post('/signup', (req, res) => {
+ mongo.Account.count().exec()
+ .then((cnt) => {
+ req.body.admin = cnt === 0;
+
+ req.body.token = _randomString();
+
+ return new mongo.Account(req.body);
+ })
+ .then((account) => {
+ return new Promise((resolve, reject) => {
+ mongo.Account.register(account, req.body.password, (err, _account) => {
+ if (err)
+ reject(err);
+
+ if (!_account)
+ reject(new Error('Failed to create account.'));
+
+ resolve(_account);
+ });
+ });
+ })
+ .then((account) => new mongo.Space({name: 'Personal space', owner: account._id}).save()
+ .then(() => account)
+ )
+ .then((account) => {
+ return new Promise((resolve, reject) => {
+ req.logIn(account, {}, (err) => {
+ if (err)
+ reject(err);
+
+ resolve(account);
+ });
+ });
+ })
+ .then((account) => {
+ res.sendStatus(200);
+
+ account.resetPasswordToken = _randomString();
+
+ return account.save()
+ .then(() => mail.send(account, `Thanks for signing up for ${settings.smtp.username}.`,
+ `Hello ${account.firstName} ${account.lastName}!<br><br>` +
+ `You are receiving this email because you have signed up to use <a href="http://${req.headers.host}">${settings.smtp.username}</a>.<br><br>` +
+ 'If you have not done the sign up and do not know what this email is about, please ignore it.<br>' +
+ 'You may reset the password by clicking on the following link, or paste this into your browser:<br><br>' +
+ `http://${req.headers.host}/password/reset?token=${account.resetPasswordToken}`));
+ })
+ .catch((err) => {
+ res.status(401).send(err.message);
+ });
+ });
+
+ /**
+ * Sign in into exist account.
+ */
+ router.post('/signin', (req, res, next) => {
+ passport.authenticate('local', (errAuth, user) => {
+ if (errAuth)
+ return res.status(401).send(errAuth.message);
+
+ if (!user)
+ return res.status(401).send('Invalid email or password');
+
+ req.logIn(user, {}, (errLogIn) => {
+ if (errLogIn)
+ return res.status(401).send(errLogIn.message);
+
+ return res.sendStatus(200);
+ });
+ })(req, res, next);
+ });
+
+ /**
+ * Logout.
+ */
+ router.post('/logout', (req, res) => {
+ req.logout();
+
+ res.sendStatus(200);
+ });
+
+ /**
+ * Send e-mail to user with reset token.
+ */
+ router.post('/password/forgot', (req, res) => {
+ mongo.Account.findOne({email: req.body.email}).exec()
+ .then((user) => {
+ if (!user)
+ throw new Error('Account with that email address does not exists!');
+
+ user.resetPasswordToken = _randomString();
+
+ return user.save();
+ })
+ .then((user) => mail.send(user, 'Password Reset',
+ `Hello ${user.firstName} ${user.lastName}!<br><br>` +
+ 'You are receiving this because you (or someone else) have requested the reset of the password for your account.<br><br>' +
+ 'Please click on the following link, or paste this into your browser to complete the process:<br><br>' +
+ 'http://' + req.headers.host + '/password/reset?token=' + user.resetPasswordToken + '<br><br>' +
+ 'If you did not request this, please ignore this email and your password will remain unchanged.',
+ 'Failed to send email with reset link!')
+ )
+ .then(() => res.status(200).send('An email has been sent with further instructions.'))
+ .catch((err) => {
+ // TODO IGNITE-843 Send email to admin
+ return res.status(401).send(err.message);
+ });
+ });
+
+ /**
+ * Change password with given token.
+ */
+ router.post('/password/reset', (req, res) => {
+ mongo.Account.findOne({resetPasswordToken: req.body.token}).exec()
+ .then((user) => {
+ if (!user)
+ throw new Error('Failed to find account with this token! Please check link from email.');
+
+ return new Promise((resolve, reject) => {
+ user.setPassword(req.body.password, (err, _user) => {
+ if (err)
+ return reject(new Error('Failed to reset password: ' + err.message));
+
+ _user.resetPasswordToken = undefined; // eslint-disable-line no-undefined
+
+ resolve(_user.save());
+ });
+ });
+ })
+ .then((user) => mail.send(user, 'Your password has been changed',
+ `Hello ${user.firstName} ${user.lastName}!<br><br>` +
+ `This is a confirmation that the password for your account on <a href="http://${req.headers.host}">${settings.smtp.username}</a> has just been changed.<br><br>`,
+ 'Password was changed, but failed to send confirmation email!'))
+ .then((user) => res.status(200).send(user.email))
+ .catch((err) => res.status(401).send(err.message));
+ });
+
+ /* GET reset password page. */
+ router.post('/password/validate/token', (req, res) => {
+ const token = req.body.token;
+
+ mongo.Account.findOne({resetPasswordToken: token}).exec()
+ .then((user) => {
+ if (!user)
+ throw new Error('Invalid token for password reset!');
+
+ return res.json({token, email: user.email});
+ })
+ .catch((err) => res.status(401).send(err.message));
+ });
+
+ factoryResolve(router);
+ });
+};
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/serve/routes/routes.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/serve/routes/routes.js b/modules/web-console/src/main/js/serve/routes/routes.js
new file mode 100644
index 0000000..cbee8bb
--- /dev/null
+++ b/modules/web-console/src/main/js/serve/routes/routes.js
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+// Fire me up!
+
+module.exports = {
+ implements: 'routes',
+ inject: [
+ 'public-routes',
+ 'admin-routes',
+ 'profile-routes',
+ 'demo-routes',
+ 'clusters-routes',
+ 'domains-routes',
+ 'caches-routes',
+ 'igfs-routes',
+ 'notebooks-routes',
+ 'agent-routes',
+ 'ignite_modules/routes:*' // Loads all routes modules of all plugins
+ ]
+};
+
+module.exports.factory = function(publicRoutes, adminRoutes, profileRoutes, demoRoutes,
+ clusterRoutes, domainRoutes, cacheRoutes, igfsRoutes, notebookRoutes, agentRoutes, pluginRoutes) {
+ return {
+ register: (app) => {
+ app.all('*', (req, res, next) => {
+ req.currentUserId = () => {
+ if (!req.user)
+ return null;
+
+ if (req.session.viewedUser && req.user.admin)
+ return req.session.viewedUser._id;
+
+ return req.user._id;
+ };
+
+ next();
+ });
+
+ const _mustAuthenticated = (req, res, next) => req.isAuthenticated() ? next() : res.redirect('/');
+
+ const _adminOnly = (req, res, next) => req.isAuthenticated() && req.user.admin ? next() : res.sendStatus(403);
+
+ // Registering the standard routes
+ app.use('/', publicRoutes);
+ app.use('/admin', _mustAuthenticated, _adminOnly, adminRoutes);
+ app.use('/profile', _mustAuthenticated, profileRoutes);
+ app.use('/demo', _mustAuthenticated, demoRoutes);
+
+ app.all('/configuration/*', _mustAuthenticated);
+
+ app.use('/configuration/clusters', clusterRoutes);
+ app.use('/configuration/domains', domainRoutes);
+ app.use('/configuration/caches', cacheRoutes);
+ app.use('/configuration/igfs', igfsRoutes);
+
+ app.use('/notebooks', _mustAuthenticated, notebookRoutes);
+ app.use('/agent', _mustAuthenticated, agentRoutes);
+
+ // Registering the routes of all plugin modules
+ for (const name in pluginRoutes) {
+ if (pluginRoutes.hasOwnProperty(name))
+ pluginRoutes[name].register(app, _mustAuthenticated, _adminOnly);
+ }
+
+ // Catch 404 and forward to error handler.
+ app.use((req, res, next) => {
+ const err = new Error('Not Found: ' + req.originalUrl);
+
+ err.status = 404;
+
+ next(err);
+ });
+
+ // Production error handler: no stacktraces leaked to user.
+ app.use((err, req, res) => {
+ res.status(err.status || 500);
+
+ res.render('error', {
+ message: err.message,
+ error: {}
+ });
+ });
+ }
+ };
+};
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/serve/settings.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/serve/settings.js b/modules/web-console/src/main/js/serve/settings.js
new file mode 100644
index 0000000..5b14bcc
--- /dev/null
+++ b/modules/web-console/src/main/js/serve/settings.js
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+// Fire me up!
+
+/**
+ * Module with server-side configuration.
+ */
+module.exports = {
+ implements: 'settings',
+ inject: ['require(nconf)', 'require(fs)']
+};
+
+module.exports.factory = function(nconf, fs) {
+ nconf.file({file: './serve/config/settings.json'});
+
+ /**
+ * Normalize a port into a number, string, or false.
+ */
+ const _normalizePort = function(val) {
+ const port = parseInt(val, 10);
+
+ // named pipe
+ if (isNaN(port))
+ return val;
+
+ // port number
+ if (port >= 0)
+ return port;
+
+ return false;
+ };
+
+ return {
+ agent: {
+ dists: 'serve/agent_dists',
+ port: _normalizePort(nconf.get('agent-server:port') || 3002),
+ legacyPort: _normalizePort(nconf.get('agent-server:legacyPort')),
+ SSLOptions: nconf.get('agent-server:ssl') && {
+ key: fs.readFileSync(nconf.get('agent-server:key')),
+ cert: fs.readFileSync(nconf.get('agent-server:cert')),
+ passphrase: nconf.get('agent-server:keyPassphrase')
+ }
+ },
+ server: {
+ port: _normalizePort(nconf.get('server:port') || 3000),
+ SSLOptions: nconf.get('server:ssl') && {
+ enable301Redirects: true,
+ trustXFPHeader: true,
+ key: fs.readFileSync(nconf.get('server:key')),
+ cert: fs.readFileSync(nconf.get('server:cert')),
+ passphrase: nconf.get('server:keyPassphrase')
+ }
+ },
+ smtp: {
+ service: nconf.get('smtp:service'),
+ username: nconf.get('smtp:username'),
+ sign: nconf.get('smtp:sign'),
+ email: nconf.get('smtp:email'),
+ password: nconf.get('smtp:password'),
+ address: (username, email) => username ? '"' + username + '" <' + email + '>' : email
+ },
+ mongoUrl: nconf.get('mongoDB:url') || 'mongodb://localhost/console',
+ cookieTTL: 3600000 * 24 * 30,
+ sessionSecret: 'keyboard cat',
+ tokenLength: 20
+ };
+};
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/base.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/base.jade b/modules/web-console/src/main/js/views/base.jade
new file mode 100644
index 0000000..a910d1b
--- /dev/null
+++ b/modules/web-console/src/main/js/views/base.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.
+
+include includes/header
+
+.container.body-container
+ .main-content(ui-view='')
+
+include includes/footer
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/configuration/caches.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/configuration/caches.jade b/modules/web-console/src/main/js/views/configuration/caches.jade
new file mode 100644
index 0000000..a5b331f
--- /dev/null
+++ b/modules/web-console/src/main/js/views/configuration/caches.jade
@@ -0,0 +1,52 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+include ../../app/helpers/jade/mixins.jade
+
+.docs-header
+ h1 Configure Ignite Caches
+.docs-body(ng-controller='cachesController')
+ ignite-information
+ ul
+ li Configure #[a(href='https://apacheignite.readme.io/docs/data-grid' target='_blank') memory] settings
+ li Configure persistence
+ div(ignite-loading='loadingCachesScreen' ignite-loading-text='Loading caches...' ignite-loading-position='top')
+ div(ng-show='ui.ready')
+ hr
+ +main-table('caches', 'caches', 'cacheName', 'selectItem(row)', '{{$index + 1}}) {{row.label}}', 'label')
+ .padding-top-dflt(bs-affix)
+ .panel-tip-container(data-placement='bottom' bs-tooltip='' data-title='Create new cache')
+ button.btn.btn-primary(id='new-item' ng-click='createItem()') Add cache
+ +save-remove-clone-undo-buttons('cache')
+ hr
+ .bs-affix-fix
+ div(bs-collapse='' data-allow-multiple='true' ng-model='ui.activePanels')
+ form.form-horizontal(name='ui.inputForm' ng-show='contentVisible()' novalidate)
+ .panel-group
+ ignite-configuration-caches-general
+ ignite-configuration-caches-memory
+ ignite-configuration-caches-query
+ ignite-configuration-caches-store
+
+ +advanced-options-toggle-default
+
+ div(ng-show='ui.expanded')
+ ignite-configuration-caches-concurrency
+ ignite-configuration-caches-rebalance
+ ignite-configuration-caches-server-near-cache
+ ignite-configuration-caches-statistics
+
+ +advanced-options-toggle-default
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/configuration/clusters.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/configuration/clusters.jade b/modules/web-console/src/main/js/views/configuration/clusters.jade
new file mode 100644
index 0000000..6e29d86
--- /dev/null
+++ b/modules/web-console/src/main/js/views/configuration/clusters.jade
@@ -0,0 +1,60 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+include ../../app/helpers/jade/mixins.jade
+
+.docs-header
+ h1 Configure Ignite Clusters
+.docs-body(ng-controller='clustersController')
+ ignite-information
+ ul
+ li Configure #[a(href='https://apacheignite.readme.io/docs/clustering' target='_blank') clusters] properties
+ li Associate clusters with caches and in-memory file systems
+ div(ignite-loading='loadingClustersScreen' ignite-loading-text='Loading clusters...' ignite-loading-position='top')
+ div(ng-show='ui.ready')
+ hr
+ +main-table('clusters', 'clusters', 'clusterName', 'selectItem(row)', '{{$index + 1}}) {{row.label}}', 'label')
+ .padding-top-dflt(bs-affix)
+ .panel-tip-container(data-placement='bottom' bs-tooltip='' data-title='Create new cluster')
+ button.btn.btn-primary(id='new-item' ng-click='createItem()') Add cluster
+ +save-remove-clone-undo-buttons('cluster')
+ hr
+ .bs-affix-fix
+ div(bs-collapse='' data-allow-multiple='true' ng-model='ui.activePanels')
+ form.form-horizontal(name='ui.inputForm' ng-show='contentVisible()' novalidate)
+ .panel-group
+ ignite-configuration-clusters-general
+
+ +advanced-options-toggle-default
+
+ div(ng-show='ui.expanded')
+ ignite-configuration-clusters-atomic
+ ignite-configuration-clusters-binary
+ ignite-configuration-clusters-communication
+ ignite-configuration-clusters-connector
+ ignite-configuration-clusters-deployment
+ ignite-configuration-clusters-discovery
+ ignite-configuration-clusters-events
+ ignite-configuration-clusters-igfs
+ ignite-configuration-clusters-marshaller
+ ignite-configuration-clusters-metrics
+ ignite-configuration-clusters-ssl
+ ignite-configuration-clusters-swap
+ ignite-configuration-clusters-thread
+ ignite-configuration-clusters-time
+ ignite-configuration-clusters-transactions
+
+ +advanced-options-toggle-default
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/configuration/domains-import.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/configuration/domains-import.jade b/modules/web-console/src/main/js/views/configuration/domains-import.jade
new file mode 100644
index 0000000..46385f9
--- /dev/null
+++ b/modules/web-console/src/main/js/views/configuration/domains-import.jade
@@ -0,0 +1,196 @@
+//-
+ 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 chk(mdl, change, tip)
+ input(type='checkbox' ng-model=mdl ng-change=change bs-tooltip='' data-title=tip data-trigger='hover' data-placement='top')
+
+mixin td-ellipses-lbl(w, lbl)
+ td.td-ellipsis(width='#{w}' style='min-width: #{w}; max-width: #{w}')
+ label #{lbl}
+
+.modal.modal-domain-import.center(role='dialog')
+ .modal-dialog
+ .modal-content(ignite-loading='importDomainFromDb' ignite-loading-text='{{importDomain.loadingOptions.text}}')
+ #errors-container.modal-header.header
+ button.close(ng-click='$hide()' aria-hidden='true') ×
+ h4.modal-title(ng-if='!importDomain.demo') Import domain models from database
+ h4.modal-title(ng-if='importDomain.demo') Import domain models from demo database
+ .import-domain-model-wizard-page(ng-if='importDomain.action == "drivers" && !importDomain.jdbcDriversNotFound' style='margin-bottom: 321px')
+ .import-domain-model-wizard-page(ng-if='importDomain.action == "drivers" && importDomain.jdbcDriversNotFound' style='margin-bottom: 220px')
+ | Domain model could not be imported
+ ul
+ li Agent failed to find JDBC drivers
+ li Copy required JDBC drivers into agent '\jdbc-drivers' folder and try again
+ li Refer to agent README.txt for more information
+ .import-domain-model-wizard-page(ng-show='importDomain.action == "connect" && importDomain.demo' style='margin-bottom: 211px')
+ div(ng-if='demoConnection.db == "H2"')
+ label Demo description:
+ ul
+ li In-memory H2 database server will be started inside agent
+ li Database will be populated with sample tables
+ li You could test domain model generation with this demo database
+ li Click "Next" to continue
+ div(ng-if='demoConnection.db != "H2"')
+ label Demo could not be started
+ ul
+ li Agent failed to resolve H2 database jar
+ li Copy h2-x.x.x.jar into agent '\jdbc-drivers' folder and try again
+ li Refer to agent README.txt for more information
+ .import-domain-model-wizard-page(ng-show='importDomain.action == "connect" && !importDomain.demo' style='margin-bottom: 90px')
+ form.form-horizontal(name='connectForm' novalidate)
+ .settings-row
+ label.col-xs-4.col-sm-2.col-md-2 Driver JAR:
+ .col-xs-8.col-sm-10.col-md-10
+ i.tipField.fa.fa-question-circle(bs-tooltip='' data-title='Select appropriate JAR with JDBC driver<br> To add another driver you need to place it into "/jdbc-drivers" folder of Ignite Web Agent<br> Refer to Ignite Web Agent README.txt for for more information')
+ .input-tip
+ button.select-toggle.form-control(id='jdbcDriverJar' bs-select data-container='.modal-domain-import' ng-model='ui.selectedJdbcDriverJar' ng-class='{placeholder: !(jdbcDriverJars && jdbcDriverJars.length > 0)}' placeholder='Choose JDBC driver' bs-options='item.value as item.label for item in jdbcDriverJars')
+ .settings-row
+ label.col-xs-4.col-sm-2.col-md-2 JDBC Driver:
+ .col-xs-8.col-sm-10.col-md-10
+ i.tipField.fa.fa-question-circle(bs-tooltip='' data-title='Fully qualified class name of JDBC driver that will be used to connect to database')
+ .input-tip
+ input.form-control(id='jdbcDriverClass' type='text' ng-model='selectedPreset.jdbcDriverClass' placeholder='JDBC driver fully qualified class name' required=true)
+ .settings-row
+ label.col-xs-4.col-sm-2.col-md-2 JDBC URL:
+ .col-xs-8.col-sm-10.col-md-10
+ i.tipField.fa.fa-question-circle(bs-tooltip='' data-title='JDBC URL for connecting to database<br>Refer to your database documentation for details')
+ .input-tip
+ input.form-control(id='jdbcUrl' type='text' ng-model='selectedPreset.jdbcUrl' placeholder='JDBC URL' required=true)
+ .settings-row
+ label.col-xs-4.col-sm-2.col-md-2 User:
+ .col-xs-8.col-sm-10.col-md-10
+ i.tipField.fa.fa-question-circle(bs-tooltip='' data-title='User name for connecting to database')
+ .input-tip
+ input.form-control(id='user' type='text' ng-model='selectedPreset.user')
+ .settings-row
+ label.col-xs-4.col-sm-2.col-md-2 Password:
+ .col-xs-8.col-sm-10.col-md-10
+ i.tipField.fa.fa-question-circle(bs-tooltip='' data-title='Password for connecting to database<br>Note, password would not be saved in preferences for security reasons')
+ .input-tip
+ input.form-control(id='password' type='password' ng-model='selectedPreset.password' on-enter='importDomainNext()')
+ .settings-row
+ .checkbox
+ label
+ input(id='tablesOnly' type='checkbox' ng-model='selectedPreset.tablesOnly')
+ | Tables only
+ i.tipLabel.fa.fa-question-circle(bs-tooltip='' data-title='If selected, then only tables metadata will be parsed<br>Otherwise table and view metadata will be parsed')
+ .import-domain-model-wizard-page(ng-show='importDomain.action == "schemas"')
+ table.table.metadata(st-table='importDomain.displayedSchemas' st-safe-src='importDomain.schemas')
+ thead
+ tr
+ th.header(colspan='2')
+ .col-sm-4.pull-right(style='margin-bottom: 5px')
+ input.form-control(type='text' st-search='name' placeholder='Filter schemas...' ng-model='importDomain.displayedSchemasFilter' ng-change='selectSchema()')
+ tr
+ th(width='30px')
+ +chk('importDomain.allSchemasSelected', 'selectAllSchemas()', 'Select all schemas')
+ th
+ label Schema
+ tbody
+ tr
+ td(colspan='2')
+ .scrollable-y(style='height: 213px')
+ table.table-modal-striped(id='importSchemasData')
+ tbody
+ tr(ng-repeat='schema in importDomain.displayedSchemas')
+ td(width='30px')
+ input(type='checkbox' ng-model='schema.use' ng-change='selectSchema()')
+ td
+ label {{schema.name}}
+ .import-domain-model-wizard-page(ng-show='importDomain.action == "tables"')
+ table.table.metadata(st-table='importDomain.displayedTables' st-safe-src='importDomain.tables')
+ thead
+ tr
+ th.header(colspan='6')
+ .col-sm-4.pull-right(style='margin-bottom: 8px')
+ input.form-control(type='text' st-search='label' placeholder='Filter tables...' ng-model='importDomain.displayedTablesFilter' ng-change='selectTable()')
+ tr
+ th(width='30px')
+ +chk('importDomain.allTablesSelected', 'selectAllTables()', 'Select all tables')
+ th(width='130px')
+ label Schema
+ th(width='160px')
+ label Table name
+ th(colspan=2 width='288px')
+ label Cache
+ th
+ tbody
+ tr
+ td(colspan='6')
+ .scrollable-y(style='height: 143px')
+ table.table-modal-striped(id='importTableData')
+ tbody
+ tr(ng-repeat='table in importDomain.displayedTables track by $index')
+ td(width='30px' style='min-width: 30px; max-width: 30px')
+ input(type='checkbox' ng-model='table.use' ng-change='selectTable()')
+ +td-ellipses-lbl('130px', '{{table.schema}}')
+ +td-ellipses-lbl('160px', '{{table.tbl}}')
+ td(colspan='2' width='288px' style='min-width: 160px; max-width: 160px')
+ div.td-ellipsis
+ a(ng-if='!table.edit' ng-click='startEditDbTableCache(table)') {{tableActionView(table)}}
+ div(style='display: flex' ng-if='table.edit')
+ button.select-toggle.form-control(style='width: 35%; margin-right: 5px' bs-select ng-model='table.action' data-container='.modal-domain-import' bs-options='item.value as item.shortLabel for item in importActions')
+ button.select-toggle.form-control(style='width: 65%; margin-right: 0' bs-select ng-model='table.cacheOrTemplate' data-container='.modal-domain-import' bs-options='item.value as item.label for item in table.cachesOrTemplates')
+ td
+ .settings-row
+ label Defaults to be applied for filtered tables
+ i.tipLabel.fa.fa-question-circle(bs-tooltip='' data-title='Select and apply options for caches generation')
+ .settings-row
+ .col-sm-11
+ .col-sm-6(style='padding-right: 5px')
+ button.select-toggle.form-control(bs-select ng-model='importCommon.action' data-container='.modal-domain-import' bs-options='item.value as item.label for item in importActions')
+ .col-sm-6(style='padding-left: 5px; padding-right: 5px')
+ button.select-toggle.form-control(bs-select ng-model='importCommon.cacheOrTemplate' data-container='.modal-domain-import' bs-options='item.value as item.label for item in importCommon.cachesOrTemplates')
+ .col-sm-1(style='padding-left: 5px')
+ button.btn.btn-primary(ng-click='applyDefaults()') Apply
+ .import-domain-model-wizard-page(ng-show='importDomain.action == "options"' style='margin-bottom: 176px')
+ form.form-horizontal(name='optionsForm' novalidate)
+ .settings-row
+ .col-xs-3.col-sm-2.col-md-2.required
+ label.required Package:
+ .col-xs-9.col-sm-10.col-md-10
+ i.tipField.fa.fa-question-circle(bs-tooltip='' data-title='Package that will be used for POJOs generation')
+ .input-tip
+ input.form-control(id='domainPackageName' type='text' ng-model='ui.packageName' placeholder='Package for POJOs generation')
+ .settings-row
+ .checkbox
+ label
+ input(id='domainBuiltinKeys' type='checkbox' ng-model='ui.builtinKeys')
+ | Use Java built-in types for keys
+ i.tipLabel.fa.fa-question-circle(bs-tooltip='' data-title='Use Java built-in types like "Integer", "Long", "String" instead of POJO generation in case when table primary key contains only one field')
+ .settings-row
+ .checkbox
+ label
+ input(id='domainUsePrimitives' type='checkbox' ng-model='ui.usePrimitives')
+ | Use primitive types for NOT NULL table columns
+ i.tipLabel.fa.fa-question-circle(bs-tooltip='' data-title='Use primitive types like "int", "long", "double" for POJOs fields generation in case of NOT NULL columns')
+ .settings-row
+ .checkbox
+ label
+ input(id='domainGenerateAliases' type='checkbox' ng-model='ui.generateAliases')
+ | Generate aliases for query fields
+ i.tipLabel.fa.fa-question-circle(bs-tooltip='' data-title='Generate aliases for query fields with names from database fields')
+ .settings-row
+ .col-xs-3.col-sm-2.col-md-2.required
+ label Clusters:
+ .col-xs-9.col-sm-10.col-md-10
+ i.tipField.fa.fa-question-circle(bs-tooltip='' data-title='Choose clusters that will be associated with generated caches')
+ .input-tip
+ button.select-toggle.form-control(id='generatedCachesClusters' bs-select ng-model='ui.generatedCachesClusters' ng-class='{placeholder: !(ui.generatedCachesClusters && ui.generatedCachesClusters.length > 0)}' data-container='.modal-domain-import' data-multiple='1' placeholder='Choose clusters for generated caches' bs-options='item.value as item.label for item in clusters')
+ .modal-footer
+ label(ng-hide='importDomain.action == "drivers" || (importDomain.action == "connect" && importDomain.demo)').labelField {{importDomain.info}}
+ a.btn.btn-primary(ng-hide='importDomain.action == "drivers" || importDomain.action == "connect"' ng-click='importDomainPrev()' bs-tooltip='' data-title='{{prevTooltipText()}}' data-placement='bottom') Prev
+ a.btn.btn-primary(ng-click='importDomainNext()' ng-disabled='!importDomainNextAvailable()' bs-tooltip='' data-title='{{nextTooltipText()}}' data-placement='bottom') {{importDomain.button}}
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/configuration/domains.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/configuration/domains.jade b/modules/web-console/src/main/js/views/configuration/domains.jade
new file mode 100644
index 0000000..9975df9
--- /dev/null
+++ b/modules/web-console/src/main/js/views/configuration/domains.jade
@@ -0,0 +1,66 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+include ../../app/helpers/jade/mixins.jade
+
+.docs-header
+ h1 Configure Domain Model And SQL Queries
+.docs-body(ng-controller='domainsController')
+ ignite-information
+ ul: li Import database schemas
+ li Configure indexed types
+ div(ignite-loading='loadingDomainModelsScreen' ignite-loading-text='Loading domain models...' ignite-loading-position='top')
+ div(ng-show='ui.ready')
+ hr
+ .padding-bottom-dflt(ng-show='domains && domains.length > 0')
+ table.links(st-table='displayedRows' st-safe-src='domains')
+ thead
+ tr
+ th
+ .col-sm-8
+ .col-sm-5
+ lable.labelHeader.labelFormField {{domainModelTitle()}}
+ .col-sm-7
+ .pull-right.labelLogin.additional-filter(ng-if='(domains | domainsValidation:false:true).length > 0')
+ a.labelFormField(ng-if='ui.showValid' ng-click='toggleValid()' bs-tooltip='' data-title='{{::ui.invalidKeyFieldsTooltip}}') Key fields should be configured: {{(displayedRows | domainsValidation:false:true).length}} 
+ a.labelFormField(ng-if='!ui.showValid' ng-click='toggleValid()') Show all domain models: {{displayedRows.length}} 
+ .col-sm-4
+ input.form-control.pull-right(type='text' st-search='valueType' placeholder='Filter domain models...')
+ tbody
+ tr
+ td
+ .scrollable-y(ng-show='(displayedRows | domainsValidation:ui.showValid:true).length > 0' style='max-height: 200px')
+ table
+ tbody
+ tr(ng-repeat='row in (displayedRows | domainsValidation:ui.showValid:true) track by row._id' ignite-bs-affix-update)
+ td
+ a(ng-class='{active: row._id == selectedItem._id}' ng-click='selectItem(row)') {{$index + 1}}) {{row.valueType}}
+ label.placeholder(ng-show='(displayedRows | domainsValidation:ui.showValid:true).length == 0') No domain models found
+ .padding-top-dflt(bs-affix)
+ .panel-tip-container(data-placement='bottom' bs-tooltip='' data-title='Create new domain model')
+ button.btn.btn-primary(id='new-item' ng-click='createItem()') Add domain model
+ .panel-tip-container(bs-tooltip='' data-title='Import domain models from database' data-placement='bottom')
+ button.btn.btn-primary(ng-click='showImportDomainModal()') Import from database
+ +save-remove-clone-undo-buttons('domain model')
+ .btn-group.panel-tip-container.pull-right(bs-tooltip='' data-title='Import domain models from demo database' data-placement='bottom')
+ hr
+ .bs-affix-fix
+ div(bs-collapse='' data-allow-multiple='true' ng-model='ui.activePanels')
+ form.form-horizontal(name='ui.inputForm' ng-show='contentVisible()' novalidate)
+ .panel-group
+ ignite-configuration-domains-general
+ ignite-configuration-domains-query
+ ignite-configuration-domains-store
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/configuration/igfs.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/configuration/igfs.jade b/modules/web-console/src/main/js/views/configuration/igfs.jade
new file mode 100644
index 0000000..b889a97
--- /dev/null
+++ b/modules/web-console/src/main/js/views/configuration/igfs.jade
@@ -0,0 +1,51 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+include ../../app/helpers/jade/mixins.jade
+
+.docs-header
+ h1 Configure Ignite In-memory File Systems
+.docs-body(ng-controller='igfsController')
+ ignite-information(data-title='Configure IGFS only if you are going to use In-memory File System')
+ ul
+ li Ignite File System (#[a(href='https://apacheignite-fs.readme.io/docs/in-memory-file-system' target='_blank') IGFS]) is an in-memory file system allowing work with files and directories over existing cache infrastructure
+ li IGFS can either work as purely in-memory file system, or delegate to another file system (e.g. various Hadoop file system implementations) acting as a caching layer (see #[a(href='https://apacheignite-fs.readme.io/docs/secondary-file-system' target='_blank') secondary file system] for more detail)
+ li In addition IGFS provides API to execute map-reduce tasks over file system data
+ div(ignite-loading='loadingIgfsScreen' ignite-loading-text='Loading IGFS screen...' ignite-loading-position='top')
+ div(ng-show='ui.ready')
+ hr
+ +main-table('IGFS', 'igfss', 'igfsName', 'selectItem(row)', '{{$index + 1}}) {{row.name}}', 'name')
+ .padding-top-dflt(bs-affix)
+ .panel-tip-container(data-placement='bottom' bs-tooltip='' data-title='Create new IGFS')
+ button.btn.btn-primary(id='new-item' ng-click='createItem()') Add IGFS
+ +save-remove-clone-undo-buttons('IGFS')
+ hr
+ .bs-affix-fix
+ div(bs-collapse='' data-allow-multiple='true' ng-model='ui.activePanels')
+ form.form-horizontal(name='ui.inputForm' ng-show='contentVisible()' novalidate)
+ .panel-group
+ ignite-configuration-igfs-general
+
+ +advanced-options-toggle-default
+
+ div(ng-show='ui.expanded')
+ ignite-configuration-igfs-secondary
+ ignite-configuration-igfs-ipc
+ ignite-configuration-igfs-fragmentizer
+ ignite-configuration-igfs-dual
+ ignite-configuration-igfs-misc
+
+ +advanced-options-toggle-default
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/configuration/sidebar.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/configuration/sidebar.jade b/modules/web-console/src/main/js/views/configuration/sidebar.jade
new file mode 100644
index 0000000..bba6b25
--- /dev/null
+++ b/modules/web-console/src/main/js/views/configuration/sidebar.jade
@@ -0,0 +1,29 @@
+//-
+ 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.
+
+.row
+ .col-xs-3.col-sm-3.col-md-2.border-right.section-left.greedy
+ .sidebar-nav(bs-affix)
+ ul.menu(ignite-sidebar)
+ li(ng-repeat='item in sidebar.items')
+ a(ui-sref-active='active' ui-sref='{{::item.sref}}')
+ span.fa-stack
+ i.fa.fa-circle-thin.fa-stack-2x
+ i.fa.fa-stack-1x {{::$index + 1}}
+ | {{::item.text}}
+
+ .col-xs-9.col-sm-9.col-md-10.border-left.section-right
+ .docs-content(ui-view='')
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/configuration/summary-project-structure.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/configuration/summary-project-structure.jade b/modules/web-console/src/main/js/views/configuration/summary-project-structure.jade
new file mode 100644
index 0000000..aa09437
--- /dev/null
+++ b/modules/web-console/src/main/js/views/configuration/summary-project-structure.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.
+.popover.summary-project-structure
+ h3.popover-title
+ label.labelField Project structure
+ button.close(id='summary-project-structure-close' ng-click='$hide()') ×
+ .popover-content
+ treecontrol.tree-classic(tree-model='projectStructure' options='projectStructureOptions' expanded-nodes='projectStructureExpanded')
+ span(ng-switch='' on='node.type')
+ span(ng-switch-when='folder')
+ label {{node.name}}
+ span(ng-switch-when='file')
+ i.fa.fa-file-text-o
+ label {{node.name}}
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/configuration/summary-tabs.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/configuration/summary-tabs.jade b/modules/web-console/src/main/js/views/configuration/summary-tabs.jade
new file mode 100644
index 0000000..847b42f
--- /dev/null
+++ b/modules/web-console/src/main/js/views/configuration/summary-tabs.jade
@@ -0,0 +1,25 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ul.nav(ng-class='$navClass', role='tablist')
+ li(role='presentation' ng-repeat='$pane in $panes track by $index' ng-class='[ $isActive($pane, $index) ? $activeClass : "", $pane.disabled ? "disabled" : "" ]')
+ a.summary-tab(ng-show='$pane.title != "POJO" || (cluster | hasPojo)' ng-switch='$pane.title' role='tab' data-toggle='tab' ng-click='!$pane.disabled && $setActive($pane.name || $index)' data-index='{{ $index }}' aria-controls='$pane.title') {{$pane.title}}
+ img(ng-switch-when='XML' src='/images/xml.png')
+ img(ng-switch-when='Java' src='/images/java.png')
+ img(ng-switch-when='POM' src='/images/xml.png')
+ img(ng-switch-when='POJO' src='/images/java.png')
+ img(ng-switch-when='Dockerfile' src='/images/docker.png')
+.tab-content(ng-transclude style='fontSize: 12px; min-height: 25em')
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/configuration/summary.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/configuration/summary.jade b/modules/web-console/src/main/js/views/configuration/summary.jade
new file mode 100644
index 0000000..830adc1
--- /dev/null
+++ b/modules/web-console/src/main/js/views/configuration/summary.jade
@@ -0,0 +1,152 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+include ../../app/helpers/jade/mixins.jade
+
+mixin hard-link(ref, txt)
+ a(style='color:#ec1c24' href=ref target='_blank') #{txt}
+
+.docs-header
+ h1 Configurations Summary
+.docs-body
+ ignite-information
+ ul
+ li Preview XML configurations for #[a(href='https://apacheignite.readme.io/docs/clients-vs-servers' target='_blank') server and client] nodes
+ li Preview code configuration
+ li Preview #[a(href='https://apacheignite.readme.io/docs/docker-deployment' target='_blank') Docker file]
+ li Preview POM dependencies
+ li Download ready-to-use Maven project
+
+ hr
+ .padding-dflt(ng-if='ui.ready && (!clusters || clusters.length == 0)')
+ | You have no clusters configured. Please configure them #[a(ui-sref='base.configuration.clusters') here].
+
+ div(ng-show='clusters && clusters.length > 0' ignite-loading='summaryPage' ignite-loading-text='Loading summary screen...' ignite-loading-position='top')
+ +main-table('clusters', 'clustersView', 'clusterName', 'selectItem(row)', '{{$index + 1}}) {{row.name}}', 'name')
+ div(ng-show='selectedItem && contentVisible(displayedRows, selectedItem)')
+ .padding-top-dflt(bs-affix)
+ button.btn.btn-primary(id='download' ng-click='downloadConfiguration()' bs-tooltip='' data-title='Download project' data-placement='bottom') Download project
+ .btn.btn-primary(bs-tooltip='' data-title='Preview generated project structure' data-placement='bottom')
+ div(bs-popover data-template-url='/configuration/summary-project-structure.html', data-placement='bottom', data-trigger='click' data-auto-close='true')
+ i.fa.fa-sitemap
+ label.tipLabel Project structure
+ button.btn.btn-primary(id='proprietary-jdbc-drivers' ng-if='downloadJdbcDriversVisible()' ng-click='downloadJdbcDrivers()' bs-tooltip='' data-title='Open proprietary JDBC drivers download pages' data-placement='bottom') Download JDBC drivers
+ hr
+ .bs-affix-fix
+ .panel-group(bs-collapse ng-init='ui.activePanels=[0,1]' ng-model='ui.activePanels' data-allow-multiple='true')
+ .panel.panel-default
+ .panel-heading(role='tab' bs-collapse-toggle)
+ ignite-form-panel-chevron
+ label Server
+
+ .panel-collapse(id='server' role='tabpanel' bs-collapse-target)
+ ignite-ui-ace-tabs.summary-tabs
+ div(bs-tabs data-bs-active-pane="tabsServer.activeTab" template='configuration/summary-tabs.html')
+ div(bs-pane title='XML')
+ ignite-ui-ace-xml(ng-if='tabsServer.activeTab == 0 || tabsServer.init[0]' ng-init='tabsServer.init[0] = true' data-master='cluster' data-no-deep-watch)
+ div(bs-pane title='Java')
+ ignite-ui-ace-java(ng-if='tabsServer.activeTab == 1 || tabsServer.init[1]' ng-init='tabsServer.init[1] = true' data-master='cluster' data-no-deep-watch)
+ div(bs-pane title='POM')
+ ignite-ui-ace-pom(ng-if='tabsServer.activeTab == 2 || tabsServer.init[2]' ng-init='tabsServer.init[2] = true' data-cluster='cluster' data-no-deep-watch)
+ div(bs-pane title='Dockerfile')
+ ignite-ui-ace-docker(ng-if='tabsServer.activeTab == 3 || tabsServer.init[3]' ng-init='tabsServer.init[3] = true' data-cluster='cluster' data-no-deep-watch ng-model='ctrl.data.docker')
+
+ .panel.panel-default
+ .panel-heading(role='tab' bs-collapse-toggle)
+ ignite-form-panel-chevron
+ label Client
+
+ .panel-collapse(id='client' role='tabpanel' bs-collapse-target)
+ form(name='clientForm' novalidate)
+ -var nearCfg = 'ctrl.cluster.clientNearCfg'
+ -var nearCfgEvictionPolicy = nearCfg + '.nearEvictionPolicy[' + nearCfg + '.nearEvictionPolicy.kind]'
+
+ .group-content
+ .settings-row
+ ignite-form-field.col-xs-8.col-sm-8.col-md-7(data-label='Near cache start size')
+ ignite-form-field-tooltip
+ | Initial cache size for near cache which will be used to pre-create internal hash table after start
+ ignite-form-field-input-number(
+ data-name='nearStartSize'
+ data-ng-model='#{nearCfg}.nearStartSize'
+ data-placeholder='375000'
+ )
+
+ .settings-row
+ ignite-form-field.col-xs-8.col-sm-8.col-md-7(data-label='Near cache eviction policy')
+ ignite-form-field-tooltip
+ | Cache expiration policy
+ ignite-form-field-dropdown(
+ data-id='evictionPolicies'
+ data-name='evictionPolicies'
+ data-placeholder='Not set'
+ data-options='[\
+ {value: "LRU", label: "LRU"},\
+ {value: "FIFO", label: "FIFO"},\
+ {value: "SORTED", label: "Sorted"},\
+ {value: undefined, label: "Not set"}\
+ ]'
+ data-ng-model='#{nearCfg}.nearEvictionPolicy.kind'
+ )
+ span(ng-if='#{nearCfg}.nearEvictionPolicy.kind')
+ a.customize(
+ ng-show='ctrl.__form.expanded'
+ ng-click='ctrl.__form.expanded = false'
+ ) Hide settings
+ a.customize(
+ ng-hide='ctrl.__form.expanded'
+ ng-click='ctrl.__form.expanded = true'
+ ) Show settings
+
+ .settings-row
+ .panel-details.col-xs-12.col-sm-12.col-md-7(ng-if='ctrl.__form.expanded && #{nearCfg}.nearEvictionPolicy.kind')
+ .details-row
+ ignite-form-field(data-label='Batch size')
+ ignite-form-field-tooltip
+ | Number of entries to remove on shrink
+ ignite-form-field-input-number(
+ data-name='batchSize'
+ data-ng-model='#{nearCfgEvictionPolicy}.batchSize'
+ data-placeholder='1'
+ )
+ .details-row
+ ignite-form-field(data-label='Max memory size')
+ ignite-form-field-tooltip
+ | Maximum allowed cache size in bytes
+ ignite-form-field-input-number(
+ data-name='maxMemorySize'
+ data-ng-model='#{nearCfgEvictionPolicy}.maxMemorySize'
+ data-placeholder='0'
+ )
+ .details-row
+ ignite-form-field(data-label='Max size')
+ ignite-form-field-tooltip
+ | Maximum allowed size of cache before entry will start getting evicted
+ ignite-form-field-input-number(
+ data-name='maxSize'
+ data-ng-model='#{nearCfgEvictionPolicy}.maxSize'
+ data-placeholder='100000'
+ )
+ .summary-tabs(ignite-ui-ace-tabs)
+ div(bs-tabs data-bs-active-pane="tabsClient.activeTab" template='configuration/summary-tabs.html')
+ div(bs-pane title='XML')
+ ignite-ui-ace-xml(ng-if='tabsClient.activeTab == 0 || tabsClient.init[0]' ng-init='tabsClient.init[0] = true' data-master='cluster' data-no-deep-watch data-cluster-cfg='#{nearCfg}')
+ div(bs-pane title='Java')
+ ignite-ui-ace-java(ng-if='tabsClient.activeTab == 1 || tabsClient.init[1]' ng-init='tabsClient.init[1] = true' data-master='cluster' data-no-deep-watch data-cluster-cfg='#{nearCfg}')
+ div(bs-pane title='POM')
+ ignite-ui-ace-pom(ng-if='tabsClient.activeTab == 2 || tabsClient.init[2]' ng-init='tabsClient.init[2] = true' data-cluster='cluster' data-no-deep-watch)
+ div(bs-pane title='POJO' ng-if='cluster | hasPojo')
+ ignite-ui-ace-pojos(ng-if='tabsClient.activeTab == 3 || tabsClient.init[3]' ng-init='tabsClient.init[3] = true' data-cluster='cluster' data-no-deep-watch ng-model='ctrl.data.pojos')
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/includes/footer.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/includes/footer.jade b/modules/web-console/src/main/js/views/includes/footer.jade
new file mode 100644
index 0000000..4ef3bf6
--- /dev/null
+++ b/modules/web-console/src/main/js/views/includes/footer.jade
@@ -0,0 +1,23 @@
+//-
+ 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
+ .col-md-offset-1.col-md-10
+ ignite-footer
+ .col-md-1
+ .pull-right
+ ignite-powered-by-apache
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/includes/header.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/includes/header.jade b/modules/web-console/src/main/js/views/includes/header.jade
new file mode 100644
index 0000000..2b66d82
--- /dev/null
+++ b/modules/web-console/src/main/js/views/includes/header.jade
@@ -0,0 +1,48 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+header#header.header
+ .viewedUser(ng-show='$root.user.becomeUsed')
+ | Currently assuming #[strong {{$root.user.firstName}} {{$root.user.lastName}}], #[a(ng-click='$root.revertIdentity()') revert to your identity].
+ table.container
+ tr
+ td.col-xs-3.col-sm-3.col-md-2
+ ignite-header-logo
+ td(ng-if='$root.user' style='padding-top: 20px')
+ ul.nav.navbar-nav(ignite-sidebar ignite-navbar)
+ li(ng-class='{active: $state.includes("base.configuration")}')
+ a.dropdown-toggle(data-toggle='dropdown' bs-dropdown='sidebar.items' data-placement='bottom-right') Configuration
+ span.caret
+
+ li.sql-notebooks(ng-class='{active: $state.includes("base.sql")}' ng-controller='notebooks')
+ a(ng-if='IgniteDemoMode' ui-sref='base.sql.demo') SQL
+
+ a(ng-if='!IgniteDemoMode && !notebooks.length' ng-click='inputNotebookName()') SQL
+
+ a.dropdown-toggle(ng-if='!IgniteDemoMode && notebooks.length' data-toggle='dropdown' bs-dropdown='notebookDropdown' data-placement='bottom-left') SQL
+ span.caret
+
+ li(ui-sref-active='active' ng-repeat='item in navbar.items')
+ a(ui-sref='{{::item.sref}}') {{::item.text}}
+
+ a(ng-controller='demoController')
+ button.btn.btn-info(ng-if='IgniteDemoMode' ng-click='closeDemo()') Close demo
+ button.btn.btn-info(ng-if='!IgniteDemoMode' ng-click='startDemo()') Start demo
+
+ ul.nav.navbar-nav.pull-right(ignite-userbar)
+ li(ng-class='{active: $state.includes("settings")}')
+ a.dropdown-toggle(data-toggle='dropdown' bs-dropdown='userbar.items' data-placement='bottom-right') {{user.firstName}} {{user.lastName}}
+ span.caret
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/index.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/index.jade b/modules/web-console/src/main/js/views/index.jade
new file mode 100644
index 0000000..8514533
--- /dev/null
+++ b/modules/web-console/src/main/js/views/index.jade
@@ -0,0 +1,66 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+doctype html
+html(ng-app='ignite-console' id='app' ng-strict-di)
+ head
+ base(href='/')
+ link(rel='shortcut icon' href='favicon.ico')
+
+ meta(http-equiv='content-type' content='text/html; charset=UTF8')
+ meta(http-equiv='content-language' content='en')
+
+ title(ng-bind='$meta.title')
+
+ meta(name='fragment' content='!')
+ meta(name='description' content='{{$meta.description}}')
+ meta(name='keywords' content='{{$meta.keywords}}')
+ meta(ng-repeat='(key, value) in $meta.properties' name='{{::key}}' content='{{::value}}')
+
+ // build:css
+ link(rel='stylesheet', href='/vendors.css')
+ link(rel='stylesheet', href='/app.css')
+ // endbuild
+
+ body.theme-line.body-overlap.greedy
+
+ .splash.splash-max-foreground(hide-on-state-change)
+ .splash-wrapper
+ .spinner
+ .bounce1
+ .bounce2
+ .bounce3
+
+ .splash-wellcome Loading...
+
+
+ .ribbon-wrapper.right(ng-cloak)
+ .ribbon(ng-style='IgniteDemoMode && {"background": "#1b6d88"}')
+ label {{IgniteDemoMode ? "Demo" : "Beta" }}
+
+ .wrapper(ui-view='')
+
+
+ // build:js
+ script(src='jspm_packages/system.js')
+ script(src='system.config.js')
+ script(src='vendors.js')
+ script(src='app.js')
+ script System.import('app/index');
+ // endbuild
+
+ // ignite:plugins
+ // endignite
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/reset.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/reset.jade b/modules/web-console/src/main/js/views/reset.jade
new file mode 100644
index 0000000..e5b8f12
--- /dev/null
+++ b/modules/web-console/src/main/js/views/reset.jade
@@ -0,0 +1,48 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+header#header.header
+ table.container
+ tr
+ td.col-xs-3.col-sm-3.col-md-2
+ ignite-header-logo
+ td
+ ignite-header-title
+
+.container.body-container
+ .main-content(ng-controller='resetPassword')
+ .row
+ .text-center(ng-if='!token')
+ p Further instructions for password reset have been sent to your e-mail address.
+ .text-center(ng-if='error')
+ p {{::error}}
+ div(ng-if='token && !error')
+ form.form-horizontal(name='resetForm' ng-init='reset_info.token = token')
+ .settings-row
+ label.col-sm-1 E-mail:
+ label {{::email}}
+ .settings-row
+ label.col-sm-1.required Password:
+ .col-sm-3
+ input#user_password.form-control(enter-focus-next='user_confirm' type='password' ng-model='reset_info.password' placeholder='New password' required)
+ .settings-row
+ label.col-sm-1.required Confirm:
+ .col-sm-3
+ input#user_confirm.form-control(type='password' ng-model='reset_info.confirm' match='reset_info.password' placeholder='Confirm new password' required on-enter='resetForm.$valid && resetPassword(user_info)')
+ .settings-row
+ button.btn.btn-primary(ng-disabled='resetForm.$invalid' ng-click='resetPassword(reset_info)') Reset Password
+
+include includes/footer
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/views/settings/admin.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/settings/admin.jade b/modules/web-console/src/main/js/views/settings/admin.jade
new file mode 100644
index 0000000..862d959
--- /dev/null
+++ b/modules/web-console/src/main/js/views/settings/admin.jade
@@ -0,0 +1,76 @@
+//-
+ 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.
+
+.row(ng-controller='adminController')
+ .docs-content.greedy
+ .docs-header
+ h1 List of registered users
+ hr
+ .docs-body
+ .col-xs-12
+ table.table.table-striped.table-vertical-middle.admin(st-table='displayedUsers' st-safe-src='users')
+ thead
+ tr
+ th.header(colspan='10')
+ .col-xs-3
+ input.form-control(type='text' st-search='label' placeholder='Filter users...')
+ .col-xs-9.admin-summary.text-right(colspan='10')
+ strong Total users: {{ users.length }}
+ .col-xs-offset-6.col-xs-6.text-right
+ div(st-pagination st-items-by-page='15' st-displayed-pages='5' st-template='../templates/pagination.html')
+ tr
+ th(st-sort='userName') User
+ th(st-sort='email') Email
+ th(st-sort='company') Company
+ th(st-sort='country') Country
+ th.col-xs-2(st-sort='lastLogin' st-sort-default='reverse') Last login
+ th.text-nowrap(st-sort='counters.clusters' st-descending-first bs-tooltip='"Clusters count"' data-placement='top')
+ i.fa.fa-sitemap()
+ th.text-nowrap(st-sort='counters.models' st-descending-first bs-tooltip='"Models count"' data-placement='top')
+ i.fa.fa-object-group()
+ th.text-nowrap(st-sort='counters.caches' st-descending-first bs-tooltip='"Caches count"' data-placement='top')
+ i.fa.fa-database()
+ th.text-nowrap(st-sort='counters.igfs' st-descending-first bs-tooltip='"IGFS count"' data-placement='top')
+ i.fa.fa-folder-o()
+ th(width='1%') Actions
+ tbody
+ tr(ng-repeat='row in displayedUsers track by row._id')
+ td {{::row.userName}}
+ td
+ a(ng-href='mailto:{{::row.email}}') {{::row.email}}
+ td {{::row.company}}
+ td {{::row.countryCode}}
+ td {{::row.lastLogin | date:'medium'}}
+ td {{::row.counters.clusters}}
+ td {{::row.counters.models}}
+ td {{::row.counters.caches}}
+ td {{::row.counters.igfs}}
+ td.text-center
+ a.btn.btn-default.dropdown-toggle(bs-dropdown='' ng-show='row._id != user._id' data-placement='bottom-right')
+ i.fa.fa-gear
+ span.caret
+ ul.dropdown-menu(role='menu')
+ li
+ a(ng-click='becomeUser(row)') Become this user
+ li
+ a(ng-click='toggleAdmin(row)' ng-if='row.admin && row._id !== user._id') Revoke admin
+ a(ng-click='toggleAdmin(row)' ng-if='!row.admin && row._id !== user._id') Grant admin
+ li
+ a(ng-click='removeUser(row)') Remove user
+ tfoot
+ tr
+ td.text-right(colspan='10')
+ div(st-pagination st-items-by-page='15' st-displayed-pages='5' st-template='../templates/pagination.html')