#ignite-1121 Merged with ignite-843
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/a45a700c Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/a45a700c Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/a45a700c Branch: refs/heads/ignite-1121 Commit: a45a700c63b70c075df494fd080e668803387c32 Parents: 71b313c 14fa6f6 Author: Andrey <anovi...@gridgain.com> Authored: Thu Jul 23 15:41:20 2015 +0700 Committer: Andrey <anovi...@gridgain.com> Committed: Thu Jul 23 15:41:20 2015 +0700 ---------------------------------------------------------------------- modules/web-control-center/nodejs/.gitignore | 4 - modules/web-control-center/nodejs/DEVNOTES.txt | 21 - .../nodejs/agents/agent-manager.js | 283 ----- .../nodejs/agents/agent-server.js | 90 -- modules/web-control-center/nodejs/app.js | 156 --- modules/web-control-center/nodejs/bin/www | 110 -- .../nodejs/config/default.json | 17 - .../nodejs/controllers/admin-controller.js | 68 - .../nodejs/controllers/caches-controller.js | 333 ----- .../nodejs/controllers/clusters-controller.js | 309 ----- .../nodejs/controllers/common-module.js | 422 ------- .../nodejs/controllers/metadata-controller.js | 678 ---------- .../nodejs/controllers/models/caches.json | 905 ------------- .../nodejs/controllers/models/clusters.json | 896 ------------- .../nodejs/controllers/models/metadata.json | 218 ---- .../nodejs/controllers/models/sql.json | 5 - .../nodejs/controllers/models/summary.json | 150 --- .../nodejs/controllers/profile-controller.js | 51 - .../nodejs/controllers/sql-controller.js | 60 - .../nodejs/controllers/summary-controller.js | 171 --- modules/web-control-center/nodejs/db.js | 358 ------ .../nodejs/helpers/configuration-loader.js | 22 - .../nodejs/helpers/data-structures.js | 84 -- modules/web-control-center/nodejs/keys/test.crt | 13 - modules/web-control-center/nodejs/keys/test.key | 18 - modules/web-control-center/nodejs/package.json | 51 - .../nodejs/public/favicon.ico | Bin 1150 -> 0 bytes .../nodejs/public/images/docker.png | Bin 994 -> 0 bytes .../nodejs/public/images/java.png | Bin 170 -> 0 bytes .../nodejs/public/images/logo.png | Bin 8148 -> 0 bytes .../nodejs/public/images/xml.png | Bin 232 -> 0 bytes .../nodejs/public/stylesheets/style.less | 1125 ----------------- .../web-control-center/nodejs/routes/admin.js | 79 -- .../web-control-center/nodejs/routes/agent.js | 37 - .../web-control-center/nodejs/routes/caches.js | 95 -- .../nodejs/routes/clusters.js | 104 -- .../nodejs/routes/generator/common.js | 299 ----- .../nodejs/routes/generator/docker.js | 58 - .../nodejs/routes/generator/java.js | 626 --------- .../nodejs/routes/generator/xml.js | 580 --------- .../nodejs/routes/metadata.js | 95 -- .../web-control-center/nodejs/routes/profile.js | 97 -- .../web-control-center/nodejs/routes/public.js | 123 -- modules/web-control-center/nodejs/routes/sql.js | 24 - .../web-control-center/nodejs/routes/summary.js | 108 -- .../nodejs/tests/routes/agent.js | 94 -- .../nodejs/views/configuration/caches.jade | 70 - .../nodejs/views/configuration/clusters.jade | 73 -- .../nodejs/views/configuration/metadata.jade | 120 -- .../nodejs/views/configuration/sidebar.jade | 39 - .../nodejs/views/configuration/summary.jade | 115 -- .../web-control-center/nodejs/views/error.jade | 22 - .../nodejs/views/includes/controls.jade | 316 ----- .../nodejs/views/includes/footer.jade | 22 - .../nodejs/views/includes/header.jade | 39 - .../web-control-center/nodejs/views/index.jade | 30 - .../web-control-center/nodejs/views/login.jade | 55 - .../nodejs/views/settings/admin.jade | 58 - .../nodejs/views/settings/profile.jade | 58 - .../nodejs/views/sql/sql.jade | 70 - .../nodejs/views/templates/confirm.jade | 27 - .../nodejs/views/templates/layout.jade | 61 - .../nodejs/views/templates/saveAs.jade | 31 - .../nodejs/views/templates/select.jade | 26 - .../web-control-center/src/main/js/.gitignore | 4 + .../web-control-center/src/main/js/DEVNOTES.txt | 21 + .../src/main/js/agents/agent-manager.js | 283 +++++ .../src/main/js/agents/agent-server.js | 90 ++ modules/web-control-center/src/main/js/app.js | 156 +++ modules/web-control-center/src/main/js/bin/www | 110 ++ .../src/main/js/config/default.json | 17 + .../src/main/js/controllers/admin-controller.js | 68 + .../js/controllers/cache-viewer-controller.js | 77 ++ .../main/js/controllers/caches-controller.js | 333 +++++ .../main/js/controllers/clusters-controller.js | 309 +++++ .../src/main/js/controllers/common-module.js | 422 +++++++ .../main/js/controllers/metadata-controller.js | 680 ++++++++++ .../src/main/js/controllers/models/caches.json | 918 ++++++++++++++ .../main/js/controllers/models/clusters.json | 907 +++++++++++++ .../main/js/controllers/models/metadata.json | 230 ++++ .../src/main/js/controllers/models/sql.json | 5 + .../src/main/js/controllers/models/summary.json | 163 +++ .../main/js/controllers/profile-controller.js | 51 + .../src/main/js/controllers/sql-controller.js | 60 + .../main/js/controllers/summary-controller.js | 170 +++ modules/web-control-center/src/main/js/db.js | 358 ++++++ .../src/main/js/helpers/configuration-loader.js | 22 + .../src/main/js/helpers/data-structures.js | 84 ++ .../src/main/js/keys/test.crt | 13 + .../src/main/js/keys/test.key | 18 + .../web-control-center/src/main/js/package.json | 51 + .../src/main/js/public/favicon.ico | Bin 0 -> 1150 bytes .../src/main/js/public/images/docker.png | Bin 0 -> 994 bytes .../src/main/js/public/images/java.png | Bin 0 -> 170 bytes .../src/main/js/public/images/logo.png | Bin 0 -> 8148 bytes .../src/main/js/public/images/xml.png | Bin 0 -> 232 bytes .../src/main/js/public/stylesheets/style.less | 1193 ++++++++++++++++++ .../src/main/js/routes/admin.js | 79 ++ .../src/main/js/routes/agent.js | 37 + .../src/main/js/routes/caches.js | 95 ++ .../src/main/js/routes/clusters.js | 104 ++ .../src/main/js/routes/generator/common.js | 299 +++++ .../src/main/js/routes/generator/docker.js | 58 + .../src/main/js/routes/generator/java.js | 626 +++++++++ .../src/main/js/routes/generator/xml.js | 580 +++++++++ .../src/main/js/routes/metadata.js | 95 ++ .../src/main/js/routes/profile.js | 97 ++ .../src/main/js/routes/public.js | 123 ++ .../src/main/js/routes/sql.js | 24 + .../src/main/js/routes/summary.js | 108 ++ .../src/main/js/views/configuration/caches.jade | 74 ++ .../main/js/views/configuration/clusters.jade | 77 ++ .../main/js/views/configuration/metadata.jade | 121 ++ .../main/js/views/configuration/sidebar.jade | 39 + .../main/js/views/configuration/summary.jade | 115 ++ .../src/main/js/views/error.jade | 22 + .../src/main/js/views/includes/controls.jade | 336 +++++ .../src/main/js/views/includes/footer.jade | 22 + .../src/main/js/views/includes/header.jade | 39 + .../src/main/js/views/index.jade | 30 + .../src/main/js/views/login.jade | 55 + .../src/main/js/views/settings/admin.jade | 58 + .../src/main/js/views/settings/profile.jade | 58 + .../src/main/js/views/sql.jade | 70 + .../src/main/js/views/templates/confirm.jade | 27 + .../src/main/js/views/templates/copy.jade | 31 + .../src/main/js/views/templates/layout.jade | 61 + .../src/main/js/views/templates/select.jade | 26 + .../src/main/js/views/templates/tab.jade | 3 + .../src/test/js/routes/agent.js | 94 ++ 130 files changed, 10496 insertions(+), 10269 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/agents/agent-manager.js ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/agents/agent-manager.js index 0000000,0000000..252b984 new file mode 100644 --- /dev/null +++ b/modules/web-control-center/src/main/js/agents/agent-manager.js @@@ -1,0 -1,0 +1,283 @@@ ++/* ++ * Licensed to the Apache Software Foundation (ASF) under one or more ++ * contributor license agreements. See the NOTICE file distributed with ++ * this work for additional information regarding copyright ownership. ++ * The ASF licenses this file to You under the Apache License, Version 2.0 ++ * (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++var WebSocketServer = require('ws').Server; ++ ++var ignite = require('apache-ignite'); ++ ++var db = require('../db'); ++ ++var AgentServer = require('./agent-server').AgentServer; ++ ++/** ++ * @constructor ++ */ ++function AgentManager(srv) { ++ this._clients = {}; ++ ++ this._server = srv; ++ ++ this._wss = new WebSocketServer({ server: this._server }); ++ ++ var self = this; ++ ++ this._wss.on('connection', function(ws) { ++ var client = new Client(ws, self); ++ }); ++} ++ ++/** ++ * @param userId ++ * @param {Client} client ++ */ ++AgentManager.prototype._removeClient = function(userId, client) { ++ var connections = this._clients[userId]; ++ ++ if (connections) { ++ removeFromArray(connections, client); ++ ++ if (connections.length == 0) ++ delete this._clients[userId]; ++ } ++}; ++ ++/** ++ * @param userId ++ * @param {Client} client ++ */ ++AgentManager.prototype._addClient = function(userId, client) { ++ var existingConnections = this._clients[userId]; ++ ++ if (!existingConnections) { ++ existingConnections = []; ++ ++ this._clients[userId] = existingConnections; ++ } ++ ++ existingConnections.push(client); ++}; ++ ++/** ++ * @param userId ++ * @return {Client} ++ */ ++AgentManager.prototype.findClient = function(userId) { ++ var clientsList = this._clients[userId]; ++ ++ if (!clientsList) ++ return null; ++ ++ return clientsList[0]; ++}; ++ ++/** ++ * For tests only!!! ++ * @return {Client} ++ */ ++AgentManager.prototype.getOneClient = function() { ++ for (var userId in this._clients) { ++ if (this._clients.hasOwnProperty(userId)) { ++ var m = this._clients[userId]; ++ ++ if (m.length > 0) ++ return m[0]; ++ } ++ } ++ ++ return null; ++}; ++ ++ ++/** ++ * @constructor ++ * @param {AgentManager} manager ++ * @param {WebSocket} ws ++ */ ++function Client(ws, manager) { ++ var self = this; ++ ++ this._manager = manager; ++ this._ws = ws; ++ ++ ws.on('close', function() { ++ if (self.user) { ++ self._manager._removeClient(self.user._id, self); ++ } ++ }); ++ ++ ws.on('message', function (msg) { ++ self._handleMessage(JSON.parse(msg)) ++ }); ++ ++ this._restCounter = 0; ++ ++ this._cbMap = {}; ++} ++ ++/** ++ * @param {String|Object} msg ++ * @param {Function} cb ++ */ ++Client.prototype.sendMessage = function(msg, cb) { ++ if (typeof msg == 'object') { ++ msg = JSON.stringify(msg); ++ } ++ ++ this._ws.send(msg, cb); ++}; ++ ++/** ++ * @param {String} path ++ * @param {Object} params ++ * @param {Function} cb ++ * @param {String} method ++ * @param {String} body ++ * @param {Object} headers ++ */ ++Client.prototype.invokeRest = function(path, params, cb, method, body, headers) { ++ var self = this; ++ ++ if (typeof(params) != 'object') ++ throw "'params' argument must be an object"; ++ ++ if (typeof(cb) != 'function') ++ throw "callback must be a function"; ++ ++ if (body && typeof(body) != 'string') ++ throw "body must be a string"; ++ ++ if (headers && typeof(headers) != 'object') ++ throw "headers must be an object"; ++ ++ if (!method) ++ method = 'GET'; ++ else ++ method = method.toUpperCase(); ++ ++ if (method != 'GET' && method != 'POST') ++ throw "Unknown HTTP method: " + method; ++ ++ var reqId = this._restCounter++; ++ ++ this._cbMap[reqId] = cb; ++ ++ this.sendMessage({ ++ id: reqId, ++ type: 'RestRequest', ++ method: method, ++ params: params, ++ path: path, ++ body: body, ++ headers: headers ++ }, function(err) { ++ if (err) { ++ delete self._cbMap[reqId]; ++ ++ cb(err) ++ } ++ }) ++}; ++ ++/** ++ * @param {Object} msg ++ */ ++Client.prototype._handleMessage = function(msg) { ++ var self = this; ++ ++ switch (msg.type) { ++ case 'AuthMessage': ++ var account = db.Account.findByUsername(msg.login, function(err, account) { ++ if (err) { ++ ws.send("{type: 'AuthResult', success: false}"); ++ } ++ else { ++ account.authenticate(msg.password, function(err, user, res) { ++ if (!user) { ++ self._ws.send(JSON.stringify({type: 'AuthResult', success: false, message: res.message})); ++ } ++ else { ++ self._ws.send("{type: 'AuthResult', success: true}"); ++ ++ self._user = account; ++ ++ self._manager._addClient(account._id, self); ++ ++ self._ignite = new ignite.Ignite(new AgentServer(self)); ++ } ++ }); ++ } ++ }); ++ ++ break; ++ ++ case 'RestResult': ++ var cb = this._cbMap[msg.requestId]; ++ ++ if (!cb) ++ break; ++ ++ delete this._cbMap[msg.requestId]; ++ ++ if (!msg.executed) { ++ cb(msg.message) ++ } ++ else { ++ cb(null, msg.code, msg.message) ++ } ++ ++ break; ++ ++ default: ++ this._ws.close() ++ } ++}; ++ ++/** ++ * @return {Ignite} ++ */ ++Client.prototype.ignite = function() { ++ return this._ignite; ++}; ++ ++function removeFromArray(arr, val) { ++ var idx; ++ ++ while ((idx = arr.indexOf(val)) !== -1) { ++ arr.splice(idx, 1); ++ } ++} ++ ++exports.AgentManager = AgentManager; ++ ++/** ++ * @type {AgentManager} ++ */ ++var manager = null; ++ ++exports.createManager = function(srv) { ++ if (manager) ++ throw "Agent manager already cleared!"; ++ ++ manager = new AgentManager(srv); ++}; ++ ++/** ++ * @return {AgentManager} ++ */ ++exports.getAgentManager = function() { ++ return manager; ++}; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/agents/agent-server.js ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/agents/agent-server.js index 0000000,0000000..31dee5a new file mode 100644 --- /dev/null +++ b/modules/web-control-center/src/main/js/agents/agent-server.js @@@ -1,0 -1,0 +1,90 @@@ ++/* ++ * Licensed to the Apache Software Foundation (ASF) under one or more ++ * contributor license agreements. See the NOTICE file distributed with ++ * this work for additional information regarding copyright ownership. ++ * The ASF licenses this file to You under the Apache License, Version 2.0 ++ * (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++/** ++ * Creates an instance of server for Ignite ++ * ++ * @constructor ++ * @this {AgentServer} ++ * @param {Client} client connected client ++ */ ++function AgentServer(client) { ++ this._client = client; ++} ++ ++/** ++ * Run http request ++ * ++ * @this {AgentServer} ++ * @param {Command} cmd Command ++ * @param {callback} callback on finish ++ */ ++AgentServer.prototype.runCommand = function(cmd, callback) { ++ var params = {cmd: cmd.name()}; ++ ++ for (var p of cmd._params) { ++ params[p.key] = p.value; ++ } ++ ++ var body = undefined; ++ ++ var headers = undefined; ++ ++ if (cmd._isPost()) { ++ body = cmd.postData(); ++ ++ headers = {'Content-Length': body.length, 'JSONObject': 'application/json'}; ++ } ++ ++ this._client.invokeRest("ignite", params, function(error, code, message) { ++ if (error) { ++ callback(error); ++ return ++ } ++ ++ if (code !== 200) { ++ if (code === 401) { ++ callback.call(null, "Authentication failed. Status code 401."); ++ } ++ else { ++ callback.call(null, "Request failed. Status code " + code); ++ } ++ ++ return; ++ } ++ ++ var igniteResponse; ++ ++ try { ++ igniteResponse = JSON.parse(message); ++ } ++ catch (e) { ++ callback.call(null, e, null); ++ ++ return; ++ } ++ ++ if (igniteResponse.successStatus) { ++ callback.call(null, igniteResponse.error, null) ++ } ++ else { ++ callback.call(null, null, igniteResponse.response); ++ } ++ }, cmd._method(), body, headers); ++}; ++ ++exports.AgentServer = AgentServer; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/app.js ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/app.js index 0000000,8c347db..8cd8494 mode 000000,100644..100644 --- a/modules/web-control-center/src/main/js/app.js +++ b/modules/web-control-center/src/main/js/app.js @@@ -1,0 -1,154 +1,156 @@@ + /* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + var flash = require('connect-flash'); + var express = require('express'); + var path = require('path'); + var favicon = require('serve-favicon'); + var logger = require('morgan'); + var cookieParser = require('cookie-parser'); + var bodyParser = require('body-parser'); + var session = require('express-session'); + var mongoStore = require('connect-mongo')(session); + + var publicRoutes = require('./routes/public'); + var clustersRouter = require('./routes/clusters'); + var cachesRouter = require('./routes/caches'); + var metadataRouter = require('./routes/metadata'); + var summary = require('./routes/summary'); + var adminRouter = require('./routes/admin'); + var profileRouter = require('./routes/profile'); + var sqlRouter = require('./routes/sql'); ++var agentRouter = require('./routes/agent'); + + var passport = require('passport'); + + var db = require('./db'); + + var app = express(); + + // Views engine setup. + app.set('views', path.join(__dirname, 'views')); + app.set('view engine', 'jade'); + + // Site favicon. + app.use(favicon(__dirname + '/public/favicon.ico')); + + app.use(logger('dev')); + + app.use(bodyParser.json()); + app.use(bodyParser.urlencoded({extended: false})); + + app.use(require('less-middleware')(path.join(__dirname, 'public'), { + render: { + compress: false + } + })); + + app.use(express.static(path.join(__dirname, 'public'))); + app.use(express.static(path.join(__dirname, 'controllers'))); + app.use(express.static(path.join(__dirname, 'helpers'))); + + app.use(cookieParser('keyboard cat')); + + app.use(session({ + secret: 'keyboard cat', + resave: false, + saveUninitialized: true, + store: new mongoStore({ + mongooseConnection: db.mongoose.connection + }) + })); + + app.use(flash()); + + app.use(passport.initialize()); + app.use(passport.session()); + + passport.serializeUser(db.Account.serializeUser()); + passport.deserializeUser(db.Account.deserializeUser()); + + passport.use(db.Account.createStrategy()); + + var mustAuthenticated = function (req, res, next) { + req.isAuthenticated() ? next() : res.redirect('/'); + }; + + var adminOnly = function(req, res, next) { + req.isAuthenticated() && req.user.admin ? next() : res.sendStatus(403); + }; + + app.all('/configuration/*', mustAuthenticated); + + app.all('*', function(req, res, next) { + var becomeUsed = req.session.viewedUser && req.user.admin; + + res.locals.user = becomeUsed ? req.session.viewedUser : req.user; + res.locals.becomeUsed = becomeUsed; + + req.currentUserId = function() { + if (!req.user) + return null; + + if (req.session.viewedUser && req.user.admin) + return req.session.viewedUser._id; + + return req.user._id; + }; + + next(); + }); + + app.use('/', publicRoutes); + app.use('/admin', mustAuthenticated, adminOnly, adminRouter); + app.use('/profile', mustAuthenticated, profileRouter); + + app.use('/configuration/clusters', clustersRouter); + app.use('/configuration/caches', cachesRouter); + app.use('/configuration/metadata', metadataRouter); + app.use('/configuration/summary', summary); + app.use('/sql', sqlRouter); ++app.use('/agent', agentRouter); + + // Catch 404 and forward to error handler. + app.use(function (req, res, next) { + var err = new Error('Not Found: ' + req.originalUrl); + err.status = 404; + next(err); + }); + + // Error handlers. + + // Development error handler: will print stacktrace. + if (app.get('env') === 'development') { + app.use(function (err, req, res) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: err + }); + }); + } + + // Production error handler: no stacktraces leaked to user. + app.use(function (err, req, res) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: {} + }); + }); + + module.exports = app; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/bin/www ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/bin/www index 0000000,4cf0583..cbc637a mode 000000,100644..100644 --- a/modules/web-control-center/src/main/js/bin/www +++ b/modules/web-control-center/src/main/js/bin/www @@@ -1,0 -1,85 +1,110 @@@ + #!/usr/bin/env node + + /** + * Module dependencies. + */ -var app = require('../app'); ++var http = require('http'); ++var https = require('https'); + var config = require('../helpers/configuration-loader.js'); ++var app = require('../app'); ++var agentManager = require('../agents/agent-manager'); ++ ++var fs = require('fs'); ++ + var debug = require('debug')('ignite-web-control-center:server'); -var http = require('http'); + + /** + * Get port from environment and store in Express. + */ + var port = normalizePort(process.env.PORT || config.get('express:port')); + app.set('port', port); + + /** + * Create HTTP server. + */ + var server = http.createServer(app); + + /** + * Listen on provided port, on all network interfaces. + */ + server.listen(port); + server.on('error', onError); + server.on('listening', onListening); + + /** ++ * Start agent server. ++ */ ++var agentServer; ++ ++if (config.get('monitor:server:ssl')) { ++ agentServer = https.createServer({ ++ key: fs.readFileSync(config.get('monitor:server:key')), ++ cert: fs.readFileSync(config.get('monitor:server:cert')), ++ passphrase: config.get('monitor:server:keyPassphrase') ++ }); ++} ++else { ++ agentServer = http.createServer(); ++} ++ ++agentServer.listen(config.get('monitor:server:port')); ++ ++agentManager.createManager(agentServer); ++ ++/** + * Normalize a port into a number, string, or false. + */ + function normalizePort(val) { + var port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; + } + + /** + * Event listener for HTTP server "error" event. + */ + function onError(error) { + if (error.syscall !== 'listen') { + throw error; + } + + var bind = typeof port === 'string' + ? 'Pipe ' + port + : 'Port ' + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } + } + + /** + * Event listener for HTTP server "listening" event. + */ + function onListening() { + var addr = server.address(); + var bind = typeof addr === 'string' + ? 'pipe ' + addr + : 'port ' + addr.port; + + debug('Listening on ' + bind); + } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/config/default.json ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/config/default.json index 0000000,72dbd4e..f7f7a02 mode 000000,100644..100644 --- a/modules/web-control-center/src/main/js/config/default.json +++ b/modules/web-control-center/src/main/js/config/default.json @@@ -1,0 -1,8 +1,17 @@@ + { + "express": { + "port": 3000 + }, + "mongoDB": { + "url": "mongodb://localhost/web-control-center" ++ }, ++ "monitor": { ++ "server": { ++ "port": 3001, ++ "ssl": true, ++ "key": "keys/test.key", ++ "cert": "keys/test.crt", ++ "keyPassphrase": "password" ++ } + } -} ++} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/controllers/models/sql.json ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/controllers/models/sql.json index 0000000,0000000..b00e5dd new file mode 100644 --- /dev/null +++ b/modules/web-control-center/src/main/js/controllers/models/sql.json @@@ -1,0 -1,0 +1,5 @@@ ++{ ++ "screenTip": [ ++ "Execute SQL queries." ++ ] ++} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/controllers/sql-controller.js ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/controllers/sql-controller.js index 0000000,0000000..2562117 new file mode 100644 --- /dev/null +++ b/modules/web-control-center/src/main/js/controllers/sql-controller.js @@@ -1,0 -1,0 +1,60 @@@ ++/* ++ * Licensed to the Apache Software Foundation (ASF) under one or more ++ * contributor license agreements. See the NOTICE file distributed with ++ * this work for additional information regarding copyright ownership. ++ * The ASF licenses this file to You under the Apache License, Version 2.0 ++ * (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++var demoResults = [ ++ { ++ id: 256, ++ firstName: 'Ivan', ++ lastName: 'Ivanov' ++ }, ++ { ++ id: 384, ++ firstName: 'Sergey', ++ lastName: 'Petrov' ++ }, ++ { ++ id: 923, ++ firstName: 'Andrey', ++ lastName: 'Sidorov' ++ } ++]; ++ ++var demoCaches = [{_id: '1', name: 'Users', mode: 'LOCAL'}, {_id: '2', name: 'Organizations', mode: 'REPLICATED'}, {_id: '3', name: 'Cities', mode: 'PARTITIONED'}]; ++ ++controlCenterModule.controller('sqlController', ['$scope', '$http', '$common', function ($scope, $http, $common) { ++ $scope.joinTip = $common.joinTip; ++ ++ $scope.modes = [ ++ {value: 'PARTITIONED', label: 'PARTITIONED'}, ++ {value: 'REPLICATED', label: 'REPLICATED'}, ++ {value: 'LOCAL', label: 'LOCAL'} ++ ]; ++ ++ $http.get('/models/sql.json') ++ .success(function (data) { ++ $scope.screenTip = data.screenTip; ++ }) ++ .error(function (errMsg) { ++ $common.showError(errMsg); ++ }); ++ ++ $scope.query = "select u.id, u.firstName, u.lastName from User u where u.name like 'aaaa';"; ++ ++ $scope.results = demoResults; ++ ++ $scope.caches = demoCaches; ++}]); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/controllers/summary-controller.js ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/controllers/summary-controller.js index 0000000,1291683..531dc83 mode 000000,100644..100644 --- a/modules/web-control-center/src/main/js/controllers/summary-controller.js +++ b/modules/web-control-center/src/main/js/controllers/summary-controller.js @@@ -1,0 -1,164 +1,170 @@@ + /* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + controlCenterModule.controller('summaryController', ['$scope', '$http', '$common', function ($scope, $http, $common) { + $scope.joinTip = $common.joinTip; + $scope.getModel = $common.getModel; + + $scope.javaClassItems = [ + {label: 'snippet', value: false}, + {label: 'factory class', value: true} + ]; + + $scope.evictionPolicies = [ + {value: 'LRU', label: 'LRU'}, + {value: 'RND', label: 'Random'}, + {value: 'FIFO', label: 'FIFO'}, + {value: 'SORTED', label: 'Sorted'}, + {value: undefined, label: 'Not set'} + ]; + + $scope.oss = ['debian:8', 'ubuntu:14.10']; + + $scope.configServer = {javaClassServer: false, os: undefined}; + $scope.backupItem = {javaClassClient: false}; + + $http.get('/models/summary.json') + .success(function (data) { + $scope.screenTip = data.screenTip; + $scope.clientFields = data.clientFields; + }) + .error(function (errMsg) { + $common.showError(errMsg); + }); + + $scope.clusters = []; + + $scope.aceInit = function (editor) { + editor.setReadOnly(true); + editor.setOption("highlightActiveLine", false); + ++ var renderer = editor.renderer; ++ ++ renderer.setHighlightGutterLine(false); ++ renderer.setShowPrintMargin(false); ++ renderer.setOption('fontSize', '14px'); ++ + editor.setTheme('ace/theme/chrome'); + }; + + $scope.reloadServer = function () { + $scope.javaServer = $scope.configServer.javaClassServer ? $scope.configServer.javaClass : $scope.configServer.javaSnippet; + + if ($scope.configServer.docker) { + var os = $scope.configServer.os ? $scope.configServer.os : $scope.oss[0]; + + $scope.dockerServer = $scope.configServer.docker.replace(new RegExp('\%OS\%', 'g'), os); + } + }; + + $scope.selectItem = function (cluster) { + if (!cluster) + return; + + $scope.selectedItem = cluster; + + $scope.$watch('javaClassServer', $scope.reloadServer); + $scope.$watch('os', $scope.reloadServer); + + $scope.generateServer(cluster); + + $scope.reloadServer(); + + $scope.$watch('configServer', function () { + $scope.reloadServer(); + }, true); + + $scope.$watch('backupItem', function () { + $scope.generateClient(); + }, true); + }; + + $scope.generateServer = function (cluster) { + $http.post('summary/generator', {_id: cluster._id}) + .success(function (data) { + $scope.xmlServer = data.xmlServer; + + $scope.configServer.javaClass = data.javaClassServer; + $scope.configServer.javaSnippet = data.javaSnippetServer; + $scope.configServer.docker = data.docker; + }).error(function (errMsg) { + $common.showError('Failed to generate config: ' + errMsg); + }); + }; + + $scope.generateClient = function () { + $http.post('summary/generator', { + _id: $scope.selectedItem._id, javaClass: $scope.backupItem.javaClassClient, + clientNearConfiguration: $scope.backupItem.nearConfiguration + }) + .success(function (data) { + $scope.xmlClient = data.xmlClient; + $scope.javaClient = data.javaClient; + }).error(function (errMsg) { + $common.showError('Failed to generate config: ' + errMsg); + }); + }; + + $scope.download = function () { + $http.post('summary/download', {_id: $scope.selectedItem._id, javaClass: $scope.javaClass, os: $scope.os}) + .success(function (data) { + var file = document.createElement('a'); + + file.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + data); + file.setAttribute('download', $scope.selectedItem.name + '-configuration.zip'); + + file.style.display = 'none'; + + document.body.appendChild(file); + + file.click(); + + document.body.removeChild(file); + }) + .error(function (errMsg) { + $common.showError('Failed to generate zip: ' + errMsg); + }); + }; + + $http.post('clusters/list').success(function (data) { + $scope.clusters = data.clusters; + + if ($scope.clusters.length > 0) { + var restoredId = sessionStorage.summarySelectedId; + + var selectIdx = 0; + + if (restoredId) { + var idx = _.findIndex($scope.clusters, function (cluster) { + return cluster._id == restoredId; + }); + + if (idx >= 0) + selectIdx = idx; + else + delete sessionStorage.summarySelectedId; + } + + $scope.selectItem($scope.clusters[selectIdx]); + + $scope.$watch('selectedItem', function (val) { + if (val) + sessionStorage.summarySelectedId = val._id; + }, true); + } + }); + }]); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/keys/test.crt ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/keys/test.crt index 0000000,0000000..50c6d5c new file mode 100644 --- /dev/null +++ b/modules/web-control-center/src/main/js/keys/test.crt @@@ -1,0 -1,0 +1,13 @@@ ++-----BEGIN CERTIFICATE----- ++MIIB6zCCAVQCCQDcAphbU6UcLjANBgkqhkiG9w0BAQsFADA6MRIwEAYDVQQDDAls ++b2NhbGhvc3QxJDAiBgkqhkiG9w0BCQEWFXNldmRva2ltb3ZAYXBhY2hlLm9yZzAe ++Fw0xNTA3MTQxMzAyNTNaFw0xODA2MjMxMzAyNTNaMDoxEjAQBgNVBAMMCWxvY2Fs ++aG9zdDEkMCIGCSqGSIb3DQEJARYVc2V2ZG9raW1vdkBhcGFjaGUub3JnMIGfMA0G ++CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDP/zpJrdHqCj6lPpeFF6LQtzKef6UiyBBo ++rbuOtCCgW8KMJJciluBWk2126qLt9smBN4jBpSNU3pq0r9gBMUTd/LSe7aY4D5ED ++Pjp7XsypNVKeHaHbFi7KhfHy0LYxsWiNPmmHJv4dtYOp+pGK25rkXNfyJxxjgxN6 ++wo34+MnZIQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAFk9XEjcdyihws+fVmdGGUFo ++bVxI9YGH6agiNbU3WNF4B4VRzcPPW8z2mEo7eF9kgYmq/YzH4T8tgi/qkL/u8eZV ++Wmi9bg6RThLN6/hj3wVoOFKykbDQ05FFdhIJXN5UOjPmxYM97EKqg6J0W2HAb8SG +++UekPnmAo/2HTKsLykH8 ++-----END CERTIFICATE----- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/keys/test.key ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/keys/test.key index 0000000,0000000..1b395c0 new file mode 100644 --- /dev/null +++ b/modules/web-control-center/src/main/js/keys/test.key @@@ -1,0 -1,0 +1,18 @@@ ++-----BEGIN RSA PRIVATE KEY----- ++Proc-Type: 4,ENCRYPTED ++DEK-Info: DES-EDE3-CBC,6798185330CE2EE2 ++ ++sOwkmD8rvjx11l09V26dJhLhl+SyPIhyeZ3TqHXrYCATKoXlzidT+uPu1jVYtrwr ++nBLA6TrIDYRrBNlEsqGZ0cSvWTIczzVW1xZKHEJo5q2vUT/W8u/Q1QQtS3P3GeKF ++dEzx496rpZqwwVw59GNbuIwyYoVvQf3iEXzfhplGmLPELYIplDFOLgNuXQyXSGx6 ++rwKsCxXMLsDyrA6DCz0Odf08p2HvWk/s5Ne3DFcQlqRNtIrBVGD2O0/Fp8ZZ2I4E ++Yn2OIIWJff3HanOjLOWKdN8YAn5UleNmlEUdIHeS5qaQ68mabOxLkSef9qglV+sd ++FHTtUq0cG6t6nhxZBziexha6v1yl/xABAHHhNPOfak+HthWxRD4N9f1yFYAeTmkn ++4kwBWoSUe12XRf2pGNqhEUKN/KhDmWk85wI55i/Cu2XmNoiBFlS9BXrRYU8uVCJw ++KlxjKTDWl1opCyvxTDxJnMkt44ZT445LRePKVueGIIKSUIXNQypOE+C1I0CL0N2W ++Ts3m9nthquvLeMx92k7b8yW69BER5uac3SIlGCOJObQXsHgyk8wYiyd/zLKfjctG ++PXieaW81UKjp+GqWpvWPz3VqnKwoyUWeVOOTviurli6kYOrHuySTMqMb6hxJctw9 ++grAQTT0UPiAKWcM7InLzZnRjco+v9QLLEokjVngXPba16K/CItFY16xuGlaFLW7Y ++XTc67AkL8b76HBZelMjmCsqjvSoULhuMFwTOvUMm/mSM8rMoi9asrJRLQHRMWCST ++/6RENPLzPlOMnNLBujpBbn8V3/aYzEZsHMI+6S3d27WYlTJIqpabSA== ++-----END RSA PRIVATE KEY----- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/package.json ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/package.json index 0000000,5e5463c..477266a mode 000000,100644..100644 --- a/modules/web-control-center/src/main/js/package.json +++ b/modules/web-control-center/src/main/js/package.json @@@ -1,0 -1,50 +1,51 @@@ + { + "name": "ignite-web-control-center", + "version": "1.0.0", + "description": "Web application for configuration, monitoring Ignite Cluster", + "private": true, + "scripts": { + "start": "node ./bin/www" + }, + "author": "", + "contributors": [ + { + "name": "", + "email": "" + } + ], + "license": "Apache-2.0", + "keywords": "grid", + "homepage": "https://ignite.incubator.apache.org/", + "engines": { + "node": ">=0.12.4" + }, + "dependencies": { + "angular-ui-ace": "^0.2.3", + "archiver": "^0.14.4", + "body-parser": "~1.12.0", + "connect-flash": "^0.1.1", + "connect-mongo": "^0.8.1", + "cookie-parser": "~1.3.4", + "debug": "~2.1.1", + "express": "~4.12.2", + "express-session": "^1.11.1", + "jade": "~1.9.2", + "less-middleware": "1.0.x", + "lodash": "3.10.0", + "mongoose": "^4.0.2", + "nconf": "^0.7.1", + "passport": "^0.2.1", + "passport-local": "^1.0.0", + "passport-local-mongoose": "^1.0.0", + "pg": "^4.4.0", + "serve-favicon": "~2.2.0", - "util": "^0.10.3" ++ "util": "^0.10.3", ++ "ws": "~0.7.2" + }, + "devDependencies": { + "morgan": "~1.5.1", + "supertest": "^1.0.1", + "mocha": "~2.0.1", + "should": "~3.1.3" + } + } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/public/stylesheets/style.less ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/public/stylesheets/style.less index 0000000,e05f0ff..3d0ede7 mode 000000,100644..100644 --- a/modules/web-control-center/src/main/js/public/stylesheets/style.less +++ b/modules/web-control-center/src/main/js/public/stylesheets/style.less @@@ -1,0 -1,1182 +1,1193 @@@ + /* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + @logo-path: "https://www.filepicker.io/api/file/QagunjDGRFul2JgNCAli"; + @input-height: 28px; + @ignite-red: #ec1c24; + @ignite-block-callout-background: #f3f8f3; + @ignite-block-callout: #50af51; + + hr { + margin-top: 20px; + margin-bottom: 20px; + } + + .main-header .logo { + height: auto; + } + + .main-sidebar { + padding-top: 60px; + } + + .navbar-default .navbar-brand, .navbar-default .navbar-brand:hover { + position: absolute; + width: 100%; + left: 0; + text-align: center; + } + + .modal-backdrop.am-fade { + opacity: .5; + transition: opacity .15s linear; + &.ng-enter { + opacity: 0; + &.ng-enter-active { + opacity: .5; + } + } + &.ng-leave { + opacity: .5; + &.ng-leave-active { + opacity: 0; + } + } + } + + .modal.center .modal-dialog { + position: fixed; + top: 50%; + left: 50%; + -webkit-transform: translateX(-50%) translateY(-50%); + transform: translateX(-50%) translateY(-50%); + } + + .border-left { + box-shadow: 1px 0 0 0 #eee inset; + } + + .border-right { + box-shadow: 1px 0 0 0 #eee; + } + + .theme-line { + background-color: #f9f9f9; + } + + .theme-line header { + background-color: #fff; + } + + .theme-line header a.btn { + border: 0 none; + padding: 10px 25px; + background-color: rgba(0, 0, 0, 0.15); + } + + .theme-line header a.btn:hover { + background-color: rgba(0, 0, 0, 0.25); + } + + .theme-line header a.btn.btn-link { + background: transparent; + color: rgba(255, 255, 255, 0.8); + } + + .theme-line header a.btn.btn-link:hover { + color: #fff; + text-decoration: none; + } + + .theme-line .navbar-nav a { + background-color: transparent; + } + + .theme-line .navbar-nav a:hover, + .theme-line .navbar-nav a:active, + .theme-line .navbar-nav a:focus { + background-color: transparent; + } + + .theme-line .main-links { + padding-top: 50px; + } + + .theme-line .main-links h3 { + margin-top: 0; + font-size: 17px; + } + + .theme-line .main-links .links a { + color: #888; + } + + .theme-line .main-links .links a:hover { + text-decoration: none; + } + + .theme-line #category-columns, + .theme-solid #category-columns { + margin: 50px 30px 0; + } + + .theme-line #category-columns h4 { + text-transform: uppercase; + font-weight: 300; + color: #999; + font-size: 14px; + } + + .theme-line #category-columns ul { + list-style: none; + padding: 0; + margin-bottom: 15px; + } + + .theme-line #category-columns ul li a { + padding: 5px 0; + display: block; + font-size: 16px; + } + + .theme-line #category-columns ul .view-all { + font-size: 0.85em; + } + + .theme-line .docs-header { + color: #999; + overflow: hidden; + } + + .theme-line .docs-header h1 { + color: #444; + margin-top: 0; + font-size: 22px; + } + + .theme-line .btn-primary { + border: 0 none; + background-color: @ignite-red; + } + + .theme-line .btn-primary:hover { + background-color: #950d12; + } + + .theme-line .main-content .nav-horizontal a { + box-shadow: 0 0; + border: 0 none; + background-color: #fff; + border-radius: 0; + color: #aaa; + padding: 6px; + margin: 0 14px; + } + + .theme-line .main-content .nav-horizontal a:hover { + color: #999; + border-bottom: 5px solid #ddd; + } + + .theme-line .main-content .nav-horizontal a.active { + border-bottom: 5px solid #888; + } + + .theme-line .navbar-nav, .theme-line .sidebar-nav { + ul li > a.active { + cursor: default; + pointer-events: none; + } + } + + .theme-line .sidebar-nav { + color: #474a54; + padding-bottom: 30px; + + ul { + padding: 0; + list-style: none; + font-size: 14px; + margin: 3px 0 0; + li { + color: #666; + line-height: @input-height; + + span.fa-stack { + margin-right: 5px; + font-size: 12px; + height: 26px; + } + + a { + font-size: 18px; + color: #666; + position: relative; + white-space: nowrap; + overflow: hidden; + -o-text-overflow: ellipsis; + text-overflow: ellipsis; + } + } + } + } + + .theme-line .sidebar-nav ul li a:hover { + text-decoration: none; + } + + .theme-line .select, + .theme-line .typeahead { + li a { + color: #666; + background-color: transparent; + } + + li a:hover { + color: @ignite-red; + } + + .active { + background-color: #eee; + } + } + + .theme-line .sidebar-nav ul li .subcategory { + padding-left: 15px; + } + + .theme-line .sidebar-nav h4 { + margin-top: 2em; + font-weight: normal; + text-transform: uppercase; + font-size: 11px; + margin-bottom: 10px; + color: #bbb; + } + + .theme-line .sidebar-nav h4:first-child { + margin-top: 0; + } + + .theme-line .sidebar-nav .ask { + width: 100%; + text-align: center; + padding: 10px; + } + + .theme-line .border-left .sidebar-nav { + padding-left: 15px; + } + + .theme-line .suggest { + padding: 5px; + display: inline-block; + font-size: 12px; + } + + .header { + padding: 15px; + } + + .header .has-github { + padding-right: 136px; + } + + .header h1.navbar-brand { + height: 40px; + width: 200px; + padding: 0; + margin: 5px 15px 0 0; + } + + .header h1.navbar-brand a { + text-indent: -99999px; + background: no-repeat center center; + display: block; + width: 100%; + height: 100%; + background-size: contain; + } + + .header .nav.navbar-nav.pull-right { + position: relative; + right: -30px; + } + + .header .nav.navbar-nav .not-link { + padding: 15px; + display: inline-block; + } + + .header .nav.navbar-nav .stable, + .header .nav.navbar-nav .beta, + .header .nav.navbar-nav .private { + font-size: 9px; + padding: 3px 5px; + display: inline-block; + line-height: 8px; + border-radius: 3px; + margin-left: 6px; + color: #fff; + top: -2px; + position: relative; + opacity: 0.6; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; + filter: alpha(opacity=60); + } + + .header .nav.navbar-nav a:hover > .stable, + .header .nav.navbar-nav a:hover > .beta, + .header .nav.navbar-nav a:hover > .private { + opacity: 1; + -ms-filter: none; + filter: none; + } + + .header .nav.navbar-nav .beta { + background-color: #59c3d1; + } + + .header .nav.navbar-nav .stable { + background-color: #41b841; + } + + .header .nav.navbar-nav .private { + background-color: #333; + } + + .theme-line header { + border-bottom: 8px solid; + } + + .theme-line header h2 { + color: #aaa; + } + + .theme-line header p { + color: #666; + } + + .theme-line header { + border-bottom-color: @ignite-red; + } + + .theme-line .navbar-nav { + color: #888; + } + + .theme-line .navbar-nav a { + color: #bbb; + } + + .theme-line header a.btn { + background-color: @ignite-red; + } + + .theme-line header a.btn:hover { + background-color: #950d12; + } + + .theme-line header .navbar-nav .tt-cursor { + background-color: @ignite-red; + } + + .theme-line header .navbar-nav a:hover, .theme-line header .navbar-nav .open > a { + color: @ignite-red; + } + + .theme-line .navbar-nav .active a { + //font-weight: bold; + color: @ignite-red; + } + + .theme-line .navbar-nav .active a:hover { + color: #950d12; + } + + .theme-line .main-links .links a:hover { + color: @ignite-red; + } + + .theme-line .main-content a { + color: #666; + } + + .theme-line .main-content a:hover { + color: #950d12; + } + + .theme-line .sidebar-nav ul li a.active:before { + background-color: @ignite-red; + } + + .theme-line .sidebar-nav ul li a.active { + color: @ignite-red; + } + + .theme-line .sidebar-nav ul li a:hover, .theme-line .sidebar-nav ul li a.active:hover { + color: #950d12; + } + + .theme-line .main-content .nav-horizontal a.active { + border-color: @ignite-red; + color: @ignite-red; + } + + .theme-line .main-content .nav-horizontal a:hover { + color: #950d12; + } + + .theme-line .main-content .nav-horizontal a.active:hover { + border-color: #950d12; + } + + .theme-line header .navbar-nav a.active, .theme-line #versions-list li a:hover strong, .theme-line #versions-list li a.active .current, .theme-line #versions-list li a:active .current { + color: @ignite-red; + } + + .theme-line header .navbar-nav a { + font-size: 18px; + } + + .theme-line.body-threes .section-right .threes-nav .btn-default:hover, .theme-line.page-docs.body-threes .section-right .threes-nav .pull-right a:hover { + color: @ignite-red; + border-color: @ignite-red; + } + + .theme-line .section-right { + padding-left: 30px; + } + + .body-overlap .main-content { + margin-top: 30px; + } + + .body-box .main-content, + .body-overlap .main-content { + padding: 30px; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); + background-color: #fff; + } + + body { + font-weight: 400; + font-family: Roboto Slab, serif;; + } + + h1, h2, h3, h4, h5, h6 { + font-weight: 700; + font-family: Roboto Slab, serif; + margin-bottom: 10px; + } + + .submit-vote.submit-vote-parent.voted a.submit-vote-button, .submit-vote.submit-vote-parent a.submit-vote-button:hover { + background-color: @ignite-red; + } + + div.submit-vote.submit-vote-parent.voted a.submit-vote-button:hover { + background-color: #950d12; + } + + a, .link .title { + color: @ignite-red; + } + + a:hover, .link:hover .title { + color: #950d12; + } + + .header h1.navbar-brand a { + background-image: url("@{logo-path}"); + } + + .header h1.navbar-brand { + width: 96px; + } + + .block-edit-parameters { + text-align: right; + padding-bottom: 5px; + } + + .container-footer { + margin-top: 20px; + } + + /* Modal */ + .modal { + display: block; + overflow: hidden; + } + + .modal .close { + position: absolute; + top: 10px; + right: 10px; + float: none; + } + + // Close icon + .modal-header .close { + margin-right: -2px; + } + + .modal .modal-dialog { + width: 610px; + } + + .modal .modal-content { + border-radius: 0; + background-color: #f7f7f7; + } + + .modal .modal-content .modal-header { + background-color: #fff; + text-align: center; + color: #555; + padding: 15px; + font-family: "myriad-pro", sans-serif; + } + + .modal .modal-content .modal-header h4 { + font-family: "myriad-pro", sans-serif; + font-size: 22px; + } + + .modal .modal-content .modal-header h4 .fa { + display: block; + font-size: 41px; + color: #ddd; + margin-bottom: 5px; + } + + .modal .modal-content .modal-header p { + color: #aaa; + font-size: 1em; + margin: 3px 0 0; + } + + .modal .modal-content .modal-spacer { + padding: 10px 10px 0 10px; + } + + .modal .modal-content .modal-footer { + margin-top: 0; + } + + .modal-body { + padding-top: 15px; + } + + h1.ignite-logo { + background-image: url("@{logo-path}"); + } + + .block-display-image img { + max-width: 100%; + max-height: 450px; + margin: auto; + display: block; + } + + .greedy { - min-height: 200px; ++ min-height: 100%; + height: ~"calc(100vh - 290px)"; + } + + @media (min-width: 768px) { + .navbar-nav > li > a { + padding-top: 18px; + padding-bottom: 10px; + } + } + + .details-row { + padding: 0 10px; + } + + .details-row, .settings-row { + display: block; + margin: 10px 0; + + label.table-header { + line-height: @input-height; + } + + [class*="col-"] { + display: inline-block; + vertical-align: middle; + float: none; + + padding-left: 0 !important; + padding-right: 0 !important; + } + + input[type="checkbox"] { + line-height: 20px; + margin-right: 5px; + } + + .checkbox label { + line-height: 20px; + vertical-align: middle; + } + } + + button { + margin-right: 5px; + } + + h1, + h2, + h3 { + user-select: none; + font-weight: normal; + /* Makes the vertical size of the text the same for all fonts. */ + line-height: 1; + } + + h3 { + color: black; + font-size: 1.2em; + margin-top: 0; + margin-bottom: 1.5em; + } + + table tr:hover { + cursor: pointer; + } + + .btn { + padding: 3px 6px; + } + + button .caret, .btn .caret { + float: right; + margin-left: 5px; + margin-top: 7px; + } + + .base-control { + text-align: left; + padding: 3px 3px; + height: @input-height; + } + + .form-control:extend(.base-control all) { + display: inline-block; + + button { + text-align: left; + } + } + + .theme-line .panel-heading { + padding: 10px 10px; + margin: 0; + + h3 { + margin-bottom: 0; + } + + h3 > a { + color: black; + } + } + + .theme-line .panel-title { + a { + color: @ignite-red; + } + + h3 { + margin-bottom: 20px; + } + } + + .theme-line .panel-body { + padding: 10px 20px; + } + + .theme-line .main-content a.customize { + margin-left: 5px; + color: @ignite-red; + } + + .theme-line .panel-collapse { + margin: 0; + } + + .theme-line .links table { + display: table; + table-layout: fixed; + + td { + padding-left: 18px; + } + + .active a { + color: @ignite-red; + font-weight: bold; + } + + a:hover { + color: #950d12; + } + + a { + color: #666; + } + } + + .theme-line table.links-edit:extend(.theme-line .links table all) { + margin-top: 5px; + margin-bottom: 5px; + + label { + line-height: @input-height; + color: #666; + } + } + + .theme-line table.links-edit-details:extend(.theme-line .links table all) { + margin-bottom: 10px; + + label { + line-height: @input-height; + color: #666; + } + + td { + padding: 0; + + .input-tip { + padding: 0; + } + } + } + + .theme-line table.admin { + tr:hover { + cursor: default; + } + + thead > tr th.header { + padding: 0 0 10px; + + div { + padding: 0 + } + } + + margin-bottom: 10px; + + label { + line-height: @input-height; + color: #666; + } + + thead > tr th, td { + padding: 10px 10px; + + .input-tip { + padding: 0; + } + } + + tfoot > tr > td { + padding: 0; + + .pagination { + margin: 10px 0; + + > .active > a { + color: @ignite-red; + font-weight: bold; + border-color: #ddd; + background-color: #eee; + } + } + } + } + + .panel-title a { + font-size: 14px; + } + + .panel-details { + margin-top: 10px; + + padding: 0; + + border-radius: 5px; + border: thin dotted lightgrey; + } + + .table-details { + border-radius: 5px; + border: thin dotted lightgrey; + + margin-top: 10px; + + padding-left: 10px; + padding-right: 5px; + } + + .tooltip.right .tooltip-arrow { + border-right-color: @ignite-red; + } + + .tooltip > .tooltip-inner { + max-width: 400px; + text-align: left; + background-color: @ignite-red; + } + + label { + font-weight: normal; + margin-bottom: 0; + } + + .form-horizontal .checkbox { + padding-top: 0; + } + + .input-tip { + display: block; + overflow: hidden; + } + + .labelField { + float: left; + margin-right: 5px; + } + + .labelFormField { + float: left; + line-height: @input-height; + } + + .form-horizontal .form-group { + margin: 0; + } + + .form-horizontal .has-feedback .form-control-feedback { + right: 0; + } + + .tipField { + float: right; + line-height: @input-height; + margin-left: 5px; + } + + .tipLabel { + font-size: 14px; + margin-left: 5px; + } + + .fieldSep { + float: right; + line-height: @input-height; + margin: 0 5px; + } + + .fieldButton { + float: right; + margin-left: 5px; + margin-right: 0; + } + + .fa-plus { + cursor: pointer; + } + + .fa-remove { + color: @ignite-red; + cursor: pointer; + } + + .fa-floppy-o { + cursor: pointer; + } + + .fa-arrow-up { + cursor: pointer; + } + + .fa-arrow-down { + cursor: pointer; + } + + label.required:after { + color: @ignite-red; + content: ' *'; + display: inline; + } + + .blank { + visibility: hidden; + } + + .alert { + outline: 0 + } + + .alert.bottom, .alert.bottom-left, .alert.bottom-right, .alert.top, + .alert.top-left, .alert.top-right { + position: fixed; + z-index: 1050; + margin: 20px + } + + .alert.top, .alert.top-left, .alert.top-right { + top: 50px + } + + .alert.top { + right: 0; + left: 0 + } + + .alert.top-right { + right: 0 + } + + .alert.top-right .close { + padding-left: 10px + } + + .alert.top-left { + left: 0 + } + + .alert.top-left .close { + padding-right: 10px + } + + .alert.bottom, .alert.bottom-left, .alert.bottom-right { + bottom: 0 + } + + .alert.bottom { + right: 0; + left: 0 + } + + .alert.bottom-right { + right: 0 + } + + .alert.bottom-right .close { + padding-left: 10px + } + + .alert.bottom-left { + left: 0 + } + + .alert.bottom-left .close { + padding-right: 10px + } + + // Summary page + #cfgResult textarea { + font-family: monospace; + font-size: 12px; + } + + input[type="number"]::-webkit-outer-spin-button, + input[type="number"]::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } + + input[type="number"] { + -moz-appearance: textfield; + } + + input.ng-dirty.ng-invalid, button.ng-dirty.ng-invalid { + border-color: @ignite-red; + + :focus { + border-color: @ignite-red; + } + } + + .form-control-feedback { + display: inline-block; + color: @ignite-red; + right: 18px; + line-height: @input-height; + pointer-events: initial; + } + + .syntaxhighlighter { + padding: 10px 5px; + border-radius: 6px; + } + + .theme-line table.links-edit-small-padding:extend(.theme-line .links table all) { + label { + line-height: @input-height; + color: #666; + } + + a { + line-height: @input-height; + } + + input[type="checkbox"] { + line-height: 20px; + margin-right: 5px; + } + + .checkbox label { + line-height: 20px; + vertical-align: middle; + } + + th { + text-align: center; + } + + td { + padding-left: 10px; + } + + margin-top: 10px; + } + -.configBox .nav > li > a { ++.nav-tabs > li > a { + padding: 5px 5px; + } + + .viewedUser { + position: absolute; + width: 100%; + left: 0; + + text-align: center; + + margin-top: -15px; + + background-color: #f8d5d8; + } + + a { + cursor: pointer; + } + + .st-sort-ascent:after { + content: '\25B2'; + } + + .st-sort-descent:after { + content: '\25BC'; + } + + .panel { + margin-bottom: 0; + } + + .panel-group { + margin-bottom: 0; + } + + .panel-group .panel + .panel { + margin-top: 20px; + } + + .margin-top-dflt { + margin-top: 10px; + } + + .margin-bottom-dflt { + margin-bottom: 10px; + } + + .margin-dflt { + margin-top: 10px; + margin-bottom: 10px; + } + + .padding-top-dflt { + padding-top: 10px; + } + + .padding-bottom-dflt { + padding-bottom: 10px; + } + + .padding-dflt { + padding-top: 10px; + padding-bottom: 10px; + } + + .theme-line .panel-title h3 { + margin-top: 20px; + margin-bottom: 20px; + } + + .block-callout-parent { + background-color: @ignite-block-callout-background; + overflow: hidden; + } + + .block-callout { + background-color: @ignite-block-callout-background; + display: inline-block; + vertical-align: top; + width: 50%; + + i { + padding: 10px 5px 0 10px; + color: @ignite-block-callout; + } + + ul { + padding-left: 20px; + margin-bottom: 0; + } + + p { + padding: 5px 0 10px 20px; + margin: 0; + } + + label { + font-weight: bold; + color: @ignite-block-callout; + } + } + + .block-callout-border { + border-left: 5px solid; + border-color: @ignite-block-callout; + } + + .labelHeader { + font-weight: bold; + } + + .ace_editor, #ace_document { ++ margin: 0.65em 0 0 0; ++ + width: 100%; + height: 400px; -} + ++ .ace_gutter { ++ background: transparent !important; ++ border: 1px #ddd; ++ border-right-style: solid; ++ } + ++ .ace_gutter-cell, .ace_folding-enabled > .ace_gutter-cell { ++ padding-left: 0.65em; ++ padding-right: 0.9em; ++ } ++} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/routes/agent.js ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/routes/agent.js index 0000000,0000000..19379e2 new file mode 100644 --- /dev/null +++ b/modules/web-control-center/src/main/js/routes/agent.js @@@ -1,0 -1,0 +1,37 @@@ ++/* ++ * Licensed to the Apache Software Foundation (ASF) under one or more ++ * contributor license agreements. See the NOTICE file distributed with ++ * this work for additional information regarding copyright ownership. ++ * The ASF licenses this file to You under the Apache License, Version 2.0 ++ * (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++var router = require('express').Router(); ++var agentManager = require('../agents/agent-manager'); ++ ++/* GET summary page. */ ++router.post('/topology', function(req, res) { ++ var c = agentManager.getAgentManager().getOneClient(); ++ ++ if (!c) ++ return res.status(500).send("Client not found"); ++ ++ var ignite = c.ignite(); ++ ++ ignite.cluster().then(function (cluster) { ++ res.json(cluster); ++ }, function (err) { ++ res.send(err); ++ }); ++}); ++ ++module.exports = router; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/views/configuration/summary.jade ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/views/configuration/summary.jade index 0000000,6f2f6d8..0370ef4 mode 000000,100644..100644 --- a/modules/web-control-center/src/main/js/views/configuration/summary.jade +++ b/modules/web-control-center/src/main/js/views/configuration/summary.jade @@@ -1,0 -1,117 +1,115 @@@ + //- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + extends sidebar + + append scripts + script(src='/summary-controller.js') + + script(src="//cdn.jsdelivr.net/angularjs/1.3.15/angular-animate.min.js") + script(src="//cdn.jsdelivr.net/angularjs/1.3.15/angular-sanitize.min.js") + + script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/theme-chrome.js') + script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-xml.js') + script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-java.js') + script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-dockerfile.js') + + append css + + include ../includes/controls + + mixin hard-link(ref, txt) + a(style='color:#ec1c24' href=ref target="_blank") #{txt} + + block content + .docs-header + h1 Configurations Summary + hr + .docs-body(ng-controller='summaryController') + +block-callout('{{screenTip.workflowTitle}}', 'joinTip(screenTip.workflowContent)', '{{screenTip.whatsNextTitle}}', 'joinTip(screenTip.whatsNextContent)') + .padding-dflt(ng-if='clusters.length == 0') + | No cluster configured. You can + 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') ++ div(ng-show='selectedItem' bs-tabs style='margin-top: 0.65em') ++ div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane) ++ div(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlServer') ++ div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane) ++ .details-row ++ .col-sm-1 ++ label Generate: ++ .col-sm-3 ++ button.form-control(type='button' ng-model='configServer.javaClassServer' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false') ++ div(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaServer') ++ div(title='<img src="/images/docker.png" width="16px" height="16px"/> Dockerfile' bs-pane) ++ .details-row ++ p ++ +hard-link('https://docs.docker.com/reference/builder', 'Docker') ++ | 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') ++ div(ng-show='selectedItem') ++ .details-row(ng-repeat='field in clientFields') ++ +form-row-custom(['col-sm-3'], ['col-sm-3']) ++ div(bs-tabs style='margin-top: 0.65em') ++ div(title='<img src="/images/xml.png" width="16px" height="16px"/> XML' bs-pane) ++ div(ui-ace='{ onLoad: aceInit, mode: "xml" }' ng-model='xmlClient') ++ div(title='<img src="/images/java.png" width="16px" height="16px"/> Java' bs-pane) ++ .details-row ++ .col-sm-1 ++ label Generate: ++ .col-sm-4 ++ button.form-control(type='button' ng-model='backupItem.javaClassClient' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false') ++ div(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaClient') http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/views/includes/header.jade ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/views/includes/header.jade index 0000000,ab2d31e..bfd5275 mode 000000,100644..100644 --- a/modules/web-control-center/src/main/js/views/includes/header.jade +++ b/modules/web-control-center/src/main/js/views/includes/header.jade @@@ -1,0 -1,39 +1,39 @@@ + //- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + mixin header-item(active, ref, txt) + li + a(ng-class='{active: isActive("#{active}")}' href='#{ref}') #{txt} + + header.header(id='header') + .viewedUser(ng-show='becomeUsed') Currently assuming " + strong {{user.username}} + | ", + a(href='/admin/become') revert to your identity. + .container + h1.navbar-brand + a(href='/') Apache Ignite Web Configurator + .navbar-collapse.collapse(ng-controller='auth') + ul.nav.navbar-nav(ng-controller='activeLink' ng-show='user') + +header-item('/configuration', '/configuration/clusters', 'Configuration') + //+header-item('/monitoring', '/monitoring', 'Monitoring') - //+header-item('/sql', '/sql', 'SQL') ++ +header-item('/sql', '/sql', 'SQL') + //+header-item('/deploy', '/deploy', 'Deploy') + ul.nav.navbar-nav.pull-right + li(ng-if='user') + a.dropdown-toggle(data-toggle='dropdown' bs-dropdown='userDropdown' data-placement='bottom-right') {{user.username}} + span.caret + li.nav-login(ng-if='!user') + a(ng-click='login()' href='#') Log In http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/views/sql.jade ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/views/sql.jade index 0000000,0000000..9ba3056 new file mode 100644 --- /dev/null +++ b/modules/web-control-center/src/main/js/views/sql.jade @@@ -1,0 -1,0 +1,70 @@@ ++//- ++ Licensed to the Apache Software Foundation (ASF) under one or more ++ contributor license agreements. See the NOTICE file distributed with ++ this work for additional information regarding copyright ownership. ++ The ASF licenses this file to You under the Apache License, Version 2.0 ++ (the "License"); you may not use this file except in compliance with ++ the License. You may obtain a copy of the License at ++ http://www.apache.org/licenses/LICENSE-2.0 ++ Unless required by applicable law or agreed to in writing, software ++ distributed under the License is distributed on an "AS IS" BASIS, ++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ See the License for the specific language governing permissions and ++ limitations under the License. ++extends ../templates/layout ++ ++append scripts ++ script(src='/sql-controller.js') ++ ++ script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/theme-chrome.js') ++ script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-sql.js') ++ script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ext-language_tools.js') ++ ++block container ++ .row ++ .col-sm-12 ++ .docs-content ++ .docs-header ++ h1 Connect to Ignite and execute SQL queries ++ hr ++ .docs-body(ng-controller='sqlController') ++ .block-callout ++ p(ng-bind-html='joinTip(screenTip)') ++ .tabs-below(bs-tabs bs-active-pane='tabs.activeTab') ++ div(title='Query #1' bs-pane) ++ .row ++ .col-sm-9 ++ div(style='height: 200px' ui-ace='{ theme: "chrome", mode: "sql",' + ++ 'require: ["ace/ext/language_tools"],' + ++ 'rendererOptions: {showPrintMargin: false, highlightGutterLine: false, fontSize: 14},' + ++ 'advanced: {enableSnippets: false, enableBasicAutocompletion: true, enableLiveAutocompletion: true}}' ng-model='query') ++ .col-sm-3 ++ .links(ng-hide='caches.length == 0' style='margin-top: 0.65em') ++ lable.labelHeader Caches: ++ table(st-table='caches') ++ tbody ++ tr(ng-repeat='row in caches track by row._id') ++ td.col-sm-6(ng-class='{active: row._id == selectedItem._id}') ++ a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}} ++ div(title='Query #2' bs-pane) ++ .row ++ .settings-row ++ button.btn.btn-primary(ng-click='') Explain ++ button.btn.btn-primary(ng-click='') Execute ++ button.btn.btn-primary(ng-click='' disabled) Scan ++ //#resultPanel ++ // strong Results ++ // ++ // #queryResult ++ // div(ng-repeat='r in results') ++ // .resultRow ++ // | {{r.id}} -> {{r.s}} ++ // span.props {{r.fields}} ++ ++ div(ng-hide='results.length == 0' style='margin-top: 0.65em') ++ lable.labelHeader Results: ++ table.table-bordered(st-table='results') ++ tbody ++ tr(ng-repeat='row in results') ++ td ++ a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/views/templates/layout.jade ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/views/templates/layout.jade index 0000000,a4191ae..8fbcd7e mode 000000,100644..100644 --- a/modules/web-control-center/src/main/js/views/templates/layout.jade +++ b/modules/web-control-center/src/main/js/views/templates/layout.jade @@@ -1,0 -1,61 +1,61 @@@ + //- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + doctype html + html(ng-app='ignite-web-control-center', ng-init='user = #{JSON.stringify(user)}; becomeUsed = #{becomeUsed}') + head + title= title + + block css + // Bootstrap + link(rel='stylesheet', href='//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.css') + + // Font Awesome Icons + link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.css') + + // Font + link(rel='stylesheet', href='//fonts.googleapis.com/css?family=Roboto+Slab:700:serif|Roboto+Slab:400:serif') + + link(rel='stylesheet', href='/stylesheets/style.css') + + block scripts + script(src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js') + + script(src='//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min.js') + + script(src='//ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.js') + script(src='//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.2/angular-sanitize.js') + script(src='//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.0/angular-strap.js') + script(src='//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.0/angular-strap.tpl.min.js') + + script(src='//cdnjs.cloudflare.com/ajax/libs/angular-smart-table/2.0.3/smart-table.js') + + script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js') + script(src='//angular-ui.github.io/ui-ace/dist/ui-ace.min.js') + + script(src='/common-module.js') + script(src='/data-structures.js') + - body.theme-line.body-overlap ++ body.theme-line.body-overlap.greedy + .wrapper + include ../includes/header + + block main-container + .container.body-container + .main-content + block container + + include ../includes/footer http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/a45a700c/modules/web-control-center/src/main/js/views/templates/tab.jade ---------------------------------------------------------------------- diff --cc modules/web-control-center/src/main/js/views/templates/tab.jade index 0000000,0000000..ce62bd6 new file mode 100644 --- /dev/null +++ b/modules/web-control-center/src/main/js/views/templates/tab.jade @@@ -1,0 -1,0 +1,3 @@@ ++// ++ Created by nva on 23/07/15. ++