Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Support notebook upload from the UI #111

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion notebooker/web/routes/core.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from pathlib import Path
from flask import Blueprint, jsonify, request

import notebooker.version
from notebooker.constants import DEFAULT_RESULT_LIMIT
from notebooker.utils.results import get_all_available_results_json, get_count_and_latest_time_per_report
from notebooker.web.utils import get_serializer, get_all_possible_templates, all_templates_flattened
from notebooker.web.utils import _get_python_template_dir, get_serializer, get_all_possible_templates, all_templates_flattened

core_bp = Blueprint("core_bp", __name__)

Expand Down Expand Up @@ -76,3 +77,19 @@ def get_version_no():
:returns: A JSON mapping from "version" to the string repr of the version number.
"""
return jsonify({"version": notebooker.version.__version__})


@core_bp.route("/core/notebook/upload", methods=["POST"])
def upload_notebook():
"""
Stores a notebook in git
"""
templates = Path(_get_python_template_dir())
web = templates / "web"
web.mkdir(exist_ok=True)
notebook_name = request.values.get("name")
if not notebook_name or not notebook_name.endswith(".ipynb"):
return jsonify({"status": "Invalid notebook name"}), 400
with open(web / request.values.get("name"), "w") as fp:
fp.write(request.values.get("notebook", ""))
return jsonify({"status": "Notebook uploaded"})
30 changes: 30 additions & 0 deletions notebooker/web/static/notebooker/header.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,34 @@
$(document).ready(() => {
$('#showUploadNotebookButton').click(() =>
$('#uploadNotebookModal').modal({
closable: true,
onHidden: function() {
$('#notebook').val('');
},
onApprove: function() {
let notebook = $('#notebook').prop('files')[0];
let reader = new FileReader();
reader.addEventListener('load', (e) => {
$.ajax({
url: '/core/notebook/upload',
cache: false,
type: 'POST',
data: {
name: notebook.name,
notebook: e.target.result
},
success: () => {
$('body').toast({class: 'info', message: 'Upload successful! Refresh the page in order to see it.'});
},
error: (result) => {
$('body').toast({class: 'error', message: `Error uploading notebook: ${result.responseJSON.status} (${result.status})`});
},
});
});
reader.readAsText(notebook);
}
}).modal('show')
);
$.ajax({
url: '/core/version',
success: (result) => {
Expand Down
21 changes: 20 additions & 1 deletion notebooker/web/templates/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,30 @@ <h4 class="ui header inverted">Execute a notebook:</h4>
</div>
{% endif %}
{% endfor %}
<a class="item bottom" href="https://notebooker.readthedocs.io/en/latest/templates.html#creating-a-notebook-template">
<a id="showUploadNotebookButton" class="item bottom" href="#">
<i class="plus icon"></i>
<i>Add a new notebook</i>
</a>
</div>
<div class="ui modal" id="uploadNotebookModal">
<div class="header">Upload notebook</div>
<div class="content">
<p>
Notebooks uploaded via this interface will be stored in the <code>web</code> folder.
They will be automatically uploaded to git. Look at the
<a href="https://notebooker.readthedocs.io/en/latest/templates.html#creating-a-notebook-template">documentation</a>
for adding notebooks in different folders and making new packages available.
</p>
<form class="ui form" id="uploadNotebookForm">
<input type="file" id="notebook" name="notebook" class="ui">
</form>
<div class="actions">
<div class="ui approve button">Submit</div>
<div class="ui cancel button">Cancel</div>
</div>
</div>
</div>

</body>
<footer></footer>
</html>
Expand Down