Mercurial > piecrust2
changeset 615:cbb170d9c894
admin: Improve publish logs showing as alerts in the admin panel.
* Don't show stuff that happened before the page was opened.
* Skinning tweaks.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 04 Feb 2016 21:50:18 -0800 |
parents | a2d9ef307a08 |
children | ccd328d0881f |
files | foodtruck/pubutil.py foodtruck/templates/layouts/master.html foodtruckui/assets/js/foodtruck.js foodtruckui/assets/sass/foodtruck.scss foodtruckui/assets/sass/foodtruck/_base.scss foodtruckui/assets/sass/foodtruck/_publog.scss |
diffstat | 6 files changed, 118 insertions(+), 75 deletions(-) [+] |
line wrap: on
line diff
--- a/foodtruck/pubutil.py Thu Feb 04 21:49:15 2016 -0800 +++ b/foodtruck/pubutil.py Thu Feb 04 21:50:18 2016 -0800 @@ -28,7 +28,20 @@ lambda *args: _shutdown_server_and_raise_sigint()) +def _read_pid_file(pid_file): + logger.debug("Reading PID file: %s" % pid_file) + try: + with open(pid_file, 'r') as fp: + pid_str = fp.read() + + return int(pid_str.strip()) + except Exception: + logger.error("Error reading PID file.") + raise + + def _pid_exists(pid): + logger.debug("Checking if process ID %d is running" % pid) try: os.kill(pid, 0) except OSError as ex: @@ -44,61 +57,52 @@ return True -def _read_pid_file(pid_file): - logger.debug("Reading PID file: %s" % pid_file) - try: - with open(pid_file, 'r') as fp: - pid_str = fp.read() - - return int(pid_str.strip()) - except Exception: - logger.error("Error reading PID file.") - raise - - class PublishLogReader(object): - _pub_max_time = 10 * 60 # Don't bother about pubs older than 10mins. _poll_interval = 1 # Check the process every 1 seconds. _ping_interval = 30 # Send a ping message every 30 seconds. def __init__(self, pid_path, log_path): self.pid_path = pid_path self.log_path = log_path - self._pub_pid_mtime = 0 - self._last_seek = -1 - self._last_ping_time = 0 def run(self): logger.debug("Opening publish log...") pid = None + pid_mtime = 0 is_running = False + last_seek = -1 + last_ping_time = 0 try: while not server_shutdown: # PING! - interval = time.time() - self._last_ping_time + interval = time.time() - last_ping_time if interval > self._ping_interval: logger.debug("Sending ping...") - self._last_ping_time = time.time() + last_ping_time = time.time() yield bytes("event: ping\ndata: 1\n\n", 'utf8') - # Check if the PID file has changed. + # Check the PID file timestamp. try: new_mtime = os.path.getmtime(self.pid_path) except OSError: new_mtime = 0 - if (new_mtime > 0 and - time.time() - new_mtime > self._pub_max_time): - new_mtime = 0 + # If there's a valid PID file and we either just started + # streaming (pid_mtime == 0) or we remember an older version + # of that PID file (pid_mtime != new_mtime), let's read the + # PID from the file. + is_pid_file_prehistoric = False + if new_mtime > 0 and new_mtime != pid_mtime: + is_pid_file_prehistoric = (pid_mtime == 0) + pid_mtime = new_mtime + pid = _read_pid_file(self.pid_path) - # Re-read the PID file. - prev_mtime = self._pub_pid_mtime - if new_mtime > 0 and new_mtime != prev_mtime: - self._pub_pid_mtime = new_mtime - pid = _read_pid_file(self.pid_path) - if pid: - logger.debug("Monitoring new process, PID: %d" % pid) + if is_pid_file_prehistoric: + logger.debug("PID file is pre-historic, we will skip the " + "first parts of the log.") + # If we have a valid PID, let's check if the process is + # currently running. was_running = is_running if pid: is_running = _pid_exists(pid) @@ -106,29 +110,41 @@ "Process %d is %s" % (pid, 'running' if is_running else 'not running')) if not is_running: + # Let's forget this PID file until it changes. pid = None else: is_running = False - # Send data. + # Read new data from the log file. new_data = None if is_running or was_running: - if self._last_seek < 0: - outstr = 'event: message\ndata: Publish started.\n\n' - yield bytes(outstr, 'utf8') - self._last_seek = 0 + if last_seek < 0: + # Only send the "publish started" message if we + # actually caught the process as it was starting, not + # if we started streaming after it started. + # This means we saw the PID file get changed. + if not is_pid_file_prehistoric: + outstr = ( + 'event: message\n' + 'data: Publish started.\n\n') + yield bytes(outstr, 'utf8') + last_seek = 0 try: with open(self.log_path, 'r', encoding='utf8') as fp: - fp.seek(self._last_seek) + fp.seek(last_seek) new_data = fp.read() - self._last_seek = fp.tell() + last_seek = fp.tell() except OSError: pass if not is_running: - self._last_seek = 0 + # Process is not running anymore, let's reset our seek + # marker back to the beginning. + last_seek = -1 - if new_data: + # Stream the new data to the client, but don't send old stuff + # that happened before we started this stream. + if new_data and not is_pid_file_prehistoric: logger.debug("SSE: %s" % new_data) for line in new_data.split('\n'): outstr = 'event: message\ndata: %s\n\n' % line
--- a/foodtruck/templates/layouts/master.html Thu Feb 04 21:49:15 2016 -0800 +++ b/foodtruck/templates/layouts/master.html Thu Feb 04 21:50:18 2016 -0800 @@ -21,7 +21,12 @@ {% block content %}{% endblock %} </section> {% block after_content %}{% endblock %} - <div id="ft-publog"></div> + <div id="ft-publog" class="ft-publog" role="alert" style="display: none;"> + <button type="button" class="close" aria-label="close"> + <span aria-hidden="true">×</span> + </button> + <div id="ft-publog-container"></div> + </div> <footer> <p>Prepared by <a href="http://bolt80.com">BOLT80</a>.</p> <p>Much <span class="icon ion-heart"></span> to
--- a/foodtruckui/assets/js/foodtruck.js Thu Feb 04 21:49:15 2016 -0800 +++ b/foodtruckui/assets/js/foodtruck.js Thu Feb 04 21:50:18 2016 -0800 @@ -5,35 +5,47 @@ $('#ft-commit-modal').on('shown.bs.modal', function () { $('#ft-commit-msg').focus(); }); + + var publogEl = $('#ft-publog'); + publogEl.mouseenter(function() { + publogEl.attr('data-autohide', 'false'); + }); + publogEl.on('hide', function() { + var containerEl = $('#ft-publog-container', publogEl); + containerEl.empty(); + }); + + var closePublogBtn = $('button', publogEl); + closePublogBtn.on('click', function() { + publogEl.fadeOut(200); + }); }); var onPublishEvent = function(e) { - var msgEl = $('<div></div>'); + var publogEl = $('#ft-publog'); + var containerEl = $('#ft-publog-container', publogEl); + + var msgEl = $('<div>' + e.data + '</div>'); var removeMsgEl = function() { msgEl.remove(); - var publogEl = $('#ft-publog'); - if (publogEl.children().length == 0) { - publogEl.hide(); + if (containerEl.children().length == 0) { + // Last message, hide the log window. + publogEl.fadeOut(200); } }; - - msgEl.addClass('alert-dismissible'); - msgEl.attr('role', 'alert'); - msgEl.append('<button type="button" class="close" data-dismiss="alert" aria-label="close">' + - '<span aria-hidden="true">×</span></button>'); - msgEl.append('<div>' + e.data + '</div>'); var timeoutId = window.setTimeout(function() { - msgEl.fadeOut(400, removeMsgEl); + if (publogEl.attr('data-autohide') == 'true') { + msgEl.fadeOut(400, removeMsgEl); + } }, 4000); - msgEl.mouseenter(function() { - window.clearTimeout(timeoutId); - }); - $('button', msgEl).click(removeMsgEl); - var logEl = $('#ft-publog'); - logEl.append(msgEl); - logEl.show(); + if (containerEl.children().length == 0) { + // First message, show the log window, reset the mouseover marker. + publogEl.attr('data-autohide', 'true'); + publogEl.fadeIn(200); + } + containerEl.append(msgEl); }; if (!!window.EventSource) { @@ -45,3 +57,4 @@ source.addEventListener('message', onPublishEvent); } +
--- a/foodtruckui/assets/sass/foodtruck.scss Thu Feb 04 21:49:15 2016 -0800 +++ b/foodtruckui/assets/sass/foodtruck.scss Thu Feb 04 21:50:18 2016 -0800 @@ -40,4 +40,5 @@ @import "foodtruck/base"; @import "foodtruck/sidebar"; @import "foodtruck/editing"; +@import "foodtruck/publog";
--- a/foodtruckui/assets/sass/foodtruck/_base.scss Thu Feb 04 21:49:15 2016 -0800 +++ b/foodtruckui/assets/sass/foodtruck/_base.scss Thu Feb 04 21:50:18 2016 -0800 @@ -45,21 +45,3 @@ padding: 0 0.2em; } -#ft-publog { - position: fixed; - right: 0; - bottom: 0; - margin: 0.5em; - width: 50%; - max-width: 30em; - display: none; -} -#ft-publog>div { - padding: 1em 35px 1em 1em; - margin: 0.3em; - color: $ft-color-gray-light; - background: $ft-color-gray-darker; - border-radius: 0.5em; - box-shadow: 0 0 10px $ft-color-gray-dark; -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foodtruckui/assets/sass/foodtruck/_publog.scss Thu Feb 04 21:50:18 2016 -0800 @@ -0,0 +1,26 @@ + +#ft-publog { + position: fixed; + right: 0; + bottom: 0; + width: 42%; + min-width: 20em; + margin: 0.5em; + color: $ft-color-white; + background: $ft-color-blue; + border-radius: 0.5em; + box-shadow: 0 0 10px darken($ft-color-blue, 50%); + + button { + padding: 0.2em 0.4em; + } +} + +#ft-publog-container { + margin: 1em; + + div { + margin: 0.1em; + } +} +