##// END OF EJS Templates
Merge pull request #6370 from minrk/handle-no-checkpoint...
Min RK -
r17717:5b68572e merge
parent child Browse files
Show More
@@ -1,242 +1,246
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 define([
4 define([
5 'base/js/namespace',
5 'base/js/namespace',
6 'jquery',
6 'jquery',
7 'base/js/utils',
7 'base/js/utils',
8 'base/js/dialog',
8 'base/js/dialog',
9 'base/js/keyboard',
9 'base/js/keyboard',
10 'moment',
10 'moment',
11 ], function(IPython, $, utils, dialog, keyboard, moment) {
11 ], function(IPython, $, utils, dialog, keyboard, moment) {
12 "use strict";
12 "use strict";
13
13
14 var SaveWidget = function (selector, options) {
14 var SaveWidget = function (selector, options) {
15 // TODO: Remove circular ref.
15 // TODO: Remove circular ref.
16 this.notebook = undefined;
16 this.notebook = undefined;
17 this.selector = selector;
17 this.selector = selector;
18 this.events = options.events;
18 this.events = options.events;
19 this._checkpoint_date = undefined;
19 this._checkpoint_date = undefined;
20 this.keyboard_manager = options.keyboard_manager;
20 this.keyboard_manager = options.keyboard_manager;
21 if (this.selector !== undefined) {
21 if (this.selector !== undefined) {
22 this.element = $(selector);
22 this.element = $(selector);
23 this.bind_events();
23 this.bind_events();
24 }
24 }
25 };
25 };
26
26
27
27
28 SaveWidget.prototype.bind_events = function () {
28 SaveWidget.prototype.bind_events = function () {
29 var that = this;
29 var that = this;
30 this.element.find('span#notebook_name').click(function () {
30 this.element.find('span#notebook_name').click(function () {
31 that.rename_notebook();
31 that.rename_notebook();
32 });
32 });
33 this.element.find('span#notebook_name').hover(function () {
33 this.element.find('span#notebook_name').hover(function () {
34 $(this).addClass("ui-state-hover");
34 $(this).addClass("ui-state-hover");
35 }, function () {
35 }, function () {
36 $(this).removeClass("ui-state-hover");
36 $(this).removeClass("ui-state-hover");
37 });
37 });
38 this.events.on('notebook_loaded.Notebook', function () {
38 this.events.on('notebook_loaded.Notebook', function () {
39 that.update_notebook_name();
39 that.update_notebook_name();
40 that.update_document_title();
40 that.update_document_title();
41 });
41 });
42 this.events.on('notebook_saved.Notebook', function () {
42 this.events.on('notebook_saved.Notebook', function () {
43 that.update_notebook_name();
43 that.update_notebook_name();
44 that.update_document_title();
44 that.update_document_title();
45 });
45 });
46 this.events.on('notebook_renamed.Notebook', function () {
46 this.events.on('notebook_renamed.Notebook', function () {
47 that.update_notebook_name();
47 that.update_notebook_name();
48 that.update_document_title();
48 that.update_document_title();
49 that.update_address_bar();
49 that.update_address_bar();
50 });
50 });
51 this.events.on('notebook_save_failed.Notebook', function () {
51 this.events.on('notebook_save_failed.Notebook', function () {
52 that.set_save_status('Autosave Failed!');
52 that.set_save_status('Autosave Failed!');
53 });
53 });
54 this.events.on('checkpoints_listed.Notebook', function (event, data) {
54 this.events.on('checkpoints_listed.Notebook', function (event, data) {
55 that._set_last_checkpoint(data[0]);
55 that._set_last_checkpoint(data[0]);
56 });
56 });
57
57
58 this.events.on('checkpoint_created.Notebook', function (event, data) {
58 this.events.on('checkpoint_created.Notebook', function (event, data) {
59 that._set_last_checkpoint(data);
59 that._set_last_checkpoint(data);
60 });
60 });
61 this.events.on('set_dirty.Notebook', function (event, data) {
61 this.events.on('set_dirty.Notebook', function (event, data) {
62 that.set_autosaved(data.value);
62 that.set_autosaved(data.value);
63 });
63 });
64 };
64 };
65
65
66
66
67 SaveWidget.prototype.rename_notebook = function (options) {
67 SaveWidget.prototype.rename_notebook = function (options) {
68 options = options || {};
68 options = options || {};
69 var that = this;
69 var that = this;
70 var dialog_body = $('<div/>').append(
70 var dialog_body = $('<div/>').append(
71 $("<p/>").addClass("rename-message")
71 $("<p/>").addClass("rename-message")
72 .text('Enter a new notebook name:')
72 .text('Enter a new notebook name:')
73 ).append(
73 ).append(
74 $("<br/>")
74 $("<br/>")
75 ).append(
75 ).append(
76 $('<input/>').attr('type','text').attr('size','25').addClass('form-control')
76 $('<input/>').attr('type','text').attr('size','25').addClass('form-control')
77 .val(that.notebook.get_notebook_name())
77 .val(that.notebook.get_notebook_name())
78 );
78 );
79 dialog.modal({
79 dialog.modal({
80 title: "Rename Notebook",
80 title: "Rename Notebook",
81 body: dialog_body,
81 body: dialog_body,
82 notebook: options.notebook,
82 notebook: options.notebook,
83 keyboard_manager: this.keyboard_manager,
83 keyboard_manager: this.keyboard_manager,
84 buttons : {
84 buttons : {
85 "Cancel": {},
85 "Cancel": {},
86 "OK": {
86 "OK": {
87 class: "btn-primary",
87 class: "btn-primary",
88 click: function () {
88 click: function () {
89 var new_name = $(this).find('input').val();
89 var new_name = $(this).find('input').val();
90 if (!that.notebook.test_notebook_name(new_name)) {
90 if (!that.notebook.test_notebook_name(new_name)) {
91 $(this).find('.rename-message').text(
91 $(this).find('.rename-message').text(
92 "Invalid notebook name. Notebook names must "+
92 "Invalid notebook name. Notebook names must "+
93 "have 1 or more characters and can contain any characters " +
93 "have 1 or more characters and can contain any characters " +
94 "except :/\\. Please enter a new notebook name:"
94 "except :/\\. Please enter a new notebook name:"
95 );
95 );
96 return false;
96 return false;
97 } else {
97 } else {
98 that.notebook.rename(new_name);
98 that.notebook.rename(new_name);
99 }
99 }
100 }}
100 }}
101 },
101 },
102 open : function (event, ui) {
102 open : function (event, ui) {
103 var that = $(this);
103 var that = $(this);
104 // Upon ENTER, click the OK button.
104 // Upon ENTER, click the OK button.
105 that.find('input[type="text"]').keydown(function (event, ui) {
105 that.find('input[type="text"]').keydown(function (event, ui) {
106 if (event.which === keyboard.keycodes.enter) {
106 if (event.which === keyboard.keycodes.enter) {
107 that.find('.btn-primary').first().click();
107 that.find('.btn-primary').first().click();
108 return false;
108 return false;
109 }
109 }
110 });
110 });
111 that.find('input[type="text"]').focus().select();
111 that.find('input[type="text"]').focus().select();
112 }
112 }
113 });
113 });
114 };
114 };
115
115
116
116
117 SaveWidget.prototype.update_notebook_name = function () {
117 SaveWidget.prototype.update_notebook_name = function () {
118 var nbname = this.notebook.get_notebook_name();
118 var nbname = this.notebook.get_notebook_name();
119 this.element.find('span#notebook_name').text(nbname);
119 this.element.find('span#notebook_name').text(nbname);
120 };
120 };
121
121
122
122
123 SaveWidget.prototype.update_document_title = function () {
123 SaveWidget.prototype.update_document_title = function () {
124 var nbname = this.notebook.get_notebook_name();
124 var nbname = this.notebook.get_notebook_name();
125 document.title = nbname;
125 document.title = nbname;
126 };
126 };
127
127
128 SaveWidget.prototype.update_address_bar = function(){
128 SaveWidget.prototype.update_address_bar = function(){
129 var base_url = this.notebook.base_url;
129 var base_url = this.notebook.base_url;
130 var nbname = this.notebook.notebook_name;
130 var nbname = this.notebook.notebook_name;
131 var path = this.notebook.notebook_path;
131 var path = this.notebook.notebook_path;
132 var state = {path : path, name: nbname};
132 var state = {path : path, name: nbname};
133 window.history.replaceState(state, "", utils.url_join_encode(
133 window.history.replaceState(state, "", utils.url_join_encode(
134 base_url,
134 base_url,
135 "notebooks",
135 "notebooks",
136 path,
136 path,
137 nbname)
137 nbname)
138 );
138 );
139 };
139 };
140
140
141
141
142 SaveWidget.prototype.set_save_status = function (msg) {
142 SaveWidget.prototype.set_save_status = function (msg) {
143 this.element.find('span#autosave_status').text(msg);
143 this.element.find('span#autosave_status').text(msg);
144 };
144 };
145
145
146 SaveWidget.prototype._set_checkpoint_status = function (human_date, iso_date) {
146 SaveWidget.prototype._set_checkpoint_status = function (human_date, iso_date) {
147 var el = this.element.find('span#checkpoint_status')
147 var el = this.element.find('span#checkpoint_status');
148 if(human_date){
148 if(human_date){
149 el.text("Last Checkpoint: "+human_date).attr('title',iso_date);
149 el.text("Last Checkpoint: "+human_date).attr('title',iso_date);
150 } else {
150 } else {
151 el.text('').attr('title','no-checkpoint')
151 el.text('').attr('title', 'no-checkpoint');
152 }
152 }
153 };
153 };
154
154
155 // compute (roughly) the remaining time in millisecond until the next
155 // compute (roughly) the remaining time in millisecond until the next
156 // moment.js relative time update of the string, which by default
156 // moment.js relative time update of the string, which by default
157 // happend at
157 // happend at
158 // (a few seconds ago)
158 // (a few seconds ago)
159 // - 45sec,
159 // - 45sec,
160 // (a minute ago)
160 // (a minute ago)
161 // - 90sec,
161 // - 90sec,
162 // ( x minutes ago)
162 // ( x minutes ago)
163 // - then every minutes until
163 // - then every minutes until
164 // - 45 min,
164 // - 45 min,
165 // (an hour ago)
165 // (an hour ago)
166 // - 1h45,
166 // - 1h45,
167 // (x hours ago )
167 // (x hours ago )
168 // - then every hours
168 // - then every hours
169 // - 22 hours ago
169 // - 22 hours ago
170 var _next_timeago_update = function(deltatime_ms){
170 var _next_timeago_update = function(deltatime_ms){
171 var s = 1000;
171 var s = 1000;
172 var m = 60*s;
172 var m = 60*s;
173 var h = 60*m;
173 var h = 60*m;
174
174
175 var mtt = moment.relativeTimeThreshold;
175 var mtt = moment.relativeTimeThreshold;
176
176
177 if(deltatime_ms < mtt.s*s){
177 if(deltatime_ms < mtt.s*s){
178 return mtt.s*s-deltatime_ms;
178 return mtt.s*s-deltatime_ms;
179 } else if (deltatime_ms < (mtt.s*s+m)) {
179 } else if (deltatime_ms < (mtt.s*s+m)) {
180 return (mtt.s*s+m)-deltatime_ms;
180 return (mtt.s*s+m)-deltatime_ms;
181 } else if (deltatime_ms < mtt.m*m){
181 } else if (deltatime_ms < mtt.m*m){
182 return m;
182 return m;
183 } else if (deltatime_ms < (mtt.m*m+h)){
183 } else if (deltatime_ms < (mtt.m*m+h)){
184 return (mtt.m*m+h)-deltatime_ms;
184 return (mtt.m*m+h)-deltatime_ms;
185 } else {
185 } else {
186 return h;
186 return h;
187 }
187 }
188
188 };
189
190 }
191
189
192 SaveWidget.prototype._regularly_update_checkpoint_date = function(){
190 SaveWidget.prototype._regularly_update_checkpoint_date = function(){
193 if (!this._checkpoint_date) {
191 if (!this._checkpoint_date) {
194 this.set_checkpoint_status(null);
192 this._set_checkpoint_status(null);
195 console.log('no checkpoint done');
193 console.log('no checkpoint done');
196 return;
194 return;
197 }
195 }
198 var chkd = moment(this._checkpoint_date);
196 var chkd = moment(this._checkpoint_date);
199 var longdate = chkd.format('llll');
197 var longdate = chkd.format('llll');
200
198
201 var that = this;
199 var that = this;
202 var recall = function(t){
200 var recall = function(t){
203 // recall slightly later (1s) as long timeout in js might be imprecise,
201 // recall slightly later (1s) as long timeout in js might be imprecise,
204 // and you want to be call **after** the change of formatting should happend.
202 // and you want to be call **after** the change of formatting should happend.
205 return setTimeout($.proxy(that._regularly_update_checkpoint_date, that),(t+1000))
203 return setTimeout(
204 $.proxy(that._regularly_update_checkpoint_date, that),
205 t + 1000
206 );
206 }
207 }
207 var tdelta = Math.ceil(new Date()-this._checkpoint_date);
208 var tdelta = Math.ceil(new Date()-this._checkpoint_date);
208
209
209 // update regularly for the first 6hours and show
210 // update regularly for the first 6hours and show
210 // <x time> ago
211 // <x time> ago
211 if(tdelta < tdelta < 6*3600*1000){
212 if(tdelta < tdelta < 6*3600*1000){
212 recall(_next_timeago_update(tdelta));
213 recall(_next_timeago_update(tdelta));
213 this._set_checkpoint_status( chkd.fromNow(), longdate);
214 this._set_checkpoint_status(chkd.fromNow(), longdate);
214 // otherwise update every hour and show
215 // otherwise update every hour and show
215 // <Today | yesterday|...> at hh,mm,ss
216 // <Today | yesterday|...> at hh,mm,ss
216 } else {
217 } else {
217 recall(1*3600*1000)
218 recall(1*3600*1000);
218 this._set_checkpoint_status( chkd.calendar(), longdate);
219 this._set_checkpoint_status(chkd.calendar(), longdate);
219 }
220 }
220
221 };
221 }
222
222
223 SaveWidget.prototype._set_last_checkpoint = function (checkpoint) {
223 SaveWidget.prototype._set_last_checkpoint = function (checkpoint) {
224 if (checkpoint) {
224 this._checkpoint_date = new Date(checkpoint.last_modified);
225 this._checkpoint_date = new Date(checkpoint.last_modified);
226 } else {
227 this._checkpoint_date = null;
228 }
225 this._regularly_update_checkpoint_date();
229 this._regularly_update_checkpoint_date();
226
230
227 };
231 };
228
232
229 SaveWidget.prototype.set_autosaved = function (dirty) {
233 SaveWidget.prototype.set_autosaved = function (dirty) {
230 if (dirty) {
234 if (dirty) {
231 this.set_save_status("(unsaved changes)");
235 this.set_save_status("(unsaved changes)");
232 } else {
236 } else {
233 this.set_save_status("(autosaved)");
237 this.set_save_status("(autosaved)");
234 }
238 }
235 };
239 };
236
240
237 // Backwards compatibility.
241 // Backwards compatibility.
238 IPython.SaveWidget = SaveWidget;
242 IPython.SaveWidget = SaveWidget;
239
243
240 return {'SaveWidget': SaveWidget};
244 return {'SaveWidget': SaveWidget};
241
245
242 });
246 });
General Comments 0
You need to be logged in to leave comments. Login now