add basic home, admin pages

- index no longer requires login, it's just a big fat login button
- home has stop, start, admin buttons
- admin doesn't do anything yet
- add jhapi javascript client for REST API
This commit is contained in:
MinRK
2014-09-14 16:46:23 -07:00
parent b24e47d94a
commit c93f17c324
9 changed files with 338 additions and 4 deletions

View File

@@ -1,8 +1,8 @@
from .base import *
from .login import *
from . import base, login
from . import base, pages, login
default_handlers = []
for mod in (base, login):
for mod in (base, pages, login):
default_handlers.extend(mod.default_handlers)

View File

@@ -0,0 +1,55 @@
"""Basic html-rendering handlers."""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from tornado import web
from .. import orm
from ..utils import admin_only, url_path_join
from .base import BaseHandler
class RootHandler(BaseHandler):
"""Render the Hub root page.
Currently redirects to home if logged in,
shows big fat login button otherwise.
"""
def get(self):
if self.get_current_user():
self.redirect(
url_path_join(self.hub.server.base_url, 'home'),
permanent=False,
)
return
html = self.render_template('index.html',
login_url=self.settings['login_url'],
)
self.finish(html)
class HomeHandler(BaseHandler):
"""Render the user's home page."""
@web.authenticated
def get(self):
html = self.render_template('home.html',
user=self.get_current_user(),
)
self.finish(html)
class AdminHandler(BaseHandler):
"""Render the admin page."""
@admin_only
def get(self):
html = self.render_template('admin.html',
user=self.get_current_user(),
users=self.db.query(orm.User),
)
self.finish(html)
default_handlers = [
(r'/', RootHandler),
(r'/home', HomeHandler),
(r'/admin', AdminHandler),
]

View File

@@ -0,0 +1,19 @@
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
require(["jquery", "jhapi"], function ($, JHAPI) {
"use strict";
var base_url = window.jhdata.base_url;
var user = window.jhdata.user;
var api = new JHAPI(base_url);
$("#stop").click(function () {
api.stop_server(user, {
success: function () {
$("#stop").hide();
}
});
});
});

View File

@@ -0,0 +1,89 @@
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
define(['jquery', 'utils'], function ($, utils) {
"use strict";
var JHAPI = function (base_url) {
this.base_url = base_url;
};
var default_options = {
type: 'GET',
headers: {'Content-Type': 'application/json'},
cache: false,
dataType : "json",
processData: false,
success: null,
error: utils.log_jax_error,
};
var update = function (d1, d2) {
$.map(d2, function (i, key) {
d1[key] = d2[key];
});
return d1;
};
var ajax_defaults = function (options) {
var d = {};
update(d, default_options);
update(d, options);
return d;
};
JHAPI.prototype.api_request = function (path, options) {
options = options || {};
options = ajax_defaults(options || {});
var url = utils.url_path_join(
this.base_url,
'api',
utils.encode_uri_components(path)
);
$.ajax(url, options);
};
JHAPI.prototype.start_server = function (user, options) {
options = options || {};
options.update({
type: 'POST',
});
this.api_request(
utils.url_path_join('users', user, 'server'),
options
);
};
JHAPI.prototype.stop_server = function (user, options) {
options = update(options || {}, {
type: 'DELETE',
});
this.api_request(
utils.url_path_join('users', user, 'server'),
options
);
};
JHAPI.prototype.list_users = function (options) {
this.api_request('users', options);
};
JHAPI.prototype.get_user = function (user, options) {
this.api_request(
utils.url_path_join('users', user),
options
);
};
JHAPI.prototype.delete_user = function (user, options) {
options = update(options || {}, {
type: 'DELETE',
});
this.api_request(
utils.url_path_join('users', user),
options
);
};
return JHAPI;
});

View File

@@ -0,0 +1,127 @@
// Based on IPython's base.js.utils
// Original Copyright (c) IPython Development Team.
// Distributed under the terms of the Modified BSD License.
// Modifications Copyright (c) Juptyer Development Team.
// Distributed under the terms of the Modified BSD License.
define(['jquery'], function($){
"use strict";
var url_path_join = function () {
// join a sequence of url components with '/'
var url = '';
for (var i = 0; i < arguments.length; i++) {
if (arguments[i] === '') {
continue;
}
if (url.length > 0 && url[url.length-1] != '/') {
url = url + '/' + arguments[i];
} else {
url = url + arguments[i];
}
}
url = url.replace(/\/\/+/, '/');
return url;
};
var parse_url = function (url) {
// an `a` element with an href allows attr-access to the parsed segments of a URL
// a = parse_url("http://localhost:8888/path/name#hash")
// a.protocol = "http:"
// a.host = "localhost:8888"
// a.hostname = "localhost"
// a.port = 8888
// a.pathname = "/path/name"
// a.hash = "#hash"
var a = document.createElement("a");
a.href = url;
return a;
};
var encode_uri_components = function (uri) {
// encode just the components of a multi-segment uri,
// leaving '/' separators
return uri.split('/').map(encodeURIComponent).join('/');
};
var url_join_encode = function () {
// join a sequence of url components with '/',
// encoding each component with encodeURIComponent
return encode_uri_components(url_path_join.apply(null, arguments));
};
var escape_html = function (text) {
// escape text to HTML
return $("<div/>").text(text).html();
};
var get_body_data = function(key) {
// get a url-encoded item from body.data and decode it
// we should never have any encoded URLs anywhere else in code
// until we are building an actual request
return decodeURIComponent($('body').data(key));
};
// http://stackoverflow.com/questions/2400935/browser-detection-in-javascript
var browser = (function() {
if (typeof navigator === 'undefined') {
// navigator undefined in node
return 'None';
}
var N= navigator.appName, ua= navigator.userAgent, tem;
var M= ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
if (M && (tem= ua.match(/version\/([\.\d]+)/i)) !== null) M[2]= tem[1];
M= M? [M[1], M[2]]: [N, navigator.appVersion,'-?'];
return M;
})();
// http://stackoverflow.com/questions/11219582/how-to-detect-my-browser-version-and-operating-system-using-javascript
var platform = (function () {
if (typeof navigator === 'undefined') {
// navigator undefined in node
return 'None';
}
var OSName="None";
if (navigator.appVersion.indexOf("Win")!=-1) OSName="Windows";
if (navigator.appVersion.indexOf("Mac")!=-1) OSName="MacOS";
if (navigator.appVersion.indexOf("X11")!=-1) OSName="UNIX";
if (navigator.appVersion.indexOf("Linux")!=-1) OSName="Linux";
return OSName;
})();
var ajax_error_msg = function (jqXHR) {
// Return a JSON error message if there is one,
// otherwise the basic HTTP status text.
if (jqXHR.responseJSON && jqXHR.responseJSON.message) {
return jqXHR.responseJSON.message;
} else {
return jqXHR.statusText;
}
};
var log_ajax_error = function (jqXHR, status, error) {
// log ajax failures with informative messages
var msg = "API request failed (" + jqXHR.status + "): ";
console.log(jqXHR);
msg += ajax_error_msg(jqXHR);
console.log(msg);
};
var utils = {
url_path_join : url_path_join,
url_join_encode : url_join_encode,
encode_uri_components : encode_uri_components,
escape_html : escape_html,
get_body_data : get_body_data,
parse_url : parse_url,
browser : browser,
platform: platform,
ajax_error_msg : ajax_error_msg,
log_ajax_error : log_ajax_error,
};
return utils;
});

View File

@@ -0,0 +1,13 @@
{% extends "page.html" %}
{% block main %}
<div class="container">
<div class="row">
<div class="text-center">
<a class="btn btn-lg btn-primary">Administrate!</a>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,29 @@
{% extends "page.html" %}
{% block main %}
<div class="container">
<div class="row">
<div class="text-center">
{% if user.server %}
<a id="stop" class="btn btn-lg btn-danger">Stop My Server</a>
{% endif %}
<a id="start" class="btn btn-lg btn-success"
href="{{base_url}}user/{{user.name}}/"
>
My Server
</a>
{% if user.admin %}
<a id="admin" class="btn btn-lg btn-primary" href="{{base_url}}admin">Admin</a>
{% endif %}
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script type="text/javascript">
require(["home"]);
</script>
{% endblock %}

View File

@@ -1,11 +1,14 @@
{% extends "page.html" %}
{% block login_widget %}
{% endblock %}
{% block main %}
<div class="container">
<div class="row">
<div class="text-center">
<a id="start" class="btn btn-lg btn-primary" href="{{server_url}}">Dashboard</a>
<a id="login" class="btn btn-lg btn-primary" href="{{login_url}}">Log in</a>
</div>
</div>
</div>

View File

@@ -1,6 +1,5 @@
{% extends "page.html" %}
{% block login_widget %}
{% endblock %}