complete rewriting of the Web UI using bootstrap

fixes #461, #366 and #417
This commit is contained in:
nclsHart 2014-12-24 16:06:33 +01:00 committed by Nicolargo
parent b4fd824168
commit 57eaefc3e8
9 changed files with 172 additions and 223 deletions

View File

@ -0,0 +1,59 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="refresh" content="{{refresh_time}}">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Glances</title>
<link rel="stylesheet" type="text/css" href="normalize.css" />
<link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="style.css" />
<script src="modernizr.custom.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-sm-12">
<div class="pull-left">
% include('plugin_text', plugin_name="system", stats=stats['system'])
</div>
<div class="pull-right">
% include('plugin_text', plugin_name="uptime", stats=stats['uptime'])
</div>
</div>
</div>
<div class="row">
<div class="col-sm-3">
% include('plugin_table', plugin_name="cpu", stats=stats['cpu'])
</div>
<div class="col-sm-3 col-lg-2 col-lg-offset-1">
% include('plugin_table', plugin_name="load", stats=stats['load'])
</div>
<div class="col-sm-3 col-lg-3">
% include('plugin_table', plugin_name="mem", stats=stats['mem'])
</div>
<div class="col-sm-3 col-lg-2 col-lg-offset-1">
% include('plugin_table', plugin_name="memswap", stats=stats['memswap'])
</div>
</div>
<div class="row">
<div class="col-sm-3">
% include('plugin_table', plugin_name="network", stats=stats['network'])
% include('plugin_table', plugin_name="diskio", stats=stats['diskio'])
% include('plugin_table', plugin_name="fs", stats=stats['fs'])
% include('plugin_table', plugin_name="sensors", stats=stats['sensors'])
</div>
<div class="col-sm-9">
% include('plugin_table', plugin_name="alert", stats=stats['alert'])
% include('plugin_text', plugin_name="processcount", stats=stats['processcount'])
<div class="row">
<div class="col-sm-9">
% include('plugin_table', plugin_name="monitor", stats=stats['monitor'])
</div>
</div>
% include('plugin_table', plugin_name="processlist", stats=stats['processlist'])
</div>
</div>
</div>
</body>
</html>

View File

@ -1,4 +0,0 @@
</body>
<footer>
</footer>
</html>

View File

@ -1,11 +0,0 @@
<!DOCTYPE HTML><html>
<head>
<meta http-equiv="refresh" content="{{refresh_time}}">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Glances</title>
<link rel="stylesheet" type="text/css" href="normalize.css" />
<link rel="stylesheet" type="text/css" href="style.css" />
<script src="modernizr.custom.js"></script>
</head>
<body>

View File

@ -1 +0,0 @@
<div id="newline"></div>

View File

@ -0,0 +1,30 @@
% if stats['msgdict'] != []:
<section id="{{ plugin_name }}" class="plugin">
<table class="table">
<tbody>
<tr>
% for msg in stats['msgdict']:
% if msg['msg'].startswith('\n'):
</tr>
<tr>
% else:
% if stats['display']:
% if plugin_name == 'processlist':
% if not msg['splittable'] or msg['splittable'] and msg['decoration'] == 'PROCESS':
<td class="{{ msg['decoration'].lower() }}">
{{ msg['msg'] }}
</td>
% end
% else:
<td class="{{ msg['decoration'].lower() }} {{ 'hidden-xs hidden-sm' if msg['optional'] else '' }}">
{{ msg['msg'] }}
</td>
% end
% end
% end
% end
</tr>
</tbody>
</table>
</section>
% end

View File

@ -0,0 +1,11 @@
% if stats['msgdict'] != []:
<section id="{{ plugin_name }}" class="plugin">
% for msg in stats['msgdict']:
% if stats['display']:
<span class="{{ msg['decoration'].lower() }} {{ 'hidden-xs hidden-sm' if msg['optional'] else '' }}">
{{ msg['msg'] }}
</span>
% end
% end
</section>
% end

View File

@ -56,27 +56,6 @@ class GlancesBottle(object):
# Path where the statics files are stored
self.STATIC_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'static')
# Define the style (CSS) list (hash table) for stats
self.__style_list = {
'DEFAULT': '',
'UNDERLINE': 'underline',
'BOLD': 'bold',
'SORT': 'sort',
'OK': 'ok',
'FILTER': 'filter',
'TITLE': 'title',
'CAREFUL': 'careful',
'WARNING': 'warning',
'CRITICAL': 'critical',
'OK_LOG': 'ok_log',
'CAREFUL_LOG': 'careful_log',
'WARNING_LOG': 'warning_log',
'CRITICAL_LOG': 'critical_log',
'NICE': 'nice',
'STATUS': 'status',
'PROCESS': ''
}
def _route(self):
"""Define route."""
self._app.route('/', method="GET", callback=self._index)
@ -269,78 +248,23 @@ class GlancesBottle(object):
stats: Stats database to display
"""
html = template('header', refresh_time=refresh_time)
html += '<header>'
html += self.display_plugin('system', self.stats.get_plugin('system').get_stats_display(args=self.args))
html += self.display_plugin('uptime', self.stats.get_plugin('uptime').get_stats_display(args=self.args))
html += '</header>'
html += template('newline')
html += '<section>'
html += self.display_plugin('cpu', self.stats.get_plugin('cpu').get_stats_display(args=self.args))
load_msg = self.stats.get_plugin('load').get_stats_display(args=self.args)
if load_msg['msgdict'] != []:
# Load is not available on all OS
# Only display if stat is available
html += self.display_plugin('load', load_msg)
html += self.display_plugin('mem', self.stats.get_plugin('mem').get_stats_display(args=self.args))
html += self.display_plugin('memswap', self.stats.get_plugin('memswap').get_stats_display(args=self.args))
html += '</section>'
html += template('newline')
html += '<div>'
html += '<aside id="lefttstats">'
html += self.display_plugin('network', self.stats.get_plugin('network').get_stats_display(args=self.args))
html += self.display_plugin('diskio', self.stats.get_plugin('diskio').get_stats_display(args=self.args))
html += self.display_plugin('fs', self.stats.get_plugin('fs').get_stats_display(args=self.args))
html += self.display_plugin('raid', self.stats.get_plugin('raid').get_stats_display(args=self.args))
html += self.display_plugin('sensors', self.stats.get_plugin('sensors').get_stats_display(args=self.args))
html += '</aside>'
html += '<section id="rightstats">'
html += self.display_plugin('alert', self.stats.get_plugin('alert').get_stats_display(args=self.args))
html += self.display_plugin('processcount', self.stats.get_plugin('processcount').get_stats_display(args=self.args))
html += self.display_plugin('monitor', self.stats.get_plugin('monitor').get_stats_display(args=self.args))
html += self.display_plugin('processlist', self.stats.get_plugin('processlist').get_stats_display(args=self.args))
html += '</section>'
html += '</div>'
html += template('newline')
html += template('footer')
return html
stats = {
'system': self.stats.get_plugin('system').get_stats_display(args=self.args),
'uptime': self.stats.get_plugin('uptime').get_stats_display(args=self.args),
'cpu': self.stats.get_plugin('cpu').get_stats_display(args=self.args),
'load': self.stats.get_plugin('load').get_stats_display(args=self.args),
'mem': self.stats.get_plugin('mem').get_stats_display(args=self.args),
'memswap': self.stats.get_plugin('memswap').get_stats_display(args=self.args),
'network': self.stats.get_plugin('network').get_stats_display(args=self.args),
'diskio': self.stats.get_plugin('diskio').get_stats_display(args=self.args),
'fs': self.stats.get_plugin('fs').get_stats_display(args=self.args),
'raid': self.stats.get_plugin('raid').get_stats_display(args=self.args),
'sensors': self.stats.get_plugin('sensors').get_stats_display(args=self.args),
'alert': self.stats.get_plugin('alert').get_stats_display(args=self.args),
'processcount': self.stats.get_plugin('processcount').get_stats_display(args=self.args),
'monitor': self.stats.get_plugin('monitor').get_stats_display(args=self.args),
'processlist': self.stats.get_plugin('processlist').get_stats_display(args=self.args)
}
def display_plugin(self, plugin_name, plugin_stats):
"""Generate the Bottle template for the plugin_stats."""
# Template header
tpl = """ \
%#Template for Bottle
"""
tpl += '<article class="plugin" id="%s">' % plugin_name
tpl += '<div id="table">'
tpl += '<div class="row">'
for m in plugin_stats['msgdict']:
# New line
if m['msg'].startswith('\n'):
tpl += '</div>'
tpl += '<div class="row">'
continue
if plugin_name == 'processlist' and m['splittable']:
# Processlist: Display first 20 chars of the process name
if m['msg'].split(' ', 1)[0] != '':
tpl += '<span class="cell" id="%s">&nbsp;%s</span>' % \
(self.__style_list[m['decoration']],
m['msg'].split(' ', 1)[0].replace(' ', '&nbsp;')[:20])
elif m['optional']:
# Manage optional stats (responsive design)
tpl += '<span class="cell hide" id="%s">%s</span>' % \
(self.__style_list[m['decoration']], m['msg'].replace(' ', '&nbsp;'))
else:
# Display stat
tpl += '<span class="cell" id="%s">%s</span>' % \
(self.__style_list[m['decoration']], m['msg'].replace(' ', '&nbsp;'))
tpl += '</div>'
tpl += '</div>'
tpl += """ \
</article>
%#End Template for Bottle
"""
return template(tpl)
return template('base', refresh_time=refresh_time, stats=stats)

File diff suppressed because one or more lines are too long

View File

@ -2,162 +2,93 @@ body {
background: black;
color: #BBB;
font-family: "Lucida Sans Typewriter", "Lucida Console", Monaco, "Bitstream Vera Sans Mono", monospace;
font-size: 100%;
}
header,footer,
article,section,
hgroup,nav,
figure,div,aside {
display: block;
.plugin {
margin-bottom: 20px;
}
section {
text-align: justify;
}
section > article {
display: inline-block;
vertical-align: top;
*display: inline;
zoom: 1;
}
section:after {
content: "";
.plugin table {
width: 100%;
display: inline-block;
}
aside {
float: left;
margin-right: 2%;
.plugin table tr td:not(:first-child) {
text-align: right;
}
div#newline{
clear: both;
height: 1em;
}
#underline{
.underline{
text-decoration: underline
}
#bold{
.bold{
font-weight: bold;
}
#sort{
.sort{
font-weight: bold;
}
#sort:after{
.sort:after{
content: '\25BC'
}
/*Theme*/
#title{
.text-right {
text-align: right;
}
/* Theme */
.title{
font-weight: bold;
color: white;
}
#table {
display: table;
}
.row {
display: table-row;
}
.cell {
display: table-cell;
}
#ok {
.ok {
color: green;
}
#filter {
.filter {
color: cyan;
}
#ok_log {
.ok_log {
background-color: green;
color: white;
}
#careful {
.careful {
color: blueviolet;
}
#careful_log {
.careful_log {
background-color: blueviolet;
color: white;
}
#warning {
.warning {
color: orange;
}
#warning_log {
.warning_log {
background-color: orange;
color: white;
}
#critical {
.critical {
color: red;
}
#critical_log {
.critical_log {
background-color: red;
color: white;
}
#nice {
.nice {
color: magenta;
}
#status {
.status {
color: green;
}
/*Plugins*/
#system {
float: left;
.process {
color: green;
}
#uptime {
float: right;
/* Plugins */
#cpu table tr td:nth-child(3),
#mem table tr td:nth-child(3),
#monitor table tr td:nth-child(3) {
text-align: left;
padding-left: 20px;
}
#cpu {}
#load {}
#mem {}
#memswap {}
#leftstats {}
#network {
margin-bottom: 1em;
}
#diskio {
margin-bottom: 1em;
}
#fs {
margin-bottom: 1em;
}
#raid {
margin-bottom: 1em;
}
#sensors {}
#rightstats {}
#alert {
display: block;
}
#processcount {
display: block;
margin: 1em;
}
#monitor {
display: block;
margin: 1em;
}
#processlist {}
/*
article#processlist>div>div>span:last-child {
visibility: hidden;
#processlist table tr td {
padding: 0px 5px 0px 5px;
white-space: nowrap;
text-align: right;
}
*/
#now {}
/*Responsive design*/
@media only screen and (max-width: 1600px) {
body { font-size:90%; }
}
@media only screen and (max-width: 1280px) {
body { font-size:80%; }
}
@media only screen and (max-width: 1024px) {
body { font-size:80%; }
#processlist .hide { display: none; }
}
@media only screen and (max-width: 768px) {
body { font-size:70%; }
aside { margin-right: 1%; }
.hide { display: none; }
}
@media only screen and (max-width: 480px) {
body { font-size:60%; }
aside { margin-right: 1%; }
.hide { display: none; }
}
#processlist table tr td:nth-child(6),
#processlist table tr td:nth-child(12) {
text-align: left;
}