mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-11 03:52:59 +00:00
allow sorting admin columns
This commit is contained in:
@@ -45,10 +45,47 @@ class AdminHandler(BaseHandler):
|
||||
|
||||
@admin_only
|
||||
def get(self):
|
||||
available = {'name', 'admin', 'running', 'last_activity'}
|
||||
default_sort = ['admin', 'name']
|
||||
mapping = {
|
||||
'running': '_server_id'
|
||||
}
|
||||
default_order = {
|
||||
'name': 'asc',
|
||||
'last_activity': 'desc',
|
||||
'admin': 'desc',
|
||||
'running': 'desc',
|
||||
}
|
||||
sorts = self.get_arguments('sort') or default_sort
|
||||
orders = self.get_arguments('order')
|
||||
|
||||
for bad in set(sorts).difference(available):
|
||||
self.log.warn("ignoring invalid sort: %r", bad)
|
||||
sorts.remove(bad)
|
||||
for bad in set(orders).difference({'asc', 'desc'}):
|
||||
self.log.warn("ignoring invalid order: %r", bad)
|
||||
orders.remove(bad)
|
||||
|
||||
# add default sort as secondary
|
||||
for s in default_sort:
|
||||
if s not in sorts:
|
||||
sorts.append(s)
|
||||
if len(orders) < len(sorts):
|
||||
for col in sorts[len(orders):]:
|
||||
orders.append(default_order[col])
|
||||
else:
|
||||
orders = orders[:len(sorts)]
|
||||
|
||||
# this could be one incomprehensible nested list comprehension
|
||||
# get User columns
|
||||
cols = [ getattr(orm.User, mapping.get(c, c)) for c in sorts ]
|
||||
# get User.col.desc() order objects
|
||||
ordered = [ getattr(c, o)() for c, o in zip(cols, orders) ]
|
||||
html = self.render_template('admin.html',
|
||||
user=self.get_current_user(),
|
||||
users=self.db.query(orm.User),
|
||||
users=self.db.query(orm.User).order_by(*ordered),
|
||||
admin_access=self.settings.get('admin_access', False),
|
||||
sort={s:o for s,o in zip(sorts, orders)},
|
||||
)
|
||||
self.finish(html)
|
||||
|
||||
|
@@ -9,12 +9,46 @@ require(["jquery", "bootstrap", "moment", "jhapi", "utils"], function ($, bs, mo
|
||||
|
||||
var api = new JHAPI(base_url);
|
||||
|
||||
var get_row = function (element) {
|
||||
function get_row (element) {
|
||||
while (!element.hasClass("user-row")) {
|
||||
element = element.parent();
|
||||
}
|
||||
return element;
|
||||
};
|
||||
}
|
||||
|
||||
function resort (col, order) {
|
||||
var query = window.location.search.slice(1).split('&');
|
||||
// if col already present in args, remove it
|
||||
var i = 0;
|
||||
while (i < query.length) {
|
||||
if (query[i] === 'sort=' + col) {
|
||||
query.splice(i,1);
|
||||
if (query[i] && query[i].substr(0, 6) === 'order=') {
|
||||
query.splice(i,1);
|
||||
}
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
// add new order to the front
|
||||
if (order) {
|
||||
query.unshift('order=' + order);
|
||||
}
|
||||
query.unshift('sort=' + col);
|
||||
// reload page with new order
|
||||
window.location = window.location.pathname + '?' + query.join('&');
|
||||
}
|
||||
|
||||
$("th").map(function (i, th) {
|
||||
th = $(th);
|
||||
var col = th.data('sort');
|
||||
var order = th.find('i').hasClass('fa-sort-desc') ? 'asc':'desc';
|
||||
th.find('a').click(
|
||||
function () {
|
||||
resort(col, order);
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
$(".time-col").map(function (i, el) {
|
||||
// convert ISO datestamps to nice momentjs ones
|
||||
|
3
share/jupyter/hub/static/less/admin.less
Normal file
3
share/jupyter/hub/static/less/admin.less
Normal file
@@ -0,0 +1,3 @@
|
||||
i.sort-icon {
|
||||
margin-left: 4px;
|
||||
}
|
@@ -22,6 +22,7 @@
|
||||
|
||||
@import "./variables.less";
|
||||
@import "./page.less";
|
||||
@import "./admin.less";
|
||||
@import "./error.less";
|
||||
@import "./logout.less";
|
||||
@import "./login.less";
|
||||
|
@@ -1,13 +1,28 @@
|
||||
{% extends "page.html" %}
|
||||
|
||||
{% macro th(key, label, order, colspan) %}
|
||||
<th data-sort="{{key}}" colspan="{{colspan}}">{{label}}
|
||||
<a href="#"><i class="fa {% if order == 'asc' -%}
|
||||
fa-sort-asc
|
||||
{%- elif order == 'desc' -%}
|
||||
fa-sort-desc
|
||||
{%- else -%}
|
||||
fa-sort
|
||||
{%- endif %} sort-icon">
|
||||
</i></a>
|
||||
</th>
|
||||
{% endmacro %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<div class="container">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="2">User</th>
|
||||
<th colspan="3">Last Seen</th>
|
||||
{{ th('name', "User", sort.get('name'), 1) }}
|
||||
{{ th('admin', "Admin", sort.get('admin'), 1) }}
|
||||
{{ th('last_activity', "Last Seen", sort.get('last_activity'), 1) }}
|
||||
{{ th('running', "Running", sort.get('running'), 2) }}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
Reference in New Issue
Block a user