diff --git a/IPython/html/static/components b/IPython/html/static/components index a80ac7a..b3909af 160000 --- a/IPython/html/static/components +++ b/IPython/html/static/components @@ -1 +1 @@ -Subproject commit a80ac7a2f6d045e3903d3c9e189a10cc96255b05 +Subproject commit b3909af1b61ca7a412481759fdb441ecdfb3ab66 diff --git a/IPython/html/static/notebook/js/menubar.js b/IPython/html/static/notebook/js/menubar.js index a6f0b28..42a0beb 100644 --- a/IPython/html/static/notebook/js/menubar.js +++ b/IPython/html/static/notebook/js/menubar.js @@ -7,7 +7,8 @@ define([ 'base/js/utils', 'notebook/js/tour', 'bootstrap', -], function(IPython, $, utils, tour) { + 'moment', +], function(IPython, $, utils, tour, bootstrap, moment) { "use strict"; var MenuBar = function (selector, options) { @@ -335,7 +336,7 @@ define([ $("
  • ").append( $("") .attr("href", "#") - .text(d.format("mmm dd HH:MM:ss")) + .text(moment(d).format("LLLL")) .click(function () { that.notebook.restore_checkpoint_dialog(checkpoint); }) diff --git a/IPython/html/static/notebook/js/notificationarea.js b/IPython/html/static/notebook/js/notificationarea.js index 6566667..54a398a 100644 --- a/IPython/html/static/notebook/js/notificationarea.js +++ b/IPython/html/static/notebook/js/notificationarea.js @@ -7,7 +7,8 @@ define([ 'base/js/utils', 'base/js/dialog', 'notebook/js/notificationwidget', -], function(IPython, $, utils, dialog, notificationwidget) { + 'moment' +], function(IPython, $, utils, dialog, notificationwidget, moment) { "use strict"; var NotificationArea = function (selector, options) { @@ -208,7 +209,7 @@ define([ var msg = "Checkpoint created"; if (data.last_modified) { var d = new Date(data.last_modified); - msg = msg + ": " + d.format("HH:MM:ss"); + msg = msg + ": " + moment(d).format("HH:mm:ss"); } nnw.set_message(msg, 2000); }); diff --git a/IPython/html/static/notebook/js/savewidget.js b/IPython/html/static/notebook/js/savewidget.js index 7daddcd..0a7cff1 100644 --- a/IPython/html/static/notebook/js/savewidget.js +++ b/IPython/html/static/notebook/js/savewidget.js @@ -7,8 +7,8 @@ define([ 'base/js/utils', 'base/js/dialog', 'base/js/keyboard', - 'dateformat', -], function(IPython, $, utils, dialog, keyboard, dateformat) { + 'moment', +], function(IPython, $, utils, dialog, keyboard, moment) { "use strict"; var SaveWidget = function (selector, options) { @@ -16,6 +16,7 @@ define([ this.notebook = undefined; this.selector = selector; this.events = options.events; + this._checkpoint_date = undefined; this.keyboard_manager = options.keyboard_manager; if (this.selector !== undefined) { this.element = $(selector); @@ -51,11 +52,11 @@ define([ that.set_save_status('Autosave Failed!'); }); this.events.on('checkpoints_listed.Notebook', function (event, data) { - that.set_last_checkpoint(data[0]); + that._set_last_checkpoint(data[0]); }); this.events.on('checkpoint_created.Notebook', function (event, data) { - that.set_last_checkpoint(data); + that._set_last_checkpoint(data); }); this.events.on('set_dirty.Notebook', function (event, data) { that.set_autosaved(data.value); @@ -123,7 +124,7 @@ define([ var nbname = this.notebook.get_notebook_name(); document.title = nbname; }; - + SaveWidget.prototype.update_address_bar = function(){ var base_url = this.notebook.base_url; var nbname = this.notebook.notebook_name; @@ -142,19 +143,87 @@ define([ this.element.find('span#autosave_status').text(msg); }; - SaveWidget.prototype.set_checkpoint_status = function (msg) { - this.element.find('span#checkpoint_status').text(msg); + SaveWidget.prototype._set_checkpoint_status = function (human_date, iso_date) { + var el = this.element.find('span#checkpoint_status') + if(human_date){ + el.text("Last Checkpoint: "+human_date).attr('title',iso_date); + } else { + el.text('').attr('title','no-checkpoint') + } }; - SaveWidget.prototype.set_last_checkpoint = function (checkpoint) { - if (!checkpoint) { - this.set_checkpoint_status(""); + // compute (roughly) the remaining time in millisecond until the next + // moment.js relative time update of the string, which by default + // happend at + // (a few seconds ago) + // - 45sec, + // (a minute ago) + // - 90sec, + // ( x minutes ago) + // - then every minutes until + // - 45 min, + // (an hour ago) + // - 1h45, + // (x hours ago ) + // - then every hours + // - 22 hours ago + var _next_timeago_update = function(deltatime_ms){ + var s = 1000; + var m = 60*s; + var h = 60*m; + + var mtt = moment.relativeTimeThreshold; + + if(deltatime_ms < mtt.s*s){ + return mtt.s*s-deltatime_ms; + } else if (deltatime_ms < (mtt.s*s+m)) { + return (mtt.s*s+m)-deltatime_ms; + } else if (deltatime_ms < mtt.m*m){ + return m; + } else if (deltatime_ms < (mtt.m*m+h)){ + return (mtt.m*m+h)-deltatime_ms; + } else { + return h; + } + + + } + + SaveWidget.prototype._regularly_update_checkpoint_date = function(){ + if (!this._checkpoint_date) { + this.set_checkpoint_status(null); + console.log('no checkpoint done'); return; } - var d = new Date(checkpoint.last_modified); - this.set_checkpoint_status( - "Last Checkpoint: " + dateformat(d,'mmm dd HH:MM') - ); + var chkd = moment(this._checkpoint_date); + var longdate = chkd.format('llll'); + + var that = this; + var recall = function(t){ + // recall slightly later (1s) as long timeout in js might be imprecise, + // and you want to be call **after** the change of formatting should happend. + return setTimeout($.proxy(that._regularly_update_checkpoint_date, that),(t+1000)) + } + var tdelta = Math.ceil(new Date()-this._checkpoint_date); + + // update regularly for the first 6hours and show + // ago + if(tdelta < tdelta < 6*3600*1000){ + recall(_next_timeago_update(tdelta)); + this._set_checkpoint_status( chkd.fromNow(), longdate); + // otherwise update every hour and show + // at hh,mm,ss + } else { + recall(1*3600*1000) + this._set_checkpoint_status( chkd.calendar(), longdate); + } + + } + + SaveWidget.prototype._set_last_checkpoint = function (checkpoint) { + this._checkpoint_date = new Date(checkpoint.last_modified); + this._regularly_update_checkpoint_date(); + }; SaveWidget.prototype.set_autosaved = function (dirty) { diff --git a/IPython/html/static/notebook/less/savewidget.less b/IPython/html/static/notebook/less/savewidget.less index 5b7c6ef..59e4757 100644 --- a/IPython/html/static/notebook/less/savewidget.less +++ b/IPython/html/static/notebook/less/savewidget.less @@ -31,4 +31,4 @@ span#checkpoint_status, span#autosave_status { } } - \ No newline at end of file + diff --git a/IPython/html/templates/page.html b/IPython/html/templates/page.html index fc38982..ea0a89d 100644 --- a/IPython/html/templates/page.html +++ b/IPython/html/templates/page.html @@ -28,6 +28,7 @@ dateformat: 'dateformat/date.format', jqueryui: 'components/jquery-ui/ui/minified/jquery-ui.min', highlight: 'components/highlight.js/build/highlight.pack', + moment: "components/moment/moment", }, shim: { underscore: { diff --git a/setupbase.py b/setupbase.py index 269c02d..f2f20d1 100644 --- a/setupbase.py +++ b/setupbase.py @@ -160,6 +160,8 @@ def find_package_data(): pjoin(components, "marked", "lib", "marked.js"), pjoin(components, "requirejs", "require.js"), pjoin(components, "underscore", "underscore-min.js"), + pjoin(components, "moment", "moment.js"), + pjoin(components, "moment", "min","moment.min.js"), ]) # Ship all of Codemirror's CSS and JS