Removed old versions of UI in static directory.

This commit is contained in:
Chris Church
2013-05-08 12:02:56 -04:00
parent cc16c394fe
commit e5057fbd83
201 changed files with 0 additions and 88469 deletions

27
lib/ui/README.md Normal file
View File

@@ -0,0 +1,27 @@
Ansible UI
==========
The user interface to Ansible Commander
Installation
------------
To use the UI you will first need to complete the installation of Ansible Commander. Within
Ansbile Commander you should be able to start the server (make runserver) and log into the
admin console. If that all works, then you are ready to install Ansible UI.
For now the UI runs under the django server installed with Commander. If you are planning to
do development, do NOT pull a copy of UI into the same directory structure as Commander. In
other words, for development the UI should not be insalled as a subdirectory of Commander.
Once you have obtained a copy of UI, create a symbolic link within the Commander lib/static
directory that points to the app subdirectory under ansible-ui. Call the link web:
cd ~/ansible-commander/lib/static
ln -s ../../../ansible-ui/app web
With the Ansible Commander server running, you should now be able to access the UI:
http://127.0.0.1:8013/static/web/index.html
You will be immediately prompted for to log in. User your Commander superuser credientials.

6
lib/ui/TODO.md Normal file
View File

@@ -0,0 +1,6 @@
TODO
====
* mpd - figure out way to mark each object generically with whether it can be edited/administrated/etc
* mpd - enable generic filtering, look into sorting

97
lib/ui/ascii_mockups.md Normal file
View File

@@ -0,0 +1,97 @@
Mockups
=======
Goals/priority:
Organizations
Inventory
Groups
Hosts
Subgroup
Host variable
Group variable
Jobs and Job Results
Credentials
Projects
Teams
Permissions
Later/Roadmap:
Rich Editing
Just conceptual stuff prior to using Balsamiq.
Login
username:
password:
When log in, menu options:
organizations
projects
teams
credentials
Organization tab:
[if admin, plus sign for add ? ]
org1 [ if admin, delete ]
org2
org3
Organizations detail:
[ see all properties ]
[ click to edit some of them if admin ]
[ if org admin, + project to organization ]
[ + add a user ]
[ + add more admins ]
Projects details:
(projects are created from the organization detail page)
Teams:
add users / remove users
Users:
add remove/users
Credentials:
Permissions:
Jobs:
Inventory View:
| Groups
+--+ Subgroup <----------------- click on this
+----- subgroup
see hosts in group that was selected above, (directly?)
MPD: may need to add a way to see all child hosts of a given group in API
/api/v1/groups/N/all_hosts
if no group is selected, use /api/v1/hosts/
[ Group selector ] [ edit link ] [ delete link (if no kids?) ]
[ Host list ] [ edit link ] [ delete link ]
tree of list of
GROUPS | HOSTS
x | asdf
x | jkl
x | foo
x |
x |

244
lib/ui/scripts/web-server.js Executable file
View File

@@ -0,0 +1,244 @@
#!/usr/bin/env node
var util = require('util'),
http = require('http'),
fs = require('fs'),
url = require('url'),
events = require('events');
var DEFAULT_PORT = 8000;
function main(argv) {
new HttpServer({
'GET': createServlet(StaticServlet),
'HEAD': createServlet(StaticServlet)
}).start(Number(argv[2]) || DEFAULT_PORT);
}
function escapeHtml(value) {
return value.toString().
replace('<', '&lt;').
replace('>', '&gt;').
replace('"', '&quot;');
}
function createServlet(Class) {
var servlet = new Class();
return servlet.handleRequest.bind(servlet);
}
/**
* An Http server implementation that uses a map of methods to decide
* action routing.
*
* @param {Object} Map of method => Handler function
*/
function HttpServer(handlers) {
this.handlers = handlers;
this.server = http.createServer(this.handleRequest_.bind(this));
}
HttpServer.prototype.start = function(port) {
this.port = port;
this.server.listen(port);
util.puts('Http Server running at http://localhost:' + port + '/');
};
HttpServer.prototype.parseUrl_ = function(urlString) {
var parsed = url.parse(urlString);
parsed.pathname = url.resolve('/', parsed.pathname);
return url.parse(url.format(parsed), true);
};
HttpServer.prototype.handleRequest_ = function(req, res) {
var logEntry = req.method + ' ' + req.url;
if (req.headers['user-agent']) {
logEntry += ' ' + req.headers['user-agent'];
}
util.puts(logEntry);
req.url = this.parseUrl_(req.url);
var handler = this.handlers[req.method];
if (!handler) {
res.writeHead(501);
res.end();
} else {
handler.call(this, req, res);
}
};
/**
* Handles static content.
*/
function StaticServlet() {}
StaticServlet.MimeMap = {
'txt': 'text/plain',
'html': 'text/html',
'css': 'text/css',
'xml': 'application/xml',
'json': 'application/json',
'js': 'application/javascript',
'jpg': 'image/jpeg',
'jpeg': 'image/jpeg',
'gif': 'image/gif',
'png': 'image/png',
  'svg': 'image/svg+xml'
};
StaticServlet.prototype.handleRequest = function(req, res) {
var self = this;
var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){
return String.fromCharCode(parseInt(hex, 16));
});
var parts = path.split('/');
if (parts[parts.length-1].charAt(0) === '.')
return self.sendForbidden_(req, res, path);
fs.stat(path, function(err, stat) {
if (err)
return self.sendMissing_(req, res, path);
if (stat.isDirectory())
return self.sendDirectory_(req, res, path);
return self.sendFile_(req, res, path);
});
}
StaticServlet.prototype.sendError_ = function(req, res, error) {
res.writeHead(500, {
'Content-Type': 'text/html'
});
res.write('<!doctype html>\n');
res.write('<title>Internal Server Error</title>\n');
res.write('<h1>Internal Server Error</h1>');
res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');
util.puts('500 Internal Server Error');
util.puts(util.inspect(error));
};
StaticServlet.prototype.sendMissing_ = function(req, res, path) {
path = path.substring(1);
res.writeHead(404, {
'Content-Type': 'text/html'
});
res.write('<!doctype html>\n');
res.write('<title>404 Not Found</title>\n');
res.write('<h1>Not Found</h1>');
res.write(
'<p>The requested URL ' +
escapeHtml(path) +
' was not found on this server.</p>'
);
res.end();
util.puts('404 Not Found: ' + path);
};
StaticServlet.prototype.sendForbidden_ = function(req, res, path) {
path = path.substring(1);
res.writeHead(403, {
'Content-Type': 'text/html'
});
res.write('<!doctype html>\n');
res.write('<title>403 Forbidden</title>\n');
res.write('<h1>Forbidden</h1>');
res.write(
'<p>You do not have permission to access ' +
escapeHtml(path) + ' on this server.</p>'
);
res.end();
util.puts('403 Forbidden: ' + path);
};
StaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {
res.writeHead(301, {
'Content-Type': 'text/html',
'Location': redirectUrl
});
res.write('<!doctype html>\n');
res.write('<title>301 Moved Permanently</title>\n');
res.write('<h1>Moved Permanently</h1>');
res.write(
'<p>The document has moved <a href="' +
redirectUrl +
'">here</a>.</p>'
);
res.end();
util.puts('301 Moved Permanently: ' + redirectUrl);
};
StaticServlet.prototype.sendFile_ = function(req, res, path) {
var self = this;
var file = fs.createReadStream(path);
res.writeHead(200, {
'Content-Type': StaticServlet.
MimeMap[path.split('.').pop()] || 'text/plain'
});
if (req.method === 'HEAD') {
res.end();
} else {
file.on('data', res.write.bind(res));
file.on('close', function() {
res.end();
});
file.on('error', function(error) {
self.sendError_(req, res, error);
});
}
};
StaticServlet.prototype.sendDirectory_ = function(req, res, path) {
var self = this;
if (path.match(/[^\/]$/)) {
req.url.pathname += '/';
var redirectUrl = url.format(url.parse(url.format(req.url)));
return self.sendRedirect_(req, res, redirectUrl);
}
fs.readdir(path, function(err, files) {
if (err)
return self.sendError_(req, res, error);
if (!files.length)
return self.writeDirectoryIndex_(req, res, path, []);
var remaining = files.length;
files.forEach(function(fileName, index) {
fs.stat(path + '/' + fileName, function(err, stat) {
if (err)
return self.sendError_(req, res, err);
if (stat.isDirectory()) {
files[index] = fileName + '/';
}
if (!(--remaining))
return self.writeDirectoryIndex_(req, res, path, files);
});
});
});
};
StaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {
path = path.substring(1);
res.writeHead(200, {
'Content-Type': 'text/html'
});
if (req.method === 'HEAD') {
res.end();
return;
}
res.write('<!doctype html>\n');
res.write('<title>' + escapeHtml(path) + '</title>\n');
res.write('<style>\n');
res.write(' ol { list-style-type: none; font-size: 1.2em; }\n');
res.write('</style>\n');
res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');
res.write('<ol>');
files.forEach(function(fileName) {
if (fileName.charAt(0) !== '.') {
res.write('<li><a href="' +
escapeHtml(fileName) + '">' +
escapeHtml(fileName) + '</a></li>');
}
});
res.write('</ol>');
res.end();
};
// Must be last,
main(process.argv);