##// END OF EJS Templates
update upload and copy...
MinRK -
Show More
@@ -71,8 +71,7 b' class NotebookHandler(IPythonHandler):'
71 @web.authenticated
71 @web.authenticated
72 @json_errors
72 @json_errors
73 def patch(self, path='', name=None):
73 def patch(self, path='', name=None):
74 """patch is currently used strictly for notebook renaming.
74 """PATCH renames a notebook without re-uploading content."""
75 Changes the notebook name to the name given in data."""
76 nbm = self.notebook_manager
75 nbm = self.notebook_manager
77 if name is None:
76 if name is None:
78 raise web.HTTPError(400, u'Notebook name missing')
77 raise web.HTTPError(400, u'Notebook name missing')
@@ -90,10 +89,31 b' class NotebookHandler(IPythonHandler):'
90 @web.authenticated
89 @web.authenticated
91 @json_errors
90 @json_errors
92 def post(self, path='', name=None):
91 def post(self, path='', name=None):
93 """Create a new notebook in the location given by 'notebook_path'."""
92 """Create a new notebook in the specified path.
93
94 POST creates new notebooks.
95
96 POST /api/notebooks/path : new untitled notebook in path
97 POST /api/notebooks/path/notebook.ipynb : new notebook with name in path
98 If content specified upload notebook, otherwise start empty.
99 """
94 nbm = self.notebook_manager
100 nbm = self.notebook_manager
95 model = self.get_json_body()
101 model = self.get_json_body()
96 model = nbm.create_notebook_model(model, path)
102 if name is None:
103 # creating new notebook, model doesn't make sense
104 if model is not None:
105 raise web.HTTPError(400, "Model not valid when creating untitled notebooks.")
106 model = nbm.create_notebook_model(path=path)
107 else:
108 if model is None:
109 self.log.info("Creating new Notebook at %s/%s", path, name)
110 model = {}
111 else:
112 self.log.info("Uploading Notebook to %s/%s", path, name)
113 # set the model name from the URL
114 model['name'] = name
115 model = nbm.create_notebook_model(model, path)
116
97 location = self.notebook_location(model[u'name'], model[u'path'])
117 location = self.notebook_location(model[u'name'], model[u'path'])
98 self.set_header(u'Location', location)
118 self.set_header(u'Location', location)
99 self.set_header(u'Last-Modified', model[u'last_modified'])
119 self.set_header(u'Last-Modified', model[u'last_modified'])
@@ -120,6 +140,29 b' class NotebookHandler(IPythonHandler):'
120 self.set_status(204)
140 self.set_status(204)
121 self.finish()
141 self.finish()
122
142
143 class NotebookCopyHandler(IPythonHandler):
144
145 SUPPORTED_METHODS = ('POST')
146
147 @web.authenticated
148 @json_errors
149 def post(self, path='', name=None):
150 """Copy an existing notebook."""
151 nbm = self.notebook_manager
152 model = self.get_json_body()
153 if name is None:
154 raise web.HTTPError(400, "Notebook name required")
155 self.log.info("Copying Notebook %s/%s", path, name)
156 model = nbm.copy_notebook(name, path)
157 location = url_path_join(
158 self.base_project_url, 'api', 'notebooks',
159 model['path'], model['name'],
160 )
161 self.set_header(u'Location', location)
162 self.set_header(u'Last-Modified', model[u'last_modified'])
163 self.set_status(201)
164 self.finish(json.dumps(model, default=date_default))
165
123
166
124 class NotebookCheckpointsHandler(IPythonHandler):
167 class NotebookCheckpointsHandler(IPythonHandler):
125
168
@@ -180,6 +223,7 b' _notebook_name_regex = r"(?P<name>[^/]+\\.ipynb)"'
180 _notebook_path_regex = "%s/%s" % (_path_regex, _notebook_name_regex)
223 _notebook_path_regex = "%s/%s" % (_path_regex, _notebook_name_regex)
181
224
182 default_handlers = [
225 default_handlers = [
226 (r"/api/notebooks/?%s/copy" % _notebook_path_regex, NotebookCopyHandler),
183 (r"/api/notebooks/?%s/checkpoints" % _notebook_path_regex, NotebookCheckpointsHandler),
227 (r"/api/notebooks/?%s/checkpoints" % _notebook_path_regex, NotebookCheckpointsHandler),
184 (r"/api/notebooks/?%s/checkpoints/%s" % (_notebook_path_regex, _checkpoint_id_regex),
228 (r"/api/notebooks/?%s/checkpoints/%s" % (_notebook_path_regex, _checkpoint_id_regex),
185 ModifyNotebookCheckpointsHandler),
229 ModifyNotebookCheckpointsHandler),
@@ -87,7 +87,7 b' class NotebookManager(LoggingConfigurable):'
87 """
87 """
88 return basename
88 return basename
89
89
90 def list_notebooks(self):
90 def list_notebooks(self, path=''):
91 """Return a list of notebook dicts without content.
91 """Return a list of notebook dicts without content.
92
92
93 This returns a list of dicts, each of the form::
93 This returns a list of dicts, each of the form::
@@ -112,53 +112,51 b' class NotebookManager(LoggingConfigurable):'
112 """Update the notebook model and return the model with no content."""
112 """Update the notebook model and return the model with no content."""
113 raise NotImplementedError('must be implemented in a subclass')
113 raise NotImplementedError('must be implemented in a subclass')
114
114
115 def delete_notebook_model(self, name, path):
115 def delete_notebook_model(self, name, path=''):
116 """Delete notebook by name and path."""
116 """Delete notebook by name and path."""
117 raise NotImplementedError('must be implemented in a subclass')
117 raise NotImplementedError('must be implemented in a subclass')
118
118
119 def create_notebook_model(self, model=None, path=''):
119 def create_notebook_model(self, model=None, path=''):
120 """Create a new untitled notebook and return its model with no content."""
120 """Create a new untitled notebook and return its model with no content."""
121 untitled = self.increment_filename('Untitled', path)
122 if model is None:
121 if model is None:
123 model = {}
122 model = {}
123 if 'content' not in model:
124 metadata = current.new_metadata(name=u'')
124 metadata = current.new_metadata(name=u'')
125 nb = current.new_notebook(metadata=metadata)
125 model['content'] = current.new_notebook(metadata=metadata)
126 model['content'] = nb
126 if 'name' not in model:
127 model['name'] = name = untitled
127 model['name'] = self.increment_filename('Untitled', path)
128 model['path'] = path
128
129 else:
129 model['path'] = path
130 name = model.setdefault('name', untitled)
130 model = self.save_notebook_model(model, model['name'], model['path'])
131 model['path'] = path
132 model = self.save_notebook_model(model, name, path)
133 return model
131 return model
134
132
135 def copy_notebook(self, name, path='/', content=False):
133 def copy_notebook(self, name, path=''):
136 """Copy an existing notebook and return its new model."""
134 """Copy an existing notebook and return its new model."""
137 model = self.get_notebook_model(name, path)
135 model = self.get_notebook_model(name, path)
138 name = os.path.splitext(name)[0] + '-Copy'
136 name = os.path.splitext(name)[0] + '-Copy'
139 name = self.increment_filename(name, path) + self.filename_ext
137 name = self.increment_filename(name, path) + self.filename_ext
140 model['name'] = name
138 model['name'] = name
141 model = self.save_notebook_model(model, name, path, content=content)
139 model = self.save_notebook_model(model, name, path)
142 return model
140 return model
143
141
144 # Checkpoint-related
142 # Checkpoint-related
145
143
146 def create_checkpoint(self, name, path='/'):
144 def create_checkpoint(self, name, path=''):
147 """Create a checkpoint of the current state of a notebook
145 """Create a checkpoint of the current state of a notebook
148
146
149 Returns a checkpoint_id for the new checkpoint.
147 Returns a checkpoint_id for the new checkpoint.
150 """
148 """
151 raise NotImplementedError("must be implemented in a subclass")
149 raise NotImplementedError("must be implemented in a subclass")
152
150
153 def list_checkpoints(self, name, path='/'):
151 def list_checkpoints(self, name, path=''):
154 """Return a list of checkpoints for a given notebook"""
152 """Return a list of checkpoints for a given notebook"""
155 return []
153 return []
156
154
157 def restore_checkpoint(self, checkpoint_id, name, path='/'):
155 def restore_checkpoint(self, checkpoint_id, name, path=''):
158 """Restore a notebook from one of its checkpoints"""
156 """Restore a notebook from one of its checkpoints"""
159 raise NotImplementedError("must be implemented in a subclass")
157 raise NotImplementedError("must be implemented in a subclass")
160
158
161 def delete_checkpoint(self, checkpoint_id, name, path='/'):
159 def delete_checkpoint(self, checkpoint_id, name, path=''):
162 """delete a checkpoint for a notebook"""
160 """delete a checkpoint for a notebook"""
163 raise NotImplementedError("must be implemented in a subclass")
161 raise NotImplementedError("must be implemented in a subclass")
164
162
@@ -1768,15 +1768,12 b' var IPython = (function (IPython) {'
1768
1768
1769 Notebook.prototype.copy_notebook = function(){
1769 Notebook.prototype.copy_notebook = function(){
1770 var path = this.notebookPath();
1770 var path = this.notebookPath();
1771 var name = {'name': this.notebook_name}
1772 var settings = {
1771 var settings = {
1773 processData : false,
1772 processData : false,
1774 cache : false,
1773 cache : false,
1775 type : "POST",
1774 type : "POST",
1776 data: JSON.stringify(name),
1777 dataType : "json",
1778 success:$.proxy(function (data, status, xhr){
1775 success:$.proxy(function (data, status, xhr){
1779 notebook_name = data.name;
1776 var notebook_name = data.name;
1780 window.open(utils.url_path_join(
1777 window.open(utils.url_path_join(
1781 this._baseProjectUrl,
1778 this._baseProjectUrl,
1782 'notebooks',
1779 'notebooks',
@@ -1787,8 +1784,10 b' var IPython = (function (IPython) {'
1787 };
1784 };
1788 var url = utils.url_path_join(
1785 var url = utils.url_path_join(
1789 this._baseProjectUrl,
1786 this._baseProjectUrl,
1790 'notebooks',
1787 'api/notebooks',
1791 path
1788 path,
1789 this.notebook_name,
1790 'copy'
1792 );
1791 );
1793 $.ajax(url,settings);
1792 $.ajax(url,settings);
1794 };
1793 };
@@ -312,7 +312,7 b' var IPython = (function (IPython) {'
312 var upload_button = $('<button/>').text("Upload")
312 var upload_button = $('<button/>').text("Upload")
313 .addClass('btn btn-primary btn-mini upload_button')
313 .addClass('btn btn-primary btn-mini upload_button')
314 .click(function (e) {
314 .click(function (e) {
315 var nbname = item.find('.item_name > input').attr('value');
315 var nbname = item.find('.item_name > input').val();
316 var nbformat = item.data('nbformat');
316 var nbformat = item.data('nbformat');
317 var nbdata = item.data('nbdata');
317 var nbdata = item.data('nbdata');
318 var content_type = 'application/json';
318 var content_type = 'application/json';
@@ -323,8 +323,6 b' var IPython = (function (IPython) {'
323 }
323 }
324 var model = {
324 var model = {
325 content : JSON.parse(nbdata),
325 content : JSON.parse(nbdata),
326 name : nbname,
327 path : that.notebookPath()
328 };
326 };
329 var settings = {
327 var settings = {
330 processData : false,
328 processData : false,
@@ -345,7 +343,8 b' var IPython = (function (IPython) {'
345 var url = utils.url_path_join(
343 var url = utils.url_path_join(
346 that.baseProjectUrl(),
344 that.baseProjectUrl(),
347 'api/notebooks',
345 'api/notebooks',
348 that.notebookPath()
346 that.notebookPath(),
347 nbname + '.ipynb'
349 );
348 );
350 $.ajax(url, settings);
349 $.ajax(url, settings);
351 return false;
350 return false;
General Comments 0
You need to be logged in to leave comments. Login now