Skip to content
This repository

Brian's Notebook work #899

Merged
merged 23 commits into from over 2 years ago

3 participants

Min RK Fernando Perez Brian E. Granger
Min RK
Owner

This is a rebase of Brian's recent notebook work. It is principally a bit of housekeeping on some files and namespaces, but also fixes a bug preventing the password authentication from working in some environments.

Fernando Perez
Owner

Everything looks great, except that I'd put the todo.rst file in the docs, not in the code directories. Otherwise good to go.

Min RK
Owner

Arg - I should have noted that it would be easier to rebase #897 on top of this one, rather than vice versa, since it's only one commit. Shouldn't be a big deal, though.

Fernando Perez
Owner

Sorry! Just trying to keep up with you and push that open PR count down to 0 :)

Min RK
Owner

the conflict was tiny. Rebased again, with todo moved to dev docs.

Fernando Perez fperez merged commit 284cfec into from October 18, 2011
Fernando Perez fperez closed this October 18, 2011
Fernando Perez fperez referenced this pull request from a commit January 10, 2012
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 23 unique commits by 2 authors.

Oct 18, 2011
Brian E. Granger Adding base_project_url and base_kernel_url as HTML data attribs.
* Also saving the notebook_id using that as well.
9ba28df
Min RK don't present meaningless username option in notebook
username isn't used for anything other than hash input
for authentication, so remove the field in the login form
and just use a uuid.
29cdf0f
Brian E. Granger Minor changes to handlers. e3e41dc
Brian E. Granger Removing focus.html. ddfe765
Brian E. Granger Misc changes to the notebook.
* IPythonNotebookApp->NotebookApp.
* Cleaned up html templates of unused stylesheets.
e64adb9
Brian E. Granger Adding data-project to the body data attribs. a676e3d
Brian E. Granger Updating JS URL scheme to use embedded data.
All ajax requests from JS now use the data-base-project-url
and data-base-kernel-url data attributes set on the body.
e45f706
Brian E. Granger Updating notebook list to use data-base-project-url. 4ecb79d
Brian E. Granger Further work updating JS URL scheme to use data-base-project-url. e5c5e2e
Brian E. Granger Simplifying logic on login page. a704e24
Brian E. Granger Renaming things in the notebook.
* nbbrowser -> projectdashboard.
* Getting rid of underscores on .js filenames.
7c74d0b
Brian E. Granger Further cleanup and renaming of notebook. 0bd5d55
Brian E. Granger Renaming NBBrowserHandler->ProjectDashboardHandler. 23289ed
Brian E. Granger Removed save widget delay. 2d0493e
Brian E. Granger Minor changes to the notebook handlers. a0b37c9
Min RK Renaming user cookie to username to better match usage. 9d26999
Min RK Moving status widget to Kernel section of L panel. c912b45
Brian E. Granger Added kill_kernel to notebook template. eed0376
Brian E. Granger Adding todo.rst for notebook. 3168128
Brian E. Granger Using self.request._cookies in WS handlers. a16d5e3
Min RK update notebook todo 9b6c843
Min RK move notebook todo into dev docs 3901181
Min RK style Sign In button with jQuery b7e6ff5
This page is out of date. Refresh to see the latest.

Showing 20 changed files with 211 additions and 182 deletions. Show diff stats Hide diff stats

  1. 6  IPython/core/profileapp.py
  2. 56  IPython/frontend/html/notebook/handlers.py
  3. 26  IPython/frontend/html/notebook/notebookapp.py
  4. 11  IPython/frontend/html/notebook/static/css/notebook.css
  5. 0  IPython/frontend/html/notebook/static/css/{nbbrowser.css → projectdashboard.css}
  6. 8  IPython/frontend/html/notebook/static/js/kernel.js
  7. 30  IPython/frontend/html/notebook/static/js/loginmain.js
  8. 12  IPython/frontend/html/notebook/static/js/notebook.js
  9. 11  IPython/frontend/html/notebook/static/js/notebooklist.js
  10. 0  IPython/frontend/html/notebook/static/js/{notebook_main.js → notebookmain.js}
  11. 10  IPython/frontend/html/notebook/static/js/panelsection.js
  12. 2  IPython/frontend/html/notebook/static/js/{nbbrowser_main.js → projectdashboardmain.js}
  13. 4  IPython/frontend/html/notebook/static/js/savewidget.js
  14. 87  IPython/frontend/html/notebook/templates/focus.html
  15. 23  IPython/frontend/html/notebook/templates/login.html
  16. 38  IPython/frontend/html/notebook/templates/notebook.html
  17. 10  IPython/frontend/html/notebook/templates/{nbbrowser.html → projectdashboard.html}
  18. 2  IPython/frontend/terminal/ipapp.py
  19. 1  docs/source/development/index.txt
  20. 56  docs/source/development/notebook_todo.txt
6  IPython/core/profileapp.py
@@ -194,15 +194,15 @@ def init_config_files(self):
194 194
         else:
195 195
             apps.append(IPythonQtConsoleApp)
196 196
         try:
197  
-            from IPython.frontend.html.notebook.notebookapp import IPythonNotebookApp
  197
+            from IPython.frontend.html.notebook.notebookapp import NotebookApp
198 198
         except ImportError:
199 199
             pass
200 200
         except Exception:
201  
-            self.log.debug('Unexpected error when importing IPythonNotebookApp',
  201
+            self.log.debug('Unexpected error when importing NotebookApp',
202 202
                            exc_info=True
203 203
             )
204 204
         else:
205  
-            apps.append(IPythonNotebookApp)
  205
+            apps.append(NotebookApp)
206 206
         if self.parallel:
207 207
             from IPython.parallel.apps.ipcontrollerapp import IPControllerApp
208 208
             from IPython.parallel.apps.ipengineapp import IPEngineApp
56  IPython/frontend/html/notebook/handlers.py
@@ -18,6 +18,7 @@
18 18
 
19 19
 import logging
20 20
 import Cookie
  21
+import uuid
21 22
 
22 23
 from tornado import web
23 24
 from tornado import websocket
@@ -40,51 +41,74 @@
40 41
 
41 42
 class AuthenticatedHandler(web.RequestHandler):
42 43
     """A RequestHandler with an authenticated user."""
  44
+
43 45
     def get_current_user(self):
44  
-        user_id = self.get_secure_cookie("user")
  46
+        user_id = self.get_secure_cookie("username")
  47
+        # For now the user_id should not return empty, but it could eventually
45 48
         if user_id == '':
46 49
             user_id = 'anonymous'
47 50
         if user_id is None:
48 51
             # prevent extra Invalid cookie sig warnings:
49  
-            self.clear_cookie('user')
  52
+            self.clear_cookie('username')
50 53
             if not self.application.password:
51 54
                 user_id = 'anonymous'
52 55
         return user_id
53 56
 
54 57
 
55  
-class NBBrowserHandler(AuthenticatedHandler):
  58
+class ProjectDashboardHandler(AuthenticatedHandler):
  59
+
56 60
     @web.authenticated
57 61
     def get(self):
58 62
         nbm = self.application.notebook_manager
59 63
         project = nbm.notebook_dir
60  
-        self.render('nbbrowser.html', project=project)
  64
+        self.render(
  65
+            'projectdashboard.html', project=project,
  66
+            base_project_url=u'/', base_kernel_url=u'/'
  67
+        )
  68
+
61 69
 
62 70
 class LoginHandler(AuthenticatedHandler):
  71
+
63 72
     def get(self):
64  
-        user_id = self.get_secure_cookie("user") or ''
65  
-        self.render('login.html', user_id=user_id)
  73
+        self.render('login.html', next='/')
66 74
 
67 75
     def post(self):
68  
-        pwd = self.get_argument("password", default=u'')
  76
+        pwd = self.get_argument('password', default=u'')
69 77
         if self.application.password and pwd == self.application.password:
70  
-            self.set_secure_cookie("user", self.get_argument("name", default=u''))
71  
-        url = self.get_argument("next", default="/")
  78
+            self.set_secure_cookie('username', str(uuid.uuid4()))
  79
+        url = self.get_argument('next', default='/')
72 80
         self.redirect(url)
73 81
 
  82
+
74 83
 class NewHandler(AuthenticatedHandler):
  84
+
75 85
     @web.authenticated
76 86
     def get(self):
77  
-        notebook_id = self.application.notebook_manager.new_notebook()
78  
-        self.render('notebook.html', notebook_id=notebook_id)
  87
+        nbm = self.application.notebook_manager
  88
+        project = nbm.notebook_dir
  89
+        notebook_id = nbm.new_notebook()
  90
+        self.render(
  91
+            'notebook.html', project=project,
  92
+            notebook_id=notebook_id,
  93
+            base_project_url=u'/', base_kernel_url=u'/',
  94
+            kill_kernel=False
  95
+        )
79 96
 
80 97
 
81 98
 class NamedNotebookHandler(AuthenticatedHandler):
  99
+
82 100
     @web.authenticated
83 101
     def get(self, notebook_id):
84 102
         nbm = self.application.notebook_manager
  103
+        project = nbm.notebook_dir
85 104
         if not nbm.notebook_exists(notebook_id):
86 105
             raise web.HTTPError(404, u'Notebook does not exist: %s' % notebook_id)
87  
-        self.render('notebook.html', notebook_id=notebook_id)
  106
+        self.render(
  107
+            'notebook.html', project=project,
  108
+            notebook_id=notebook_id,
  109
+            base_project_url=u'/', base_kernel_url=u'/',
  110
+            kill_kernel=False
  111
+        )
88 112
 
89 113
 
90 114
 #-----------------------------------------------------------------------------
@@ -166,11 +190,13 @@ def _on_zmq_reply(self, msg_list):
166 190
         try:
167 191
             msg = self._reserialize_reply(msg_list)
168 192
         except:
169  
-            self.application.kernel_manager.log.critical("Malformed message: %r" % msg_list)
  193
+            self.application.log.critical("Malformed message: %r" % msg_list)
170 194
         else:
171 195
             self.write_message(msg)
172 196
 
  197
+
173 198
 class AuthenticatedZMQStreamHandler(ZMQStreamHandler):
  199
+
174 200
     def open(self, kernel_id):
175 201
         self.kernel_id = kernel_id.decode('ascii')
176 202
         try:
@@ -184,7 +210,7 @@ def open(self, kernel_id):
184 210
         self.on_message = self.on_first_message
185 211
 
186 212
     def get_current_user(self):
187  
-        user_id = self.get_secure_cookie("user")
  213
+        user_id = self.get_secure_cookie("username")
188 214
         if user_id == '' or (user_id is None and not self.application.password):
189 215
             user_id = 'anonymous'
190 216
         return user_id
@@ -196,7 +222,7 @@ def _inject_cookie_message(self, msg):
196 222
             # Cookie can't constructor doesn't accept unicode strings for some reason
197 223
             msg = msg.encode('utf8', 'replace')
198 224
         try:
199  
-            self._cookies = Cookie.SimpleCookie(msg)
  225
+            self.request._cookies = Cookie.SimpleCookie(msg)
200 226
         except:
201 227
             logging.warn("couldn't parse cookie string: %s",msg, exc_info=True)
202 228
 
26  IPython/frontend/html/notebook/notebookapp.py
@@ -37,7 +37,7 @@
37 37
 
38 38
 from .kernelmanager import MappingKernelManager
39 39
 from .handlers import (LoginHandler,
40  
-    NBBrowserHandler, NewHandler, NamedNotebookHandler,
  40
+    ProjectDashboardHandler, NewHandler, NamedNotebookHandler,
41 41
     MainKernelHandler, KernelHandler, KernelActionHandler, IOPubHandler,
42 42
     ShellHandler, NotebookRootHandler, NotebookHandler, RSTHandler
43 43
 )
@@ -80,7 +80,7 @@ class NotebookWebApplication(web.Application):
80 80
 
81 81
     def __init__(self, ipython_app, kernel_manager, notebook_manager, log):
82 82
         handlers = [
83  
-            (r"/", NBBrowserHandler),
  83
+            (r"/", ProjectDashboardHandler),
84 84
             (r"/login", LoginHandler),
85 85
             (r"/new", NewHandler),
86 86
             (r"/%s" % _notebook_id_regex, NamedNotebookHandler),
@@ -125,11 +125,11 @@ def __init__(self, ipython_app, kernel_manager, notebook_manager, log):
125 125
 aliases = dict(ipkernel_aliases)
126 126
 
127 127
 aliases.update({
128  
-    'ip': 'IPythonNotebookApp.ip',
129  
-    'port': 'IPythonNotebookApp.port',
130  
-    'keyfile': 'IPythonNotebookApp.keyfile',
131  
-    'certfile': 'IPythonNotebookApp.certfile',
132  
-    'ws-hostname': 'IPythonNotebookApp.ws_hostname',
  128
+    'ip': 'NotebookApp.ip',
  129
+    'port': 'NotebookApp.port',
  130
+    'keyfile': 'NotebookApp.keyfile',
  131
+    'certfile': 'NotebookApp.certfile',
  132
+    'ws-hostname': 'NotebookApp.ws_hostname',
133 133
     'notebook-dir': 'NotebookManager.notebook_dir',
134 134
 })
135 135
 
@@ -141,10 +141,10 @@ def __init__(self, ipython_app, kernel_manager, notebook_manager, log):
141 141
                     u'notebook-dir']
142 142
 
143 143
 #-----------------------------------------------------------------------------
144  
-# IPythonNotebookApp
  144
+# NotebookApp
145 145
 #-----------------------------------------------------------------------------
146 146
 
147  
-class IPythonNotebookApp(BaseIPythonApplication):
  147
+class NotebookApp(BaseIPythonApplication):
148 148
 
149 149
     name = 'ipython-notebook'
150 150
     default_config_file_name='ipython_notebook_config.py'
@@ -213,7 +213,7 @@ def get_ws_url(self):
213 213
         return prefix + self.ws_hostname + u':' + unicode(self.port)
214 214
 
215 215
     def parse_command_line(self, argv=None):
216  
-        super(IPythonNotebookApp, self).parse_command_line(argv)
  216
+        super(NotebookApp, self).parse_command_line(argv)
217 217
         if argv is None:
218 218
             argv = sys.argv[1:]
219 219
 
@@ -254,14 +254,14 @@ def init_configurables(self):
254 254
         self.notebook_manager.list_notebooks()
255 255
 
256 256
     def init_logging(self):
257  
-        super(IPythonNotebookApp, self).init_logging()
  257
+        super(NotebookApp, self).init_logging()
258 258
         # This prevents double log messages because tornado use a root logger that
259 259
         # self.log is a child of. The logging module dipatches log messages to a log
260 260
         # and all of its ancenstors until propagate is set to False.
261 261
         self.log.propagate = False
262 262
 
263 263
     def initialize(self, argv=None):
264  
-        super(IPythonNotebookApp, self).initialize(argv)
  264
+        super(NotebookApp, self).initialize(argv)
265 265
         self.init_configurables()
266 266
         self.web_app = NotebookWebApplication(
267 267
             self, self.kernel_manager, self.notebook_manager, self.log
@@ -309,7 +309,7 @@ def start(self):
309 309
 #-----------------------------------------------------------------------------
310 310
 
311 311
 def launch_new_instance():
312  
-    app = IPythonNotebookApp()
  312
+    app = NotebookApp()
313 313
     app.initialize()
314 314
     app.start()
315 315
 
11  IPython/frontend/html/notebook/static/css/notebook.css
@@ -37,9 +37,8 @@ input#notebook_name {
37 37
 }
38 38
 
39 39
 span#kernel_status {
40  
-    position: absolute;
41  
-    padding: 8px 5px 5px 5px;
42  
-    right: 10px;
  40
+    float: right;
  41
+    padding: 0px 5px;
43 42
     font-weight: bold;
44 43
 }
45 44
 
@@ -65,10 +64,14 @@ div#left_panel {
65 64
     position: absolute;
66 65
 }
67 66
 
68  
-h3.section_header {
  67
+div.section_header {
69 68
     padding: 5px;
70 69
 }
71 70
 
  71
+div.section_header h3 {
  72
+    display: inline;
  73
+}
  74
+
72 75
 div.section_content {
73 76
     padding: 5px;
74 77
 }
0  ...n/frontend/html/notebook/static/css/nbbrowser.css → ...end/html/notebook/static/css/projectdashboard.css
File renamed without changes
8  IPython/frontend/html/notebook/static/js/kernel.js
@@ -15,12 +15,10 @@ var IPython = (function (IPython) {
15 15
 
16 16
     var Kernel = function () {
17 17
         this.kernel_id = null;
18  
-        this.base_url = "/kernels";
19  
-        this.kernel_url = null;
20 18
         this.shell_channel = null;
21 19
         this.iopub_channel = null;
  20
+        this.base_url = $('body').data('baseKernelUrl') + "kernels";
22 21
         this.running = false;
23  
-        
24 22
         this.username = "username";
25 23
         this.session_id = utils.uuid();
26 24
         
@@ -52,7 +50,8 @@ var IPython = (function (IPython) {
52 50
         var that = this;
53 51
         if (!this.running) {
54 52
             var qs = $.param({notebook:notebook_id});
55  
-            $.post(this.base_url + '?' + qs,
  53
+            var url = this.base_url + '?' + qs
  54
+            $.post(url,
56 55
                 function (kernel_id) {
57 56
                     that._handle_start_kernel(kernel_id, callback);
58 57
                 }, 
@@ -97,7 +96,6 @@ var IPython = (function (IPython) {
97 96
         this.iopub_channel = new this.WebSocket(ws_url + "/iopub");
98 97
         send_cookie = function(){
99 98
             this.send(document.cookie);
100  
-            console.log(this);
101 99
         }
102 100
         this.shell_channel.onopen = send_cookie;
103 101
         this.iopub_channel.onopen = send_cookie;
30  IPython/frontend/html/notebook/static/js/loginmain.js
... ...
@@ -0,0 +1,30 @@
  1
+//----------------------------------------------------------------------------
  2
+//  Copyright (C) 2008-2011  The IPython Development Team
  3
+//
  4
+//  Distributed under the terms of the BSD License.  The full license is in
  5
+//  the file COPYING, distributed as part of this software.
  6
+//----------------------------------------------------------------------------
  7
+
  8
+//============================================================================
  9
+// On document ready
  10
+//============================================================================
  11
+
  12
+
  13
+$(document).ready(function () {
  14
+
  15
+    $('div#header').addClass('border-box-sizing');
  16
+    $('div#header_border').addClass('border-box-sizing ui-widget ui-widget-content');
  17
+
  18
+    $('div#main_app').addClass('border-box-sizing ui-widget');
  19
+    $('div#app_hbox').addClass('hbox');
  20
+
  21
+    $('div#left_panel').addClass('box-flex');
  22
+    $('div#right_panel').addClass('box-flex');
  23
+    $('input#signin').button();
  24
+
  25
+    // These have display: none in the css file and are made visible here to prevent FLOUC.
  26
+    $('div#header').css('display','block');
  27
+    $('div#main_app').css('display','block');
  28
+
  29
+});
  30
+
12  IPython/frontend/html/notebook/static/js/notebook.js
@@ -929,7 +929,8 @@ var IPython = (function (IPython) {
929 929
                 error : $.proxy(this.notebook_save_failed,this)
930 930
             };
931 931
             IPython.save_widget.status_saving();
932  
-            $.ajax("/notebooks/" + notebook_id, settings);
  932
+            var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id
  933
+            $.ajax(url, settings);
933 934
         };
934 935
     };
935 936
 
@@ -937,7 +938,7 @@ var IPython = (function (IPython) {
937 938
     Notebook.prototype.notebook_saved = function (data, status, xhr) {
938 939
         this.dirty = false;
939 940
         IPython.save_widget.notebook_saved();
940  
-        setTimeout($.proxy(IPython.save_widget.status_save,IPython.save_widget),500);
  941
+        IPython.save_widget.status_save();
941 942
     }
942 943
 
943 944
 
@@ -945,7 +946,7 @@ var IPython = (function (IPython) {
945 946
         // Notify the user and reset the save button
946 947
         // TODO: Handle different types of errors (timeout etc.)
947 948
         alert('An unexpected error occured while saving the notebook.');
948  
-        setTimeout($.proxy(IPython.save_widget.reset_status,IPython.save_widget),500);                                                                               
  949
+        IPython.save_widget.reset_status();
949 950
     }
950 951
 
951 952
 
@@ -966,7 +967,8 @@ var IPython = (function (IPython) {
966 967
             }
967 968
         };
968 969
         IPython.save_widget.status_loading();
969  
-        $.ajax("/notebooks/" + notebook_id, settings);
  970
+        var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id
  971
+        $.ajax(url, settings);
970 972
     }
971 973
 
972 974
 
@@ -987,8 +989,10 @@ var IPython = (function (IPython) {
987 989
         }, 50);
988 990
     };
989 991
 
  992
+
990 993
     IPython.Notebook = Notebook;
991 994
 
  995
+
992 996
     return IPython;
993 997
 
994 998
 }(IPython));
11  IPython/frontend/html/notebook/static/js/notebooklist.js
@@ -67,7 +67,8 @@ var IPython = (function (IPython) {
67 67
             dataType : "json",
68 68
             success : $.proxy(this.list_loaded, this)
69 69
         };
70  
-        $.ajax("/notebooks", settings);
  70
+        var url = $('body').data('baseProjectUrl') + 'notebooks'
  71
+        $.ajax(url, settings);
71 72
     };
72 73
 
73 74
 
@@ -105,7 +106,7 @@ var IPython = (function (IPython) {
105 106
         var new_item_name = $('<span/>').addClass('item_name');
106 107
         new_item_name.append(
107 108
             $('<a/>').
108  
-            attr('href','/'+notebook_id).
  109
+            attr('href', $('body').data('baseProjectURL')+notebook_id).
109 110
             attr('target','_blank').
110 111
             text(nbname)
111 112
         );
@@ -170,7 +171,8 @@ var IPython = (function (IPython) {
170 171
                                     parent_item.remove();
171 172
                                 }
172 173
                             };
173  
-                            $.ajax("/notebooks/" + notebook_id, settings);
  174
+                            var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id
  175
+                            $.ajax(url, settings);
174 176
                             $(this).dialog('close');
175 177
                         },
176 178
                         "Cancel": function () {
@@ -217,7 +219,8 @@ var IPython = (function (IPython) {
217 219
                 };
218 220
 
219 221
                 var qs = $.param({name:nbname, format:nbformat});
220  
-                $.ajax('/notebooks?' + qs, settings);
  222
+                var url = $('body').data('baseProjectUrl') + 'notebooks?' + qs
  223
+                $.ajax(url, settings);
221 224
             });
222 225
         var cancel_button = $('<button>Cancel</button>').button().
223 226
             click(function (e) {
0  ...frontend/html/notebook/static/js/notebook_main.js → .../frontend/html/notebook/static/js/notebookmain.js
File renamed without changes
10  IPython/frontend/html/notebook/static/js/panelsection.js
@@ -19,7 +19,7 @@ var IPython = (function (IPython) {
19 19
         this.selector = selector;
20 20
         if (this.selector !== undefined) {
21 21
             this.element = $(selector);
22  
-            this.header = this.element.find('h3.section_header');
  22
+            this.header = this.element.find('div.section_header');
23 23
             this.content = this.element.find('div.section_content');
24 24
             this.style();
25 25
             this.bind_events();
@@ -29,7 +29,7 @@ var IPython = (function (IPython) {
29 29
 
30 30
 
31 31
     PanelSection.prototype.style = function () {
32  
-        this.header.addClass('ui-widget ui-state-default');
  32
+        this.header.addClass('ui-widget ui-state-default ui-helper-clearfix');
33 33
         this.header.attr('title', "Click to Show/Hide Section");
34 34
         this.content.addClass('ui-widget section_content');
35 35
     };
@@ -106,15 +106,15 @@ var IPython = (function (IPython) {
106 106
         PanelSection.prototype.bind_events.apply(this);
107 107
         var that = this;
108 108
         this.content.find('#new_notebook').click(function () {
109  
-            window.open('/new');
  109
+            window.open($('body').data('baseProjectUrl')+'new');
110 110
         });
111 111
         this.content.find('#open_notebook').click(function () {
112  
-            window.open('/');
  112
+            window.open($('body').data('baseProjectUrl'));
113 113
         });
114 114
         this.content.find('#download_notebook').click(function () {
115 115
             var format = that.content.find('#download_format').val();
116 116
             var notebook_id = IPython.save_widget.get_notebook_id();
117  
-            var url = '/notebooks/' + notebook_id + '?format=' + format;
  117
+            var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id + '?format=' + format;
118 118
             window.open(url,'_newtab');
119 119
         });
120 120
     };
2  ...rontend/html/notebook/static/js/nbbrowser_main.js → ...d/html/notebook/static/js/projectdashboardmain.js
@@ -21,7 +21,7 @@ $(document).ready(function () {
21 21
     $('div#content_toolbar').addClass('ui-widget ui-helper-clearfix');    
22 22
 
23 23
     $('#new_notebook').button().click(function (e) {
24  
-        window.open('/new');
  24
+        window.open($('body').data('baseProjectUrl')+'new');
25 25
     });
26 26
 
27 27
     $('div#left_panel').addClass('box-flex');
4  IPython/frontend/html/notebook/static/js/savewidget.js
@@ -82,12 +82,12 @@ var IPython = (function (IPython) {
82 82
 
83 83
     SaveWidget.prototype.set_document_title = function () {
84 84
         nbname = this.get_notebook_name();
85  
-        document.title = 'IPy: ' + nbname;
  85
+        document.title = nbname;
86 86
     };
87 87
         
88 88
 
89 89
     SaveWidget.prototype.get_notebook_id = function () {
90  
-        return this.element.find('span#notebook_id').text()
  90
+        return $('body').data('notebookId');
91 91
     };
92 92
 
93 93
 
87  IPython/frontend/html/notebook/templates/focus.html
... ...
@@ -1,87 +0,0 @@
1  
-<!DOCTYPE HTML>
2  
-<html>
3  
-
4  
-<head>
5  
-
6  
-    <title>Event ordering</title>
7  
-
8  
-    <style>
9  
-        div#outer {
10  
-            width: 400px;
11  
-            height: 300px;
12  
-            border: solid 2px black;
13  
-        }
14  
-
15  
-        div#inner {
16  
-            width: 80%;
17  
-            height: 80%;
18  
-            border: solid 2px black;
19  
-        }
20  
-
21  
-        div#innerinner {
22  
-            width: 80%;
23  
-            height: 80%;
24  
-            border: solid 2px black;
25  
-        }
26  
-
27  
-    </style>
28  
-</head>
29  
-
30  
-<body>
31  
-
32  
-<div id="outer" tabindex="-1">
33  
-    This is the outer div.
34  
-
35  
-    <div id="inner" tabindex="-1">
36  
-        This is the inner div.
37  
-        <div id="innerinner" tabindex="-1">
38  
-            This is the innerinner div
39  
-        </div>
40  
-    </div>
41  
-
42  
-</div>
43  
-
44  
-<script src="static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script>
45  
-
46  
-<script>
47  
-    $(document).ready(function () {
48  
-        $('div#outer').click(function (e) {
49  
-            console.log("outer.click");
50  
-        });
51  
-        $('div#outer').focus(function (e) {
52  
-            console.log("outer.focus");
53  
-        });
54  
-        $('div#outer').focusin(function (e) {
55  
-            console.log("outer.focusin");
56  
-        });
57  
-
58  
-        $('div#inner').click(function (e) {
59  
-            console.log("--inner.click");
60  
-        });
61  
-        $('div#inner').focus(function (e) {
62  
-            console.log("--inner.focus");
63  
-        });
64  
-        $('div#inner').focusin(function (e) {
65  
-            console.log("--inner.focusin");
66  
-            e.stopPropagation();
67  
-        });
68  
-
69  
-        $('div#innerinner').click(function (e) {
70  
-            console.log("----innerinner.click");
71  
-        });
72  
-        $('div#innerinner').focus(function (e) {
73  
-            console.log("----innerinner.focus");
74  
-        });
75  
-        $('div#innerinner').focusin(function (e) {
76  
-            console.log("----innerinner.focusin");
77  
-        });
78  
-
79  
-    });
80  
-</script>
81  
-
82  
-</body>
83  
-
84  
-</html>
85  
-
86  
-
87  
-
23  IPython/frontend/html/notebook/templates/login.html
@@ -7,24 +7,13 @@
7 7
     <title>IPython Notebook</title>
8 8
 
9 9
     <link rel="stylesheet" href="static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" />
10  
-<!--     <link rel="stylesheet" href="static/jquery/css/themes/rocket/jquery-wijmo.css" type="text/css" /> -->
11  
-<!--    <link rel="stylesheet" href="static/jquery/css/themes/smoothness/jquery-ui-1.8.14.custom.css" type="text/css" />-->
12  
-
13 10
     <link rel="stylesheet" href="static/css/boilerplate.css" type="text/css" />
14 11
     <link rel="stylesheet" href="static/css/layout.css" type="text/css" />
15 12
     <link rel="stylesheet" href="static/css/base.css" type="text/css" />
16  
-<script type="text/javascript" charset="utf-8">
17  
-function add_next_to_action(){
18  
-    // add 'next' argument to action url, to preserve redirect
19  
-    var query = location.search.substring(1);
20  
-    var form = document.forms[0];
21  
-    var action = form.getAttribute("action");
22  
-    form.setAttribute("action", action + '?' + query);
23  
-}
24  
-</script>
  13
+
25 14
 </head>
26 15
 
27  
-<body onload="add_next_to_action()">
  16
+<body>
28 17
 
29 18
 <div id="header">
30 19
     <span id="ipython_notebook"><h1>IPython Notebook</h1></span>
@@ -40,10 +29,9 @@
40 29
     </div>
41 30
     
42 31
     <div id="content_panel">
43  
-        <form action="/login" method="post">
44  
-            Name: <input type="text" name="name" value="{{user_id}}">
  32
+        <form action="/login?next={{url_escape(next)}}" method="post">
45 33
             Password: <input type="password" name="password">
46  
-            <input type="submit" value="Sign in">
  34
+            <input type="submit" value="Sign in" id="signin">
47 35
         </form>
48 36
     </div>
49 37
     <div id="right_panel">
@@ -56,8 +44,7 @@
56 44
 <script src="static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script>
57 45
 <script src="static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script>
58 46
 <script src="static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
59  
-<script src="static/js/notebooklist.js" type="text/javascript" charset="utf-8"></script>
60  
-<script src="static/js/nbbrowser_main.js" type="text/javascript" charset="utf-8"></script>
  47
+<script src="static/js/loginmain.js" type="text/javascript" charset="utf-8"></script>
61 48
 
62 49
 </body>
63 50
 
38  IPython/frontend/html/notebook/templates/notebook.html
@@ -6,10 +6,6 @@
6 6
 
7 7
     <title>IPython Notebook</title>
8 8
 
9  
-    <link rel="stylesheet" href="static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" />
10  
-<!--     <link rel="stylesheet" href="static/jquery/css/themes/rocket/jquery-wijmo.css" type="text/css" /> -->
11  
-<!--    <link rel="stylesheet" href="static/jquery/css/themes/smoothness/jquery-ui-1.8.14.custom.css" type="text/css" />-->
12  
-
13 9
     <!-- <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML" charset="utf-8"></script> -->
14 10
     <script type='text/javascript' src='static/mathjax/MathJax.js?config=TeX-AMS_HTML' charset='utf-8'></script>
15 11
     <script type="text/javascript">
@@ -30,6 +26,7 @@
30 26
     }
31 27
     </script>
32 28
 
  29
+    <link rel="stylesheet" href="static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" />
33 30
     <link rel="stylesheet" href="static/codemirror/lib/codemirror.css">
34 31
     <link rel="stylesheet" href="static/codemirror/mode/markdown/markdown.css">
35 32
     <link rel="stylesheet" href="static/codemirror/mode/rst/rst.css">
@@ -47,19 +44,20 @@
47 44
 
48 45
 </head>
49 46
 
50  
-<body onload='CheckMathJax();'>
  47
+<body onload='CheckMathJax();'
  48
+    data-project={{project}} data-notebook-id={{notebook_id}}
  49
+    data-base-project-url={{base_project_url}} data-base-kernel-url={{base_kernel_url}}
  50
+>
51 51
 
52 52
 <div id="header">
53 53
     <span id="ipython_notebook"><h1>IPython Notebook</h1></span>
54 54
     <span id="save_widget">
55 55
         <input type="text" id="notebook_name" size="20"></textarea>
56  
-        <span id="notebook_id" style="display:none">{{notebook_id}}</span>
57 56
         <button id="save_notebook"><u>S</u>ave</button>
58 57
     </span>
59 58
     <span id="quick_help_area">
60 59
       <button id="quick_help">Quick<u>H</u>elp</button>
61 60
       </span>
62  
-    <span id="kernel_status">Idle</span>
63 61
 </div>
64 62
 
65 63
 <div id="MathJaxFetchingWarning"
@@ -90,7 +88,9 @@
90 88
     <div id="left_panel">
91 89
 
92 90
         <div id="notebook_section">
93  
-            <h3 class="section_header">Notebook</h3>
  91
+            <div class="section_header">
  92
+                <h3>Notebook</h3>
  93
+            </div>
94 94
             <div class="section_content">
95 95
                 <div class="section_row">
96 96
                     <span id="new_open" class="section_row_buttons">
@@ -121,7 +121,9 @@ <h3 class="section_header">Notebook</h3>
121 121
         </div>
122 122
 
123 123
         <div id="cell_section">
124  
-            <h3 class="section_header">Cell</h3>
  124
+            <div class="section_header">
  125
+                <h3>Cell</h3>
  126
+            </div>
125 127
             <div class="section_content">
126 128
                 <div class="section_row">
127 129
                     <span class="section_row_buttons">
@@ -175,7 +177,10 @@ <h3 class="section_header">Cell</h3>
175 177
         </div>
176 178
 
177 179
         <div id="kernel_section">
178  
-            <h3 class="section_header">Kernel</h3>
  180
+            <div class="section_header">
  181
+                <h3>Kernel</h3>
  182
+                <span id="kernel_status">Idle</span>
  183
+            </div>
179 184
             <div class="section_content">
180 185
                 <div class="section_row">
181 186
                     <span id="int_restart" class="section_row_buttons">
@@ -186,7 +191,11 @@ <h3 class="section_header">Kernel</h3>
186 191
                 </div>
187 192
                 <div class="section_row">
188 193
                     <span id="kernel_persist">
189  
-                        <input type="checkbox" id="kill_kernel"></input>
  194
+                        {% if kill_kernel %}
  195
+                            <input type="checkbox" id="kill_kernel" checked="true"></input>
  196
+                        {% else %}
  197
+                            <input type="checkbox" id="kill_kernel"></input>
  198
+                        {% end %}
190 199
                     </span>
191 200
                     <span class="checkbox_label" id="kill_kernel_label">Kill kernel upon exit:</span>
192 201
                 </div>
@@ -194,7 +203,9 @@ <h3 class="section_header">Kernel</h3>
194 203
         </div>
195 204
 
196 205
         <div id="help_section">
197  
-            <h3 class="section_header">Help</h3>
  206
+            <div class="section_header">
  207
+                <h3>Cell</h3>
  208
+            </div>
198 209
             <div class="section_content">
199 210
                 <div class="section_row">
200 211
                     <span id="help_buttons0" class="section_row_buttons">
@@ -272,8 +283,7 @@ <h3 class="section_header">Help</h3>
272 283
 <script src="static/js/printwidget.js" type="text/javascript" charset="utf-8"></script>
273 284
 <script src="static/js/leftpanel.js" type="text/javascript" charset="utf-8"></script>
274 285
 <script src="static/js/notebook.js" type="text/javascript" charset="utf-8"></script>
275  
-<script src="static/js/notebook_main.js" type="text/javascript" charset="utf-8"></script>
276  
-
  286
+<script src="static/js/notebookmain.js" type="text/javascript" charset="utf-8"></script>
277 287
 
278 288
 </body>
279 289
 
10  ...n/frontend/html/notebook/templates/nbbrowser.html → ...end/html/notebook/templates/projectdashboard.html
@@ -7,17 +7,15 @@
7 7
     <title>IPython Notebook</title>
8 8
 
9 9
     <link rel="stylesheet" href="static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" />
10  
-<!--     <link rel="stylesheet" href="static/jquery/css/themes/rocket/jquery-wijmo.css" type="text/css" /> -->
11  
-<!--    <link rel="stylesheet" href="static/jquery/css/themes/smoothness/jquery-ui-1.8.14.custom.css" type="text/css" />-->
12  
-
13 10
     <link rel="stylesheet" href="static/css/boilerplate.css" type="text/css" />
14 11
     <link rel="stylesheet" href="static/css/layout.css" type="text/css" />
15 12
     <link rel="stylesheet" href="static/css/base.css" type="text/css" />
16  
-    <link rel="stylesheet" href="static/css/nbbrowser.css" type="text/css" />
  13
+    <link rel="stylesheet" href="static/css/projectdashboard.css" type="text/css" />
17 14
 
18 15
 </head>
19 16
 
20  
-<body>
  17
+<body data-project={{project}} data-base-project-url={{base_project_url}}
  18
+      data-base-kernel-url={{base_kernel_url}}>
21 19
 
22 20
 <div id="header">
23 21
     <span id="ipython_notebook"><h1>IPython Notebook</h1></span>
@@ -56,7 +54,7 @@
56 54
 <script src="static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script>
57 55
 <script src="static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
58 56
 <script src="static/js/notebooklist.js" type="text/javascript" charset="utf-8"></script>
59  
-<script src="static/js/nbbrowser_main.js" type="text/javascript" charset="utf-8"></script>
  57
+<script src="static/js/projectdashboardmain.js" type="text/javascript" charset="utf-8"></script>
60 58
 
61 59
 </body>
62 60
 
2  IPython/frontend/terminal/ipapp.py
@@ -206,7 +206,7 @@ def _classes_default(self):
206 206
         qtconsole=('IPython.frontend.qt.console.qtconsoleapp.IPythonQtConsoleApp',
207 207
             """Launch the IPython Qt Console."""
208 208
         ),
209  
-        notebook=('IPython.frontend.html.notebook.notebookapp.IPythonNotebookApp',
  209
+        notebook=('IPython.frontend.html.notebook.notebookapp.NotebookApp',
210 210
             """Launch the IPython HTML Notebook Server"""
211 211
         ),
212 212
         profile = ("IPython.core.profileapp.ProfileApp",
1  docs/source/development/index.txt
@@ -22,3 +22,4 @@ IPython developer's guide
22 22
    ipgraph.txt
23 23
    ipython_qt.txt
24 24
    ipythonzmq.txt
  25
+   notebook_todo.txt
56  docs/source/development/notebook_todo.txt
... ...
@@ -0,0 +1,56 @@
  1
+Notebook todo
  2
+=============
  3
+
  4
+* Style the login page consistently with the rest of the site.
  5
+* Style the "Log Out" and username links in the header.
  6
+* Do a review of the header design and decide what to do about save widget moving
  7
+  to the Notebook section of the L panel.
  8
+* Show last saved time next to save widget.
  9
+* Make the header logo a link to "/".
  10
+* Add a better divider line between the header and the content area.
  11
+  - Fix spacing on notebook page.
  12
+* Organize templates to use inheritance and includes.
  13
+
  14
+* Implement better restart logic.
  15
+  - Have LocalKernel monitor the hb port and always to restarts.
  16
+  - Have the WebSocket still monitor the hb and notify the user of restarts.
  17
+
  18
+* Create unrendered rst cells.
  19
+* Users should be able to edit the contents of any cell in a global ACE editor.
  20
+* Add JSON'd metadata to the .py format notebooks.
  21
+* Implement white space between cells for insert. 
  22
+* Implement a notebook reload button.
  23
+* Indicate visual difference between html and markdown cell.
  24
+* Export should save first.
  25
+* Add ability to merge and split cells.
  26
+* Add Ctrl-Z for undo delete cell.
  27
+* Fix horizontal overflow and scrolling of output_area.
  28
+* Add per cells controls on the R side of each cell.
  29
+* Users should be able to drag a .py file to a cell and have it imported into that cell.
  30
+
  31
+* Add reconnect logic in the javascript kernel.
  32
+* Add logic for failed ajax requests. With this, investigate returning JSON data to more
  33
+  completely describe the HTTP error codes.
  34
+* Test web services against hostile attacks.
  35
+* Add optional html sanitizing.
  36
+* Add timestamp to cells. ISO8601. IPython.utils.jsonutil.ISO8601. Save as 
  37
+  submitted/started/completed/received. See http://webcloud.se/log/JavaScript-and-ISO-8601/
  38
+* Try to figure out the issue with jQuery and <script> tags. See
  39
+  http://stackoverflow.com/questions/610995/jquery-cant-append-script-element
  40
+
  41
+CodeMirror related
  42
+------------------
  43
+
  44
+* Focus should only be called when the editor is on the page and visible.
  45
+* Refresh needs to be called when the editor is shown after hiding.
  46
+* Right now focus, then setValue causes the arrow keys to lock up. If that bug is
  47
+  not fixed, we need to possible move to passing the input to the CodeCell
  48
+  constructor.
  49
+* Implement a top-level refresh methods on Cells and the Notebook that can be called
  50
+  after page/notebook load.
  51
+* Make insert_code_cell_* methods not call select always. Probably move to a model
  52
+  where those methods take an options object.
  53
+* Notebook loading should be done without calls to select/focus/refresh. A single
  54
+  refresh pass should be done after everything has been made visible.
  55
+* Remove \u0000 from placeholders after the relevant CM bug is fixed.
  56
+
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.