mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-17 17:47:03 +00:00
More bootstrap work, status page now updates
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
/* Site Wide */
|
||||
html {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
@@ -9,11 +10,6 @@ body {
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.mailbox-header {
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
@@ -27,12 +23,14 @@ body {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.message-controls {
|
||||
padding: 10px 0;
|
||||
/* Mailbox & Messages */
|
||||
.mailbox-header {
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
#emailContent {
|
||||
padding-bottom: 20px;
|
||||
.message-controls {
|
||||
padding: 0 0 10px 0;
|
||||
}
|
||||
|
||||
.message-header dl {
|
||||
@@ -49,31 +47,20 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
.message-body {
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.message-attachments {
|
||||
margin-top: 20px;
|
||||
padding: 10px 20px;;
|
||||
}
|
||||
|
||||
.message-attachments ul {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
#emailSubject {
|
||||
border-bottom: 1px #606060 solid;
|
||||
margin: 0;
|
||||
width: 617px;
|
||||
}
|
||||
|
||||
#emailBody {
|
||||
color: #555;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.errors {
|
||||
background-color: #ffa0a0;
|
||||
color: #333;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
/* Metrics */
|
||||
table.metrics {
|
||||
}
|
||||
|
||||
@@ -90,27 +77,3 @@ table.metrics {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
#emailAttachments {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
#emailAttachments th, #emailAttachments td {
|
||||
text-align: left;
|
||||
padding: 0 3px 3px 0;
|
||||
}
|
||||
|
||||
#emailAttachments .fileName:before {
|
||||
content: '\203A\00A0';
|
||||
}
|
||||
|
||||
#emailAttachments a {
|
||||
background: #8ac6dc;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
#emailAttachments a:hover {
|
||||
background: #becf74;
|
||||
}
|
||||
|
||||
|
||||
2
themes/bootstrap/public/jquery.color-2.1.2.min.js
vendored
Normal file
2
themes/bootstrap/public/jquery.color-2.1.2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
5
themes/bootstrap/public/jquery.sparkline.min.js
vendored
Normal file
5
themes/bootstrap/public/jquery.sparkline.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -27,8 +27,8 @@
|
||||
</div>
|
||||
<div id="navbar" class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="/" accesskey="1">Home</a></li>
|
||||
<li><a href="/status" accesskey="2">Status</a></li>
|
||||
<li id="nav-mail"><a href="/" accesskey="1">Mail</a></li>
|
||||
<li id="nav-status"><a href="/status" accesskey="2">Status</a></li>
|
||||
</ul>
|
||||
<form class="navbar-form navbar-right" action="{{reverse "MailboxIndex"}}" method="GET">
|
||||
<div class="form-group">
|
||||
|
||||
@@ -2,26 +2,26 @@
|
||||
{{$id := .message.Id}}
|
||||
<div class="btn-group btn-group-sm message-controls" role="group" aria-label="Message Controls">
|
||||
<button type="button"
|
||||
class="btn btn-default"
|
||||
class="btn btn-primary"
|
||||
onClick="window.open('/link/{{$name}}/{{$id}}');">
|
||||
<span class="glyphicon glyphicon-link" aria-hidden="true"></span>
|
||||
Link
|
||||
</button>
|
||||
<button type="button"
|
||||
class="btn btn-default"
|
||||
class="btn btn-danger"
|
||||
onClick="deleteMessage('{{.message.Id}}');">
|
||||
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
|
||||
Delete
|
||||
</button>
|
||||
<button type="button"
|
||||
class="btn btn-default"
|
||||
class="btn btn-primary"
|
||||
onClick="messageSource('{{.message.Id}}');">
|
||||
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
||||
Source
|
||||
</button>
|
||||
{{if .htmlAvailable}}
|
||||
<button type="button"
|
||||
class="btn btn-default"
|
||||
class="btn btn-primary"
|
||||
onClick="htmlView('{{.message.Id}}');">
|
||||
<span class="glyphicon glyphicon-new-window" aria-hidden="true"></span>
|
||||
HTML
|
||||
@@ -29,7 +29,8 @@
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<div class="well well-sm message-header">
|
||||
<div class="panel panel-default message-header">
|
||||
<div class="panel-body">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>From:</dt>
|
||||
<dd>{{.message.From}}</dd>
|
||||
@@ -39,22 +40,35 @@
|
||||
<dd>{{.message.Subject}}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="message-body">{{.body}}</div>
|
||||
<div class="message-body">{{.body}}</div>
|
||||
|
||||
{{with .attachments}}
|
||||
<div class="panel panel-default message-attachments">
|
||||
<div class="panel-body">
|
||||
<div class="well message-attachments">
|
||||
<ul class="list-unstyled">
|
||||
{{range $i, $e := .}}
|
||||
<li>
|
||||
<span class="glyphicon glyphicon-paperclip" aria-hidden="true"></span>
|
||||
{{$e.FileName}}
|
||||
({{$e.ContentType}})
|
||||
<a href="/mailbox/vattach/{{$name}}/{{$id}}/{{$i}}/{{$e.FileName}}" target="_blank">View</a>
|
||||
<a href="/mailbox/dattach/{{$name}}/{{$id}}/{{$i}}/{{$e.FileName}}">Download</a>
|
||||
<a class="btn btn-success btn-sm"
|
||||
role="button"
|
||||
href="/mailbox/vattach/{{$name}}/{{$id}}/{{$i}}/{{$e.FileName}}"
|
||||
target="_blank"
|
||||
aria-label="View">
|
||||
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
|
||||
View
|
||||
</a>
|
||||
<a class="btn btn-primary btn-sm"
|
||||
role="button"
|
||||
hhref="/mailbox/dattach/{{$name}}/{{$id}}/{{$i}}/{{$e.FileName}}"
|
||||
aria-label="Download">
|
||||
<span class="glyphicon glyphicon-download" aria-hidden="true"></span>
|
||||
Download
|
||||
</a>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -1,49 +1,50 @@
|
||||
{{define "title"}}{{printf "Inbucket for %v" .name}}{{end}}
|
||||
{{define "navMail"}}true{{end}}
|
||||
{{$name := .name}}
|
||||
|
||||
{{define "script"}}
|
||||
<script>
|
||||
var selected = "{{.selected}}"
|
||||
var selected = "{{.selected}}";
|
||||
function messageLoaded(responseText, textStatus, XMLHttpRequest) {
|
||||
if (textStatus == "error") {
|
||||
alert("Failed to load message, server said:\n" + responseText)
|
||||
alert("Failed to load message, server said:\n" + responseText);
|
||||
} else {
|
||||
window.scrollTo(0,0)
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
}
|
||||
|
||||
function listLoaded() {
|
||||
$('.listEntry').click(
|
||||
function() {
|
||||
$('.listEntry').removeClass("disabled")
|
||||
$(this).addClass("disabled")
|
||||
$('#emailContent').load('/mailbox/{{.name}}/' + this.id, messageLoaded)
|
||||
selected = this.id
|
||||
$('.listEntry').removeClass("disabled");
|
||||
$(this).addClass("disabled");
|
||||
$('#emailContent').load('/mailbox/{{.name}}/' + this.id, messageLoaded);
|
||||
selected = this.id;
|
||||
}
|
||||
)
|
||||
$("#messageList").slideDown()
|
||||
$("#messageList").slideDown();
|
||||
if (selected != "") {
|
||||
$("#" + selected).click()
|
||||
selected = ""
|
||||
$("#" + selected).click();
|
||||
selected = "";
|
||||
}
|
||||
}
|
||||
|
||||
function loadList() {
|
||||
$('#messageList').load("/mailbox/{{.name}}", listLoaded)
|
||||
$('#messageList').load("/mailbox/{{.name}}", listLoaded);
|
||||
}
|
||||
|
||||
function reloadList() {
|
||||
$('#messageList').hide()
|
||||
loadList()
|
||||
$('#messageList').hide();
|
||||
loadList();
|
||||
}
|
||||
|
||||
function listInit() {
|
||||
$("#messageList").hide()
|
||||
loadList()
|
||||
$("#messageList").hide();
|
||||
loadList();
|
||||
}
|
||||
|
||||
function deleteMessage(id) {
|
||||
$('#emailContent').empty()
|
||||
$('#emailContent').empty();
|
||||
$.ajax({
|
||||
type: 'DELETE',
|
||||
url: '/mailbox/{{.name}}/' + id,
|
||||
@@ -54,21 +55,26 @@
|
||||
function htmlView(id) {
|
||||
window.open('/mailbox/{{.name}}/' + id + "/html", '_blank',
|
||||
'width=800,height=600,' +
|
||||
'menubar=yes,resizable=yes,scrollbars=yes,status=yes,toolbar=yes')
|
||||
'menubar=yes,resizable=yes,scrollbars=yes,status=yes,toolbar=yes');
|
||||
}
|
||||
|
||||
function messageSource(id) {
|
||||
window.open('/mailbox/{{.name}}/' + id + "/source", '_blank',
|
||||
'width=800,height=600,' +
|
||||
'menubar=no,resizable=yes,scrollbars=yes,status=no,toolbar=no')
|
||||
'menubar=no,resizable=yes,scrollbars=yes,status=no,toolbar=no');
|
||||
}
|
||||
|
||||
$(document).ready(listInit)
|
||||
function docReady() {
|
||||
$('#nav-mail').addClass("active");
|
||||
listInit();
|
||||
}
|
||||
|
||||
$(document).ready(docReady)
|
||||
</script>
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading mailbox-header">
|
||||
<span class="glyphicon glyphicon-inbox" aria-hidden="true"></span>
|
||||
{{.name}}
|
||||
|
||||
@@ -2,32 +2,33 @@
|
||||
|
||||
{{define "script"}}
|
||||
<script src="/public/jquery.sparkline.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="/public/jquery.color-2.1.2.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script>
|
||||
jQuery.ajaxSetup({ cache: false })
|
||||
flashOn = jQuery.Color("rgba(255,255,0,1)")
|
||||
flashOff = jQuery.Color("rgba(255,255,0,0)")
|
||||
dataHist = new Object()
|
||||
jQuery.ajaxSetup({ cache: false });
|
||||
flashOn = jQuery.Color("rgba(255,255,0,1)");
|
||||
flashOff = jQuery.Color("rgba(255,255,0,0)");
|
||||
dataHist = new Object();
|
||||
|
||||
function timeFilter(seconds) {
|
||||
if (seconds < 60) {
|
||||
return seconds + " seconds"
|
||||
return seconds + " seconds";
|
||||
} else if (seconds < 3600) {
|
||||
return (seconds/60).toFixed(0) + " minute(s)"
|
||||
return (seconds/60).toFixed(0) + " minute(s)";
|
||||
} else if (seconds < 86400) {
|
||||
return (seconds/3600).toFixed(1) + " hour(s)"
|
||||
return (seconds/3600).toFixed(1) + " hour(s)";
|
||||
}
|
||||
return (seconds/86400).toFixed(0) + " day(s)"
|
||||
return (seconds/86400).toFixed(0) + " day(s)";
|
||||
}
|
||||
|
||||
function sizeFilter(bytes) {
|
||||
if (bytes < 1024) {
|
||||
return bytes + " bytes"
|
||||
return bytes + " bytes";
|
||||
} else if (bytes < 1048576) {
|
||||
return (bytes/1024).toFixed(0) + " KB"
|
||||
return (bytes/1024).toFixed(0) + " KB";
|
||||
} else if (bytes < 1073741824) {
|
||||
return (bytes/1048576).toFixed(2) + " MB"
|
||||
return (bytes/1048576).toFixed(2) + " MB";
|
||||
}
|
||||
return (bytes/1073741824).toFixed(2) + " GB"
|
||||
return (bytes/1073741824).toFixed(2) + " GB";
|
||||
}
|
||||
|
||||
function numberFilter(x) {
|
||||
@@ -37,101 +38,102 @@
|
||||
}
|
||||
|
||||
function appendHistory(name, value) {
|
||||
var h = dataHist[name]
|
||||
var h = dataHist[name];
|
||||
if (! h) {
|
||||
h = new Array(0)
|
||||
h = new Array(0);
|
||||
}
|
||||
// Prevent array from growing
|
||||
if (h.length >= 60) {
|
||||
h = h.slice(1,60)
|
||||
h = h.slice(1,60);
|
||||
}
|
||||
h.push(parseInt(value))
|
||||
dataHist[name] = h
|
||||
el = $('#s-' + name)
|
||||
h.push(parseInt(value));
|
||||
dataHist[name] = h;
|
||||
el = $('#s-' + name);
|
||||
if (el) {
|
||||
el.sparkline(dataHist[name])
|
||||
el.sparkline(dataHist[name]);
|
||||
}
|
||||
}
|
||||
|
||||
// Show spikes for numbers that only increase
|
||||
function setHistoryOfActivity(name, value) {
|
||||
var h = value.split(",")
|
||||
var prev = parseInt(h[0])
|
||||
var h = value.split(",");
|
||||
var prev = parseInt(h[0]);
|
||||
for (i=0; i<h.length; i++) {
|
||||
var t = parseInt(h[i])
|
||||
h[i] = t-prev
|
||||
prev = t
|
||||
var t = parseInt(h[i]);
|
||||
h[i] = t-prev;
|
||||
prev = t;
|
||||
}
|
||||
// First value will always be zero
|
||||
if (h.length > 0) {
|
||||
h = h.slice(1)
|
||||
h = h.slice(1);
|
||||
}
|
||||
el = $('#s-' + name)
|
||||
el = $('#s-' + name);
|
||||
if (el) {
|
||||
el.sparkline(h)
|
||||
el.sparkline(h);
|
||||
}
|
||||
}
|
||||
|
||||
// Show up/down for numbers that can decrease
|
||||
function setHistoryOfCount(name, value) {
|
||||
var h = value.split(",")
|
||||
el = $('#s-' + name)
|
||||
var h = value.split(",");
|
||||
el = $('#s-' + name);
|
||||
if (el) {
|
||||
el.sparkline(h)
|
||||
el.sparkline(h);
|
||||
}
|
||||
}
|
||||
|
||||
function metric(name, value, filter, chartable) {
|
||||
if (chartable) {
|
||||
appendHistory(name, value)
|
||||
appendHistory(name, value);
|
||||
}
|
||||
if (filter) {
|
||||
value = filter(value)
|
||||
value = filter(value);
|
||||
}
|
||||
var el = $('#m-' + name)
|
||||
if (el.text() != value) {
|
||||
el.text(value)
|
||||
el.css('background-color', flashOn)
|
||||
el.animate({ backgroundColor: flashOff }, 1500)
|
||||
el.text(value);
|
||||
el.css('background-color', flashOn);
|
||||
el.animate({ backgroundColor: flashOff }, 1500);
|
||||
}
|
||||
}
|
||||
|
||||
function displayMetrics(data, textStatus, jqXHR) {
|
||||
// Non graphing
|
||||
metric('uptime', data.uptime, timeFilter, false)
|
||||
metric('retentionScanCompleted', data.retention.SecondsSinceScanCompleted, timeFilter, false)
|
||||
metric('retentionPeriod', data.retention.Period, timeFilter, false)
|
||||
metric('uptime', data.uptime, timeFilter, false);
|
||||
metric('retentionScanCompleted', data.retention.SecondsSinceScanCompleted, timeFilter, false);
|
||||
metric('retentionPeriod', data.retention.Period, timeFilter, false);
|
||||
|
||||
// JavaScript history
|
||||
metric('memstatsSys', data.memstats.Sys, sizeFilter, true)
|
||||
metric('memstatsHeapAlloc', data.memstats.HeapAlloc, sizeFilter, true)
|
||||
metric('memstatsHeapSys', data.memstats.HeapSys, sizeFilter, true)
|
||||
metric('memstatsHeapObjects', data.memstats.HeapObjects, numberFilter, true)
|
||||
metric('smtpConnectsCurrent', data.smtp.ConnectsCurrent, numberFilter, true)
|
||||
metric('memstatsSys', data.memstats.Sys, sizeFilter, true);
|
||||
metric('memstatsHeapAlloc', data.memstats.HeapAlloc, sizeFilter, true);
|
||||
metric('memstatsHeapSys', data.memstats.HeapSys, sizeFilter, true);
|
||||
metric('memstatsHeapObjects', data.memstats.HeapObjects, numberFilter, true);
|
||||
metric('smtpConnectsCurrent', data.smtp.ConnectsCurrent, numberFilter, true);
|
||||
|
||||
// Server-side history
|
||||
metric('smtpReceivedTotal', data.smtp.ReceivedTotal, numberFilter, false)
|
||||
setHistoryOfActivity('smtpReceivedTotal', data.smtp.ReceivedHist)
|
||||
metric('smtpConnectsTotal', data.smtp.ConnectsTotal, numberFilter, false)
|
||||
setHistoryOfActivity('smtpConnectsTotal', data.smtp.ConnectsHist)
|
||||
metric('smtpWarnsTotal', data.smtp.WarnsTotal, numberFilter, false)
|
||||
setHistoryOfActivity('smtpWarnsTotal', data.smtp.WarnsHist)
|
||||
metric('smtpErrorsTotal', data.smtp.ErrorsTotal, numberFilter, false)
|
||||
setHistoryOfActivity('smtpErrorsTotal', data.smtp.ErrorsHist)
|
||||
metric('retentionDeletesTotal', data.retention.DeletesTotal, numberFilter, false)
|
||||
setHistoryOfActivity('retentionDeletesTotal', data.retention.DeletesHist)
|
||||
metric('retainedCurrent', data.retention.RetainedCurrent, numberFilter, false)
|
||||
setHistoryOfCount('retainedCurrent', data.retention.RetainedHist)
|
||||
metric('smtpReceivedTotal', data.smtp.ReceivedTotal, numberFilter, false);
|
||||
setHistoryOfActivity('smtpReceivedTotal', data.smtp.ReceivedHist);
|
||||
metric('smtpConnectsTotal', data.smtp.ConnectsTotal, numberFilter, false);
|
||||
setHistoryOfActivity('smtpConnectsTotal', data.smtp.ConnectsHist);
|
||||
metric('smtpWarnsTotal', data.smtp.WarnsTotal, numberFilter, false);
|
||||
setHistoryOfActivity('smtpWarnsTotal', data.smtp.WarnsHist);
|
||||
metric('smtpErrorsTotal', data.smtp.ErrorsTotal, numberFilter, false);
|
||||
setHistoryOfActivity('smtpErrorsTotal', data.smtp.ErrorsHist);
|
||||
metric('retentionDeletesTotal', data.retention.DeletesTotal, numberFilter, false);
|
||||
setHistoryOfActivity('retentionDeletesTotal', data.retention.DeletesHist);
|
||||
metric('retainedCurrent', data.retention.RetainedCurrent, numberFilter, false);
|
||||
setHistoryOfCount('retainedCurrent', data.retention.RetainedHist);
|
||||
}
|
||||
|
||||
function loadMetrics() {
|
||||
// jQuery.getJSON( url [, data] [, success(data, textStatus, jqXHR)] )
|
||||
jQuery.getJSON('/debug/vars', null, displayMetrics)
|
||||
jQuery.getJSON('/debug/vars', null, displayMetrics);
|
||||
}
|
||||
|
||||
function aboutInit() {
|
||||
loadMetrics()
|
||||
setInterval(loadMetrics, 10000)
|
||||
$('#navStatus').addClass('active');
|
||||
loadMetrics();
|
||||
setInterval(loadMetrics, 10000);
|
||||
}
|
||||
|
||||
$(document).ready(aboutInit)
|
||||
|
||||
Reference in New Issue
Block a user