Dashboard charts
This commit is contained in:
parent
088b63a507
commit
4db8e84cac
|
@ -1,26 +1,29 @@
|
|||
* { box-sizing: border-box; }
|
||||
.title, td, th {
|
||||
.heading, td, th {
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
font-size: 1.3em;
|
||||
padding: 0.6em;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.title, table {
|
||||
.heading, table {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
width: 650px;
|
||||
margin-left: -325px;
|
||||
}
|
||||
.title {
|
||||
.heading {
|
||||
top: 10px;
|
||||
text-align: center;
|
||||
font-size: 1.8em;
|
||||
text-align: center;
|
||||
}
|
||||
table {
|
||||
top: 100px;
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
th, td {
|
||||
font-size: 1.3em;
|
||||
padding: 0.6em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
th {
|
||||
font-weight: 400;
|
||||
|
@ -28,13 +31,15 @@ th {
|
|||
thead tr {
|
||||
border-bottom: #666 1px solid;
|
||||
}
|
||||
tbody tr:nth-child(even) {
|
||||
/*tbody tr:nth-child(even) {
|
||||
background-color: #f5f5f5;
|
||||
}*/
|
||||
.title {
|
||||
position: relative;
|
||||
width: 350px;
|
||||
}
|
||||
.name {
|
||||
width: 350px;
|
||||
max-width: 350px;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
@ -44,6 +49,16 @@ tbody tr:nth-child(even) {
|
|||
max-width: 150px;
|
||||
text-align: right;
|
||||
}
|
||||
.num {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
font-family: 'Lucida Console', Monaco, 'Courier New', Courier, monospace;
|
||||
font-size: 0.8em;
|
||||
line-height: 0.8em;
|
||||
padding: 5px;
|
||||
background: rgba(255, 255, 255, .8);
|
||||
border-radius: 3px;
|
||||
}
|
||||
.zero {
|
||||
color: #aaa;
|
||||
}
|
||||
|
@ -65,3 +80,18 @@ tbody tr:nth-child(even) {
|
|||
#placeholder td {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.chart {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
top: 0;
|
||||
right: -300px;
|
||||
width: 300px;
|
||||
height: 100%;
|
||||
}
|
||||
.in {
|
||||
fill: #7df;
|
||||
}
|
||||
.out {
|
||||
fill: #7fd;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
/*
|
||||
* Dashboard
|
||||
*/
|
||||
|
||||
function loadStatus(callback) {
|
||||
var xhr = new XMLHttpRequest(),
|
||||
loading = document.getElementById('loading');
|
||||
|
||||
loading.setAttribute('style', 'display: block;');
|
||||
xhr.open('GET', '/status', true);
|
||||
xhr.open('GET', '/status?rates=please', true);
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status === 200) {
|
||||
|
@ -38,44 +42,143 @@ function updateDashboard(queues) {
|
|||
tr = document.createElement('tr');
|
||||
tr.setAttribute('id', id);
|
||||
|
||||
var nameCol = document.createElement('td');
|
||||
nameCol.appendChild(document.createTextNode(queue));
|
||||
tr.appendChild(nameCol);
|
||||
tr.appendChild(document.createElement('td'));
|
||||
tr.appendChild(document.createElement('td'));
|
||||
var titleCol = document.createElement('td'),
|
||||
messagesCol = document.createElement('td'),
|
||||
subscriptionsCol = document.createElement('td'),
|
||||
nameDiv = document.createElement('div'),
|
||||
svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
|
||||
pathIn = document.createElementNS('http://www.w3.org/2000/svg', 'path'),
|
||||
pathOut = document.createElementNS('http://www.w3.org/2000/svg', 'path'),
|
||||
messagesDiv = document.createElement('div'),
|
||||
subscriptionsDiv = document.createElement('div');
|
||||
|
||||
pathIn.setAttribute('class', 'in');
|
||||
pathOut.setAttribute('class', 'out');
|
||||
svg.setAttributeNS(null, 'viewbox', '0 0 300 40');
|
||||
svg.appendChild(pathIn);
|
||||
svg.appendChild(pathOut);
|
||||
|
||||
nameDiv.setAttribute('class', 'name');
|
||||
svg.setAttribute('class', 'chart');
|
||||
titleCol.setAttribute('class', 'title');
|
||||
messagesCol.setAttribute('class', 'messages');
|
||||
subscriptionsCol.setAttribute('class', 'subscriptions');
|
||||
|
||||
nameDiv.appendChild(document.createTextNode(queue));
|
||||
titleCol.appendChild(svg);
|
||||
titleCol.appendChild(nameDiv);
|
||||
messagesCol.appendChild(messagesDiv);
|
||||
subscriptionsCol.appendChild(subscriptionsDiv);
|
||||
tr.appendChild(titleCol);
|
||||
tr.appendChild(messagesCol);
|
||||
tr.appendChild(subscriptionsCol);
|
||||
queuesList.appendChild(tr);
|
||||
}
|
||||
|
||||
var cols = tr.getElementsByTagName('td'),
|
||||
nameCol = cols[0],
|
||||
messagesCol = cols[1],
|
||||
subscriptionsCol = cols[2];
|
||||
var titleCol = tr.getElementsByClassName('title')[0],
|
||||
nameDiv = titleCol.getElementsByClassName('name')[0],
|
||||
svg = titleCol.getElementsByClassName('chart')[0],
|
||||
messagesCol = tr.getElementsByClassName('messages')[0],
|
||||
subscriptionsCol = tr.getElementsByClassName('subscriptions')[0],
|
||||
messagesDiv = messagesCol.getElementsByTagName('div')[0],
|
||||
subscriptionsDiv = subscriptionsCol.getElementsByTagName('div')[0],
|
||||
messages = Number(meta.messages).toLocaleString(),
|
||||
subscriptions = Number(meta.subscriptions).toLocaleString();
|
||||
|
||||
messagesCol.innerHTML = Number(meta.messages).toLocaleString();
|
||||
subscriptionsCol.innerHTML = Number(meta.subscriptions).toLocaleString();
|
||||
messagesDiv.innerHTML = messages;
|
||||
subscriptionsDiv.innerHTML = subscriptions;
|
||||
|
||||
if (meta.messages > hotThreshold) {
|
||||
nameCol.setAttribute('class', 'name hot');
|
||||
messagesCol.setAttribute('class', 'messages hot');
|
||||
nameDiv.setAttribute('class', 'name hot');
|
||||
messagesDiv.setAttribute('class', 'num messages hot');
|
||||
} else if (meta.messages > fatThreshold) {
|
||||
nameCol.setAttribute('class', 'name fat');
|
||||
messagesCol.setAttribute('class', 'messages fat');
|
||||
nameDiv.setAttribute('class', 'name fat');
|
||||
messagesDiv.setAttribute('class', 'num messages fat');
|
||||
} else if (meta.messages === 0) {
|
||||
messagesCol.setAttribute('class', 'messages zero');
|
||||
messagesDiv.setAttribute('class', 'num messages zero');
|
||||
} else {
|
||||
nameCol.setAttribute('class', 'name');
|
||||
messagesCol.setAttribute('class', 'messages');
|
||||
nameDiv.setAttribute('class', 'name');
|
||||
messagesDiv.setAttribute('class', 'num messages');
|
||||
}
|
||||
|
||||
if (meta.subscriptions === 0) {
|
||||
subscriptionsCol.setAttribute('class', 'subscriptions zero');
|
||||
subscriptionsDiv.setAttribute('class', 'num subscriptions zero');
|
||||
} else {
|
||||
subscriptionsCol.setAttribute('class', 'subscriptions');
|
||||
subscriptionsDiv.setAttribute('class', 'num subscriptions');
|
||||
}
|
||||
|
||||
svg.setAttributeNS(null, 'viewbox', '0 0 300 '+ titleCol.offsetTop);
|
||||
drawChart(svg, titleCol.offsetTop, meta.in_rate_history, meta.out_rate_history);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Charts
|
||||
*/
|
||||
|
||||
function drawChart(svg, maxHeight, valuesIn, valuesOut) {
|
||||
var pathIn = svg.getElementsByClassName('in')[0],
|
||||
pathOut = svg.getElementsByClassName('out')[0],
|
||||
// valuesIn = generateValues(300),
|
||||
// valuesOut = generateValues(300),
|
||||
maxDouble = calcMaxDouble(valuesIn, valuesOut),
|
||||
pointsIn = [],
|
||||
pointsOut = [];
|
||||
|
||||
for (var i = 0; i < valuesIn.length; i++) {
|
||||
var normIn = Math.ceil(valuesIn[i] / maxDouble * maxHeight),
|
||||
normOut = Math.ceil(valuesOut[i] / maxDouble * maxHeight),
|
||||
pointIn = maxHeight/2 - normIn,
|
||||
pointOut = maxHeight/2 + normOut;
|
||||
|
||||
pointsIn.push(pointIn);
|
||||
pointsOut.push(pointOut);
|
||||
}
|
||||
|
||||
pathIn.setAttributeNS(null, 'd', buildPathD(pointsIn, maxHeight));
|
||||
pathIn.setAttributeNS(null, 'class', 'in');
|
||||
pathOut.setAttributeNS(null, 'd', buildPathD(pointsOut, maxHeight));
|
||||
pathOut.setAttributeNS(null, 'class', 'out');
|
||||
}
|
||||
|
||||
function generateValues(num) {
|
||||
var values = [];
|
||||
for (var i = 0; i < num; i++) {
|
||||
var value = Math.ceil(Math.random() * 60) + 30;
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
function calcMaxDouble(a, b) {
|
||||
var doubleValue = 0;
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
if (a[i] * 2 > doubleValue) {
|
||||
doubleValue = a[i] * 2;
|
||||
}
|
||||
if (b[i] * 2 > doubleValue) {
|
||||
doubleValue = b[i] * 2;
|
||||
}
|
||||
}
|
||||
|
||||
return doubleValue * 1.2;
|
||||
}
|
||||
|
||||
function buildPathD(points, maxHeight) {
|
||||
var d = ['M0,'+ maxHeight/2];
|
||||
for (var i = 0; i < points.length; i++) {
|
||||
d.push('L'+ i +','+ points[i]);
|
||||
}
|
||||
d.push('L300,'+ maxHeight/2, 'Z');
|
||||
|
||||
return d.join(' ');
|
||||
}
|
||||
|
||||
/*
|
||||
* Starting up
|
||||
*/
|
||||
|
||||
function loop(timeout, func) {
|
||||
func();
|
||||
window.setTimeout(function(){
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<link rel="stylesheet" type="text/css" href="/static/app.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="title">Burlesque v{{.version}} at {{.hostname}}</h1>
|
||||
<h1 class="heading">Burlesque v{{.version}} at {{.hostname}}</h1>
|
||||
<table class="stats">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
Loading…
Reference in New Issue