mirror of https://github.com/mthenw/frontail.git
parent
c58955c627
commit
a32ee45021
|
@ -2,7 +2,7 @@
|
|||
|
||||
```frontail``` is node.js application for serving `tail -F` output to browser.
|
||||
|
||||
[](https://travis-ci.org/mthenw/frontail)
|
||||
[](https://travis-ci.org/mthenw/frontail)
|
||||
[](http://badge.fury.io/js/frontail)
|
||||
|
||||
## Features
|
||||
|
@ -39,6 +39,8 @@
|
|||
-c, --certificate <cert.pem> Certificate for HTTPS, option works only along with -k option
|
||||
--pid-path <path> if run as daemon file that will store the process id, default /var/run/frontail.pid
|
||||
--log-path <path> if run as daemon file that will be used as a log, default /dev/null
|
||||
--ui-hide-topbar hide topbar (log file name and search box)
|
||||
--ui-no-indent don't indent log lines (every line after first one)
|
||||
|
||||
Web interface is on http://localhost:[port]
|
||||
|
||||
|
|
5
index.js
5
index.js
|
@ -36,6 +36,8 @@ program
|
|||
String, '/var/run/frontail.pid')
|
||||
.option('--log-path <path>', 'if run as daemon file that will be used as a log, default /dev/null',
|
||||
String, '/dev/null')
|
||||
.option('--ui-hide-topbar', 'hide topbar (log file name and search box)')
|
||||
.option('--ui-no-indent', 'don\'t indent log lines (every line after first one)')
|
||||
.parse(process.argv);
|
||||
|
||||
if (program.args.length === 0) {
|
||||
|
@ -125,6 +127,9 @@ if (program.daemonize) {
|
|||
var filesSocket = io.of('/' + filesNamespace).on('connection', function (socket) {
|
||||
socket.emit('options:lines', program.lines);
|
||||
|
||||
program.uiHideTopbar && socket.emit('options:hide-topbar');
|
||||
!program.uiIndent && socket.emit('options:no-indent');
|
||||
|
||||
tailer.getBuffer().forEach(function (line) {
|
||||
socket.emit('line', line);
|
||||
});
|
||||
|
|
|
@ -26,6 +26,18 @@ window.App = (function (window, document) {
|
|||
*/
|
||||
var _filterValue = '';
|
||||
|
||||
/**
|
||||
* @type {HTMLElement}
|
||||
* @private
|
||||
*/
|
||||
var _topbar;
|
||||
|
||||
/**
|
||||
* @type {HTMLElement}
|
||||
* @private
|
||||
*/
|
||||
var _body;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
|
@ -127,20 +139,12 @@ window.App = (function (window, document) {
|
|||
init: function (opts) {
|
||||
var self = this;
|
||||
|
||||
// socket.io init
|
||||
_socket = opts.socket;
|
||||
_socket
|
||||
.on('options:lines', function (limit) {
|
||||
_linesLimit = limit;
|
||||
})
|
||||
.on('line', function (line) {
|
||||
self.log(line);
|
||||
});
|
||||
|
||||
// Elements
|
||||
_logContainer = opts.container;
|
||||
_filterInput = opts.filterInput;
|
||||
_filterInput.focus();
|
||||
_topbar = opts.topbar;
|
||||
_body = opts.body;
|
||||
|
||||
// Filter input bind
|
||||
_filterInput.addEventListener('keyup', function (e) {
|
||||
|
@ -161,6 +165,23 @@ window.App = (function (window, document) {
|
|||
_isWindowFocused = true;
|
||||
_faviconReset();
|
||||
}, true);
|
||||
|
||||
// socket.io init
|
||||
_socket = opts.socket;
|
||||
_socket
|
||||
.on('options:lines', function (limit) {
|
||||
_linesLimit = limit;
|
||||
})
|
||||
.on('options:hide-topbar', function () {
|
||||
_topbar.className += ' hide';
|
||||
_body.className = 'no-topbar';
|
||||
})
|
||||
.on('options:no-indent', function () {
|
||||
_logContainer.className += ' no-indent';
|
||||
})
|
||||
.on('line', function (line) {
|
||||
self.log(line);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,6 +5,10 @@ body {
|
|||
background-color: #2F3238;
|
||||
}
|
||||
|
||||
.no-topbar {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background-color: #26292E;
|
||||
border: 0;
|
||||
|
@ -32,6 +36,11 @@ body {
|
|||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.log.no-indent .inner-line {
|
||||
margin-left: 0;
|
||||
text-indent: 0;
|
||||
}
|
||||
|
||||
.log .line-selected {
|
||||
background-color: #302436;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ body {
|
|||
padding-top: 4em;
|
||||
}
|
||||
|
||||
.no-topbar {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-brand {
|
||||
color: white;
|
||||
}
|
||||
|
@ -24,6 +28,11 @@ body {
|
|||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.log.no-indent .inner-line {
|
||||
margin-left: 0;
|
||||
text-indent: 0;
|
||||
}
|
||||
|
||||
.log .line-selected {
|
||||
background-color: #ffb2b0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<link rel="icon" href="/favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||
<nav class="topbar navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<span class="navbar-brand" href="#">tail -F __TITLE__</span>
|
||||
<form class="navbar-form navbar-right" role="search">
|
||||
|
@ -29,8 +29,10 @@
|
|||
window.load = App.init({
|
||||
socket: socket,
|
||||
container: document.getElementsByClassName('log')[0],
|
||||
filterInput: document.getElementsByClassName('query')[0]
|
||||
filterInput: document.getElementsByClassName('query')[0],
|
||||
topbar: document.getElementsByClassName('topbar')[0],
|
||||
body: document.getElementsByTagName('body')[0]
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "frontail",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"description": "tail -F output in browser",
|
||||
"homepage": "https://github.com/mthenw/frontail",
|
||||
"author": "Maciej Winnicki <maciej.winnicki@gmail.com>",
|
||||
|
|
34
test/app.js
34
test/app.js
|
@ -11,7 +11,7 @@ describe('browser application', function () {
|
|||
io = new EventEmitter();
|
||||
|
||||
jsdom.env(
|
||||
'<title></title><body><div id="log"></div><input type="test" id="filter"/></body>',
|
||||
'<title></title><body><div class="topbar"></div><div class="log"></div><input type="test" id="filter"/></body>',
|
||||
['../lib/web/assets/app.js', './lib/jquery.js'],
|
||||
function (errors, domWindow) {
|
||||
window = domWindow;
|
||||
|
@ -24,7 +24,7 @@ describe('browser application', function () {
|
|||
|
||||
io.emit('line', 'test');
|
||||
|
||||
var log = window.document.getElementById('log');
|
||||
var log = window.document.querySelector('.log');
|
||||
log.childNodes.length.should.be.equal(1);
|
||||
log.childNodes[0].textContent.should.be.equal('test');
|
||||
log.childNodes[0].className.should.be.equal('line');
|
||||
|
@ -61,17 +61,39 @@ describe('browser application', function () {
|
|||
io.emit('line', 'line2');
|
||||
io.emit('line', 'line3');
|
||||
|
||||
var log = window.document.getElementById('log');
|
||||
var log = window.document.querySelector('.log');
|
||||
log.childNodes.length.should.be.equal(2);
|
||||
log.childNodes[0].textContent.should.be.equal('line2');
|
||||
log.childNodes[1].textContent.should.be.equal('line3');
|
||||
});
|
||||
|
||||
it('should hide topbar', function () {
|
||||
initApp();
|
||||
|
||||
io.emit('options:hide-topbar');
|
||||
|
||||
var topbar = window.document.querySelector('.topbar');
|
||||
topbar.className.should.match(/hide/);
|
||||
var body = window.document.querySelector('body');
|
||||
body.className.should.match(/no-topbar/);
|
||||
});
|
||||
|
||||
it('should not indent log lines', function () {
|
||||
initApp();
|
||||
|
||||
io.emit('options:no-indent');
|
||||
|
||||
var log = window.document.querySelector('.log');
|
||||
log.className.should.match(/no-indent/);
|
||||
});
|
||||
|
||||
function initApp() {
|
||||
window.App.init({
|
||||
socket: io,
|
||||
container: window.document.getElementById('log'),
|
||||
filterInput: window.document.getElementById('filter')
|
||||
container: window.document.querySelector('.log'),
|
||||
filterInput: window.document.querySelector('#filter'),
|
||||
topbar: window.document.querySelector('.topbar'),
|
||||
body: window.document.querySelector('body')
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -80,4 +102,4 @@ describe('browser application', function () {
|
|||
click.initMouseEvent('click', true, true);
|
||||
line.dispatchEvent(click);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue